import { IPosPayload } from '@/common/models/posPayload.model' 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 { SharedSaleInvoiceFilterService } from '@/common/services/saleInvoices/sale-invoice-filter.service' import { translateEnumValue } from '@/common/utils' import { PrismaService } from '@/prisma/prisma.service' import { Injectable, NotFoundException } from '@nestjs/common' import { ResponseMapper } from 'common/response/response-mapper' import { Prisma } from 'generated/prisma/client' import { TspProviderRequestType, TspProviderResponseStatus } from 'generated/prisma/enums' import { SalesInvoiceTspService } from '../../tspProviders/sales-invoice-tsp.service' import { PosCorrectionSalesInvoiceDto, PosCreateSalesInvoiceDto, PosReturnSalesInvoiceDto, } from './dto/create-sales-invoice.dto' import { SalesInvoicesFilterDto } from './dto/sales-invoices-filter.dto' @Injectable() export class SalesInvoicesService { constructor( private prisma: PrismaService, private salesInvoiceTaxService: SalesInvoiceTspService, private sharedSaleInvoiceCreateService: SharedSaleInvoiceCreateService, private sharedSaleInvoiceActionsService: SharedSaleInvoiceActionsService, private sharedSaleInvoiceFilterService: SharedSaleInvoiceFilterService, ) {} async findAll(posInfo: IPosPayload, query: SalesInvoicesFilterDto = {}) { const page = query.page || 1 const perPage = Math.min(query.perPage || 10, 100) const where = this.buildFindAllWhere(posInfo, query) const [items, total] = await this.prisma.$transaction(async tx => [ await tx.salesInvoice.findMany({ where, orderBy: { created_at: 'desc', }, skip: (page - 1) * perPage, take: perPage, select: { ...QUERY_CONSTANTS.SALE_INVOICE.summarySelect, }, }), await tx.salesInvoice.count({ where }), ]) const summaryItems = items.map(invoice => { const { last_tsp_status, type, ...rest } = invoice return { ...rest, type: translateEnumValue('TspProviderRequestType', type), status: translateEnumValue( 'TspProviderResponseStatus', last_tsp_status || TspProviderResponseStatus.NOT_SEND, ), } }) return ResponseMapper.paginate(summaryItems, { total, page, perPage }) } async findOne(posInfo: IPosPayload, id: string) { const invoice = await this.prisma.salesInvoice.findUnique({ where: { id, pos: { id: posInfo.pos_id, complex: { business_activity_id: posInfo.business_id, }, }, }, select: { ...QUERY_CONSTANTS.SALE_INVOICE.select, }, }) if (invoice) { const { last_tsp_status, type, ...rest } = invoice const mappedInvoice = { ...rest, type: translateEnumValue('TspProviderRequestType', type), status: translateEnumValue( 'TspProviderResponseStatus', last_tsp_status || TspProviderResponseStatus.NOT_SEND, ), settlement_type: translateEnumValue( 'InvoiceSettlementType', invoice.settlement_type, ), } return ResponseMapper.single(mappedInvoice) } else throw new NotFoundException('صورت‌حساب مورد نظر شما یافت نشد.') } async create(data: PosCreateSalesInvoiceDto, posInfo: IPosPayload) { let salesInvoice = await this.sharedSaleInvoiceCreateService.create({ data, businessId: posInfo.business_id, complexId: posInfo.complex_id, posId: posInfo.pos_id, consumerAccountId: posInfo.consumer_account_id, type: TspProviderRequestType.ORIGINAL, }) if (data.send_to_tsp) { const providerResponse = await this.salesInvoiceTaxService.originalSend( salesInvoice.id, posInfo.pos_id, ) if (providerResponse?.invoice) { salesInvoice = providerResponse?.invoice as any } } return ResponseMapper.create(salesInvoice) } async send(invoiceId: string, posInfo: IPosPayload) { const invoice = await this.sharedSaleInvoiceActionsService.send( posInfo.consumer_account_id, posInfo.pos_id, invoiceId, ) 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 correction( invoiceId: string, posInfo: IPosPayload, data: PosCorrectionSalesInvoiceDto, ) { const { consumer_account_id, pos_id, business_id, complex_id } = posInfo const invoice = await this.sharedSaleInvoiceActionsService.correction( data, consumer_account_id, pos_id, complex_id, business_id, invoiceId, ) return ResponseMapper.single(invoice) } async return(invoiceId: string, posInfo: IPosPayload, data: PosReturnSalesInvoiceDto) { const { consumer_account_id, pos_id, business_id, complex_id } = posInfo const invoice = await this.sharedSaleInvoiceActionsService.return( data, consumer_account_id, pos_id, complex_id, business_id, invoiceId, ) return ResponseMapper.create(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) } private buildFindAllWhere(posInfo: IPosPayload, query: SalesInvoicesFilterDto) { const where: Prisma.SalesInvoiceWhereInput = { ...this.sharedSaleInvoiceFilterService.buildWhere(query), pos: { id: posInfo.pos_id, complex: { business_activity_id: posInfo.business_id, }, }, referenced_by: null, } if (query.invoice_number) { where.invoice_number = parseInt(query.invoice_number + '') } return where } }