# 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"