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)
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
import { GoodsController } from './goods.controller'
|
||||
import { GoodsService } from './goods.service'
|
||||
import { GuildGoodImagesModule } from './images/images.module'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, GuildGoodImagesModule],
|
||||
controllers: [GoodsController],
|
||||
providers: [GoodsService],
|
||||
})
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { TokenAccount } from '@/common/decorators/tokenInfo.decorator'
|
||||
import { multerImageOptions } from '@/multer.config'
|
||||
import {
|
||||
BadRequestException,
|
||||
Controller,
|
||||
Param,
|
||||
Post,
|
||||
UploadedFile,
|
||||
UseInterceptors,
|
||||
} from '@nestjs/common'
|
||||
import { FileInterceptor } from '@nestjs/platform-express'
|
||||
import { ApiBody, ApiConsumes } from '@nestjs/swagger'
|
||||
import { GuildGoodImagesService } from './images.service'
|
||||
|
||||
@Controller('admin/guilds/:guildId/goods/:goodId/images')
|
||||
export class GuildGoodImagesController {
|
||||
constructor(private readonly service: GuildGoodImagesService) {}
|
||||
|
||||
@Post('')
|
||||
@UseInterceptors(FileInterceptor('file', multerImageOptions))
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@ApiBody({
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
file: { type: 'string', format: 'binary' },
|
||||
},
|
||||
},
|
||||
})
|
||||
async uploadImage(
|
||||
@TokenAccount('account_id') accountId: string,
|
||||
@Param('guildId') guildId: string,
|
||||
@Param('goodId') goodId: string,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
) {
|
||||
if (!file) {
|
||||
throw new BadRequestException('فایل را وارد کنید')
|
||||
}
|
||||
|
||||
const url = await this.service.uploadFile(accountId, goodId, file)
|
||||
return { url }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { UploaderModule } from '@/modules/uploader/uploader.module'
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
import { GuildGoodImagesController } from './images.controller'
|
||||
import { GuildGoodImagesService } from './images.service'
|
||||
|
||||
@Module({
|
||||
controllers: [GuildGoodImagesController],
|
||||
providers: [GuildGoodImagesService],
|
||||
imports: [PrismaModule, UploaderModule],
|
||||
})
|
||||
export class GuildGoodImagesModule {}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { UploadedFileTypes } from '@/common/enums/enums'
|
||||
import { UploaderService } from '@/modules/uploader/uploader.service'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { BadRequestException, Injectable } from '@nestjs/common'
|
||||
|
||||
@Injectable()
|
||||
export class GuildGoodImagesService {
|
||||
constructor(
|
||||
private readonly prisma: PrismaService,
|
||||
private readonly uploadFileService: UploaderService,
|
||||
) {}
|
||||
|
||||
async uploadFile(account_id: string, goodId: string, file: Express.Multer.File) {
|
||||
try {
|
||||
const currentImage = await this.prisma.good.findUniqueOrThrow({
|
||||
where: {
|
||||
id: goodId,
|
||||
},
|
||||
select: {
|
||||
image_url: true,
|
||||
},
|
||||
})
|
||||
const url = await this.uploadFileService.uploadFile(file, UploadedFileTypes.GOOD)
|
||||
if (url) {
|
||||
if (currentImage.image_url) {
|
||||
this.uploadFileService.deleteFile(currentImage.image_url)
|
||||
}
|
||||
return this.prisma.good.update({
|
||||
where: {
|
||||
id: goodId,
|
||||
is_default_guild_good: true,
|
||||
},
|
||||
data: {
|
||||
image_url: url,
|
||||
},
|
||||
})
|
||||
} else {
|
||||
throw new BadRequestException('متاسفانه در بارگذاری فایل مشکلی پیش آمده')
|
||||
}
|
||||
} catch (err) {
|
||||
throw err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Body, Controller, Get, Param, Patch } from '@nestjs/common'
|
||||
import { UpdateLicenseDto } from './dto/license.dto'
|
||||
import { Controller, Get, Param } from '@nestjs/common'
|
||||
import { PartnerLicensesService } from './licenses.service'
|
||||
|
||||
@Controller('admin/licenses')
|
||||
@@ -16,10 +15,10 @@ export class LicensesController {
|
||||
return this.licensesService.findOne(id)
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(@Param('id') id: string, @Body() data: UpdateLicenseDto) {
|
||||
return this.licensesService.update(id, data)
|
||||
}
|
||||
// @Patch(':id')
|
||||
// async update(@Param('id') id: string, @Body() data: UpdateLicenseDto) {
|
||||
// return this.licensesService.update(id, data)
|
||||
// }
|
||||
|
||||
// @Delete(':id')
|
||||
// async delete(@Param('id') id: string) {
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { LicenseSelect } from '@/generated/prisma/models'
|
||||
import { ActivatedLicenseSelect } from '@/generated/prisma/models'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
import { UpdateLicenseDto } from './dto/license.dto'
|
||||
|
||||
@Injectable()
|
||||
export class PartnerLicensesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private readonly licenseDefaultSelect: LicenseSelect = {
|
||||
private readonly licenseDefaultSelect: ActivatedLicenseSelect = {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
status: true,
|
||||
consumer: {
|
||||
select: {
|
||||
first_name: true,
|
||||
@@ -21,22 +19,31 @@ export class PartnerLicensesService {
|
||||
status: true,
|
||||
},
|
||||
},
|
||||
partner: {
|
||||
license: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
charged_license_transaction: {
|
||||
select: {
|
||||
partner: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
async findAll(page = 1, pageSize = 10) {
|
||||
const [licenses, count] = await this.prisma.$transaction([
|
||||
this.prisma.license.findMany({
|
||||
this.prisma.activatedLicense.findMany({
|
||||
select: this.licenseDefaultSelect,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
}),
|
||||
this.prisma.license.count(),
|
||||
this.prisma.activatedLicense.count(),
|
||||
])
|
||||
|
||||
return ResponseMapper.paginate(licenses, {
|
||||
@@ -47,22 +54,13 @@ export class PartnerLicensesService {
|
||||
}
|
||||
|
||||
async findOne(id: string) {
|
||||
const license = await this.prisma.license.findFirst({
|
||||
where: { id },
|
||||
include: this.licenseDefaultSelect,
|
||||
omit: {
|
||||
partner_id: true,
|
||||
const license = await this.prisma.activatedLicense.findFirst({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
select: this.licenseDefaultSelect,
|
||||
})
|
||||
|
||||
return ResponseMapper.single(license)
|
||||
}
|
||||
|
||||
async update(id: string, data: UpdateLicenseDto) {
|
||||
const license = await this.prisma.license.update({
|
||||
where: { id },
|
||||
data: { ...data },
|
||||
})
|
||||
return ResponseMapper.update(license)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { Controller, Get, Param } from '@nestjs/common'
|
||||
import { ApiTags } from '@nestjs/swagger'
|
||||
import { PartnerActivatedLicensesService } from './activatedLicenses.service'
|
||||
|
||||
@ApiTags('AdminPartnerActivatedLicenses')
|
||||
@Controller('admin/partners/:partnerId/activated-licenses')
|
||||
export class PartnerLicensesController {
|
||||
constructor(private readonly service: PartnerActivatedLicensesService) {}
|
||||
|
||||
@Get()
|
||||
async findAll(@Param('partnerId') partnerId: string) {
|
||||
return this.service.findAll(partnerId)
|
||||
}
|
||||
|
||||
// @Get(':id')
|
||||
// async findOne(@Param('partnerId') partnerId: string, @Param('id') id: string) {
|
||||
// return this.service.findOne(partnerId, id)
|
||||
// }
|
||||
|
||||
// @Post()
|
||||
// async create(
|
||||
// @Param('partnerId') partnerId: string,
|
||||
// @Body() data: CreatePartnerLicenseDto,
|
||||
// ) {
|
||||
// return this.licensesService.create(partnerId, data)
|
||||
// }
|
||||
|
||||
// @Patch(':id')
|
||||
// async update(
|
||||
// @Param('partnerId') partnerId: string,
|
||||
// @Param('id') id: string,
|
||||
// @Body() data: UpdateLicenseDto,
|
||||
// ) {
|
||||
// return this.licensesService.update(partnerId, id, data)
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PartnerLicensesController } from './activatedLicenses.controller'
|
||||
import { PartnerActivatedLicensesService } from './activatedLicenses.service'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [PartnerLicensesController],
|
||||
providers: [PartnerActivatedLicensesService],
|
||||
exports: [PartnerActivatedLicensesService],
|
||||
})
|
||||
export class AdminPartnerActivatedLicensesModule {}
|
||||
@@ -0,0 +1,62 @@
|
||||
import { ActivatedLicenseWhereInput } from '@/generated/prisma/models'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
|
||||
@Injectable()
|
||||
export class PartnerActivatedLicensesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAll(partner_id: string, page = 1, pageSize = 10) {
|
||||
const defaultWhere: ActivatedLicenseWhereInput = {
|
||||
license: {
|
||||
charged_license_transaction: {
|
||||
partner_id,
|
||||
},
|
||||
},
|
||||
}
|
||||
const [licenses, count] = await this.prisma.$transaction(async tx => [
|
||||
await tx.activatedLicense.findMany({
|
||||
where: defaultWhere,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
license_id: true,
|
||||
created_at: true,
|
||||
consumer: {
|
||||
select: {
|
||||
id: true,
|
||||
first_name: true,
|
||||
last_name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
await tx.activatedLicense.count({
|
||||
where: defaultWhere,
|
||||
}),
|
||||
])
|
||||
|
||||
return ResponseMapper.paginate(licenses, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
})
|
||||
}
|
||||
|
||||
// async update(partnerId: string, id: string, data: UpdateLicenseDto) {
|
||||
// const license = await this.prisma.license.update({
|
||||
// where: { id },
|
||||
// data: { ...data, partner_id: partnerId },
|
||||
// })
|
||||
// return ResponseMapper.update(license)
|
||||
// }
|
||||
|
||||
async delete(partnerId: string, id: string) {
|
||||
await this.prisma.license.delete({ where: { id } })
|
||||
return ResponseMapper.delete()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export class CreatePartnerLicenseDto {}
|
||||
|
||||
export class UpdateLicenseDto {}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { Body, Controller, Get, Param, Post } from '@nestjs/common'
|
||||
import { ApiTags } from '@nestjs/swagger'
|
||||
import { PartnerChargedLicenseTransactionsService } from './chargedLicenseTransactions.service'
|
||||
import { ChargeLicenseDto } from './dto/chargedLicenseTransactions.dto'
|
||||
|
||||
@ApiTags('AdminPartnerChargedLicenseTransactions')
|
||||
@Controller('admin/partners/:partnerId/charge-license-transactions')
|
||||
export class PartnerChargedLicenseTransactionsController {
|
||||
constructor(private readonly service: PartnerChargedLicenseTransactionsService) {}
|
||||
|
||||
@Get()
|
||||
async findAll(@Param('partnerId') partnerId: string) {
|
||||
return this.service.findAll(partnerId)
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
async findOne(@Param('partnerId') partnerId: string, @Param('id') id: string) {
|
||||
return this.service.findOne(partnerId, id)
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(@Param('partnerId') partnerId: string, @Body() data: ChargeLicenseDto) {
|
||||
return this.service.create(partnerId, data)
|
||||
}
|
||||
|
||||
// @Patch(':id')
|
||||
// async update(
|
||||
// @Param('partnerId') partnerId: string,
|
||||
// @Param('id') id: string,
|
||||
// @Body() data: UpdateLicenseDto,
|
||||
// ) {
|
||||
// return this.licensesService.update(partnerId, id, data)
|
||||
// }
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
import { PartnerChargedLicenseTransactionsController } from './chargedLicenseTransactions.controller'
|
||||
import { PartnerChargedLicenseTransactionsService } from './chargedLicenseTransactions.service'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule],
|
||||
controllers: [PartnerChargedLicenseTransactionsController],
|
||||
providers: [PartnerChargedLicenseTransactionsService],
|
||||
exports: [PartnerChargedLicenseTransactionsService],
|
||||
})
|
||||
export class AdminPartnerChargedLicenseTransactionsModule {}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
import {
|
||||
ChargedLicenseTransactionsWhereInput,
|
||||
LicenseCreateInput,
|
||||
} from '@/generated/prisma/models'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { BadRequestException, Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
import { ChargeLicenseDto } from './dto/chargedLicenseTransactions.dto'
|
||||
|
||||
@Injectable()
|
||||
export class PartnerChargedLicenseTransactionsService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private readonly mappedTransaction = (transaction: any) => {
|
||||
const { licenses, ...rest } = transaction
|
||||
return {
|
||||
...rest,
|
||||
charged_license_count: licenses.length,
|
||||
remained_license_count: licenses.filter(license => !license?.activated_license)
|
||||
.length,
|
||||
}
|
||||
}
|
||||
|
||||
async findAll(partner_id: string, page = 1, pageSize = 10) {
|
||||
const defaultWhere: ChargedLicenseTransactionsWhereInput = {
|
||||
partner_id,
|
||||
}
|
||||
|
||||
const [transactions, count] = await this.prisma.$transaction(async tx => [
|
||||
await tx.chargedLicenseTransactions.findMany({
|
||||
where: defaultWhere,
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
select: {
|
||||
id: true,
|
||||
created_at: true,
|
||||
activation_expires_at: true,
|
||||
licenses: {
|
||||
select: {
|
||||
activated_license: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
await tx.chargedLicenseTransactions.count({
|
||||
where: defaultWhere,
|
||||
}),
|
||||
])
|
||||
|
||||
const mappedTransactions = transactions.map(this.mappedTransaction)
|
||||
|
||||
return ResponseMapper.paginate(mappedTransactions, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
})
|
||||
}
|
||||
|
||||
async findOne(partner_id: string, id: string) {
|
||||
const transaction = this.prisma.chargedLicenseTransactions.findUniqueOrThrow({
|
||||
where: {
|
||||
id,
|
||||
partner_id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
created_at: true,
|
||||
activation_expires_at: true,
|
||||
licenses: {
|
||||
select: {
|
||||
id: true,
|
||||
activated_license: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
return ResponseMapper.single(this.mappedTransaction(transaction))
|
||||
}
|
||||
|
||||
async create(partner_id: string, data: ChargeLicenseDto) {
|
||||
try {
|
||||
return await this.prisma.$transaction(async tx => {
|
||||
const transaction = await tx.chargedLicenseTransactions.create({
|
||||
data: {
|
||||
activation_expires_at: data.activated_expires_at,
|
||||
partner: { connect: { id: partner_id } },
|
||||
},
|
||||
})
|
||||
|
||||
if (!transaction) {
|
||||
throw new BadRequestException('متاسفانه مشکلی پیش آمده است.')
|
||||
}
|
||||
|
||||
const licenseCreationPromises: any[] = []
|
||||
for (let i = 0; i < data.quantity; i++) {
|
||||
const license: LicenseCreateInput = {
|
||||
charged_license_transaction: {
|
||||
connect: {
|
||||
id: transaction.id,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
licenseCreationPromises.push(tx.license.create({ data: license }))
|
||||
}
|
||||
const createdLicenses = await Promise.all(licenseCreationPromises)
|
||||
|
||||
return { transaction, createdLicenses }
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
import { ApiProperty } from '@nestjs/swagger'
|
||||
import { IsDateString, IsNumber } from 'class-validator'
|
||||
|
||||
export class CreatePartnerLicenseDto {}
|
||||
|
||||
export class UpdateLicenseDto {}
|
||||
|
||||
export class ChargeLicenseDto {
|
||||
@ApiProperty({
|
||||
required: true,
|
||||
minimum: 1,
|
||||
maximum: 10_000,
|
||||
})
|
||||
@IsNumber({
|
||||
maxDecimalPlaces: 0,
|
||||
})
|
||||
quantity: number
|
||||
|
||||
@ApiProperty({
|
||||
required: true,
|
||||
})
|
||||
@IsDateString()
|
||||
activated_expires_at: string
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
import { IsDateString, IsEnum, IsOptional, IsString } from 'class-validator'
|
||||
import { AccountStatus, LicenseStatus, POSType } from 'generated/prisma/enums'
|
||||
|
||||
export class CreatePartnerLicenseDto {
|
||||
@IsString()
|
||||
first_name: string
|
||||
|
||||
@IsString()
|
||||
last_name: string
|
||||
|
||||
@IsString()
|
||||
mobile_number: string
|
||||
|
||||
@IsString()
|
||||
national_code: string
|
||||
|
||||
@IsString()
|
||||
username: string
|
||||
|
||||
@IsString()
|
||||
password: string
|
||||
|
||||
@IsEnum(AccountStatus)
|
||||
account_status: AccountStatus
|
||||
|
||||
@IsString()
|
||||
guild: string
|
||||
|
||||
@IsString()
|
||||
business_activity_name: string
|
||||
|
||||
@IsString()
|
||||
tax_id: string
|
||||
|
||||
@IsString()
|
||||
complex_name: string
|
||||
|
||||
@IsString()
|
||||
pos_serial: string
|
||||
|
||||
@IsString()
|
||||
pos_status: string
|
||||
|
||||
@IsEnum(POSType)
|
||||
pos_type: POSType
|
||||
|
||||
@IsString()
|
||||
pos_device: string
|
||||
|
||||
@IsDateString()
|
||||
@IsOptional()
|
||||
starts_at: string
|
||||
|
||||
@IsDateString()
|
||||
@IsOptional()
|
||||
expires_at: string
|
||||
}
|
||||
|
||||
export class UpdateLicenseDto {
|
||||
@IsString()
|
||||
pos_id?: string
|
||||
|
||||
@IsDateString()
|
||||
starts_at?: string
|
||||
|
||||
@IsDateString()
|
||||
expires_at?: string
|
||||
|
||||
@IsEnum(LicenseStatus)
|
||||
status?: LicenseStatus
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common'
|
||||
import { CreatePartnerLicenseDto, UpdateLicenseDto } from './dto/license.dto'
|
||||
import { PartnerLicensesService } from './licenses.service'
|
||||
|
||||
@Controller('admin/partners/:partnerId/licenses')
|
||||
export class PartnerLicensesController {
|
||||
constructor(private readonly licensesService: PartnerLicensesService) {}
|
||||
|
||||
@Get()
|
||||
async findAll(@Param('partnerId') partnerId: string) {
|
||||
return this.licensesService.findAll(partnerId)
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
async findOne(@Param('partnerId') partnerId: string, @Param('id') id: string) {
|
||||
return this.licensesService.findOne(partnerId, id)
|
||||
}
|
||||
|
||||
@Post()
|
||||
async create(
|
||||
@Param('partnerId') partnerId: string,
|
||||
@Body() data: CreatePartnerLicenseDto,
|
||||
) {
|
||||
return this.licensesService.create(partnerId, data)
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
async update(
|
||||
@Param('partnerId') partnerId: string,
|
||||
@Param('id') id: string,
|
||||
@Body() data: UpdateLicenseDto,
|
||||
) {
|
||||
return this.licensesService.update(partnerId, id, data)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
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],
|
||||
exports: [PartnerLicensesService],
|
||||
})
|
||||
export class AdminPartnerLicensesModule {}
|
||||
@@ -1,183 +0,0 @@
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
import { CreatePartnerLicenseDto, UpdateLicenseDto } from './dto/license.dto'
|
||||
|
||||
@Injectable()
|
||||
export class PartnerLicensesService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
async findAll(partner_id: string, page = 1, pageSize = 10) {
|
||||
const [licenses, count] = await this.prisma.$transaction(async tx => [
|
||||
await tx.license.findMany({
|
||||
where: {
|
||||
partner_id,
|
||||
},
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
select: {
|
||||
id: true,
|
||||
starts_at: true,
|
||||
expires_at: true,
|
||||
consumer: {
|
||||
select: {
|
||||
id: true,
|
||||
first_name: true,
|
||||
last_name: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
await tx.license.count({
|
||||
where: {
|
||||
partner_id,
|
||||
},
|
||||
}),
|
||||
])
|
||||
|
||||
return ResponseMapper.paginate(licenses, {
|
||||
page,
|
||||
pageSize,
|
||||
count,
|
||||
})
|
||||
}
|
||||
|
||||
async findOne(partnerId: string, id: string) {
|
||||
// const license = await this.prisma.license.findFirst({
|
||||
// where: { id, partner_id: partnerId },
|
||||
// include: {
|
||||
// pos: {
|
||||
// include: {
|
||||
// complex: true,
|
||||
// provider: true,
|
||||
|
||||
// accounts: {
|
||||
// include: {
|
||||
// user: true,
|
||||
// },
|
||||
// omit: {
|
||||
// business_id: true,
|
||||
// partner_id: true,
|
||||
// provider_id: true,
|
||||
// pos_id: true,
|
||||
// },
|
||||
// },
|
||||
// device: {
|
||||
// include: {
|
||||
// brand: true,
|
||||
// },
|
||||
// omit: {
|
||||
// brand_id: true,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// omit: {
|
||||
// pos_id: true,
|
||||
// partner_id: true,
|
||||
// },
|
||||
// })
|
||||
// if (license) {
|
||||
// const { pos, ...rest } = license
|
||||
// const { accounts, ...posRest } = pos
|
||||
// return ResponseMapper.single({
|
||||
// account: accounts[0],
|
||||
// pos: posRest,
|
||||
// ...rest,
|
||||
// })
|
||||
// }
|
||||
|
||||
return ResponseMapper.single({})
|
||||
}
|
||||
|
||||
async create(partnerId: string, data: CreatePartnerLicenseDto) {
|
||||
// const license = await this.prisma.$transaction(async tx => {
|
||||
// const user = await tx.user.upsert({
|
||||
// where: {
|
||||
// mobile_number: data.mobile_number,
|
||||
// },
|
||||
// update: {},
|
||||
// create: {
|
||||
// first_name: data.first_name,
|
||||
// last_name: data.last_name,
|
||||
// mobile_number: data.mobile_number,
|
||||
// national_code: data.national_code,
|
||||
// },
|
||||
// })
|
||||
|
||||
// const business = await tx.businessActivity.create({
|
||||
// data: {
|
||||
// name: data.business_activity_name,
|
||||
// guild_id: data.guild,
|
||||
// user: {
|
||||
// connect: {
|
||||
// id: user.id,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// })
|
||||
|
||||
// const complex = await tx.complex.create({
|
||||
// data: {
|
||||
// name: data.complex_name,
|
||||
// tax_id: data.tax_id,
|
||||
// business_activity_id: business.id,
|
||||
// },
|
||||
// })
|
||||
|
||||
// const pos = await tx.pos.create({
|
||||
// data: {
|
||||
// pos_type: data.pos_type,
|
||||
// serial: data.pos_serial,
|
||||
// device_id: data.pos_device,
|
||||
// complex_id: complex.id,
|
||||
// },
|
||||
// })
|
||||
|
||||
// const date = new Date()
|
||||
// const expiresAt = new Date(date.setFullYear(date.getFullYear() + 1))
|
||||
|
||||
// const license = await tx.license.create({
|
||||
// data: {
|
||||
// partner_id: partnerId,
|
||||
// pos_id: pos.id,
|
||||
// starts_at: data.starts_at || new Date(),
|
||||
// expires_at: data.expires_at || expiresAt,
|
||||
// status: LicenseStatus.ACTIVE,
|
||||
// },
|
||||
// })
|
||||
|
||||
// const hashedPassword = await PasswordUtil.hash(data.password)
|
||||
|
||||
// const account = await tx.account.create({
|
||||
// data: {
|
||||
// username: data.username,
|
||||
// password: hashedPassword,
|
||||
// type: AccountType.POS,
|
||||
// user_id: user.id,
|
||||
// pos_id: pos.id,
|
||||
// status: data.account_status,
|
||||
// },
|
||||
// })
|
||||
|
||||
// return {
|
||||
// license,
|
||||
// }
|
||||
// })
|
||||
return ResponseMapper.create('license')
|
||||
}
|
||||
|
||||
async update(partnerId: string, id: string, data: UpdateLicenseDto) {
|
||||
const license = await this.prisma.license.update({
|
||||
where: { id },
|
||||
data: { ...data, partner_id: partnerId },
|
||||
})
|
||||
return ResponseMapper.update(license)
|
||||
}
|
||||
|
||||
async delete(partnerId: string, id: string) {
|
||||
await this.prisma.license.delete({ where: { id } })
|
||||
return ResponseMapper.delete()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common'
|
||||
import { CreatePartnerDto, LicenseChargeDto, UpdatePartnerDto } from './dto/partner.dto'
|
||||
import { Body, Controller, Get, Param, Patch, Post } from '@nestjs/common'
|
||||
import { CreatePartnerDto, UpdatePartnerDto } from './dto/partner.dto'
|
||||
import { PartnersService } from './partners.service'
|
||||
|
||||
@Controller('admin/partners')
|
||||
@@ -26,13 +26,8 @@ export class PartnersController {
|
||||
return this.partnersService.update(id, data)
|
||||
}
|
||||
|
||||
@Post(':id/charge-license')
|
||||
async licenseCharge(@Param('id') id: string, @Body() data: LicenseChargeDto) {
|
||||
return this.partnersService.licenseCharge(id, data)
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
async delete(@Param('id') id: string) {
|
||||
return this.partnersService.delete(id)
|
||||
}
|
||||
// @Delete(':id')
|
||||
// async delete(@Param('id') id: string) {
|
||||
// return this.partnersService.delete(id)
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { PrismaModule } from '@/prisma/prisma.module'
|
||||
import { Module } from '@nestjs/common'
|
||||
|
||||
import { AdminPartnerLicensesModule } from './licenses/licenses.module'
|
||||
import { AdminPartnerActivatedLicensesModule } from './activatedLicenses/activatedLicenses.module'
|
||||
import { AdminPartnerChargedLicenseTransactionsModule } from './chargedLicenseTransactions/chargedLicenseTransactions.module'
|
||||
import { AdminPartnerAccountsModule } from './partnerAccounts/accounts.module'
|
||||
import { PartnersController } from './partners.controller'
|
||||
import { PartnersService } from './partners.service'
|
||||
|
||||
@Module({
|
||||
imports: [PrismaModule, AdminPartnerLicensesModule, AdminPartnerAccountsModule],
|
||||
imports: [
|
||||
PrismaModule,
|
||||
AdminPartnerChargedLicenseTransactionsModule,
|
||||
AdminPartnerActivatedLicensesModule,
|
||||
AdminPartnerAccountsModule,
|
||||
],
|
||||
controllers: [PartnersController],
|
||||
providers: [PartnersService],
|
||||
exports: [PartnersService],
|
||||
|
||||
@@ -1,43 +1,111 @@
|
||||
import { PasswordUtil } from '@/common/utils/password.util'
|
||||
import { ChargedLicenseTransactions } from '@/generated/prisma/client'
|
||||
import {
|
||||
AccountStatus,
|
||||
AccountType,
|
||||
PartnerRole,
|
||||
PartnerStatus,
|
||||
} from '@/generated/prisma/enums'
|
||||
import { PartnerSelect } from '@/generated/prisma/models'
|
||||
import { PrismaService } from '@/prisma/prisma.service'
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { ResponseMapper } from 'common/response/response-mapper'
|
||||
import { CreatePartnerDto, LicenseChargeDto, UpdatePartnerDto } from './dto/partner.dto'
|
||||
import { CreatePartnerDto, UpdatePartnerDto } from './dto/partner.dto'
|
||||
|
||||
@Injectable()
|
||||
export class PartnersService {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private readonly defaultSelect: PartnerSelect = {
|
||||
id: true,
|
||||
name: true,
|
||||
code: true,
|
||||
status: true,
|
||||
created_at: true,
|
||||
chargedLicenseTransactions: {
|
||||
select: {
|
||||
activation_expires_at: true,
|
||||
licenses: {
|
||||
select: {
|
||||
activated_license: {
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
private readonly separateLicenseCount = (
|
||||
transactions: ChargedLicenseTransactions[] | null,
|
||||
) => {
|
||||
function toDateOnlyString(date) {
|
||||
return date.toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
const startOfTodayDate = toDateOnlyString(new Date())
|
||||
|
||||
const used = transactions?.reduce((sum, cur) => {
|
||||
const license = cur as any
|
||||
return (
|
||||
sum + license.licenses.filter(license => license.activated_license).length || 0
|
||||
)
|
||||
}, 0)
|
||||
|
||||
const total = transactions?.reduce((sum, cur) => {
|
||||
const license = cur as any
|
||||
|
||||
return sum + license.licenses.length || 0
|
||||
}, 0)
|
||||
|
||||
const expired = transactions?.reduce((sum, cur) => {
|
||||
const license = cur as any
|
||||
const activationExpiresDate = toDateOnlyString(license.activation_expires_at)
|
||||
if (startOfTodayDate > activationExpiresDate)
|
||||
return (
|
||||
sum + license.licenses.filter(license => !license.activated_license).length || 0
|
||||
)
|
||||
return sum
|
||||
}, 0)
|
||||
|
||||
return {
|
||||
total,
|
||||
used,
|
||||
expired,
|
||||
}
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
const partners = await this.prisma.partner.findMany()
|
||||
return ResponseMapper.list(partners)
|
||||
const partners = await this.prisma.partner.findMany({
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
|
||||
const mappedPartners = partners.map(partner => {
|
||||
const { chargedLicenseTransactions, ...rest } = partner
|
||||
return {
|
||||
...rest,
|
||||
licenses_status: this.separateLicenseCount(chargedLicenseTransactions),
|
||||
}
|
||||
})
|
||||
|
||||
return ResponseMapper.list(mappedPartners)
|
||||
}
|
||||
|
||||
async findOne(id: string) {
|
||||
const [partner, relatedLicenseCount] = await this.prisma.$transaction([
|
||||
this.prisma.partner.findUnique({
|
||||
where: { id },
|
||||
}),
|
||||
this.prisma.license.count({
|
||||
where: {
|
||||
partner_id: id,
|
||||
},
|
||||
}),
|
||||
])
|
||||
|
||||
return ResponseMapper.single({
|
||||
...partner,
|
||||
remained_license: Math.max(
|
||||
(partner?.license_quota || 0) - (relatedLicenseCount || 0),
|
||||
0,
|
||||
),
|
||||
const partner = await this.prisma.partner.findUniqueOrThrow({
|
||||
where: { id },
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
|
||||
const { chargedLicenseTransactions, ...rest } = partner
|
||||
const mappedPartner = {
|
||||
...rest,
|
||||
licenses_status: this.separateLicenseCount(chargedLicenseTransactions),
|
||||
}
|
||||
|
||||
return ResponseMapper.single(mappedPartner)
|
||||
}
|
||||
|
||||
async create(data: CreatePartnerDto) {
|
||||
@@ -60,23 +128,16 @@ export class PartnersService {
|
||||
},
|
||||
},
|
||||
},
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
return ResponseMapper.create(partner)
|
||||
}
|
||||
|
||||
async update(id: string, data: UpdatePartnerDto) {
|
||||
const partner = await this.prisma.partner.update({ where: { id }, data })
|
||||
return ResponseMapper.update(partner)
|
||||
}
|
||||
|
||||
async licenseCharge(id: string, data: LicenseChargeDto) {
|
||||
const partner = await this.prisma.partner.update({
|
||||
where: { id },
|
||||
data: {
|
||||
license_quota: {
|
||||
increment: data.count,
|
||||
},
|
||||
},
|
||||
data,
|
||||
select: this.defaultSelect,
|
||||
})
|
||||
return ResponseMapper.update(partner)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user