/** * Geerntete Honigmenge je Kalenderjahr - Grundlage für die Honigkosten je kg * in ERPNext (Imkerei-Ausgaben des Jahres / geerntete kg). * * Gleiche Definition wie die Statistik in ApiCore (Honigertrag je Jahr): * Summe der Nettogewichte (kg) der Ernten, Jahr aus dem Erntedatum. Das * Jahr wird in UTC bestimmt, weil Erntedaten als Kalendertag (Mitternacht * UTC) gespeichert werden. Ernten ohne Nettogewicht zählen nicht zur Menge, * werden aber ausgewiesen - sonst sähe eine unvollständig erfasste Ernte * wie ein schlechtes Jahr aus und die Kosten je kg wären zu hoch. */ export interface HarvestWeight { date: Date; /** Kilogramm; null, wenn nicht erfasst. */ netWeight: number | null; } export interface HarvestYear { year: number; /** Summe der Nettogewichte in kg, auf Gramm gerundet. */ netWeightKg: number; harvestCount: number; harvestsWithoutNetWeight: number; } const GRAMS_PER_KG = 1000; function roundToGrams(kg: number): number { return Math.round(kg * GRAMS_PER_KG) / GRAMS_PER_KG; } function emptyYear(year: number): HarvestYear { return { year, netWeightKg: 0, harvestCount: 0, harvestsWithoutNetWeight: 0, }; } /** * Fasst Ernten je Jahr zusammen, älteste Jahre zuerst. Mit `onlyYear` nur * dieses Jahr, und zwar auch dann, wenn es keine Ernte hat (Nullzeile). */ export function summarizeHarvestYears( harvests: readonly HarvestWeight[], onlyYear?: number, ): HarvestYear[] { const byYear = new Map(); if (onlyYear !== undefined) { byYear.set(onlyYear, emptyYear(onlyYear)); } for (const harvest of harvests) { const year = harvest.date.getUTCFullYear(); if (onlyYear !== undefined && year !== onlyYear) continue; const current = byYear.get(year) ?? emptyYear(year); byYear.set(year, { year, netWeightKg: current.netWeightKg + (harvest.netWeight ?? 0), harvestCount: current.harvestCount + 1, harvestsWithoutNetWeight: current.harvestsWithoutNetWeight + (harvest.netWeight === null ? 1 : 0), }); } return [...byYear.values()] .sort((a, b) => a.year - b.year) .map((entry) => ({ ...entry, netWeightKg: roundToGrams(entry.netWeightKg), })); }