LidlConnect.py/LidlConnect/api/invoices.py
2025-05-24 01:03:16 +02:00

173 lines
No EOL
6.8 KiB
Python

"""Invoices-related API functionality for Lidl Connect."""
from typing import Dict, Any, List, Optional
from datetime import datetime
from ..helpers import ttl_cache
class InvoicesMixin:
"""Invoices-related API methods for Lidl Connect API."""
INVOICES_URL = "https://selfcare.lidl-connect.at/customer/invoices/invoice-list"
VOUCHER_URL = "https://selfcare.lidl-connect.at/customer/invoices/consumed-vouchers"
@ttl_cache(30)
def get_invoices(self) -> List[Dict[str, Any]]:
"""
Get list of invoices for the current account.
Returns:
List[Dict]: List of invoice objects with transaction details
"""
if not self.logged_in or not self.csrf_token:
raise ValueError("Not logged in or missing CSRF token")
headers = {
"Accept": "application/json",
"Content-Type": "application/json;charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Origin": "https://selfcare.lidl-connect.at",
"Referer": self.DASHBOARD_URL,
"X-CSRF-TOKEN": self.csrf_token,
"X-SELF-CARE": "1",
"ocrAvailable": "0",
}
payload = {"accountId": self.endpoint_id, "userId": self.user_id, "endpointId": self.endpoint_id}
r = self.session.post(self.INVOICES_URL, headers=headers, json=payload)
if r.status_code != 200:
if r.status_code == 422 and r.text == '[]':
return []
raise ValueError(f"Invoices request failed: {r.status_code} {r.text!r}")
return r.json()
@ttl_cache(30)
def get_vouchers(self) -> List[Dict[str, Any]]:
"""
Get list of consumed vouchers for the current account.
Returns:
List[Dict]: List of voucher objects with transaction details
"""
if not self.logged_in or not self.csrf_token:
raise ValueError("Not logged in or missing CSRF token")
headers = {
"Accept": "application/json",
"Content-Type": "application/json;charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Origin": "https://selfcare.lidl-connect.at",
"Referer": self.DASHBOARD_URL,
"X-CSRF-TOKEN": self.csrf_token,
"X-SELF-CARE": "1",
"ocrAvailable": "0",
}
payload = {"userId": self.user_id, "endpointId": self.endpoint_id}
r = self.session.post(self.VOUCHER_URL, headers=headers, json=payload)
if r.status_code != 200:
if r.status_code == 422 and r.text == '[]':
return []
raise ValueError(f"Vouchers request failed: {r.status_code} {r.text!r}")
return r.json()
def print_invoices(self) -> None:
"""
Pretty-print invoice and voucher history.
"""
try:
invoices = self.get_invoices()
vouchers = self.get_vouchers()
if not invoices and not vouchers:
print("\nNo payment history available")
return
if invoices:
print(f"\n{'=' * 20} INVOICE HISTORY {'=' * 20}")
for invoice in invoices:
try:
posting_date = datetime.fromisoformat(invoice.get("postingDate").replace("Z", "+00:00"))
date_str = posting_date.strftime("%d %b %Y, %H:%M")
except (ValueError, AttributeError):
date_str = invoice.get("postingDate", "Unknown date")
payment_type = invoice.get("type", "").capitalize()
provider = invoice.get("provider", "")
channel = invoice.get("channel", "").replace("_", " ").title()
payment_method = f"{payment_type} via {provider} ({channel})"
print(f"\n{'-' * 60}")
print(f"Transaction ID: {invoice.get('id')}")
print(f"Date: {date_str}")
print(f"Amount: €{invoice.get('amount', 0):.2f}")
print(f"Payment Method: {payment_method}")
if vouchers:
print(f"\n{'=' * 20} VOUCHER HISTORY {'=' * 20}")
for voucher in vouchers:
try:
posting_date = datetime.fromisoformat(voucher.get("consumedDate").replace("Z", "+00:00"))
date_str = posting_date.strftime("%d %b %Y, %H:%M")
except (ValueError, AttributeError):
date_str = voucher.get("consumedDate", "Unknown date")
print(f"\n{'-' * 60}")
print(f"Voucher ID: {voucher.get('id')}")
print(f"Serial: {voucher.get('serial')}")
print(f"Value: €{voucher.get('balanceAdvice', 0):.2f}")
print(f"Consumed Date: {date_str}")
except Exception as e:
print(f"\nError fetching payment history: {str(e)}")
import traceback
traceback.print_exc()
def get_total_spent(self) -> float:
"""
Calculate the total amount spent across all invoices and vouchers.
Returns:
float: Total amount in euros
"""
total = 0.0
try:
invoices = self.get_invoices()
vouchers = self.get_vouchers()
total += sum(invoice.get("amount", 0) for invoice in invoices)
total += sum(voucher.get("balanceAdvice", 0) for voucher in vouchers)
except Exception:
pass
return total
@property
def last_payment_date(self) -> Optional[str]:
"""
Get the date of the most recent payment from either invoices or vouchers.
Returns:
str: ISO formatted date string or None if no payments
"""
try:
all_dates = []
invoices = self.get_invoices()
invoice_dates = [(invoice.get("postingDate"), invoice.get("amount"))
for invoice in invoices if invoice.get("postingDate")]
vouchers = self.get_vouchers()
voucher_dates = [(voucher.get("consumedDate"), voucher.get("balanceAdvice"))
for voucher in vouchers if voucher.get("consumedDate")]
all_dates = invoice_dates + voucher_dates
if not all_dates:
return None
all_dates.sort(key=lambda x: x[0], reverse=True)
return all_dates[0][0]
except Exception:
return None