fix: Include period-based lines and normalize product grouping

- Include lines with period fields even without keywords
- Normalize product names to group similar lines
- Improves monthly Hosting - AR2 visibility
This commit is contained in:
Christian 2026-01-27 01:19:08 +01:00
parent 9c6834b9f6
commit 501032efcd

View File

@ -191,20 +191,24 @@ class SubscriptionMatrixService:
product_number = line.get('product', {}).get('productNumber')
product_name = line.get('product', {}).get('name') or line.get('description')
line_description = (line.get('description') or product_name or "").lower()
# Only include lines that indicate a period or subscription
line_period = self._extract_period_from_text(line_description) or invoice_period
has_period = bool(line.get('period', {}).get('from') if line.get('period') else None) or bool(line_period)
# Only include lines that indicate a period or subscription or explicit period fields
if (
"periode" not in line_description
and "abonnement" not in line_description
and "periode" not in invoice_text
and "abonnement" not in invoice_text
and not has_period
):
continue
line_period = self._extract_period_from_text(line_description) or invoice_period
if not product_number and not product_name:
logger.debug(f"Skipping line without product number: {line}")
continue
product_key = product_number or (product_name or "").strip().lower()
product_key = product_number or self._normalize_product_key(product_name or "")
# Cache product name
if product_key not in product_names:
@ -355,6 +359,19 @@ class SubscriptionMatrixService:
next_month = dt.replace(day=28) + timedelta(days=4)
return next_month - timedelta(days=next_month.day)
@staticmethod
def _normalize_product_key(name: str) -> str:
"""Normalize product names to keep similar lines on the same row."""
base = (name or "").lower().strip()
# Remove period phrases like "periode" and trailing date ranges
for token in ["periode", "abonnement"]:
if token in base:
base = base.split(token)[0].strip()
# Collapse multiple spaces
while " " in base:
base = base.replace(" ", " ")
return base or name.lower().strip()
@staticmethod
def _extract_period_from_text(text: str) -> Optional[datetime]:
"""Extract month/year from invoice title/notes text (e.g., 'Periode May 2025')."""