This commit is contained in:
natib21
2026-07-02 08:51:21 +00:00
parent db8ead322c
commit 07abe9b679
11 changed files with 126 additions and 9 deletions

View File

@@ -1,6 +1,6 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { IsIn, IsNumber, IsOptional, IsUUID, Min } from 'class-validator';
import { IsBoolean, IsIn, IsNumber, IsOptional, IsUUID, Min } from 'class-validator';
import { FIRST_MILE_STATUSES, FirstMileStatus } from '../entities/first-mile.entity';
@@ -58,4 +58,9 @@ export class CreateFirstMileDto {
@Transform(({ value }) => (value === '' ? undefined : value))
@IsUUID()
vehicleId?: string | null;
@ApiPropertyOptional({ description: 'Invoice payment status', default: false })
@IsOptional()
@IsBoolean()
paid?: boolean;
}

View File

@@ -35,6 +35,9 @@ export class FirstMile extends BaseEntity {
@Column({ name: 'remaining_payment', type: 'numeric', precision: 14, scale: 2, default: 0 })
remainingPayment!: number;
@Column({ name: 'paid', type: 'boolean', default: false })
paid!: boolean;
// TODO: uncomment after migration creates column
// @Column({ type: 'boolean', default: false })
// isPostPaymentCompleted!: boolean;

View File

@@ -12,6 +12,8 @@ import { UpdateFirstMileDto } from './dto/update-first-mile.dto';
import { FirstMile, FirstMileStatus } from './entities/first-mile.entity';
import { FirstMileContainerAllocation } from './entities/first-mile-container-allocation.entity';
import { FirstMileRepository } from './first-mile.repository';
import { OnEvent } from '@nestjs/event-emitter';
import { InvoiceEventPayload } from '../billing/billing.service';
type FirstMileListFilter = {
status?: FirstMileStatus;
@@ -146,6 +148,18 @@ export class FirstMileService {
};
}
@OnEvent("firstmile.invoice.paid")
async onBookingInvoicePaid(payload: InvoiceEventPayload): Promise<void> {
try {
await this.firstMileRepository.update(payload.sourceId, { paid: true } as any);
this.logger.log(`Marked first-mile record ${payload.sourceId} as paid (invoice ${payload.invoiceId})`);
} catch (err) {
this.logger.error(
`Failed to update first-mile payment status for record ${payload.sourceId}: ${String(err)}`,
);
}
}
async findById(id: string): Promise<FirstMile> {
const record = await this.firstMileRepository.findById(id, {
relations: {
@@ -175,6 +189,7 @@ export class FirstMileService {
estimatedKm: dto.estimatedKm ?? null,
exactKm: dto.exactKm ?? null,
vehicleId: dto.vehicleId ?? null,
paid: (dto as any).paid ?? false,
});
}
@@ -207,6 +222,7 @@ export class FirstMileService {
async update(id: string, dto: UpdateFirstMileDto): Promise<FirstMile> {
const existing = await this.findById(id);
const dtoAny = dto as any;
const updated = await this.firstMileRepository.update(id, {
...(dto.bookingId !== undefined ? { bookingId: dto.bookingId } : {}),
...(dto.status !== undefined ? { status: dto.status } : {}),
@@ -215,7 +231,8 @@ export class FirstMileService {
...(dto.estimatedKm !== undefined ? { estimatedKm: dto.estimatedKm } : {}),
...(dto.exactKm !== undefined ? { exactKm: dto.exactKm } : {}),
...(dto.vehicleId !== undefined ? { vehicleId: dto.vehicleId } : {}),
});
...(dtoAny.paid !== undefined ? { paid: dtoAny.paid } : {}),
} as any);
if (!updated) {
throw new NotFoundException(`First-mile record ${id} not found`);