from django.db import models from django.core.validators import MinValueValidator from django.utils.translation import gettext_lazy as _ from decimal import Decimal from inventory.models import Supplier # Supplier model removed - using inventory.models.Supplier instead class PurchaseOrder(models.Model): """Purchase order model""" ORDER_STATUS = [ ('draft', 'Draft'), ('sent', 'Sent to Supplier'), ('confirmed', 'Confirmed by Supplier'), ('received', 'Received'), ('cancelled', 'Cancelled'), ] order_number = models.CharField(max_length=50, unique=True, help_text='Unique purchase order number') supplier = models.ForeignKey('inventory.Supplier', on_delete=models.CASCADE, related_name='purchase_orders') date = models.DateField() expected_delivery_date = models.DateField(blank=True, null=True) status = models.CharField(max_length=20, choices=ORDER_STATUS, default='draft') # Financial information subtotal = models.DecimalField( max_digits=12, decimal_places=2, default=0, validators=[MinValueValidator(Decimal('0'))] ) tax_amount = models.DecimalField( max_digits=12, decimal_places=2, default=0, validators=[MinValueValidator(Decimal('0'))] ) shipping_cost = models.DecimalField( max_digits=12, decimal_places=2, default=0, validators=[MinValueValidator(Decimal('0'))] ) total_amount = models.DecimalField( max_digits=12, decimal_places=2, default=0, validators=[MinValueValidator(Decimal('0'))] ) # Additional information notes = models.TextField(blank=True) terms_conditions = models.TextField(blank=True) # User tracking created_by = models.ForeignKey('users.CustomUser', on_delete=models.SET_NULL, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ['-date', '-created_at'] verbose_name = _('Purchase Order') verbose_name_plural = _('Purchase Orders') def __str__(self): return f"PO-{self.order_number} - {self.supplier.name}" def save(self, *args, **kwargs): """Override save to calculate total amount""" self.total_amount = self.subtotal + self.tax_amount + self.shipping_cost super().save(*args, **kwargs) def get_item_count(self): """Get total number of items in this purchase order""" return self.items.count() def is_overdue(self): """Check if delivery is overdue""" if self.expected_delivery_date and self.status not in ['received', 'cancelled']: from django.utils import timezone return timezone.now().date() > self.expected_delivery_date return False class PurchaseOrderItem(models.Model): """Individual items in purchase orders""" purchase_order = models.ForeignKey(PurchaseOrder, on_delete=models.CASCADE, related_name='items') product = models.ForeignKey('inventory.Product', on_delete=models.CASCADE, related_name='purchase_order_items') quantity = models.DecimalField( max_digits=10, decimal_places=2, validators=[MinValueValidator(Decimal('0.01'))] ) unit_price = models.DecimalField( max_digits=10, decimal_places=2, validators=[MinValueValidator(Decimal('0'))] ) total_price = models.DecimalField( max_digits=12, decimal_places=2, validators=[MinValueValidator(Decimal('0'))] ) # Additional information description = models.CharField(max_length=200, blank=True) notes = models.TextField(blank=True) class Meta: verbose_name = _('Purchase Order Item') verbose_name_plural = _('Purchase Order Items') def __str__(self): return f"{self.purchase_order.order_number} - {self.product.name} ({self.quantity})" def save(self, *args, **kwargs): """Override save to calculate total price""" self.total_price = self.quantity * self.unit_price super().save(*args, **kwargs) # Update purchase order subtotal self.purchase_order.subtotal = self.purchase_order.items.aggregate( total=models.Sum('total_price') )['total'] or Decimal('0') self.purchase_order.save() class PurchaseReceipt(models.Model): """Receipt for received purchase orders""" receipt_number = models.CharField(max_length=50, unique=True) purchase_order = models.ForeignKey(PurchaseOrder, on_delete=models.CASCADE, related_name='receipts') receipt_date = models.DateField() # Receipt details notes = models.TextField(blank=True) received_by = models.ForeignKey('users.CustomUser', on_delete=models.SET_NULL, null=True) # Timestamps created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['-receipt_date'] verbose_name = _('Purchase Receipt') verbose_name_plural = _('Purchase Receipts') def __str__(self): return f"Receipt-{self.receipt_number} for PO-{self.purchase_order.order_number}"