Files
edr-platform/apps/edr-freight-api/src/modules/eims/dto/bulk-cancel-eims-registration.dto.ts
Hagernesh 7d8ab932c2 feat(eims): implement POST /v1/bulkCancel
New endpoint: POST invoices/eims/bulk-cancel, body { items: [{invoiceId,
reasonCode, remark?}] }. Same eimsCancel permission as single cancel — a
batch-scale version of the same irreversible-at-MoR action, not a new
capability.

Same local-eligibility doctrine as single cancel: an already-cancelled or
never-registered invoice is refused right here, no HTTP call, before it
gets a seat in the batch. Only genuinely eligible invoices go into the one
/v1/bulkCancel request; every outcome (local refusal or MoR's own
per-IRN result) is reported back independently — one invoice failing
never blocks the rest.

MoR's bulk response mixes success and error shapes in the same array,
disambiguated by Status (capital, error) vs status (lowercase, success)
— matched back to our invoices by IRN. Notably the bulk success shape
carries no cancellationDate at all, unlike single cancel.

Left out of this pass: bulkRegister. It's async (returns only a
conversationId immediately, results arrive via a webhook callback we
don't have yet) and needs manual counter/previousIrn management per
the collection's own docs — a materially different reservation model
than today's single-invoice TX1/TX2 pattern. Scoping that is a
separate, bigger piece of work.
2026-08-17 17:49:33 +00:00

34 lines
1.0 KiB
TypeScript

import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { Type } from "class-transformer";
import { ArrayMinSize, IsArray, IsOptional, IsString, IsUUID, Length, ValidateNested } from "class-validator";
export class BulkCancelEimsItemDto {
@ApiProperty({ description: "Invoice ID to cancel." })
@IsUUID()
invoiceId!: string;
@ApiProperty({
description: 'Numeric reason code, e.g. "1" (Duplicate), "6" (Calculation Error).',
example: "1",
})
@IsString()
@Length(1, 8)
reasonCode!: string;
@ApiPropertyOptional({ description: "Free-text cancellation note.", example: "Duplicate submission" })
@IsOptional()
@IsString()
@Length(0, 500)
remark?: string;
}
/** `POST invoices/eims/bulk-cancel` body — see `EimsCancellationService.cancelBulkWithEims`. */
export class BulkCancelEimsRegistrationDto {
@ApiProperty({ type: [BulkCancelEimsItemDto] })
@IsArray()
@ArrayMinSize(1)
@ValidateNested({ each: true })
@Type(() => BulkCancelEimsItemDto)
items!: BulkCancelEimsItemDto[];
}