121 lines
3.4 KiB
TypeScript
121 lines
3.4 KiB
TypeScript
import ExcelJS from 'exceljs';
|
|
import type { DashboardReportPayload } from '../types/dashboardReport.ts';
|
|
|
|
const na = (value: number | null | undefined): number | string =>
|
|
value == null || !Number.isFinite(value) ? 'N/A' : value;
|
|
|
|
export async function downloadReportExcel(payload: DashboardReportPayload): Promise<void> {
|
|
const workbook = new ExcelJS.Workbook();
|
|
workbook.creator = 'Dashboard CPSP';
|
|
|
|
const counting = workbook.addWorksheet('Chicken Counting');
|
|
counting.addRow([
|
|
'Tanggal',
|
|
'Hari',
|
|
'Stok awal',
|
|
'Mortalitas',
|
|
'Panen',
|
|
'Stok akhir',
|
|
'IoT',
|
|
'Akurasi %',
|
|
]);
|
|
for (const row of payload.counting) {
|
|
counting.addRow([
|
|
row.date,
|
|
row.day,
|
|
na(row.countBefore),
|
|
na(row.mortality),
|
|
na(row.harvest),
|
|
na(row.countAfter),
|
|
na(row.iotCount),
|
|
na(row.accuracy),
|
|
]);
|
|
}
|
|
|
|
const weight = workbook.addWorksheet('Weight');
|
|
weight.addRow([
|
|
'Tanggal',
|
|
'Hari',
|
|
'AVG manual',
|
|
'AVG IoT',
|
|
'Keseragaman',
|
|
'Selisih',
|
|
'Akurasi %',
|
|
]);
|
|
for (const row of payload.weight) {
|
|
weight.addRow([
|
|
row.date,
|
|
row.day,
|
|
na(row.avgManual),
|
|
na(row.avgIot),
|
|
na(row.uniformity),
|
|
na(row.difference),
|
|
na(row.accuracy),
|
|
]);
|
|
}
|
|
|
|
const feedInSheet = workbook.addWorksheet('Feed In');
|
|
feedInSheet.addRow(['Tanggal', 'Manual in', 'IoT in', 'Akurasi in %']);
|
|
for (const row of payload.feedIn) {
|
|
feedInSheet.addRow([row.date, na(row.manualIn), na(row.iotIn), na(row.accuracy)]);
|
|
}
|
|
|
|
const feedUseSheet = workbook.addWorksheet('Feed Use');
|
|
feedUseSheet.addRow(['Tanggal', 'Hari', 'Manual use', 'IoT use', 'Akurasi use %']);
|
|
for (const row of payload.feedUse) {
|
|
feedUseSheet.addRow([row.date, row.day, na(row.manualUse), na(row.iotUse), na(row.accuracy)]);
|
|
}
|
|
|
|
const feedOutSheet = workbook.addWorksheet('Feed Out');
|
|
feedOutSheet.addRow(['Tanggal', 'Manual out', 'IoT out', 'Akurasi out %']);
|
|
for (const row of payload.feedOut) {
|
|
feedOutSheet.addRow([row.date, na(row.manualOut), na(row.iotOut), na(row.accuracy)]);
|
|
}
|
|
|
|
const fcrSheet = workbook.addWorksheet('FCR');
|
|
fcrSheet.addRow(['Hari', 'FCR', 'Total Pakan', 'Bobot IoT', 'Ayam Hidup', 'Total Bobot Panen']);
|
|
for (const row of payload.fcr) {
|
|
fcrSheet.addRow([
|
|
row.day,
|
|
na(row.iotFcr),
|
|
na(row.feedTotal),
|
|
na(row.iotWeight),
|
|
na(row.chickenLife),
|
|
na(row.harvestWeightTotal),
|
|
]);
|
|
}
|
|
|
|
const eefSheet = workbook.addWorksheet('EEF');
|
|
eefSheet.addRow([
|
|
'Hari',
|
|
'EEF',
|
|
'Persentase Ayam Hidup',
|
|
'BW Rata-rata Panen',
|
|
'Umur Rata-rata Panen',
|
|
'FCR',
|
|
]);
|
|
for (const row of payload.eef) {
|
|
eefSheet.addRow([
|
|
row.day,
|
|
na(row.iotEef),
|
|
na(row.chickenLifePercentage),
|
|
na(row.iotAverageHarvestBw),
|
|
na(row.iotAverageDayWeight),
|
|
na(row.iotFcr),
|
|
]);
|
|
}
|
|
|
|
const buffer = await workbook.xlsx.writeBuffer();
|
|
const blob = new Blob([buffer], {
|
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
});
|
|
const period =
|
|
payload.reportType === 'end_cycle' ? 'Akhir-Siklus' : `Harian-Hari-${payload.upToDay}`;
|
|
const url = URL.createObjectURL(blob);
|
|
const anchor = document.createElement('a');
|
|
anchor.href = url;
|
|
anchor.download = `Laporan-${period}-${payload.area}-${payload.kandangName}-${payload.cycleStart}_sd_${payload.cycleEnd}.xlsx`;
|
|
anchor.click();
|
|
URL.revokeObjectURL(url);
|
|
}
|