/** * Typed shapes matching the 12 MEGA INFRASTRUCTURE collections on * `https://pb.mega.infra.apphub.co.za`. Keep in sync with the live * schema — re-run `scripts/pb-bootstrap-schema.py` after changes. */ import type { RecordModel } from "./pb"; export interface SiteRecord extends RecordModel { collectionName: "sites"; project_code: string; name: string; duration: string; contract_value: number; work_hours: number; hours_per_week: number; wages_hours_per_day: number; expand?: Record; } export type WorkerType = "permanent" | "casual"; export interface EmployeeRecord extends RecordModel { collectionName: "employees"; project_code: string; site: string; // relation id name: string; employee_no: string; position: string; rate_per_hour: number; hours_per_day_standard: number; worker_type: WorkerType; expand?: { site?: SiteRecord }; } export interface VehicleRecord extends RecordModel { collectionName: "vehicles"; project_code: string; site: string; description: string; standard_work_hours: string | number; fuel_limits: string; qr_code_id: string; cost_per_hour: number; expand?: { site?: SiteRecord }; } export interface PlantRecord extends VehicleRecord { // Deprecated alias — Plant has been merged into Vehicles. } export interface FixedCostRecord extends RecordModel { collectionName: "fixed_costs"; project_code: string; site: string; date_logged: string; description: string; cost: number; notes: string; expand?: { site?: SiteRecord }; } export type BatchType = | "timesheets" | "fuel_logs" | "purchase_orders" | "delivery_notes"; export type BatchStatus = | "pending" | "processing" | "processed" | "failed" | "dead"; export interface DataImportBatchRecord extends RecordModel { collectionName: "data_import_batches"; batch_type: BatchType; content_type?: string; original_file: string; date_uploaded: string; uploaded_by: string; status?: BatchStatus; // nullable for legacy T/F rows attempts?: number; last_error?: string; last_attempt_at?: string; next_retry_at?: string; processed_at?: string; processed_record_id?: string; } export interface PurchaseOrderRecord extends RecordModel { collectionName: "purchase_orders"; purchase_order_number: string; project_code: string; site: string; supplier: string; required_by_date: string; ordered_by: string; items_count: number; total_value: number; purchase_order_file: string; raw_ocr_data: unknown; is_verified: boolean; expand?: { site?: SiteRecord }; } export interface PurchaseOrderItemRecord extends RecordModel { collectionName: "purchase_order_items"; purchase_order: string; material_code: string; cost_code: string; description: string; qty: number; qty_outstanding: number; unit: string; rate: number; disc_percent: number; vat_percent: number; amount: number; expand?: { purchase_order?: PurchaseOrderRecord }; } export interface TimesheetRecord extends RecordModel { collectionName: "timesheets"; employee: string; batch_reference: string; date_logged: string; hours_worked: number; expand?: { employee?: EmployeeRecord; batch_reference?: DataImportBatchRecord }; } export interface FuelLogRecord extends RecordModel { collectionName: "fuel_logs"; project_code: string; site: string; vehicle: string; batch_reference: string; date_logged: string; litres: number; odo_reading: number; /** * "Latest Consumption" value as reported by the pump sheet (typically * litres/100km or litres/hour). Persisted verbatim from the source * Excel/CSV rather than recomputed, so the audit trail reflects what * the fuel team actually filed. Optional — the Aug 2026 sample has * ~9% empty cells, which we preserve as `undefined` rather than * fabricating a value. Added in the 2026-08-24 migration. */ latest_consumption?: number; expand?: { site?: SiteRecord; vehicle?: VehicleRecord; batch_reference?: DataImportBatchRecord; }; } export interface DeliveryNoteRecord extends RecordModel { collectionName: "delivery_notes"; delivery_note_number: string; project_code: string; site: string; purchase_order: string; date_received: string; received_by: string; slip_image: string; raw_ocr_data: unknown; is_verified: boolean; expand?: { site?: SiteRecord; purchase_order?: PurchaseOrderRecord }; } export interface ReceivedItemRecord extends RecordModel { collectionName: "received_items"; delivery_note: string; purchase_order_item: string; qty_received: number; condition_notes: string; expand?: { delivery_note?: DeliveryNoteRecord; purchase_order_item?: PurchaseOrderItemRecord; }; }