Add dashboard report snapshots feature with CRUD operations. Implemented new database migrations for dashboard_report_snapshots, including report type handling. Updated backend routes and models to support snapshot retrieval and upsert functionality. Enhanced frontend components to integrate report snapshot management, including UI for daily and end-cycle reports. Added tests for new functionality to ensure reliability.
CI / lint-and-test (push) Canceled after 0s

This commit is contained in:
Alberto-Audrix committed 2026-08-13 15:46:16 +07:00
1 parent 059087be1d
commit 34336b9bd1
41 files changed
+4824 -178

No files matched your search

@@ -0,0 +1,28 @@
-- Frozen latest Dashboard IoT-vs-manual report snapshot per cycle + kandang.
-- Generate again overwrites the same row. No TTL / expires_at.
CREATE TABLE IF NOT EXISTS dashboard_report_snapshots (
id SERIAL PRIMARY KEY,
cycle_id VARCHAR(255) NOT NULL,
kandang_id INTEGER NOT NULL,
payload JSONB NOT NULL DEFAULT '{}'::jsonb,
up_to_day INTEGER NOT NULL,
generated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (cycle_id) REFERENCES cycles(id) ON DELETE CASCADE,
FOREIGN KEY (kandang_id) REFERENCES kandangs(id) ON DELETE CASCADE,
UNIQUE (cycle_id, kandang_id)
);
CREATE INDEX IF NOT EXISTS idx_dashboard_report_snapshots_cycle_kandang
ON dashboard_report_snapshots (cycle_id, kandang_id);
DROP TRIGGER IF EXISTS update_dashboard_report_snapshots_updated_at ON dashboard_report_snapshots;
CREATE TRIGGER update_dashboard_report_snapshots_updated_at
BEFORE UPDATE ON dashboard_report_snapshots
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
COMMENT ON TABLE dashboard_report_snapshots IS
'Latest desktop Dashboard daily IoT-vs-manual report snapshot; one row per cycle+kandang, overwritten on Generate';
@@ -0,0 +1,39 @@
-- Independent daily vs end-cycle snapshots for the same cycle + kandang.
ALTER TABLE dashboard_report_snapshots
ADD COLUMN IF NOT EXISTS report_type VARCHAR(32) NOT NULL DEFAULT 'daily';
DO $$
DECLARE
constraint_name text;
BEGIN
SELECT conname INTO constraint_name
FROM pg_constraint
WHERE conrelid = 'dashboard_report_snapshots'::regclass
AND contype = 'u'
AND pg_get_constraintdef(oid) LIKE '%(cycle_id, kandang_id)%'
AND pg_get_constraintdef(oid) NOT LIKE '%report_type%';
IF constraint_name IS NOT NULL THEN
EXECUTE format('ALTER TABLE dashboard_report_snapshots DROP CONSTRAINT IF EXISTS %I', constraint_name);
END IF;
END $$;
ALTER TABLE dashboard_report_snapshots
DROP CONSTRAINT IF EXISTS dashboard_report_snapshots_cycle_id_kandang_id_key;
ALTER TABLE dashboard_report_snapshots
DROP CONSTRAINT IF EXISTS dashboard_report_snapshots_cycle_kandang_type_key;
ALTER TABLE dashboard_report_snapshots
ADD CONSTRAINT dashboard_report_snapshots_cycle_kandang_type_key
UNIQUE (cycle_id, kandang_id, report_type);
ALTER TABLE dashboard_report_snapshots
DROP CONSTRAINT IF EXISTS dashboard_report_snapshots_report_type_check;
ALTER TABLE dashboard_report_snapshots
ADD CONSTRAINT dashboard_report_snapshots_report_type_check
CHECK (report_type IN ('daily', 'end_cycle'));
COMMENT ON COLUMN dashboard_report_snapshots.report_type IS
'daily or end_cycle; unique with cycle_id + kandang_id so each type keeps its own latest snapshot';