feat: complete drainage review and admin search workflows

This commit is contained in:
hectorzhao
2026-07-14 09:58:18 +08:00
parent dec2430b7e
commit 6421671259
33 changed files with 1107 additions and 255 deletions
@@ -0,0 +1,78 @@
CREATE TABLE "SmsDrainageInfo" (
"id" TEXT NOT NULL,
"tenantId" TEXT NOT NULL,
"signatureId" TEXT NOT NULL,
"applicationId" TEXT,
"siteName" TEXT NOT NULL,
"url" TEXT NOT NULL,
"remark" TEXT,
"reportValues" JSONB,
"auditStatus" TEXT NOT NULL DEFAULT 'pending',
"rejectReason" TEXT,
"submittedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"reviewedAt" TIMESTAMP(3),
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "SmsDrainageInfo_pkey" PRIMARY KEY ("id")
);
CREATE TEMP TABLE drainage_backfill_map AS
SELECT
signature."id" AS "signatureId",
COALESCE(NULLIF(item.value->>'id', ''), item.ordinality::text) AS "oldId",
'drain_' || md5(signature."id" || ':' || COALESCE(NULLIF(item.value->>'id', ''), item.ordinality::text)) AS "newId",
signature."tenantId" AS "tenantId",
signature."applicationId" AS "applicationId",
item.value AS item
FROM "SmsSignature" signature
CROSS JOIN LATERAL jsonb_array_elements(COALESCE(signature."drainageInfo"->'links', '[]'::jsonb)) WITH ORDINALITY AS item(value, ordinality);
INSERT INTO "SmsDrainageInfo" (
"id", "tenantId", "signatureId", "applicationId", "siteName", "url", "remark", "reportValues",
"auditStatus", "submittedAt", "createdAt", "updatedAt"
)
SELECT
"newId",
"tenantId",
"signatureId",
"applicationId",
COALESCE(NULLIF(item->>'siteName', ''), '未命名站点'),
COALESCE(item->>'url', ''),
NULLIF(item->>'remark', ''),
COALESCE(item->'reportValues', '{}'::jsonb),
CASE WHEN item->>'auditStatus' IN ('pending', 'approved', 'rejected') THEN item->>'auditStatus' ELSE 'pending' END,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP,
CURRENT_TIMESTAMP
FROM drainage_backfill_map;
UPDATE "ChannelSignatureReportTask" task
SET "drainageItemId" = map."newId"
FROM drainage_backfill_map map
WHERE task."signatureId" = map."signatureId"
AND task."reportType" = 'drainage'
AND task."drainageItemId" = map."oldId";
UPDATE "DrainageReportMaterial" material
SET "drainageItemId" = map."newId"
FROM drainage_backfill_map map
WHERE material."signatureId" = map."signatureId"
AND material."drainageItemId" = map."oldId";
DROP TABLE drainage_backfill_map;
CREATE INDEX "SmsDrainageInfo_tenantId_auditStatus_updatedAt_idx"
ON "SmsDrainageInfo"("tenantId", "auditStatus", "updatedAt");
CREATE INDEX "SmsDrainageInfo_signatureId_auditStatus_idx"
ON "SmsDrainageInfo"("signatureId", "auditStatus");
CREATE INDEX "SmsDrainageInfo_applicationId_idx"
ON "SmsDrainageInfo"("applicationId");
ALTER TABLE "SmsDrainageInfo" ADD CONSTRAINT "SmsDrainageInfo_tenantId_fkey"
FOREIGN KEY ("tenantId") REFERENCES "Tenant"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
ALTER TABLE "SmsDrainageInfo" ADD CONSTRAINT "SmsDrainageInfo_signatureId_fkey"
FOREIGN KEY ("signatureId") REFERENCES "SmsSignature"("id") ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE "SmsDrainageInfo" ADD CONSTRAINT "SmsDrainageInfo_applicationId_fkey"
FOREIGN KEY ("applicationId") REFERENCES "SmsApplication"("id") ON DELETE SET NULL ON UPDATE CASCADE;
ALTER TABLE "ChannelSignatureReportTask" ADD CONSTRAINT "ChannelSignatureReportTask_drainageItemId_fkey"
FOREIGN KEY ("drainageItemId") REFERENCES "SmsDrainageInfo"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
@@ -0,0 +1,2 @@
ALTER TABLE "ChannelSignatureReportRecord"
ADD COLUMN "sourceEntry" TEXT NOT NULL DEFAULT 'system';
+31
View File
@@ -26,6 +26,7 @@ model Tenant {
smsBillingRecords SmsBillingRecord[]
smsApplications SmsApplication[]
smsSignatures SmsSignature[]
smsDrainageInfos SmsDrainageInfo[]
smsTemplates SmsTemplate[]
auditRecords AuditRecord[]
riskRules RiskRule[]
@@ -366,6 +367,7 @@ model SmsApplication {
tenant Tenant @relation(fields: [tenantId], references: [id])
ipAllowlist SmsApplicationIpAllowlist[]
signatures SmsSignature[]
drainageInfos SmsDrainageInfo[]
templates SmsTemplate[]
enterpriseBlacklists EnterpriseBlacklist[]
sendTasks SmsSendTask[]
@@ -413,6 +415,7 @@ model SmsSignature {
templates SmsTemplate[]
reportMaterials SignatureReportMaterial[]
drainageReportMaterials DrainageReportMaterial[]
drainageItems SmsDrainageInfo[]
reportTasks ChannelSignatureReportTask[]
messageRecords SmsMessageRecord[]
@@ -420,6 +423,32 @@ model SmsSignature {
@@index([tenantId, reportStatus])
}
model SmsDrainageInfo {
id String @id @default(cuid())
tenantId String
signatureId String
applicationId String?
siteName String
url String
remark String?
reportValues Json?
auditStatus String @default("pending")
rejectReason String?
submittedAt DateTime @default(now())
reviewedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
tenant Tenant @relation(fields: [tenantId], references: [id])
signature SmsSignature @relation(fields: [signatureId], references: [id], onDelete: Cascade)
application SmsApplication? @relation(fields: [applicationId], references: [id])
reportTasks ChannelSignatureReportTask[]
@@index([tenantId, auditStatus, updatedAt])
@@index([signatureId, auditStatus])
@@index([applicationId])
}
model SignatureMaterial {
id String @id @default(cuid())
signatureId String
@@ -730,6 +759,7 @@ model ChannelSignatureReportTask {
signature SmsSignature @relation(fields: [signatureId], references: [id])
channel SmsChannel @relation(fields: [channelId], references: [id])
drainageInfo SmsDrainageInfo? @relation(fields: [drainageItemId], references: [id])
records ChannelSignatureReportRecord[]
exportFiles ReportExportFile[]
receiptImports ReportReceiptImport[]
@@ -749,6 +779,7 @@ model ChannelSignatureReportRecord {
statusAfter String
reason String?
operatorId String?
sourceEntry String @default("system")
createdAt DateTime @default(now())
task ChannelSignatureReportTask @relation(fields: [taskId], references: [id], onDelete: Cascade)