feat: add settlement_type to SalesInvoice model and related DTOs

- Added settlement_type field to SalesInvoice model with ENUM values (CASH, CREDIT, MIXED).
- Updated SalesInvoice aggregate types, input types, and where filters to include settlement_type.
- Modified StatisticsService to calculate credit amounts based on settlement_type.
- Enhanced TspProviderOriginalSendPayloadDto to include settlement_type.
- Updated NamaProvider DTOs and utility functions to handle new settlement_type logic.
- Created migration to add settlement_type column to sales_invoices table and backfill existing records.
This commit is contained in:
2026-05-24 19:40:04 +03:30
parent b53b7d3ed3
commit ea6f1bfdd0
17 changed files with 340 additions and 268 deletions
@@ -5,6 +5,7 @@ import {
} from '@/common/services/saleInvoices/sale-invoice-create.dto'
import {
CustomerType,
InvoiceSettlementType,
InvoiceTemplateType,
PaymentMethodType,
TspProviderRequestType,
@@ -208,6 +209,10 @@ export class TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true })
@IsString()
tsp_token: string
@ApiProperty({ required: true, enum: InvoiceSettlementType })
@IsEnum(InvoiceSettlementType)
settlement_type: InvoiceSettlementType
}
export class TspProviderSendItemResultDto {
@@ -288,6 +288,7 @@ export class SalesInvoiceTspService {
items: dataToUpdate.items,
total_amount: dataToUpdate.total_amount,
customer_id: relatedInvoice.customer_id || undefined,
settlement_type: relatedInvoice.settlement_type,
},
businessId,
complexId,
@@ -320,8 +321,7 @@ export class SalesInvoiceTspService {
)
if (result?.hasError) {
result.provider_request_payload =
result.provider_request_payload ||
JSON.parse(JSON.stringify(correctionPayload))
result.provider_request_payload || JSON.parse(JSON.stringify(correctionPayload))
result.sent_at = result.sent_at || new Date().toISOString()
result.received_at = result.received_at || new Date().toISOString()
}
@@ -472,6 +472,7 @@ export class SalesInvoiceTspService {
customer_type: relatedInvoice.customer?.type || CustomerType.UNKNOWN,
invoice_date: new Date(),
payments,
settlement_type: relatedInvoice.settlement_type,
items: relatedInvoice.items.map(item => ({
unit_price: Number(item.unit_price),
quantity: Number(item.quantity),
@@ -168,9 +168,17 @@ export class NamaProviderHeaderDto {
@IsString()
bid: string
@ApiProperty({ required: true, description: 'روش تسویه' })
@ApiProperty({ required: true, description: 'روش تسویه (۱.نقدی، ۲.نسیه، ۳.نقدی-نسیه)' })
@IsString()
setm: string
setm: '1' | '2' | '3'
@ApiProperty({ description: 'سهم پرداخت نقدی در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
cap: string
@ApiProperty({ description: 'سهم پرداخت نسیه در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
insp: string
}
export class NamaProviderRequestDto {
@@ -508,9 +516,17 @@ export class NamaProviderCorrectionHeaderDto {
@IsString()
bid: string
@ApiProperty({ required: true, description: 'روش تسویه' })
@ApiProperty({ required: true, description: 'روش تسویه (۱.نقدی، ۲.نسیه، ۳.نقدی-نسیه)' })
@IsString()
setm: string
setm: '1' | '2' | '3'
@ApiProperty({ description: 'سهم پرداخت نقدی در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
cap: string
@ApiProperty({ description: 'سهم پرداخت نسیه در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
insp: string
}
export class NamaProviderCorrectionRequestDto {
@@ -1,6 +1,7 @@
import { TspProviderCustomerType } from '@/common/enums/enums'
import {
CustomerType,
InvoiceSettlementType,
InvoiceTemplateType,
PaymentMethodType,
TspProviderRequestType,
@@ -54,7 +55,11 @@ export class NamaProviderUtils {
inno: payload.invoice_number.toString(),
tins: '',
indatim: payload.invoice_date.getTime() + '',
setm: '1',
...this.mapSettlementBased(
payload.settlement_type,
payload.payments,
payload.total_amount,
),
...this.mapCustomerInfo(payload.customer),
},
body: payload.items.map(item => ({
@@ -134,6 +139,41 @@ export class NamaProviderUtils {
}
}
private mapSettlementType(type: InvoiceSettlementType) {
switch (type) {
case InvoiceSettlementType.CASH:
return '1'
case InvoiceSettlementType.CREDIT:
return '2'
case InvoiceSettlementType.MIXED:
return '3'
}
}
private mapSettlementBased(
type: InvoiceSettlementType,
payments: PaymentInfoDto[],
totalAmount: number,
) {
switch (type) {
case InvoiceSettlementType.CASH:
return {
setm: '1',
}
case InvoiceSettlementType.CREDIT:
return {
setm: '2',
}
case InvoiceSettlementType.MIXED:
const totalPayed = payments.reduce((prev, curr) => (prev += curr.amount), 0)
return {
setm: '3',
cap: totalPayed.toString(),
insp: (totalAmount - totalPayed).toString(),
}
}
}
private mapInvoiceTemplate(template: InvoiceTemplateType) {
switch (template) {
case InvoiceTemplateType.SALE: