mirror of
https://github.com/Kizuren/LidlConnect.py.git
synced 2025-12-23 15:53:52 +01:00
173 lines
No EOL
6.8 KiB
Python
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 |