complete first version of main proccess
This commit is contained in:
		
							parent
							
								
									6ff4740d04
								
							
						
					
					
						commit
						f2fc2362a7
					
				
					 61 changed files with 3280 additions and 28 deletions
				
			
		| 
						 | 
				
			
			@ -18,6 +18,7 @@ class Item(NameSlugModel):
 | 
			
		|||
        decimal_places=2, 
 | 
			
		||||
        verbose_name="قیمت واحد"
 | 
			
		||||
    )
 | 
			
		||||
    is_special = models.BooleanField(default=False, verbose_name='ویژه برای فاکتور نهایی')
 | 
			
		||||
    default_quantity = models.PositiveIntegerField(
 | 
			
		||||
        default=1, 
 | 
			
		||||
        verbose_name="تعداد پیشفرض"
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +103,8 @@ class Quote(NameSlugModel):
 | 
			
		|||
 | 
			
		||||
    def calculate_totals(self):
 | 
			
		||||
        """محاسبه مبالغ کل"""
 | 
			
		||||
        total = sum(item.total_price for item in self.items.all())
 | 
			
		||||
        total = sum(item.total_price for item in self.items.filter(is_deleted=False).all())
 | 
			
		||||
        total = sum(item.total_price for item in self.items.filter(is_deleted=False).all())
 | 
			
		||||
        self.total_amount = total
 | 
			
		||||
        
 | 
			
		||||
        # محاسبه تخفیف
 | 
			
		||||
| 
						 | 
				
			
			@ -260,15 +262,19 @@ class Invoice(NameSlugModel):
 | 
			
		|||
            self.discount_amount = 0
 | 
			
		||||
        
 | 
			
		||||
        self.final_amount = self.total_amount - self.discount_amount
 | 
			
		||||
        self.remaining_amount = self.final_amount - self.paid_amount
 | 
			
		||||
        
 | 
			
		||||
        # بروزرسانی وضعیت
 | 
			
		||||
        if self.remaining_amount <= 0:
 | 
			
		||||
        # خالص مانده به نفع شرکت (مثبت) یا به نفع مشتری (منفی)
 | 
			
		||||
        net_due = self.final_amount - self.paid_amount
 | 
			
		||||
        self.remaining_amount = net_due
 | 
			
		||||
 | 
			
		||||
        # وضعیت بر اساس مانده خالص
 | 
			
		||||
        if net_due == 0:
 | 
			
		||||
            self.status = 'paid'
 | 
			
		||||
        elif self.paid_amount > 0:
 | 
			
		||||
            self.status = 'partially_paid'
 | 
			
		||||
        elif net_due > 0:
 | 
			
		||||
            # مشتری هنوز باید پرداخت کند
 | 
			
		||||
            self.status = 'partially_paid' if self.paid_amount > 0 else 'sent'
 | 
			
		||||
        else:
 | 
			
		||||
            self.status = 'sent'
 | 
			
		||||
            # شرکت باید به مشتری پرداخت کند
 | 
			
		||||
            self.status = 'partially_paid'
 | 
			
		||||
        
 | 
			
		||||
        self.save()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -314,6 +320,12 @@ class Payment(BaseModel):
 | 
			
		|||
    """مدل پرداختها"""
 | 
			
		||||
    invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE, related_name='payments', verbose_name="فاکتور")
 | 
			
		||||
    amount = models.DecimalField(max_digits=15, decimal_places=2, verbose_name="مبلغ پرداخت")
 | 
			
		||||
    direction = models.CharField(
 | 
			
		||||
        max_length=3,
 | 
			
		||||
        choices=[('in', 'دریافتی'), ('out', 'پرداختی')],
 | 
			
		||||
        default='in',
 | 
			
		||||
        verbose_name='نوع تراکنش'
 | 
			
		||||
    )
 | 
			
		||||
    payment_method = models.CharField(
 | 
			
		||||
        max_length=20,
 | 
			
		||||
        choices=[
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +338,7 @@ class Payment(BaseModel):
 | 
			
		|||
        default='cash',
 | 
			
		||||
        verbose_name="روش پرداخت"
 | 
			
		||||
    )
 | 
			
		||||
    reference_number = models.CharField(max_length=100, verbose_name="شماره مرجع", blank=True)
 | 
			
		||||
    reference_number = models.CharField(max_length=100, verbose_name="شماره مرجع", blank=True, unique=True)
 | 
			
		||||
    payment_date = models.DateField(verbose_name="تاریخ پرداخت")
 | 
			
		||||
    notes = models.TextField(verbose_name="یادداشتها", blank=True)
 | 
			
		||||
    receipt_image = models.ImageField(upload_to='payments/%Y/%m/%d/', null=True, blank=True, verbose_name="تصویر فیش")
 | 
			
		||||
| 
						 | 
				
			
			@ -345,6 +357,17 @@ class Payment(BaseModel):
 | 
			
		|||
        """بروزرسانی مبالغ فاکتور"""
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
        # بروزرسانی مبلغ پرداخت شده فاکتور
 | 
			
		||||
        total_paid = sum(payment.amount for payment in self.invoice.payments.all())
 | 
			
		||||
        total_paid = sum((p.amount if p.direction == 'in' else -p.amount) for p in self.invoice.payments.filter(is_deleted=False).all())
 | 
			
		||||
        self.invoice.paid_amount = total_paid
 | 
			
		||||
        self.invoice.calculate_totals()
 | 
			
		||||
 | 
			
		||||
    def delete(self, using=None, keep_parents=False):
 | 
			
		||||
        """حذف نرم و بروزرسانی مبالغ فاکتور پس از حذف"""
 | 
			
		||||
        result = super().delete(using=using, keep_parents=keep_parents)
 | 
			
		||||
        try:
 | 
			
		||||
            total_paid = sum((p.amount if p.direction == 'in' else -p.amount) for p in self.invoice.payments.filter(is_deleted=False).all())
 | 
			
		||||
            self.invoice.paid_amount = total_paid
 | 
			
		||||
            self.invoice.calculate_totals()
 | 
			
		||||
        except Exception:
 | 
			
		||||
            pass
 | 
			
		||||
        return result
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue