fix: booking paid trigger

This commit is contained in:
ghost2023
2026-07-02 16:18:46 +03:00
parent 4098b5476f
commit 79c3293a72
2 changed files with 43 additions and 36 deletions

View File

@@ -5,6 +5,7 @@ import {
Injectable,
Logger,
} from "@nestjs/common";
import { OnEvent } from "@nestjs/event-emitter";
import { Freight } from "@edr/types";
import { DataSource, EntityManager } from "typeorm";
@@ -94,6 +95,7 @@ export class BookingInvoiceService {
* reactions live here (not in the payment process): each invoice type advances
* the booking its own way. Only PREPAID exists today.
*/
@OnEvent("booking.invoice.paid")
async onBookingInvoicePaid(payload: InvoiceEventPayload): Promise<void> {
this.logger.log(
`onBookingInvoicePaid trigger for ${payload.sourceId} from ${payload.invoiceId}`,

View File

@@ -189,48 +189,53 @@ export class PaymentService {
* has stored the intent id, avoiding a settle-before-correlation race.
*/
async initiate(input: InitiateIntentInput): Promise<InitiateIntentResult> {
const snapshot = await this.paymentClient.initiate({
service: PaymentServiceEnum.FREIGHT,
referenceType: PaymentReferenceType.SHIPMENT,
referenceId: input.referenceId,
orderRef: input.orderRef,
amountMinor: input.amountMinor,
currency: input.currency,
provider: input.method as ProviderMethod,
platform: input.platform,
payerAccount: input.payerAccount,
returnUrl:
input.returnUrl ?? "https://edrfreight.triaplc.com/payment/success",
failureUrl:
input.failureUrl ?? "https://edrfreight.triaplc.com/payment/failure",
});
try {
const snapshot = await this.paymentClient.initiate({
service: PaymentServiceEnum.FREIGHT,
referenceType: PaymentReferenceType.SHIPMENT,
referenceId: input.referenceId,
orderRef: input.orderRef,
amountMinor: input.amountMinor,
currency: input.currency,
provider: input.method as ProviderMethod,
platform: input.platform,
payerAccount: input.payerAccount,
returnUrl:
input.returnUrl ?? "https://edrfreight.triaplc.com/payment/success",
failureUrl:
input.failureUrl ?? "https://edrfreight.triaplc.com/payment/failure",
});
const immediateSuccess =
snapshot.status === ProviderPaymentStatus.SUCCEEDED;
const paidAt = snapshot.paidAt ? new Date(snapshot.paidAt) : undefined;
const immediateSuccess =
snapshot.status === ProviderPaymentStatus.SUCCEEDED;
const paidAt = snapshot.paidAt ? new Date(snapshot.paidAt) : undefined;
const intent = await this.upsertIntent(input, snapshot);
const intent = await this.upsertIntent(input, snapshot);
if (immediateSuccess) {
// Settle the projection but DO NOT notify billing — billing settles
// inline once it has stored intentId on the invoice (see payInvoice),
// avoiding a settle-before-correlation race.
await this.markIntentSucceeded(intent.id, {
if (immediateSuccess) {
// Settle the projection but DO NOT notify billing — billing settles
// inline once it has stored intentId on the invoice (see payInvoice),
// avoiding a settle-before-correlation race.
await this.markIntentSucceeded(intent.id, {
providerTxnId: snapshot.providerTxnId,
paidAt,
notify: false,
});
}
return {
intentId: intent.id,
// `intent` still reflects the projection status ("processing" on immediate
// success — settlement is applied by the caller, not shown synchronously).
response: this.formatIntentResponse(intent),
immediateSuccess,
providerTxnId: snapshot.providerTxnId,
paidAt,
notify: false,
});
};
} catch (err) {
console.log(err);
throw err;
}
return {
intentId: intent.id,
// `intent` still reflects the projection status ("processing" on immediate
// success — settlement is applied by the caller, not shown synchronously).
response: this.formatIntentResponse(intent),
immediateSuccess,
providerTxnId: snapshot.providerTxnId,
paidAt,
};
}
/** Create or update the local intent projection from a provider snapshot. */