Merge pull request #724 from Tria-plc/freight/feat/fixes-v1

Freight/feat/fixes v1
This commit is contained in:
Nathnael Wondisha
2026-07-16 10:59:36 +03:00
committed by GitHub
3 changed files with 34 additions and 20 deletions

View File

@@ -125,7 +125,7 @@ export class BillingService {
private readonly payment: PaymentService,
private readonly companies: CompaniesService,
private readonly invoiceDocuments: InvoiceDocumentService,
) {}
) { }
// ── Reads ──────────────────────────────────────────────────────────────────
@@ -432,7 +432,7 @@ export class BillingService {
input.dueAt ??
new Date(
Date.now() +
(input.dueInDays ?? DEFAULT_DUE_DAYS) * 24 * 60 * 60 * 1000,
(input.dueInDays ?? DEFAULT_DUE_DAYS) * 24 * 60 * 60 * 1000,
);
const invoiceNumber = await this.nextInvoiceNumber(mg);
@@ -991,26 +991,26 @@ export class BillingService {
returnUrl: opts.returnUrl,
failureUrl: opts.failureUrl,
});
//
//
// Link the intent to the invoice BEFORE any settlement can correlate against it.
await this.dataSource
.getRepository(Invoice)
.update({ id: invoice.id }, { paymentId: result.intentId });
// DEMO: manually fire the gateway `payment.succeeded` callback here, without
// waiting for real gateway settlement. Runs AFTER the paymentId link above so
// `handlePaymentEvent → settleByPaymentId` can correlate the invoice. TODO:
// remove — real settlement flips this via the `${source}.invoice.paid` handler.
if (!result.immediateSuccess) {
await this.payment.handlePaymentEvent({
eventType: "payment.succeeded",
eventId: `demo-${result.intentId}`,
referenceId: invoice.sourceId,
intentId: result.intentId,
providerTxnId: result.providerTxnId,
paidAt: (result.paidAt ?? new Date()).toISOString(),
});
}
// // DEMO: manually fire the gateway `payment.succeeded` callback here, without
// // waiting for real gateway settlement. Runs AFTER the paymentId link above so
// // `handlePaymentEvent → settleByPaymentId` can correlate the invoice. TODO:
// // remove — real settlement flips this via the `${source}.invoice.paid` handler.
// if (!result.immediateSuccess) {
// await this.payment.handlePaymentEvent({
// eventType: "payment.succeeded",
// eventId: `demo-${result.intentId}`,
// referenceId: invoice.sourceId,
// intentId: result.intentId,
// providerTxnId: result.providerTxnId,
// paidAt: (result.paidAt ?? new Date()).toISOString(),
// });
// }
if (result.immediateSuccess) {
await this.settleByPaymentId(

View File

@@ -110,6 +110,13 @@ export default function ContractClearanceDetailPage() {
const { data: bookingMilestones, refetch: refetchBookingMilestones } =
useBookingMilestones(linkedBookingId);
// react-query's imperative refetch() ignores `enabled`, so calling it while
// linkedBookingId is still undefined (pre-booking clearance) would fire
// GET /contracts/bookings/undefined/milestones → 400 (uuid expected). Guard it.
const refetchBookingMilestonesIfLinked = () => {
if (linkedBookingId) void refetchBookingMilestones();
};
if (isLoading) {
return (
<PageContainer>
@@ -261,7 +268,7 @@ export default function ContractClearanceDetailPage() {
onChanged={() => {
void refetch();
void refetchContract();
void refetchBookingMilestones();
refetchBookingMilestonesIfLinked();
}}
/>
</Grid.Col>
@@ -279,7 +286,7 @@ export default function ContractClearanceDetailPage() {
roleMode="ET"
onChanged={() => {
void refetch();
void refetchBookingMilestones();
refetchBookingMilestonesIfLinked();
}}
onViewFile={view}
onDownloadFile={(f) => void downloadBookingFile(f.id, f.name)}

View File

@@ -105,6 +105,13 @@ export default function GlClearanceDetailPage() {
const { data: bookingMilestones, refetch: refetchBookingMilestones } =
useBookingMilestones(linkedBookingId);
// react-query's imperative refetch() ignores `enabled`, so calling it while
// linkedBookingId is still undefined (pre-booking clearance) would fire
// GET /contracts/bookings/undefined/milestones → 400 (uuid expected). Guard it.
const refetchBookingMilestonesIfLinked = () => {
if (linkedBookingId) void refetchBookingMilestones();
};
if (isLoading) {
return (
<PageContainer>
@@ -275,7 +282,7 @@ export default function GlClearanceDetailPage() {
onUploadRoRequest={() => setUploadKind("ro")}
onChanged={() => {
void refetch();
void refetchBookingMilestones();
refetchBookingMilestonesIfLinked();
}}
onViewFile={view}
onDownloadFile={(f) => void downloadBookingFile(f.id, f.name)}