From cd3492d62591c1c2cc477c510c3f3df1bb4903bd Mon Sep 17 00:00:00 2001 From: ahasani194 Date: Wed, 27 May 2026 22:44:01 +0330 Subject: [PATCH] update get status of tsp provider --- src/modules/tspProviders/dto/common.dto.ts | 46 +++++++++++++++++- src/modules/tspProviders/dto/get.dto.ts | 44 +++-------------- src/modules/tspProviders/dto/original.dto.ts | 48 +++---------------- .../tspProviders/dto/provider-switch.dto.ts | 14 +++--- .../sales-invoice-tsp-switch.service.ts | 8 ++-- .../tspProviders/sales-invoice-tsp.service.ts | 28 +---------- .../tspProviders/switch/nama/dto/get.dto.ts | 12 ++--- .../switch/nama/nama-provider.adapter.ts | 47 ++++++++---------- .../utils/sales-invoice-tsp.utils.ts | 33 +++++++------ 9 files changed, 116 insertions(+), 164 deletions(-) diff --git a/src/modules/tspProviders/dto/common.dto.ts b/src/modules/tspProviders/dto/common.dto.ts index 79e1cb5..259dec6 100644 --- a/src/modules/tspProviders/dto/common.dto.ts +++ b/src/modules/tspProviders/dto/common.dto.ts @@ -1,7 +1,12 @@ -import { CustomerType, PaymentMethodType } from '@/generated/prisma/enums' +import { + CustomerType, + PaymentMethodType, + TspProviderResponseStatus, +} from '@/generated/prisma/enums' import { ApiProperty } from '@nestjs/swagger' import { Type } from 'class-transformer' import { + IsBoolean, IsDateString, IsEnum, IsNumber, @@ -127,3 +132,42 @@ export class goldTypePayload { @IsString() commission: string } + +export class ProviderCommonResponse { + @ApiProperty({ enum: TspProviderResponseStatus }) + @IsEnum(TspProviderResponseStatus) + status: TspProviderResponseStatus + + @ApiProperty({ required: false, nullable: true, type: Object }) + @IsOptional() + @IsObject() + provider_response?: Object + + @ApiProperty({ required: true }) + @IsBoolean() + hasError: boolean + + @ApiProperty({ required: false, nullable: true }) + @IsOptional() + @IsString() + message?: string | null + + @ApiProperty({ required: false, nullable: true }) + @IsOptional() + @IsString() + error_message?: string + + @ApiProperty({ required: false, nullable: true, type: Object }) + @IsOptional() + @IsObject() + fiscal_warnings?: Object + + @ApiProperty({ required: false, nullable: true, type: Object }) + @IsOptional() + @IsObject() + validation_errors?: Object + + @ApiProperty({ required: true }) + @IsDateString() + received_at: string +} diff --git a/src/modules/tspProviders/dto/get.dto.ts b/src/modules/tspProviders/dto/get.dto.ts index 7c85b64..6b5cdd3 100644 --- a/src/modules/tspProviders/dto/get.dto.ts +++ b/src/modules/tspProviders/dto/get.dto.ts @@ -1,42 +1,12 @@ import { TspProviderResponseStatus } from '@/generated/prisma/enums' -import { ApiProperty } from '@nestjs/swagger' -import { - IsBoolean, - IsDateString, - IsEnum, - IsObject, - IsOptional, - IsString, -} from 'class-validator' - -export class TspProviderGetResultDto { - @ApiProperty() - @IsString() - tax_id: string +import { ApiProperty, OmitType } from '@nestjs/swagger' +import { IsEnum } from 'class-validator' +import { ProviderCommonResponse } from './common.dto' +export class TspProviderGetResponseDto extends OmitType(ProviderCommonResponse, [ + 'status', +]) { @ApiProperty({ enum: TspProviderResponseStatus }) @IsEnum(TspProviderResponseStatus) - status: TspProviderResponseStatus - - @ApiProperty({ required: true }) - @IsBoolean() - hasError: boolean - - @ApiProperty({ required: false, nullable: true }) - @IsOptional() - @IsString() - message?: string | null - - @ApiProperty({ required: false, nullable: true, type: Object }) - @IsOptional() - @IsObject() - provider_response_payload?: Object - - @ApiProperty({ required: true }) - @IsDateString() - sent_at: string - - @ApiProperty({ required: true }) - @IsDateString() - received_at: string + status?: TspProviderResponseStatus } diff --git a/src/modules/tspProviders/dto/original.dto.ts b/src/modules/tspProviders/dto/original.dto.ts index 62b3641..2a07967 100644 --- a/src/modules/tspProviders/dto/original.dto.ts +++ b/src/modules/tspProviders/dto/original.dto.ts @@ -1,14 +1,12 @@ import { InvoiceSettlementType, InvoiceTemplateType, - TspProviderResponseStatus, TspProviderType, } from '@/generated/prisma/enums' import { ApiProperty } from '@nestjs/swagger' import { Type } from 'class-transformer' import { IsArray, - IsBoolean, IsDateString, IsEnum, IsNumber, @@ -17,7 +15,12 @@ import { IsString, ValidateNested, } from 'class-validator' -import { CustomerInfoDto, goldTypePayload, PaymentInfoDto } from './common.dto' +import { + CustomerInfoDto, + goldTypePayload, + PaymentInfoDto, + ProviderCommonResponse, +} from './common.dto' export class TspProviderOriginalItemPayloadDto { @ApiProperty({ required: true }) @@ -133,15 +136,11 @@ export class TspProviderOriginalSendPayloadDto { payments: PaymentInfoDto[] } -export class TspProviderOriginalSendItemResultDto { +export class TspProviderOriginalResponseDto extends ProviderCommonResponse { @ApiProperty() @IsString() invoice_id: string - @ApiProperty({ enum: TspProviderResponseStatus }) - @IsEnum(TspProviderResponseStatus) - status: TspProviderResponseStatus - @ApiProperty({ required: false, nullable: true }) @IsOptional() @IsString() @@ -157,37 +156,4 @@ export class TspProviderOriginalSendItemResultDto { @ValidateNested({ each: true }) @Type(() => TspProviderOriginalSendPayloadDto) provider_request_payload: TspProviderOriginalSendPayloadDto - - @ApiProperty({ required: false, nullable: true, type: Object }) - @IsOptional() - @IsObject() - provider_response?: Object - - @ApiProperty({ required: true }) - @IsBoolean() - hasError: boolean - - @ApiProperty({ required: false, nullable: true }) - @IsOptional() - @IsString() - message?: string | null - - @ApiProperty({ required: false, nullable: true }) - @IsOptional() - @IsString() - error_message?: string - - @ApiProperty({ required: false, nullable: true, type: Object }) - @IsOptional() - @IsObject() - fiscal_warnings?: Object - - @ApiProperty({ required: false, nullable: true, type: Object }) - @IsOptional() - @IsObject() - validation_errors?: Object - - @ApiProperty({ required: true }) - @IsDateString() - received_at: string } diff --git a/src/modules/tspProviders/dto/provider-switch.dto.ts b/src/modules/tspProviders/dto/provider-switch.dto.ts index 8ccd36b..5524678 100644 --- a/src/modules/tspProviders/dto/provider-switch.dto.ts +++ b/src/modules/tspProviders/dto/provider-switch.dto.ts @@ -6,9 +6,9 @@ import { TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendResponseDto, } from './correction.dto' -import { TspProviderGetResultDto } from './get.dto' +import { TspProviderGetResponseDto } from './get.dto' import { - TspProviderOriginalSendItemResultDto, + TspProviderOriginalResponseDto, TspProviderOriginalSendPayloadDto, } from './original.dto' import { TspProviderRevokePayloadDto, TspProviderRevokeResponseDto } from './revoke.dto' @@ -18,11 +18,11 @@ export class TspProviderBulkSendResultDto { @IsString() invoice_id: string - @ApiProperty({ type: [TspProviderOriginalSendItemResultDto] }) + @ApiProperty({ type: [TspProviderOriginalResponseDto] }) @IsArray() @ValidateNested({ each: true }) - @Type(() => TspProviderOriginalSendItemResultDto) - items: TspProviderOriginalSendItemResultDto[] + @Type(() => TspProviderOriginalResponseDto) + items: TspProviderOriginalResponseDto[] } export class TspProviderActionResponseDto { @@ -40,13 +40,13 @@ export interface IProviderSwitchAdapter { readonly code: string originalSend( payload: TspProviderOriginalSendPayloadDto, - ): Promise + ): Promise sendBulk( payloads: TspProviderOriginalSendPayloadDto[], ): Promise correctionSend( payload: TspProviderCorrectionSendPayloadDto, ): Promise - get(invoiceId: string, tsp_token: string): Promise + get(invoiceId: string, tsp_token: string): Promise revoke(payload: TspProviderRevokePayloadDto): Promise } diff --git a/src/modules/tspProviders/sales-invoice-tsp-switch.service.ts b/src/modules/tspProviders/sales-invoice-tsp-switch.service.ts index 7186eab..de92d74 100644 --- a/src/modules/tspProviders/sales-invoice-tsp-switch.service.ts +++ b/src/modules/tspProviders/sales-invoice-tsp-switch.service.ts @@ -3,8 +3,8 @@ import { TspProviderBulkSendResultDto, TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendResponseDto, - TspProviderGetResultDto, - TspProviderOriginalSendItemResultDto, + TspProviderGetResponseDto, + TspProviderOriginalResponseDto, TspProviderOriginalSendPayloadDto, TspProviderRevokePayloadDto, TspProviderRevokeResponseDto, @@ -34,7 +34,7 @@ export class SalesInvoiceTspSwitchService { async send( payload: TspProviderOriginalSendPayloadDto, - ): Promise { + ): Promise { const adapter = this.resolveSwitch(payload.tsp_provider) return adapter.originalSend(payload) @@ -74,7 +74,7 @@ export class SalesInvoiceTspSwitchService { providerCode: string, invoiceId: string, tspToken: string, - ): Promise { + ): Promise { const adapter = this.resolveSwitch(providerCode) return await adapter.get(invoiceId, tspToken) } diff --git a/src/modules/tspProviders/sales-invoice-tsp.service.ts b/src/modules/tspProviders/sales-invoice-tsp.service.ts index aba113d..9317b67 100644 --- a/src/modules/tspProviders/sales-invoice-tsp.service.ts +++ b/src/modules/tspProviders/sales-invoice-tsp.service.ts @@ -53,7 +53,7 @@ export class SalesInvoiceTspService { }, }) - const result = await trySend(this.tspSwitchService, payload) + const result = await this.tspSwitchService.send(payload) return await onResult(this.prisma, result, attempt.id) } @@ -152,31 +152,7 @@ export class SalesInvoiceTspService { business_activity.partner_token, ) - if (!result) { - throw new NotFoundException('نتیجه ارسال فاکتور یافت نشد.') - } - - const updatedAttempt = await this.prisma.saleInvoiceTspAttempts.update({ - where: { - id: attempt.id, - }, - data: { - provider_response: JSON.parse(JSON.stringify(result)), - status: result.status, - received_at: result.received_at, - }, - select: { - status: true, - invoice: true, - message: true, - }, - }) - - return { - invoice: updatedAttempt.invoice, - status: updatedAttempt.status, - message: updatedAttempt.message, - } + return await onResult(this.prisma, result, attempt.id) } async correctionSend( diff --git a/src/modules/tspProviders/switch/nama/dto/get.dto.ts b/src/modules/tspProviders/switch/nama/dto/get.dto.ts index c825781..5b6c06f 100644 --- a/src/modules/tspProviders/switch/nama/dto/get.dto.ts +++ b/src/modules/tspProviders/switch/nama/dto/get.dto.ts @@ -1,11 +1,9 @@ -import { ApiProperty, OmitType } from '@nestjs/swagger' -import { IsString } from 'class-validator' +import { OmitType } from '@nestjs/swagger' import { NamaProviderResponseDto } from './common.dto' export class NamaProviderGetResponseDto extends OmitType(NamaProviderResponseDto, [ 'tax_id', -]) { - @ApiProperty() - @IsString() - tax_id: string -} + 'inno', + 'reference_number', + 'uuid', +]) {} diff --git a/src/modules/tspProviders/switch/nama/nama-provider.adapter.ts b/src/modules/tspProviders/switch/nama/nama-provider.adapter.ts index b1476bb..1991f06 100644 --- a/src/modules/tspProviders/switch/nama/nama-provider.adapter.ts +++ b/src/modules/tspProviders/switch/nama/nama-provider.adapter.ts @@ -9,8 +9,8 @@ import { Injectable, Logger } from '@nestjs/common' import { TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendResponseDto, - TspProviderGetResultDto, - TspProviderOriginalSendItemResultDto, + TspProviderGetResponseDto, + TspProviderOriginalResponseDto, TspProviderOriginalSendPayloadDto, TspProviderRevokePayloadDto, TspProviderRevokeResponseDto, @@ -79,7 +79,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { async originalSend( payload: TspProviderOriginalSendPayloadDto, - ): Promise { + ): Promise { const mappedRequest = this.namaProviderUtils.mapToNamaOriginalRequestDto(payload) try { const response = await this.httpClient.request( @@ -91,10 +91,8 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { this.createRequestInterceptors(payload.token), ) const providerResponse: NamaProviderOriginalResponseDto = await response.json() - this.logger.debug('NAMA provider response', response) - this.logger.debug('NAMA provider providerResponse', providerResponse) - const result: TspProviderOriginalSendItemResultDto = { + const result: TspProviderOriginalResponseDto = { invoice_id: payload.id, provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), hasError: !response.ok, @@ -112,8 +110,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { return result } catch (err) { - this.logger.error('NAMA send failed', err) - const failure: TspProviderOriginalSendItemResultDto = { + const failure: TspProviderOriginalResponseDto = { invoice_id: payload.id, provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), hasError: true, @@ -142,7 +139,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { const providerResponse: NamaProviderOriginalResponseDto = await response.json() this.logger.debug('NAMA provider response', providerResponse) - const result: TspProviderOriginalSendItemResultDto = { + const result: TspProviderOriginalResponseDto = { invoice_id: payload.id, provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), hasError: !response.ok, @@ -158,7 +155,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { return result } catch (err) { this.logger.error('NAMA send failed', err) - const failure: TspProviderOriginalSendItemResultDto = { + const failure: TspProviderOriginalResponseDto = { invoice_id: payload.id, provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), hasError: true, @@ -185,25 +182,27 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { return result } - async get(invoiceId: string, tsp_token: string): Promise { + async get(invoiceId: string, token: string): Promise { try { const response = await this.httpClient.request( this.buildGetUrl(invoiceId), { method: 'GET', }, - this.createRequestInterceptors(tsp_token), + this.createRequestInterceptors(token), ) const providerResponse: NamaProviderGetResponseDto = await response.json() this.logger.debug('NAMA provider response', providerResponse) - const result: TspProviderGetResultDto = { + const result: TspProviderGetResponseDto = { hasError: !response.ok, + provider_response: JSON.parse(JSON.stringify(providerResponse)), message: providerResponse.message, - provider_response_payload: providerResponse, - sent_at: new Date().toISOString(), received_at: new Date().toISOString(), - tax_id: providerResponse.tax_id, + error_message: providerResponse.error_message, + fiscal_warnings: providerResponse.tax_api_response, + validation_errors: providerResponse.validation_error, + status: this.namaProviderUtils.mapResponseStatus( providerResponse.status as NamaProviderResponseStatus, ), @@ -212,16 +211,12 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter { return result } catch (err) { this.logger.error('NAMA send failed', err) - // const failure: TspProviderGetResultDto = { - // invoice_id: invoiceId, - // hasError: true, - // message: (err as Error).message, - // received_at: new Date().toISOString(), - // tax_id: null, - // status: TspProviderResponseStatus.NOT_SEND, - // } - // return failure - throw err + const failure: TspProviderGetResponseDto = { + hasError: true, + message: (err as Error).message, + received_at: new Date().toISOString(), + } + return failure } } diff --git a/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts b/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts index 3ecc660..963f8fc 100644 --- a/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts +++ b/src/modules/tspProviders/utils/sales-invoice-tsp.utils.ts @@ -8,7 +8,8 @@ import { } from 'generated/prisma/client' import { TspProviderCorrectionSendPayloadDto, - TspProviderOriginalSendItemResultDto, + TspProviderGetResponseDto, + TspProviderOriginalResponseDto, TspProviderOriginalSendPayloadDto, TspProviderRevokePayloadDto, } from '../dto' @@ -473,27 +474,29 @@ export async function trySend( tspSwitchService: { send( payload: TspProviderOriginalSendPayloadDto, - ): Promise + ): Promise }, payload: TspProviderOriginalSendPayloadDto, -): Promise { +): Promise { return (await tspSwitchService.send(payload)) || null } export async function onResult( prisma: PrismaService, - result: TspProviderOriginalSendItemResultDto, + result: TspProviderOriginalResponseDto | TspProviderGetResponseDto, attempt_id: string, ): Promise { let attemptUpdatedData: SaleInvoiceTspAttemptsUpdateInput = {} + console.log('attempt', result, attempt_id) + const resultMessage = result.message if (result) { attemptUpdatedData = { - provider_request_payload: JSON.parse( - JSON.stringify(result.provider_request_payload), - ), + provider_request_payload: result['provider_request_payload'] + ? JSON.parse(JSON.stringify(result['provider_request_payload'])) + : undefined, provider_response: JSON.parse(JSON.stringify(result.provider_response)), status: result.status, received_at: result.received_at || new Date().toISOString(), @@ -504,18 +507,18 @@ export async function onResult( : 'فاکتور با موفقیت به سامانه مالیاتی ارسال شد.', invoice: { update: { - tax_id: result.tax_id, + tax_id: result['tax_id'] ? result['tax_id'] : undefined, }, }, } 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), - ))) + 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 = {