feat: implement partner licenses module with pagination and filtering capabilities

This commit is contained in:
2026-04-26 09:54:48 +03:30
parent b72e6c7194
commit 34793295c9
24 changed files with 459 additions and 76 deletions
+12 -2
View File
@@ -23,12 +23,22 @@ export class PosGuard {
const { posId } = cookie const { posId } = cookie
if (!posId) { if (!posId) {
throw new ForbiddenException('شما دسترسی لازم را ندارید.') return false
// throw new ForbiddenException('شما دسترسی لازم را ندارید.')
} }
const checkLicenseActivation = await this.prisma.licenseAccountAllocation.findFirst({ const checkLicenseActivation = await this.prisma.licenseAccountAllocation.findFirst({
where: { where: {
account_id: tokenPayload.account_id, OR: [
{
account_id: tokenPayload.account_id,
},
{
account: {
consumer_id: tokenPayload.user?.id,
},
},
],
license_activation: { license_activation: {
OR: [ OR: [
{ {
@@ -84,6 +84,9 @@ export class ResponseMappingInterceptor implements NestInterceptor {
// } // }
break break
case 'paginate': { case 'paginate': {
const { items: a, ...rest } = wrapped
console.log(rest)
const items = Array.isArray(wrapped.items) ? wrapped.items : [] const items = Array.isArray(wrapped.items) ? wrapped.items : []
const total = const total =
typeof wrapped.total === 'number' ? wrapped.total : items.length typeof wrapped.total === 'number' ? wrapped.total : items.length
+6 -6
View File
@@ -12,9 +12,9 @@ export type MapperWrapper<T> =
| { __mapped: 'delete' } | { __mapped: 'delete' }
interface IPaginateMeta { interface IPaginateMeta {
count: number total: number
page?: number page?: number
pageSize?: number perPage?: number
} }
export const ResponseMapper = { export const ResponseMapper = {
@@ -38,12 +38,12 @@ export const ResponseMapper = {
return { __mapped: 'list', items } return { __mapped: 'list', items }
}, },
paginate<T>(items: T[], { count, page = 1, pageSize: perPage }: IPaginateMeta) { paginate<T>(items: T[], { total, page = 1, perPage }: IPaginateMeta) {
return { __mapped: 'paginate', items, count, page, perPage } return { __mapped: 'paginate', items, total, page, perPage }
}, },
sequelizePaginate<T>(rows: T[], count: number, page = 1, pageSize = rows.length) { sequelizePaginate<T>(rows: T[], total: number, page = 1, pageSize = rows.length) {
return { __mapped: 'sequelize', rows, count, page, pageSize } return { __mapped: 'sequelize', rows, total, page, pageSize }
}, },
} }
@@ -46,14 +46,14 @@ export class AdminConsumersService {
} }
async findAll() { async findAll() {
const [consumers, count] = await this.prisma.$transaction([ const [consumers, total] = await this.prisma.$transaction([
this.prisma.consumer.findMany({ this.prisma.consumer.findMany({
select: this.defaultSelect, select: this.defaultSelect,
}), }),
this.prisma.consumer.count(), this.prisma.consumer.count(),
]) ])
return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), { count }) return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), { total })
} }
async findOne(id: string) { async findOne(id: string) {
+5 -5
View File
@@ -7,16 +7,16 @@ import { CreateDeviceDto, UpdateDeviceDto } from './dto/device.dto'
export class DevicesService { export class DevicesService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async findAll(page = 1, pageSize = 10) { async findAll(page = 1, perPage = 10) {
const [items, count] = await this.prisma.$transaction([ const [items, total] = await this.prisma.$transaction([
this.prisma.device.findMany({ this.prisma.device.findMany({
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
include: { brand: true }, include: { brand: true },
}), }),
this.prisma.device.count(), this.prisma.device.count(),
]) ])
return ResponseMapper.paginate(items, { count, page, pageSize }) return ResponseMapper.paginate(items, { total, page, perPage })
} }
async findOne(id: string) { async findOne(id: string) {
@@ -37,7 +37,7 @@ export class GoodsService {
}) })
async findAll(guildId: string) { async findAll(guildId: string) {
const [goods, count] = await this.prisma.$transaction([ const [goods, total] = await this.prisma.$transaction([
this.prisma.good.findMany({ this.prisma.good.findMany({
where: this.defaultWhere(guildId), where: this.defaultWhere(guildId),
select: this.defaultSelect, select: this.defaultSelect,
@@ -45,7 +45,7 @@ export class GoodsService {
this.prisma.good.count(), this.prisma.good.count(),
]) ])
return ResponseMapper.paginate(goods, { return ResponseMapper.paginate(goods, {
count, total,
}) })
} }
+2 -2
View File
@@ -9,7 +9,7 @@ export class GuildsService {
constructor(private prisma: PrismaService) {} constructor(private prisma: PrismaService) {}
async findAll() { async findAll() {
const [guilds, count] = await this.prisma.$transaction([ const [guilds, total] = await this.prisma.$transaction([
this.prisma.guild.findMany({ this.prisma.guild.findMany({
include: { include: {
_count: { _count: {
@@ -30,7 +30,7 @@ export class GuildsService {
businessActivitiesCount: guild._count.business_activities, businessActivitiesCount: guild._count.business_activities,
} }
}), }),
{ count }, { total },
) )
} }
@@ -48,20 +48,20 @@ export class PartnerLicensesService {
created_at: true, created_at: true,
} }
async findAll(page = 1, pageSize = 10) { async findAll(page = 1, perPage = 10) {
const [licenses, count] = await this.prisma.$transaction([ const [licenses, total] = await this.prisma.$transaction([
this.prisma.licenseActivation.findMany({ this.prisma.licenseActivation.findMany({
select: this.licenseDefaultSelect, select: this.licenseDefaultSelect,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
}), }),
this.prisma.licenseActivation.count(), this.prisma.licenseActivation.count(),
]) ])
return ResponseMapper.paginate(licenses, { return ResponseMapper.paginate(licenses, {
count, total,
page, page,
pageSize, perPage,
}) })
} }
@@ -7,7 +7,7 @@ import { ResponseMapper } from 'common/response/response-mapper'
export class PartnerActivatedLicensesService { export class PartnerActivatedLicensesService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async findAll(partner_id: string, page = 1, pageSize = 10) { async findAll(partner_id: string, page = 1, perPage = 10) {
const defaultWhere: LicenseActivationWhereInput = { const defaultWhere: LicenseActivationWhereInput = {
license: { license: {
charge_transaction: { charge_transaction: {
@@ -15,11 +15,11 @@ export class PartnerActivatedLicensesService {
}, },
}, },
} }
const [licenses, count] = await this.prisma.$transaction(async tx => [ const [licenses, total] = await this.prisma.$transaction(async tx => [
await tx.licenseActivation.findMany({ await tx.licenseActivation.findMany({
where: defaultWhere, where: defaultWhere,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
select: { select: {
id: true, id: true,
starts_at: true, starts_at: true,
@@ -71,8 +71,8 @@ export class PartnerActivatedLicensesService {
return ResponseMapper.paginate(mappedLicenses, { return ResponseMapper.paginate(mappedLicenses, {
page, page,
pageSize, perPage,
count, total,
}) })
} }
@@ -7,18 +7,18 @@ import { ResponseMapper } from 'common/response/response-mapper'
export class PartnerAllocatedAccountsService { export class PartnerAllocatedAccountsService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async findAll(partner_id: string, page = 1, pageSize = 10) { async findAll(partner_id: string, page = 1, perPage = 10) {
const defaultWhere: PartnerAccountQuotaCreditWhereInput = { const defaultWhere: PartnerAccountQuotaCreditWhereInput = {
charge_transaction: { charge_transaction: {
partner_id, partner_id,
}, },
} }
const [allocations, count] = await this.prisma.$transaction(async tx => [ const [allocations, total] = await this.prisma.$transaction(async tx => [
await tx.partnerAccountQuotaCredit.findMany({ await tx.partnerAccountQuotaCredit.findMany({
where: defaultWhere, where: defaultWhere,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
select: { select: {
id: true, id: true,
created_at: true, created_at: true,
@@ -54,8 +54,8 @@ export class PartnerAllocatedAccountsService {
return ResponseMapper.paginate(allocations, { return ResponseMapper.paginate(allocations, {
page, page,
pageSize, perPage,
count, total,
}) })
} }
} }
@@ -51,16 +51,16 @@ export class PartnerAccountChargeTransactionService {
}, },
} }
async findAll(partner_id: string, page = 1, pageSize = 10) { async findAll(partner_id: string, page = 1, perPage = 10) {
const defaultWhere: PartnerAccountQuotaChargeTransactionWhereInput = { const defaultWhere: PartnerAccountQuotaChargeTransactionWhereInput = {
partner_id, partner_id,
} }
const [transactions, count] = await this.prisma.$transaction(async tx => [ const [transactions, total] = await this.prisma.$transaction(async tx => [
await tx.partnerAccountQuotaChargeTransaction.findMany({ await tx.partnerAccountQuotaChargeTransaction.findMany({
where: defaultWhere, where: defaultWhere,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
select: this.defaultSelect, select: this.defaultSelect,
}), }),
await tx.partnerAccountQuotaChargeTransaction.count({ await tx.partnerAccountQuotaChargeTransaction.count({
@@ -72,8 +72,8 @@ export class PartnerAccountChargeTransactionService {
return ResponseMapper.paginate(mappedTransactions, { return ResponseMapper.paginate(mappedTransactions, {
page, page,
pageSize, perPage,
count, total,
}) })
} }
@@ -51,16 +51,16 @@ export class PartnerLicenseChargeTransactionService {
}, },
} }
async findAll(partner_id: string, page = 1, pageSize = 10) { async findAll(partner_id: string, page = 1, perPage = 10) {
const defaultWhere: LicenseChargeTransactionWhereInput = { const defaultWhere: LicenseChargeTransactionWhereInput = {
partner_id, partner_id,
} }
const [transactions, count] = await this.prisma.$transaction(async tx => [ const [transactions, total] = await this.prisma.$transaction(async tx => [
await tx.licenseChargeTransaction.findMany({ await tx.licenseChargeTransaction.findMany({
where: defaultWhere, where: defaultWhere,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
select: this.defaultSelect, select: this.defaultSelect,
}), }),
await tx.licenseChargeTransaction.count({ await tx.licenseChargeTransaction.count({
@@ -72,8 +72,8 @@ export class PartnerLicenseChargeTransactionService {
return ResponseMapper.paginate(mappedTransactions, { return ResponseMapper.paginate(mappedTransactions, {
page, page,
pageSize, perPage,
count, total,
}) })
} }
+2 -2
View File
@@ -8,13 +8,13 @@ export class AdminUsersService {
constructor(private readonly prisma: PrismaService) {} constructor(private readonly prisma: PrismaService) {}
async findAll() { async findAll() {
const [users, count] = await this.prisma.$transaction([ const [users, total] = await this.prisma.$transaction([
this.prisma.admin.findMany(), this.prisma.admin.findMany(),
this.prisma.admin.count(), this.prisma.admin.count(),
]) ])
return ResponseMapper.paginate( return ResponseMapper.paginate(
users.map(user => ({ ...user, fullname: `${user.first_name} ${user.last_name}` })), users.map(user => ({ ...user, fullname: `${user.first_name} ${user.last_name}` })),
{ count }, { total },
) )
} }
@@ -20,10 +20,10 @@ export class SalesInvoicesService {
}, },
} }
const pageSize = 10 const perPage = 10
const page = 1 const page = 1
const [items, count] = await this.prisma.$transaction([ const [items, total] = await this.prisma.$transaction([
this.prisma.salesInvoice.findMany({ this.prisma.salesInvoice.findMany({
where: defaultWhere, where: defaultWhere,
select: { select: {
@@ -91,14 +91,14 @@ export class SalesInvoicesService {
}, },
unknown_customer: true, unknown_customer: true,
}, },
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
}), }),
this.prisma.salesInvoice.count({ this.prisma.salesInvoice.count({
where: defaultWhere, where: defaultWhere,
}), }),
]) ])
return ResponseMapper.paginate(items, { count, page, pageSize }) return ResponseMapper.paginate(items, { total, page, perPage })
} }
findOne(complex_id: string, pos_id: string, id: string) { findOne(complex_id: string, pos_id: string, id: string) {
@@ -60,19 +60,19 @@ export class consumerCustomersService {
} }
} }
async findAll(consumer_id: string, page = 1, pageSize = 10) { async findAll(consumer_id: string, page = 1, perPage = 10) {
const [customers, count] = await this.prisma.$transaction(async tx => [ const [customers, total] = await this.prisma.$transaction(async tx => [
await tx.customer.findMany({ await tx.customer.findMany({
where: this.defaultWhere(consumer_id), where: this.defaultWhere(consumer_id),
select: this.defaultSelect, select: this.defaultSelect,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: 10, take: 10,
}), }),
await tx.customer.count({ await tx.customer.count({
where: this.defaultWhere(consumer_id), where: this.defaultWhere(consumer_id),
}), }),
]) ])
return ResponseMapper.paginate(customers, { count, page, pageSize }) return ResponseMapper.paginate(customers, { total, page, perPage })
} }
async findOne(consumer_id: string, customer_id: string) { async findOne(consumer_id: string, customer_id: string) {
@@ -50,7 +50,7 @@ export class CustomerSaleInvoicesService {
created_at: true, created_at: true,
} }
async findAll(consumer_id: string, customer_id: string, page = 1, pageSize = 10) { async findAll(consumer_id: string, customer_id: string, page = 1, perPage = 10) {
const salesWhere: SalesInvoiceWhereInput = { const salesWhere: SalesInvoiceWhereInput = {
customer_id, customer_id,
pos: { pos: {
@@ -62,7 +62,7 @@ export class CustomerSaleInvoicesService {
}, },
} }
const [accounts, count] = await this.prisma.$transaction(async tx => [ const [accounts, total] = await this.prisma.$transaction(async tx => [
await tx.salesInvoice.findMany({ await tx.salesInvoice.findMany({
where: salesWhere, where: salesWhere,
select: { select: {
@@ -73,7 +73,7 @@ export class CustomerSaleInvoicesService {
}, },
}, },
}, },
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: 10, take: 10,
}), }),
await tx.salesInvoice.count({ await tx.salesInvoice.count({
@@ -90,9 +90,9 @@ export class CustomerSaleInvoicesService {
}) })
return ResponseMapper.paginate(mappedAccounts, { return ResponseMapper.paginate(mappedAccounts, {
count, total,
page, page,
pageSize, perPage,
}) })
} }
@@ -47,22 +47,22 @@ export class SaleInvoicesService {
}, },
} }
async findAll(consumer_id: string, page = 1, pageSize = 10) { async findAll(consumer_id: string, page = 1, perPage = 10) {
const invoicesWhere: SalesInvoiceWhereInput = { const invoicesWhere: SalesInvoiceWhereInput = {
consumer_account: { consumer_account: {
consumer_id, consumer_id,
}, },
} }
const [invoices, count] = await this.prisma.$transaction(async tx => [ const [invoices, total] = await this.prisma.$transaction(async tx => [
await tx.salesInvoice.findMany({ await tx.salesInvoice.findMany({
where: invoicesWhere, where: invoicesWhere,
select: this.defaultSelect, select: this.defaultSelect,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: pageSize, take: perPage,
}), }),
await tx.salesInvoice.count({ where: invoicesWhere }), await tx.salesInvoice.count({ where: invoicesWhere }),
]) ])
return ResponseMapper.paginate(invoices, { page, pageSize, count }) return ResponseMapper.paginate(invoices, { page, perPage, total })
} }
async findOne(consumer_id: string, id: string) { async findOne(consumer_id: string, id: string) {
@@ -37,12 +37,12 @@ export class PartnerConsumersService {
partner_id, partner_id,
}) })
async findAll(partner_id: string, page = 1, pageSize = 10) { async findAll(partner_id: string, page = 1, perPage = 10) {
const [consumers, count] = await this.prisma.$transaction(async tx => [ const [consumers, total] = await this.prisma.$transaction(async tx => [
await tx.consumer.findMany({ await tx.consumer.findMany({
where: this.defaultWhere(partner_id), where: this.defaultWhere(partner_id),
select: this.defaultSelect, select: this.defaultSelect,
skip: (page - 1) * pageSize, skip: (page - 1) * perPage,
take: 10, take: 10,
}), }),
await tx.consumer.count({ await tx.consumer.count({
@@ -50,9 +50,9 @@ export class PartnerConsumersService {
}), }),
]) ])
return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), { return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), {
count, total,
page, page,
pageSize, perPage,
}) })
} }
@@ -0,0 +1,140 @@
import { ApiProperty } from '@nestjs/swagger'
import { Paginated } from 'common/response/response-mapper'
export interface PartnerLicenseActivationConsumerResponseDto {
id: string
first_name: string
last_name: string
mobile_number: string
}
export interface PartnerLicenseActivationBusinessActivityResponseDto {
id: string
name: string
consumer: PartnerLicenseActivationConsumerResponseDto
}
export interface PartnerLicenseActivationChargeTransactionResponseDto {
id: string
tracking_code: string
activation_expires_at: Date
}
export interface PartnerLicenseActivationLicenseResponseDto {
id: string
accounts_limit: number
charge_transaction: PartnerLicenseActivationChargeTransactionResponseDto
}
export interface PartnerLicenseActivationCountResponseDto {
account_allocations: number
}
export interface PartnerLicenseActivationResponseDto {
id: string
starts_at: Date
expires_at: Date
created_at: Date
updated_at: Date
business_activity: PartnerLicenseActivationBusinessActivityResponseDto
license: PartnerLicenseActivationLicenseResponseDto
_count: PartnerLicenseActivationCountResponseDto
}
export type PartnerLicenseActivationPaginatedResponseDto =
Paginated<PartnerLicenseActivationResponseDto>
export class PartnerLicenseActivationConsumerResponseSchema {
@ApiProperty()
id: string
@ApiProperty()
first_name: string
@ApiProperty()
last_name: string
@ApiProperty()
mobile_number: string
}
export class PartnerLicenseActivationBusinessActivityResponseSchema {
@ApiProperty()
id: string
@ApiProperty()
name: string
@ApiProperty({ type: () => PartnerLicenseActivationConsumerResponseSchema })
consumer: PartnerLicenseActivationConsumerResponseSchema
}
export class PartnerLicenseActivationChargeTransactionResponseSchema {
@ApiProperty()
id: string
@ApiProperty()
tracking_code: string
@ApiProperty()
activation_expires_at: Date
}
export class PartnerLicenseActivationLicenseResponseSchema {
@ApiProperty()
id: string
@ApiProperty()
accounts_limit: number
@ApiProperty({ type: () => PartnerLicenseActivationChargeTransactionResponseSchema })
charge_transaction: PartnerLicenseActivationChargeTransactionResponseSchema
}
export class PartnerLicenseActivationCountResponseSchema {
@ApiProperty()
account_allocations: number
}
export class PartnerLicenseActivationResponseSchema {
@ApiProperty()
id: string
@ApiProperty()
starts_at: Date
@ApiProperty()
expires_at: Date
@ApiProperty()
created_at: Date
@ApiProperty()
updated_at: Date
@ApiProperty({ type: () => PartnerLicenseActivationBusinessActivityResponseSchema })
business_activity: PartnerLicenseActivationBusinessActivityResponseSchema
@ApiProperty({ type: () => PartnerLicenseActivationLicenseResponseSchema })
license: PartnerLicenseActivationLicenseResponseSchema
@ApiProperty({ type: () => PartnerLicenseActivationCountResponseSchema })
_count: PartnerLicenseActivationCountResponseSchema
}
export class PartnerLicenseActivationPaginatedResponseSchema {
@ApiProperty({ example: 'paginate' })
__mapped: string
@ApiProperty({ type: () => [PartnerLicenseActivationResponseSchema] })
items: PartnerLicenseActivationResponseSchema[]
@ApiProperty()
total: number
@ApiProperty()
page: number
@ApiProperty()
perPage: number
}
@@ -0,0 +1,49 @@
import { PartnerInfo } from '@/common/decorators/partnerInfo.decorator'
import { Controller, Get, Query } from '@nestjs/common'
import { ApiOkResponse, ApiQuery, ApiTags } from '@nestjs/swagger'
import { PartnerLicenseActivationPaginatedResponseSchema } from './dto/licenses-response.dto'
import { PartnerLicensesService } from './licenses.service'
@ApiTags('PartnerLicenses')
@Controller('partner/licenses')
export class PartnerLicensesController {
constructor(private readonly service: PartnerLicensesService) {}
@Get()
@ApiQuery({ name: 'page', required: false, type: Number, example: 1 })
@ApiQuery({
name: 'perPage',
required: false,
type: Number,
example: 10,
description: 'Max value is 50.',
})
@ApiQuery({ name: 'consumer_name', required: false, type: String })
@ApiQuery({ name: 'consumer_mobile', required: false, type: String })
@ApiQuery({
name: 'expires_from',
required: false,
type: String,
example: '2026-01-01',
})
@ApiQuery({ name: 'expires_to', required: false, type: String, example: '2026-12-31' })
@ApiOkResponse({ type: PartnerLicenseActivationPaginatedResponseSchema })
async findAll(
@PartnerInfo('id') partnerId: string,
@Query('page') page = '1',
@Query('perPage') perPage = '10',
@Query('consumer_name') consumer_name?: string,
@Query('consumer_mobile') consumer_mobile?: string,
@Query('expires_from') expires_from?: string,
@Query('expires_to') expires_to?: string,
) {
return this.service.findAll(partnerId, {
page: Number(page) || 1,
perPage: Number(perPage) || 10,
consumer_name,
consumer_mobile,
expires_from,
expires_to,
})
}
}
@@ -0,0 +1,11 @@
import { PrismaModule } from '@/prisma/prisma.module'
import { Module } from '@nestjs/common'
import { PartnerLicensesController } from './licenses.controller'
import { PartnerLicensesService } from './licenses.service'
@Module({
imports: [PrismaModule],
controllers: [PartnerLicensesController],
providers: [PartnerLicensesService],
})
export class PartnerLicensesModule {}
@@ -0,0 +1,167 @@
import { PrismaService } from '@/prisma/prisma.service'
import { BadRequestException, Injectable } from '@nestjs/common'
import { ResponseMapper } from 'common/response/response-mapper'
import {
PartnerLicenseActivationPaginatedResponseDto,
PartnerLicenseActivationResponseDto,
} from './dto/licenses-response.dto'
type FindPartnerLicensesParams = {
perPage?: number
page?: number
consumer_name?: string
consumer_mobile?: string
expires_from?: string
expires_to?: string
}
@Injectable()
export class PartnerLicensesService {
private readonly defaultPerPage = 10
private readonly maxPerPage = 50
constructor(private readonly prisma: PrismaService) {}
async findAll(
partner_id: string,
params: FindPartnerLicensesParams = {},
): Promise<PartnerLicenseActivationPaginatedResponseDto> {
const { perPage, page, consumer_name, consumer_mobile, expires_from, expires_to } =
params
const normalizedPage = Number.isFinite(page)
? Math.max(1, Math.floor(page as number))
: 1
const requestedPerPage = Number.isFinite(perPage)
? Math.max(1, Math.floor(perPage as number))
: this.defaultPerPage
const normalizedPerPage = Math.min(requestedPerPage, this.maxPerPage)
const andWhere: any[] = [
{
license: {
charge_transaction: {
partner_id,
},
},
},
]
const consumerName = consumer_name?.trim()
const consumerMobile = consumer_mobile?.trim()
if (consumerName || consumerMobile) {
andWhere.push({
business_activity: {
consumer: {
OR: [
{ first_name: { contains: consumerName } },
{ last_name: { contains: consumerName } },
],
},
},
})
}
if (consumerMobile) {
andWhere.push({
business_activity: {
consumer: {
mobile_number: {
contains: consumerMobile,
},
},
},
})
}
if (expires_from || expires_to) {
const expiresAtFilter: {
gte?: Date
lte?: Date
} = {}
if (expires_from) {
const fromDate = new Date(expires_from)
if (Number.isNaN(fromDate.getTime())) {
throw new BadRequestException('مقدار expires_from نامعتبر است.')
}
expiresAtFilter.gte = fromDate
}
if (expires_to) {
const toDate = new Date(expires_to)
if (Number.isNaN(toDate.getTime())) {
throw new BadRequestException('مقدار expires_to نامعتبر است.')
}
expiresAtFilter.lte = toDate
}
andWhere.push({
expires_at: expiresAtFilter,
})
}
const where = { AND: andWhere }
const [licenseActivations, total] = await this.prisma.$transaction(async tx => [
await tx.licenseActivation.findMany({
where,
orderBy: {
created_at: 'desc',
},
skip: (normalizedPage - 1) * normalizedPerPage,
take: normalizedPerPage,
select: {
id: true,
starts_at: true,
expires_at: true,
created_at: true,
updated_at: true,
business_activity: {
select: {
id: true,
name: true,
consumer: {
select: {
id: true,
first_name: true,
last_name: true,
mobile_number: true,
},
},
},
},
license: {
select: {
id: true,
accounts_limit: true,
charge_transaction: {
select: {
id: true,
tracking_code: true,
activation_expires_at: true,
},
},
},
},
_count: {
select: {
account_allocations: true,
},
},
},
}),
await tx.licenseActivation.count({ where }),
])
return ResponseMapper.paginate<PartnerLicenseActivationResponseDto>(
licenseActivations,
{
total,
page: normalizedPage,
perPage: normalizedPerPage,
},
)
}
}
+2 -1
View File
@@ -2,13 +2,14 @@ import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/c
import { JwtService } from '@nestjs/jwt' import { JwtService } from '@nestjs/jwt'
import { PartnerAccountsModule } from './accounts/accounts.module' import { PartnerAccountsModule } from './accounts/accounts.module'
import { PartnerCustomersModule } from './consumers/consumers.module' import { PartnerCustomersModule } from './consumers/consumers.module'
import { PartnerLicensesModule } from './licenses/licenses.module'
import { PartnerController } from './partners.controller' import { PartnerController } from './partners.controller'
import { PartnerMiddleware } from './partners.middleware' import { PartnerMiddleware } from './partners.middleware'
import { PartnerService } from './partners.service' import { PartnerService } from './partners.service'
@Module({ @Module({
controllers: [PartnerController], controllers: [PartnerController],
imports: [PartnerAccountsModule, PartnerCustomersModule], imports: [PartnerAccountsModule, PartnerCustomersModule, PartnerLicensesModule],
providers: [JwtService, PartnerService], providers: [JwtService, PartnerService],
}) })
export class PartnerModule implements NestModule { export class PartnerModule implements NestModule {
+2
View File
@@ -18,6 +18,7 @@ export class PosService {
select: { select: {
id: true, id: true,
name: true, name: true,
branch_code: true,
business_activity: { business_activity: {
select: { select: {
id: true, id: true,
@@ -72,6 +73,7 @@ export class PosService {
complex: { complex: {
id: complexId, id: complexId,
name: complexName, name: complexName,
branch_code: complex.branch_code,
}, },
businessActivity: { businessActivity: {
id: businessId, id: businessId,