Files
superfaktura-client/superfaktura/invoice.py
2025-02-08 14:31:40 +01:00

256 lines
8.1 KiB
Python

"""
Invoice Module.
This module provides classes and functions for working with invoices in the SuperFaktura API.
It allows for retrieving, creating, updating, and deleting invoices.
Classes:
- InvoiceModel: Dataclass representing an invoice.
- InvoiceItem: Dataclass representing an invoice item.
- Invoice: Class for interacting with invoices.
Exceptions:
- NoDefaultBankAccountException: Exception for when no default bank account is found.
Functions:
- (none)
Usage:
import superfaktura.invoice
# Create an instance of Invoice
invoice = superfaktura.invoice.Invoice()
# Create an invoice
invoice.add(
invoice=superfaktura.invoice.InvoiceModel(
type=superfaktura.invoice.InvoiceType.PROFORMA,
name="Invoice 3",
due=superfaktura.invoice.Date("2025-02-01"),
invoice_currency=superfaktura.invoice.Currencies.CZK,
header_comment="We invoice you for services",
bank_accounts=[bank.default().as_dict()],
),
items=[
superfaktura.invoice.InvoiceItem(name="Services", unit_price=100, quantity=1,
unit="ks", tax=21),
superfaktura.invoice.InvoiceItem(name="SIM card", unit_price=50, quantity=1,
tax=21, unit="ks"),
superfaktura.invoice.InvoiceItem(
name="SIM card 2", unit_price=75, quantity=1, tax=21, unit="ks"
),
],
contact=superfaktura.client_contacts.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,
),
)
"""
from dataclasses import dataclass, asdict
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 superfaktura.utils.data_types import Date, DateEncoder
@dataclass
class InvoiceModel:
"""This dataclass represents an invoice in the SuperFaktura API."""
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:
"""Returns a dictionary representation of the InvoiceModel."""
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:
"""This dataclass represents an invoice item in the SuperFaktura API."""
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:
"""Returns a dictionary representation of the InvoiceItem."""
data = asdict(self)
for key in list(data.keys()):
if data[key] is None:
del data[key]
return data
class InvoiceType:
""" "
Invoice Type Enumeration.
This enumeration represents the different types of invoices that can be created.
Usage:
invoice_type = InvoiceType.PROFORMA
"""
PROFORMA = "proforma"
INVOICE = "regular"
class Invoice(SuperFakturaAPI):
"""
Invoice Class.
This class provides methods for interacting with invoices in the SuperFaktura API.
It allows for retrieving, creating, updating, and deleting invoices.
Methods:
- add: Creates a new invoice.
- get: Retrieves an invoice by ID.
- list: Retrieves a list of invoices.
- update: Updates an existing invoice.
Usage:
invoice = Invoice()
invoice.add(
invoice=InvoiceModel(
type=InvoiceType.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,
),
)
"""
def __init__(self):
super().__init__()
def add(
self,
invoice_model: InvoiceModel,
items: List[InvoiceItem],
contact: ClientContactModel,
):
"""Creates a new invoice."""
data = {
"Invoice": invoice_model.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_model=InvoiceModel(
type=InvoiceType.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,
),
)