from __future__ import annotations from django.db import models from django.utils import timezone # Import domain models with light coupling from orgs.models import Organization from recycle_core.models import Customer, PickupOrder, Material class TimestampedModel(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: abstract = True class Invoice(TimestampedModel): STATUS_DRAFT = "draft" STATUS_ISSUED = "issued" STATUS_PAID = "paid" STATUS_VOID = "void" STATUS_CHOICES = ( (STATUS_DRAFT, "Draft"), (STATUS_ISSUED, "Issued"), (STATUS_PAID, "Paid"), (STATUS_VOID, "Void"), ) organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="invoices") customer = models.ForeignKey(Customer, on_delete=models.PROTECT, related_name="invoices") pickup = models.ForeignKey(PickupOrder, on_delete=models.SET_NULL, null=True, blank=True, related_name="invoices") currency_code = models.CharField(max_length=8, default="USD") total_amount = models.DecimalField(max_digits=14, decimal_places=2, default=0) status = models.CharField(max_length=8, choices=STATUS_CHOICES, default=STATUS_DRAFT, db_index=True) issued_at = models.DateTimeField(null=True, blank=True) due_at = models.DateTimeField(null=True, blank=True) class InvoiceLine(TimestampedModel): invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name="lines") description = models.CharField(max_length=255) material = models.ForeignKey(Material, on_delete=models.SET_NULL, null=True, blank=True) quantity = models.DecimalField(max_digits=12, decimal_places=3) unit = models.CharField(max_length=8, choices=Material.UNIT_CHOICES, default=Material.UNIT_KG) unit_price = models.DecimalField(max_digits=12, decimal_places=2) line_total = models.DecimalField(max_digits=14, decimal_places=2) class Payment(TimestampedModel): invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name="payments") amount = models.DecimalField(max_digits=14, decimal_places=2) currency_code = models.CharField(max_length=8, default="USD") received_at = models.DateTimeField(default=timezone.now) reference = models.CharField(max_length=128, blank=True) class Payout(TimestampedModel): organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="payouts") customer = models.ForeignKey(Customer, on_delete=models.PROTECT, related_name="payouts") pickup = models.ForeignKey(PickupOrder, on_delete=models.SET_NULL, null=True, blank=True, related_name="payouts") amount = models.DecimalField(max_digits=14, decimal_places=2) currency_code = models.CharField(max_length=8, default="USD") paid_at = models.DateTimeField(default=timezone.now) reference = models.CharField(max_length=128, blank=True)