Add sales types, party adjustments, FunZone party fields, and treasury fee support
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -40,6 +40,11 @@ class Party(models.Model):
|
||||
('customer', 'Customer'),
|
||||
('supplier', 'Supplier'),
|
||||
]
|
||||
EXTERNAL_SOURCES = [
|
||||
('', 'Manual'),
|
||||
('funzone_customer', 'FunZone Customer'),
|
||||
('funzone_owner', 'FunZone Owner'),
|
||||
]
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
kind = models.CharField(max_length=20, choices=PARTY_KINDS)
|
||||
@@ -48,11 +53,33 @@ class Party(models.Model):
|
||||
economic_code = models.CharField(max_length=50, blank=True, default='')
|
||||
address = models.TextField(blank=True, default='')
|
||||
opening_balance = models.FloatField(default=0)
|
||||
external_id = models.UUIDField(null=True, blank=True, db_index=True)
|
||||
external_source = models.CharField(
|
||||
max_length=30, choices=EXTERNAL_SOURCES, blank=True, default=''
|
||||
)
|
||||
first_name = models.CharField(max_length=100, blank=True, default='')
|
||||
last_name = models.CharField(max_length=100, blank=True, default='')
|
||||
username = models.CharField(max_length=100, blank=True, default='')
|
||||
email = models.EmailField(blank=True, default='')
|
||||
national_code = models.CharField(max_length=20, blank=True, default='')
|
||||
iban = models.CharField(max_length=34, blank=True, default='')
|
||||
wallet_balance = models.FloatField(default=0)
|
||||
is_active = models.BooleanField(default=True)
|
||||
is_verified = models.BooleanField(default=False)
|
||||
birthday = models.DateField(null=True, blank=True)
|
||||
venues = models.JSONField(default=list, blank=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'accounting_parties'
|
||||
ordering = ['name']
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['external_id', 'external_source'],
|
||||
condition=models.Q(external_id__isnull=False),
|
||||
name='unique_external_party',
|
||||
),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
@@ -120,6 +147,51 @@ class VoucherLine(models.Model):
|
||||
return f"Line {self.account_id} D:{self.debit} C:{self.credit}"
|
||||
|
||||
|
||||
class SalesType(models.Model):
|
||||
"""A sales category (نوع فروش) referenced by sales documents."""
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
code = models.CharField(max_length=50, db_index=True)
|
||||
name = models.CharField(max_length=150)
|
||||
description = models.TextField(blank=True, default='')
|
||||
active = models.BooleanField(default=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'accounting_sales_types'
|
||||
ordering = ['code']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.code} - {self.name}"
|
||||
|
||||
|
||||
class PartyAdjustment(models.Model):
|
||||
"""Debit/credit notice adjusting a customer receivable (اعلامیه بدهکار/بستانکار)."""
|
||||
|
||||
ADJUSTMENT_KINDS = [
|
||||
('debit', 'Debit'),
|
||||
('credit', 'Credit'),
|
||||
]
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
number = models.PositiveIntegerField(default=0)
|
||||
party = models.ForeignKey(
|
||||
Party, on_delete=models.CASCADE, related_name='adjustments'
|
||||
)
|
||||
kind = models.CharField(max_length=20, choices=ADJUSTMENT_KINDS)
|
||||
date = models.DateField()
|
||||
amount = models.FloatField(default=0)
|
||||
description = models.TextField(blank=True, default='')
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
db_table = 'accounting_party_adjustments'
|
||||
ordering = ['-date', '-number']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.kind} notice #{self.number}"
|
||||
|
||||
|
||||
class Invoice(models.Model):
|
||||
"""A sales or purchase invoice (فاکتور)."""
|
||||
|
||||
@@ -127,6 +199,11 @@ class Invoice(models.Model):
|
||||
('sale', 'Sale'),
|
||||
('purchase', 'Purchase'),
|
||||
]
|
||||
DOCUMENT_TYPES = [
|
||||
('proforma', 'Proforma'),
|
||||
('invoice', 'Invoice'),
|
||||
('return', 'Return'),
|
||||
]
|
||||
STATUS_CHOICES = [
|
||||
('draft', 'Draft'),
|
||||
('confirmed', 'Confirmed'),
|
||||
@@ -135,10 +212,19 @@ class Invoice(models.Model):
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
kind = models.CharField(max_length=20, choices=INVOICE_KINDS)
|
||||
document_type = models.CharField(
|
||||
max_length=20, choices=DOCUMENT_TYPES, default='invoice'
|
||||
)
|
||||
number = models.PositiveIntegerField(default=0)
|
||||
party = models.ForeignKey(
|
||||
Party, on_delete=models.SET_NULL, null=True, blank=True, related_name='invoices'
|
||||
)
|
||||
sales_type = models.ForeignKey(
|
||||
SalesType, on_delete=models.SET_NULL, null=True, blank=True, related_name='invoices'
|
||||
)
|
||||
related_invoice = models.ForeignKey(
|
||||
'self', on_delete=models.SET_NULL, null=True, blank=True, related_name='derived_docs'
|
||||
)
|
||||
date = models.DateField()
|
||||
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft')
|
||||
note = models.TextField(blank=True, default='')
|
||||
@@ -194,8 +280,12 @@ class TreasuryTxn(models.Model):
|
||||
Party, on_delete=models.SET_NULL, null=True, blank=True, related_name='treasury_txns'
|
||||
)
|
||||
amount = models.FloatField(default=0)
|
||||
tax_amount = models.FloatField(default=0)
|
||||
platform_profit_amount = models.FloatField(default=0)
|
||||
owner_net_amount = models.FloatField(default=0)
|
||||
reference = models.CharField(max_length=120, blank=True, default='')
|
||||
description = models.TextField(blank=True, default='')
|
||||
source = models.CharField(max_length=120, blank=True, default='')
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
|
||||
Reference in New Issue
Block a user