feat: implement partner licenses module with pagination and filtering capabilities
This commit is contained in:
@@ -23,12 +23,22 @@ export class PosGuard {
|
||||
const { posId } = cookie
|
||||
|
||||
if (!posId) {
|
||||
throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
||||
return false
|
||||
// throw new ForbiddenException('شما دسترسی لازم را ندارید.')
|
||||
}
|
||||
|
||||
const checkLicenseActivation = await this.prisma.licenseAccountAllocation.findFirst({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
account_id: tokenPayload.account_id,
|
||||
},
|
||||
{
|
||||
account: {
|
||||
consumer_id: tokenPayload.user?.id,
|
||||
},
|
||||
},
|
||||
],
|
||||
license_activation: {
|
||||
OR: [
|
||||
{
|
||||
|
||||
@@ -84,6 +84,9 @@ export class ResponseMappingInterceptor implements NestInterceptor {
|
||||
// }
|
||||
break
|
||||
case 'paginate': {
|
||||
const { items: a, ...rest } = wrapped
|
||||
console.log(rest)
|
||||
|
||||
const items = Array.isArray(wrapped.items) ? wrapped.items : []
|
||||
const total =
|
||||
typeof wrapped.total === 'number' ? wrapped.total : items.length
|
||||
|
||||
@@ -12,9 +12,9 @@ export type MapperWrapper<T> =
|
||||
| { __mapped: 'delete' }
|
||||
|
||||
interface IPaginateMeta {
|
||||
count: number
|
||||
total: number
|
||||
page?: number
|
||||
pageSize?: number
|
||||
perPage?: number
|
||||
}
|
||||
|
||||
export const ResponseMapper = {
|
||||
@@ -38,12 +38,12 @@ export const ResponseMapper = {
|
||||
return { __mapped: 'list', items }
|
||||
},
|
||||
|
||||
paginate<T>(items: T[], { count, page = 1, pageSize: perPage }: IPaginateMeta) {
|
||||
return { __mapped: 'paginate', items, count, page, perPage }
|
||||
paginate<T>(items: T[], { total, page = 1, perPage }: IPaginateMeta) {
|
||||
return { __mapped: 'paginate', items, total, page, perPage }
|
||||
},
|
||||
|
||||
sequelizePaginate<T>(rows: T[], count: number, page = 1, pageSize = rows.length) {
|
||||
return { __mapped: 'sequelize', rows, count, page, pageSize }
|
||||
sequelizePaginate<T>(rows: T[], total: number, page = 1, pageSize = rows.length) {
|
||||
return { __mapped: 'sequelize', rows, total, page, pageSize }
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -46,14 +46,14 @@ export class AdminConsumersService {
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
const [consumers, count] = await this.prisma.$transaction([
|
||||
const [consumers, total] = await this.prisma.$transaction([
|
||||
this.prisma.consumer.findMany({
|
||||
select: this.defaultSelect,
|
||||
}),
|
||||
this.prisma.consumer.count(),
|
||||
])
|
||||
|
||||
return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), { count })
|
||||
return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), { total })
|
||||
}
|
||||
|
||||
async findOne(id: string) {
|
||||
|
||||
@@ -7,16 +7,16 @@ import { CreateDeviceDto, UpdateDeviceDto } from './dto/device.dto'
|
||||
export class DevicesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAll(page = 1, pageSize = 10) {
|
||||
const [items, count] = await this.prisma.$transaction([
|
||||
async findAll(page = 1, perPage = 10) {
|
||||
const [items, total] = await this.prisma.$transaction([
|
||||
this.prisma.device.findMany({
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
include: { brand: true },
|
||||
}),
|
||||
this.prisma.device.count(),
|
||||
])
|
||||
return ResponseMapper.paginate(items, { count, page, pageSize })
|
||||
return ResponseMapper.paginate(items, { total, page, perPage })
|
||||
}
|
||||
|
||||
async findOne(id: string) {
|
||||
|
||||
@@ -37,7 +37,7 @@ export class GoodsService {
|
||||
})
|
||||
|
||||
async findAll(guildId: string) {
|
||||
const [goods, count] = await this.prisma.$transaction([
|
||||
const [goods, total] = await this.prisma.$transaction([
|
||||
this.prisma.good.findMany({
|
||||
where: this.defaultWhere(guildId),
|
||||
select: this.defaultSelect,
|
||||
@@ -45,7 +45,7 @@ export class GoodsService {
|
||||
this.prisma.good.count(),
|
||||
])
|
||||
return ResponseMapper.paginate(goods, {
|
||||
count,
|
||||
total,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export class GuildsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
async findAll() {
|
||||
const [guilds, count] = await this.prisma.$transaction([
|
||||
const [guilds, total] = await this.prisma.$transaction([
|
||||
this.prisma.guild.findMany({
|
||||
include: {
|
||||
_count: {
|
||||
@@ -30,7 +30,7 @@ export class GuildsService {
|
||||
businessActivitiesCount: guild._count.business_activities,
|
||||
}
|
||||
}),
|
||||
{ count },
|
||||
{ total },
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,20 +48,20 @@ export class PartnerLicensesService {
|
||||
created_at: true,
|
||||
}
|
||||
|
||||
async findAll(page = 1, pageSize = 10) {
|
||||
const [licenses, count] = await this.prisma.$transaction([
|
||||
async findAll(page = 1, perPage = 10) {
|
||||
const [licenses, total] = await this.prisma.$transaction([
|
||||
this.prisma.licenseActivation.findMany({
|
||||
select: this.licenseDefaultSelect,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
}),
|
||||
this.prisma.licenseActivation.count(),
|
||||
])
|
||||
|
||||
return ResponseMapper.paginate(licenses, {
|
||||
count,
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
perPage,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { ResponseMapper } from 'common/response/response-mapper'
|
||||
export class PartnerActivatedLicensesService {
|
||||
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 = {
|
||||
license: {
|
||||
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({
|
||||
where: defaultWhere,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
@@ -71,8 +71,8 @@ export class PartnerActivatedLicensesService {
|
||||
|
||||
return ResponseMapper.paginate(mappedLicenses, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
perPage,
|
||||
total,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,18 +7,18 @@ import { ResponseMapper } from 'common/response/response-mapper'
|
||||
export class PartnerAllocatedAccountsService {
|
||||
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 = {
|
||||
charge_transaction: {
|
||||
partner_id,
|
||||
},
|
||||
}
|
||||
|
||||
const [allocations, count] = await this.prisma.$transaction(async tx => [
|
||||
const [allocations, total] = await this.prisma.$transaction(async tx => [
|
||||
await tx.partnerAccountQuotaCredit.findMany({
|
||||
where: defaultWhere,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
select: {
|
||||
id: true,
|
||||
created_at: true,
|
||||
@@ -54,8 +54,8 @@ export class PartnerAllocatedAccountsService {
|
||||
|
||||
return ResponseMapper.paginate(allocations, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
perPage,
|
||||
total,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -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 = {
|
||||
partner_id,
|
||||
}
|
||||
|
||||
const [transactions, count] = await this.prisma.$transaction(async tx => [
|
||||
const [transactions, total] = await this.prisma.$transaction(async tx => [
|
||||
await tx.partnerAccountQuotaChargeTransaction.findMany({
|
||||
where: defaultWhere,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
select: this.defaultSelect,
|
||||
}),
|
||||
await tx.partnerAccountQuotaChargeTransaction.count({
|
||||
@@ -72,8 +72,8 @@ export class PartnerAccountChargeTransactionService {
|
||||
|
||||
return ResponseMapper.paginate(mappedTransactions, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
perPage,
|
||||
total,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -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 = {
|
||||
partner_id,
|
||||
}
|
||||
|
||||
const [transactions, count] = await this.prisma.$transaction(async tx => [
|
||||
const [transactions, total] = await this.prisma.$transaction(async tx => [
|
||||
await tx.licenseChargeTransaction.findMany({
|
||||
where: defaultWhere,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
select: this.defaultSelect,
|
||||
}),
|
||||
await tx.licenseChargeTransaction.count({
|
||||
@@ -72,8 +72,8 @@ export class PartnerLicenseChargeTransactionService {
|
||||
|
||||
return ResponseMapper.paginate(mappedTransactions, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
perPage,
|
||||
total,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ export class AdminUsersService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAll() {
|
||||
const [users, count] = await this.prisma.$transaction([
|
||||
const [users, total] = await this.prisma.$transaction([
|
||||
this.prisma.admin.findMany(),
|
||||
this.prisma.admin.count(),
|
||||
])
|
||||
return ResponseMapper.paginate(
|
||||
users.map(user => ({ ...user, fullname: `${user.first_name} ${user.last_name}` })),
|
||||
{ count },
|
||||
{ total },
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -20,10 +20,10 @@ export class SalesInvoicesService {
|
||||
},
|
||||
}
|
||||
|
||||
const pageSize = 10
|
||||
const perPage = 10
|
||||
const page = 1
|
||||
|
||||
const [items, count] = await this.prisma.$transaction([
|
||||
const [items, total] = await this.prisma.$transaction([
|
||||
this.prisma.salesInvoice.findMany({
|
||||
where: defaultWhere,
|
||||
select: {
|
||||
@@ -91,14 +91,14 @@ export class SalesInvoicesService {
|
||||
},
|
||||
unknown_customer: true,
|
||||
},
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
}),
|
||||
this.prisma.salesInvoice.count({
|
||||
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) {
|
||||
|
||||
@@ -60,19 +60,19 @@ export class consumerCustomersService {
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(consumer_id: string, page = 1, pageSize = 10) {
|
||||
const [customers, count] = await this.prisma.$transaction(async tx => [
|
||||
async findAll(consumer_id: string, page = 1, perPage = 10) {
|
||||
const [customers, total] = await this.prisma.$transaction(async tx => [
|
||||
await tx.customer.findMany({
|
||||
where: this.defaultWhere(consumer_id),
|
||||
select: this.defaultSelect,
|
||||
skip: (page - 1) * pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: 10,
|
||||
}),
|
||||
await tx.customer.count({
|
||||
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) {
|
||||
|
||||
@@ -50,7 +50,7 @@ export class CustomerSaleInvoicesService {
|
||||
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 = {
|
||||
customer_id,
|
||||
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({
|
||||
where: salesWhere,
|
||||
select: {
|
||||
@@ -73,7 +73,7 @@ export class CustomerSaleInvoicesService {
|
||||
},
|
||||
},
|
||||
},
|
||||
skip: (page - 1) * pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: 10,
|
||||
}),
|
||||
await tx.salesInvoice.count({
|
||||
@@ -90,9 +90,9 @@ export class CustomerSaleInvoicesService {
|
||||
})
|
||||
|
||||
return ResponseMapper.paginate(mappedAccounts, {
|
||||
count,
|
||||
total,
|
||||
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 = {
|
||||
consumer_account: {
|
||||
consumer_id,
|
||||
},
|
||||
}
|
||||
const [invoices, count] = await this.prisma.$transaction(async tx => [
|
||||
const [invoices, total] = await this.prisma.$transaction(async tx => [
|
||||
await tx.salesInvoice.findMany({
|
||||
where: invoicesWhere,
|
||||
select: this.defaultSelect,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: perPage,
|
||||
}),
|
||||
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) {
|
||||
|
||||
@@ -37,12 +37,12 @@ export class PartnerConsumersService {
|
||||
partner_id,
|
||||
})
|
||||
|
||||
async findAll(partner_id: string, page = 1, pageSize = 10) {
|
||||
const [consumers, count] = await this.prisma.$transaction(async tx => [
|
||||
async findAll(partner_id: string, page = 1, perPage = 10) {
|
||||
const [consumers, total] = await this.prisma.$transaction(async tx => [
|
||||
await tx.consumer.findMany({
|
||||
where: this.defaultWhere(partner_id),
|
||||
select: this.defaultSelect,
|
||||
skip: (page - 1) * pageSize,
|
||||
skip: (page - 1) * perPage,
|
||||
take: 10,
|
||||
}),
|
||||
await tx.consumer.count({
|
||||
@@ -50,9 +50,9 @@ export class PartnerConsumersService {
|
||||
}),
|
||||
])
|
||||
return ResponseMapper.paginate(consumers.map(mapConsumerWithLicenseUtil), {
|
||||
count,
|
||||
total,
|
||||
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,13 +2,14 @@ import { MiddlewareConsumer, Module, NestModule, RequestMethod } from '@nestjs/c
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import { PartnerAccountsModule } from './accounts/accounts.module'
|
||||
import { PartnerCustomersModule } from './consumers/consumers.module'
|
||||
import { PartnerLicensesModule } from './licenses/licenses.module'
|
||||
import { PartnerController } from './partners.controller'
|
||||
import { PartnerMiddleware } from './partners.middleware'
|
||||
import { PartnerService } from './partners.service'
|
||||
|
||||
@Module({
|
||||
controllers: [PartnerController],
|
||||
imports: [PartnerAccountsModule, PartnerCustomersModule],
|
||||
imports: [PartnerAccountsModule, PartnerCustomersModule, PartnerLicensesModule],
|
||||
providers: [JwtService, PartnerService],
|
||||
})
|
||||
export class PartnerModule implements NestModule {
|
||||
|
||||
@@ -18,6 +18,7 @@ export class PosService {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
branch_code: true,
|
||||
business_activity: {
|
||||
select: {
|
||||
id: true,
|
||||
@@ -72,6 +73,7 @@ export class PosService {
|
||||
complex: {
|
||||
id: complexId,
|
||||
name: complexName,
|
||||
branch_code: complex.branch_code,
|
||||
},
|
||||
businessActivity: {
|
||||
id: businessId,
|
||||
|
||||
Reference in New Issue
Block a user