Abo (A1+A2): Liefertag frei waehlbar 1-31, Aenderung nur nach vorn, Sperre erst am Ausfuehrungstag

A1: Jeder Monatstag ist als Liefertag erlaubt (UserAbo::allowedDeliveryDays),
Tage 29-31 liefern in kuerzeren Monaten am letzten Tag. Eine Stelle
AboHelper::dateForDayInMonth klammert; setNextDate, Erstausfuehrung,
Admin-Termin und Pause rechnen darueber, der Folgemonat immer aus dem
Liefertag (31.01 -> 28.02 -> 31.03). Liefertag-Aenderung gilt fuer den
laufenden Zyklus und nur nach vorn: ist der Tag im Referenzmonat vorbei,
wird abgelehnt, der Monat verschiebt sich nie (Rueckfrage R1).
Admin-Filter "naechste Ausfuehrung" als Datumsbereich. Prognose-Kacheln
bekommen die Kachel Monatsende, Team-Abos rechnen bis Monatsende.

A2: Sperrfristen Default 0, Setting 0 ist ausdruecklich 0 (fiel bisher auf
den Default zurueck). Bedingung Kalendertage <= Sperre, zentral in
AboHelper::isWithinLock: am Ausfuehrungstag ab 0:00 Uhr fixiert, Vortag bis
23:59 Uhr frei, fuer Liefertag, Produkte, Pause und Kuendigung (R2). Texte
mit _zero-Varianten ueber AboHelper::lockMessage.

Sprachdateien de/en/es/fr, neuer AboDeliveryDayTest, bestehende Tests
angepasst, Plan-Status mit Deploy-Schritt (Settings auf 0).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin 2026-09-16 11:28:55 +00:00
parent ec3ecadc5d
commit 66c6ae05fb
30 changed files with 638 additions and 185 deletions

View file

