Files
aza/AzA march 2026 - Kopie (27)/wc_period_payload.py
2026-05-20 00:09:28 +02:00

117 lines
3.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# wc_period_payload.py Woo Bridge: Periodenfelder aus Provision/Sync-Payload ableiten
# (ohne /wc/v3/subscriptions REST).
from __future__ import annotations
from typing import Any, Optional, Tuple
from aza_wc_period_sync import _parse_wc_datetime, _subtract_billing_period
# Plausible Unix range: 2000-01-01 … 2100-01-01 UTC
_TS_MIN = 946684800
_TS_MAX = 4102444800
def _normalize_int_ts(v: Optional[int]) -> Optional[int]:
if v is None:
return None
try:
x = int(v)
except (TypeError, ValueError):
return None
if x > 10**12: # ms
x //= 1000
if _TS_MIN <= x <= _TS_MAX:
return x
return None
def coerce_next_payment_unix(value: Any) -> Optional[int]:
"""Unix-Sekunden aus next_payment (int, Ziffernstring oder ISO-Datum)."""
if value is None:
return None
if isinstance(value, bool):
return None
if isinstance(value, int):
return _normalize_int_ts(value)
if isinstance(value, float):
return _normalize_int_ts(int(value))
s = str(value).strip()
if not s:
return None
if s.isdigit():
return _normalize_int_ts(int(s))
parsed = _parse_wc_datetime(s)
return _normalize_int_ts(parsed) if parsed is not None else None
def _normalize_billing_period_word(raw: Optional[str]) -> str:
"""
WooCommerce REST liefert oft 'month'/'day'/…
WP Desk Flexible Subscriptions API nutzt Einzelbuchstaben: D, W, M, Y.
"""
if raw is None or (isinstance(raw, str) and not str(raw).strip()):
return "month"
s = str(raw).strip().lower()
if len(s) == 1:
return {"d": "day", "w": "week", "m": "month", "y": "year"}.get(s, s)
return s
def resolve_wc_period_fields(
*,
current_period_start: Optional[int] = None,
current_period_end: Optional[int] = None,
next_payment_date: Any = None,
billing_period: Optional[str] = None,
billing_interval: Optional[int] = None,
) -> Tuple[Optional[int], Optional[int]]:
"""
Liefert (period_start, period_end) oder (None, None) wenn nicht ableitbar/ungültig.
Priorität:
1) Beide current_period_* gesetzt und start < end
2) next_payment_date + billing_period/billing_interval → Ende = Zahlungszeitpunkt,
Start = Ende Abrechnungsintervall (wie Woo-REST-Logik)
"""
cs = _normalize_int_ts(current_period_start)
ce = _normalize_int_ts(current_period_end)
if cs is not None and ce is not None:
if cs < ce:
return cs, ce
return None, None
# Nur period_end gesetzt: Start aus Abrechnungsintervall rückwärts (Default month/1)
if ce is not None and cs is None:
bp = _normalize_billing_period_word(billing_period)
try:
bi = int(billing_interval) if billing_interval is not None else 1
except (TypeError, ValueError):
bi = 1
if bi < 1:
bi = 1
ps = _subtract_billing_period(ce, bp, bi)
if ps >= ce:
ps = ce - 86400
if ps < ce and _TS_MIN <= ps <= _TS_MAX:
return ps, ce
return None, None
pe = coerce_next_payment_unix(next_payment_date)
if pe is not None and cs is None and ce is None:
bp = _normalize_billing_period_word(billing_period)
try:
bi = int(billing_interval) if billing_interval is not None else 1
except (TypeError, ValueError):
bi = 1
if bi < 1:
bi = 1
ps = _subtract_billing_period(pe, bp, bi)
if ps >= pe:
ps = pe - 86400
if ps < pe and _TS_MIN <= ps <= _TS_MAX:
return ps, pe
return None, None
# Nur eines der Felder nicht raten
return None, None