diff --git a/superfaktura/invoice.py b/superfaktura/invoice.py new file mode 100644 index 0000000..2110c69 --- /dev/null +++ b/superfaktura/invoice.py @@ -0,0 +1,139 @@ +from dataclasses import dataclass, asdict +from pprint import pprint +from typing import Optional, List +import json + +from superfaktura.bank_account import BankAccount +from superfaktura.client_contacts import ClientContactModel +from superfaktura.enumerations.currency import Currencies +from superfaktura.superfaktura_api import SuperFakturaAPI +from utils.data_types import Date, DateEncoder + + +@dataclass +class InvoiceModel: + add_rounding_item: Optional[int] = 0 + already_paid: Optional[int] = None + bank_accounts: Optional[List[dict]] = None + comment: Optional[str] = None + constant: Optional[str] = None + created: Optional[Date] = None + delivery: Optional[Date] = None + delivery_type: Optional[str] = None + deposit: Optional[float] = None + discount: Optional[float] = 0 + discount_total: Optional[float] = None + due: Optional[Date] = None + estimate_id: Optional[int] = None + header_comment: Optional[str] = None + internal_comment: Optional[str] = None + invoice_currency: Optional[str] = None + invoice_no_formatted: Optional[str] = None + issued_by: Optional[str] = None + issued_by_email: Optional[str] = None + issued_by_phone: Optional[str] = None + issued_by_web: Optional[str] = None + logo_id: Optional[int] = None + mark_sent: Optional[int] = None + mark_sent_message: Optional[str] = None + mark_sent_subject: Optional[str] = None + name: Optional[str] = None + order_no: Optional[str] = None + parent_id: Optional[int] = None + paydate: Optional[Date] = None + payment_type: Optional[str] = None + proforma_id: Optional[str] = None + rounding: Optional[str] = None + sequence_id: Optional[int] = None + specific: Optional[str] = None + tax_document: Optional[int] = None + type: Optional[str] = None + variable: Optional[str] = None + vat_transfer: Optional[int] = None + + def as_dict(self) -> dict: + data = asdict(self) + for key in list(data.keys()): + if data[key] is None: + del data[key] + return data + + def to_dict(self) -> dict: + """ + Converts the Record object to a dictionary for JSON serialization. + """ + return {"due": self.due.to_dict() if self.due else None} + + +@dataclass +class InvoiceItem: + name: str + unit_price: float + description: Optional[str] = None + discount: Optional[float] = 0 + discount_description: Optional[str] = None + load_data_from_stock: int = 0 + quantity: Optional[float] = 1 + sku: Optional[str] = None + stock_item_id: Optional[int] = None + tax: Optional[float] = None + unit: Optional[str] = None + use_document_currency: Optional[int] = 0 + + def as_dict(self) -> dict: + data = asdict(self) + for key in list(data.keys()): + if data[key] is None: + del data[key] + return data + + +class Invoice(SuperFakturaAPI): + def __init__(self): + super().__init__() + + def add( + self, + invoice: InvoiceModel, + items: List[InvoiceItem], + contact: ClientContactModel, + ): + data = { + "Invoice": invoice.as_dict(), + "InvoiceItem": [item.as_dict() for item in items], + "Client": contact.as_dict(), + } + url = "invoices/create" + resp = self.post(endpoint=url, data=json.dumps(data, cls=DateEncoder)) + return resp + + +if __name__ == "__main__": + invoice = Invoice() + bank = BankAccount() + invoice.add( + invoice=InvoiceModel( + type="proforma", + name="Invoice 3", + due=Date("2025-02-01"), + invoice_currency=Currencies.CZK, + header_comment="We invoice you for services", + bank_accounts=[bank.default().as_dict()], + ), + items=[ + InvoiceItem(name="Services", unit_price=100, quantity=1, unit="ks", tax=21), + InvoiceItem(name="SIM card", unit_price=50, quantity=1, tax=21, unit="ks"), + InvoiceItem( + name="SIM card 2", unit_price=75, quantity=1, tax=21, unit="ks" + ), + ], + contact=ClientContactModel( + name="Richard Kubíček", + email="kubicekr@eledio.com", + phone="+420 123 456 789", + address="Jaroslava Foglara 861/1", + ico="123", + update=True, + country_id=57, + ), + )