Files
mariomitte 5d39e048ba
Some checks failed
ERP CI Pipeline / test (push) Has been cancelled
prvi kod za live uporabu
2026-07-09 21:21:17 +02:00

123 lines
3.7 KiB
Python

# backend/modules/invoicing/models.py
import datetime
from django.utils import timezone
from core.base_models import BaseModel
from django.db import models, transaction
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from .utils import generate_invoice_number
class Invoice(BaseModel):
# Identifikacija (UUID i created_at dolaze iz BaseModel)
invoice_number = models.CharField(max_length=50, unique=True, verbose_name=_("Broj fakture"))
# Relacije
creator = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
related_name="invoices"
)
client = models.ForeignKey(
'crm.Client',
on_delete=models.PROTECT,
verbose_name=_("Klijent")
)
# Financijski detalji
amount = models.DecimalField(max_digits=12, decimal_places=2, verbose_name=_("Iznos"))
currency = models.CharField(max_length=3, default="EUR")
tax_rate = models.DecimalField(max_digits=4, decimal_places=2, default=25.00)
# Statusi
status = models.CharField(
max_length=20,
choices=[
('draft', 'Nacrt'),
('sent', 'Poslano'),
('paid', 'Plaćeno'),
('cancelled', 'Stornirano')
],
default='draft'
)
due_date = models.DateField(verbose_name=_("Rok plaćanja"))
class Meta:
# Nasljeđujemo ordering iz BaseModel, ali ga možemo override-ati
verbose_name = _("Faktura")
verbose_name_plural = _("Fakture")
def __str__(self):
return f"{self.invoice_number} - {self.client}"
def get_total_amount(self):
return self.items.aggregate(total=models.Sum(models.F('quantity') * models.F('unit_price')))['total'] or 0
def save(self, *args, **kwargs):
if not self.invoice_number:
self.invoice_number = generate_invoice_number()
super().save(*args, **kwargs)
class InvoiceItem(BaseModel):
# Relacija prema fakturi
invoice = models.ForeignKey(
Invoice,
on_delete=models.CASCADE,
related_name='items',
verbose_name=_("Faktura")
)
# Detalji stavke
description = models.CharField(
max_length=255,
verbose_name=_("Opis stavke")
)
quantity = models.DecimalField(
max_digits=10,
decimal_places=2,
default=1,
verbose_name=_("Količina")
)
unit_price = models.DecimalField(
max_digits=12,
decimal_places=2,
verbose_name=_("Cijena po jedinici")
)
# Automatski izračun (property ne zauzima prostor u bazi)
@property
def total(self):
return self.quantity * self.unit_price
class Meta:
verbose_name = _("Stavka fakture")
verbose_name_plural = _("Stavke fakture")
def __str__(self):
# Koristimo prednost BaseModel __str__ metode
return f"{self.description} ({self.quantity} x {self.unit_price})"
class InvoiceTransaction(BaseModel):
# Polja specifična za fakturiranje
invoice = models.ForeignKey(
Invoice,
on_delete=models.PROTECT,
related_name='transactions',
verbose_name=_("Faktura")
)
work_order = models.ForeignKey(
'fleet.WorkOrder',
on_delete=models.SET_NULL,
related_name='invoice_transactions',
null=True,
blank=True,
verbose_name=_("Putni nalog"),
)
invoice_number = models.CharField(max_length=50)
amount = models.DecimalField(max_digits=10, decimal_places=2)
payment_date = models.DateField(default=timezone.now)
class Meta:
verbose_name = "Financijski zapis"
verbose_name_plural = "Financijski zapisi"