feat: implement inquiry, send, retry, and revoke actions for sales invoices; enhance query constants and service structure

This commit is contained in:
2026-05-10 19:56:05 +03:30
parent 9a76880b1d
commit 5e6bd33cdd
8 changed files with 175 additions and 297 deletions
+97 -24
View File
@@ -10,16 +10,37 @@ export const summarySelect: SalesInvoiceSelect = {
tax_id: true,
type: true,
notes: true,
created_at: true,
customer: {
select: {
type: true,
individual: {
select: {
first_name: true,
last_name: true,
mobile_number: true,
national_id: true,
},
},
legal: {
select: {
name: true,
economic_code: true,
registration_number: true,
},
},
},
},
tsp_attempts: {
orderBy: {
created_at: 'desc',
},
take: 1,
select: {
status: true,
sent_at: true,
message: true,
},
orderBy: {
attempt_no: 'desc',
},
take: 1,
},
reference_invoice: {
select: {
@@ -31,42 +52,94 @@ export const summarySelect: SalesInvoiceSelect = {
export const select: SalesInvoiceSelect = {
...summarySelect,
payments: {
updated_at: true,
unknown_customer: true,
pos: {
select: {
amount: true,
paid_at: true,
payment_method: true,
terminal_info: {
id: true,
name: true,
complex: {
select: {
customer_card_no: true,
terminal_id: true,
rrn: true,
stan: true,
transaction_date_time: true,
id: true,
name: true,
business_activity: {
select: {
id: true,
name: true,
},
},
},
},
},
},
unknown_customer: true,
customer: {
consumer_account: {
select: {
type: true,
legal: true,
individual: true,
id: true,
role: true,
account: {
select: {
username: true,
},
},
},
},
items: {
select: {
id: true,
good_id: true,
service_id: true,
quantity: true,
unit_price: true,
discount: true,
total_amount: true,
payload: true,
measure_unit_code: true,
measure_unit_text: true,
sku_code: true,
sku_vat: true,
unit_price: true,
discount: true,
total_amount: true,
notes: true,
payload: true,
good_snapshot: true,
good: {
select: {
name: true,
barcode: true,
image_url: true,
category: true,
},
},
},
},
payments: {
select: {
id: true,
amount: true,
payment_method: true,
paid_at: true,
created_at: true,
terminal_info: {
select: {
terminal_id: true,
stan: true,
rrn: true,
transaction_date_time: true,
customer_card_no: true,
description: true,
},
},
},
},
tsp_attempts: {
orderBy: {
created_at: 'desc',
},
select: {
id: true,
attempt_no: true,
status: true,
message: true,
sent_at: true,
received_at: true,
created_at: true,
},
take: 1,
},
}
@@ -1,4 +1,6 @@
import { PosInfo } from '@/common/decorators/posInfo.decorator'
import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
import type { IPosPayload } from '@/common/models'
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
import { ApiTags } from '@nestjs/swagger'
import type {
@@ -28,11 +30,6 @@ export class StatisticsController {
return this.service.findOne(consumerId, id)
}
@Post(':id/send_tax')
async send(@TokenAccount('userId') consumerId: string, @Param('id') id: string) {
return this.service.send(consumerId, id)
}
@Post('send_tax_bulk')
async sendBulk(
@TokenAccount('userId') consumerId: string,
@@ -40,4 +37,24 @@ export class StatisticsController {
) {
return this.service.sendBulk(consumerId, data.invoice_ids)
}
@Get(':id/inquiry')
inquiry(@PosInfo() posInfo: IPosPayload, @Param('id') id: string) {
return this.service.inquiry(posInfo.consumer_account_id, posInfo.pos_id, id)
}
@Post(':id/send')
send(@Param('id') id: string, @PosInfo() posInfo: IPosPayload) {
return this.service.send(id, posInfo)
}
@Post(':id/retry')
retry(@Param('id') id: string, @PosInfo() posInfo: IPosPayload) {
return this.service.retry(id, posInfo)
}
@Post(':id/revoke')
revoke(@Param('id') id: string, @PosInfo() posInfo: IPosPayload) {
return this.service.revoke(id, posInfo)
}
}
@@ -1,3 +1,5 @@
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceAccessService } from '@/common/services/saleInvoices/sale-invoice-access.service'
import { SaleInvoiceTspModule } from '@/modules/tspProviders/sales-invoice-tsp.module'
import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common'
@@ -7,7 +9,7 @@ import { SaleInvoicesService } from './saleInvoices.service'
@Module({
imports: [PrismaModule, SaleInvoiceTspModule],
controllers: [StatisticsController],
providers: [SaleInvoicesService],
providers: [SaleInvoicesService, SharedSaleInvoiceActionsService, SharedSaleInvoiceAccessService],
exports: [SaleInvoicesService],
})
export class ConsumerSaleInvoicesModule {}
@@ -1,3 +1,6 @@
import { IPosPayload } from '@/common/models'
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { translateEnumValue } from '@/common/utils'
import { TspProviderResponseStatus } from '@/generated/prisma/enums'
import {
@@ -15,24 +18,10 @@ export class SaleInvoicesService {
constructor(
private readonly prisma: PrismaService,
private salesInvoiceTaxService: SalesInvoiceTspService,
private sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService,
) {}
private readonly defaultSelect: SalesInvoiceSelect = {
id: true,
code: true,
total_amount: true,
invoice_date: true,
created_at: true,
consumer_account: {
select: {
role: true,
account: {
select: {
username: true,
},
},
},
},
pos: {
select: {
id: true,
@@ -51,17 +40,6 @@ export class SaleInvoicesService {
},
},
},
tsp_attempts: {
orderBy: {
created_at: 'asc',
},
take: 1,
select: {
id: true,
status: true,
},
},
}
private readonly invoiceMapper = (invoice: any) => {
@@ -85,7 +63,10 @@ export class SaleInvoicesService {
const [invoices, total] = await this.prisma.$transaction(async tx => [
await tx.salesInvoice.findMany({
where: invoicesWhere,
select: this.defaultSelect,
select: {
...QUERY_CONSTANTS.SALE_INVOICE.summarySelect,
...this.defaultSelect,
},
skip: (page - 1) * perPage,
take: perPage,
}),
@@ -106,71 +87,8 @@ export class SaleInvoicesService {
const invoice = await this.prisma.salesInvoice.findUniqueOrThrow({
where: invoicesWhere,
select: {
...QUERY_CONSTANTS.SALE_INVOICE.select,
...this.defaultSelect,
notes: true,
created_at: true,
payments: {
select: {
amount: true,
payment_method: true,
},
},
items: {
select: {
id: true,
notes: true,
unit_price: true,
discount: true,
quantity: true,
total_amount: true,
payload: true,
good: {
select: {
id: true,
name: true,
pricing_model: true,
measure_unit: {
select: {
id: true,
name: true,
},
},
category: {
select: {
id: true,
name: true,
image_url: true,
},
},
},
},
},
},
customer: {
select: {
id: true,
type: true,
legal: {
select: {
name: true,
economic_code: true,
registration_number: true,
postal_code: true,
},
},
individual: {
select: {
first_name: true,
last_name: true,
economic_code: true,
national_id: true,
postal_code: true,
},
},
},
},
unknown_customer: true,
},
})
@@ -180,15 +98,47 @@ export class SaleInvoicesService {
throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.')
}
async send(consumer_id: string, invoice_id: string) {
const tspProviderResult = await this.salesInvoiceTaxService.originalSend(
consumer_id,
invoice_id,
async send(invoiceId: string, posInfo: IPosPayload) {
const invoice = await this.sharedSaleInvoiceActionsService.send(
posInfo.consumer_account_id,
posInfo.pos_id,
invoiceId,
)
return ResponseMapper.single({
...tspProviderResult,
})
return ResponseMapper.single(invoice)
}
async retry(invoiceId: string, posInfo: IPosPayload) {
const invoice = await this.sharedSaleInvoiceActionsService.retry(
posInfo.consumer_account_id,
posInfo.pos_id,
invoiceId,
)
return ResponseMapper.single(invoice)
}
async revoke(invoiceId: string, posInfo: IPosPayload) {
const { consumer_account_id, pos_id, business_id, complex_id } = posInfo
const invoice = await this.sharedSaleInvoiceActionsService.revoke(
consumer_account_id,
pos_id,
complex_id,
business_id,
invoiceId,
)
return ResponseMapper.single(invoice)
}
async inquiry(consumer_account_id: string, pos_id: string, invoiceId: string) {
const invoice = await this.sharedSaleInvoiceActionsService.inquiry(
consumer_account_id,
pos_id,
invoiceId,
)
return ResponseMapper.single(invoice)
}
async sendBulk(consumer_id: string, invoiceIds: string[]) {
@@ -1,6 +1,7 @@
import { IPosPayload } from '@/common/models/posPayload.model'
import { SharedSaleInvoiceCreateService } from '@/common/services/saleInvoices/sale-invoice-create.service'
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { SharedSaleInvoiceActionsService } from '@/common/services/saleInvoices/sale-invoice-actions.service'
import { SharedSaleInvoiceCreateService } from '@/common/services/saleInvoices/sale-invoice-create.service'
import { translateEnumValue } from '@/common/utils'
import { PrismaService } from '@/prisma/prisma.service'
import { Injectable, NotFoundException } from '@nestjs/common'
@@ -34,41 +35,7 @@ export class SalesInvoicesService {
skip: (page - 1) * perPage,
take: perPage,
select: {
id: true,
code: true,
invoice_number: true,
invoice_date: true,
created_at: true,
total_amount: true,
customer: {
select: {
type: true,
individual: {
select: {
first_name: true,
last_name: true,
mobile_number: true,
national_id: true,
},
},
legal: {
select: {
name: true,
economic_code: true,
registration_number: true,
},
},
},
},
tsp_attempts: {
orderBy: {
created_at: 'desc',
},
take: 1,
select: {
status: true,
},
},
...QUERY_CONSTANTS.SALE_INVOICE.summarySelect,
},
}),
await tx.salesInvoice.count({ where }),
@@ -97,120 +64,7 @@ export class SalesInvoicesService {
},
},
select: {
id: true,
code: true,
invoice_number: true,
invoice_date: true,
created_at: true,
updated_at: true,
notes: true,
total_amount: true,
unknown_customer: true,
tax_id: true,
customer: {
select: {
id: true,
type: true,
individual: {
select: {
first_name: true,
last_name: true,
mobile_number: true,
national_id: true,
postal_code: true,
economic_code: true,
},
},
legal: {
select: {
name: true,
economic_code: true,
registration_number: true,
postal_code: true,
},
},
},
},
pos: {
select: {
id: true,
name: true,
complex: {
select: {
id: true,
name: true,
business_activity: {
select: {
id: true,
name: true,
},
},
},
},
},
},
consumer_account: {
select: {
id: true,
role: true,
account: {
select: {
username: true,
},
},
},
},
items: {
select: {
id: true,
good_id: true,
service_id: true,
quantity: true,
measure_unit_code: true,
measure_unit_text: true,
sku_code: true,
unit_price: true,
discount: true,
total_amount: true,
notes: true,
payload: true,
good_snapshot: true,
},
},
payments: {
select: {
id: true,
amount: true,
payment_method: true,
paid_at: true,
created_at: true,
terminal_info: {
select: {
terminal_id: true,
stan: true,
rrn: true,
transaction_date_time: true,
customer_card_no: true,
description: true,
},
},
},
},
tsp_attempts: {
orderBy: {
created_at: 'desc',
},
select: {
id: true,
attempt_no: true,
status: true,
message: true,
sent_at: true,
received_at: true,
created_at: true,
},
take: 1,
},
...QUERY_CONSTANTS.SALE_INVOICE.select,
},
})
+1 -1
View File
@@ -25,7 +25,7 @@ export function getPrismaOptions(): any {
} else {
options.log = [
{ emit: 'stdout', level: 'query' },
{ emit: 'stdout', level: 'info' },
// { emit: 'stdout', level: 'info' },
{ emit: 'stdout', level: 'warn' },
{ emit: 'stdout', level: 'error' },
]