181 lines
4.4 KiB
TypeScript
181 lines
4.4 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { buildInMemoryReport } from '../buildInMemoryReport.ts';
|
|
import type { ChickenCounting, Cycle, Karung, KPI } from '../../types/api.ts';
|
|
|
|
const cycle: Cycle = {
|
|
id: 1,
|
|
kandang: 9,
|
|
kandang_name: 'Kandang 1',
|
|
total_days: 35,
|
|
current_day: 1,
|
|
visible_through_date: '2026-05-02',
|
|
start_date: '2026-05-01',
|
|
end_date: '2026-06-04',
|
|
chick_in_weight: 45,
|
|
doc_in_count: 20000,
|
|
feed_initial_balance: 0,
|
|
status: 'active',
|
|
created_at: '',
|
|
updated_at: '',
|
|
};
|
|
|
|
describe('buildInMemoryReport', () => {
|
|
it('maps IoT counting and karung onto daily rows up to current_day', () => {
|
|
const countings: ChickenCounting[] = [
|
|
{
|
|
id: 1,
|
|
cycle: 1,
|
|
kandang: 9,
|
|
flock_id: 1,
|
|
date: '2026-05-02',
|
|
total_count: 19800,
|
|
mortality_count: 12,
|
|
created_at: '',
|
|
updated_at: '',
|
|
},
|
|
];
|
|
const karungs: Karung[] = [
|
|
{
|
|
id: 1,
|
|
cycle: 1,
|
|
kandang: 9,
|
|
flock_id: 1,
|
|
date: '2026-05-02',
|
|
in_today: 10,
|
|
out_today: 8,
|
|
in_total: 10,
|
|
out_total: 8,
|
|
feed_use_today: 8,
|
|
feed_use_total: 8,
|
|
created_at: '',
|
|
updated_at: '',
|
|
},
|
|
];
|
|
const kpis: KPI[] = [
|
|
{
|
|
id: 1,
|
|
cycle: 1,
|
|
kandang: 9,
|
|
flock_id: 1,
|
|
date: '2026-05-02',
|
|
age: 1,
|
|
mortality: 12,
|
|
mortality_total: 12,
|
|
feed: 8,
|
|
feed_total: 8,
|
|
harvest: 0,
|
|
harvest_total: 0,
|
|
harvest_weight: 0,
|
|
harvest_weight_total: 0,
|
|
chicken_life: 19800,
|
|
chicken_life_percentage: 99,
|
|
iot_weight: 0,
|
|
average_harvest_day: 0,
|
|
average_harvest_weight: 0,
|
|
fcr: 1.2,
|
|
eef: 250,
|
|
cc: 1,
|
|
cw: 1,
|
|
fs: 1,
|
|
manual: 1,
|
|
created_at: '',
|
|
updated_at: '',
|
|
},
|
|
];
|
|
|
|
const payload = buildInMemoryReport({
|
|
cycle,
|
|
kandangId: 9,
|
|
kandangName: 'Kandang 1',
|
|
area: 'Sukawarna',
|
|
reportType: 'daily',
|
|
countings,
|
|
manuals: [],
|
|
weights: [],
|
|
karungs,
|
|
kpis,
|
|
});
|
|
|
|
expect(payload.upToDay).toBe(1);
|
|
expect(payload.docWeight).toBe(45);
|
|
expect(payload.counting).toHaveLength(2);
|
|
const day0 = payload.counting.find((row) => row.day === 0);
|
|
expect(day0?.countBefore).toBe(20000);
|
|
expect(day0?.countAfter).toBe(20000);
|
|
const day1 = payload.counting.find((row) => row.day === 1);
|
|
expect(day1?.countBefore).toBe(20000);
|
|
expect(day1?.iotCount).toBe(19800);
|
|
expect(day1?.mortality).toBe(12);
|
|
const feed1 = payload.feedUse.find((row) => row.day === 1);
|
|
expect(feed1?.iotUse).toBe(8);
|
|
expect(payload.fcr.find((row) => row.day === 1)?.iotFcr).toBe(1.2);
|
|
});
|
|
|
|
it('uses doc_in_count for day-0 stok awal instead of reverse-calculating from stok akhir', () => {
|
|
const countings: ChickenCounting[] = [
|
|
{
|
|
id: 1,
|
|
cycle: 1,
|
|
kandang: 9,
|
|
flock_id: 1,
|
|
date: '2026-05-01',
|
|
total_count: 36900,
|
|
mortality_count: 42,
|
|
created_at: '',
|
|
updated_at: '',
|
|
},
|
|
];
|
|
const kpis: KPI[] = [
|
|
{
|
|
id: 1,
|
|
cycle: 1,
|
|
kandang: 9,
|
|
flock_id: 1,
|
|
date: '2026-05-01',
|
|
age: 0,
|
|
mortality: 42,
|
|
mortality_total: 42,
|
|
feed: 0,
|
|
feed_total: 0,
|
|
harvest: 0,
|
|
harvest_total: 0,
|
|
harvest_weight: 0,
|
|
harvest_weight_total: 0,
|
|
chicken_life: 45000,
|
|
chicken_life_percentage: 100,
|
|
iot_weight: 0,
|
|
average_harvest_day: 0,
|
|
average_harvest_weight: 0,
|
|
fcr: 0,
|
|
eef: 0,
|
|
cc: 1,
|
|
cw: 1,
|
|
fs: 1,
|
|
manual: 1,
|
|
created_at: '',
|
|
updated_at: '',
|
|
},
|
|
];
|
|
|
|
const payload = buildInMemoryReport({
|
|
cycle: { ...cycle, doc_in_count: 45000, current_day: 0, start_date: '2026-05-01' },
|
|
kandangId: 9,
|
|
kandangName: 'Kandang 1',
|
|
area: 'Sukawarna',
|
|
reportType: 'daily',
|
|
countings,
|
|
manuals: [],
|
|
weights: [],
|
|
karungs: [],
|
|
kpis,
|
|
});
|
|
|
|
const day0 = payload.counting.find((row) => row.day === 0);
|
|
expect(day0?.countBefore).toBe(45000);
|
|
expect(day0?.mortality).toBe(42);
|
|
expect(day0?.countAfter).toBe(45000);
|
|
expect(day0?.iotCount).toBe(36900);
|
|
expect(day0?.accuracy).toBe(82);
|
|
});
|
|
});
|