use time::{Date, Time};
use mako_fristen::HolidayCalendar;
use mako_mabis::Bilanzierungsmonat;
pub use mako_fristen::antwort::{MODELL_2_ANMELDUNG_ANTWORT_WT, MODELL_2_DREI_WERKTAGE};
pub const BEENDIGUNG_AN_LF_WT: u32 = 3;
pub const MODELLWECHSEL_VORLAUF_MONATE: u32 = 1;
pub const ZP_NGZ_ZUORDNUNG_VORLAUF_WT: u32 = 5;
pub const ZP_NGZ_ANTWORT_WT: u32 = 1;
pub const ZP_NGZ_UENB_INFO_WT: u32 = 1;
pub const BK_SZR_ZP_AKTIVIERUNG_VORLAUF_WT: u32 = 1;
pub const TAEGLICHE_BK_SZR_UHRZEIT: Time = time::macros::time!(14:00);
#[must_use]
pub fn fruehester_modellwechsel(uebertragungstag: Date) -> Date {
let ein_monat_spaeter = crate::bg::naechster_monatserster(uebertragungstag);
crate::bg::naechster_monatserster(ein_monat_spaeter)
}
#[must_use]
pub fn taegliche_bk_szr_faellig(liefertag: Date) -> time::OffsetDateTime {
let folgetag = liefertag
.next_day()
.expect("a delivery day is never the last representable date");
mako_fristen::berlin_at(folgetag, TAEGLICHE_BK_SZR_UHRZEIT)
}
#[must_use]
pub fn korrekturfrist(monat: Bilanzierungsmonat) -> Date {
monat.monatsende_nach(KORREKTURFENSTER_MONATE)
}
pub const KORREKTURFENSTER_MONATE: u32 = 7;
#[must_use]
pub fn spaetester_zp_ngz_versand(erster_datenversand: Date) -> Date {
mako_fristen::sub_werktage(
erster_datenversand,
ZP_NGZ_ZUORDNUNG_VORLAUF_WT,
HolidayCalendar::BdewMaKo,
)
}
#[cfg(test)]
mod tests {
use super::*;
use time::Month;
fn d(y: i32, m: u8, day: u8) -> Date {
Date::from_calendar_date(y, Month::try_from(m).unwrap(), day).unwrap()
}
#[test]
fn a_month_of_lead_time_lands_two_month_starts_ahead() {
assert_eq!(fruehester_modellwechsel(d(2026, 11, 1)), d(2027, 1, 1));
assert_eq!(fruehester_modellwechsel(d(2026, 11, 30)), d(2027, 1, 1));
assert_eq!(fruehester_modellwechsel(d(2026, 12, 15)), d(2027, 2, 1));
}
#[test]
fn the_daily_series_is_due_at_1400_the_next_day() {
let due = taegliche_bk_szr_faellig(d(2026, 11, 3));
assert_eq!(mako_fristen::berlin_date(due), d(2026, 11, 4));
assert_eq!(due.to_offset(due.offset()).time(), TAEGLICHE_BK_SZR_UHRZEIT);
}
#[test]
fn the_zp_zuordnung_needs_five_werktage() {
assert_eq!(spaetester_zp_ngz_versand(d(2026, 11, 16)), d(2026, 11, 9));
}
#[test]
fn the_korrekturfrist_closes_at_the_end_of_month_seven() {
let november = Bilanzierungsmonat::enthaltend(d(2026, 11, 12));
assert_eq!(korrekturfrist(november), d(2027, 6, 30));
let februar = Bilanzierungsmonat::enthaltend(d(2027, 2, 3));
assert_eq!(korrekturfrist(februar), d(2027, 9, 30));
}
#[test]
fn the_answer_windows_come_from_the_one_table() {
assert_eq!(MODELL_2_ANMELDUNG_ANTWORT_WT, 7);
assert_eq!(MODELL_2_DREI_WERKTAGE, 3);
assert_eq!(BEENDIGUNG_AN_LF_WT, MODELL_2_DREI_WERKTAGE);
}
}