v3数据表更改

This commit is contained in:
2026-07-01 14:36:50 +08:00
parent 638898b71e
commit aeb4ecfc84
46 changed files with 4553 additions and 918 deletions
@@ -2,6 +2,8 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { buildBenefitLedgerEvent, benefitLedgerWhere } from '../../common/event/event.helpers';
import { mapBenefitLedgerCompat } from '../../common/compat/v31-compat';
import type { AdminBenefitCouponsQueryDto, AdminBenefitLedgersQueryDto } from './dto/admin-query.dto';
@Injectable()
@@ -38,12 +40,16 @@ export class AdminBenefitService {
include: {
user: { select: { id: true, userNo: true, phone: true, nickname: true } },
order: { select: { id: true, orderNo: true, status: true, payAmount: true } },
ledgers: { orderBy: { createdAt: 'desc' }, take: 20 },
redeemRecords: { orderBy: { createdAt: 'desc' }, take: 10, include: { store: { select: { id: true, name: true } } } },
},
});
if (!coupon) throw new NotFoundException('权益券不存在');
return serializeBigInt(coupon);
const ledgers = await this.prisma.commonEvent.findMany({
where: benefitLedgerWhere(undefined, id),
orderBy: { createdAt: 'desc' },
take: 20,
});
return serializeBigInt({ ...coupon, ledgers });
}
async voidCoupon(id: bigint) {
@@ -57,8 +63,8 @@ export class AdminBenefitService {
data: { status: 'VOID', balance: 0 },
});
if (Number(coupon.balance) > 0) {
await tx.benefitLedger.create({
data: {
await tx.commonEvent.create({
data: buildBenefitLedgerEvent({
userId: coupon.userId,
couponId: coupon.id,
type: 'ADJUST',
@@ -66,7 +72,7 @@ export class AdminBenefitService {
balanceAfter: 0,
refType: 'ADMIN_VOID',
remark: 'HQ 手动作废',
},
}),
});
}
return row;
@@ -77,24 +83,47 @@ export class AdminBenefitService {
async listLedgers(query: AdminBenefitLedgersQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where: Prisma.BenefitLedgerWhereInput = {};
if (query.userId) where.userId = BigInt(query.userId);
if (query.couponId) where.couponId = BigInt(query.couponId);
if (query.type) where.type = query.type as Prisma.EnumBenefitLedgerTypeFilter['equals'];
const where: Prisma.CommonEventWhereInput = {
eventType: 'BENEFIT_LEDGER',
...(query.userId ? { actorType: 'USER', actorId: BigInt(query.userId) } : {}),
...(query.couponId ? { param2: BigInt(query.couponId).toString() } : {}),
...(query.type ? { param1: query.type } : {}),
};
const [items, total] = await Promise.all([
this.prisma.benefitLedger.findMany({
this.prisma.commonEvent.findMany({
where,
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
include: {
user: { select: { id: true, userNo: true } },
coupon: { select: { id: true, couponNo: true } },
},
}),
this.prisma.benefitLedger.count({ where }),
this.prisma.commonEvent.count({ where }),
]);
return serializeBigInt({ items, total, page, pageSize });
const userIds = [...new Set(items.map((i) => i.actorId).filter(Boolean))] as bigint[];
const couponIds = [...new Set(items.map((i) => i.param2).filter(Boolean))].map((id) => BigInt(id!));
const [users, coupons] = await Promise.all([
userIds.length
? this.prisma.user.findMany({ where: { id: { in: userIds } }, select: { id: true, userNo: true } })
: Promise.resolve([] as { id: bigint; userNo: string | null }[]),
couponIds.length
? this.prisma.benefitCoupon.findMany({ where: { id: { in: couponIds } }, select: { id: true, couponNo: true } })
: Promise.resolve([] as { id: bigint; couponNo: string }[]),
]);
const userMap = new Map(users.map((u) => [u.id.toString(), u] as const));
const couponMap = new Map(coupons.map((c) => [c.id.toString(), c] as const));
return serializeBigInt({
items: items.map((e) =>
mapBenefitLedgerCompat(
e,
e.actorId ? userMap.get(e.actorId.toString()) : null,
e.param2 ? couponMap.get(e.param2) : null,
),
),
total,
page,
pageSize,
});
}
}
@@ -12,14 +12,14 @@ export class AdminCitiesService {
async list(query: AdminCitiesQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where: Prisma.CityWhereInput = {};
const where: Prisma.CommonCityWhereInput = {};
if (query.name) where.name = { contains: query.name };
if (query.code) where.code = { contains: query.code };
if (query.status) where.status = query.status as Prisma.EnumCityStatusFilter['equals'];
if (query.partnerId) where.partnerId = BigInt(query.partnerId);
const [items, total] = await Promise.all([
this.prisma.city.findMany({
this.prisma.commonCity.findMany({
where,
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
@@ -29,7 +29,7 @@ export class AdminCitiesService {
_count: { select: { stores: true, orders: true } },
},
}),
this.prisma.city.count({ where }),
this.prisma.commonCity.count({ where }),
]);
return serializeBigInt({
items: items.map((c) => ({
@@ -45,7 +45,7 @@ export class AdminCitiesService {
}
async detail(id: bigint) {
const city = await this.prisma.city.findUnique({
const city = await this.prisma.commonCity.findUnique({
where: { id },
include: {
partner: true,
@@ -58,9 +58,9 @@ export class AdminCitiesService {
}
async create(dto: CreateCityDto) {
const exists = await this.prisma.city.findUnique({ where: { code: dto.code } });
const exists = await this.prisma.commonCity.findUnique({ where: { code: dto.code } });
if (exists) throw new BadRequestException('城市编码已存在');
const city = await this.prisma.city.create({
const city = await this.prisma.commonCity.create({
data: {
code: dto.code,
name: dto.name,
@@ -79,7 +79,7 @@ export class AdminCitiesService {
}
async update(id: bigint, dto: UpdateCityDto) {
const city = await this.prisma.city.update({
const city = await this.prisma.commonCity.update({
where: { id },
data: {
...(dto.name !== undefined ? { name: dto.name } : {}),
@@ -2,6 +2,8 @@ import { Injectable, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { orderStatusLogWhere } from '../../common/event/event.helpers';
import { mapOrderCompat, mapStatusLogCompat } from '../../common/compat/v31-compat';
import type { AdminOrdersQueryDto } from './dto/admin-query.dto';
@Injectable()
@@ -54,17 +56,24 @@ export class AdminOrdersService {
phoneVerifiedAt: true,
},
},
items: true,
delivery: true,
payment: true,
statusLogs: { orderBy: { createdAt: 'asc' } },
benefitCoupons: {
benefitCoupon: {
select: { id: true, couponNo: true, balance: true, status: true },
},
city: { select: { id: true, name: true, code: true } },
product: { select: { id: true, name: true, skuCode: true, barcode69: true } },
imageResource: { select: { id: true, url: true } },
},
});
if (!order) throw new NotFoundException('订单不存在');
return serializeBigInt(order);
const statusLogs = await this.prisma.commonEvent.findMany({
where: orderStatusLogWhere(id),
orderBy: { createdAt: 'asc' },
});
return serializeBigInt(mapOrderCompat({
...order,
statusLogs: mapStatusLogCompat(statusLogs),
benefitCoupons: order.benefitCoupon ? [order.benefitCoupon] : [],
}));
}
}
@@ -0,0 +1,31 @@
import { Body, Controller, Get, Param, Post, Put, Query, UseGuards } from '@nestjs/common';
import { HqAuthGuard } from '../../common/guards/hq-auth.guard';
import { AdminProductsService } from './admin-products.service';
import { AdminProductsQueryDto } from './dto/admin-query.dto';
import { CreateProductDto, UpdateProductDto } from './dto/admin-mutate.dto';
@Controller('admin/products')
@UseGuards(HqAuthGuard)
export class AdminProductsController {
constructor(private readonly service: AdminProductsService) {}
@Get()
list(@Query() query: AdminProductsQueryDto) {
return this.service.list(query);
}
@Get(':id')
detail(@Param('id') id: string) {
return this.service.detail(BigInt(id));
}
@Post()
create(@Body() dto: CreateProductDto) {
return this.service.create(dto);
}
@Put(':id')
update(@Param('id') id: string, @Body() dto: UpdateProductDto) {
return this.service.update(BigInt(id), dto);
}
}
@@ -0,0 +1,135 @@
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import type { AdminProductsQueryDto } from './dto/admin-query.dto';
import type { CreateProductDto, UpdateProductDto } from './dto/admin-mutate.dto';
@Injectable()
export class AdminProductsService {
constructor(private readonly prisma: PrismaService) {}
async list(query: AdminProductsQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where: Prisma.CommonProductItemWhereInput = {};
if (query.name) where.name = { contains: query.name };
if (query.status) where.status = query.status as Prisma.EnumProductStatusFilter['equals'];
if (query.aromaType) where.aromaType = query.aromaType as Prisma.EnumAromaTypeFilter['equals'];
const [items, total] = await Promise.all([
this.prisma.commonProductItem.findMany({
where,
orderBy: { sortOrder: 'asc' },
skip: (page - 1) * pageSize,
take: pageSize,
include: { coverResource: true },
}),
this.prisma.commonProductItem.count({ where }),
]);
return serializeBigInt({
items: items.map((p) => ({
...p,
mainImageUrl: p.coverResource?.url ?? null,
})),
total,
page,
pageSize,
});
}
async detail(id: bigint) {
const product = await this.prisma.commonProductItem.findUnique({
where: { id },
include: { coverResource: true },
});
if (!product) throw new NotFoundException('商品不存在');
return serializeBigInt({ ...product, mainImageUrl: product.coverResource?.url ?? null });
}
async create(dto: CreateProductDto) {
const exists = await this.prisma.commonProductItem.findFirst({
where: { OR: [{ skuCode: dto.skuCode }, { barcode69: dto.barcode69 }] },
});
if (exists) throw new BadRequestException('SKU 或 69 码已存在');
const product = await this.prisma.commonProductItem.create({
data: {
skuCode: dto.skuCode,
barcode69: dto.barcode69,
name: dto.name,
subtitle: dto.subtitle,
aromaType: dto.aromaType as 'QINGXIANG' | 'JIANGXIANG' | 'NONGXIANG',
spec: dto.spec,
price: dto.price,
benefitAmount: dto.benefitAmount ?? dto.price,
status: (dto.status ?? 'DRAFT') as 'DRAFT' | 'ON_SALE' | 'OFF_SALE',
sortOrder: dto.sortOrder ?? 0,
},
});
if (dto.coverUrl) {
const cover = await this.prisma.commonResource.create({
data: {
ownerType: 'PRODUCT',
ownerId: product.id,
bizType: 'COVER',
mediaType: 'IMAGE',
ossBucket: 'legacy',
ossKey: dto.coverUrl,
url: dto.coverUrl,
},
});
await this.prisma.commonProductItem.update({
where: { id: product.id },
data: { coverResourceId: cover.id },
});
}
return this.detail(product.id);
}
async update(id: bigint, dto: UpdateProductDto) {
await this.detail(id);
await this.prisma.commonProductItem.update({
where: { id },
data: {
...(dto.name !== undefined ? { name: dto.name } : {}),
...(dto.subtitle !== undefined ? { subtitle: dto.subtitle } : {}),
...(dto.spec !== undefined ? { spec: dto.spec } : {}),
...(dto.price !== undefined ? { price: dto.price } : {}),
...(dto.benefitAmount !== undefined ? { benefitAmount: dto.benefitAmount } : {}),
...(dto.status !== undefined ? { status: dto.status as 'DRAFT' | 'ON_SALE' | 'OFF_SALE' } : {}),
...(dto.sortOrder !== undefined ? { sortOrder: dto.sortOrder } : {}),
},
});
if (dto.coverUrl) {
const product = await this.prisma.commonProductItem.findUniqueOrThrow({ where: { id } });
if (product.coverResourceId) {
await this.prisma.commonResource.update({
where: { id: product.coverResourceId },
data: { url: dto.coverUrl, ossKey: dto.coverUrl },
});
} else {
const cover = await this.prisma.commonResource.create({
data: {
ownerType: 'PRODUCT',
ownerId: id,
bizType: 'COVER',
mediaType: 'IMAGE',
ossBucket: 'legacy',
ossKey: dto.coverUrl,
url: dto.coverUrl,
},
});
await this.prisma.commonProductItem.update({
where: { id },
data: { coverResourceId: cover.id },
});
}
}
return this.detail(id);
}
}
@@ -1,4 +1,5 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import type { DeliveryProvider } from '@prisma/client';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
@@ -42,7 +43,6 @@ export class AdminRedeemService {
store: { include: { partner: { select: { id: true, companyName: true } } } },
coupon: true,
payout: true,
commissions: true,
},
});
if (!record) throw new NotFoundException('核销记录不存在');
@@ -58,7 +58,7 @@ export class AdminDeliveriesService {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where: Prisma.OrderDeliveryWhereInput = {};
if (query.provider) where.provider = query.provider;
if (query.provider) where.provider = query.provider as DeliveryProvider;
if (query.trackingNo) where.trackingNo = { contains: query.trackingNo };
if (query.orderNo) {
where.order = { orderNo: { contains: query.orderNo } };
@@ -79,6 +79,8 @@ export class AdminDeliveriesService {
receiverName: true,
receiverPhone: true,
deliveryType: true,
productName: true,
quantity: true,
},
},
},
@@ -95,7 +97,7 @@ export class AdminDeliveriesService {
order: {
include: {
user: { select: { id: true, userNo: true, phone: true } },
items: true,
imageResource: { select: { url: true } },
},
},
},
@@ -108,7 +110,7 @@ export class AdminDeliveriesService {
const delivery = await this.prisma.orderDelivery.update({
where: { id },
data: {
...(dto.provider !== undefined ? { provider: dto.provider } : {}),
...(dto.provider !== undefined ? { provider: dto.provider as DeliveryProvider } : {}),
...(dto.providerOrderNo !== undefined ? { providerOrderNo: dto.providerOrderNo } : {}),
...(dto.trackingNo !== undefined ? { trackingNo: dto.trackingNo } : {}),
},
@@ -2,6 +2,7 @@ import { BadRequestException, Injectable, NotFoundException } from '@nestjs/comm
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../common/prisma/prisma.module';
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
import { mapStoreCompat } from '../../common/compat/v31-compat';
import type { AdminStoreAccountsQueryDto, AdminStoreMediaQueryDto, AdminStoresQueryDto } from './dto/admin-query.dto';
import type {
CreateStoreAccountDto,
@@ -37,11 +38,17 @@ export class AdminStoresService {
cityRef: { select: { id: true, name: true, code: true } },
partner: { select: { id: true, companyName: true } },
account: { select: { id: true, phone: true, name: true, status: true } },
coverResource: { select: { id: true, url: true } },
},
}),
this.prisma.store.count({ where }),
]);
return serializeBigInt({ items, total, page, pageSize });
return serializeBigInt({
items: items.map((s) => mapStoreCompat(s)),
total,
page,
pageSize,
});
}
async detailStore(id: bigint) {
@@ -52,18 +59,30 @@ export class AdminStoresService {
partner: true,
category: true,
account: true,
media: { orderBy: { sortOrder: 'asc' } },
audits: { orderBy: { submittedAt: 'desc' }, take: 5 },
coverResource: true,
_count: { select: { redeemRecords: true, ratings: true } },
},
});
if (!store) throw new NotFoundException('门店不存在');
return serializeBigInt({
const [media, audits] = await Promise.all([
this.prisma.commonResource.findMany({
where: { ownerType: 'STORE', ownerId: id, status: 'ACTIVE' },
orderBy: { sortOrder: 'asc' },
}),
this.prisma.commonEvent.findMany({
where: { eventType: 'STORE_AUDIT', refType: 'STORE', refId: id },
orderBy: { createdAt: 'desc' },
take: 5,
}),
]);
return serializeBigInt(mapStoreCompat({
...store,
media,
audits,
redeemCount: store._count.redeemRecords,
ratingCount: store._count.ratings,
_count: undefined,
});
}));
}
async updateStoreStatus(id: bigint, dto: UpdateStoreStatusDto) {
@@ -81,18 +100,41 @@ export class AdminStoresService {
...(dto.name !== undefined ? { name: dto.name } : {}),
...(dto.phone !== undefined ? { phone: dto.phone } : {}),
...(dto.intro !== undefined ? { intro: dto.intro } : {}),
...(dto.coverUrl !== undefined ? { coverUrl: dto.coverUrl } : {}),
...(dto.address !== undefined ? { address: dto.address } : {}),
...(dto.district !== undefined ? { district: dto.district } : {}),
},
});
return serializeBigInt(store);
if (dto.coverUrl) {
const current = await this.prisma.store.findUniqueOrThrow({ where: { id } });
if (current.coverResourceId) {
await this.prisma.commonResource.update({
where: { id: current.coverResourceId },
data: { url: dto.coverUrl, ossKey: dto.coverUrl },
});
} else {
const cover = await this.prisma.commonResource.create({
data: {
ownerType: 'STORE',
ownerId: id,
bizType: 'COVER',
mediaType: 'IMAGE',
ossBucket: 'legacy',
ossKey: dto.coverUrl,
url: dto.coverUrl,
},
});
await this.prisma.store.update({ where: { id }, data: { coverResourceId: cover.id } });
}
}
return this.detailStore(id);
}
async createStore(dto: CreateStoreDto) {
const partner = await this.prisma.partner.findUnique({ where: { id: BigInt(dto.partnerId) } });
if (!partner) throw new BadRequestException('开城合伙人不存在');
const city = await this.prisma.city.findUnique({ where: { id: BigInt(dto.cityId) } });
const city = await this.prisma.commonCity.findUnique({ where: { id: BigInt(dto.cityId) } });
if (!city) throw new BadRequestException('开城城市不存在');
const store = await this.prisma.store.create({
@@ -107,7 +149,6 @@ export class AdminStoresService {
district: dto.district ?? '',
address: dto.address,
intro: dto.intro ?? null,
coverUrl: dto.coverUrl ?? null,
status: 'OPEN',
},
});
@@ -139,19 +180,21 @@ export class AdminStoresService {
async listStoreMedia(query: AdminStoreMediaQueryDto) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const where: Prisma.StoreMediaWhereInput = {};
if (query.storeId) where.storeId = BigInt(query.storeId);
if (query.mediaType) where.mediaType = query.mediaType;
const where: Prisma.CommonResourceWhereInput = {
ownerType: 'STORE',
status: 'ACTIVE',
};
if (query.storeId) where.ownerId = BigInt(query.storeId);
if (query.mediaType) where.mediaType = query.mediaType as Prisma.EnumResourceMediaTypeFilter['equals'];
const [items, total] = await Promise.all([
this.prisma.storeMedia.findMany({
this.prisma.commonResource.findMany({
where,
orderBy: [{ sortOrder: 'asc' }, { createdAt: 'desc' }],
skip: (page - 1) * pageSize,
take: pageSize,
include: { store: { select: { id: true, name: true } } },
}),
this.prisma.storeMedia.count({ where }),
this.prisma.commonResource.count({ where }),
]);
return serializeBigInt({ items, total, page, pageSize });
}
@@ -159,10 +202,14 @@ export class AdminStoresService {
async createStoreMedia(dto: CreateStoreMediaDto) {
const store = await this.prisma.store.findUnique({ where: { id: BigInt(dto.storeId) } });
if (!store) throw new BadRequestException('门店不存在');
const media = await this.prisma.storeMedia.create({
const media = await this.prisma.commonResource.create({
data: {
storeId: store.id,
mediaType: dto.mediaType,
ownerType: 'STORE',
ownerId: store.id,
bizType: 'ENV',
mediaType: dto.mediaType as 'IMAGE' | 'VIDEO',
ossBucket: 'legacy',
ossKey: dto.url,
url: dto.url,
sortOrder: dto.sortOrder ?? 0,
},
@@ -171,11 +218,11 @@ export class AdminStoresService {
}
async updateStoreMedia(id: bigint, dto: UpdateStoreMediaDto) {
const media = await this.prisma.storeMedia.update({
const media = await this.prisma.commonResource.update({
where: { id },
data: {
...(dto.url !== undefined ? { url: dto.url } : {}),
...(dto.mediaType !== undefined ? { mediaType: dto.mediaType } : {}),
...(dto.url !== undefined ? { url: dto.url, ossKey: dto.url } : {}),
...(dto.mediaType !== undefined ? { mediaType: dto.mediaType as 'IMAGE' | 'VIDEO' } : {}),
...(dto.sortOrder !== undefined ? { sortOrder: dto.sortOrder } : {}),
},
});
@@ -183,7 +230,10 @@ export class AdminStoresService {
}
async deleteStoreMedia(id: bigint) {
await this.prisma.storeMedia.delete({ where: { id } });
await this.prisma.commonResource.update({
where: { id },
data: { status: 'DELETED' },
});
return { ok: true };
}
@@ -59,7 +59,7 @@ export class AdminUsersService {
const user = await this.prisma.user.findUnique({
where: { id },
include: {
cityPref: true,
cityPreference: true,
mergedInto: { select: { id: true, userNo: true, phone: true, nickname: true } },
orders: {
orderBy: { createdAt: 'desc' },
@@ -1,4 +1,4 @@
import { IsIn, IsNotEmpty, IsOptional, IsString } from 'class-validator';
import { IsIn, IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator';
export class UpdateStoreStatusDto {
@IsString()
@@ -311,3 +311,81 @@ export class UpdateHqAccountDto {
@IsIn(['ACTIVE', 'DISABLED'])
status?: string;
}
export class CreateProductDto {
@IsString()
@IsNotEmpty()
skuCode: string;
@IsString()
@IsNotEmpty()
barcode69: string;
@IsString()
@IsNotEmpty()
name: string;
@IsOptional()
@IsString()
subtitle?: string;
@IsIn(['QINGXIANG', 'JIANGXIANG', 'NONGXIANG'])
aromaType: string;
@IsString()
@IsNotEmpty()
spec: string;
@IsNumber()
price: number;
@IsOptional()
@IsNumber()
benefitAmount?: number;
@IsOptional()
@IsIn(['DRAFT', 'ON_SALE', 'OFF_SALE'])
status?: string;
@IsOptional()
@IsNumber()
sortOrder?: number;
@IsOptional()
@IsString()
coverUrl?: string;
}
export class UpdateProductDto {
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
subtitle?: string;
@IsOptional()
@IsString()
spec?: string;
@IsOptional()
@IsNumber()
price?: number;
@IsOptional()
@IsNumber()
benefitAmount?: number;
@IsOptional()
@IsIn(['DRAFT', 'ON_SALE', 'OFF_SALE'])
status?: string;
@IsOptional()
@IsNumber()
sortOrder?: number;
@IsOptional()
@IsString()
coverUrl?: string;
}
@@ -213,6 +213,20 @@ export class AdminCitiesQueryDto extends PaginationQueryDto {
partnerId?: string;
}
export class AdminProductsQueryDto extends PaginationQueryDto {
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
status?: string;
@IsOptional()
@IsString()
aromaType?: string;
}
export class AdminStoreMediaQueryDto extends PaginationQueryDto {
@IsOptional()
@IsString()
@@ -18,6 +18,8 @@ import { AdminRedeemRecordsController, AdminDeliveriesController } from './admin
import { AdminRedeemService, AdminDeliveriesService } from './admin-redeem.service';
import { AdminHqAccountsController } from './admin-hq-accounts.controller';
import { AdminHqAccountsService } from './admin-hq-accounts.service';
import { AdminProductsController } from './admin-products.controller';
import { AdminProductsService } from './admin-products.service';
import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
@Module({
@@ -37,6 +39,7 @@ import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
AdminRedeemRecordsController,
AdminDeliveriesController,
AdminHqAccountsController,
AdminProductsController,
],
providers: [
AdminDashboardService,
@@ -49,6 +52,7 @@ import { SuperAdminGuard } from '../../common/guards/super-admin.guard';
AdminRedeemService,
AdminDeliveriesService,
AdminHqAccountsService,
AdminProductsService,
SuperAdminGuard,
],
})