update license structures and setup file storage services
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common'
|
||||
import { AdminUsersService } from './consumers.service'
|
||||
import { AdminConsumersService } from './consumers.service'
|
||||
import { CreateConsumerDto, UpdateConsumerDto } from './dto/consumer.dto'
|
||||
|
||||
@Controller('admin/consumers')
|
||||
export class AdminUsersController {
|
||||
constructor(private readonly usersService: AdminUsersService) {}
|
||||
constructor(private readonly usersService: AdminConsumersService) {}
|
||||
|
||||
@Get()
|
||||
async findAll() {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Module } from '@nestjs/common'
|
||||
import { AdminUserAccountsModule } from './accounts/accounts.module'
|
||||
import { AdminConsumerBusinessActivitiesModule } from './business-activities/business-activities.module'
|
||||
import { AdminUsersController } from './consumers.controller'
|
||||
import { AdminUsersService } from './consumers.service'
|
||||
import { AdminConsumersService } from './consumers.service'
|
||||
import { AdminConsumerLicensesModule } from './licenses/licenses.module'
|
||||
|
||||
@Module({
|
||||
@@ -14,7 +14,7 @@ import { AdminConsumerLicensesModule } from './licenses/licenses.module'
|
||||
AdminConsumerLicensesModule,
|
||||
],
|
||||
controllers: [AdminUsersController],
|
||||
providers: [AdminUsersService],
|
||||
providers: [AdminConsumersService],
|
||||
exports: [AdminUserAccountsModule],
|
||||
})
|
||||
export class AdminConsumersModule {}
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
AccountStatus,
|
||||
AccountType,
|
||||
ConsumerRole,
|
||||
LicenseStatus,
|
||||
PartnerStatus,
|
||||
} from '@/generated/prisma/enums'
|
||||
import { ConsumerCreateInput, ConsumerSelect } from '@/generated/prisma/models'
|
||||
@@ -13,7 +12,7 @@ import { ResponseMapper } from 'common/response/response-mapper'
|
||||
import { CreateConsumerDto, UpdateConsumerDto } from './dto/consumer.dto'
|
||||
|
||||
@Injectable()
|
||||
export class AdminUsersService {
|
||||
export class AdminConsumersService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private readonly defaultSelect: ConsumerSelect = {
|
||||
@@ -23,22 +22,67 @@ export class AdminUsersService {
|
||||
mobile_number: true,
|
||||
status: true,
|
||||
created_at: true,
|
||||
license: {
|
||||
activated_licenses: {
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
status: true,
|
||||
partner: {
|
||||
license: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
charged_license_transaction: {
|
||||
select: {
|
||||
partner: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
private readonly mapConsumer = (consumer: any) => {
|
||||
const { activated_licenses, ...rest } = consumer
|
||||
|
||||
let lastLicense: any = null
|
||||
|
||||
if (consumer.activated_licenses.length) {
|
||||
lastLicense = consumer.activated_licenses[0]
|
||||
if (consumer.activated_licenses.length > 1) {
|
||||
const activeLicenseInfo = consumer.activated_licenses.find(
|
||||
activated_license => activated_license.expires_at,
|
||||
)
|
||||
|
||||
if (!activeLicenseInfo) {
|
||||
consumer.activated_licenses.sort((a, b) =>
|
||||
a.expires_at > b.expires_at ? 1 : -1,
|
||||
)
|
||||
lastLicense = consumer.activated_licenses[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...rest,
|
||||
fullname: `${rest?.first_name} ${rest?.last_name}`,
|
||||
license_info: this.prepareLicenseInfo(lastLicense),
|
||||
}
|
||||
}
|
||||
|
||||
private readonly prepareLicenseInfo = (latestLicense: any) => {
|
||||
if (!latestLicense) return null
|
||||
const { license, ...rest } = latestLicense
|
||||
|
||||
return {
|
||||
...rest,
|
||||
partner: license.charged_license_transaction.partner,
|
||||
}
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
const [consumers, count] = await this.prisma.$transaction([
|
||||
this.prisma.consumer.findMany({
|
||||
@@ -46,32 +90,24 @@ export class AdminUsersService {
|
||||
}),
|
||||
this.prisma.consumer.count(),
|
||||
])
|
||||
return ResponseMapper.paginate(
|
||||
consumers.map(consumer => ({
|
||||
...consumer,
|
||||
fullname: `${consumer.first_name} ${consumer.last_name}`,
|
||||
})),
|
||||
{ count },
|
||||
)
|
||||
|
||||
return ResponseMapper.paginate(consumers.map(this.mapConsumer), { count })
|
||||
}
|
||||
|
||||
async findOne(id: string) {
|
||||
this.prisma.license.findFirst({
|
||||
where: {},
|
||||
})
|
||||
const consumer = await this.prisma.consumer.findUniqueOrThrow({
|
||||
where: { id },
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
|
||||
return ResponseMapper.single({
|
||||
...consumer,
|
||||
fullname: `${consumer?.first_name} ${consumer?.last_name}`,
|
||||
})
|
||||
return ResponseMapper.single(this.mapConsumer(consumer))
|
||||
}
|
||||
|
||||
async create(data: CreateConsumerDto) {
|
||||
const { username, password, license, ...rest } = data
|
||||
const startOfToday = new Date()
|
||||
startOfToday.setHours(0, 0, 0, 0)
|
||||
|
||||
const { username, password, partner_id, ...rest } = data
|
||||
const dataToCreate: ConsumerCreateInput = {
|
||||
...rest,
|
||||
consumer_accounts: {
|
||||
@@ -88,52 +124,37 @@ export class AdminUsersService {
|
||||
},
|
||||
},
|
||||
}
|
||||
if (license) {
|
||||
if (license.partner_id) {
|
||||
const partner = await this.prisma.partner.findUnique({
|
||||
where: {
|
||||
id: license.partner_id,
|
||||
status: PartnerStatus.ACTIVE,
|
||||
if (partner_id) {
|
||||
const partnerLicense = await this.prisma.license.findFirst({
|
||||
where: {
|
||||
charged_license_transaction: {
|
||||
partner: {
|
||||
id: partner_id,
|
||||
status: PartnerStatus.ACTIVE,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
name: true,
|
||||
license_quota: true,
|
||||
_count: {
|
||||
select: {
|
||||
licenses: true,
|
||||
activated_license: null,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
charged_license_transaction: {
|
||||
select: {
|
||||
partner: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
status: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (!partner) {
|
||||
throw new BadRequestException('متاسفانه شریک تجاری مورد نظر شما یافت نشد')
|
||||
}
|
||||
const partnerLicensesRemainsQuota =
|
||||
partner.license_quota || 0 - partner._count.licenses
|
||||
|
||||
if (!partnerLicensesRemainsQuota) {
|
||||
throw new BadRequestException(
|
||||
`تعداد لایسنسهای فعلی شریک تجاری ${partner.name} به پایان رسیده است`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
dataToCreate.license = {
|
||||
create: {
|
||||
starts_at: license.starts_at,
|
||||
expires_at: new Date(
|
||||
new Date(license.starts_at).setFullYear(
|
||||
new Date(license.starts_at).getFullYear() + 1,
|
||||
),
|
||||
).toISOString(),
|
||||
status: LicenseStatus.ACTIVE,
|
||||
partner: {
|
||||
connect: {
|
||||
id: license.partner_id,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (!partnerLicense) {
|
||||
throw new BadRequestException(
|
||||
`تعداد لایسنسهای فعلی شریک تجاری به پایان رسیده است.`,
|
||||
)
|
||||
}
|
||||
}
|
||||
return this.prisma.consumer.create({
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ConsumerStatus } from '@/generated/prisma/enums'
|
||||
import { ApiProperty, OmitType, PartialType } from '@nestjs/swagger'
|
||||
import { IsEnum, IsObject, IsString } from 'class-validator'
|
||||
import { CreateLicenseDto } from '../licenses/dto/license.dto'
|
||||
import { IsEnum, IsOptional, IsString } from 'class-validator'
|
||||
|
||||
export class CreateConsumerDto {
|
||||
@IsString()
|
||||
@@ -24,14 +23,13 @@ export class CreateConsumerDto {
|
||||
@ApiProperty({ required: true })
|
||||
password: string
|
||||
|
||||
@IsObject()
|
||||
@ApiProperty()
|
||||
license: CreateLicenseDto
|
||||
@IsOptional()
|
||||
partner_id: string
|
||||
}
|
||||
export class UpdateConsumerDto extends OmitType(PartialType(CreateConsumerDto), [
|
||||
'password',
|
||||
'username',
|
||||
'license',
|
||||
]) {
|
||||
@IsEnum(ConsumerStatus)
|
||||
@ApiProperty({ enum: ConsumerStatus })
|
||||
|
||||
@@ -17,7 +17,10 @@ export class CreateLicenseDto {
|
||||
)
|
||||
expires_at?: Date
|
||||
|
||||
@ApiProperty()
|
||||
@ApiProperty({
|
||||
required: true,
|
||||
nullable: false,
|
||||
})
|
||||
partner_id: string
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Body, Controller, Param, Patch, Post } from '@nestjs/common'
|
||||
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
|
||||
import { ApiTags } from '@nestjs/swagger'
|
||||
import { CreateLicenseDto, UpdateLicenseDto } from './dto/license.dto'
|
||||
import { CreateLicenseDto } from './dto/license.dto'
|
||||
import { LicensesService } from './licenses.service'
|
||||
|
||||
@ApiTags('AdminConsumerAccounts')
|
||||
@@ -8,15 +8,20 @@ import { LicensesService } from './licenses.service'
|
||||
export class LicensesController {
|
||||
constructor(private readonly service: LicensesService) {}
|
||||
|
||||
@Get()
|
||||
async findAll(@Param('consumerId') consumerId: string) {
|
||||
return this.service.findAll(consumerId)
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Param('consumerId') consumerId: string, @Body() data: CreateLicenseDto) {
|
||||
return this.service.create(consumerId, data)
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(@Param('id') id: string, @Body() data: UpdateLicenseDto) {
|
||||
return this.service.update(id, data)
|
||||
}
|
||||
// @Patch(':id')
|
||||
// async update(@Param('id') id: string, @Body() data: UpdateLicenseDto) {
|
||||
// return this.service.update(id, data)
|
||||
// }
|
||||
|
||||
// @Delete(':id')
|
||||
// async delete(@Param('id') id: string) {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { LicenseStatus } from '@/generated/prisma/enums'
|
||||
import { LicenseUpdateInput } from '@/generated/prisma/models'
|
||||
import { PartnerStatus } from '@/generated/prisma/enums'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { BadRequestException, Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
import { CreateLicenseDto, UpdateLicenseDto } from './dto/license.dto'
|
||||
import { CreateLicenseDto } from './dto/license.dto'
|
||||
|
||||
@Injectable()
|
||||
export class LicensesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
private startOfToday = new Date()
|
||||
|
||||
constructor(private readonly prisma: PrismaService) {
|
||||
this.startOfToday.setHours(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
private readonly setExpireDate = (starts_at: Date) => {
|
||||
return new Date(
|
||||
@@ -15,85 +18,143 @@ export class LicensesService {
|
||||
).toISOString()
|
||||
}
|
||||
|
||||
async create(consumerId: string, data: CreateLicenseDto) {
|
||||
const { starts_at, expires_at } = data
|
||||
const license = await this.prisma.license.create({
|
||||
data: {
|
||||
starts_at,
|
||||
expires_at: expires_at ?? this.setExpireDate(starts_at),
|
||||
partner: {
|
||||
connect: {
|
||||
id: data.partner_id,
|
||||
async findAll(consumer_id: string) {
|
||||
const licenses = await this.prisma.activatedLicense.findMany({
|
||||
where: {
|
||||
consumer_id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
created_at: true,
|
||||
license: {
|
||||
select: {
|
||||
id: true,
|
||||
charged_license_transaction: {
|
||||
select: {
|
||||
partner: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
consumer: {
|
||||
connect: {
|
||||
id: consumerId,
|
||||
},
|
||||
},
|
||||
status: LicenseStatus.ACTIVE,
|
||||
},
|
||||
})
|
||||
return ResponseMapper.create(license)
|
||||
|
||||
return ResponseMapper.list(licenses)
|
||||
}
|
||||
|
||||
async update(id: string, data: UpdateLicenseDto) {
|
||||
async create(consumerId: string, data: CreateLicenseDto) {
|
||||
const { starts_at, expires_at, partner_id } = data
|
||||
const currentLicense = await this.prisma.license.findUnique({
|
||||
where: { id },
|
||||
select: {
|
||||
partner_id: true,
|
||||
},
|
||||
})
|
||||
|
||||
if (partner_id && currentLicense?.partner_id !== partner_id) {
|
||||
const partner = await this.prisma.partner.findUnique({
|
||||
const license = await this.prisma.$transaction(async tx => {
|
||||
const partnerLicense = await tx.license.findFirst({
|
||||
where: {
|
||||
id: partner_id,
|
||||
activated_license: null,
|
||||
charged_license_transaction: {
|
||||
activation_expires_at: {
|
||||
gte: this.startOfToday,
|
||||
},
|
||||
partner: {
|
||||
id: partner_id,
|
||||
status: PartnerStatus.ACTIVE,
|
||||
},
|
||||
},
|
||||
},
|
||||
select: {
|
||||
name: true,
|
||||
license_quota: true,
|
||||
_count: {
|
||||
select: {
|
||||
licenses: true,
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
|
||||
if (!partnerLicense) {
|
||||
throw new BadRequestException(
|
||||
`تعداد لایسنسهای فعلی شریک تجاری به پایان رسیده است.`,
|
||||
)
|
||||
}
|
||||
|
||||
return await this.prisma.activatedLicense.create({
|
||||
data: {
|
||||
starts_at,
|
||||
expires_at: expires_at ?? this.setExpireDate(starts_at),
|
||||
consumer: {
|
||||
connect: {
|
||||
id: consumerId,
|
||||
},
|
||||
},
|
||||
license: {
|
||||
connect: {
|
||||
id: partnerLicense.id,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (!((partner?.license_quota || 0) - (partner?._count.licenses || 0))) {
|
||||
throw new BadRequestException(`تعداد لایسنسهای ${partner?.name} کافی نیست.`)
|
||||
}
|
||||
}
|
||||
|
||||
const dataToUpdate: LicenseUpdateInput = {}
|
||||
|
||||
if (partner_id) {
|
||||
dataToUpdate.partner = {
|
||||
connect: {
|
||||
id: partner_id,
|
||||
},
|
||||
}
|
||||
} else if (currentLicense?.partner_id) {
|
||||
dataToUpdate.partner = {
|
||||
disconnect: {
|
||||
id: currentLicense?.partner_id,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if (starts_at) {
|
||||
dataToUpdate.starts_at = starts_at
|
||||
dataToUpdate.expires_at = this.setExpireDate(starts_at)
|
||||
}
|
||||
|
||||
const license = await this.prisma.license.update({
|
||||
where: { id },
|
||||
data: {
|
||||
...dataToUpdate,
|
||||
},
|
||||
})
|
||||
return ResponseMapper.update(license)
|
||||
|
||||
return ResponseMapper.create(license)
|
||||
}
|
||||
|
||||
// async update(id: string, data: UpdateLicenseDto) {
|
||||
// const { starts_at, expires_at, partner_id } = data
|
||||
// const currentLicense = await this.prisma.license.findUnique({
|
||||
// where: { id },
|
||||
// select: {
|
||||
// partner_id: true,
|
||||
// },
|
||||
// })
|
||||
|
||||
// if (partner_id && currentLicense?.partner_id !== partner_id) {
|
||||
// const partner = await this.prisma.partner.findUnique({
|
||||
// where: {
|
||||
// id: partner_id,
|
||||
// },
|
||||
// select: {
|
||||
// name: true,
|
||||
// license_quota: true,
|
||||
// _count: {
|
||||
// select: {
|
||||
// licenses: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
|
||||
// if (!((partner?.license_quota || 0) - (partner?._count.licenses || 0))) {
|
||||
// throw new BadRequestException(`تعداد لایسنسهای ${partner?.name} کافی نیست.`)
|
||||
// }
|
||||
// }
|
||||
|
||||
// const dataToUpdate: LicenseUpdateInput = {}
|
||||
|
||||
// if (partner_id) {
|
||||
// dataToUpdate.partner = {
|
||||
// connect: {
|
||||
// id: partner_id,
|
||||
// },
|
||||
// }
|
||||
// } else if (currentLicense?.partner_id) {
|
||||
// dataToUpdate.partner = {
|
||||
// disconnect: {
|
||||
// id: currentLicense?.partner_id,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (starts_at) {
|
||||
// dataToUpdate.starts_at = starts_at
|
||||
// dataToUpdate.expires_at = this.setExpireDate(starts_at)
|
||||
// }
|
||||
|
||||
// const license = await this.prisma.license.update({
|
||||
// where: { id },
|
||||
// data: {
|
||||
// ...dataToUpdate,
|
||||
// },
|
||||
// })
|
||||
// return ResponseMapper.update(license)
|
||||
// }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user