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
CI / lint-and-test (push) Canceled after 0s
This commit is contained in:
1 parent
059087be1d
commit
34336b9bd1
41 files changed
+4824
-178
No files matched your search
@@ -0,0 +1,94 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type {
|
||||
DashboardReportCountingRow,
|
||||
DashboardReportFeedInRow,
|
||||
DashboardReportFeedUseRow,
|
||||
} from '../../types/dashboardReport.ts';
|
||||
import { countingTotals, feedInTotals, feedUseTotals } from '../reportTotals.ts';
|
||||
|
||||
describe('countingTotals', () => {
|
||||
it('sums mortality, harvest, and harvest weight; omits stok akhir and IoT', () => {
|
||||
const rows: DashboardReportCountingRow[] = [
|
||||
{
|
||||
date: '2026-05-22',
|
||||
day: 0,
|
||||
countBefore: 100,
|
||||
mortality: 0,
|
||||
harvest: 0,
|
||||
harvestWeight: null,
|
||||
countAfter: 100,
|
||||
iotCount: 98,
|
||||
accuracy: 98,
|
||||
},
|
||||
{
|
||||
date: '2026-05-23',
|
||||
day: 1,
|
||||
countBefore: 100,
|
||||
mortality: 5,
|
||||
harvest: 1,
|
||||
harvestWeight: 4.5,
|
||||
countAfter: 94,
|
||||
iotCount: 90,
|
||||
accuracy: 95.7,
|
||||
},
|
||||
{
|
||||
date: '2026-05-24',
|
||||
day: 2,
|
||||
countBefore: 94,
|
||||
mortality: 2,
|
||||
harvest: 0,
|
||||
harvestWeight: null,
|
||||
countAfter: 92,
|
||||
iotCount: 91,
|
||||
accuracy: 98.9,
|
||||
},
|
||||
];
|
||||
|
||||
expect(countingTotals(rows)).toEqual({
|
||||
label: 'Total',
|
||||
countBefore: 100,
|
||||
mortality: 7,
|
||||
harvest: 1,
|
||||
harvestWeight: 4.5,
|
||||
countAfter: null,
|
||||
iotCount: null,
|
||||
accuracy: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns null when there are no counting rows', () => {
|
||||
expect(countingTotals([])).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('feedInTotals', () => {
|
||||
it('sums sacks and recomputes accuracy from the totals', () => {
|
||||
const rows: DashboardReportFeedInRow[] = [
|
||||
{ date: '2026-05-22', manualIn: 10, iotIn: 10, accuracy: 100 },
|
||||
{ date: '2026-05-23', manualIn: 5, iotIn: 4, accuracy: 80 },
|
||||
];
|
||||
|
||||
expect(feedInTotals(rows)).toEqual({
|
||||
label: 'Total',
|
||||
manualIn: 15,
|
||||
iotIn: 14,
|
||||
accuracy: 93.3,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('feedUseTotals', () => {
|
||||
it('sums left+right daily sacks across the period', () => {
|
||||
const rows: DashboardReportFeedUseRow[] = [
|
||||
{ date: '2026-05-22', day: 0, manualUse: 30, iotUse: 30, accuracy: 100 },
|
||||
{ date: '2026-05-23', day: 1, manualUse: 10, iotUse: 8, accuracy: 80 },
|
||||
];
|
||||
|
||||
expect(feedUseTotals(rows)).toEqual({
|
||||
label: 'Total',
|
||||
manualUse: 40,
|
||||
iotUse: 38,
|
||||
accuracy: 95,
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user