143 lines
4.0 KiB
TypeScript
143 lines
4.0 KiB
TypeScript
// routes/api/create/lease.ts
|
|
import { define } from "../../../utils.ts";
|
|
import { createLease } from "../../../services/leaseService.ts";
|
|
import { getProperty } from "../../../services/propertyService.ts";
|
|
import { SessionCookie } from "../../auth/callback.ts";
|
|
|
|
export const handler = define.handlers({
|
|
async POST(ctx) {
|
|
try {
|
|
const stateData: SessionCookie = ctx.state.data;
|
|
const { user_id } = stateData;
|
|
|
|
// Check authentication
|
|
if (!user_id) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: "Unauthorized: No session found",
|
|
}),
|
|
{
|
|
status: 401,
|
|
headers: { "Content-Type": "application/json" },
|
|
},
|
|
);
|
|
}
|
|
|
|
const form = await ctx.req.formData();
|
|
const sender = form.get("sender");
|
|
const tenant_id = form.get("tenant_id")?.toString();
|
|
const propertyId = form.get("property_id")?.toString() || "";
|
|
const title = form.get("title")?.toString() || "";
|
|
const rent = Number(form.get("rent"));
|
|
const start_date = form.get("start_date")
|
|
? Date.parse(form.get("start_date")?.toString() + "T00:00:00")
|
|
: null;
|
|
const end_date = form.get("end_date")
|
|
? Date.parse(form.get("end_date")?.toString() + "T00:00:00")
|
|
: null;
|
|
const security_deposit = Number(form.get("security_deposit")) || 0;
|
|
|
|
// Validate required fields
|
|
if (!propertyId) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: "Property ID is required",
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
},
|
|
);
|
|
}
|
|
|
|
if (!start_date || !end_date || isNaN(start_date) || isNaN(end_date)) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: "Valid start and end dates are required",
|
|
}),
|
|
{
|
|
status: 400,
|
|
headers: { "Content-Type": "application/json" },
|
|
},
|
|
);
|
|
}
|
|
|
|
const property = await getProperty(propertyId);
|
|
|
|
if (property.length !== 1) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: "Property not found",
|
|
}),
|
|
{
|
|
status: 404,
|
|
headers: { "Content-Type": "application/json" },
|
|
},
|
|
);
|
|
}
|
|
|
|
const owner_id = property[0].owner_id as string;
|
|
|
|
// OWNERSHIP VALIDATION: Only property owner can create leases
|
|
if (owner_id !== user_id) {
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: "Forbidden: You do not own this property",
|
|
details: {
|
|
user_id,
|
|
property_owner_id: owner_id,
|
|
property_id: propertyId,
|
|
},
|
|
}),
|
|
{
|
|
status: 403,
|
|
headers: { "Content-Type": "application/json" },
|
|
},
|
|
);
|
|
}
|
|
|
|
// Create lease with ownership validated
|
|
await createLease(
|
|
title,
|
|
propertyId,
|
|
owner_id,
|
|
start_date,
|
|
end_date,
|
|
rent,
|
|
security_deposit,
|
|
tenant_id,
|
|
);
|
|
|
|
const senderPath = sender?.toString() || "/";
|
|
let redirectUrl = senderPath;
|
|
try {
|
|
if (senderPath.startsWith("/")) {
|
|
const url = new URL(ctx.req.url);
|
|
redirectUrl = url.origin + senderPath;
|
|
}
|
|
} catch (_) {
|
|
// fallback: just use senderPath
|
|
}
|
|
return Response.redirect(redirectUrl, 303);
|
|
} catch (e) {
|
|
console.error("Error creating lease:", e);
|
|
return new Response(
|
|
JSON.stringify({
|
|
success: false,
|
|
error: "Internal server error",
|
|
details: e instanceof Error ? e.message : String(e),
|
|
}),
|
|
{
|
|
status: 500,
|
|
headers: { "Content-Type": "application/json" },
|
|
},
|
|
);
|
|
}
|
|
},
|
|
});
|