diff --git a/serverless.yml b/serverless.yml index 82f3b36..20e4f77 100644 --- a/serverless.yml +++ b/serverless.yml @@ -1,4 +1,4 @@ -service: minglar +service: minglarDev useDotenv: true diff --git a/src/modules/host/dto/createActivity.schema.ts b/src/modules/host/dto/createActivity.schema.ts index 9e68354..e97a625 100644 --- a/src/modules/host/dto/createActivity.schema.ts +++ b/src/modules/host/dto/createActivity.schema.ts @@ -36,12 +36,11 @@ export const PickupDetailDto = z.object({ locationLat: z.number().nullable().optional(), locationLong: z.number().nullable().optional(), locationAddress: z.string().nullable().optional(), - transportTotalPrice: z.number().int().min(1), + transportTotalPrice: z.number().int().min(0), }); export const PickupTransportDto = z.object({ transportModeXid: z.number().int(), - pickupDetails: z.array(PickupDetailDto).optional().default([]), }); /* ================= EQUIPMENT ================= */ @@ -146,6 +145,7 @@ export const CreateActivityDto = z.object({ foodTypeIds: z.array(z.number().int()).optional().default([]), cuisineIds: z.array(z.number().int()).optional().default([]), pickupTransports: z.array(PickupTransportDto).optional().default([]), + pickupDetails: z.array(PickupDetailDto).optional().default([]), navigationModes: z .array(NavigationModeDto) diff --git a/src/modules/host/services/host.service.ts b/src/modules/host/services/host.service.ts index 4ddc6ab..1d240c3 100644 --- a/src/modules/host/services/host.service.ts +++ b/src/modules/host/services/host.service.ts @@ -1009,39 +1009,88 @@ export class HostService { }, }); - // documents UPSERT - if (documents?.length) { - for (const doc of documents) { - if (!doc.filePath) continue; - const existingDoc = await tx.hostDocuments.findFirst({ - where: { - hostXid: updatedHost.id, - documentTypeXid: doc.documentTypeXid, - }, - }); + // // documents UPSERT + // if (documents?.length) { + // for (const doc of documents) { + // if (!doc.filePath) continue; + // const existingDoc = await tx.hostDocuments.findFirst({ + // where: { + // hostXid: updatedHost.id, + // documentTypeXid: doc.documentTypeXid, + // }, + // }); + + // if (existingDoc) { + // await tx.hostDocuments.update({ + // where: { id: existingDoc.id }, + // data: { + // filePath: doc.filePath, + // documentName: + // sanitizeDocumentName(doc.documentName) || + // existingDoc.documentName, + // }, + // }); + // } else { + // await tx.hostDocuments.create({ + // data: { + // hostXid: updatedHost.id, + // documentTypeXid: doc.documentTypeXid, + // documentName: sanitizeDocumentName(doc.documentName), + // filePath: doc.filePath, + // }, + // }); + // } + // } + // } + // documents handling (FINAL FIX) +if (documents?.length) { + for (const doc of documents) { + if (!doc.filePath) continue; + + // 🔹 CUSTOM DOCUMENTS → ALWAYS CREATE + if (doc.documentTypeXid === 9) { + await tx.hostDocuments.create({ + data: { + hostXid: updatedHost.id, + documentTypeXid: doc.documentTypeXid, + documentName: sanitizeDocumentName(doc.documentName), + filePath: doc.filePath, + }, + }); + continue; + } + + // 🔹 NORMAL DOCUMENTS → UPSERT (ONE PER TYPE) + const existingDoc = await tx.hostDocuments.findFirst({ + where: { + hostXid: updatedHost.id, + documentTypeXid: doc.documentTypeXid, + }, + }); + + if (existingDoc) { + await tx.hostDocuments.update({ + where: { id: existingDoc.id }, + data: { + filePath: doc.filePath, + documentName: + sanitizeDocumentName(doc.documentName) || + existingDoc.documentName, + }, + }); + } else { + await tx.hostDocuments.create({ + data: { + hostXid: updatedHost.id, + documentTypeXid: doc.documentTypeXid, + documentName: sanitizeDocumentName(doc.documentName), + filePath: doc.filePath, + }, + }); + } + } +} - if (existingDoc) { - await tx.hostDocuments.update({ - where: { id: existingDoc.id }, - data: { - filePath: doc.filePath, - documentName: - sanitizeDocumentName(doc.documentName) || - existingDoc.documentName, - }, - }); - } else { - await tx.hostDocuments.create({ - data: { - hostXid: updatedHost.id, - documentTypeXid: doc.documentTypeXid, - documentName: sanitizeDocumentName(doc.documentName), - filePath: doc.filePath, - }, - }); - } - } - } // parent logic untouched if (companyData.isSubsidairy) { @@ -3003,11 +3052,19 @@ export class HostService { } /* -------------------------------- - * 1️⃣1️⃣ CLEAN & CREATE PICKUP/DROP TRANSPORTS WITH DETAILS & TAXES + * 1️⃣1️⃣ CLEAN & CREATE PICKUP/DROP TRANSPORTS (INDEPENDENT ARRAY) * -------------------------------- */ /* -------------------------------- - * 1️⃣1️⃣ CLEAN OLD PICKUP/DROP DATA + * 1️⃣1️⃣ CLEAN OLD PICKUP/DROP TRANSPORT DATA (INDEPENDENT FROM NAVIGATION MODES) * -------------------------------- */ + // Clean up old pickup transport modes (independent array) + await tx.activityPickUpTransport.deleteMany({ + where: { + activityXid: Number(activityXid), + }, + }); + + // Clean up old pickup details and their taxes (independent from transport modes) const oldPickupDetailIds = ( await tx.activityPickUpDetails.findMany({ where: { activitiesXid: activityXid }, @@ -3022,71 +3079,71 @@ export class HostService { }, }); - await tx.activityPickUpTransport.deleteMany({ - where: { - activityXid: Number(activityXid), - }, - }); - await tx.activityPickUpDetails.deleteMany({ where: { id: { in: oldPickupDetailIds } }, }); } + /* -------------------------------- + * 1️⃣1️⃣ CREATE PICKUP TRANSPORTS (INDEPENDENT ARRAY - JUST TRANSPORT MODES) + * -------------------------------- */ if (Array.isArray(payload.pickupTransports)) { for (const transport of payload.pickupTransports) { - // ✅ CREATE TRANSPORT ONCE PER MODE - const pickupTransport = await tx.activityPickUpTransport.create({ + // ✅ CREATE TRANSPORT MODE INDEPENDENTLY (NO RELATION TO PICKUP DETAILS) + await tx.activityPickUpTransport.create({ data: { activityXid: activityXid, transportModeXid: transport.transportModeXid, }, }); + } + } - if (Array.isArray(transport.pickupDetails)) { - for (const detail of transport.pickupDetails) { - const totalPrice = toNumber(detail.transportTotalPrice) ?? 0; + /* -------------------------------- + * 1️⃣1️⃣ CREATE PICKUP DETAILS (INDEPENDENT ARRAY - SEPARATE FROM TRANSPORT MODES) + * -------------------------------- */ + if (Array.isArray(payload.pickupDetails)) { + for (const detail of payload.pickupDetails) { + const totalPrice = toNumber(detail.transportTotalPrice) ?? 0; - // On submit enforce > 0, on draft just skip - if (!isDraft && totalPrice <= 0) { - throw new ApiError( - 400, - 'transportTotalPrice must be > 0 when chargeable', - ); - } + // On submit enforce > 0, on draft just skip + if (!isDraft && totalPrice <= 0) { + throw new ApiError( + 400, + 'transportTotalPrice must be > 0 when chargeable', + ); + } - if (totalPrice <= 0) continue; + if (totalPrice <= 0) continue; - const { basePrice, taxDetails } = computeBasePriceAndTaxes( - totalPrice, - rootTaxes, - ); + const { basePrice, taxDetails } = computeBasePriceAndTaxes( + totalPrice, + rootTaxes, + ); - /* 1️⃣ CREATE PICKUP DETAILS */ - const pickupDetail = await tx.activityPickUpDetails.create({ - data: { - activitiesXid: activityXid, - isPickUp: toBool(detail.isPickUp), - locationLat: toNumber(detail.locationLat), - locationLong: toNumber(detail.locationLong), - locationAddress: detail.locationAddress ?? null, - transportBasePrice: basePrice, - transportTotalPrice: totalPrice, - }, - }); + /* CREATE PICKUP DETAILS INDEPENDENTLY */ + const pickupDetail = await tx.activityPickUpDetails.create({ + data: { + activitiesXid: activityXid, + isPickUp: toBool(detail.isPickUp), + locationLat: toNumber(detail.locationLat), + locationLong: toNumber(detail.locationLong), + locationAddress: detail.locationAddress ?? null, + transportBasePrice: basePrice, + transportTotalPrice: totalPrice, + }, + }); - /* 2️⃣ CREATE TAXES */ - if (taxDetails.length) { - await tx.activityPickUpTransportTaxes.createMany({ - data: taxDetails.map((t) => ({ - activityPickUpDetailsXid: pickupDetail.id, - taxXid: t.taxXid, - taxPer: t.taxPer, - taxAmount: t.taxAmount, - })), - }); - } - } + /* CREATE TAXES FOR PICKUP DETAILS */ + if (taxDetails.length) { + await tx.activityPickUpTransportTaxes.createMany({ + data: taxDetails.map((t) => ({ + activityPickUpDetailsXid: pickupDetail.id, + taxXid: t.taxXid, + taxPer: t.taxPer, + taxAmount: t.taxAmount, + })), + }); } } }