fix: booking invoice issue

This commit is contained in:
ghost2023
2026-07-01 16:11:47 +03:00
parent 43d1634823
commit 2f79178496
3 changed files with 56 additions and 54 deletions

View File

@@ -65,7 +65,7 @@ export class BookingInvoiceService {
async ensureInvoiceForBooking(
booking: Booking,
invoiceOptions: InvoiceOptions = {},
): Promise<Invoice | null> {
): Promise<Invoice> {
const existing = await this.billing.findPayable(
Freight.InvoiceSource.Booking,
booking.id,
@@ -77,16 +77,9 @@ export class BookingInvoiceService {
this.logger.warn(
`Skipping invoice for booking ${booking.reference} (${booking.id}): no company to bill.`,
);
return null;
}
const input = this.buildInput(booking, invoiceOptions);
if (!input) {
this.logger.warn(
`Skipping invoice for booking ${booking.reference} (${booking.id}): no priced amount.`,
);
return null;
}
return this.billing.generateInvoice(input);
}
@@ -154,7 +147,7 @@ export class BookingInvoiceService {
private buildInput(
booking: Booking,
invoiceOptions: InvoiceOptions = {},
): GenerateInvoiceInput | null {
): GenerateInvoiceInput {
const breakdown = (booking.pricingBreakdown ??
{}) as StoredPricingBreakdown;
const currency = breakdown.currency ?? booking.paymentCurrency ?? "ETB";
@@ -172,7 +165,7 @@ export class BookingInvoiceService {
// Fall back to a single freight line when no breakdown was snapshotted.
if (lines.length === 0) {
const amount = Number(booking.totalAmount);
if (!Number.isFinite(amount) || amount <= 0) return null;
if (!Number.isFinite(amount) || amount <= 0) throw new Error("No price");
lines.push({
chargeType: "FREIGHT",
description: "Rail freight",

View File

@@ -3,6 +3,7 @@ import {
forwardRef,
Inject,
Injectable,
Logger,
} from "@nestjs/common";
import type { TCurrentUser } from "@tria-plc/api-common/modules/auth/types/current-user.type";
@@ -31,6 +32,7 @@ import { Freight } from "@edr/types";
@Injectable()
export class BookingTransitionService {
private readonly logger = new Logger(BookingTransitionService.name);
constructor(
private readonly bookingsRepository: BookingsRepository,
private readonly ruleEngineService: RuleEngineService,
@@ -918,8 +920,10 @@ export class BookingTransitionService {
private async acceptOperationRequest(booking: Booking): Promise<Booking> {
const now = new Date();
const invoice =
(await this.invoiceService.ensureInvoiceForBooking(booking))!;
const invoice = await this.invoiceService.ensureInvoiceForBooking(booking);
this.logger.log(
`Generated invoice ${invoice.invoiceNumber} (${invoice.id}) for ${booking.reference}:${booking.id}`,
);
await this.invoiceService.updateStatus(
invoice.id,
Freight.InvoiceStatus.Pending,

View File

@@ -1,44 +1,44 @@
import { Module, forwardRef } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ExchangeModule, ExchangeOptions } from '@edr/api-common';
import { Module, forwardRef } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ExchangeModule, ExchangeOptions } from "@edr/api-common";
// import { CustomersModule } from '../customers/customers.module';
import { CompaniesModule } from '../companies/companies.module';
import { FilesModule } from '../files/files.module';
import { MinioModule } from '../minio/minio.module';
import { RuleEngineModule } from '../rule-engine/rule-engine.module';
import { FileUploadSettingsModule } from '../file-upload-settings/file-upload-settings.module';
import { SignaturesModule } from '../signatures/signatures.module';
import { BillingModule } from '../billing/billing.module';
import { FirstMileModule } from '../first-mile/first-mile.module';
import { BookingContractService } from './booking-contract.service';
import { BookingInvoiceService } from './booking-invoice.service';
import { BookingPaymentController } from './booking-payment.controller';
import { BookingPaymentService } from './booking-payment.service';
import { BookingPricingService } from './booking-pricing.service';
import { BookingReferenceDataService } from './booking-reference-data.service';
import { BookingTransitionService } from './booking-transition.service';
import { BookingsController } from './bookings.controller';
import { PayController } from './pay.controller';
import { BookingsRepository } from './bookings.repository';
import { ConsolidationService } from './consolidation.service';
import { BookingsService } from './bookings.service';
import { BookingApprovalStep } from './entities/booking-approval-step.entity';
import { BookingCargoModifier } from './entities/booking-cargo-modifier.entity';
import { BookingDocumentReview } from './entities/booking-document-review.entity';
import { BookingContainer } from './entities/booking-container.entity';
import { BookingRateSnapshot } from './entities/booking-rate-snapshot.entity';
import { BookingContractSignature } from './entities/booking-contract-signature.entity';
import { BookingReviewNote } from './entities/booking-review-note.entity';
import { Booking } from './entities/booking.entity';
import { BookingContainerAllocation } from './entities/booking-container-allocation.entity';
import { ContractPdfService } from '../../contracts/contract-pdf.service';
import { ContractPricingScheduleBuilder } from '../../contracts/contract-pricing-schedule.builder';
import { ContractRendererService } from '../../contracts/contract-renderer.service';
import { ContractTemplateResolver } from '../../contracts/contract-template.resolver';
import { ContractViewModelBuilder } from '../../contracts/contract-view-model.builder';
import { TrainSchedulingModule } from '../train-scheduling/train-scheduling.module';
import { CompaniesModule } from "../companies/companies.module";
import { FilesModule } from "../files/files.module";
import { MinioModule } from "../minio/minio.module";
import { RuleEngineModule } from "../rule-engine/rule-engine.module";
import { FileUploadSettingsModule } from "../file-upload-settings/file-upload-settings.module";
import { SignaturesModule } from "../signatures/signatures.module";
import { BillingModule } from "../billing/billing.module";
import { FirstMileModule } from "../first-mile/first-mile.module";
import { BookingContractService } from "./booking-contract.service";
import { BookingInvoiceService } from "./booking-invoice.service";
import { BookingPaymentController } from "./booking-payment.controller";
import { BookingPaymentService } from "./booking-payment.service";
import { BookingPricingService } from "./booking-pricing.service";
import { BookingReferenceDataService } from "./booking-reference-data.service";
import { BookingTransitionService } from "./booking-transition.service";
import { BookingsController } from "./bookings.controller";
import { PayController } from "./pay.controller";
import { BookingsRepository } from "./bookings.repository";
import { ConsolidationService } from "./consolidation.service";
import { BookingsService } from "./bookings.service";
import { BookingApprovalStep } from "./entities/booking-approval-step.entity";
import { BookingCargoModifier } from "./entities/booking-cargo-modifier.entity";
import { BookingDocumentReview } from "./entities/booking-document-review.entity";
import { BookingContainer } from "./entities/booking-container.entity";
import { BookingRateSnapshot } from "./entities/booking-rate-snapshot.entity";
import { BookingContractSignature } from "./entities/booking-contract-signature.entity";
import { BookingReviewNote } from "./entities/booking-review-note.entity";
import { Booking } from "./entities/booking.entity";
import { BookingContainerAllocation } from "./entities/booking-container-allocation.entity";
import { ContractPdfService } from "../../contracts/contract-pdf.service";
import { ContractPricingScheduleBuilder } from "../../contracts/contract-pricing-schedule.builder";
import { ContractRendererService } from "../../contracts/contract-renderer.service";
import { ContractTemplateResolver } from "../../contracts/contract-template.resolver";
import { ContractViewModelBuilder } from "../../contracts/contract-view-model.builder";
import { TrainSchedulingModule } from "../train-scheduling/train-scheduling.module";
@Module({
imports: [
@@ -66,7 +66,7 @@ import { TrainSchedulingModule } from '../train-scheduling/train-scheduling.modu
ExchangeModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService): ExchangeOptions =>
config.get<ExchangeOptions>('app.cbeExchange') ?? {},
config.get<ExchangeOptions>("app.cbeExchange") ?? {},
}),
],
controllers: [BookingsController, PayController, BookingPaymentController],
@@ -86,6 +86,11 @@ import { TrainSchedulingModule } from '../train-scheduling/train-scheduling.modu
ContractRendererService,
ContractPdfService,
],
exports: [BookingsService, BookingsRepository, BookingPricingService, BookingInvoiceService],
exports: [
BookingsService,
BookingsRepository,
BookingPricingService,
BookingInvoiceService,
],
})
export class BookingsModule {}
export class BookingsModule { }