eims integration master test complete

This commit is contained in:
Hagernesh
2026-08-12 14:08:28 +00:00
parent 8d53dc17ce
commit 2d4da8110b
38 changed files with 2270 additions and 173 deletions

View File

@@ -0,0 +1,19 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsOptional, IsString, Length } from "class-validator";
/** `POST /v1/cancel` body — `ReasonCode`/`Remark` are the collection's own field names. */
export class CancelEimsRegistrationDto {
@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;
}

View File

@@ -0,0 +1,88 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsIn, IsNumber, IsOptional, IsString, Length } from "class-validator";
import { EIMS_MODE_OF_PAYMENT, EimsModeOfPayment } from "../eims-receipt.types";
/**
* `POST /v1/receipt/sales` — invoice/amounts/currency/IRN are derived from the invoice; everything
* here is what this codebase has no source of truth for, so it is asked of the caller rather than
* guessed (payment method, collector, provider references — none of it is modelled on `Invoice`).
*/
export class RegisterSalesReceiptDto {
@ApiProperty({ enum: EIMS_MODE_OF_PAYMENT, description: "MoR's confirmed ModeOfPayment enum." })
@IsIn(EIMS_MODE_OF_PAYMENT)
modeOfPayment!: EimsModeOfPayment;
@ApiPropertyOptional({ description: 'Defaults to "Payment received".' })
@IsOptional()
@IsString()
reason?: string;
@ApiPropertyOptional({ description: "Overrides the amount collected; defaults to the invoice's paidAmount." })
@IsOptional()
@IsNumber()
collectedAmount?: number;
@ApiPropertyOptional({ description: "ETB, USD or CAD. Defaults to the invoice's currency." })
@IsOptional()
@IsString()
currency?: string;
@ApiPropertyOptional({ description: "Required when currency is not ETB." })
@IsOptional()
@IsNumber()
exchangeRate?: number;
@ApiPropertyOptional({ description: 'Defaults to "FULL" if the invoice balance is 0, else "PARTIAL".' })
@IsOptional()
@IsString()
paymentCoverage?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 200)
collectorName?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 200)
paymentServiceProvider?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 200)
otherPaymentServiceProviderName?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 100)
accountNumber?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 100)
transactionNumber?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 100)
chequeNumber?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 100)
cpoNumber?: string;
@ApiPropertyOptional()
@IsOptional()
@IsString()
@Length(0, 100)
documentNumber?: string;
}

View File

@@ -0,0 +1,40 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsNumber, IsOptional, IsString, Length } from "class-validator";
/**
* `POST /v1/receipt/withholding`. `type`/`preTaxAmount`/`withholdingAmount` are real money/tax
* values this codebase has no computed source for (the same "no tax model" gap the invoice mapper
* documents) — required from the caller rather than defaulted or derived.
*/
export class RegisterWithholdingReceiptDto {
@ApiProperty({
description: 'WithholdDetail.Type. Only "TWHT" has been observed; not restricted to it.',
example: "TWHT",
})
@IsString()
@Length(1, 16)
type!: string;
@ApiPropertyOptional()
@IsOptional()
@IsNumber()
rate?: number;
@ApiProperty({ description: "Amount the withholding is calculated against." })
@IsNumber()
preTaxAmount!: number;
@ApiProperty({ description: "The withheld amount itself." })
@IsNumber()
withholdingAmount!: number;
@ApiPropertyOptional({ description: 'Defaults to "Withholding".' })
@IsOptional()
@IsString()
reason?: string;
@ApiPropertyOptional({ description: "Required when the invoice currency is not ETB." })
@IsOptional()
@IsNumber()
exchangeRate?: number;
}

View File

@@ -10,9 +10,11 @@ export class ResolveEimsRegistrationDto {
description: "IRN confirmed in the MoR portal. Records the registration and resumes the chain.",
example: "9fe9bbbece6ab76c112b617534e6aac7aa8b819d5be79f4d3d088ed2e887b2e0",
})
// Not capped at 64: eims_irn is `text` now — a real IRN already overflowed a former
// varchar(64) (69 chars). This bound is a sanity ceiling, not a confirmed MoR format.
@IsOptional()
@IsString()
@Length(1, 64)
@Length(1, 500)
irn?: string;
@ApiPropertyOptional({