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
@@ -0,0 +1,26 @@
-- 1. Add the new columns
ALTER TABLE `sale_invoice_tsp_attempts`
ADD COLUMN `error_message` TEXT NULL,
ADD COLUMN `fiscal_warnings` JSON NULL,
ADD COLUMN `provider_response` JSON NULL,
ADD COLUMN `validation_errors` JSON NULL;
-- 2. Copy data from the old column to the new JSON column
-- Note: We use a check to ensure we don't try to move invalid data
UPDATE `sale_invoice_tsp_attempts`
SET `provider_response` = CAST(`provider_response_payload` AS JSON)
WHERE `provider_response_payload` IS NOT NULL AND JSON_VALID(`provider_response_payload`);
-- 3. SANITIZE 'provider_request_payload' before converting to JSON
-- This replaces empty strings or invalid JSON with a default empty object '{}'
UPDATE `sale_invoice_tsp_attempts`
SET `provider_request_payload` = '{}'
WHERE `provider_request_payload` IS NULL
OR `provider_request_payload` = ''
OR JSON_VALID(`provider_request_payload`) = 0;
-- 4. Perform the final modifications and drop the old column
ALTER TABLE `sale_invoice_tsp_attempts`
DROP COLUMN `provider_response_payload`,
MODIFY `status` ENUM('NOT_SEND', 'QUEUED', 'FISCAL_QUEUED', 'SEND_FAILURE', 'SUCCESS', 'FAILURE') NOT NULL,
MODIFY `provider_request_payload` JSON NOT NULL;
+4 -2
View File
@@ -169,10 +169,12 @@ enum TspProviderType {
} }
enum TspProviderResponseStatus { enum TspProviderResponseStatus {
SUCCESS
FAILURE
NOT_SEND NOT_SEND
QUEUED QUEUED
FISCAL_QUEUED
SEND_FAILURE
SUCCESS
FAILURE
} }
enum TspProviderRequestType { enum TspProviderRequestType {
+5 -2
View File
@@ -74,9 +74,12 @@ model SaleInvoiceTspAttempts {
status TspProviderResponseStatus status TspProviderResponseStatus
raw_request_payload Json raw_request_payload Json
provider_request_payload Json? provider_request_payload Json
provider_response_payload Json? provider_response Json?
message String @db.Text message String @db.Text
error_message String? @db.Text
validation_errors Json?
fiscal_warnings Json?
sent_at DateTime? @db.Timestamp(0) sent_at DateTime? @db.Timestamp(0)
received_at DateTime? @db.Timestamp(0) received_at DateTime? @db.Timestamp(0)
+6 -4
View File
@@ -137,10 +137,12 @@ export default {
SUN: 'سان', SUN: 'سان',
}, },
TspProviderResponseStatus: { TspProviderResponseStatus: {
SUCCESS: 'موفق', [TspProviderResponseStatus.SUCCESS]: 'موفق',
FAILURE: 'ناموفق', [TspProviderResponseStatus.FAILURE]: 'ناموفق',
NOT_SEND: 'ارسال نشده', [TspProviderResponseStatus.NOT_SEND]: 'ارسال نشده',
[TspProviderResponseStatus.QUEUED]: 'در صف ارسال', [TspProviderResponseStatus.QUEUED]: 'در صف ارسال به معتمد',
[TspProviderResponseStatus.FISCAL_QUEUED]: 'در صف ارسال به مالیات',
[TspProviderResponseStatus.SEND_FAILURE]: 'خطا در ارسال',
}, },
TspProviderRequestType: { TspProviderRequestType: {
ORIGINAL: 'اصلی', ORIGINAL: 'اصلی',
@@ -150,12 +150,6 @@ export class SharedSaleInvoiceCreateService {
const rawPayments = (paymentsData || {}) as Record<string, unknown> const rawPayments = (paymentsData || {}) as Record<string, unknown>
const terminalInfo = rawPayments.terminals as TerminalPaymentInfo | undefined const terminalInfo = rawPayments.terminals as TerminalPaymentInfo | undefined
console.log(
'terminalInfo0',
rawPayments.terminals?.[0]?.customer_card_no,
terminalInfo,
)
const payments: NormalizedPayment[] = Object.entries(rawPayments) const payments: NormalizedPayment[] = Object.entries(rawPayments)
.filter(([key, value]) => key !== 'terminals' && value && Number(value) > 0) .filter(([key, value]) => key !== 'terminals' && value && Number(value) > 0)
.map(([key, value]) => ({ .map(([key, value]) => ({
+5 -3
View File
@@ -267,10 +267,12 @@ export type TspProviderType = (typeof TspProviderType)[keyof typeof TspProviderT
export const TspProviderResponseStatus = { export const TspProviderResponseStatus = {
SUCCESS: 'SUCCESS',
FAILURE: 'FAILURE',
NOT_SEND: 'NOT_SEND', NOT_SEND: 'NOT_SEND',
QUEUED: 'QUEUED' QUEUED: 'QUEUED',
FISCAL_QUEUED: 'FISCAL_QUEUED',
SEND_FAILURE: 'SEND_FAILURE',
SUCCESS: 'SUCCESS',
FAILURE: 'FAILURE'
} as const } as const
export type TspProviderResponseStatus = (typeof TspProviderResponseStatus)[keyof typeof TspProviderResponseStatus] export type TspProviderResponseStatus = (typeof TspProviderResponseStatus)[keyof typeof TspProviderResponseStatus]
File diff suppressed because one or more lines are too long
@@ -4141,8 +4141,11 @@ export const SaleInvoiceTspAttemptsScalarFieldEnum = {
status: 'status', status: 'status',
raw_request_payload: 'raw_request_payload', raw_request_payload: 'raw_request_payload',
provider_request_payload: 'provider_request_payload', provider_request_payload: 'provider_request_payload',
provider_response_payload: 'provider_response_payload', provider_response: 'provider_response',
message: 'message', message: 'message',
error_message: 'error_message',
validation_errors: 'validation_errors',
fiscal_warnings: 'fiscal_warnings',
sent_at: 'sent_at', sent_at: 'sent_at',
received_at: 'received_at', received_at: 'received_at',
created_at: 'created_at', created_at: 'created_at',
@@ -4683,6 +4686,7 @@ export type SalesInvoiceItemOrderByRelevanceFieldEnum = (typeof SalesInvoiceItem
export const SaleInvoiceTspAttemptsOrderByRelevanceFieldEnum = { export const SaleInvoiceTspAttemptsOrderByRelevanceFieldEnum = {
id: 'id', id: 'id',
message: 'message', message: 'message',
error_message: 'error_message',
invoice_id: 'invoice_id' invoice_id: 'invoice_id'
} as const } as const
@@ -666,8 +666,11 @@ export const SaleInvoiceTspAttemptsScalarFieldEnum = {
status: 'status', status: 'status',
raw_request_payload: 'raw_request_payload', raw_request_payload: 'raw_request_payload',
provider_request_payload: 'provider_request_payload', provider_request_payload: 'provider_request_payload',
provider_response_payload: 'provider_response_payload', provider_response: 'provider_response',
message: 'message', message: 'message',
error_message: 'error_message',
validation_errors: 'validation_errors',
fiscal_warnings: 'fiscal_warnings',
sent_at: 'sent_at', sent_at: 'sent_at',
received_at: 'received_at', received_at: 'received_at',
created_at: 'created_at', created_at: 'created_at',
@@ -1208,6 +1211,7 @@ export type SalesInvoiceItemOrderByRelevanceFieldEnum = (typeof SalesInvoiceItem
export const SaleInvoiceTspAttemptsOrderByRelevanceFieldEnum = { export const SaleInvoiceTspAttemptsOrderByRelevanceFieldEnum = {
id: 'id', id: 'id',
message: 'message', message: 'message',
error_message: 'error_message',
invoice_id: 'invoice_id' invoice_id: 'invoice_id'
} as const } as const
@@ -39,6 +39,7 @@ export type SaleInvoiceTspAttemptsMinAggregateOutputType = {
attempt_no: number | null attempt_no: number | null
status: $Enums.TspProviderResponseStatus | null status: $Enums.TspProviderResponseStatus | null
message: string | null message: string | null
error_message: string | null
sent_at: Date | null sent_at: Date | null
received_at: Date | null received_at: Date | null
created_at: Date | null created_at: Date | null
@@ -50,6 +51,7 @@ export type SaleInvoiceTspAttemptsMaxAggregateOutputType = {
attempt_no: number | null attempt_no: number | null
status: $Enums.TspProviderResponseStatus | null status: $Enums.TspProviderResponseStatus | null
message: string | null message: string | null
error_message: string | null
sent_at: Date | null sent_at: Date | null
received_at: Date | null received_at: Date | null
created_at: Date | null created_at: Date | null
@@ -62,8 +64,11 @@ export type SaleInvoiceTspAttemptsCountAggregateOutputType = {
status: number status: number
raw_request_payload: number raw_request_payload: number
provider_request_payload: number provider_request_payload: number
provider_response_payload: number provider_response: number
message: number message: number
error_message: number
validation_errors: number
fiscal_warnings: number
sent_at: number sent_at: number
received_at: number received_at: number
created_at: number created_at: number
@@ -85,6 +90,7 @@ export type SaleInvoiceTspAttemptsMinAggregateInputType = {
attempt_no?: true attempt_no?: true
status?: true status?: true
message?: true message?: true
error_message?: true
sent_at?: true sent_at?: true
received_at?: true received_at?: true
created_at?: true created_at?: true
@@ -96,6 +102,7 @@ export type SaleInvoiceTspAttemptsMaxAggregateInputType = {
attempt_no?: true attempt_no?: true
status?: true status?: true
message?: true message?: true
error_message?: true
sent_at?: true sent_at?: true
received_at?: true received_at?: true
created_at?: true created_at?: true
@@ -108,8 +115,11 @@ export type SaleInvoiceTspAttemptsCountAggregateInputType = {
status?: true status?: true
raw_request_payload?: true raw_request_payload?: true
provider_request_payload?: true provider_request_payload?: true
provider_response_payload?: true provider_response?: true
message?: true message?: true
error_message?: true
validation_errors?: true
fiscal_warnings?: true
sent_at?: true sent_at?: true
received_at?: true received_at?: true
created_at?: true created_at?: true
@@ -208,9 +218,12 @@ export type SaleInvoiceTspAttemptsGroupByOutputType = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: runtime.JsonValue raw_request_payload: runtime.JsonValue
provider_request_payload: runtime.JsonValue | null provider_request_payload: runtime.JsonValue
provider_response_payload: runtime.JsonValue | null provider_response: runtime.JsonValue | null
message: string message: string
error_message: string | null
validation_errors: runtime.JsonValue | null
fiscal_warnings: runtime.JsonValue | null
sent_at: Date | null sent_at: Date | null
received_at: Date | null received_at: Date | null
created_at: Date created_at: Date
@@ -245,9 +258,12 @@ export type SaleInvoiceTspAttemptsWhereInput = {
attempt_no?: Prisma.IntFilter<"SaleInvoiceTspAttempts"> | number attempt_no?: Prisma.IntFilter<"SaleInvoiceTspAttempts"> | number
status?: Prisma.EnumTspProviderResponseStatusFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts"> raw_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts">
provider_request_payload?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts"> provider_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts">
provider_response_payload?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts"> provider_response?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
message?: Prisma.StringFilter<"SaleInvoiceTspAttempts"> | string message?: Prisma.StringFilter<"SaleInvoiceTspAttempts"> | string
error_message?: Prisma.StringNullableFilter<"SaleInvoiceTspAttempts"> | string | null
validation_errors?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
fiscal_warnings?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
sent_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null sent_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null
received_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null received_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null
created_at?: Prisma.DateTimeFilter<"SaleInvoiceTspAttempts"> | Date | string created_at?: Prisma.DateTimeFilter<"SaleInvoiceTspAttempts"> | Date | string
@@ -260,9 +276,12 @@ export type SaleInvoiceTspAttemptsOrderByWithRelationInput = {
attempt_no?: Prisma.SortOrder attempt_no?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
raw_request_payload?: Prisma.SortOrder raw_request_payload?: Prisma.SortOrder
provider_request_payload?: Prisma.SortOrderInput | Prisma.SortOrder provider_request_payload?: Prisma.SortOrder
provider_response_payload?: Prisma.SortOrderInput | Prisma.SortOrder provider_response?: Prisma.SortOrderInput | Prisma.SortOrder
message?: Prisma.SortOrder message?: Prisma.SortOrder
error_message?: Prisma.SortOrderInput | Prisma.SortOrder
validation_errors?: Prisma.SortOrderInput | Prisma.SortOrder
fiscal_warnings?: Prisma.SortOrderInput | Prisma.SortOrder
sent_at?: Prisma.SortOrderInput | Prisma.SortOrder sent_at?: Prisma.SortOrderInput | Prisma.SortOrder
received_at?: Prisma.SortOrderInput | Prisma.SortOrder received_at?: Prisma.SortOrderInput | Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
@@ -280,9 +299,12 @@ export type SaleInvoiceTspAttemptsWhereUniqueInput = Prisma.AtLeast<{
attempt_no?: Prisma.IntFilter<"SaleInvoiceTspAttempts"> | number attempt_no?: Prisma.IntFilter<"SaleInvoiceTspAttempts"> | number
status?: Prisma.EnumTspProviderResponseStatusFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts"> raw_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts">
provider_request_payload?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts"> provider_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts">
provider_response_payload?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts"> provider_response?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
message?: Prisma.StringFilter<"SaleInvoiceTspAttempts"> | string message?: Prisma.StringFilter<"SaleInvoiceTspAttempts"> | string
error_message?: Prisma.StringNullableFilter<"SaleInvoiceTspAttempts"> | string | null
validation_errors?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
fiscal_warnings?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
sent_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null sent_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null
received_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null received_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null
created_at?: Prisma.DateTimeFilter<"SaleInvoiceTspAttempts"> | Date | string created_at?: Prisma.DateTimeFilter<"SaleInvoiceTspAttempts"> | Date | string
@@ -295,9 +317,12 @@ export type SaleInvoiceTspAttemptsOrderByWithAggregationInput = {
attempt_no?: Prisma.SortOrder attempt_no?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
raw_request_payload?: Prisma.SortOrder raw_request_payload?: Prisma.SortOrder
provider_request_payload?: Prisma.SortOrderInput | Prisma.SortOrder provider_request_payload?: Prisma.SortOrder
provider_response_payload?: Prisma.SortOrderInput | Prisma.SortOrder provider_response?: Prisma.SortOrderInput | Prisma.SortOrder
message?: Prisma.SortOrder message?: Prisma.SortOrder
error_message?: Prisma.SortOrderInput | Prisma.SortOrder
validation_errors?: Prisma.SortOrderInput | Prisma.SortOrder
fiscal_warnings?: Prisma.SortOrderInput | Prisma.SortOrder
sent_at?: Prisma.SortOrderInput | Prisma.SortOrder sent_at?: Prisma.SortOrderInput | Prisma.SortOrder
received_at?: Prisma.SortOrderInput | Prisma.SortOrder received_at?: Prisma.SortOrderInput | Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
@@ -317,9 +342,12 @@ export type SaleInvoiceTspAttemptsScalarWhereWithAggregatesInput = {
attempt_no?: Prisma.IntWithAggregatesFilter<"SaleInvoiceTspAttempts"> | number attempt_no?: Prisma.IntWithAggregatesFilter<"SaleInvoiceTspAttempts"> | number
status?: Prisma.EnumTspProviderResponseStatusWithAggregatesFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusWithAggregatesFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonWithAggregatesFilter<"SaleInvoiceTspAttempts"> raw_request_payload?: Prisma.JsonWithAggregatesFilter<"SaleInvoiceTspAttempts">
provider_request_payload?: Prisma.JsonNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> provider_request_payload?: Prisma.JsonWithAggregatesFilter<"SaleInvoiceTspAttempts">
provider_response_payload?: Prisma.JsonNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> provider_response?: Prisma.JsonNullableWithAggregatesFilter<"SaleInvoiceTspAttempts">
message?: Prisma.StringWithAggregatesFilter<"SaleInvoiceTspAttempts"> | string message?: Prisma.StringWithAggregatesFilter<"SaleInvoiceTspAttempts"> | string
error_message?: Prisma.StringNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> | string | null
validation_errors?: Prisma.JsonNullableWithAggregatesFilter<"SaleInvoiceTspAttempts">
fiscal_warnings?: Prisma.JsonNullableWithAggregatesFilter<"SaleInvoiceTspAttempts">
sent_at?: Prisma.DateTimeNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> | Date | string | null sent_at?: Prisma.DateTimeNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> | Date | string | null
received_at?: Prisma.DateTimeNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> | Date | string | null received_at?: Prisma.DateTimeNullableWithAggregatesFilter<"SaleInvoiceTspAttempts"> | Date | string | null
created_at?: Prisma.DateTimeWithAggregatesFilter<"SaleInvoiceTspAttempts"> | Date | string created_at?: Prisma.DateTimeWithAggregatesFilter<"SaleInvoiceTspAttempts"> | Date | string
@@ -331,9 +359,12 @@ export type SaleInvoiceTspAttemptsCreateInput = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message: string message: string
error_message?: string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Date | string | null sent_at?: Date | string | null
received_at?: Date | string | null received_at?: Date | string | null
created_at?: Date | string created_at?: Date | string
@@ -345,9 +376,12 @@ export type SaleInvoiceTspAttemptsUncheckedCreateInput = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message: string message: string
error_message?: string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Date | string | null sent_at?: Date | string | null
received_at?: Date | string | null received_at?: Date | string | null
created_at?: Date | string created_at?: Date | string
@@ -359,9 +393,12 @@ export type SaleInvoiceTspAttemptsUpdateInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -373,9 +410,12 @@ export type SaleInvoiceTspAttemptsUncheckedUpdateInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -387,9 +427,12 @@ export type SaleInvoiceTspAttemptsCreateManyInput = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message: string message: string
error_message?: string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Date | string | null sent_at?: Date | string | null
received_at?: Date | string | null received_at?: Date | string | null
created_at?: Date | string created_at?: Date | string
@@ -401,9 +444,12 @@ export type SaleInvoiceTspAttemptsUpdateManyMutationInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -414,9 +460,12 @@ export type SaleInvoiceTspAttemptsUncheckedUpdateManyInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -450,8 +499,11 @@ export type SaleInvoiceTspAttemptsCountOrderByAggregateInput = {
status?: Prisma.SortOrder status?: Prisma.SortOrder
raw_request_payload?: Prisma.SortOrder raw_request_payload?: Prisma.SortOrder
provider_request_payload?: Prisma.SortOrder provider_request_payload?: Prisma.SortOrder
provider_response_payload?: Prisma.SortOrder provider_response?: Prisma.SortOrder
message?: Prisma.SortOrder message?: Prisma.SortOrder
error_message?: Prisma.SortOrder
validation_errors?: Prisma.SortOrder
fiscal_warnings?: Prisma.SortOrder
sent_at?: Prisma.SortOrder sent_at?: Prisma.SortOrder
received_at?: Prisma.SortOrder received_at?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
@@ -467,6 +519,7 @@ export type SaleInvoiceTspAttemptsMaxOrderByAggregateInput = {
attempt_no?: Prisma.SortOrder attempt_no?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
message?: Prisma.SortOrder message?: Prisma.SortOrder
error_message?: Prisma.SortOrder
sent_at?: Prisma.SortOrder sent_at?: Prisma.SortOrder
received_at?: Prisma.SortOrder received_at?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
@@ -478,6 +531,7 @@ export type SaleInvoiceTspAttemptsMinOrderByAggregateInput = {
attempt_no?: Prisma.SortOrder attempt_no?: Prisma.SortOrder
status?: Prisma.SortOrder status?: Prisma.SortOrder
message?: Prisma.SortOrder message?: Prisma.SortOrder
error_message?: Prisma.SortOrder
sent_at?: Prisma.SortOrder sent_at?: Prisma.SortOrder
received_at?: Prisma.SortOrder received_at?: Prisma.SortOrder
created_at?: Prisma.SortOrder created_at?: Prisma.SortOrder
@@ -539,9 +593,12 @@ export type SaleInvoiceTspAttemptsCreateWithoutInvoiceInput = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message: string message: string
error_message?: string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Date | string | null sent_at?: Date | string | null
received_at?: Date | string | null received_at?: Date | string | null
created_at?: Date | string created_at?: Date | string
@@ -552,9 +609,12 @@ export type SaleInvoiceTspAttemptsUncheckedCreateWithoutInvoiceInput = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message: string message: string
error_message?: string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Date | string | null sent_at?: Date | string | null
received_at?: Date | string | null received_at?: Date | string | null
created_at?: Date | string created_at?: Date | string
@@ -594,9 +654,12 @@ export type SaleInvoiceTspAttemptsScalarWhereInput = {
attempt_no?: Prisma.IntFilter<"SaleInvoiceTspAttempts"> | number attempt_no?: Prisma.IntFilter<"SaleInvoiceTspAttempts"> | number
status?: Prisma.EnumTspProviderResponseStatusFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFilter<"SaleInvoiceTspAttempts"> | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts"> raw_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts">
provider_request_payload?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts"> provider_request_payload?: Prisma.JsonFilter<"SaleInvoiceTspAttempts">
provider_response_payload?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts"> provider_response?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
message?: Prisma.StringFilter<"SaleInvoiceTspAttempts"> | string message?: Prisma.StringFilter<"SaleInvoiceTspAttempts"> | string
error_message?: Prisma.StringNullableFilter<"SaleInvoiceTspAttempts"> | string | null
validation_errors?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
fiscal_warnings?: Prisma.JsonNullableFilter<"SaleInvoiceTspAttempts">
sent_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null sent_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null
received_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null received_at?: Prisma.DateTimeNullableFilter<"SaleInvoiceTspAttempts"> | Date | string | null
created_at?: Prisma.DateTimeFilter<"SaleInvoiceTspAttempts"> | Date | string created_at?: Prisma.DateTimeFilter<"SaleInvoiceTspAttempts"> | Date | string
@@ -608,9 +671,12 @@ export type SaleInvoiceTspAttemptsCreateManyInvoiceInput = {
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message: string message: string
error_message?: string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Date | string | null sent_at?: Date | string | null
received_at?: Date | string | null received_at?: Date | string | null
created_at?: Date | string created_at?: Date | string
@@ -621,9 +687,12 @@ export type SaleInvoiceTspAttemptsUpdateWithoutInvoiceInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -634,9 +703,12 @@ export type SaleInvoiceTspAttemptsUncheckedUpdateWithoutInvoiceInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -647,9 +719,12 @@ export type SaleInvoiceTspAttemptsUncheckedUpdateManyWithoutInvoiceInput = {
attempt_no?: Prisma.IntFieldUpdateOperationsInput | number attempt_no?: Prisma.IntFieldUpdateOperationsInput | number
status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus status?: Prisma.EnumTspProviderResponseStatusFieldUpdateOperationsInput | $Enums.TspProviderResponseStatus
raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue raw_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_request_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_request_payload?: Prisma.JsonNullValueInput | runtime.InputJsonValue
provider_response_payload?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue provider_response?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
message?: Prisma.StringFieldUpdateOperationsInput | string message?: Prisma.StringFieldUpdateOperationsInput | string
error_message?: Prisma.NullableStringFieldUpdateOperationsInput | string | null
validation_errors?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
fiscal_warnings?: Prisma.NullableJsonNullValueInput | runtime.InputJsonValue
sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null sent_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null received_at?: Prisma.NullableDateTimeFieldUpdateOperationsInput | Date | string | null
created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string created_at?: Prisma.DateTimeFieldUpdateOperationsInput | Date | string
@@ -663,8 +738,11 @@ export type SaleInvoiceTspAttemptsSelect<ExtArgs extends runtime.Types.Extension
status?: boolean status?: boolean
raw_request_payload?: boolean raw_request_payload?: boolean
provider_request_payload?: boolean provider_request_payload?: boolean
provider_response_payload?: boolean provider_response?: boolean
message?: boolean message?: boolean
error_message?: boolean
validation_errors?: boolean
fiscal_warnings?: boolean
sent_at?: boolean sent_at?: boolean
received_at?: boolean received_at?: boolean
created_at?: boolean created_at?: boolean
@@ -680,15 +758,18 @@ export type SaleInvoiceTspAttemptsSelectScalar = {
status?: boolean status?: boolean
raw_request_payload?: boolean raw_request_payload?: boolean
provider_request_payload?: boolean provider_request_payload?: boolean
provider_response_payload?: boolean provider_response?: boolean
message?: boolean message?: boolean
error_message?: boolean
validation_errors?: boolean
fiscal_warnings?: boolean
sent_at?: boolean sent_at?: boolean
received_at?: boolean received_at?: boolean
created_at?: boolean created_at?: boolean
invoice_id?: boolean invoice_id?: boolean
} }
export type SaleInvoiceTspAttemptsOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "attempt_no" | "status" | "raw_request_payload" | "provider_request_payload" | "provider_response_payload" | "message" | "sent_at" | "received_at" | "created_at" | "invoice_id", ExtArgs["result"]["saleInvoiceTspAttempts"]> export type SaleInvoiceTspAttemptsOmit<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = runtime.Types.Extensions.GetOmit<"id" | "attempt_no" | "status" | "raw_request_payload" | "provider_request_payload" | "provider_response" | "message" | "error_message" | "validation_errors" | "fiscal_warnings" | "sent_at" | "received_at" | "created_at" | "invoice_id", ExtArgs["result"]["saleInvoiceTspAttempts"]>
export type SaleInvoiceTspAttemptsInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = { export type SaleInvoiceTspAttemptsInclude<ExtArgs extends runtime.Types.Extensions.InternalArgs = runtime.Types.Extensions.DefaultArgs> = {
invoice?: boolean | Prisma.SalesInvoiceDefaultArgs<ExtArgs> invoice?: boolean | Prisma.SalesInvoiceDefaultArgs<ExtArgs>
} }
@@ -703,9 +784,12 @@ export type $SaleInvoiceTspAttemptsPayload<ExtArgs extends runtime.Types.Extensi
attempt_no: number attempt_no: number
status: $Enums.TspProviderResponseStatus status: $Enums.TspProviderResponseStatus
raw_request_payload: runtime.JsonValue raw_request_payload: runtime.JsonValue
provider_request_payload: runtime.JsonValue | null provider_request_payload: runtime.JsonValue
provider_response_payload: runtime.JsonValue | null provider_response: runtime.JsonValue | null
message: string message: string
error_message: string | null
validation_errors: runtime.JsonValue | null
fiscal_warnings: runtime.JsonValue | null
sent_at: Date | null sent_at: Date | null
received_at: Date | null received_at: Date | null
created_at: Date created_at: Date
@@ -1085,8 +1169,11 @@ export interface SaleInvoiceTspAttemptsFieldRefs {
readonly status: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'TspProviderResponseStatus'> readonly status: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'TspProviderResponseStatus'>
readonly raw_request_payload: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'> readonly raw_request_payload: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'>
readonly provider_request_payload: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'> readonly provider_request_payload: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'>
readonly provider_response_payload: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'> readonly provider_response: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'>
readonly message: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'String'> readonly message: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'String'>
readonly error_message: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'String'>
readonly validation_errors: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'>
readonly fiscal_warnings: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'Json'>
readonly sent_at: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'DateTime'> readonly sent_at: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'DateTime'>
readonly received_at: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'DateTime'> readonly received_at: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'DateTime'>
readonly created_at: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'DateTime'> readonly created_at: Prisma.FieldRef<"SaleInvoiceTspAttempts", 'DateTime'>
@@ -41,13 +41,17 @@ export class SalesInvoicesService {
await tx.salesInvoice.count({ where }), await tx.salesInvoice.count({ where }),
]) ])
const summaryItems = items.map(invoice => ({ const summaryItems = items.map(invoice => {
...invoice, const { tsp_attempts, type, ...rest } = invoice
return {
...rest,
type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND,
), ),
})) }
})
return ResponseMapper.paginate(summaryItems, { total, page, perPage }) return ResponseMapper.paginate(summaryItems, { total, page, perPage })
} }
@@ -69,15 +73,17 @@ export class SalesInvoicesService {
}) })
if (invoice) { if (invoice) {
const { tsp_attempts, ...rest } = invoice || {} const { tsp_attempts, type, ...rest } = invoice
const mappedInvoice = {
return ResponseMapper.single({
...rest, ...rest,
type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue( status: translateEnumValue(
'TspProviderResponseStatus', 'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND, invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND,
), ),
}) }
return ResponseMapper.single(mappedInvoice)
} else throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.') } else throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.')
} }
@@ -1,6 +1,9 @@
import { ResponseMapper } from '@/common/response/response-mapper' import { ResponseMapper } from '@/common/response/response-mapper'
import { getCurrentJalaliSeasonRange } from '@/common/utils' import { getCurrentJalaliSeasonRange } from '@/common/utils'
import { TspProviderResponseStatus } from '@/generated/prisma/enums' import {
TspProviderRequestType,
TspProviderResponseStatus,
} from '@/generated/prisma/enums'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
@@ -23,12 +26,13 @@ export class StatisticsService {
pending_count: number | null pending_count: number | null
not_sended_amount_sum: number | null not_sended_amount_sum: number | null
not_sended_count: number | null not_sended_count: number | null
credit_amount_sum: number | null not_original_amount_sum: number | null
credit_count: number | null not_original_count: number | null
}> }>
>` >`
SELECT SELECT
SUM(si.total_amount) AS all_amount_sum, SUM(si.total_amount) AS all_amount_sum,
si.type,
COUNT(*) AS all_count, COUNT(*) AS all_count,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN si.total_amount ELSE 0 END) AS success_amount_sum, SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN si.total_amount ELSE 0 END) AS success_amount_sum,
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN 1 ELSE 0 END) AS success_count, SUM(CASE WHEN la.status = ${TspProviderResponseStatus.SUCCESS} THEN 1 ELSE 0 END) AS success_count,
@@ -38,8 +42,8 @@ export class StatisticsService {
SUM(CASE WHEN la.status = ${TspProviderResponseStatus.QUEUED} THEN 1 ELSE 0 END) AS pending_count, SUM(CASE WHEN la.status = ${TspProviderResponseStatus.QUEUED} THEN 1 ELSE 0 END) AS pending_count,
SUM(CASE WHEN la.status IS NULL THEN si.total_amount ELSE 0 END) AS not_sended_amount_sum, SUM(CASE WHEN la.status IS NULL THEN si.total_amount ELSE 0 END) AS not_sended_amount_sum,
SUM(CASE WHEN la.status IS NULL THEN 1 ELSE 0 END) AS not_sended_count, SUM(CASE WHEN la.status IS NULL THEN 1 ELSE 0 END) AS not_sended_count,
SUM(CASE WHEN si.settlement_type = 'CREDIT' THEN si.total_amount ELSE 0 END) AS credit_amount_sum, SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN si.total_amount ELSE 0 END) AS not_original_amount_sum,
SUM(CASE WHEN si.settlement_type = 'CREDIT' THEN 1 ELSE 0 END) AS credit_count SUM(CASE WHEN si.type <> ${TspProviderRequestType.ORIGINAL} THEN 1 ELSE 0 END) AS not_original_count
FROM sales_invoices si FROM sales_invoices si
INNER JOIN poses p ON p.id = si.pos_id INNER JOIN poses p ON p.id = si.pos_id
LEFT JOIN ( LEFT JOIN (
@@ -64,6 +68,7 @@ export class StatisticsService {
FROM sales_invoices child FROM sales_invoices child
WHERE child.ref_id = si.id WHERE child.ref_id = si.id
) )
GROUP BY si.type
` `
return ResponseMapper.single({ return ResponseMapper.single({
@@ -87,15 +92,15 @@ export class StatisticsService {
total_tax: Number(0), total_tax: Number(0),
count: Number(item?.pending_count || 0), count: Number(item?.pending_count || 0),
}, },
notSended: { not_sended: {
total_amount: Number(item?.not_sended_amount_sum || 0), total_amount: Number(item?.not_sended_amount_sum || 0),
total_tax: Number(0), total_tax: Number(0),
count: Number(item?.not_sended_count || 0), count: Number(item?.not_sended_count || 0),
}, },
credit: { not_original: {
total_amount: Number(item?.credit_amount_sum || 0), total_amount: Number(item?.not_original_amount_sum || 0),
total_tax: Number(0), total_tax: Number(0),
count: Number(item?.credit_count || 0), count: Number(item?.not_original_count || 0),
}, },
}) })
} }
+129
View File
@@ -0,0 +1,129 @@
import { CustomerType, PaymentMethodType } from '@/generated/prisma/enums'
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
IsDateString,
IsEnum,
IsNumber,
IsObject,
IsOptional,
IsString,
Min,
ValidateNested,
} from 'class-validator'
export class CustomerUnknownInfoDto {
@ApiProperty({})
@IsString()
@IsOptional()
name: string
@ApiProperty({})
@IsString()
@IsOptional()
economic_code: string
}
export class CustomerLegalInfoDto {
@ApiProperty({ required: true })
@IsString()
name: string
@ApiProperty({ required: true })
@IsString()
economic_code: string
}
export class CustomerIndividualInfoDto {
@ApiProperty({ required: true })
@IsString()
first_name: string
@ApiProperty({ required: true })
@IsString()
last_name: string
@ApiProperty({ required: true })
@IsString()
national_id: string
@ApiProperty({ required: true })
@IsString()
mobile_number: string
}
export class CustomerInfoDto {
@ApiProperty({ required: true, enum: CustomerType })
@IsEnum(CustomerType)
type: CustomerType
@ApiProperty({})
@Type(() => CustomerLegalInfoDto)
@ValidateNested({ each: true })
legal_info?: CustomerLegalInfoDto
@ApiProperty({})
@Type(() => CustomerIndividualInfoDto)
@ValidateNested({ each: true })
individual_info?: CustomerIndividualInfoDto
@ApiProperty({})
@Type(() => CustomerUnknownInfoDto)
@ValidateNested({ each: true })
unknown_info?: CustomerUnknownInfoDto
}
export class TerminalInfoDto {
@ApiProperty({ required: false })
@IsOptional()
@IsString()
tracking_code?: string
@ApiProperty({ required: false })
@IsOptional()
@IsString()
card_number?: string
}
export class PaymentInfoDto {
@ApiProperty({ required: true, enum: PaymentMethodType })
@IsEnum(PaymentMethodType)
payment_method: PaymentMethodType
@ApiProperty({ required: true })
@IsNumber({ allowInfinity: false, allowNaN: false })
@Min(0)
amount: number
@ApiProperty({ required: false })
@IsOptional()
@IsDateString()
paid_at?: Date
@ApiProperty({ type: TerminalInfoDto })
@IsOptional()
@IsObject()
terminal_info: TerminalInfoDto
}
export class goldTypePayload {
@ApiProperty({ required: false })
@IsOptional()
@IsString()
karat: string
@ApiProperty({ required: false })
@IsOptional()
@IsString()
profit: string
@ApiProperty({ required: false })
@IsOptional()
@IsString()
wages: string
@ApiProperty({ required: false })
@IsOptional()
@IsString()
commission: string
}
@@ -0,0 +1,41 @@
import {
SharedCreateSalesInvoiceItemDto,
SharedCreateSalesInvoicePaymentsDto,
} from '@/common/services/saleInvoices/sale-invoice-create.dto'
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
ArrayMinSize,
IsArray,
IsNumber,
IsObject,
IsString,
ValidateNested,
} from 'class-validator'
import { TspProviderOriginalSendPayloadDto } from './original.dto'
export class TspProviderCorrectionInvoicePayloadDto {
@ApiProperty({ type: [SharedCreateSalesInvoiceItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => SharedCreateSalesInvoiceItemDto)
@ArrayMinSize(1)
items: SharedCreateSalesInvoiceItemDto[]
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty({ required: true, type: SharedCreateSalesInvoicePaymentsDto })
@IsObject()
@ValidateNested({ each: true })
@Type(() => SharedCreateSalesInvoicePaymentsDto)
payments: SharedCreateSalesInvoicePaymentsDto
}
export class TspProviderCorrectionSendPayloadDto extends TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true })
@IsString()
last_tax_id: string
}
export class TspProviderCorrectionSendResponseDto {}
+42
View File
@@ -0,0 +1,42 @@
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
@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
}
+6
View File
@@ -0,0 +1,6 @@
export * from './common.dto'
export * from './correction.dto'
export * from './get.dto'
export * from './original.dto'
export * from './provider-switch.dto'
export * from './revoke.dto'
@@ -0,0 +1,193 @@
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,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from 'class-validator'
import { CustomerInfoDto, goldTypePayload, PaymentInfoDto } from './common.dto'
export class TspProviderOriginalItemPayloadDto {
@ApiProperty({ required: true })
@IsString()
sku: string
@ApiProperty({ required: true })
@IsString()
sku_vat: string
@ApiProperty({ required: true })
@IsNumber()
unit_price: number
// @ApiProperty()
// @IsString()
// invoice_item_id: string
@ApiProperty()
@IsNumber()
quantity: number
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty()
@IsOptional()
@IsString()
discount: string
@ApiProperty({ required: true })
@IsString()
measure_unit: string
@ApiProperty({ nullable: true })
@IsOptional()
@IsString()
good_id?: string | null
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
service_id?: string | null
@ApiProperty({ required: false, nullable: true, type: goldTypePayload })
@IsOptional()
@IsObject()
gold_type_payload?: goldTypePayload
// @ApiProperty({ required: false, nullable: true, type: Object })
// @IsOptional()
// @IsObject()
// payload?: unknown
}
export class TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true, nullable: true })
@IsString()
id: string
@ApiProperty({ required: true, nullable: true })
@IsNumber()
invoice_number: number
@ApiProperty({ required: true, nullable: true })
@IsDateString()
invoice_date: Date
@ApiProperty({ required: true, nullable: true })
@IsString()
economic_code: string
@ApiProperty({ required: true, nullable: true })
@IsString()
fiscal_id: string
@ApiProperty({ required: true, enum: TspProviderType })
@IsEnum(TspProviderType)
tsp_provider: TspProviderType
@ApiProperty({ required: true, enum: InvoiceTemplateType })
@IsEnum(InvoiceTemplateType)
template: InvoiceTemplateType
@ApiProperty({ required: true })
@IsString()
token: string
@ApiProperty({ required: true, enum: InvoiceSettlementType })
@IsEnum(InvoiceSettlementType)
settlement_type: InvoiceSettlementType
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty({ type: [TspProviderOriginalItemPayloadDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => TspProviderOriginalItemPayloadDto)
items: TspProviderOriginalItemPayloadDto[]
@ApiProperty({ required: false })
@Type(() => CustomerInfoDto)
@ValidateNested({ each: true })
customer?: CustomerInfoDto
@ApiProperty({ required: true, type: [PaymentInfoDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => PaymentInfoDto)
payments: PaymentInfoDto[]
}
export class TspProviderOriginalSendItemResultDto {
@ApiProperty()
@IsString()
invoice_id: string
@ApiProperty({ enum: TspProviderResponseStatus })
@IsEnum(TspProviderResponseStatus)
status: TspProviderResponseStatus
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
tax_id?: string | null
@ApiProperty({
required: true,
nullable: true,
type: TspProviderOriginalSendPayloadDto,
})
@IsOptional()
@IsObject()
@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
}
@@ -1,412 +1,30 @@
import { TspProviderCustomerType } from '@/common/enums/enums' import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import {
SharedCreateSalesInvoiceItemDto,
SharedCreateSalesInvoicePaymentsDto,
} from '@/common/services/saleInvoices/sale-invoice-create.dto'
import {
CustomerType,
InvoiceSettlementType,
InvoiceTemplateType,
PaymentMethodType,
TspProviderRequestType,
TspProviderResponseStatus,
TspProviderType,
} from '@/generated/prisma/enums'
import { ApiProperty } from '@nestjs/swagger' import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer' import { Type } from 'class-transformer'
import { IsArray, IsEnum, IsObject, IsString, ValidateNested } from 'class-validator'
import { import {
ArrayMinSize, TspProviderCorrectionSendPayloadDto,
IsArray, TspProviderCorrectionSendResponseDto,
IsBoolean, } from './correction.dto'
IsDateString, import { TspProviderGetResultDto } from './get.dto'
IsEnum, import {
IsNumber, TspProviderOriginalSendItemResultDto,
IsObject, TspProviderOriginalSendPayloadDto,
IsOptional, } from './original.dto'
IsString, import { TspProviderRevokePayloadDto, TspProviderRevokeResponseDto } from './revoke.dto'
Min,
ValidateNested,
} from 'class-validator'
export class CustomerLegalInfoDto {
@ApiProperty({ required: true })
@IsString()
name: string
@ApiProperty({ required: true })
@IsString()
economic_code: string
}
export class CustomerIndividualInfoDto {
@ApiProperty({ required: true })
@IsString()
first_name: string
@ApiProperty({ required: true })
@IsString()
last_name: string
@ApiProperty({ required: true })
@IsString()
national_id: string
@ApiProperty({ required: true })
@IsString()
mobile_number: string
}
export class CustomerInfoDto {
@ApiProperty({ required: true, enum: CustomerType })
@IsEnum(CustomerType)
type: CustomerType
@ApiProperty({})
@Type(() => CustomerLegalInfoDto)
@ValidateNested({ each: true })
legal_info?: CustomerLegalInfoDto
@ApiProperty({})
@Type(() => CustomerIndividualInfoDto)
@ValidateNested({ each: true })
individual_info?: CustomerIndividualInfoDto
}
export class PaymentInfoDto {
@ApiProperty({ required: true, enum: PaymentMethodType })
@IsEnum(PaymentMethodType)
payment_method: PaymentMethodType
@ApiProperty({ required: true })
@IsNumber({ allowInfinity: false, allowNaN: false })
@Min(10_000)
amount: number
@ApiProperty({ required: false })
@IsOptional()
@IsString()
tracking_code?: string
@ApiProperty({ required: false })
@IsOptional()
@IsString()
card_number?: string
@ApiProperty({ required: false })
@IsOptional()
@IsDateString()
paid_at?: Date
}
export class TspProviderSendItemPayloadDto {
@ApiProperty({ required: true })
@IsString()
sku: string
@ApiProperty({ required: true })
@IsString()
sku_vat: string
@ApiProperty()
@IsOptional()
@IsString()
discount: string
@ApiProperty({ required: true })
@IsNumber()
unit_price: number
@ApiProperty()
@IsString()
invoice_item_id: string
@ApiProperty()
@IsNumber()
quantity: number
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty({ required: true })
@IsString()
measure_unit: string
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
good_id?: string | null
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
service_id?: string | null
@ApiProperty({ required: false, nullable: true, type: Object })
@IsOptional()
@IsObject()
payload?: unknown
}
export class TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true, enum: TspProviderRequestType })
@IsEnum(TspProviderRequestType)
type: TspProviderRequestType
@ApiProperty({ required: true, enum: TspProviderCustomerType })
@IsEnum(TspProviderCustomerType)
customer_type: TspProviderCustomerType
@ApiProperty({ type: [TspProviderSendItemPayloadDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => TspProviderSendItemPayloadDto)
items: TspProviderSendItemPayloadDto[]
@ApiProperty({ required: false })
@Type(() => CustomerInfoDto)
@ValidateNested({ each: true })
customer?: CustomerInfoDto
@ApiProperty({ required: true, nullable: true })
@IsNumber()
invoice_number: number
@ApiProperty({ required: true, nullable: true })
@IsDateString()
invoice_date: Date
@ApiProperty({ required: true, nullable: true })
@IsString()
invoice_id: string
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty({ required: true, enum: TspProviderType })
@IsEnum(TspProviderType)
tsp_provider: TspProviderType
@ApiProperty({ required: true, nullable: true })
@IsString()
economic_code: string
@ApiProperty({ required: true, nullable: true })
@IsString()
fiscal_id: string
@ApiProperty({ required: true, type: [PaymentInfoDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => PaymentInfoDto)
payments: PaymentInfoDto[]
@ApiProperty({ required: true, enum: InvoiceTemplateType })
@IsEnum(InvoiceTemplateType)
invoice_template: InvoiceTemplateType
@ApiProperty({ required: true })
@IsString()
tsp_token: string
@ApiProperty({ required: true, enum: InvoiceSettlementType })
@IsEnum(InvoiceSettlementType)
settlement_type: InvoiceSettlementType
}
export class TspProviderSendItemResultDto {
@ApiProperty()
@IsString()
invoice_id: string
@ApiProperty({ enum: TspProviderResponseStatus })
@IsEnum(TspProviderResponseStatus)
status: TspProviderResponseStatus
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
tax_id?: string | null
@ApiProperty({
required: true,
nullable: true,
type: TspProviderOriginalSendPayloadDto,
})
@IsOptional()
@IsObject()
provider_request_payload: Object
@ApiProperty({ required: false, nullable: true, type: Object })
@IsOptional()
@IsObject()
provider_response_payload?: Object
@ApiProperty({ required: true })
@IsBoolean()
hasError: boolean
@ApiProperty({ required: false, nullable: true })
@IsOptional()
@IsString()
message?: string | null
@ApiProperty({ required: true })
@IsDateString()
sent_at: string
@ApiProperty({ required: true })
@IsDateString()
received_at: string
}
export class TspProviderBulkSendResultDto { export class TspProviderBulkSendResultDto {
@ApiProperty() @ApiProperty()
@IsString() @IsString()
invoice_id: string invoice_id: string
@ApiProperty({ type: [TspProviderSendItemResultDto] }) @ApiProperty({ type: [TspProviderOriginalSendItemResultDto] })
@IsArray() @IsArray()
@ValidateNested({ each: true }) @ValidateNested({ each: true })
@Type(() => TspProviderSendItemResultDto) @Type(() => TspProviderOriginalSendItemResultDto)
items: TspProviderSendItemResultDto[] items: TspProviderOriginalSendItemResultDto[]
} }
///////////// GET RELATED DTOs /////////////
export class TspProviderGetResultDto {
@ApiProperty()
@IsString()
tax_id: string
@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
}
///////////// REVOKE RELATED DTOs /////////////
export class TspProviderRevokePayloadDto {
@ApiProperty({ required: true, nullable: true })
@IsNumber()
invoice_number: number
@ApiProperty({ required: true, nullable: true })
@IsString()
invoice_id: string
@ApiProperty({ required: true, enum: TspProviderType })
@IsEnum(TspProviderType)
tsp_provider: TspProviderType
@ApiProperty({ required: true, nullable: true })
@IsString()
economic_code: string
@ApiProperty({ required: true, nullable: true })
@IsString()
fiscal_id: string
@ApiProperty({ required: true })
@IsString()
tsp_token: string
@ApiProperty({ required: true })
@IsString()
last_tax_id: string
}
export class TspProviderRevokeResponseDto {
@ApiProperty({ required: true, nullable: true })
@IsString()
invoice_id: string
@ApiProperty({ required: true })
@IsString()
tax_id: string
@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_request_payload?: unknown
@ApiProperty({ required: false, nullable: true, type: Object })
@IsOptional()
@IsObject()
provider_response_payload?: unknown
@ApiProperty({ required: true })
@IsDateString()
sent_at: string
@ApiProperty({ required: true })
@IsDateString()
received_at: string
}
///////////// CORRECTION RELATED DTOs /////////////
export class TspProviderCorrectionInvoicePayloadDto {
@ApiProperty({ type: [SharedCreateSalesInvoiceItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => SharedCreateSalesInvoiceItemDto)
@ArrayMinSize(1)
items: SharedCreateSalesInvoiceItemDto[]
@ApiProperty()
@IsNumber()
total_amount: number
@ApiProperty({ required: true, type: SharedCreateSalesInvoicePaymentsDto })
@IsObject()
@ValidateNested({ each: true })
@Type(() => SharedCreateSalesInvoicePaymentsDto)
payments: SharedCreateSalesInvoicePaymentsDto
}
export class TspProviderCorrectionSendPayloadDto extends TspProviderOriginalSendPayloadDto {
@ApiProperty({ required: true })
@IsString()
last_tax_id: string
}
export class TspProviderCorrectionSendResponseDto {}
export class TspProviderActionResponseDto { export class TspProviderActionResponseDto {
@IsObject() @IsObject()
invoice: object invoice: object
@@ -422,7 +40,7 @@ export interface IProviderSwitchAdapter {
readonly code: string readonly code: string
originalSend( originalSend(
payload: TspProviderOriginalSendPayloadDto, payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto> ): Promise<TspProviderOriginalSendItemResultDto>
sendBulk( sendBulk(
payloads: TspProviderOriginalSendPayloadDto[], payloads: TspProviderOriginalSendPayloadDto[],
): Promise<TspProviderBulkSendResultDto[]> ): Promise<TspProviderBulkSendResultDto[]>
@@ -0,0 +1,82 @@
import { TspProviderResponseStatus, TspProviderType } from '@/generated/prisma/enums'
import { ApiProperty } from '@nestjs/swagger'
import {
IsBoolean,
IsDateString,
IsEnum,
IsNumber,
IsObject,
IsOptional,
IsString,
} from 'class-validator'
export class TspProviderRevokePayloadDto {
@ApiProperty({ required: true, nullable: true })
@IsNumber()
invoice_number: number
@ApiProperty({ required: true, nullable: true })
@IsString()
invoice_id: string
@ApiProperty({ required: true, enum: TspProviderType })
@IsEnum(TspProviderType)
tsp_provider: TspProviderType
@ApiProperty({ required: true, nullable: true })
@IsString()
economic_code: string
@ApiProperty({ required: true, nullable: true })
@IsString()
fiscal_id: string
@ApiProperty({ required: true })
@IsString()
tsp_token: string
@ApiProperty({ required: true })
@IsString()
last_tax_id: string
}
export class TspProviderRevokeResponseDto {
@ApiProperty({ required: true, nullable: true })
@IsString()
invoice_id: string
@ApiProperty({ required: true })
@IsString()
tax_id: string
@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_request_payload?: unknown
@ApiProperty({ required: false, nullable: true, type: Object })
@IsOptional()
@IsObject()
provider_response_payload?: unknown
@ApiProperty({ required: true })
@IsDateString()
sent_at: string
@ApiProperty({ required: true })
@IsDateString()
received_at: string
}
@@ -4,11 +4,11 @@ import {
TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendPayloadDto,
TspProviderCorrectionSendResponseDto, TspProviderCorrectionSendResponseDto,
TspProviderGetResultDto, TspProviderGetResultDto,
TspProviderOriginalSendItemResultDto,
TspProviderOriginalSendPayloadDto, TspProviderOriginalSendPayloadDto,
TspProviderRevokePayloadDto, TspProviderRevokePayloadDto,
TspProviderRevokeResponseDto, TspProviderRevokeResponseDto,
TspProviderSendItemResultDto, } from './dto'
} from './dto/provider-switch.dto'
import { NamaProviderSwitchAdapter } from './switch/nama/nama-provider.adapter' import { NamaProviderSwitchAdapter } from './switch/nama/nama-provider.adapter'
@Injectable() @Injectable()
@@ -34,7 +34,7 @@ export class SalesInvoiceTspSwitchService {
async send( async send(
payload: TspProviderOriginalSendPayloadDto, payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto> { ): Promise<TspProviderOriginalSendItemResultDto> {
const adapter = this.resolveSwitch(payload.tsp_provider) const adapter = this.resolveSwitch(payload.tsp_provider)
return adapter.originalSend(payload) return adapter.originalSend(payload)
@@ -9,11 +9,11 @@ import {
import { import {
TspProviderActionResponseDto, TspProviderActionResponseDto,
TspProviderCorrectionInvoicePayloadDto, TspProviderCorrectionInvoicePayloadDto,
} from './dto/provider-switch.dto' } from './dto'
import { SalesInvoiceTspSwitchService } from './sales-invoice-tsp-switch.service' import { SalesInvoiceTspSwitchService } from './sales-invoice-tsp-switch.service'
import { import {
buildCorrectionPayload, buildCorrectionPayload,
buildPayload, buildOriginalPayload,
buildRevokePayload, buildRevokePayload,
getOriginalResendAttemptNumber, getOriginalResendAttemptNumber,
onResult, onResult,
@@ -33,81 +33,27 @@ export class SalesInvoiceTspService {
private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService, private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService,
) {} ) {}
private mapProviderError(error: any) {
const isProviderFailureObject =
error &&
typeof error === 'object' &&
('provider_request_payload' in error ||
'provider_response_payload' in error ||
'sent_at' in error ||
'received_at' in error)
if (isProviderFailureObject) {
return {
hasError: true,
status: error.status || TspProviderResponseStatus.FAILURE,
message:
error.message?.toString() ||
'خطا در ارتباط با سامانه مالیاتی. لطفا مجددا تلاش کنید.',
provider_request_payload: error.provider_request_payload,
provider_response_payload: error.provider_response_payload,
sent_at: error.sent_at || new Date().toISOString(),
received_at: error.received_at || new Date().toISOString(),
}
}
return {
hasError: true,
status: TspProviderResponseStatus.FAILURE,
message:
error?.message?.toString() ||
'خطا در ارتباط با سامانه مالیاتی. لطفا مجددا تلاش کنید.',
provider_response_payload: {
error: error?.message || 'fetch failed',
cause: error?.cause || null,
},
sent_at: new Date().toISOString(),
received_at: new Date().toISOString(),
}
}
private async runProviderCall(fn: () => Promise<any>) {
try {
return await fn()
} catch (error: any) {
return this.mapProviderError(error)
}
}
async originalSend( async originalSend(
posId: string, posId: string,
invoice_id: string, invoice_id: string,
): Promise<TspProviderActionResponseDto> { ): Promise<TspProviderActionResponseDto> {
const payload = await buildPayload(this.prisma, invoice_id, posId) const payload = await buildOriginalPayload(this.prisma, invoice_id, posId)
const attemptNumber = await getOriginalResendAttemptNumber(this.prisma, invoice_id) const attemptNumber = await getOriginalResendAttemptNumber(this.prisma, invoice_id)
console.log('attemptNumber', attemptNumber)
const attempt = await this.prisma.saleInvoiceTspAttempts.create({ const attempt = await this.prisma.saleInvoiceTspAttempts.create({
data: { data: {
attempt_no: attemptNumber, attempt_no: attemptNumber,
invoice_id, invoice_id,
provider_request_payload: {},
status: TspProviderResponseStatus.QUEUED, status: TspProviderResponseStatus.QUEUED,
raw_request_payload: JSON.parse(JSON.stringify(payload)), raw_request_payload: JSON.parse(JSON.stringify(payload)),
sent_at: new Date().toISOString(),
message: 'در حال ارسال به سامانه مالیاتی...', message: 'در حال ارسال به سامانه مالیاتی...',
}, },
}) })
const result = await this.runProviderCall(() => const result = await trySend(this.tspSwitchService, payload)
trySend(this.tspSwitchService, payload),
)
if (result?.hasError) {
result.provider_request_payload =
result.provider_request_payload || JSON.parse(JSON.stringify(payload))
result.sent_at = result.sent_at || new Date().toISOString()
result.received_at = result.received_at || new Date().toISOString()
}
return await onResult(this.prisma, result, attempt.id) return await onResult(this.prisma, result, attempt.id)
} }
@@ -206,8 +152,6 @@ export class SalesInvoiceTspService {
business_activity.partner_token, business_activity.partner_token,
) )
console.log('getResult', result)
if (!result) { if (!result) {
throw new NotFoundException('نتیجه ارسال فاکتور یافت نشد.') throw new NotFoundException('نتیجه ارسال فاکتور یافت نشد.')
} }
@@ -217,7 +161,7 @@ export class SalesInvoiceTspService {
id: attempt.id, id: attempt.id,
}, },
data: { data: {
provider_response_payload: JSON.parse(JSON.stringify(result)), provider_response: JSON.parse(JSON.stringify(result)),
status: result.status, status: result.status,
received_at: result.received_at, received_at: result.received_at,
}, },
@@ -309,6 +253,7 @@ export class SalesInvoiceTspService {
status: TspProviderResponseStatus.QUEUED, status: TspProviderResponseStatus.QUEUED,
sent_at: new Date().toISOString(), sent_at: new Date().toISOString(),
raw_request_payload: JSON.parse(JSON.stringify(correctionPayload)), raw_request_payload: JSON.parse(JSON.stringify(correctionPayload)),
provider_request_payload: {},
}, },
}) })
@@ -326,8 +271,6 @@ export class SalesInvoiceTspService {
result.received_at = result.received_at || new Date().toISOString() result.received_at = result.received_at || new Date().toISOString()
} }
console.log('sendResult')
console.log(result)
return onResult(this.prisma, result, attempt.id) return onResult(this.prisma, result, attempt.id)
// const countByGoodId = (goodIds: string[]): Map<string, number> => { // const countByGoodId = (goodIds: string[]): Map<string, number> => {
@@ -505,6 +448,7 @@ export class SalesInvoiceTspService {
message: 'در حال ارسال به سامانه مالیاتی...', message: 'در حال ارسال به سامانه مالیاتی...',
status: TspProviderResponseStatus.QUEUED, status: TspProviderResponseStatus.QUEUED,
raw_request_payload: JSON.parse(JSON.stringify(payload)), raw_request_payload: JSON.parse(JSON.stringify(payload)),
provider_request_payload: {},
}, },
}) })
@@ -524,4 +468,28 @@ export class SalesInvoiceTspService {
return await onResult(this.prisma, result, attempt.id) return await onResult(this.prisma, result, attempt.id)
} }
private mapProviderError(error: any) {
return {
hasError: true,
status: error.status || TspProviderResponseStatus.FAILURE,
message:
error.message?.toString() ||
'خطا در ارتباط با سامانه مالیاتی. لطفا مجددا تلاش کنید.',
provider_response_payload: error.provider_response_payload || {
error: error?.message || 'fetch failed',
cause: error?.cause || null,
},
sent_at: error.sent_at || new Date().toISOString(),
received_at: error.received_at || new Date().toISOString(),
}
}
private async runProviderCall(fn: () => Promise<any>) {
try {
return await fn()
} catch (error: any) {
return this.mapProviderError(error)
}
}
} }
@@ -0,0 +1,257 @@
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
IsArray,
IsNumber,
IsOptional,
IsString,
Min,
ValidateNested,
} from 'class-validator'
export enum NamaProviderResponseStatus {
POSTED = 'POSTED',
PENDING = 'PENDING',
IN_PROGRESS = 'IN_PROGRESS',
SUCCESS = 'SUCCESS',
VALIDATION_ERROR = 'VALIDATION_ERROR',
FAILED = 'FAILED',
}
export class NamaProviderPaymentInfoDto {
@ApiProperty({ required: true, description: 'روش پرداخت با توجه به PaymentMethodType' })
@IsNumber()
pmt: number
@ApiProperty({
required: true,
description: 'مبلغ پرداختی. در صورتی که روش تسویه نسیه باشد برابر با ۰ است',
})
@IsNumber({ allowInfinity: false, allowNaN: false })
@Min(0)
pv: number
@ApiProperty({ required: false, description: 'شماره‌ی پیگیری' })
@IsOptional()
@IsString()
trn?: string
@ApiProperty({ required: false, description: 'شماره‌ی کارت پرداخت کننده‌ی صورت‌حساب' })
@IsOptional()
@IsString()
pcn?: string
@ApiProperty({ required: false, description: 'تاریخ و زمان پرداخت صورت‌حساب unix' })
@IsOptional()
@IsNumber()
pdt?: string
}
export class NamaProviderCommonHeaderDto {
@ApiProperty({ required: true, description: 'الگوی صورتحساب' })
@IsString()
inp: string
@ApiProperty({ required: true, description: 'نوع صورتحساب' })
@IsString()
inty: string
@ApiProperty({ required: true, description: 'سریال صورتحساب داخلی حافظه مالیاتی' })
@IsString()
inno: string
// @ApiProperty({ required: true })
// @IsString()
// tins: string
@ApiProperty({
required: true,
description: 'تاریخ و زمان صدور صورتحساب به صورت timestamp',
})
@IsString()
indatim: string
@ApiProperty({ required: true, description: 'نام مشتری' })
@IsString()
name: string
@ApiProperty({
required: false,
description:
'نوع شخصیت خریدار (در صورتی‌که خریدار نوع ۲ باشه باید ۱ یا ۲ گذاشته بشه)',
})
@IsString()
tob: string
@ApiProperty({ description: 'آدرس' })
@IsOptional()
@IsString()
address?: string
@ApiProperty({ description: 'شماره موبایل' })
@IsOptional()
@IsString()
mobile?: string
@ApiProperty({
description: `شماره ملی / شناسه ملی / شناسه مشارکت مدنی / کد فراگیر خریدار`,
})
@IsString()
bid: string
@ApiProperty({ required: true, description: 'روش تسویه (۱.نقدی، ۲.نسیه، ۳.نقدی-نسیه)' })
@IsString()
setm: '1' | '2' | '3'
@ApiProperty({ description: 'سهم پرداخت نقدی در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
cap: string
@ApiProperty({ description: 'سهم پرداخت نسیه در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
insp: string
}
export class NamaProviderCommonBodyDto {
@ApiProperty({ required: true, description: 'شناسه کالا / خدمت' })
@IsString()
sstid: string
@ApiProperty({
required: true,
description: `نرخ مالیات بر ارزش افزوده`,
})
@IsString()
vra: string
// @ApiProperty()
// @IsString()
// sstt: string
@ApiProperty({
required: true,
description: 'مبلغ واحد',
})
@IsString()
fee: string
@ApiProperty({
required: true,
description: 'مبلغ تخفیف',
})
@IsString()
dis: string
@ApiProperty({
required: true,
description: 'واحد اندازه گیری',
})
@IsString()
mu: string
@ApiProperty({
required: true,
description: 'تعداد / مقدار',
})
@IsString()
am: string
@ApiProperty({
description: ' اجرت ساخت (طلا)',
})
@IsString()
consfee: string
@ApiProperty({
description: 'حق العمل',
})
@IsString()
bros: string
@ApiProperty({
description: 'سود فروشنده',
})
@IsString()
spro: string
}
export class NamaProviderApiErrorItemDto {
@ApiProperty()
@IsString()
code: string
@ApiProperty()
@IsString()
message: string
}
export class NamaProviderTSPValidationErrorsDto {
@ApiProperty({ type: [NamaProviderApiErrorItemDto], required: false })
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderApiErrorItemDto)
error?: NamaProviderApiErrorItemDto[]
@ApiProperty({ type: [NamaProviderApiErrorItemDto], required: false })
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderApiErrorItemDto)
warning?: NamaProviderApiErrorItemDto[]
}
export class NamaProviderValidationErrorDto {
@IsString()
key: string
@IsString()
errorKeyPosition: string
@IsString()
message: string
@IsNumber()
errorKeyIndex: number
}
export class NamaProviderResponseDto {
@ApiProperty({ description: 'شناسه پیگیری فاکتور' })
@IsString()
uuid: string
@ApiProperty()
@IsString()
message: string
@ApiProperty()
@IsString()
status: NamaProviderResponseStatus
@ApiProperty()
@IsString()
inno: string
@ApiProperty({ required: true })
@IsString()
reference_number: string
@ApiProperty()
@IsString()
@IsOptional()
tax_id?: string
@ApiProperty()
@IsString()
@IsOptional()
error_message: string
@ApiProperty({ type: [NamaProviderValidationErrorDto] })
@IsArray()
@IsOptional()
validation_error: NamaProviderValidationErrorDto[]
@ApiProperty({ type: [NamaProviderTSPValidationErrorsDto], required: false })
@IsOptional()
tax_api_response?: NamaProviderTSPValidationErrorsDto[]
}
@@ -0,0 +1,60 @@
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import { IsArray, IsString, Length, ValidateNested } from 'class-validator'
import {
NamaProviderCommonBodyDto,
NamaProviderCommonHeaderDto,
NamaProviderPaymentInfoDto,
NamaProviderResponseDto,
} from './common.dto'
export class NamaProviderCorrectionHeaderDto extends NamaProviderCommonHeaderDto {
@ApiProperty({ required: true, description: 'موضوع صورتحساب (2- اصلاحی)' })
@IsString()
ins: '2'
@ApiProperty({
required: true,
description: 'شناسه مالیاتی صورت‌حساب مرجع',
minLength: 22,
maxLength: 22,
})
@IsString()
@Length(22, 22)
irtaxid: string
}
export class NamaProviderCorrectionBodyItemDto extends NamaProviderCommonBodyDto {}
export class NamaProviderCorrectionRequestDto {
@ApiProperty({ type: [NamaProviderCorrectionBodyItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderCorrectionBodyItemDto)
body: NamaProviderCorrectionBodyItemDto[]
@ApiProperty({ type: [NamaProviderPaymentInfoDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderPaymentInfoDto)
payment: NamaProviderPaymentInfoDto[]
@ApiProperty({ type: NamaProviderCorrectionHeaderDto })
@ValidateNested()
@Type(() => NamaProviderCorrectionHeaderDto)
header: NamaProviderCorrectionHeaderDto
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
economic_code: string
@ApiProperty()
@IsString()
fiscal_id: string
}
export class NamaProviderCorrectionResponseDto extends NamaProviderResponseDto {}
@@ -0,0 +1,11 @@
import { ApiProperty, OmitType } from '@nestjs/swagger'
import { IsString } from 'class-validator'
import { NamaProviderResponseDto } from './common.dto'
export class NamaProviderGetResponseDto extends OmitType(NamaProviderResponseDto, [
'tax_id',
]) {
@ApiProperty()
@IsString()
tax_id: string
}
@@ -0,0 +1,5 @@
export * from './common.dto'
export * from './correction.dto'
export * from './get.dto'
export * from './original.dto'
export * from './revoke.dto'
@@ -0,0 +1,50 @@
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import { IsArray, IsString, ValidateNested } from 'class-validator'
import {
NamaProviderCommonBodyDto,
NamaProviderCommonHeaderDto,
NamaProviderPaymentInfoDto,
NamaProviderResponseDto,
} from './common.dto'
export class NamaProviderOriginalHeaderDto extends NamaProviderCommonHeaderDto {
@ApiProperty({ required: true, description: 'موضوع صورتحساب (1- اصلی)' })
@IsString()
ins: '1'
}
export class NamaProviderOriginalBodyItemDto extends NamaProviderCommonBodyDto {}
export class NamaProviderOriginalRequestDto {
@ApiProperty({ type: [NamaProviderOriginalBodyItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderOriginalBodyItemDto)
body: NamaProviderOriginalBodyItemDto[]
@ApiProperty({ type: [NamaProviderPaymentInfoDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderPaymentInfoDto)
payment: NamaProviderPaymentInfoDto[]
@ApiProperty({ type: NamaProviderOriginalHeaderDto })
@ValidateNested()
@Type(() => NamaProviderOriginalHeaderDto)
header: NamaProviderOriginalHeaderDto
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
economic_code: string
@ApiProperty()
@IsString()
fiscal_id: string
}
export class NamaProviderOriginalResponseDto extends NamaProviderResponseDto {}
@@ -0,0 +1,54 @@
import { ApiProperty, OmitType } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import { IsString, ValidateNested } from 'class-validator'
import { NamaProviderResponseDto } from './common.dto'
export class NamaProviderRevokeHeaderDto {
@ApiProperty({ required: true, description: 'موضوع صورتحساب (3- ابطالی)' })
@IsString()
ins: '3'
@ApiProperty({ required: true, description: 'سریال صورتحساب داخلی حافظه مالیاتی' })
@IsString()
inno: string
@ApiProperty({
required: true,
description: 'تاریخ و زمان صدور صورتحساب به صورت timestamp',
})
@IsString()
indatim: string
@ApiProperty({
required: true,
description: 'آخرین شماره مالیاتی دریافت شده مربوط به فاکتور',
})
@IsString()
irtaxid: string
}
export class NamaProviderRevokeRequestDto {
@ApiProperty({ type: NamaProviderRevokeHeaderDto })
@ValidateNested()
@Type(() => NamaProviderRevokeHeaderDto)
header: NamaProviderRevokeHeaderDto
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
economic_code: string
@ApiProperty()
@IsString()
fiscal_id: string
}
export class NamaProviderRevokeResponseDto extends OmitType(NamaProviderResponseDto, [
'tax_id',
]) {
@ApiProperty()
@IsString()
tax_id: string
}
@@ -7,23 +7,25 @@ import { HttpClientUtil } from '@/common/utils/http-client.util'
import { TspProviderResponseStatus } from '@/generated/prisma/enums' import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import { Injectable, Logger } from '@nestjs/common' import { Injectable, Logger } from '@nestjs/common'
import { import {
IProviderSwitchAdapter,
TspProviderBulkSendResultDto,
TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendPayloadDto,
TspProviderCorrectionSendResponseDto, TspProviderCorrectionSendResponseDto,
TspProviderGetResultDto, TspProviderGetResultDto,
TspProviderOriginalSendItemResultDto,
TspProviderOriginalSendPayloadDto, TspProviderOriginalSendPayloadDto,
TspProviderRevokePayloadDto, TspProviderRevokePayloadDto,
TspProviderRevokeResponseDto, TspProviderRevokeResponseDto,
TspProviderSendItemResultDto, } from '../../dto'
import {
IProviderSwitchAdapter,
TspProviderBulkSendResultDto,
} from '../../dto/provider-switch.dto' } from '../../dto/provider-switch.dto'
import { import {
NamaProviderGetResponseDto, NamaProviderGetResponseDto,
NamaProviderOriginalResponseDto,
NamaProviderResponseStatus, NamaProviderResponseStatus,
NamaProviderRevokeRequestDto, NamaProviderRevokeRequestDto,
NamaProviderRevokeResponseDto, NamaProviderRevokeResponseDto,
NamaProviderSendItemResponseDto, } from './dto'
} from './nama-provider.dto'
import { NamaProviderUtils } from './nama-provider.util' import { NamaProviderUtils } from './nama-provider.util'
@Injectable() @Injectable()
@@ -77,8 +79,8 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
async originalSend( async originalSend(
payload: TspProviderOriginalSendPayloadDto, payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto> { ): Promise<TspProviderOriginalSendItemResultDto> {
const mappedRequest = this.namaProviderUtils.mapToNamaRequestDto(payload) const mappedRequest = this.namaProviderUtils.mapToNamaOriginalRequestDto(payload)
try { try {
const response = await this.httpClient.request( const response = await this.httpClient.request(
this.buildSendUrl(), this.buildSendUrl(),
@@ -86,20 +88,23 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
method: 'POST', method: 'POST',
body: JSON.stringify(mappedRequest), body: JSON.stringify(mappedRequest),
}, },
this.createRequestInterceptors(payload.tsp_token), this.createRequestInterceptors(payload.token),
) )
const providerResponse: NamaProviderSendItemResponseDto = await response.json() const providerResponse: NamaProviderOriginalResponseDto = await response.json()
this.logger.debug('NAMA provider response', providerResponse) this.logger.debug('NAMA provider response', response)
this.logger.debug('NAMA provider providerResponse', providerResponse)
const result: TspProviderSendItemResultDto = { const result: TspProviderOriginalSendItemResultDto = {
invoice_id: payload.invoice_id, invoice_id: payload.id,
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
hasError: !response.ok, hasError: !response.ok,
message: providerResponse.message, message: providerResponse.message,
provider_response_payload: JSON.parse(JSON.stringify(providerResponse)), received_at: new Date().toISOString(),
received_at: providerResponse.tsp_update_time, provider_response: JSON.parse(JSON.stringify(providerResponse)),
sent_at: new Date().toISOString(),
tax_id: providerResponse.tax_id, 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( status: this.namaProviderUtils.mapResponseStatus(
providerResponse.status as NamaProviderResponseStatus, providerResponse.status as NamaProviderResponseStatus,
), ),
@@ -108,24 +113,22 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
return result return result
} catch (err) { } catch (err) {
this.logger.error('NAMA send failed', err) this.logger.error('NAMA send failed', err)
const failure: TspProviderSendItemResultDto = { const failure: TspProviderOriginalSendItemResultDto = {
invoice_id: payload.invoice_id, invoice_id: payload.id,
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
hasError: true, hasError: true,
message: (err as Error).message, message: (err as Error).message,
sent_at: new Date().toISOString(),
received_at: new Date().toISOString(), received_at: new Date().toISOString(),
tax_id: null, status: TspProviderResponseStatus.SEND_FAILURE,
status: TspProviderResponseStatus.NOT_SEND,
} }
throw failure return failure
} }
} }
async correctionSend( async correctionSend(
payload: TspProviderCorrectionSendPayloadDto, payload: TspProviderCorrectionSendPayloadDto,
): Promise<TspProviderCorrectionSendResponseDto> { ): Promise<TspProviderCorrectionSendResponseDto> {
const mappedRequest = this.namaProviderUtils.mapToNamaRequestDto(payload) const mappedRequest = this.namaProviderUtils.mapToNamaOriginalRequestDto(payload)
try { try {
const response = await this.httpClient.request( const response = await this.httpClient.request(
@@ -134,19 +137,18 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
method: 'POST', method: 'POST',
body: JSON.stringify(mappedRequest), body: JSON.stringify(mappedRequest),
}, },
this.createRequestInterceptors(payload.tsp_token), this.createRequestInterceptors(payload.token),
) )
const providerResponse: NamaProviderSendItemResponseDto = await response.json() const providerResponse: NamaProviderOriginalResponseDto = await response.json()
this.logger.debug('NAMA provider response', providerResponse) this.logger.debug('NAMA provider response', providerResponse)
const result: TspProviderSendItemResultDto = { const result: TspProviderOriginalSendItemResultDto = {
invoice_id: payload.invoice_id, invoice_id: payload.id,
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
hasError: !response.ok, hasError: !response.ok,
message: providerResponse.message, message: providerResponse.message,
sent_at: new Date().toISOString(), provider_response: JSON.parse(JSON.stringify(providerResponse)),
provider_response_payload: JSON.parse(JSON.stringify(providerResponse)), received_at: new Date().toISOString(),
received_at: providerResponse.tsp_update_time,
tax_id: providerResponse.tax_id, tax_id: providerResponse.tax_id,
status: this.namaProviderUtils.mapResponseStatus( status: this.namaProviderUtils.mapResponseStatus(
providerResponse.status as NamaProviderResponseStatus, providerResponse.status as NamaProviderResponseStatus,
@@ -156,12 +158,11 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
return result return result
} catch (err) { } catch (err) {
this.logger.error('NAMA send failed', err) this.logger.error('NAMA send failed', err)
const failure: TspProviderSendItemResultDto = { const failure: TspProviderOriginalSendItemResultDto = {
invoice_id: payload.invoice_id, invoice_id: payload.id,
provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)), provider_request_payload: JSON.parse(JSON.stringify(mappedRequest)),
hasError: true, hasError: true,
message: (err as Error).message, message: (err as Error).message,
sent_at: new Date().toISOString(),
received_at: new Date().toISOString(), received_at: new Date().toISOString(),
tax_id: null, tax_id: null,
status: TspProviderResponseStatus.NOT_SEND, status: TspProviderResponseStatus.NOT_SEND,
@@ -177,7 +178,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
for (const payload of payloads) { for (const payload of payloads) {
const itemResults = await this.originalSend(payload) const itemResults = await this.originalSend(payload)
result.push({ result.push({
invoice_id: payload.invoice_id, invoice_id: payload.id,
items: [itemResults], items: [itemResults],
}) })
} }
@@ -201,7 +202,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
message: providerResponse.message, message: providerResponse.message,
provider_response_payload: providerResponse, provider_response_payload: providerResponse,
sent_at: new Date().toISOString(), sent_at: new Date().toISOString(),
received_at: providerResponse.tsp_update_time || new Date().toISOString(), received_at: new Date().toISOString(),
tax_id: providerResponse.tax_id, tax_id: providerResponse.tax_id,
status: this.namaProviderUtils.mapResponseStatus( status: this.namaProviderUtils.mapResponseStatus(
providerResponse.status as NamaProviderResponseStatus, providerResponse.status as NamaProviderResponseStatus,
@@ -228,7 +229,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
payload: TspProviderRevokePayloadDto, payload: TspProviderRevokePayloadDto,
): Promise<TspProviderRevokeResponseDto> { ): Promise<TspProviderRevokeResponseDto> {
const mappedRequest: NamaProviderRevokeRequestDto = const mappedRequest: NamaProviderRevokeRequestDto =
this.namaProviderUtils.mapRevokeToNamaRequestDto(payload) this.namaProviderUtils.mapToNamaRevokeRequestDto(payload)
this.logger.debug('NAMA provider response', mappedRequest) this.logger.debug('NAMA provider response', mappedRequest)
@@ -251,7 +252,7 @@ export class NamaProviderSwitchAdapter implements IProviderSwitchAdapter {
message: providerResponse.message, message: providerResponse.message,
sent_at: new Date().toISOString(), sent_at: new Date().toISOString(),
provider_response_payload: providerResponse, provider_response_payload: providerResponse,
received_at: providerResponse.tsp_update_time, received_at: new Date().toISOString(),
tax_id: providerResponse.tax_id, tax_id: providerResponse.tax_id,
status: this.namaProviderUtils.mapResponseStatus( status: this.namaProviderUtils.mapResponseStatus(
providerResponse.status as NamaProviderResponseStatus, providerResponse.status as NamaProviderResponseStatus,
@@ -1,561 +0,0 @@
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import { ApiProperty } from '@nestjs/swagger'
import { Type } from 'class-transformer'
import {
IsArray,
IsEnum,
IsNumber,
IsOptional,
IsString,
Min,
ValidateNested,
} from 'class-validator'
export enum NamaProviderResponseStatus {
POSTED = 'SUCCESS',
PENDING = 'PENDING',
IN_PROGRESS = 'IN_PROGRESS',
SUCCESS = 'SUCCESS',
FAILED = 'FAILED',
}
export class NamaProviderPaymentInfoDto {
@ApiProperty({ required: true, description: 'روش پرداخت' })
@IsNumber()
pmt: number
@ApiProperty({ required: true, description: 'مبلغ پرداختی' })
@IsNumber()
@Min(10_000)
pv: number
@ApiProperty({ required: false, description: 'شماره‌ی پیگیری' })
@IsOptional()
@IsString()
trn?: string
@ApiProperty({ required: false, description: 'شماره‌ی کارت پرداخت کننده‌ی صورت‌حساب' })
@IsOptional()
@IsString()
pcn?: string
@ApiProperty({ required: false, description: 'تاریخ و زمان پرداخت صورت‌حساب unix' })
@IsOptional()
@IsNumber()
pdt?: string
}
export class NamaProviderBodyItemDto {
@ApiProperty({ required: true, description: 'شناسه کالا / خدمت' })
@IsString()
sstid: string
@ApiProperty({
required: true,
description: `نرخ مالیات بر ارزش افزوده`,
})
@IsString()
vra: string
// @ApiProperty()
// @IsString()
// sstt: string
@ApiProperty({
required: true,
description: 'مبلغ واحد',
})
@IsString()
fee: string
@ApiProperty({
required: true,
description: 'مبلغ تخفیف',
})
@IsString()
dis: string
@ApiProperty({
required: true,
description: 'واحد اندازه گیری',
})
@IsString()
mu: string
@ApiProperty({
required: true,
description: 'تعداد / مقدار',
})
@IsString()
am: string
@ApiProperty({
description: ' اجرت ساخت (طلا)',
})
@IsString()
consfee: string
@ApiProperty({
description: 'حق العمل',
})
@IsString()
bros: string
@ApiProperty({
description: 'سود فروشنده',
})
@IsString()
spro: string
}
export class NamaProviderHeaderDto {
@ApiProperty({ required: true, description: 'موضوع صورتحساب' })
@IsString()
ins: string
@ApiProperty({ required: true, description: 'الگوی صورتحساب' })
@IsString()
inp: string
@ApiProperty({ required: true, description: 'نوع صورتحساب' })
@IsString()
inty: string
// @ApiProperty({required: true})
// @IsString()
// unique_tax_code: string
@ApiProperty({ required: true, description: 'سریال صورتحساب داخلی حافظه مالیاتی' })
@IsString()
inno: string
// @ApiProperty({ required: true })
// @IsString()
// tins: string
@ApiProperty({
required: true,
description: 'تاریخ و زمان صدور صورتحساب به صورت timestamp',
})
@IsString()
indatim: string
@ApiProperty({ required: true, description: 'نام مشتری' })
@IsString()
name: string
@ApiProperty({
required: false,
description:
'نوع شخصیت خریدار (در صورتی‌که خریدار نوع ۲ باشه باید ۱ یا ۲ گذاشته بشه)',
})
@IsString()
tob: string
@ApiProperty({ description: 'آدرس' })
@IsOptional()
@IsString()
address?: string
@ApiProperty({ description: 'شماره موبایل' })
@IsOptional()
@IsString()
mobile?: string
@ApiProperty({
description: `شماره ملی / شناسه ملی / شناسه مشارکت مدنی / کد فراگیر خریدار`,
})
@IsString()
bid: string
@ApiProperty({ required: true, description: 'روش تسویه (۱.نقدی، ۲.نسیه، ۳.نقدی-نسیه)' })
@IsString()
setm: '1' | '2' | '3'
@ApiProperty({ description: 'سهم پرداخت نقدی در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
cap: string
@ApiProperty({ description: 'سهم پرداخت نسیه در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
insp: string
}
export class NamaProviderRequestDto {
@ApiProperty({ type: [NamaProviderBodyItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderBodyItemDto)
body: NamaProviderBodyItemDto[]
@ApiProperty({ type: [NamaProviderPaymentInfoDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderPaymentInfoDto)
payment: NamaProviderPaymentInfoDto[]
@ApiProperty({ type: NamaProviderHeaderDto })
@ValidateNested()
@Type(() => NamaProviderHeaderDto)
header: NamaProviderHeaderDto
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
economic_code: string
@ApiProperty()
@IsString()
fiscal_id: string
}
export class NamaProviderApiErrorItemDto {
@ApiProperty()
@IsString()
code: string
@ApiProperty()
@IsString()
message: string
}
export class NamaProviderApiErrorResponseDto {
@ApiProperty({ type: [NamaProviderApiErrorItemDto], required: false })
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderApiErrorItemDto)
error?: NamaProviderApiErrorItemDto
}
export class NamaProviderSendItemResponseDto {
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
message: string
@ApiProperty()
@IsString()
status: NamaProviderResponseStatus
@ApiProperty()
@IsString()
tax_id: string
@ApiProperty()
@IsString()
inno: string
@ApiProperty({ required: true })
@IsString()
reference_number: string
@ApiProperty({ type: () => NamaProviderApiErrorResponseDto, required: false })
@IsOptional()
@ValidateNested()
@Type(() => NamaProviderApiErrorResponseDto)
tax_api_response?: NamaProviderApiErrorResponseDto
@ApiProperty({ required: false })
@IsOptional()
@IsString()
tsp_update_time: string
}
export class NamaProviderGetResponseDto {
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
message: string
@ApiProperty({ enum: TspProviderResponseStatus })
@IsEnum(TspProviderResponseStatus)
status: TspProviderResponseStatus
@ApiProperty()
@IsString()
tax_id: string
@ApiProperty()
@IsString()
inno: string
@ApiProperty()
@IsString()
reference_number: string
@ApiProperty()
@IsString()
tsp_update_time: string
}
export class NamaProviderRevokeHeaderDto {
@ApiProperty({ required: true, description: 'موضوع صورتحساب' })
@IsString()
ins: string
@ApiProperty({ required: true, description: 'سریال صورتحساب داخلی حافظه مالیاتی' })
@IsString()
inno: string
@ApiProperty({
required: true,
description: 'تاریخ و زمان صدور صورتحساب به صورت timestamp',
})
@IsString()
indatim: string
@ApiProperty({
required: true,
description: 'آخرین شماره مالیاتی دریافت شده مربوط به فاکتور',
})
@IsString()
irtaxid: string
}
export class NamaProviderRevokeRequestDto {
// @ApiProperty({ type: [NamaProviderBodyItemDto] })
// @IsArray()
// @ValidateNested({ each: true })
// @Type(() => NamaProviderBodyItemDto)
// body: NamaProviderBodyItemDto[]
// @ApiProperty({ type: [NamaProviderPaymentInfoDto] })
// @IsArray()
// @ValidateNested({ each: true })
// @Type(() => NamaProviderPaymentInfoDto)
// payment: NamaProviderPaymentInfoDto[]
// @ApiProperty({ type: Object, required: true })
// @IsObject()
// body: {}
@ApiProperty({ type: NamaProviderRevokeHeaderDto })
@ValidateNested()
@Type(() => NamaProviderRevokeHeaderDto)
header: NamaProviderRevokeHeaderDto
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
economic_code: string
@ApiProperty()
@IsString()
fiscal_id: string
}
export class NamaProviderRevokeResponseDto {
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
message: string
@ApiProperty()
@IsString()
status: NamaProviderResponseStatus
@ApiProperty()
@IsString()
tax_id: string
@ApiProperty()
@IsString()
inno: string
@ApiProperty({ required: true })
@IsString()
reference_number: string
@ApiProperty({ type: () => NamaProviderApiErrorResponseDto, required: false })
@IsOptional()
@ValidateNested()
@Type(() => NamaProviderApiErrorResponseDto)
tax_api_response?: NamaProviderApiErrorResponseDto
@ApiProperty({ required: false })
@IsOptional()
@IsString()
tsp_update_time: string
}
/////////////// Correction DTOs ///////////////
export class NamaProviderCorrectionBodyItemDto {
@ApiProperty({ required: true, description: 'شناسه کالا / خدمت' })
@IsString()
sstid: string
@ApiProperty({
required: true,
description: `نرخ مالیات بر ارزش افزوده`,
})
@IsString()
vra: string
// @ApiProperty()
// @IsString()
// sstt: string
@ApiProperty({
required: true,
description: 'مبلغ واحد',
})
@IsString()
fee: string
@ApiProperty({
required: true,
description: 'مبلغ تخفیف',
})
@IsString()
dis: string
@ApiProperty({
required: true,
description: 'واحد اندازه گیری',
})
@IsString()
mu: string
@ApiProperty({
required: true,
description: 'تعداد / مقدار',
})
@IsString()
am: string
@ApiProperty({
description: ' اجرت ساخت (طلا)',
})
@IsString()
consfee: string
@ApiProperty({
description: 'حق العمل',
})
@IsString()
bros: string
@ApiProperty({
description: 'سود فروشنده',
})
@IsString()
spro: string
}
export class NamaProviderCorrectionHeaderDto {
@ApiProperty({ required: true, description: 'موضوع صورتحساب' })
@IsString()
ins: string
@ApiProperty({ required: true, description: 'الگوی صورتحساب' })
@IsString()
inp: string
@ApiProperty({ required: true, description: 'نوع صورتحساب' })
@IsString()
inty: string
// @ApiProperty({required: true})
// @IsString()
// unique_tax_code: string
@ApiProperty({ required: true, description: 'سریال صورتحساب داخلی حافظه مالیاتی' })
@IsString()
inno: string
// @ApiProperty({ required: true })
// @IsString()
// tins: string
@ApiProperty({
required: true,
description: 'تاریخ و زمان صدور صورتحساب به صورت timestamp',
})
@IsString()
indatim: string
@ApiProperty({ required: true, description: 'نام مشتری' })
@IsString()
name: string
@ApiProperty({
required: false,
description:
'نوع شخصیت خریدار (در صورتی‌که خریدار نوع ۲ باشه باید ۱ یا ۲ گذاشته بشه)',
})
@IsString()
tob: string
@ApiProperty({ description: 'آدرس' })
@IsOptional()
@IsString()
address?: string
@ApiProperty({ description: 'شماره موبایل' })
@IsOptional()
@IsString()
mobile?: string
@ApiProperty({
description: `شماره ملی / شناسه ملی / شناسه مشارکت مدنی / کد فراگیر خریدار`,
})
@IsString()
bid: string
@ApiProperty({ required: true, description: 'روش تسویه (۱.نقدی، ۲.نسیه، ۳.نقدی-نسیه)' })
@IsString()
setm: '1' | '2' | '3'
@ApiProperty({ description: 'سهم پرداخت نقدی در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
cap: string
@ApiProperty({ description: 'سهم پرداخت نسیه در صورتی که نقدی - نسیه باشد (۳)' })
@IsString()
insp: string
}
export class NamaProviderCorrectionRequestDto {
@ApiProperty({ type: [NamaProviderCorrectionBodyItemDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderCorrectionBodyItemDto)
body: NamaProviderCorrectionBodyItemDto[]
@ApiProperty({ type: [NamaProviderPaymentInfoDto] })
@IsArray()
@ValidateNested({ each: true })
@Type(() => NamaProviderPaymentInfoDto)
payment: NamaProviderPaymentInfoDto[]
@ApiProperty({ type: NamaProviderCorrectionHeaderDto })
@ValidateNested()
@Type(() => NamaProviderCorrectionHeaderDto)
header: NamaProviderCorrectionHeaderDto
@ApiProperty()
@IsString()
uuid: string
@ApiProperty()
@IsString()
economic_code: string
@ApiProperty()
@IsString()
fiscal_id: string
}
@@ -13,45 +13,45 @@ import {
TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendPayloadDto,
TspProviderOriginalSendPayloadDto, TspProviderOriginalSendPayloadDto,
TspProviderRevokePayloadDto, TspProviderRevokePayloadDto,
} from '../../dto/provider-switch.dto' } from '../../dto'
import { import {
NamaProviderCorrectionRequestDto, NamaProviderCorrectionRequestDto,
NamaProviderOriginalRequestDto,
NamaProviderPaymentInfoDto, NamaProviderPaymentInfoDto,
NamaProviderRequestDto,
NamaProviderResponseStatus, NamaProviderResponseStatus,
NamaProviderRevokeRequestDto, NamaProviderRevokeRequestDto,
} from './nama-provider.dto' } from './dto'
export class NamaProviderUtils { export class NamaProviderUtils {
mapResponseStatus(status: NamaProviderResponseStatus): TspProviderResponseStatus { mapResponseStatus(status: NamaProviderResponseStatus): TspProviderResponseStatus {
console.log('NAMA status', status) console.log('NAMA status', status)
switch (status.toUpperCase()) { switch (status.toUpperCase()) {
case NamaProviderResponseStatus.SUCCESS:
case NamaProviderResponseStatus.POSTED: case NamaProviderResponseStatus.POSTED:
return TspProviderResponseStatus.FISCAL_QUEUED
case NamaProviderResponseStatus.SUCCESS:
return TspProviderResponseStatus.SUCCESS return TspProviderResponseStatus.SUCCESS
case NamaProviderResponseStatus.PENDING:
case NamaProviderResponseStatus.IN_PROGRESS:
return TspProviderResponseStatus.QUEUED
case NamaProviderResponseStatus.FAILED: case NamaProviderResponseStatus.FAILED:
return TspProviderResponseStatus.FAILURE return TspProviderResponseStatus.FAILURE
case NamaProviderResponseStatus.PENDING:
case NamaProviderResponseStatus.IN_PROGRESS:
default: default:
return TspProviderResponseStatus.QUEUED return TspProviderResponseStatus.QUEUED
} }
} }
mapToNamaRequestDto( mapToNamaOriginalRequestDto(
payload: TspProviderOriginalSendPayloadDto, payload: TspProviderOriginalSendPayloadDto,
): NamaProviderRequestDto { ): NamaProviderOriginalRequestDto {
return { return {
uuid: payload.invoice_id, uuid: payload.id,
economic_code: payload.economic_code, economic_code: payload.economic_code,
fiscal_id: payload.fiscal_id, fiscal_id: payload.fiscal_id,
payment: this.mapPayments(payload.payments), payment: this.mapPayments(payload.payments),
header: { header: {
ins: this.mapTspProviderRequestType(payload.type), ins: '1',
inp: this.mapInvoiceTemplate(payload.invoice_template), inp: this.mapInvoiceTemplate(payload.template),
inty: this.mapTspProviderCustomerType(payload.customer_type), inty: this.mapTspProviderCustomerType(payload.customer?.type),
inno: payload.invoice_number.toString(), inno: payload.invoice_number.toString(),
tins: '', tins: '',
indatim: payload.invoice_date.getTime() + '', indatim: payload.invoice_date.getTime() + '',
@@ -81,14 +81,14 @@ export class NamaProviderUtils {
payload: TspProviderCorrectionSendPayloadDto, payload: TspProviderCorrectionSendPayloadDto,
): NamaProviderCorrectionRequestDto { ): NamaProviderCorrectionRequestDto {
return { return {
uuid: payload.invoice_id, uuid: payload.id,
economic_code: payload.economic_code, economic_code: payload.economic_code,
fiscal_id: payload.fiscal_id, fiscal_id: payload.fiscal_id,
payment: this.mapPayments(payload.payments), payment: this.mapPayments(payload.payments),
header: { header: {
ins: this.mapTspProviderRequestType(TspProviderRequestType.CORRECTION), ins: this.mapRequestType(TspProviderRequestType.CORRECTION),
inp: this.mapInvoiceTemplate(payload.invoice_template), inp: this.mapInvoiceTemplate(payload.template),
inty: this.mapTspProviderCustomerType(payload.customer_type), inty: this.mapTspProviderCustomerType(payload.customer?.type),
inno: payload.invoice_number.toString(), inno: payload.invoice_number.toString(),
tins: '', tins: '',
indatim: payload.invoice_date.getTime() + '', indatim: payload.invoice_date.getTime() + '',
@@ -110,7 +110,7 @@ export class NamaProviderUtils {
} }
} }
mapRevokeToNamaRequestDto( mapToNamaRevokeRequestDto(
payload: TspProviderRevokePayloadDto, payload: TspProviderRevokePayloadDto,
): NamaProviderRevokeRequestDto { ): NamaProviderRevokeRequestDto {
return { return {
@@ -119,14 +119,14 @@ export class NamaProviderUtils {
fiscal_id: payload.fiscal_id, fiscal_id: payload.fiscal_id,
header: { header: {
inno: payload.invoice_number.toString(), inno: payload.invoice_number.toString(),
ins: this.mapTspProviderRequestType(TspProviderRequestType.REVOKE), ins: '3',
irtaxid: payload.last_tax_id, irtaxid: payload.last_tax_id,
indatim: new Date().getTime() + '', indatim: new Date().getTime() + '',
}, },
} }
} }
private mapTspProviderRequestType(type: TspProviderRequestType) { private mapRequestType(type: TspProviderRequestType) {
switch (type) { switch (type) {
case TspProviderRequestType.ORIGINAL: case TspProviderRequestType.ORIGINAL:
return '1' return '1'
@@ -206,9 +206,9 @@ export class NamaProviderUtils {
case TspProviderCustomerType.KNOWN: case TspProviderCustomerType.KNOWN:
return '1' return '1'
case TspProviderCustomerType.UNKNOWN: case TspProviderCustomerType.UNKNOWN:
return '2'
default: default:
return '3' return '2'
// return '3'
} }
} }
@@ -267,8 +267,8 @@ export class NamaProviderUtils {
return payments.map(payment => ({ return payments.map(payment => ({
pmt: this.mapPaymentMethod(payment.payment_method), pmt: this.mapPaymentMethod(payment.payment_method),
pv: payment.amount, pv: payment.amount,
trn: payment.tracking_code, trn: payment.terminal_info.tracking_code,
pcn: payment.card_number, pcn: payment.terminal_info.card_number,
pdt: payment.paid_at ? String(payment.paid_at.getTime()) : undefined, pdt: payment.paid_at ? String(payment.paid_at.getTime()) : undefined,
})) }))
} }
@@ -1,18 +1,18 @@
import { SaleInvoiceTspAttemptsUpdateInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service' import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, NotFoundException } from '@nestjs/common' import { BadRequestException, NotFoundException } from '@nestjs/common'
import { TspProviderCustomerType } from 'common/enums/enums'
import { import {
Prisma, Prisma,
TspProviderRequestType, TspProviderRequestType,
TspProviderResponseStatus, TspProviderResponseStatus,
} from 'generated/prisma/client' } from 'generated/prisma/client'
import { import {
TspProviderActionResponseDto,
TspProviderCorrectionSendPayloadDto, TspProviderCorrectionSendPayloadDto,
TspProviderOriginalSendItemResultDto,
TspProviderOriginalSendPayloadDto, TspProviderOriginalSendPayloadDto,
TspProviderRevokePayloadDto, TspProviderRevokePayloadDto,
TspProviderSendItemResultDto, } from '../dto'
} from '../dto/provider-switch.dto' import { TspProviderActionResponseDto } from '../dto/provider-switch.dto'
export async function getOriginalResendAttemptNumber( export async function getOriginalResendAttemptNumber(
prisma: PrismaService, 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( throw new BadRequestException(
'در حال حاضر فاکتور شما در حال بررسی توسط سازمان مالیاتی است.', 'در حال حاضر فاکتور شما در حال بررسی توسط سازمان مالیاتی است.',
) )
@@ -164,6 +167,7 @@ export async function buildCorrectionPayload(
invoice_date: true, invoice_date: true,
invoice_number: true, invoice_number: true,
settlement_type: true, settlement_type: true,
tax_id: true,
items: true, items: true,
pos: { pos: {
select: { select: {
@@ -207,6 +211,7 @@ export async function buildCorrectionPayload(
}, },
}, },
}, },
unknown_customer: true,
customer: { customer: {
select: { select: {
type: true, type: true,
@@ -234,6 +239,8 @@ export async function buildCorrectionPayload(
const { partner } = (invoice.pos.complex.business_activity.consumer.legal || const { partner } = (invoice.pos.complex.business_activity.consumer.legal ||
invoice.pos.complex.business_activity.consumer.individual)! invoice.pos.complex.business_activity.consumer.individual)!
const unknown_customer = (invoice.unknown_customer || {}) as Record<string, string>
return { return {
items: invoice.items.map(item => ({ items: invoice.items.map(item => ({
invoice_item_id: item.id, invoice_item_id: item.id,
@@ -253,36 +260,41 @@ export async function buildCorrectionPayload(
amount: Number(payment.amount), amount: Number(payment.amount),
payment_method: payment.payment_method, payment_method: payment.payment_method,
paid_at: payment.paid_at, paid_at: payment.paid_at,
terminal_info: {
card_number: payment.terminal_info ? payment.terminal_info.stan : undefined, card_number: payment.terminal_info ? payment.terminal_info.stan : undefined,
tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined, tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined,
},
})), })),
total_amount: Number(invoice.total_amount), total_amount: Number(invoice.total_amount),
last_tax_id: invoice.reference_invoice!.tax_id!, last_tax_id: invoice.reference_invoice!.tax_id!,
invoice_number: invoice.invoice_number, invoice_number: invoice.invoice_number,
invoice_id: invoice.id, id: invoice.id,
economic_code: invoice.pos.complex.business_activity.economic_code, economic_code: invoice.pos.complex.business_activity.economic_code,
fiscal_id: invoice.pos.complex.business_activity.fiscal_id, fiscal_id: invoice.pos.complex.business_activity.fiscal_id,
tsp_token: invoice.pos.complex.business_activity.partner_token, token: invoice.pos.complex.business_activity.partner_token,
type: TspProviderRequestType.CORRECTION,
tsp_provider: partner.tsp_provider!, 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(), invoice_date: new Date(),
settlement_type: invoice.settlement_type, settlement_type: invoice.settlement_type,
customer_type: invoice.customer?.type customer:
? TspProviderCustomerType.KNOWN invoice.customer && invoice.customer.type !== 'UNKNOWN'
: TspProviderCustomerType.UNKNOWN,
customer: invoice.customer?.type
? { ? {
type: invoice.customer.type, type: invoice.customer.type,
legal_info: invoice.customer.legal ?? undefined, legal_info: invoice.customer.legal ?? undefined,
individual_info: invoice.customer.individual ?? undefined, individual_info: invoice.customer.individual ?? undefined,
} }
: 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, prisma: PrismaService,
invoiceId: string, invoiceId: string,
posId: string, posId: string,
@@ -311,6 +323,7 @@ export async function buildPayload(
sku_vat: true, sku_vat: true,
good_id: true, good_id: true,
service_id: true, service_id: true,
discount: true,
payload: true, payload: true,
good_snapshot: true, good_snapshot: true,
}, },
@@ -357,6 +370,7 @@ export async function buildPayload(
}, },
}, },
}, },
unknown_customer: true,
customer: { customer: {
select: { select: {
type: true, type: true,
@@ -396,38 +410,48 @@ export async function buildPayload(
throw new NotFoundException('فاکتور مورد نظر یافت نشد.') throw new NotFoundException('فاکتور مورد نظر یافت نشد.')
} }
const { partner } = (invoice.pos.complex.business_activity.consumer.legal || const { pos, id, invoice_number, invoice_date, total_amount, settlement_type } = invoice
invoice.pos.complex.business_activity.consumer.individual)! 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 { return {
invoice_id: invoice.id, id,
invoice_number: invoice.invoice_number, invoice_number,
invoice_date: invoice.invoice_date, invoice_date,
total_amount: Number(invoice.total_amount), settlement_type,
economic_code: invoice.pos.complex.business_activity.economic_code, total_amount: Number(total_amount),
fiscal_id: invoice.pos.complex.business_activity.fiscal_id, economic_code: ba.economic_code,
invoice_template: invoice.pos.complex.business_activity.guild.invoice_template, fiscal_id: ba.fiscal_id,
tsp_token: invoice.pos.complex.business_activity.partner_token, template: ba.guild.invoice_template,
settlement_type: invoice.settlement_type, token: ba.partner_token,
tsp_provider: partner.tsp_provider!,
payments: invoice.payments.map(payment => ({ payments: invoice.payments.map(payment => ({
amount: Number(payment.amount), amount: Number(payment.amount),
payment_method: payment.payment_method, payment_method: payment.payment_method,
paid_at: payment.paid_at, paid_at: payment.paid_at,
terminal_info: {
card_number: payment.terminal_info ? payment.terminal_info.stan : undefined, card_number: payment.terminal_info ? payment.terminal_info.stan : undefined,
tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined, tracking_code: payment.terminal_info ? payment.terminal_info.rrn : undefined,
},
})), })),
type: TspProviderRequestType.ORIGINAL, customer:
tsp_provider: partner.tsp_provider!, invoice.customer && invoice.customer.type !== 'UNKNOWN'
customer_type: invoice.customer?.type
? TspProviderCustomerType.KNOWN
: TspProviderCustomerType.UNKNOWN,
customer: invoice.customer?.type
? { ? {
type: invoice.customer.type, type: invoice.customer.type,
legal_info: invoice.customer.legal ?? undefined, legal_info: invoice.customer.legal ?? undefined,
individual_info: invoice.customer.individual ?? undefined, individual_info: invoice.customer.individual ?? undefined,
} }
: undefined, : {
type: 'UNKNOWN',
unknown_info: {
name: unknown_customer?.name || '',
economic_code: unknown_customer?.economic_code || '',
},
},
items: invoice.items.map(item => ({ items: invoice.items.map(item => ({
invoice_item_id: item.id, invoice_item_id: item.id,
quantity: Number(item.quantity), quantity: Number(item.quantity),
@@ -449,84 +473,63 @@ export async function trySend(
tspSwitchService: { tspSwitchService: {
send( send(
payload: TspProviderOriginalSendPayloadDto, payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto | null> ): Promise<TspProviderOriginalSendItemResultDto>
}, },
payload: TspProviderOriginalSendPayloadDto, payload: TspProviderOriginalSendPayloadDto,
): Promise<TspProviderSendItemResultDto | null> { ): Promise<TspProviderOriginalSendItemResultDto> {
return (await tspSwitchService.send(payload)) || null return (await tspSwitchService.send(payload)) || null
} }
export async function onResult( export async function onResult(
prisma: PrismaService, prisma: PrismaService,
result: any, result: TspProviderOriginalSendItemResultDto,
attempt_id: string, attempt_id: string,
): Promise<TspProviderActionResponseDto> { ): Promise<TspProviderActionResponseDto> {
let attemptUpdatedData: SaleInvoiceTspAttemptsUpdateInput = {}
const resultMessage = result.message
if (result) { if (result) {
if (result.hasError) { attemptUpdatedData = {
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({ provider_request_payload: JSON.parse(
where: { JSON.stringify(result.provider_request_payload),
id: attempt_id, ),
}, provider_response: JSON.parse(JSON.stringify(result.provider_response)),
data: {
provider_request_payload: result.provider_request_payload,
provider_response_payload: JSON.parse(JSON.stringify(result)),
status: result.status, status: result.status,
sent_at: result.sent_at || new Date().toISOString(),
received_at: result.received_at || new Date().toISOString(), received_at: result.received_at || new Date().toISOString(),
message: result.message?.toString() || 'وجود مشکل در ارسال به سامانه مالیاتی', message: resultMessage
? resultMessage
: result.hasError
? 'وجود مشکل در ارسال به سامانه مالیاتی'
: 'فاکتور با موفقیت به سامانه مالیاتی ارسال شد.',
invoice: {
update: {
tax_id: result.tax_id,
}, },
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 {
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({ attemptUpdatedData = {
where: { status: TspProviderResponseStatus.SEND_FAILURE,
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,
}
}
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({
where: {
id: attempt_id,
},
data: {
provider_response_payload: {},
status: TspProviderResponseStatus.FAILURE,
message: message:
'متاسفانه امکان ارسال فاکتور به سیستم مالیاتی در حال حاضر وجود ندارد. لطفا بعدا تلاش کنید.', 'متاسفانه امکان ارسال فاکتور به سیستم مالیاتی در حال حاضر وجود ندارد. لطفا بعدا تلاش کنید.',
received_at: new Date().toISOString(), received_at: new Date().toISOString(),
}
}
const updatedAttempt = await prisma.saleInvoiceTspAttempts.update({
where: {
id: attempt_id,
}, },
data: attemptUpdatedData,
select: { select: {
status: true, status: true,
invoice: true, invoice: true,