feat: add DTOs and services for tax switch integration

- Created SendBulkSaleInvoicesDto for handling bulk sale invoice requests.
- Implemented TaxSwitchSendPayloadDto and related DTOs for tax switch item payloads and results.
- Developed SalesInvoiceTaxSwitchService to manage tax switch operations, including sending and retrieving tax information.
- Added SalesInvoiceTaxService for handling sales invoice tax logic, including bulk sending and persistence of results.
- Introduced NamaTaxSwitchAdapter to interact with the tax switch service, simulating external API responses.
- Created SendBulkSalesInvoicesDto for POS module to handle bulk sales invoice requests.
This commit is contained in:
2026-04-27 22:11:05 +03:30
parent dee96b6e91
commit 58a7c359d8
68 changed files with 7896 additions and 3534 deletions
@@ -1,3 +1,4 @@
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper'
@@ -40,22 +41,7 @@ export class PartnerBusinessActivityAccountsChargeService {
],
},
},
OR: [
{
expires_at: {
gte: startOfDay,
},
},
{
license_renews: {
some: {
expires_at: {
gte: startOfDay,
},
},
},
},
],
...QUERY_CONSTANTS.LICENSE_ACTIVATION.activeOnDate(),
},
select: {
id: true,
@@ -1,3 +1,4 @@
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { ComplexSelect, ComplexWhereInput } from '@/generated/prisma/models'
import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, Injectable } from '@nestjs/common'
@@ -44,9 +45,24 @@ export class BusinessActivityComplexesService {
async findAll(partner_id: string, consumer_id: string, business_activity_id: string) {
const complexes = await this.prisma.complex.findMany({
where: this.defaultWhere(partner_id, consumer_id, business_activity_id),
select: this.defaultSelect,
select: {
...this.defaultSelect,
_count: {
select: {
pos_list: true,
},
},
},
})
return ResponseMapper.list(complexes)
const mappedComplexes = complexes.map(complex => {
const { _count, ...rest } = complex
return {
...rest,
pos_count: _count.pos_list,
}
})
return ResponseMapper.list(mappedComplexes)
}
async findOne(
@@ -67,8 +83,6 @@ export class BusinessActivityComplexesService {
async create(partner_id: string, business_id: string, data: CreateComplexDto) {
const complex = this.prisma.$transaction(async tx => {
const now = new Date()
const relatedLicense = await tx.licenseAccountAllocation.findFirst({
where: {
license_activation: {
@@ -80,22 +94,7 @@ export class BusinessActivityComplexesService {
business_activity: {
id: business_id,
},
OR: [
{
expires_at: {
gte: now,
},
},
{
license_renews: {
some: {
expires_at: {
gte: now,
},
},
},
},
],
...QUERY_CONSTANTS.LICENSE_ACTIVATION.activeOnDate(),
},
account_id: null,
},
@@ -1,3 +1,5 @@
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { consumerRelatedPartner } from '@/common/queryConstants/consumer'
import { PasswordUtil } from '@/common/utils/password.util'
import {
AccountStatus,
@@ -77,7 +79,7 @@ export class ComplexPosesService {
business_activity: {
id: business_activity_id,
consumer: {
partner_id,
...consumerRelatedPartner(partner_id),
},
},
},
@@ -97,7 +99,9 @@ export class ComplexPosesService {
async findAll(partner_id: string, business_activity_id: string, complex_id: string) {
const poses = await this.prisma.pos.findMany({
where: this.defaultWhere(partner_id, complex_id, business_activity_id),
where: {
...this.defaultWhere(partner_id, complex_id, business_activity_id),
},
select: this.defaultSelect,
})
@@ -126,29 +130,12 @@ export class ComplexPosesService {
data: CreatePosDto,
) {
const pos = this.prisma.$transaction(async tx => {
const now = new Date()
const activeAccountAllocation = await tx.licenseAccountAllocation.findFirst({
where: {
account_id: null,
license_activation: {
business_activity_id,
OR: [
{
expires_at: {
gte: now,
},
},
{
license_renews: {
some: {
expires_at: {
gte: now,
},
},
},
},
],
...QUERY_CONSTANTS.LICENSE_ACTIVATION.activeOnDate(),
license: {
charge_transaction: {
partner_id,
@@ -10,6 +10,14 @@ export class CreateBusinessActivitiesDto {
@ApiProperty({ required: true })
economic_code: string
@IsString()
@ApiProperty({ required: true })
fiscal_id: string
@IsString()
@ApiProperty({ required: true })
partner_token: string
@IsString()
@ApiProperty({ required: true })
guild_id: string
@@ -31,9 +31,10 @@ export class PartnerConsumersService {
defaultSelect: ConsumerSelect = {
id: true,
...QUERY_CONSTANTS.CONSUMER.infoSelect,
status: true,
created_at: true,
...QUERY_CONSTANTS.CONSUMER.infoSelect,
...QUERY_CONSTANTS.CONSUMER.activeBusinessCount,
}
private defaultWhere = (partner_id: string): ConsumerWhereInput => ({
@@ -119,8 +120,7 @@ export class PartnerConsumersService {
throw new BadRequestException(`تعداد لایسنس‌های فعلی شما به پایان رسیده است.`)
}
const { username, password, customer, ...rest } = data
const { individual, legal } = customer
const { username, password, individual, legal, ...rest } = data
const createConsumerData: ConsumerCreateInput = {
...rest,
@@ -228,7 +228,15 @@ export class PartnerConsumersService {
...(this.defaultWhere(partner_id) as any),
id,
},
data,
data: {
status: data.status,
legal: {
update: data.legal,
},
individual: {
update: data.individual,
},
},
})
}
}
@@ -16,12 +16,13 @@ export class CreateConsumerDto {
@ApiProperty({ required: true })
password: string
@ApiProperty({ required: true })
@ApiProperty({ required: false })
@IsObject()
customer: {
individual?: Omit<ConsumerIndividual, 'partner_id' | 'consumer_id'>
legal?: Omit<ConsumerLegal, 'partner_id' | 'consumer_id'>
}
individual?: Omit<ConsumerIndividual, 'partner_id' | 'consumer_id'>
@ApiProperty({ required: false })
@IsObject()
legal?: Omit<ConsumerLegal, 'partner_id' | 'consumer_id'>
}
export class UpdateConsumerDto extends OmitType(PartialType(CreateConsumerDto), [
'password',
@@ -26,8 +26,6 @@ export interface PartnerLicenseActivationChargeTransactionResponseDto {
export interface PartnerLicenseActivationLicenseResponseDto {
id: string
accounts_limit: number
charge_transaction: PartnerLicenseActivationChargeTransactionResponseDto
}
export interface PartnerLicenseActivationCountResponseDto {
@@ -42,7 +40,7 @@ export interface PartnerLicenseActivationResponseDto {
updated_at: Date
business_activity: PartnerLicenseActivationBusinessActivityResponseDto
license: PartnerLicenseActivationLicenseResponseDto
_count: PartnerLicenseActivationCountResponseDto
account_allocation_count: Number
}
export type PartnerLicensesServiceFindAllResponseDto = Awaited<
@@ -1,6 +1,5 @@
import {
PartnerLicenseActivationBusinessActivityResponseDto,
PartnerLicenseActivationChargeTransactionResponseDto,
PartnerLicenseActivationConsumerResponseDto,
PartnerLicenseActivationCountResponseDto,
PartnerLicenseActivationLicenseResponseDto,
@@ -35,8 +34,6 @@ type PartnerLicenseActivationChargeTransactionQueryResult = {
type PartnerLicenseActivationLicenseQueryResult = {
id: string
accounts_limit: number
charge_transaction: PartnerLicenseActivationChargeTransactionQueryResult
}
type PartnerLicenseActivationQueryResult = {
@@ -62,7 +59,9 @@ export const mapPartnerLicenseActivationConsumer = (
first_name: individual?.first_name ?? null,
last_name: individual?.last_name ?? null,
mobile_number: individual?.mobile_number ?? null,
name: legal?.name ?? null,
name: individual
? `${individual?.first_name} ${individual?.last_name}`
: (legal?.name ?? null),
registration_code: legal?.registration_code ?? null,
}
}
@@ -78,17 +77,8 @@ export const mapPartnerLicenseActivation = (
),
}
const chargeTransaction: PartnerLicenseActivationChargeTransactionResponseDto = {
id: licenseActivation.license.charge_transaction.id,
tracking_code: licenseActivation.license.charge_transaction.tracking_code,
activation_expires_at:
licenseActivation.license.charge_transaction.activation_expires_at,
}
const license: PartnerLicenseActivationLicenseResponseDto = {
id: licenseActivation.license.id,
accounts_limit: licenseActivation.license.accounts_limit,
charge_transaction: chargeTransaction,
}
return {
@@ -99,6 +89,6 @@ export const mapPartnerLicenseActivation = (
updated_at: licenseActivation.updated_at,
business_activity: businessActivity,
license,
_count: licenseActivation._count,
account_allocation_count: licenseActivation._count.account_allocations,
}
}
@@ -11,10 +11,7 @@ export class PartnerLicensesService {
constructor(private readonly prisma: PrismaService) {}
async findAll(
partner_id: string,
params: PartnerLicensesFilterDto = {},
) {
async findAll(partner_id: string, params: PartnerLicensesFilterDto = {}) {
const { perPage, page, consumer_name, consumer_mobile, expires_from, expires_to } =
params
@@ -137,14 +134,6 @@ export class PartnerLicensesService {
license: {
select: {
id: true,
accounts_limit: true,
charge_transaction: {
select: {
id: true,
tracking_code: true,
activation_expires_at: true,
},
},
},
},
_count: {
@@ -1,3 +1,5 @@
import { QUERY_CONSTANTS } from '@/common/queryConstants'
import { consumerRelatedPartner } from '@/common/queryConstants/consumer'
import { BadRequestException } from '@nestjs/common'
type PartnerBusinessActivityAllocationClient = {
@@ -36,26 +38,9 @@ const getPartnerBusinessActivityActiveActivation = async (
where: {
business_activity_id,
business_activity: {
consumer: {
partner_id,
},
...consumerRelatedPartner(partner_id),
},
OR: [
{
expires_at: {
gte: startOfDay,
},
},
{
license_renews: {
some: {
expires_at: {
gte: startOfDay,
},
},
},
},
],
...QUERY_CONSTANTS.LICENSE_ACTIVATION.activeOnDate(startOfDay),
},
select: includeAccountAllocations
? {