274 lines
9.1 KiB
TypeScript
274 lines
9.1 KiB
TypeScript
import {
|
|
createEnsureSuccessResponseInterceptor,
|
|
createHeaderRequestInterceptor,
|
|
FetchRequestInterceptor,
|
|
} from '@/common/interceptors/fetch-request.interceptor'
|
|
import { HttpClientUtil } from '@/common/utils/http-client.util'
|
|
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
|
|
import { Injectable, Logger } from '@nestjs/common'
|
|
import {
|
|
TspProviderCorrectionSendPayloadDto,
|
|
TspProviderCorrectionSendResponseDto,
|
|
TspProviderGetResponseDto,
|
|
TspProviderOriginalResponseDto,
|
|
TspProviderOriginalSendPayloadDto,
|
|
TspProviderRevokePayloadDto,
|
|
TspProviderRevokeResponseDto,
|
|
} from '../../dto'
|
|
import {
|
|
IProviderSwitchAdapter,
|
|
TspProviderBulkSendResultDto,
|
|
} from '../../dto/provider-switch.dto'
|
|
import {
|
|
NamaProviderGetResponseDto,
|
|
NamaProviderOriginalResponseDto,
|
|
NamaProviderResponseStatus,
|
|
NamaProviderRevokeRequestDto,
|
|
NamaProviderRevokeResponseDto,
|
|
} from './dto'
|
|
import { NamaProviderUtils } from './nama-provider.util'
|
|
|
|
@Injectable()
|
|
export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
|
|
readonly code = 'NAMA'
|
|
private readonly logger = new Logger(NamaProviderSwitchAdapter.name)
|
|
private readonly sandboxBaseUrl =
|
|
process.env.NAMA_PROVIDER_SANDBOX_URL || 'https://external-api-dev.namatsp.ir'
|
|
private readonly productionBaseUrl =
|
|
process.env.NAMA_PROVIDER_PRODUCTION_URL || 'https://api.nama.ir'
|
|
|
|
private readonly sendPath = '/api/v1/invoices/single-send'
|
|
private readonly sendBulkPath = '/api/v1/invoices'
|
|
private readonly checkBulkStatus = '/api/v1/invoices/check-by-uuids'
|
|
private readonly getPath = '/api/v1/invoices'
|
|
constructor(
|
|
private readonly httpClient: HttpClientUtil,
|
|
private readonly namaProviderUtils: NamaProviderUtils,
|
|
) {}
|
|
|
|
private get baseUrl() {
|
|
return this.sandboxBaseUrl
|
|
// return process.env.NODE_ENV === 'production'
|
|
// ? this.productionBaseUrl
|
|
// : this.sandboxBaseUrl
|
|
}
|
|
|
|
private buildSendUrl() {
|
|
return `${this.baseUrl}${this.sendPath}`
|
|
}
|
|
|
|
private buildGetUrl(invoiceId: string) {
|
|
return `${this.baseUrl}${this.getPath}/${invoiceId}`
|
|
}
|
|
|
|
private createRequestInterceptors(token: string): FetchRequestInterceptor[] {
|
|
return [
|
|
createHeaderRequestInterceptor({
|
|
'Content-Type': 'application/json',
|
|
Authorization: token,
|
|
}),
|
|
createEnsureSuccessResponseInterceptor(),
|
|
{
|
|
onError: (context, error) => {
|
|
this.logger.error(`NAMA request failed: ${context.url}`, error)
|
|
return Promise.reject(error)
|
|
},
|
|
},
|
|
]
|
|
}
|
|
|
|
async originalSend(
|
|
payload: TspProviderOriginalSendPayloadDto,
|
|
): Promise<TspProviderOriginalResponseDto> {
|
|
const mappedRequest = this.namaProviderUtils.mapToNamaOriginalRequestDto(payload)
|
|
try {
|
|
const response = await this.httpClient.request(
|
|
this.buildSendUrl(),
|
|
{
|
|
method: 'POST',
|
|
body: JSON.stringify(mappedRequest),
|
|
},
|
|
this.createRequestInterceptors(payload.token),
|
|
)
|
|
const providerResponse: NamaProviderOriginalResponseDto = await response.json()
|
|
|
|
const result: TspProviderOriginalResponseDto = {
|
|
invoice_id: payload.id,
|
|
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
|
|
hasError: !response.ok,
|
|
message: providerResponse.message,
|
|
received_at: new Date().toISOString(),
|
|
provider_response: JSON.parse(JSON.stringify(providerResponse)),
|
|
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,
|
|
),
|
|
}
|
|
|
|
return result
|
|
} catch (err) {
|
|
const failure: TspProviderOriginalResponseDto = {
|
|
invoice_id: payload.id,
|
|
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
|
|
hasError: true,
|
|
message: (err as Error).message,
|
|
received_at: new Date().toISOString(),
|
|
status: TspProviderResponseStatus.SEND_FAILURE,
|
|
}
|
|
return failure
|
|
}
|
|
}
|
|
|
|
async correctionSend(
|
|
payload: TspProviderCorrectionSendPayloadDto,
|
|
): Promise<TspProviderCorrectionSendResponseDto> {
|
|
const mappedRequest = this.namaProviderUtils.mapToNamaOriginalRequestDto(payload)
|
|
|
|
try {
|
|
const response = await this.httpClient.request(
|
|
this.buildSendUrl(),
|
|
{
|
|
method: 'POST',
|
|
body: JSON.stringify(mappedRequest),
|
|
},
|
|
this.createRequestInterceptors(payload.token),
|
|
)
|
|
const providerResponse: NamaProviderOriginalResponseDto = await response.json()
|
|
this.logger.debug('NAMA provider response', providerResponse)
|
|
|
|
const result: TspProviderOriginalResponseDto = {
|
|
invoice_id: payload.id,
|
|
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
|
|
hasError: !response.ok,
|
|
message: providerResponse.message,
|
|
provider_response: JSON.parse(JSON.stringify(providerResponse)),
|
|
received_at: new Date().toISOString(),
|
|
tax_id: providerResponse.tax_id,
|
|
status: this.namaProviderUtils.mapResponseStatus(
|
|
providerResponse.status as NamaProviderResponseStatus,
|
|
),
|
|
}
|
|
|
|
return result
|
|
} catch (err) {
|
|
this.logger.error('NAMA send failed', err)
|
|
const failure: TspProviderOriginalResponseDto = {
|
|
invoice_id: payload.id,
|
|
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
|
|
hasError: true,
|
|
message: (err as Error).message,
|
|
received_at: new Date().toISOString(),
|
|
tax_id: null,
|
|
status: TspProviderResponseStatus.NOT_SEND,
|
|
}
|
|
return failure
|
|
}
|
|
}
|
|
|
|
async sendBulk(
|
|
payloads: TspProviderOriginalSendPayloadDto[],
|
|
): Promise<TspProviderBulkSendResultDto[]> {
|
|
const result: TspProviderBulkSendResultDto[] = []
|
|
for (const payload of payloads) {
|
|
const itemResults = await this.originalSend(payload)
|
|
result.push({
|
|
invoice_id: payload.id,
|
|
items: [itemResults],
|
|
})
|
|
}
|
|
return result
|
|
}
|
|
|
|
async get(invoiceId: string, token: string): Promise<TspProviderGetResponseDto> {
|
|
try {
|
|
const response = await this.httpClient.request(
|
|
this.buildGetUrl(invoiceId),
|
|
{
|
|
method: 'GET',
|
|
},
|
|
this.createRequestInterceptors(token),
|
|
)
|
|
const providerResponse: NamaProviderGetResponseDto = await response.json()
|
|
this.logger.debug('NAMA provider response', providerResponse)
|
|
|
|
const result: TspProviderGetResponseDto = {
|
|
hasError: !response.ok,
|
|
provider_response: JSON.parse(JSON.stringify(providerResponse)),
|
|
message: providerResponse.message,
|
|
received_at: new Date().toISOString(),
|
|
error_message: providerResponse.error_message,
|
|
fiscal_warnings: providerResponse.tax_api_response,
|
|
validation_errors: providerResponse.validation_error,
|
|
|
|
status: this.namaProviderUtils.mapResponseStatus(
|
|
providerResponse.status as NamaProviderResponseStatus,
|
|
),
|
|
}
|
|
|
|
return result
|
|
} catch (err) {
|
|
this.logger.error('NAMA send failed', err)
|
|
const failure: TspProviderGetResponseDto = {
|
|
hasError: true,
|
|
message: (err as Error).message,
|
|
received_at: new Date().toISOString(),
|
|
}
|
|
return failure
|
|
}
|
|
}
|
|
|
|
async revoke(
|
|
payload: TspProviderRevokePayloadDto,
|
|
): Promise<TspProviderRevokeResponseDto> {
|
|
const mappedRequest: NamaProviderRevokeRequestDto =
|
|
this.namaProviderUtils.mapToNamaRevokeRequestDto(payload)
|
|
|
|
this.logger.debug('NAMA provider response', mappedRequest)
|
|
|
|
try {
|
|
const response = await this.httpClient.request(
|
|
this.buildSendUrl(),
|
|
{
|
|
method: 'POST',
|
|
body: JSON.stringify(mappedRequest),
|
|
},
|
|
this.createRequestInterceptors(payload.tsp_token),
|
|
)
|
|
const providerResponse: NamaProviderRevokeResponseDto = await response.json()
|
|
this.logger.debug('NAMA provider response', providerResponse)
|
|
|
|
const result: TspProviderRevokeResponseDto = {
|
|
invoice_id: payload.invoice_id,
|
|
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
|
|
hasError: !response.ok,
|
|
message: providerResponse.message,
|
|
sent_at: new Date().toISOString(),
|
|
provider_response_payload: providerResponse,
|
|
received_at: new Date().toISOString(),
|
|
tax_id: providerResponse.tax_id,
|
|
status: this.namaProviderUtils.mapResponseStatus(
|
|
providerResponse.status as NamaProviderResponseStatus,
|
|
),
|
|
}
|
|
|
|
return result
|
|
} catch (err) {
|
|
this.logger.error('NAMA Revoke failed', err)
|
|
const failure: TspProviderRevokeResponseDto = {
|
|
invoice_id: payload.invoice_id,
|
|
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
|
|
hasError: true,
|
|
message: (err as Error).message,
|
|
sent_at: new Date().toISOString(),
|
|
received_at: new Date().toISOString(),
|
|
tax_id: '',
|
|
status: TspProviderResponseStatus.FAILURE,
|
|
}
|
|
return failure
|
|
}
|
|
}
|
|
}
|