diff --git a/20260507200953_update_sale/migration.sql b/20260507200953_update_sale/migration.sql deleted file mode 100644 index 5a61525..0000000 --- a/20260507200953_update_sale/migration.sql +++ /dev/null @@ -1,18 +0,0 @@ -/* - Warnings: - - - Added the required column `raw_request_payload` to the `sale_invoice_tsp_attempts` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE `sale_invoice_tsp_attempts` DROP FOREIGN KEY `sale_invoice_tsp_attempts_invoice_id_fkey`; - --- DropIndex -DROP INDEX `sale_invoice_tsp_attempts_invoice_id_key` ON `sale_invoice_tsp_attempts`; - --- AlterTable -ALTER TABLE `sale_invoice_tsp_attempts` ADD COLUMN `raw_request_payload` JSON NOT NULL, - ADD COLUMN `raw_response_payload` JSON NULL; - --- AddForeignKey -ALTER TABLE `customer_legal` ADD CONSTRAINT `customer_legal_business_activity_id_fkey` FOREIGN KEY (`business_activity_id`) REFERENCES `business_activities`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/AGENT.md b/Agents.md similarity index 100% rename from AGENT.md rename to Agents.md diff --git a/src/common/queryConstants/saleInvoice.ts b/src/common/queryConstants/saleInvoice.ts index 38a4797..d5d7c4d 100644 --- a/src/common/queryConstants/saleInvoice.ts +++ b/src/common/queryConstants/saleInvoice.ts @@ -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, + }, } diff --git a/src/modules/consumer/saleInvoices/saleInvoices.controller.ts b/src/modules/consumer/saleInvoices/saleInvoices.controller.ts index 3887146..e03c84a 100644 --- a/src/modules/consumer/saleInvoices/saleInvoices.controller.ts +++ b/src/modules/consumer/saleInvoices/saleInvoices.controller.ts @@ -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) + } } diff --git a/src/modules/consumer/saleInvoices/saleInvoices.module.ts b/src/modules/consumer/saleInvoices/saleInvoices.module.ts index 9cc4493..68e7644 100644 --- a/src/modules/consumer/saleInvoices/saleInvoices.module.ts +++ b/src/modules/consumer/saleInvoices/saleInvoices.module.ts @@ -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 {} diff --git a/src/modules/consumer/saleInvoices/saleInvoices.service.ts b/src/modules/consumer/saleInvoices/saleInvoices.service.ts index 6ceef22..6da56aa 100644 --- a/src/modules/consumer/saleInvoices/saleInvoices.service.ts +++ b/src/modules/consumer/saleInvoices/saleInvoices.service.ts @@ -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[]) { diff --git a/src/modules/pos/sales-invoices/sales-invoices.service.ts b/src/modules/pos/sales-invoices/sales-invoices.service.ts index b73b0ab..aebadb8 100644 --- a/src/modules/pos/sales-invoices/sales-invoices.service.ts +++ b/src/modules/pos/sales-invoices/sales-invoices.service.ts @@ -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, }, }) diff --git a/src/prisma/prisma-config.service.ts b/src/prisma/prisma-config.service.ts index 3d944ef..875d304 100644 --- a/src/prisma/prisma-config.service.ts +++ b/src/prisma/prisma-config.service.ts @@ -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' }, ]