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: 'gm', 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); }); });