update switch providers and nama provider. fix original send

This commit is contained in:
2026-05-27 21:55:02 +03:30
parent 4836ee4d01
commit 816c5ebb50
31 changed files with 1381 additions and 1287 deletions
@@ -1,18 +1,18 @@
import { SaleInvoiceTspAttemptsUpdateInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, NotFoundException } from '@nestjs/common'
import { TspProviderCustomerType } from 'common/enums/enums'
import {
Prisma,
TspProviderRequestType,
TspProviderResponseStatus,
} from 'generated/prisma/client'
import {
TspProviderActionResponseDto,
TspProviderCorrectionSendPayloadDto,
TspProviderOriginalSendItemResultDto,
TspProviderOriginalSendPayloadDto,
TspProviderRevokePayloadDto,
TspProviderSendItemResultDto,
} from '../dto/provider-switch.dto'
} from '../dto'
import { TspProviderActionResponseDto } from '../dto/provider-switch.dto'
export async function getOriginalResendAttemptNumber(
prisma: PrismaService,
@@ -49,7 +49,10 @@ export async function getOriginalResendAttemptNumber(
'فاکتور تایید شده از طرف سازمان مالیاتی قابل ارسال مجدد نیست.',
)
}
if (existingAttempt.status === TspProviderResponseStatus.QUEUED) {
if (
existingAttempt.status === TspProviderResponseStatus.QUEUED ||
existingAttempt.status === TspProviderResponseStatus.FISCAL_QUEUED
) {
throw new BadRequestException(
'در حال حاضر فاکتور شما در حال بررسی توسط سازمان مالیاتی است.',
)
@@ -164,6 +167,7 @@ export async function buildCorrectionPayload(
invoice_date: true,
invoice_number: true,
settlement_type: true,
tax_id: true,
items: true,
pos: {
select: {
@@ -207,6 +211,7 @@ export async function buildCorrectionPayload(
},
},
},
unknown_customer: true,
customer: {
select: {
type: true,
@@ -234,6 +239,8 @@ export async function buildCorrectionPayload(
const { partner } = (invoice.pos.complex.business_activity.consumer.legal ||
invoice.pos.complex.business_activity.consumer.individual)!
const unknown_customer = (invoice.unknown_customer || {}) as Record<string, string>
return {
items: invoice.items.map(item => ({
invoice_item_id: item.id,
@@ -253,36 +260,41 @@ export async function buildCorrectionPayload(
amount: Number(payment.amount),
payment_method: payment.payment_method,
paid_at: payment.paid_at,
card_number: payment.terminal_info ? payment.terminal_info.stan : undefined,
tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined,
terminal_info: {
card_number: payment.terminal_info ? payment.terminal_info.stan : undefined,
tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined,
},
})),
total_amount: Number(invoice.total_amount),
last_tax_id: invoice.reference_invoice!.tax_id!,
invoice_number: invoice.invoice_number,
invoice_id: invoice.id,
id: invoice.id,
economic_code: invoice.pos.complex.business_activity.economic_code,
fiscal_id: invoice.pos.complex.business_activity.fiscal_id,
tsp_token: invoice.pos.complex.business_activity.partner_token,
type: TspProviderRequestType.CORRECTION,
token: invoice.pos.complex.business_activity.partner_token,
tsp_provider: partner.tsp_provider!,
invoice_template: invoice.pos.complex.business_activity.guild.invoice_template,
template: invoice.pos.complex.business_activity.guild.invoice_template,
invoice_date: new Date(),
settlement_type: invoice.settlement_type,
customer_type: invoice.customer?.type
? TspProviderCustomerType.KNOWN
: TspProviderCustomerType.UNKNOWN,
customer: invoice.customer?.type
? {
type: invoice.customer.type,
legal_info: invoice.customer.legal ?? undefined,
individual_info: invoice.customer.individual ?? undefined,
}
: undefined,
customer:
invoice.customer && invoice.customer.type !== 'UNKNOWN'
? {
type: invoice.customer.type,
legal_info: invoice.customer.legal ?? undefined,
individual_info: invoice.customer.individual ?? undefined,
}
: {
type: 'UNKNOWN',
unknown_info: {
name: unknown_customer?.name || '',
economic_code: unknown_customer?.economic_code || '',
},
},
}
}
export async function buildPayload(
export async function buildOriginalPayload(
prisma: PrismaService,
invoiceId: string,
posId: string,
@@ -311,6 +323,7 @@ export async function buildPayload(
sku_vat: true,
good_id: true,
service_id: true,
discount: true,
payload: true,
good_snapshot: true,
},
@@ -357,6 +370,7 @@ export async function buildPayload(
},
},
},
unknown_customer: true,
customer: {
select: {
type: true,
@@ -396,38 +410,48 @@ export async function buildPayload(
throw new NotFoundException('فاکتور مورد نظر یافت نشد.')
}
const { partner } = (invoice.pos.complex.business_activity.consumer.legal ||
invoice.pos.complex.business_activity.consumer.individual)!
const { pos, id, invoice_number, invoice_date, total_amount, settlement_type } = invoice
const { business_activity: ba } = pos.complex
const unknown_customer = (invoice.unknown_customer || {}) as Record<string, string>
const { partner } = (ba.consumer.legal || ba.consumer.individual)!
return {
invoice_id: invoice.id,
invoice_number: invoice.invoice_number,
invoice_date: invoice.invoice_date,
total_amount: Number(invoice.total_amount),
economic_code: invoice.pos.complex.business_activity.economic_code,
fiscal_id: invoice.pos.complex.business_activity.fiscal_id,
invoice_template: invoice.pos.complex.business_activity.guild.invoice_template,
tsp_token: invoice.pos.complex.business_activity.partner_token,
settlement_type: invoice.settlement_type,
id,
invoice_number,
invoice_date,
settlement_type,
total_amount: Number(total_amount),
economic_code: ba.economic_code,
fiscal_id: ba.fiscal_id,
template: ba.guild.invoice_template,
token: ba.partner_token,
tsp_provider: partner.tsp_provider!,
payments: invoice.payments.map(payment => ({
amount: Number(payment.amount),
payment_method: payment.payment_method,
paid_at: payment.paid_at,
card_number: payment.terminal_info ? payment.terminal_info.stan : undefined,
tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined,
terminal_info: {
card_number: payment.terminal_info ? payment.terminal_info.stan : undefined,
tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined,
},
})),
type: TspProviderRequestType.ORIGINAL,
tsp_provider: partner.tsp_provider!,
customer_type: invoice.customer?.type
? TspProviderCustomerType.KNOWN
: TspProviderCustomerType.UNKNOWN,
customer: invoice.customer?.type
? {
type: invoice.customer.type,
legal_info: invoice.customer.legal ?? undefined,
individual_info: invoice.customer.individual ?? undefined,
}
: undefined,
customer:
invoice.customer && invoice.customer.type !== 'UNKNOWN'
? {
type: invoice.customer.type,
legal_info: invoice.customer.legal ?? undefined,
individual_info: invoice.customer.individual ?? undefined,
}
: {
type: 'UNKNOWN',
unknown_info: {
name: unknown_customer?.name || '',
economic_code: unknown_customer?.economic_code || '',
},
},
items: invoice.items.map(item => ({
invoice_item_id: item.id,
quantity: Number(item.quantity),
@@ -449,84 +473,63 @@ export async function trySend(
tspSwitchService: {
send(
payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto | null>
): Promise<TspProviderOriginalSendItemResultDto>
},
payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto | null> {
): Promise<TspProviderOriginalSendItemResultDto> {
return (await tspSwitchService.send(payload)) || null
}
export async function onResult(
prisma: PrismaService,
result: any,
result: TspProviderOriginalSendItemResultDto,
attempt_id: string,
): Promise<TspProviderActionResponseDto> {
let attemptUpdatedData: SaleInvoiceTspAttemptsUpdateInput = {}
const resultMessage = result.message
if (result) {
if (result.hasError) {
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({
where: {
id: attempt_id,
attemptUpdatedData = {
provider_request_payload: JSON.parse(
JSON.stringify(result.provider_request_payload),
),
provider_response: JSON.parse(JSON.stringify(result.provider_response)),
status: result.status,
received_at: result.received_at || new Date().toISOString(),
message: resultMessage
? resultMessage
: result.hasError
? 'وجود مشکل در ارسال به سامانه مالیاتی'
: 'فاکتور با موفقیت به سامانه مالیاتی ارسال شد.',
invoice: {
update: {
tax_id: result.tax_id,
},
data: {
provider_request_payload: result.provider_request_payload,
provider_response_payload: JSON.parse(JSON.stringify(result)),
status: result.status,
sent_at: result.sent_at || new Date().toISOString(),
received_at: result.received_at || new Date().toISOString(),
message: result.message?.toString() || 'وجود مشکل در ارسال به سامانه مالیاتی',
},
select: {
status: true,
invoice: true,
message: true,
},
})
return {
invoice: updatedAttempt.invoice,
status: updatedAttempt.status,
message: updatedAttempt.message,
}
},
}
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({
where: {
id: attempt_id,
},
data: {
provider_request_payload: result.provider_request_payload,
provider_response_payload: JSON.parse(JSON.stringify(result)),
status: result.status,
sent_at: result.sent_at,
received_at: result.received_at,
message:
result.message?.toString() || 'فاکتور با موفقیت به سامانه مالیاتی ارسال شد.',
},
select: {
status: true,
invoice: true,
message: true,
},
})
return {
invoice: updatedAttempt.invoice,
status: updatedAttempt.status,
message: updatedAttempt.message,
if (result.hasError) {
;((attemptUpdatedData.error_message = result.error_message),
(attemptUpdatedData.validation_errors = JSON.parse(
JSON.stringify(result.validation_errors),
)),
(attemptUpdatedData.fiscal_warnings = JSON.parse(
JSON.stringify(result.fiscal_warnings),
)))
}
} else {
attemptUpdatedData = {
status: TspProviderResponseStatus.SEND_FAILURE,
message:
'متاسفانه امکان ارسال فاکتور به سیستم مالیاتی در حال حاضر وجود ندارد. لطفا بعدا تلاش کنید.',
received_at: new Date().toISOString(),
}
}
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({
where: {
id: attempt_id,
},
data: {
provider_response_payload: {},
status: TspProviderResponseStatus.FAILURE,
message:
'متاسفانه امکان ارسال فاکتور به سیستم مالیاتی در حال حاضر وجود ندارد. لطفا بعدا تلاش کنید.',
received_at: new Date().toISOString(),
},
data: attemptUpdatedData,
select: {
status: true,
invoice: true,