feat(noc): integrate DocumentStat model and sync with external NOC API

This commit is contained in:
2026-03-31 15:04:51 +08:00
parent 11ef320d55
commit 6ace5b5d1c
9 changed files with 260 additions and 39 deletions

View File

@@ -0,0 +1,15 @@
-- CreateTable
CREATE TABLE "document_stat" (
"id" TEXT NOT NULL,
"villageId" TEXT NOT NULL DEFAULT 'desa1',
"label" TEXT NOT NULL,
"value" INTEGER NOT NULL DEFAULT 0,
"color" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,
CONSTRAINT "document_stat_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "document_stat_villageId_label_key" ON "document_stat"("villageId", "label");

View File

@@ -107,6 +107,19 @@ model Document {
@@map("document")
}
model DocumentStat {
id String @id @default(cuid())
villageId String @default("desa1")
label String
value Int @default(0)
color String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([villageId, label])
@@map("document_stat")
}
model Discussion {
id String @id @default(cuid())
externalId String? @unique // ID asli dari server NOC

View File

@@ -13,6 +13,7 @@ import {
seedDiscussions,
seedDivisionMetrics,
seedDocuments,
seedDocumentStats,
} from "./seeders/seed-discussions";
import {
getDivisionIds,
@@ -102,6 +103,7 @@ export async function runSeed() {
// 5. Seed Documents & Discussions
console.log("📁 [5/7] Documents & Discussions");
await seedDocuments(divisionIds, adminId);
await seedDocumentStats();
await seedDiscussions(divisionIds, adminId);
console.log();
@@ -188,6 +190,7 @@ export async function runSpecificSeeder(name: string) {
const divs = await seedDivisions();
const divIds = divs.map((d) => d.id);
await seedDocuments(divIds, docAdminId);
await seedDocumentStats();
await seedDiscussions(divIds, docAdminId);
break;
}

View File

@@ -70,6 +70,44 @@ export async function seedDocuments(divisionIds: string[], userId: string) {
console.log("✅ Documents seeded successfully");
}
/**
* Seed Document Stats
* Creates aggregate document counts matching user request
*/
export async function seedDocumentStats() {
console.log("Seeding Document Stats...");
const stats = [
{
villageId: "desa1",
label: "Gambar",
value: 389,
color: "#fac858",
},
{
villageId: "desa1",
label: "Dokumen",
value: 147,
color: "#92cc76",
},
];
for (const stat of stats) {
await prisma.documentStat.upsert({
where: {
villageId_label: {
villageId: stat.villageId,
label: stat.label,
},
},
update: stat,
create: stat,
});
}
console.log("✅ Document Stats seeded successfully");
}
/**
* Seed Discussions
* Creates sample discussions for divisions and activities
@@ -115,12 +153,15 @@ export async function seedDiscussions(divisionIds: string[], userId: string) {
// Create parent discussions first
const parentDiscussions = [];
for (let i = 0; i < discussions.length; i += 2) {
const current = discussions[i];
if (!current) continue;
const discussion = await prisma.discussion.create({
data: {
message: discussions[i].message,
senderId: discussions[i].senderId,
divisionId: discussions[i].divisionId,
isResolved: discussions[i].isResolved,
message: current.message,
senderId: current.senderId,
divisionId: current.divisionId,
isResolved: current.isResolved,
},
});
parentDiscussions.push(discussion);
@@ -128,16 +169,20 @@ export async function seedDiscussions(divisionIds: string[], userId: string) {
// Create replies
for (let i = 1; i < discussions.length; i += 2) {
const current = discussions[i];
if (!current) continue;
const parentIndex = Math.floor((i - 1) / 2);
if (parentIndex < parentDiscussions.length) {
const parent = parentDiscussions[parentIndex];
if (parent) {
await prisma.discussion.update({
where: { id: parentDiscussions[parentIndex].id },
where: { id: parent.id },
data: {
replies: {
create: {
message: discussions[i].message,
senderId: discussions[i].senderId,
isResolved: discussions[i].isResolved,
message: current.message,
senderId: current.senderId,
isResolved: current.isResolved,
},
},
},