feat(api): 广告位 CRUD——outbox ad.* 事件/audit/停用高优先级/版本化换图

Task 7(ads-carousel):/v1/admin/ads list/create/patch/delete 四端点。
- 事务三写:ads 行 + outbox(ad.updated 全量快照/ad.deleted 墓碑)+ audit
  (ad.create/update/delete);ad.* 信封 albumId 恒空串;停用迁移 true→false
  与删除均 priority='high';
- 创建/换图:staging head 三核(存在/bytes/contentType,assets complete 同
  口径)→ 事务内 copyIfAbsent 先于行写入(失败=孤儿终键对象,OSS 生命周期
  兜底)→ 版本化终键 adObjectKey(adId, v, ext);
- 更新:embed 乐观重试模式(条件 updateMany WHERE entityVersion),保证换图
  终键版本段与行版本严格对齐;换图三字段同时性校验(缺一 400);albumIds
  去重+相册存在性 count 校验([]/null 归一全局 null);
- 删除:条件 deleteMany 重跑保墓碑 entityVersion=末+1;重复删除 404;
- 载荷构建器独立 ad-payload.ts(Task 8 对账共用,逐字节同形约定);
- dto:AdCreateRequestDto.albumIds 收窄为 string[] | null(JSON null 在
  @IsOptional 下可达,embed settings 先例);
- e2e:describe 更名 ads domain (e2e),追加 ⑨-⑯ 八用例(真图直传/定向/
  非法 linkUrl/字段级 PATCH/换图/DELETE/权限/同步贯通),16/16 通过。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-09-28 23:57:43 +08:00
parent 121afadf1e
commit 4979091d2c
6 changed files with 1079 additions and 25 deletions
+3 -3
View File
@@ -1,8 +1,8 @@
// services/api/src/ads/ —— 广告位管理模块(ads-carousel Task 6,仅 cn 入口
// services/api/src/ads/ —— 广告位管理模块(ads-carousel,仅 cn 入口
// 装配:广告是 cn 权威实体,ov 侧只承接 ads_ov 投影与公开读端点)。
// UploadsModule 取 STORAGE_PORT(storage.provider.ts env 工厂;模块已 export,
// 同 EmbedModule 之后的装配口径);PrismaModule 为 @Global,Task 7 CRUD 落地
// 时直接注入。
// 同 EmbedModule 之后的装配口径);PrismaModule 为 @Global,CRUD(Task 7)
// 直接注入 PrismaService。
import { Module } from '@nestjs/common';
import { UploadsModule } from '../uploads/uploads.module';
import { AdsController } from './ads.controller';