from django.db import models class Customer(models.Model): code = models.CharField(max_length=50, unique=True) name = models.CharField(max_length=200) contact_person = models.CharField(max_length=100, blank=True) email = models.EmailField(blank=True) phone = models.CharField(max_length=20, blank=True) address = models.TextField(blank=True) tax_id = models.CharField(max_length=50, blank=True) payment_terms = models.CharField(max_length=100, blank=True) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.name class SalesOrder(models.Model): STATUS_CHOICES = [ ('processing', 'Processing'), ('completed', 'Completed'), ('cancelled', 'Cancelled'), ] so_number = models.CharField(max_length=50, unique=True, blank=True) customer = models.ForeignKey(Customer, on_delete=models.CASCADE) order_date = models.DateField() expected_delivery_date = models.DateField(null=True, blank=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='processing') subtotal = models.DecimalField(max_digits=12, decimal_places=2, default=0) tax_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0) total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0) notes = models.TextField(blank=True) created_by = models.ForeignKey('accounts.User', on_delete=models.SET_NULL, null=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def save(self, *args, **kwargs): if not self.so_number: self.so_number = self.generate_so_number() super().save(*args, **kwargs) def generate_so_number(self): """Generate a unique sales order number""" last_so = SalesOrder.objects.order_by('-id').first() if last_so and last_so.so_number and last_so.so_number.startswith('SO'): try: last_number = int(last_so.so_number[2:]) # Remove 'SO' prefix new_number = last_number + 1 except ValueError: new_number = 1 else: new_number = 1 return f'SO{new_number:04d}' def __str__(self): return self.so_number class SalesOrderItem(models.Model): so = models.ForeignKey(SalesOrder, on_delete=models.CASCADE, related_name='items') product = models.ForeignKey('inventory.Product', on_delete=models.CASCADE) quantity = models.DecimalField(max_digits=10, decimal_places=2) unit_price = models.DecimalField(max_digits=10, decimal_places=2) total_price = models.DecimalField(max_digits=12, decimal_places=2) shipped_quantity = models.DecimalField(max_digits=10, decimal_places=2, default=0) def save(self, *args, **kwargs): self.total_price = self.quantity * self.unit_price super().save(*args, **kwargs) class Delivery(models.Model): delivery_number = models.CharField(max_length=50, unique=True) so = models.ForeignKey(SalesOrder, on_delete=models.CASCADE) delivery_date = models.DateField() delivered_by = models.ForeignKey('accounts.User', on_delete=models.SET_NULL, null=True) notes = models.TextField(blank=True) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return self.delivery_number class DeliveryItem(models.Model): delivery = models.ForeignKey(Delivery, on_delete=models.CASCADE, related_name='items') so_item = models.ForeignKey(SalesOrderItem, on_delete=models.CASCADE) delivered_quantity = models.DecimalField(max_digits=10, decimal_places=2) notes = models.TextField(blank=True)