diff --git a/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.js b/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.js index 0e1c5bc..92223b0 100644 --- a/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.js +++ b/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.js @@ -1236,41 +1236,80 @@ function recalculate_totals_manually(frm) { // Новая функция для расчета итогов по tax templates function calculate_tax_template_totals(frm) { - // Reset totals + // Reset allocated totals frm.doc.total_edv_daxil_18 = 0; frm.doc.total_edv_azadolma = 0; frm.doc.total_edv_0 = 0; frm.doc.total_edv_18 = 0; frm.doc.total_allocated_sum = 0; - + + // Reset unallocated totals + frm.doc.total_edv_daxil_18_unallocated = 0; + frm.doc.total_edv_azadolma_unallocated = 0; + frm.doc.total_edv_0_unallocated = 0; + frm.doc.total_edv_18_unallocated = 0; + frm.doc.total_unallocated_sum = 0; + // Calculate totals from sales invoice table (only current month) for (let si_row of frm.doc.sales_invoice_table || []) { let allocated = si_row.allocated_amount || 0; - if (allocated <= 0) continue; - + let unallocated = si_row.unallocated_amount || 0; + let template = (si_row.item_tax_template || '').trim(); - + // Match by template name prefix (template may have company suffix like "ƏDV 18% - js") if (template.startsWith('ƏDV daxil 18%')) { - frm.doc.total_edv_daxil_18 += allocated; + if (allocated > 0) { + frm.doc.total_edv_daxil_18 += allocated; + } + if (unallocated > 0) { + frm.doc.total_edv_daxil_18_unallocated += unallocated; + } } else if (template.startsWith('ƏDV-dən azadolma')) { - frm.doc.total_edv_azadolma += allocated; + if (allocated > 0) { + frm.doc.total_edv_azadolma += allocated; + } + if (unallocated > 0) { + frm.doc.total_edv_azadolma_unallocated += unallocated; + } } else if (template.startsWith('ƏDV 0%')) { - frm.doc.total_edv_0 += allocated; + if (allocated > 0) { + frm.doc.total_edv_0 += allocated; + } + if (unallocated > 0) { + frm.doc.total_edv_0_unallocated += unallocated; + } } else if (template.startsWith('ƏDV 18%')) { - frm.doc.total_edv_18 += allocated; + if (allocated > 0) { + frm.doc.total_edv_18 += allocated; + } + if (unallocated > 0) { + frm.doc.total_edv_18_unallocated += unallocated; + } + } + + // Add to total sums + if (allocated > 0) { + frm.doc.total_allocated_sum += allocated; + } + if (unallocated > 0) { + frm.doc.total_unallocated_sum += unallocated; } - - // Add to total sum - frm.doc.total_allocated_sum += allocated; } - - // Refresh the total fields + + // Refresh the allocated total fields frm.refresh_field('total_edv_daxil_18'); frm.refresh_field('total_edv_azadolma'); frm.refresh_field('total_edv_0'); frm.refresh_field('total_edv_18'); frm.refresh_field('total_allocated_sum'); + + // Refresh the unallocated total fields + frm.refresh_field('total_edv_daxil_18_unallocated'); + frm.refresh_field('total_edv_azadolma_unallocated'); + frm.refresh_field('total_edv_0_unallocated'); + frm.refresh_field('total_edv_18_unallocated'); + frm.refresh_field('total_unallocated_sum'); } function format_currency(value) { diff --git a/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.json b/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.json index 83a8cd7..25cbe3a 100644 --- a/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.json +++ b/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.json @@ -28,6 +28,16 @@ "column_break_totals_2", "total_edv_0", "column_break_totals_3", + "unallocated_totals_section", + "total_edv_18_unallocated", + "column_break_unallocated_1", + "total_edv_daxil_18_unallocated", + "column_break_unallocated_2", + "total_edv_azadolma_unallocated", + "column_break_unallocated_3", + "total_edv_0_unallocated", + "column_break_unallocated_4", + "total_unallocated_sum", "amended_from" ], "fields": [ @@ -164,6 +174,63 @@ { "fieldname": "column_break_lpuu", "fieldtype": "Column Break" + }, + { + "fieldname": "unallocated_totals_section", + "fieldtype": "Section Break", + "label": "Sales Invoice Unallocated Totals by Tax Template" + }, + { + "fieldname": "total_edv_18_unallocated", + "fieldtype": "Currency", + "label": "\u018fDV 18% (Unallocated)", + "precision": "2", + "read_only": 1 + }, + { + "fieldname": "column_break_unallocated_1", + "fieldtype": "Column Break" + }, + { + "fieldname": "total_edv_daxil_18_unallocated", + "fieldtype": "Currency", + "label": "\u018fDV daxil 18% (Unallocated)", + "precision": "2", + "read_only": 1 + }, + { + "fieldname": "column_break_unallocated_2", + "fieldtype": "Column Break" + }, + { + "fieldname": "total_edv_azadolma_unallocated", + "fieldtype": "Currency", + "label": "\u018fDV-d\u0259n azadolma (Unallocated)", + "precision": "2", + "read_only": 1 + }, + { + "fieldname": "column_break_unallocated_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "total_edv_0_unallocated", + "fieldtype": "Currency", + "label": "\u018fDV 0% (Unallocated)", + "precision": "2", + "read_only": 1 + }, + { + "fieldname": "column_break_unallocated_4", + "fieldtype": "Column Break" + }, + { + "bold": 1, + "fieldname": "total_unallocated_sum", + "fieldtype": "Currency", + "label": "Total Unallocated Amount", + "precision": "2", + "read_only": 1 } ], "index_web_pages_for_search": 1, diff --git a/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.py b/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.py index 35b6d6b..af10490 100644 --- a/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.py +++ b/taxes_az/taxes_az/doctype/vat_allocation/vat_allocation.py @@ -18,20 +18,30 @@ class VATallocation(Document): def validate_unique_year_month(self): """ - Ensure only one VAT allocation document exists per year and month + Ensure only one submitted VAT allocation document exists per year and month + - Multiple draft documents can exist for the same period + - Only one document can be submitted for a given period + - Cannot create/save draft if a submitted document already exists """ if not self.year or not self.month: return - - existing = frappe.db.exists({ + + # Check for existing submitted documents with same year and month (excluding current document) + existing_submitted = frappe.db.exists({ 'doctype': 'VAT allocation', 'year': self.year, 'month': self.month, - 'name': ['!=', self.name] + 'name': ['!=', self.name], + 'docstatus': 1 # Only check submitted documents }) - - if existing: - frappe.throw(_(f"VAT allocation for {self.month} {self.year} already exists: {existing}")) + + if existing_submitted: + if self.docstatus == 1: + # Trying to submit, but another submitted document exists + frappe.throw(_(f"VAT allocation for {self.month} {self.year} is already submitted: {existing_submitted}")) + else: + # Trying to save draft, but a submitted document exists + frappe.throw(_(f"Cannot create/modify draft: VAT allocation for {self.month} {self.year} is already submitted: {existing_submitted}")) def recalculate_totals_from_links(self): """ @@ -108,33 +118,54 @@ class VATallocation(Document): """ Calculate totals by tax template from sales invoice table """ - # Reset totals + # Reset allocated totals self.total_edv_daxil_18 = 0 self.total_edv_azadolma = 0 self.total_edv_0 = 0 self.total_edv_18 = 0 self.total_allocated_sum = 0 + # Reset unallocated totals + self.total_edv_daxil_18_unallocated = 0 + self.total_edv_azadolma_unallocated = 0 + self.total_edv_0_unallocated = 0 + self.total_edv_18_unallocated = 0 + self.total_unallocated_sum = 0 + # Calculate totals - only from current month table for si_row in self.sales_invoice_table: allocated = Decimal(str(si_row.allocated_amount or 0)) - if allocated <= 0: - continue + unallocated = Decimal(str(si_row.unallocated_amount or 0)) template = (si_row.item_tax_template or '').strip() # Match by template name prefix (template may have company suffix like "ƏDV 18% - js") if template.startswith('ƏDV daxil 18%'): - self.total_edv_daxil_18 = float(Decimal(str(self.total_edv_daxil_18 or 0)) + allocated) + if allocated > 0: + self.total_edv_daxil_18 = float(Decimal(str(self.total_edv_daxil_18 or 0)) + allocated) + if unallocated > 0: + self.total_edv_daxil_18_unallocated = float(Decimal(str(self.total_edv_daxil_18_unallocated or 0)) + unallocated) elif template.startswith('ƏDV-dən azadolma'): - self.total_edv_azadolma = float(Decimal(str(self.total_edv_azadolma or 0)) + allocated) + if allocated > 0: + self.total_edv_azadolma = float(Decimal(str(self.total_edv_azadolma or 0)) + allocated) + if unallocated > 0: + self.total_edv_azadolma_unallocated = float(Decimal(str(self.total_edv_azadolma_unallocated or 0)) + unallocated) elif template.startswith('ƏDV 0%'): - self.total_edv_0 = float(Decimal(str(self.total_edv_0 or 0)) + allocated) + if allocated > 0: + self.total_edv_0 = float(Decimal(str(self.total_edv_0 or 0)) + allocated) + if unallocated > 0: + self.total_edv_0_unallocated = float(Decimal(str(self.total_edv_0_unallocated or 0)) + unallocated) elif template.startswith('ƏDV 18%'): - self.total_edv_18 = float(Decimal(str(self.total_edv_18 or 0)) + allocated) + if allocated > 0: + self.total_edv_18 = float(Decimal(str(self.total_edv_18 or 0)) + allocated) + if unallocated > 0: + self.total_edv_18_unallocated = float(Decimal(str(self.total_edv_18_unallocated or 0)) + unallocated) - # Add to total sum - self.total_allocated_sum = float(Decimal(str(self.total_allocated_sum or 0)) + allocated) + # Add to total sums + if allocated > 0: + self.total_allocated_sum = float(Decimal(str(self.total_allocated_sum or 0)) + allocated) + if unallocated > 0: + self.total_unallocated_sum = float(Decimal(str(self.total_unallocated_sum or 0)) + unallocated) def validate_allocations(self): """ @@ -1005,33 +1036,54 @@ def calculate_tax_template_totals(self): """ Calculate totals by tax template from sales invoice table """ - # Reset totals + # Reset allocated totals self.total_edv_daxil_18 = 0 self.total_edv_azadolma = 0 self.total_edv_0 = 0 self.total_edv_18 = 0 self.total_allocated_sum = 0 - + + # Reset unallocated totals + self.total_edv_daxil_18_unallocated = 0 + self.total_edv_azadolma_unallocated = 0 + self.total_edv_0_unallocated = 0 + self.total_edv_18_unallocated = 0 + self.total_unallocated_sum = 0 + # Calculate totals - only from current month table for si_row in self.sales_invoice_table: allocated = Decimal(str(si_row.allocated_amount or 0)) - if allocated <= 0: - continue - + unallocated = Decimal(str(si_row.unallocated_amount or 0)) + template = (si_row.item_tax_template or '').strip() - + # Match by template name if template == 'ƏDV daxil 18%': - self.total_edv_daxil_18 = float(Decimal(str(self.total_edv_daxil_18 or 0)) + allocated) + if allocated > 0: + self.total_edv_daxil_18 = float(Decimal(str(self.total_edv_daxil_18 or 0)) + allocated) + if unallocated > 0: + self.total_edv_daxil_18_unallocated = float(Decimal(str(self.total_edv_daxil_18_unallocated or 0)) + unallocated) elif template == 'ƏDV-dən azadolma': - self.total_edv_azadolma = float(Decimal(str(self.total_edv_azadolma or 0)) + allocated) + if allocated > 0: + self.total_edv_azadolma = float(Decimal(str(self.total_edv_azadolma or 0)) + allocated) + if unallocated > 0: + self.total_edv_azadolma_unallocated = float(Decimal(str(self.total_edv_azadolma_unallocated or 0)) + unallocated) elif template == 'ƏDV 0%': - self.total_edv_0 = float(Decimal(str(self.total_edv_0 or 0)) + allocated) + if allocated > 0: + self.total_edv_0 = float(Decimal(str(self.total_edv_0 or 0)) + allocated) + if unallocated > 0: + self.total_edv_0_unallocated = float(Decimal(str(self.total_edv_0_unallocated or 0)) + unallocated) elif template == 'ƏDV 18%': - self.total_edv_18 = float(Decimal(str(self.total_edv_18 or 0)) + allocated) - - # Add to total sum - self.total_allocated_sum = float(Decimal(str(self.total_allocated_sum or 0)) + allocated) + if allocated > 0: + self.total_edv_18 = float(Decimal(str(self.total_edv_18 or 0)) + allocated) + if unallocated > 0: + self.total_edv_18_unallocated = float(Decimal(str(self.total_edv_18_unallocated or 0)) + unallocated) + + # Add to total sums + if allocated > 0: + self.total_allocated_sum = float(Decimal(str(self.total_allocated_sum or 0)) + allocated) + if unallocated > 0: + self.total_unallocated_sum = float(Decimal(str(self.total_unallocated_sum or 0)) + unallocated) @frappe.whitelist() def get_payment_entries_previous_months(year, month, customers=None, min_amount=None, max_amount=None):