first commit
Docker-Images bauen und veroeffentlichen / build-and-push (push) Failing after 1m32s

This commit is contained in:
Nick Szaunig committed 2026-09-27 06:06:56 +02:00
commit 59bb5a38a3
132 files changed
+19435

No files matched your search

+65
View File
@@ -0,0 +1,65 @@
import { describe, expect, test } from "vitest";
import { buildSchedule, splitIntoInstallments } from "@/lib/payment-plan";
import { calculatePrice } from "@/lib/pricing";
describe("Exakte Zahlungsplaene laut Vorgabe", () => {
test.each([
["Early Bird", "EARLY_BIRD", false, [[220_000], [110_000, 110_000], [80_000, 70_000, 70_000]]],
["Early Bird Stammmodel", "EARLY_BIRD", true, [[198_000], [99_000, 99_000], [66_000, 66_000, 66_000]]],
["Regulaer", "REGULAR", false, [[275_000], [137_500, 137_500], [95_000, 90_000, 90_000]]],
["Regulaer Stammmodel", "REGULAR", true, [[247_500], [123_750, 123_750], [82_500, 82_500, 82_500]]],
] as const)("%s", (_label, phase, code, expected) => {
const total = calculatePrice(phase, code).totalCents;
for (const [index, plan] of expected.entries()) {
const split = splitIntoInstallments(total, index + 1);
expect(split).toEqual(plan);
expect(split.reduce((a, b) => a + b, 0)).toBe(total);
}
});
test("1.237,50 € je Rate bleibt centgenau", () => {
expect(splitIntoInstallments(247_500, 2)).toEqual([123_750, 123_750]);
});
test("mehr als drei Raten sind ausgeschlossen", () => {
expect(() => splitIntoInstallments(220_000, 4)).toThrow();
});
});
describe("Faelligkeiten", () => {
const base = {
totalCents: 220_000,
campStartDate: "2027-06-05",
finalInstallmentLeadDays: 30,
minInstallmentGapDays: 14,
};
test("letzte Rate 30 Tage vor Anreise, zweite in der Mitte, Einzug 09:00 Berlin", () => {
const result = buildSchedule({ ...base, planType: "THREE_INSTALLMENTS", now: new Date("2026-11-15T10:00:00Z") });
expect(result.ok).toBe(true);
if (!result.ok) return;
// 172 Tage bis zur Frist -> zweite Rate nach 86 Tagen.
expect(result.installments.map((i) => i.dueDate)).toEqual([null, "2027-02-09", "2027-05-06"]);
// 06.05.2027 09:00 Sommerzeit = 07:00 UTC
expect(result.installments[2]!.dueAt!.toISOString()).toBe("2027-05-06T07:00:00.000Z");
expect(result.installments[0]!.amountCents).toBe(80_000);
});
test("ohne Camp-Termin keine Ratenzahlung, Einmalzahlung bleibt moeglich", () => {
const now = new Date("2026-11-15T10:00:00Z");
expect(buildSchedule({ ...base, campStartDate: null, planType: "TWO_INSTALLMENTS", now })).toEqual({
ok: false,
reason: "CAMP_DATE_MISSING",
});
expect(buildSchedule({ ...base, campStartDate: null, planType: "FULL", now }).ok).toBe(true);
});
test("zu knapp vor der Frist wird die Variante serverseitig deaktiviert", () => {
// Frist 06.05.2027; 20 Tage vorher reichen fuer zwei, nicht fuer drei Raten.
const now = new Date("2027-04-16T10:00:00Z");
expect(buildSchedule({ ...base, planType: "TWO_INSTALLMENTS", now }).ok).toBe(true);
expect(buildSchedule({ ...base, planType: "THREE_INSTALLMENTS", now })).toEqual({ ok: false, reason: "TOO_LATE" });
const later = new Date("2027-04-30T10:00:00Z");
expect(buildSchedule({ ...base, planType: "TWO_INSTALLMENTS", now: later })).toEqual({ ok: false, reason: "TOO_LATE" });
});
});