Further CSV Import method added
Deploy / deploy (push) Successful in 2m42s

This commit is contained in:
twotalesanimation
2026-08-06 08:36:26 +02:00
parent c727795a78
commit 5f3c89119a
4 changed files with 415 additions and 3 deletions
+80
View File
@@ -951,6 +951,86 @@ export async function updateShotsSeqTimecodes(
return { updated, skipped, errors };
}
// ── Simple CSV shot import ────────────────────────────────────────────────────
export interface SimpleCsvRow {
shotCode: string;
seqTimecodeStart: string;
seqTimecodeEnd: string;
description: string;
action: "create" | "update" | "skip";
}
export async function importShotsFromSimpleCsv(
projectId: string,
rows: SimpleCsvRow[]
): Promise<{ created: string[]; updated: string[]; skipped: string[]; errors: string[] }> {
const session = await auth();
if (!session?.user) throw new Error("Unauthorized");
if (!["ADMIN", "PRODUCER", "SUPERVISOR"].includes(session.user.role)) {
throw new Error("Insufficient permissions");
}
const created: string[] = [];
const updated: string[] = [];
const skipped: string[] = [];
const errors: string[] = [];
for (const row of rows) {
if (row.action === "skip") { skipped.push(row.shotCode); continue; }
try {
const existing = await db.shot.findFirst({
where: { projectId, shotCode: row.shotCode },
select: { id: true },
});
if (existing) {
await db.shot.update({
where: { id: existing.id },
data: {
description: row.description || null,
seqTimecodeStart: row.seqTimecodeStart || null,
seqTimecodeEnd: row.seqTimecodeEnd || null,
},
});
updated.push(row.shotCode);
} else if (row.action === "create") {
const parts = row.shotCode.split("_");
const scene = parts.length >= 3 ? parts[2] : (parts[1] ?? "000");
const episode = parts.length >= 4 ? parts[1] : null;
const maxNum = await db.shot.findFirst({
where: { projectId, scene, episode },
orderBy: { shotNumber: "desc" },
select: { shotNumber: true },
});
const shotNumber = (maxNum?.shotNumber ?? 0) + 10;
await db.shot.create({
data: {
projectId,
shotCode: row.shotCode,
scene,
episode,
shotNumber,
description: row.description || null,
seqTimecodeStart: row.seqTimecodeStart || null,
seqTimecodeEnd: row.seqTimecodeEnd || null,
},
});
created.push(row.shotCode);
} else {
// action === "update" but shot not found
skipped.push(row.shotCode);
}
} catch (e) {
errors.push(`${row.shotCode}: ${e instanceof Error ? e.message : "Unknown error"}`);
}
}
revalidatePath(`/projects/${projectId}`);
return { created, updated, skipped, errors };
}
/**
* Internal: handle client requesting changes on a shot.
* Resets shotApprovalStatus = PENDING, sharedWithClient = false.