mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
demurrage invoices
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { IsBoolean, IsNumber, IsOptional, IsString, Min } from 'class-validator';
|
||||
|
||||
export class GenerateInvoiceDto {
|
||||
@ApiPropertyOptional({ description: 'Create even when the calculated amount is zero.' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
confirmZero?: boolean;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
performedBy?: string;
|
||||
}
|
||||
|
||||
export class PayInvoiceBodyDto {
|
||||
@ApiPropertyOptional()
|
||||
@IsNumber()
|
||||
@Min(0.01)
|
||||
amount!: number;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
method?: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
reference?: string;
|
||||
}
|
||||
@@ -65,6 +65,12 @@ export class WarehouseInventoryController {
|
||||
return this.inventoryService.unloadBooking(bookingId, dto);
|
||||
}
|
||||
|
||||
@Post(':id/gate-clearance')
|
||||
@ApiOperation({ summary: 'Final terminal release / gate clearance (blocked while fees unpaid)' })
|
||||
gateClearance(@Param('id', ParseUUIDPipe) id: string, @Body('performedBy') performedBy?: string) {
|
||||
return this.inventoryService.gateClearance(id, performedBy);
|
||||
}
|
||||
|
||||
@Get('loadable-wagons')
|
||||
@ApiOperation({ summary: 'List wagons usable for loading (read-only from scheduling)' })
|
||||
loadableWagons() {
|
||||
|
||||
@@ -122,8 +122,37 @@ export class WarehouseInventoryService {
|
||||
private readonly activityLog: WarehouseActivityLogService,
|
||||
private readonly scheduling: SchedulingReadFacade,
|
||||
private readonly allocation: WarehouseAllocationService,
|
||||
private readonly invoices: WarehouseInvoiceService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Batch 6 — final terminal release / gate clearance.
|
||||
* Blocked while an unpaid demurrage/storage invoice exists. Does NOT touch
|
||||
* inspection / storage / loading steps — only the final release.
|
||||
*/
|
||||
async gateClearance(id: string, performedBy?: string): Promise<WarehouseInventory> {
|
||||
const item = await this.findById(id);
|
||||
const blocking = await this.invoices.findBlockingInvoice(id);
|
||||
if (blocking) {
|
||||
throw new BadRequestException(
|
||||
'Warehouse demurrage/storage fee must be paid before terminal release.',
|
||||
);
|
||||
}
|
||||
const now = new Date();
|
||||
await this.inventoryRepository.update(id, {
|
||||
gateClearedAt: now,
|
||||
releaseDate: item.releaseDate ?? now,
|
||||
});
|
||||
await this.activityLog.record({
|
||||
activityType: 'INVENTORY_DISPATCHED',
|
||||
inventoryId: id,
|
||||
warehouseId: item.warehouseId,
|
||||
description: 'Gate clearance / terminal release',
|
||||
performedBy,
|
||||
});
|
||||
return this.findById(id);
|
||||
}
|
||||
|
||||
// ── Listing ────────────────────────────────────────────────────────────
|
||||
|
||||
findAll(filter: FilterWarehouseInventoryDto): Promise<WarehouseInventory[]> {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Body, Controller, Get, Param, ParseUUIDPipe, Patch, Post, Query } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
|
||||
|
||||
import { GenerateInvoiceDto, PayInvoiceBodyDto } from './dto/invoice.dto';
|
||||
import { WarehouseInvoiceService } from './warehouse-invoice.service';
|
||||
|
||||
@ApiTags('warehouse-fee-invoices')
|
||||
@ApiBearerAuth()
|
||||
@Controller()
|
||||
export class WarehouseInvoiceController {
|
||||
constructor(private readonly invoiceService: WarehouseInvoiceService) {}
|
||||
|
||||
@Post('warehouse-inventory/:id/generate-fee-invoice')
|
||||
@ApiOperation({ summary: 'Generate a warehouse fee invoice from Batch 5 fee calculation' })
|
||||
generate(@Param('id', ParseUUIDPipe) id: string, @Body() dto: GenerateInvoiceDto) {
|
||||
return this.invoiceService.generateForInventory(id, dto);
|
||||
}
|
||||
|
||||
@Get('warehouse-inventory/:id/fee-invoices')
|
||||
@ApiOperation({ summary: 'List fee invoices for an inventory item' })
|
||||
listForInventory(@Param('id', ParseUUIDPipe) id: string) {
|
||||
return this.invoiceService.listForInventory(id);
|
||||
}
|
||||
|
||||
@Get('bookings/:id/warehouse-fee-invoices')
|
||||
@ApiOperation({ summary: 'List warehouse fee invoices for a booking' })
|
||||
listForBooking(@Param('id', ParseUUIDPipe) id: string) {
|
||||
return this.invoiceService.listForBooking(id);
|
||||
}
|
||||
|
||||
@Get('warehouse-fee-invoices')
|
||||
@ApiOperation({ summary: 'List / filter warehouse fee invoices' })
|
||||
findAll(
|
||||
@Query('status') status?: string,
|
||||
@Query('invoiceType') invoiceType?: string,
|
||||
@Query('warehouseId') warehouseId?: string,
|
||||
@Query('facilityId') facilityId?: string,
|
||||
@Query('customerId') customerId?: string,
|
||||
@Query('bookingId') bookingId?: string,
|
||||
) {
|
||||
return this.invoiceService.findAll({
|
||||
status: status as never,
|
||||
invoiceType: invoiceType as never,
|
||||
warehouseId,
|
||||
facilityId,
|
||||
customerId,
|
||||
bookingId,
|
||||
});
|
||||
}
|
||||
|
||||
@Get('warehouse-fee-invoices/:id')
|
||||
@ApiOperation({ summary: 'Get a warehouse fee invoice with items + payment history' })
|
||||
findOne(@Param('id', ParseUUIDPipe) id: string) {
|
||||
return this.invoiceService.findById(id);
|
||||
}
|
||||
|
||||
@Patch('warehouse-fee-invoices/:id/cancel')
|
||||
@ApiOperation({ summary: 'Cancel a warehouse fee invoice' })
|
||||
cancel(@Param('id', ParseUUIDPipe) id: string) {
|
||||
return this.invoiceService.cancel(id);
|
||||
}
|
||||
|
||||
@Post('warehouse-fee-invoices/:id/pay')
|
||||
@ApiOperation({ summary: 'Record a payment against a warehouse fee invoice' })
|
||||
pay(@Param('id', ParseUUIDPipe) id: string, @Body() dto: PayInvoiceBodyDto) {
|
||||
return this.invoiceService.pay(id, dto);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { FilesModule } from '../files/files.module';
|
||||
import { WarehouseActivityLog } from './entities/warehouse-activity-log.entity';
|
||||
import { WarehouseAllocationRule } from './entities/warehouse-allocation-rule.entity';
|
||||
import { WarehouseFeeInvoice } from './entities/warehouse-fee-invoice.entity';
|
||||
import { WarehouseFeeInvoiceItem } from './entities/warehouse-fee-invoice-item.entity';
|
||||
import { WarehouseFeeRule } from './entities/warehouse-fee-rule.entity';
|
||||
import { WarehouseInspectionReport } from './entities/warehouse-inspection-report.entity';
|
||||
import { WarehouseInventory } from './entities/warehouse-inventory.entity';
|
||||
@@ -29,6 +31,10 @@ import { WarehouseAllocationRuleRepository } from './warehouse-allocation-rule.r
|
||||
import { WarehouseAllocationService } from './warehouse-allocation.service';
|
||||
import { WarehouseFeeRuleRepository } from './warehouse-fee-rule.repository';
|
||||
import { WarehouseFeeService } from './warehouse-fee.service';
|
||||
import { WarehouseFeeInvoiceItemRepository } from './warehouse-fee-invoice-item.repository';
|
||||
import { WarehouseFeeInvoiceRepository } from './warehouse-fee-invoice.repository';
|
||||
import { WarehouseInvoiceController } from './warehouse-invoice.controller';
|
||||
import { WarehouseInvoiceService } from './warehouse-invoice.service';
|
||||
import { WarehouseRulesController } from './warehouse-rules.controller';
|
||||
import { WarehouseSchedulingAdapterService } from './warehouse-scheduling-adapter.service';
|
||||
import { WarehouseYardsController } from './warehouse-yards.controller';
|
||||
@@ -54,6 +60,8 @@ import { WarehousesService } from './warehouses.service';
|
||||
WarehouseInspectionReport,
|
||||
WarehouseAllocationRule,
|
||||
WarehouseFeeRule,
|
||||
WarehouseFeeInvoice,
|
||||
WarehouseFeeInvoiceItem,
|
||||
]),
|
||||
FilesModule,
|
||||
],
|
||||
@@ -65,6 +73,7 @@ import { WarehousesService } from './warehouses.service';
|
||||
WarehouseLoadingsController,
|
||||
WarehouseInspectionController,
|
||||
WarehouseRulesController,
|
||||
WarehouseInvoiceController,
|
||||
],
|
||||
providers: [
|
||||
WarehousesRepository,
|
||||
|
||||
Reference in New Issue
Block a user