This commit is contained in:
2026-05-20 00:09:28 +02:00
parent 968bf7d102
commit 51b5ddc6f2
695 changed files with 999722 additions and 270 deletions

View File

@@ -0,0 +1,116 @@
# 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