mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 01:18:18 +00:00
feat(last-mile): customer-signed LM contract gates the advance invoice
Approval now snapshots the rate estimate and generates a last-mile contract instead of invoicing immediately. The customer picks a delivery date on the confirm form, then reviews and signs the contract in the portal (saved signature or drawn); the signed PDF is stored as LM_<CustomerName>.pdf and only then is the advance invoice issued. Backoffice shows signature status and the contract download.
This commit is contained in:
@@ -10,11 +10,35 @@ export interface LastMileRequest {
|
||||
trainScheduleId: string;
|
||||
status: "AWAITING_CONFIRMATION" | "SUBMITTED" | "APPROVED" | "REJECTED";
|
||||
requestedContainerNumbers?: string[] | null;
|
||||
requestedDeliveryDate?: string | null;
|
||||
customerSignedAt?: string | null;
|
||||
rejectionReason?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface LastMileContractView {
|
||||
requestId: string;
|
||||
bookingId: string;
|
||||
bookingReference?: string | null;
|
||||
status: LastMileRequest["status"];
|
||||
html: string;
|
||||
customerSignedAt: string | null;
|
||||
signerDisplayName: string | null;
|
||||
canSign: boolean;
|
||||
savedSignature?: {
|
||||
signerDisplayName: string;
|
||||
signatureImageUrl: string | null;
|
||||
stampImageUrl: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SignLastMileContractPayload {
|
||||
signatureImageBase64?: string;
|
||||
signerDisplayName: string;
|
||||
consentText?: string;
|
||||
}
|
||||
|
||||
export const lastMileRequestsService = {
|
||||
/** One last-mile confirmation request, by id. */
|
||||
get: async (id: string): Promise<LastMileRequest> => {
|
||||
@@ -22,12 +46,36 @@ export const lastMileRequestsService = {
|
||||
return data.data ?? data;
|
||||
},
|
||||
|
||||
/** Confirm which containers on the booking go via EDR last-mile. */
|
||||
/** Confirm which containers go via EDR last-mile and the requested delivery date. */
|
||||
submit: async (
|
||||
id: string,
|
||||
containerNumbers: string[],
|
||||
deliveryDate: string,
|
||||
): Promise<LastMileRequest> => {
|
||||
const { data } = await client.post(L.SUBMIT(id), { containerNumbers });
|
||||
const { data } = await client.post(L.SUBMIT(id), { containerNumbers, deliveryDate });
|
||||
return data.data ?? data;
|
||||
},
|
||||
|
||||
/** LM contract view model + rendered HTML + saved signature. */
|
||||
getContractView: async (id: string): Promise<LastMileContractView> => {
|
||||
const { data } = await client.get(L.CONTRACT_VIEW(id));
|
||||
return data.data ?? data;
|
||||
},
|
||||
|
||||
/** Agree & sign the LM contract — the advance invoice is issued right after. */
|
||||
signContract: async (
|
||||
id: string,
|
||||
payload: SignLastMileContractPayload,
|
||||
): Promise<LastMileRequest> => {
|
||||
const { data } = await client.post(L.CONTRACT_SIGN(id), payload);
|
||||
return data.data ?? data;
|
||||
},
|
||||
|
||||
/** The LM contract PDF (LM_<CustomerName>.pdf). */
|
||||
downloadContractDocument: async (id: string): Promise<Blob> => {
|
||||
const { data } = await client.get(L.CONTRACT_DOCUMENT(id), {
|
||||
responseType: "blob",
|
||||
});
|
||||
return data;
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user