import uuid from django.db import models class Account(models.Model): """A node in the chart of accounts (کدینگ حساب‌ها).""" ACCOUNT_TYPES = [ ('asset', 'Asset'), ('liability', 'Liability'), ('equity', 'Equity'), ('income', 'Income'), ('expense', 'Expense'), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) code = models.CharField(max_length=20, unique=True, db_index=True) name = models.CharField(max_length=150) type = models.CharField(max_length=20, choices=ACCOUNT_TYPES) parent = models.ForeignKey( 'self', on_delete=models.SET_NULL, null=True, blank=True, related_name='children' ) is_group = models.BooleanField(default=False) opening_balance = models.FloatField(default=0) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_accounts' ordering = ['code'] def __str__(self): return f"{self.code} - {self.name}" class Party(models.Model): """A trading partner (customer or supplier) used by invoices and treasury.""" PARTY_KINDS = [ ('customer', 'Customer'), ('supplier', 'Supplier'), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) kind = models.CharField(max_length=20, choices=PARTY_KINDS) name = models.CharField(max_length=150) phone = models.CharField(max_length=30, blank=True, default='') economic_code = models.CharField(max_length=50, blank=True, default='') address = models.TextField(blank=True, default='') opening_balance = models.FloatField(default=0) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_parties' ordering = ['name'] def __str__(self): return self.name class Product(models.Model): """An inventory item.""" 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) unit = models.CharField(max_length=30, blank=True, default='') sale_price = models.FloatField(default=0) purchase_price = models.FloatField(default=0) stock = models.FloatField(default=0) reorder_level = models.FloatField(default=0) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_products' ordering = ['name'] def __str__(self): return f"{self.code} - {self.name}" class Voucher(models.Model): """A double-entry journal voucher (سند حسابداری).""" STATUS_CHOICES = [ ('draft', 'Draft'), ('posted', 'Posted'), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) number = models.PositiveIntegerField(default=0) date = models.DateField() description = models.TextField(blank=True, default='') status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') source = models.CharField(max_length=120, blank=True, default='', db_index=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_vouchers' ordering = ['-date', '-number'] def __str__(self): return f"Voucher #{self.number}" class VoucherLine(models.Model): """A single debit/credit line within a voucher.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) voucher = models.ForeignKey(Voucher, on_delete=models.CASCADE, related_name='lines') account = models.ForeignKey(Account, on_delete=models.PROTECT, related_name='voucher_lines') description = models.CharField(max_length=255, blank=True, default='') debit = models.FloatField(default=0) credit = models.FloatField(default=0) class Meta: db_table = 'accounting_voucher_lines' def __str__(self): return f"Line {self.account_id} D:{self.debit} C:{self.credit}" class Invoice(models.Model): """A sales or purchase invoice (فاکتور).""" INVOICE_KINDS = [ ('sale', 'Sale'), ('purchase', 'Purchase'), ] STATUS_CHOICES = [ ('draft', 'Draft'), ('confirmed', 'Confirmed'), ('paid', 'Paid'), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) kind = models.CharField(max_length=20, choices=INVOICE_KINDS) number = models.PositiveIntegerField(default=0) party = models.ForeignKey( Party, on_delete=models.SET_NULL, null=True, blank=True, related_name='invoices' ) date = models.DateField() status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') note = models.TextField(blank=True, default='') created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_invoices' ordering = ['-date', '-number'] def __str__(self): return f"{self.kind} invoice #{self.number}" class InvoiceLine(models.Model): """A line item within an invoice.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='lines') product = models.ForeignKey( Product, on_delete=models.PROTECT, null=True, blank=True, related_name='invoice_lines' ) quantity = models.FloatField(default=0) unit_price = models.FloatField(default=0) discount = models.FloatField(default=0) tax_rate = models.FloatField(default=0) class Meta: db_table = 'accounting_invoice_lines' def __str__(self): return f"Line {self.product_id} x{self.quantity}" class TreasuryTxn(models.Model): """A treasury receipt or payment (دریافت/پرداخت).""" KIND_CHOICES = [ ('receipt', 'Receipt'), ('payment', 'Payment'), ] METHOD_CHOICES = [ ('cash', 'Cash'), ('bank', 'Bank'), ('cheque', 'Cheque'), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) number = models.PositiveIntegerField(default=0) kind = models.CharField(max_length=20, choices=KIND_CHOICES) method = models.CharField(max_length=20, choices=METHOD_CHOICES, default='bank') date = models.DateField() party = models.ForeignKey( Party, on_delete=models.SET_NULL, null=True, blank=True, related_name='treasury_txns' ) amount = models.FloatField(default=0) reference = models.CharField(max_length=120, blank=True, default='') description = models.TextField(blank=True, default='') created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_treasury_txns' ordering = ['-date', '-number'] def __str__(self): return f"{self.kind} #{self.number}" class Employee(models.Model): """A payroll employee.""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) code = models.CharField(max_length=50, blank=True, default='') name = models.CharField(max_length=150) position = models.CharField(max_length=120, blank=True, default='') base_salary = models.FloatField(default=0) insurance_no = models.CharField(max_length=50, blank=True, default='') hire_date = models.DateField(null=True, blank=True) active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_employees' ordering = ['name'] def __str__(self): return self.name class Payslip(models.Model): """A monthly payslip for an employee (فیش حقوقی).""" id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) employee = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='payslips') period = models.CharField(max_length=20, blank=True, default='') base_salary = models.FloatField(default=0) overtime = models.FloatField(default=0) bonus = models.FloatField(default=0) deductions = models.FloatField(default=0) insurance = models.FloatField(default=0) tax = models.FloatField(default=0) created_at = models.DateTimeField(auto_now_add=True) class Meta: db_table = 'accounting_payslips' ordering = ['-period'] def __str__(self): return f"Payslip {self.employee_id} - {self.period}" class CompanySettings(models.Model): """Singleton holding company info and the auto-voucher account mapping.""" id = models.PositiveSmallIntegerField(primary_key=True, default=1) name = models.CharField(max_length=150, blank=True, default='') economic_code = models.CharField(max_length=50, blank=True, default='') fiscal_year = models.CharField(max_length=20, blank=True, default='') base_currency = models.CharField(max_length=20, blank=True, default='تومان') tax_rate = models.FloatField(default=0) address = models.TextField(blank=True, default='') phone = models.CharField(max_length=40, blank=True, default='') bank_account = models.ForeignKey( Account, on_delete=models.SET_NULL, null=True, blank=True, related_name='+' ) owner_payable_account = models.ForeignKey( Account, on_delete=models.SET_NULL, null=True, blank=True, related_name='+' ) customer_payable_account = models.ForeignKey( Account, on_delete=models.SET_NULL, null=True, blank=True, related_name='+' ) owner_share_account = models.ForeignKey( Account, on_delete=models.SET_NULL, null=True, blank=True, related_name='+' ) sales_income_account = models.ForeignKey( Account, on_delete=models.SET_NULL, null=True, blank=True, related_name='+' ) class Meta: db_table = 'accounting_company_settings' def __str__(self): return self.name or 'Company Settings'