Files
psp_api/src/modules/pos/sales-invoices/sales-invoices.service.ts
T

308 lines
9.3 KiB
TypeScript

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 { 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 { CreateSalesInvoiceDto } 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,
) {}
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 { tsp_attempts, type, ...rest } = invoice
return {
...rest,
type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue(
'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.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 { tsp_attempts, type, ...rest } = invoice
const mappedInvoice = {
...rest,
type: translateEnumValue('TspProviderRequestType', type),
status: translateEnumValue(
'TspProviderResponseStatus',
invoice.tsp_attempts?.[0]?.status || TspProviderResponseStatus.NOT_SEND,
),
}
return ResponseMapper.single(mappedInvoice)
} else throw new NotFoundException('فاکتور مورد نظر شما یافت نشد.')
}
async create(data: CreateSalesInvoiceDto, 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 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 = {
pos: {
id: posInfo.pos_id,
complex: {
business_activity_id: posInfo.business_id,
},
},
}
if (query.code?.trim()) {
where.code = {
contains: query.code.trim(),
}
}
if (query.invoice_date_from || query.invoice_date_to) {
where.invoice_date = {
...(query.invoice_date_from ? { gte: new Date(query.invoice_date_from) } : {}),
...(query.invoice_date_to ? { lte: new Date(query.invoice_date_to) } : {}),
}
}
if (query.created_at_from || query.created_at_to) {
where.created_at = {
...(query.created_at_from ? { gte: new Date(query.created_at_from) } : {}),
...(query.created_at_to ? { lte: new Date(query.created_at_to) } : {}),
}
}
if (
query.total_amount !== undefined ||
query.total_amount_from !== undefined ||
query.total_amount_to !== undefined
) {
where.total_amount = {
...(query.total_amount !== undefined ? { equals: query.total_amount } : {}),
...(query.total_amount_from !== undefined
? { gte: query.total_amount_from }
: {}),
...(query.total_amount_to !== undefined ? { lte: query.total_amount_to } : {}),
}
}
if (
query.customer_name?.trim() ||
query.customer_mobile?.trim() ||
query.customer_national_id?.trim() ||
query.customer_economic_code?.trim()
) {
where.customer = {
is: {
OR: [
...(query.customer_name?.trim()
? [
{
individual: {
is: {
OR: [
{
first_name: {
contains: query.customer_name.trim(),
},
},
{
last_name: {
contains: query.customer_name.trim(),
},
},
],
},
},
},
{
legal: {
is: {
name: {
contains: query.customer_name.trim(),
},
},
},
},
]
: []),
...(query.customer_mobile?.trim()
? [
{
individual: {
is: {
mobile_number: {
contains: query.customer_mobile.trim(),
},
},
},
},
]
: []),
...(query.customer_national_id?.trim()
? [
{
individual: {
is: {
national_id: {
contains: query.customer_national_id.trim(),
},
},
},
},
]
: []),
...(query.customer_economic_code?.trim()
? [
{
legal: {
is: {
OR: [
{
economic_code: {
contains: query.customer_economic_code.trim(),
},
},
{
registration_number: {
contains: query.customer_economic_code.trim(),
},
},
],
},
},
},
]
: []),
],
},
}
}
if (query.status) {
if (query.status === TspProviderResponseStatus.NOT_SEND) {
where.tsp_attempts = undefined
} else {
where.tsp_attempts = {
some: {
status: query.status,
},
}
}
}
return where
}
}