|
|
@@ -0,0 +1,149 @@
|
|
|
+import { Injectable } from '@nestjs/common';
|
|
|
+import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
|
|
|
+import { MongoPrismaService } from '@box/db/prisma/mongo-prisma.service';
|
|
|
+import {
|
|
|
+ CreateAdsDto,
|
|
|
+ ListAdsDto,
|
|
|
+ UpdateAdsDto,
|
|
|
+} from './ads.dto';
|
|
|
+import { CommonStatus } from '../common/status.enum';
|
|
|
+
|
|
|
+@Injectable()
|
|
|
+export class AdsService {
|
|
|
+ constructor(private readonly mongoPrismaService: MongoPrismaService) {}
|
|
|
+
|
|
|
+ private now() {
|
|
|
+ return Date.now();
|
|
|
+ }
|
|
|
+
|
|
|
+ private trimOptional(value?: string | null) {
|
|
|
+ if (value === undefined) return undefined;
|
|
|
+ if (value === null) return null;
|
|
|
+ return typeof value === 'string' ? value.trim() : value;
|
|
|
+ }
|
|
|
+
|
|
|
+ private ensureTimeRange(startDt: number, expiryDt: number) {
|
|
|
+ if (expiryDt < startDt) {
|
|
|
+ throw new Error('expiryDt must be greater than or equal to startDt');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private async assertChannelExists(channelId: string) {
|
|
|
+ const exists = await this.mongoPrismaService.channel.findUnique({
|
|
|
+ where: { id: channelId },
|
|
|
+ select: { id: true },
|
|
|
+ });
|
|
|
+ if (!exists) {
|
|
|
+ throw new Error('Channel not found');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async create(dto: CreateAdsDto) {
|
|
|
+ await this.assertChannelExists(dto.channelId);
|
|
|
+ this.ensureTimeRange(dto.startDt, dto.expiryDt);
|
|
|
+
|
|
|
+ const now = this.now();
|
|
|
+ return this.mongoPrismaService.ads.create({
|
|
|
+ data: {
|
|
|
+ channelId: dto.channelId,
|
|
|
+ adsModule: dto.adsModule,
|
|
|
+ advertiser: dto.advertiser,
|
|
|
+ title: dto.title,
|
|
|
+ adsContent: this.trimOptional(dto.adsContent) ?? null,
|
|
|
+ adsCoverImg: this.trimOptional(dto.adsCoverImg) ?? null,
|
|
|
+ adsUrl: this.trimOptional(dto.adsUrl) ?? null,
|
|
|
+ startDt: dto.startDt,
|
|
|
+ expiryDt: dto.expiryDt,
|
|
|
+ seq: dto.seq ?? 0,
|
|
|
+ status: dto.status ?? CommonStatus.enabled,
|
|
|
+ createAt: now,
|
|
|
+ updateAt: now,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ async update(dto: UpdateAdsDto) {
|
|
|
+ await this.assertChannelExists(dto.channelId);
|
|
|
+ this.ensureTimeRange(dto.startDt, dto.expiryDt);
|
|
|
+
|
|
|
+ const now = this.now();
|
|
|
+ try {
|
|
|
+ return await this.mongoPrismaService.ads.update({
|
|
|
+ where: { id: dto.id },
|
|
|
+ data: {
|
|
|
+ channelId: dto.channelId,
|
|
|
+ adsModule: dto.adsModule,
|
|
|
+ advertiser: dto.advertiser,
|
|
|
+ title: dto.title,
|
|
|
+ adsContent: this.trimOptional(dto.adsContent) ?? null,
|
|
|
+ adsCoverImg: this.trimOptional(dto.adsCoverImg) ?? null,
|
|
|
+ adsUrl: this.trimOptional(dto.adsUrl) ?? null,
|
|
|
+ startDt: dto.startDt,
|
|
|
+ expiryDt: dto.expiryDt,
|
|
|
+ seq: dto.seq ?? 0,
|
|
|
+ status: dto.status ?? CommonStatus.enabled,
|
|
|
+ updateAt: now,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ } catch (e) {
|
|
|
+ if (e instanceof PrismaClientKnownRequestError && e.code === 'P2025') {
|
|
|
+ throw new Error('Ads not found');
|
|
|
+ }
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ async findOne(id: string) {
|
|
|
+ const row = await this.mongoPrismaService.ads.findUnique({
|
|
|
+ where: { id },
|
|
|
+ });
|
|
|
+ if (!row) throw new Error('Ads not found');
|
|
|
+ return row;
|
|
|
+ }
|
|
|
+
|
|
|
+ async list(dto: ListAdsDto) {
|
|
|
+ const where: any = {};
|
|
|
+
|
|
|
+ if (dto.title) {
|
|
|
+ where.title = { contains: dto.title, mode: 'insensitive' };
|
|
|
+ }
|
|
|
+ if (dto.advertiser) {
|
|
|
+ where.advertiser = { contains: dto.advertiser, mode: 'insensitive' };
|
|
|
+ }
|
|
|
+ if (dto.adsModule) {
|
|
|
+ where.adsModule = { contains: dto.adsModule, mode: 'insensitive' };
|
|
|
+ }
|
|
|
+ if (dto.channelId) where.channelId = dto.channelId;
|
|
|
+ if (dto.status !== undefined) where.status = dto.status;
|
|
|
+
|
|
|
+ const [total, data] = await this.mongoPrismaService.$transaction([
|
|
|
+ this.mongoPrismaService.ads.count({ where }),
|
|
|
+ this.mongoPrismaService.ads.findMany({
|
|
|
+ where,
|
|
|
+ orderBy: { updateAt: 'desc' },
|
|
|
+ skip: (dto.page - 1) * dto.size,
|
|
|
+ take: dto.size,
|
|
|
+ }),
|
|
|
+ ]);
|
|
|
+
|
|
|
+ return {
|
|
|
+ total,
|
|
|
+ data,
|
|
|
+ totalPages: Math.ceil(total / dto.size),
|
|
|
+ page: dto.page,
|
|
|
+ size: dto.size,
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ async remove(id: string) {
|
|
|
+ try {
|
|
|
+ await this.mongoPrismaService.ads.delete({ where: { id } });
|
|
|
+ return { message: 'Deleted' };
|
|
|
+ } catch (e) {
|
|
|
+ if (e instanceof PrismaClientKnownRequestError && e.code === 'P2025') {
|
|
|
+ throw new Error('Ads not found');
|
|
|
+ }
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|