Adds the full Next.js app (app/, components/, lib/, scripts/, assets/, docs/, Dockerfile, compose, configs) to version control. Security: - CIPC BizPortal customer-code logins (Login 1 + Login 3) now read CIPC_LOGIN1_CODE / CIPC_LOGIN1_PASSWORD / CIPC_LOGIN3_CODE / CIPC_LOGIN3_PASSWORD from .env.local instead of source. - BizPortal personal login in apply-bizportal route reads BIZPORTAL_ID_NO / BIZPORTAL_PASSWORD. - Added .env.example as the committed template. .gitignore excludes .env*, node_modules, .next, logs, sqlite, Playwright storage_state.json (live CIPC cookies), scratch dirs, client PDFs and debug screenshots.
77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
// lib/sars-runs.ts
|
|
// Tiny wrapper around the sars_runs PocketBase collection.
|
|
//
|
|
// One record per SARS capture run, written at run start (status="running")
|
|
// and patched at run end (status="completed"|"failed" + counts + result_path).
|
|
// Per-row data writes to the per-return-type collection (e.g.
|
|
// ysterbaard_SARS_EMP201_PAYE) are still a separate future sprint.
|
|
//
|
|
// The collection schema is documented in:
|
|
// - the .env.local header comment
|
|
// - the user memory entry "PocketBase auth gotcha" (refreshed 2026-09-10)
|
|
// - the request to the user when the sars_runs collection was first created
|
|
|
|
import "server-only";
|
|
import { createRecord, updateRecord, type PBRecord } from "./pb";
|
|
|
|
const COLLECTION = "sars_runs";
|
|
|
|
interface RunStartInput {
|
|
run_id: string;
|
|
started_at: string; // ISO timestamp
|
|
return_type: string;
|
|
period_start: string;
|
|
period_end: string;
|
|
periods_requested: string[];
|
|
companies: string[] | null; // null when allActive
|
|
companies_count: number;
|
|
created_by?: string;
|
|
}
|
|
|
|
interface RunEndInput {
|
|
finished_at: string;
|
|
status: "completed" | "failed";
|
|
result_path: string | null;
|
|
ok_count: number;
|
|
error_count: number;
|
|
error_message?: string | null;
|
|
}
|
|
|
|
/**
|
|
* Create a sars_runs record at the start of a run. Returns the PB
|
|
* record id so we can patch it later. Throws on failure — the caller
|
|
* is expected to handle the error and either abort the run or
|
|
* continue without PB audit.
|
|
*/
|
|
export async function createRunRecord(input: RunStartInput): Promise<string> {
|
|
const record = await createRecord<PBRecord>(COLLECTION, {
|
|
run_id: input.run_id,
|
|
started_at: input.started_at,
|
|
return_type: input.return_type,
|
|
period_start: input.period_start,
|
|
period_end: input.period_end,
|
|
periods_requested: input.periods_requested,
|
|
companies: input.companies,
|
|
companies_count: input.companies_count,
|
|
status: "running",
|
|
created_by: input.created_by ?? "sj",
|
|
});
|
|
return record.id;
|
|
}
|
|
|
|
/**
|
|
* Patch a sars_runs record at the end of a run. Best-effort: the
|
|
* caller should log but not throw on failure (the .py already
|
|
* produced the result file, and a missing audit row is recoverable
|
|
* from the result_path on disk).
|
|
*/
|
|
export async function finishRunRecord(recordId: string, input: RunEndInput): Promise<void> {
|
|
await updateRecord<PBRecord>(COLLECTION, recordId, {
|
|
finished_at: input.finished_at,
|
|
status: input.status,
|
|
result_path: input.result_path,
|
|
ok_count: input.ok_count,
|
|
error_count: input.error_count,
|
|
error_message: input.error_message ?? null,
|
|
});
|
|
}
|