@ -32,7 +32,7 @@ return [
'abo_is_active' => 'Abo ist aktiv',
'abo_copy_active' => 'Wenn das Abonnement nicht aktiv ist, erfolgt keine automatische Ausführung.',
'abo_copy_next_date' => 'Der nächste Ausführungstermin kann frühesten auf den Folgetag festgelegt werden.',
'abo_copy_abo_interval' => 'Die Anpassung des Abonnement-Liefertags wirkt sich auf den kommenden Ausführungstermin aus, wenn das Abonnement aktiv ist.',
'abo_copy_abo_interval' => 'Der Liefertag gilt ab der kommenden Lieferung und lässt sich im laufenden Zyklus nur nach vorn verschieben. Bis 23:59 Uhr des Vortags änderbar, am Liefertag fixiert.',
'admin_abo_copy_next_date' => 'Admins können den nächsten Ausführungstermin direkt über Monat und Liefertag festlegen.',
'error_abo_interval' => 'Das Abo Interval nicht korrekt',
'error_abo_interval_in_the_past' => 'Das Abo wurde diesen Monat noch nicht ausgeführt. Eine Änderung auf einen vergangenen Tag würde den aktuellen Monat überspringen.',
@ -40,9 +40,9 @@ return [
'warning_next_date_soon_select' => 'Hinweis: Die nächste Abo-Ausführung ist bereits in :placeholder_days Tagen (:placeholder_date).',
'warning_next_date_info' => 'Die nächste Abo-Ausführung ist in :days Tagen am :date.',
'info_next_execution_select' => 'Nächste Ausführung: in :placeholder_days Tagen am :placeholder_date.',
'error_change_locked' => 'Änderungen sind nicht mehr möglich. Die nächste Ausführung ist in :days Tagen. Änderungen müssen mindestens :lock Tage vorher erfolgen.',
'error_change_locked' => 'Änderungen sind nicht mehr möglich: Die Lieferung am :date ist fixiert. Änderungen müssen mindestens :lock Tage vorher erfolgen.',
'error_abo_interval_too_soon' => 'Der gewählte Liefertag liegt nur :days Tage entfernt. Bitte wähle einen Liefertag, der mindestens :lock Tage in der Zukunft liegt.',
'error_cancel_locked' => 'Eine Kündigung ist nicht mehr möglich. Die nächste Ausführung ist in :days Tagen. Kündigungen müssen mindestens :lock Tage vorher erfolgen.',
'error_cancel_locked' => 'Eine Kündigung ist nicht mehr möglich: Die Lieferung am :date ist fixiert. Kündigungen müssen mindestens :lock Tage vorher erfolgen.',
'abo_copy_pause' => 'Verschiebt die nächste Ausführung um einen Monat nach hinten. Maximal 1x alle :months Monate möglich.',
'payline_abo_turnover' => 'Abo-Umsatz in der Payline',
'payline_abo_turnover_hint' => 'Soll = Abo-Punkte pro Zyklus aller aktiven Abos deiner Payline (Berater- und Kundenabos). Ist = im laufenden Monat bereits abgerechnete Abo-Punkte der Payline.',
@ -52,7 +52,7 @@ return [
'payline_abo_counts' => ':team_abos Teamabos + :customer_abos Kundenabos in der Payline = :total Abos gesamt',
'abo_order_short' => '(Abo)',
'points_order_legend' => 'Bestellungen: blau = eigene Bestellung · grau = Kundenbestellung · türkis mit „(Abo)" = Abo-Lieferung.',
'customer_abo_forecast_title' => 'Punkte aus meinen Kundenabos zum 5. / 10. / 20. / 25.',
'customer_abo_forecast_title' => 'Punkte aus meinen Kundenabos zum 5. / 10. / 20. / 25. / Monatsende',
'customer_abo_forecast_hint' => 'Taggenau: je Termin die bis dahin aus deinen Kundenabos abgerechneten Punkte plus die Lieferungen, die bis dahin noch anstehen. Ohne dein eigenes Abo und ohne Team.',
'customer_abo_forecast_split' => ':billed abgerechnet + :upcoming offen',
'customer_abo_points_recurring' => 'Abo-Punkte',
@ -69,15 +69,15 @@ return [
'payline_none' => 'Noch keine Payline vorhanden (kein Provisionslevel erreicht).',
'abo_points_per_cycle' => 'Punkte pro Lieferung (Bestand)',
'abo_points_billed' => 'abgerechnet (:month)',
'abo_points_expected' => 'bis zum :day. erwartet',
'abo_points_expected_hint' => 'Bereits abgerechnete Abo-Punkte plus die Punkte aller Abos dieser Ebene, deren Lieferung bis zum :day. des Monats noch ansteht.',
'abo_points_expected' => 'bis Monatsende erwartet',
'abo_points_expected_hint' => 'Bereits abgerechnete Abo-Punkte plus die Punkte aller Abos dieser Ebene, deren Lieferung in diesem Monat noch ansteht.',
'pause_abo' => '1 Monat pausieren',
'confirm_pause' => 'Möchtest du das Abo wirklich um einen Monat pausieren? Die nächste Lieferung verschiebt sich auf den Folgemonat.',
'pause_success' => 'Dein Abo wurde um einen Monat pausiert. Die nächste Ausführung ist am :date.',
'error_pause_interval' => 'Das Abo kann maximal 1x alle :months Monate pausiert werden. Die nächste Pause ist ab dem :date möglich.',
'error_pause_not_active' => 'Nur aktive Abos können pausiert werden.',
'info_pause_available_from' => 'Eine Pause ist maximal 1x alle :months Monate möglich — wieder ab dem :date.',
'error_pause_locked' => 'Das Abo kann nicht mehr pausiert werden. Die nächste Ausführung ist in :days Tagen. Pausieren muss mindestens :lock Tage vorher erfolgen.',
'error_pause_locked' => 'Das Abo kann nicht mehr pausiert werden: Die Lieferung am :date ist fixiert. Pausieren muss mindestens :lock Tage vorher erfolgen.',
'error_next_date' => 'Das Datum für die nächste Ausführung nicht korrekt',
'checkout_mail_abo_hl' => 'Dein Abo / regelmäßige Lieferung.',
'checkout_mail_abo_start' => 'Dein Abo wurde erfolgreich mit folgenden Einstellungen angelegt:',
@ -335,7 +335,7 @@ return [
'pause_cancel_title' => 'Abo pausieren oder kündigen',
'pause_cancel_intro' => 'Hier kannst du dein Abo für einen Monat aussetzen oder dauerhaft beenden. Beides ist ab der :min. Lieferung möglich.',
'pause_cancel_progress' => ':count von :min Lieferungen ausgeführt',
'pause_cancel_locked_hint' => 'Die nächste Lieferung am :date wird bereits vorbereitet (Sperre :lock Tage vorher). Pausieren oder Kündigen ist erst nach dieser Lieferung wieder möglich.',
'pause_cancel_locked_hint' => 'Die Lieferung am :date ist fixiert (Sperre :lock Tage vorher). Pausieren oder Kündigen ist erst nach dieser Lieferung wieder möglich.',
'cancel_short_copy' => 'Beendet das Abo dauerhaft. Ein neues Abo beginnt wieder mit :min Pflichtlieferungen.',
'cancel_in_section_hint' => 'Die Kündigung findest du unten auf der Abo-Seite im Abschnitt „Abo pausieren oder kündigen“.',
'cancel_modal_title' => 'Abo wirklich kündigen?',
@ -376,4 +376,14 @@ return [
'actor_by_admin' => 'vom Admin',
'actor_by_system' => 'vom System',
'filter_state' => 'Zustand',
// Freier Liefertag 1-31 und Sperre bis zum Vortag (Tickets A1/A2)
'of_month_short_hint' => '(in kürzeren Monaten der letzte Tag)',
'error_change_locked_zero' => 'Änderungen sind nicht mehr möglich: Die Lieferung am :date wird heute ausgeführt. Nach der Lieferung kannst du den Liefertag für den nächsten Monat ändern.',
'error_abo_interval_passed' => 'Der :day. ist in diesem Monat schon vorbei. Die nächste Lieferung bleibt am :next – danach kannst du den Liefertag für den Folgemonat neu festlegen.',
'error_cancel_locked_zero' => 'Eine Kündigung ist nicht mehr möglich: Die Lieferung am :date wird heute ausgeführt. Nach der Lieferung kannst du kündigen.',
'error_pause_locked_zero' => 'Das Abo kann nicht mehr pausiert werden: Die Lieferung am :date wird heute ausgeführt. Nach der Lieferung kannst du pausieren.',
'pause_cancel_locked_hint_zero' => 'Die Lieferung am :date wird heute ausgeführt. Pausieren oder Kündigen ist danach wieder möglich – bis 23:59 Uhr des Vortags einer Lieferung.',
'filter_next_from' => 'von',
'filter_next_to' => 'bis',
];

View file

@ -50,7 +50,7 @@ return [
'your_shop' => 'Dein Shop',
'commission_today' => 'Provision (Stand heute)',
'commission_unavailable' => 'Die Provisionsberechnung ist gerade nicht verfuegbar. Der Wert wird nachgetragen, sobald sie wieder laeuft.',
'payline_forecast_title' => 'Payline-Prognose zum 5. / 10. / 20. / 25.',
'payline_forecast_title' => 'Payline-Prognose zum 5. / 10. / 20. / 25. / Monatsende',
'payline_forecast_basis' => 'Basis: Paylinepunkte + persönliches Volumen',
'payline_forecast_hint' => 'Basis: aktueller Kundenumsatz + Teamumsatz (Payline). Dazu kommen kumuliert die bis zum jeweiligen Termin noch anstehenden Abo-Punkte deiner Payline (inkl. deiner eigenen Abos und Kundenabos). Prognose: Pausen, Kündigungen oder fehlgeschlagene Zahlungen können den Wert verändern.',
'forecast_day' => 'Prognose zum :date',
@ -106,4 +106,6 @@ return [
'top_results_unit_points' => 'Punkte',
'top_results_unit_partners' => 'Neupartner',
'top_results_unit_abos' => 'Abos',
'forecast_month_end' => 'Prognose zum Monatsende (:date)',
];