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, Injectable,
Logger, Logger,
} from "@nestjs/common"; } from "@nestjs/common";
import { OnEvent } from "@nestjs/event-emitter";
import { Freight } from "@edr/types"; import { Freight } from "@edr/types";
import { DataSource, EntityManager } from "typeorm"; import { DataSource, EntityManager } from "typeorm";
@@ -94,6 +95,7 @@ export class BookingInvoiceService {
* reactions live here (not in the payment process): each invoice type advances * reactions live here (not in the payment process): each invoice type advances
* the booking its own way. Only PREPAID exists today. * the booking its own way. Only PREPAID exists today.
*/ */
@OnEvent("booking.invoice.paid")
async onBookingInvoicePaid(payload: InvoiceEventPayload): Promise<void> { async onBookingInvoicePaid(payload: InvoiceEventPayload): Promise<void> {
this.logger.log( this.logger.log(
`onBookingInvoicePaid trigger for ${payload.sourceId} from ${payload.invoiceId}`, `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. * has stored the intent id, avoiding a settle-before-correlation race.
*/ */
async initiate(input: InitiateIntentInput): Promise<InitiateIntentResult> { async initiate(input: InitiateIntentInput): Promise<InitiateIntentResult> {
const snapshot = await this.paymentClient.initiate({ try {
service: PaymentServiceEnum.FREIGHT, const snapshot = await this.paymentClient.initiate({
referenceType: PaymentReferenceType.SHIPMENT, service: PaymentServiceEnum.FREIGHT,
referenceId: input.referenceId, referenceType: PaymentReferenceType.SHIPMENT,
orderRef: input.orderRef, referenceId: input.referenceId,
amountMinor: input.amountMinor, orderRef: input.orderRef,
currency: input.currency, amountMinor: input.amountMinor,
provider: input.method as ProviderMethod, currency: input.currency,
platform: input.platform, provider: input.method as ProviderMethod,
payerAccount: input.payerAccount, platform: input.platform,
returnUrl: payerAccount: input.payerAccount,
input.returnUrl ?? "https://edrfreight.triaplc.com/payment/success", returnUrl:
failureUrl: input.returnUrl ?? "https://edrfreight.triaplc.com/payment/success",
input.failureUrl ?? "https://edrfreight.triaplc.com/payment/failure", failureUrl:
}); input.failureUrl ?? "https://edrfreight.triaplc.com/payment/failure",
});
const immediateSuccess = const immediateSuccess =
snapshot.status === ProviderPaymentStatus.SUCCEEDED; snapshot.status === ProviderPaymentStatus.SUCCEEDED;
const paidAt = snapshot.paidAt ? new Date(snapshot.paidAt) : undefined; 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) { if (immediateSuccess) {
// Settle the projection but DO NOT notify billing — billing settles // Settle the projection but DO NOT notify billing — billing settles
// inline once it has stored intentId on the invoice (see payInvoice), // inline once it has stored intentId on the invoice (see payInvoice),
// avoiding a settle-before-correlation race. // avoiding a settle-before-correlation race.
await this.markIntentSucceeded(intent.id, { 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, providerTxnId: snapshot.providerTxnId,
paidAt, 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. */ /** Create or update the local intent projection from a provider snapshot. */