feat: Include invoice title keywords in subscription matrix filter

- Match 'periode'/'abonnement' in invoice notes/title fields
- Allows period-only titles to include line items
- Keeps line-level keyword filtering
This commit is contained in:
Christian 2026-01-27 00:34:44 +01:00
parent 8ec457bba1
commit 39b49d4d54

View File

@ -149,30 +149,9 @@ class SubscriptionMatrixService:
product_matrix = defaultdict(dict)
product_names = {} # Cache product names
# Initialize all products with empty cells for all months
# Initialize products only if they have data within the selected month range
try:
for invoice in invoices:
lines = invoice.get('lines', [])
for line in lines:
product_number = line.get('product', {}).get('productNumber')
product_name = line.get('product', {}).get('name') or line.get('description')
if product_number and product_number not in product_names:
product_names[product_number] = product_name or f"Product {product_number}"
# Initialize all products with all months (empty)
for product_number in product_names.keys():
for year_month in all_months:
product_matrix[product_number][year_month] = {
"amount": 0.0,
"status": "missing",
"invoice_number": None,
"period_from": None,
"period_to": None,
"period_label": None
}
# Now fill in data from invoices
# Fill in data from invoices, but only for months within range
for invoice in invoices:
invoice_number = invoice.get('bookedInvoiceNumber') or invoice.get('draftInvoiceNumber')
# Determine status based on invoice type/endpoint it came from
@ -185,12 +164,35 @@ class SubscriptionMatrixService:
elif invoice.get('draftInvoiceNumber'):
invoice_status = 'draft'
invoice_date = invoice.get('date')
# Build invoice-level text (title/notes) for keyword matching
invoice_text_parts = []
notes = invoice.get('notes')
if isinstance(notes, dict):
for key in ["heading", "textLine1", "textLine2", "textLine3", "textLine4", "textLine5"]:
val = notes.get(key)
if val:
invoice_text_parts.append(str(val))
elif notes:
invoice_text_parts.append(str(notes))
other_ref = invoice.get('otherReference') or invoice.get('orderNumberDb')
if other_ref:
invoice_text_parts.append(str(other_ref))
invoice_text = " ".join(invoice_text_parts).lower()
# Process invoice lines
lines = invoice.get('lines', [])
for line in lines:
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
if (
"periode" not in line_description
and "abonnement" not in line_description
and "periode" not in invoice_text
and "abonnement" not in invoice_text
):
continue
if not product_number:
logger.debug(f"Skipping line without product number: {line}")
@ -236,19 +238,33 @@ class SubscriptionMatrixService:
# Determine month key (use first month if multi-month)
year_month = period_from.strftime('%Y-%m')
if year_month not in all_months:
# Skip lines outside the displayed month range
continue
# Calculate period label
period_label = self._format_period_label(period_from, period_to)
# Update cell (it should already exist from initialization)
if year_month in product_matrix.get(product_number, {}):
cell = product_matrix[product_number][year_month]
cell["amount"] = amount # Take last amount (or sum if multiple?)
cell["status"] = self._determine_status(invoice_status)
cell["invoice_number"] = invoice_number
cell["period_from"] = period_from.isoformat().split('T')[0]
cell["period_to"] = period_to.isoformat().split('T')[0]
cell["period_label"] = period_label
# Initialize product if first time within range
if product_number not in product_matrix:
for month_key in all_months:
product_matrix[product_number][month_key] = {
"amount": 0.0,
"status": "missing",
"invoice_number": None,
"period_from": None,
"period_to": None,
"period_label": None
}
# Update cell
cell = product_matrix[product_number][year_month]
cell["amount"] = amount # Take last amount (or sum if multiple?)
cell["status"] = self._determine_status(invoice_status)
cell["invoice_number"] = invoice_number
cell["period_from"] = period_from.isoformat().split('T')[0]
cell["period_to"] = period_to.isoformat().split('T')[0]
cell["period_label"] = period_label
except Exception as e:
logger.error(f"❌ Error aggregating data: {e}")