95 lines
3.8 KiB
Python
95 lines
3.8 KiB
Python
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)
|