fixed cob report
This commit is contained in:
parent
c22dabf943
commit
d61275ca85
|
|
@ -25,14 +25,6 @@ frappe.query_reports["Customer Outstanding Balance"] = {
|
|||
"default": frappe.datetime.get_today(),
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "customer",
|
||||
"label": __("Customer"),
|
||||
"fieldtype": "MultiSelectList",
|
||||
"get_data": function (txt) {
|
||||
return frappe.db.get_link_options("Customer", txt);
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname": "customer_group",
|
||||
"label": __("Customer Group"),
|
||||
|
|
@ -44,41 +36,80 @@ frappe.query_reports["Customer Outstanding Balance"] = {
|
|||
"formatter": function (value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
|
||||
// Highlight opening balance in blue
|
||||
if (column.fieldname == "opening_balance" && data && data.opening_balance > 0) {
|
||||
if (!data) return value;
|
||||
|
||||
// Original columns highlighting
|
||||
if (column.fieldname == "opening_balance" && data.opening_balance > 0) {
|
||||
value = "<span style='color: #1f77b4; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
// Highlight payments in green
|
||||
if (column.fieldname == "payments" && data && data.payments > 0) {
|
||||
if (column.fieldname == "payments" && data.payments > 0) {
|
||||
value = "<span style='color: #2ca02c; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
// Highlight new invoices in orange
|
||||
if (column.fieldname == "new_invoices" && data && data.new_invoices > 0) {
|
||||
if (column.fieldname == "new_invoices" && data.new_invoices > 0) {
|
||||
value = "<span style='color: #ff7f0e; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
// Highlight closing balance in dark red
|
||||
if (column.fieldname == "closing_balance" && data && data.closing_balance > 0) {
|
||||
if (column.fieldname == "closing_balance" && data.closing_balance > 0) {
|
||||
value = "<span style='color: #d62728; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
// Highlight VAT allocation columns
|
||||
if (column.fieldname == "edv_daxil_18" && data && data.edv_daxil_18 > 0) {
|
||||
value = "<span style='color: #17a2b8; font-weight: bold;'>" + value + "</span>";
|
||||
// Tax template columns highlighting
|
||||
// ƏDV 18% - Purple tones
|
||||
if (column.fieldname == "edv_18_opening" && data.edv_18_opening > 0) {
|
||||
value = "<span style='color: #9467bd; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_18_plus" && data.edv_18_plus > 0) {
|
||||
value = "<span style='color: #ff7f0e; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_18_minus" && data.edv_18_minus > 0) {
|
||||
value = "<span style='color: #2ca02c; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_18_closing" && data.edv_18_closing > 0) {
|
||||
value = "<span style='color: #8c564b; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
if (column.fieldname == "edv_azadolma" && data && data.edv_azadolma > 0) {
|
||||
value = "<span style='color: #28a745; font-weight: bold;'>" + value + "</span>";
|
||||
// ƏDV daxil 18% - Blue-green tones
|
||||
if (column.fieldname == "edv_daxil_18_opening" && data.edv_daxil_18_opening > 0) {
|
||||
value = "<span style='color: #17becf; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_daxil_18_plus" && data.edv_daxil_18_plus > 0) {
|
||||
value = "<span style='color: #ff7f0e; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_daxil_18_minus" && data.edv_daxil_18_minus > 0) {
|
||||
value = "<span style='color: #2ca02c; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_daxil_18_closing" && data.edv_daxil_18_closing > 0) {
|
||||
value = "<span style='color: #1f77b4; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
if (column.fieldname == "edv_0" && data && data.edv_0 > 0) {
|
||||
value = "<span style='color: #ffc107; font-weight: bold;'>" + value + "</span>";
|
||||
// ƏDV 0% - Green tones
|
||||
if (column.fieldname == "edv_0_opening" && data.edv_0_opening > 0) {
|
||||
value = "<span style='color: #bcbd22; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_0_plus" && data.edv_0_plus > 0) {
|
||||
value = "<span style='color: #ff7f0e; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_0_minus" && data.edv_0_minus > 0) {
|
||||
value = "<span style='color: #2ca02c; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_0_closing" && data.edv_0_closing > 0) {
|
||||
value = "<span style='color: #7f7f7f; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
if (column.fieldname == "edv_18" && data && data.edv_18 > 0) {
|
||||
value = "<span style='color: #dc3545; font-weight: bold;'>" + value + "</span>";
|
||||
// ƏDV-dən azadolma - Pink-red tones
|
||||
if (column.fieldname == "edv_azadolma_opening" && data.edv_azadolma_opening > 0) {
|
||||
value = "<span style='color: #e377c2; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_azadolma_plus" && data.edv_azadolma_plus > 0) {
|
||||
value = "<span style='color: #ff7f0e; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_azadolma_minus" && data.edv_azadolma_minus > 0) {
|
||||
value = "<span style='color: #2ca02c; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
if (column.fieldname == "edv_azadolma_closing" && data.edv_azadolma_closing > 0) {
|
||||
value = "<span style='color: #d62728; font-weight: bold;'>" + value + "</span>";
|
||||
}
|
||||
|
||||
return value;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import frappe
|
||||
from frappe import _
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
def execute(filters=None):
|
||||
"""Main function for report execution"""
|
||||
|
|
@ -13,8 +14,8 @@ def execute(filters=None):
|
|||
return columns, data
|
||||
|
||||
def get_columns():
|
||||
"""Get report columns definition"""
|
||||
return [
|
||||
"""Get report columns definition with 16 new columns for tax templates"""
|
||||
columns = [
|
||||
{
|
||||
"label": _("Customer"),
|
||||
"fieldname": "customer",
|
||||
|
|
@ -51,38 +52,64 @@ def get_columns():
|
|||
"fieldname": "closing_balance",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("ƏDV daxil 18%"),
|
||||
"fieldname": "edv_daxil_18",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("ƏDV-dən azadolma"),
|
||||
"fieldname": "edv_azadolma",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("ƏDV 0%"),
|
||||
"fieldname": "edv_0",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
},
|
||||
{
|
||||
"label": _("ƏDV 18%"),
|
||||
"fieldname": "edv_18",
|
||||
"fieldtype": "Currency",
|
||||
"width": 140
|
||||
}
|
||||
]
|
||||
|
||||
# Add 16 columns for 4 tax templates
|
||||
tax_templates = [
|
||||
{"name": "ƏDV 18%", "prefix": "edv_18"},
|
||||
{"name": "ƏDV daxil 18%", "prefix": "edv_daxil_18"},
|
||||
{"name": "ƏDV 0%", "prefix": "edv_0"},
|
||||
{"name": "ƏDV-dən azadolma", "prefix": "edv_azadolma"}
|
||||
]
|
||||
|
||||
for template in tax_templates:
|
||||
columns.extend([
|
||||
{
|
||||
"label": _(f"{template['name']} Opening"),
|
||||
"fieldname": f"{template['prefix']}_opening",
|
||||
"fieldtype": "Currency",
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"label": _(f"{template['name']} +"),
|
||||
"fieldname": f"{template['prefix']}_plus",
|
||||
"fieldtype": "Currency",
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"label": _(f"{template['name']} -"),
|
||||
"fieldname": f"{template['prefix']}_minus",
|
||||
"fieldtype": "Currency",
|
||||
"width": 130
|
||||
},
|
||||
{
|
||||
"label": _(f"{template['name']} Closing"),
|
||||
"fieldname": f"{template['prefix']}_closing",
|
||||
"fieldtype": "Currency",
|
||||
"width": 130
|
||||
}
|
||||
])
|
||||
|
||||
return columns
|
||||
|
||||
def get_data(filters):
|
||||
"""Get report data"""
|
||||
"""Get report data from VAT Allocation documents"""
|
||||
conditions = get_conditions(filters)
|
||||
|
||||
# Get opening balance (before from_date)
|
||||
# Get current period VAT Allocation
|
||||
from_date = datetime.strptime(filters.get('from_date'), '%Y-%m-%d')
|
||||
to_date = datetime.strptime(filters.get('to_date'), '%Y-%m-%d')
|
||||
|
||||
current_year = from_date.year
|
||||
current_month = from_date.strftime('%B') # Full month name
|
||||
|
||||
# Get previous month for opening balance
|
||||
previous_date = from_date - relativedelta(months=1)
|
||||
previous_year = previous_date.year
|
||||
previous_month = previous_date.strftime('%B')
|
||||
|
||||
# Get opening balance (before from_date) - original ledger-based calculation
|
||||
opening_balance_data = frappe.db.sql(f"""
|
||||
SELECT
|
||||
ple.party as customer,
|
||||
|
|
@ -103,7 +130,7 @@ def get_data(filters):
|
|||
ABS(opening_balance) >= 0.01
|
||||
""", filters, as_dict=1)
|
||||
|
||||
# Get movements during the period
|
||||
# Get movements during the period - original ledger-based calculation
|
||||
period_data = frappe.db.sql(f"""
|
||||
SELECT
|
||||
ple.party as customer,
|
||||
|
|
@ -124,7 +151,7 @@ def get_data(filters):
|
|||
ple.party
|
||||
""", filters, as_dict=1)
|
||||
|
||||
# Get closing balance (up to to_date)
|
||||
# Get closing balance (up to to_date) - original ledger-based calculation
|
||||
closing_balance_data = frappe.db.sql(f"""
|
||||
SELECT
|
||||
ple.party as customer,
|
||||
|
|
@ -145,11 +172,16 @@ def get_data(filters):
|
|||
ABS(closing_balance) >= 0.01
|
||||
""", filters, as_dict=1)
|
||||
|
||||
# Get VAT allocation data
|
||||
vat_data = get_vat_allocation_data(filters)
|
||||
# Get VAT Allocation data for tax templates
|
||||
vat_current = get_vat_allocation_data(current_year, current_month, filters.get('company'))
|
||||
vat_previous = get_vat_allocation_data(previous_year, previous_month, filters.get('company'))
|
||||
|
||||
# Get Sales Invoice data directly for current month (for "+" column)
|
||||
si_current = get_sales_invoice_data(current_year, current_month, filters.get('company'))
|
||||
|
||||
# Combine all data
|
||||
result = combine_data(opening_balance_data, period_data, closing_balance_data, vat_data)
|
||||
result = combine_data(opening_balance_data, period_data, closing_balance_data,
|
||||
vat_current, vat_previous, si_current)
|
||||
|
||||
# Get customer names and other details
|
||||
add_customer_details(result)
|
||||
|
|
@ -160,77 +192,114 @@ def get_conditions(filters):
|
|||
"""Build WHERE conditions based on filters"""
|
||||
conditions = ""
|
||||
|
||||
if filters.get("customer"):
|
||||
customer_list = "', '".join(filters.get("customer"))
|
||||
conditions += f" AND ple.party IN ('{customer_list}')"
|
||||
|
||||
if filters.get("customer_group"):
|
||||
conditions += " AND ple.party IN (SELECT name FROM `tabCustomer` WHERE customer_group = %(customer_group)s)"
|
||||
|
||||
return conditions
|
||||
|
||||
def get_vat_allocation_data(filters):
|
||||
"""Get VAT allocation data for customers in the period"""
|
||||
if not filters.get("from_date") or not filters.get("to_date"):
|
||||
return []
|
||||
def get_vat_allocation_data(year, month, company):
|
||||
"""
|
||||
Get VAT allocation data for specified year and month
|
||||
Returns dict with customer -> tax_template -> {unallocated, allocated}
|
||||
"""
|
||||
# Find VAT Allocation document
|
||||
vat_name = f"VAT-{year}-{month}"
|
||||
|
||||
# Determine year and month from the date range
|
||||
from_date = datetime.strptime(str(filters.get("from_date")), "%Y-%m-%d")
|
||||
to_date = datetime.strptime(str(filters.get("to_date")), "%Y-%m-%d")
|
||||
if not frappe.db.exists("VAT allocation", vat_name):
|
||||
return {}
|
||||
|
||||
# Get month name mapping
|
||||
month_names = [
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
]
|
||||
|
||||
# Use the to_date for determining the period
|
||||
year = to_date.year
|
||||
month = month_names[to_date.month - 1]
|
||||
|
||||
# Query VAT allocation sales invoice data from submitted documents
|
||||
vat_query = """
|
||||
# Get sales invoice table data from VAT allocation
|
||||
sales_data = frappe.db.sql("""
|
||||
SELECT
|
||||
vasi.customer,
|
||||
vasi.item_tax_template,
|
||||
SUM(vasi.allocated_amount) as allocated_amount
|
||||
customer,
|
||||
item_tax_template,
|
||||
SUM(unallocated_amount) as total_unallocated,
|
||||
SUM(allocated_amount) as total_allocated
|
||||
FROM
|
||||
`tabVAT allocation sales invoice` vasi
|
||||
INNER JOIN
|
||||
`tabVAT allocation` va ON va.name = vasi.parent
|
||||
`tabVAT allocation sales invoice`
|
||||
WHERE
|
||||
va.docstatus = 1
|
||||
AND va.year = %(year)s
|
||||
AND va.month = %(month)s
|
||||
"""
|
||||
|
||||
# Add customer filter if specified
|
||||
customer_condition = ""
|
||||
if filters.get("customer"):
|
||||
customer_list = "', '".join(filters.get("customer"))
|
||||
customer_condition = f" AND vasi.customer IN ('{customer_list}')"
|
||||
|
||||
if filters.get("customer_group"):
|
||||
customer_condition += " AND vasi.customer IN (SELECT name FROM `tabCustomer` WHERE customer_group = %(customer_group)s)"
|
||||
|
||||
vat_query += customer_condition + """
|
||||
parent = %(vat_name)s
|
||||
GROUP BY
|
||||
vasi.customer, vasi.item_tax_template
|
||||
customer, item_tax_template
|
||||
""", {"vat_name": vat_name}, as_dict=1)
|
||||
|
||||
# Organize data by customer and tax template
|
||||
result = {}
|
||||
for row in sales_data:
|
||||
customer = row['customer']
|
||||
template = row['item_tax_template']
|
||||
|
||||
if customer not in result:
|
||||
result[customer] = {}
|
||||
|
||||
result[customer][template] = {
|
||||
'unallocated': row['total_unallocated'] or 0.0,
|
||||
'allocated': row['total_allocated'] or 0.0
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
def get_sales_invoice_data(year, month, company):
|
||||
"""
|
||||
Get Sales Invoice data directly for the specified month
|
||||
Returns dict with customer -> tax_template -> amount
|
||||
"""
|
||||
# Convert month name to number
|
||||
months = {
|
||||
"January": 1, "February": 2, "March": 3, "April": 4,
|
||||
"May": 5, "June": 6, "July": 7, "August": 8,
|
||||
"September": 9, "October": 10, "November": 11, "December": 12
|
||||
}
|
||||
|
||||
vat_data = frappe.db.sql(vat_query, {
|
||||
"year": year,
|
||||
"month": month,
|
||||
"customer_group": filters.get("customer_group")
|
||||
}, as_dict=1)
|
||||
month_number = months.get(month)
|
||||
if not month_number:
|
||||
return {}
|
||||
|
||||
return vat_data
|
||||
# Get Sales Invoice items directly
|
||||
invoice_data = frappe.db.sql("""
|
||||
SELECT
|
||||
si.customer,
|
||||
sii.item_tax_template,
|
||||
SUM(sii.amount) as total_amount
|
||||
FROM
|
||||
`tabSales Invoice` si
|
||||
INNER JOIN
|
||||
`tabSales Invoice Item` sii ON si.name = sii.parent
|
||||
WHERE
|
||||
si.docstatus = 1
|
||||
AND YEAR(si.posting_date) = %(year)s
|
||||
AND MONTH(si.posting_date) = %(month)s
|
||||
AND si.company = %(company)s
|
||||
GROUP BY
|
||||
si.customer, sii.item_tax_template
|
||||
""", {"year": year, "month": month_number, "company": company}, as_dict=1)
|
||||
|
||||
def combine_data(opening_data, period_data, closing_data, vat_data):
|
||||
# Organize data by customer and tax template
|
||||
result = {}
|
||||
for row in invoice_data:
|
||||
customer = row['customer']
|
||||
template = row['item_tax_template']
|
||||
|
||||
if customer not in result:
|
||||
result[customer] = {}
|
||||
|
||||
result[customer][template] = row['total_amount'] or 0.0
|
||||
|
||||
return result
|
||||
|
||||
def combine_data(opening_data, period_data, closing_data, vat_current, vat_previous, si_current):
|
||||
"""Combine all datasets into final result"""
|
||||
result_dict = {}
|
||||
|
||||
# Add opening balances
|
||||
# Tax template mapping
|
||||
template_map = {
|
||||
"ƏDV 18%": "edv_18",
|
||||
"ƏDV daxil 18%": "edv_daxil_18",
|
||||
"ƏDV 0%": "edv_0",
|
||||
"ƏDV-dən azadolma": "edv_azadolma"
|
||||
}
|
||||
|
||||
# Add opening balances (original logic)
|
||||
for row in opening_data:
|
||||
customer = row['customer']
|
||||
result_dict[customer] = {
|
||||
|
|
@ -238,14 +307,16 @@ def combine_data(opening_data, period_data, closing_data, vat_data):
|
|||
'opening_balance': row['opening_balance'] or 0.0,
|
||||
'payments': 0.0,
|
||||
'new_invoices': 0.0,
|
||||
'closing_balance': 0.0,
|
||||
'edv_daxil_18': 0.0,
|
||||
'edv_azadolma': 0.0,
|
||||
'edv_0': 0.0,
|
||||
'edv_18': 0.0
|
||||
'closing_balance': 0.0
|
||||
}
|
||||
# Initialize tax template fields
|
||||
for prefix in template_map.values():
|
||||
result_dict[customer][f'{prefix}_opening'] = 0.0
|
||||
result_dict[customer][f'{prefix}_plus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_minus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_closing'] = 0.0
|
||||
|
||||
# Add period movements
|
||||
# Add period movements (original logic)
|
||||
for row in period_data:
|
||||
customer = row['customer']
|
||||
if customer not in result_dict:
|
||||
|
|
@ -254,17 +325,19 @@ def combine_data(opening_data, period_data, closing_data, vat_data):
|
|||
'opening_balance': 0.0,
|
||||
'payments': 0.0,
|
||||
'new_invoices': 0.0,
|
||||
'closing_balance': 0.0,
|
||||
'edv_daxil_18': 0.0,
|
||||
'edv_azadolma': 0.0,
|
||||
'edv_0': 0.0,
|
||||
'edv_18': 0.0
|
||||
'closing_balance': 0.0
|
||||
}
|
||||
# Initialize tax template fields
|
||||
for prefix in template_map.values():
|
||||
result_dict[customer][f'{prefix}_opening'] = 0.0
|
||||
result_dict[customer][f'{prefix}_plus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_minus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_closing'] = 0.0
|
||||
|
||||
result_dict[customer]['payments'] = row['payments'] or 0.0
|
||||
result_dict[customer]['new_invoices'] = row['new_invoices'] or 0.0
|
||||
|
||||
# Add closing balances
|
||||
# Add closing balances (original logic)
|
||||
for row in closing_data:
|
||||
customer = row['customer']
|
||||
if customer not in result_dict:
|
||||
|
|
@ -273,56 +346,87 @@ def combine_data(opening_data, period_data, closing_data, vat_data):
|
|||
'opening_balance': 0.0,
|
||||
'payments': 0.0,
|
||||
'new_invoices': 0.0,
|
||||
'closing_balance': 0.0,
|
||||
'edv_daxil_18': 0.0,
|
||||
'edv_azadolma': 0.0,
|
||||
'edv_0': 0.0,
|
||||
'edv_18': 0.0
|
||||
'closing_balance': 0.0
|
||||
}
|
||||
# Initialize tax template fields
|
||||
for prefix in template_map.values():
|
||||
result_dict[customer][f'{prefix}_opening'] = 0.0
|
||||
result_dict[customer][f'{prefix}_plus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_minus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_closing'] = 0.0
|
||||
|
||||
result_dict[customer]['closing_balance'] = row['closing_balance'] or 0.0
|
||||
|
||||
# Add VAT allocation data
|
||||
for row in vat_data:
|
||||
customer = row['customer']
|
||||
# Get all customers from all sources
|
||||
all_customers = set(result_dict.keys())
|
||||
all_customers.update(vat_current.keys())
|
||||
all_customers.update(vat_previous.keys())
|
||||
all_customers.update(si_current.keys())
|
||||
|
||||
# Add VAT allocation data for tax templates
|
||||
for customer in all_customers:
|
||||
# Ensure customer exists in result_dict
|
||||
if customer not in result_dict:
|
||||
result_dict[customer] = {
|
||||
'customer': customer,
|
||||
'opening_balance': 0.0,
|
||||
'payments': 0.0,
|
||||
'new_invoices': 0.0,
|
||||
'closing_balance': 0.0,
|
||||
'edv_daxil_18': 0.0,
|
||||
'edv_azadolma': 0.0,
|
||||
'edv_0': 0.0,
|
||||
'edv_18': 0.0
|
||||
'closing_balance': 0.0
|
||||
}
|
||||
# Initialize tax template fields
|
||||
for prefix in template_map.values():
|
||||
result_dict[customer][f'{prefix}_opening'] = 0.0
|
||||
result_dict[customer][f'{prefix}_plus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_minus'] = 0.0
|
||||
result_dict[customer][f'{prefix}_closing'] = 0.0
|
||||
|
||||
# Map item tax template to field names
|
||||
template = row['item_tax_template']
|
||||
allocated = row['allocated_amount'] or 0.0
|
||||
# Get data for this customer
|
||||
customer_current = vat_current.get(customer, {})
|
||||
customer_previous = vat_previous.get(customer, {})
|
||||
customer_si = si_current.get(customer, {})
|
||||
|
||||
if 'daxil 18' in template or 'daxil18' in template.lower().replace(' ', ''):
|
||||
result_dict[customer]['edv_daxil_18'] += allocated
|
||||
elif 'azadolma' in template.lower():
|
||||
result_dict[customer]['edv_azadolma'] += allocated
|
||||
elif '0%' in template or 'edv 0' in template.lower():
|
||||
result_dict[customer]['edv_0'] += allocated
|
||||
elif '18%' in template or 'edv 18' in template.lower():
|
||||
result_dict[customer]['edv_18'] += allocated
|
||||
for template_name, prefix in template_map.items():
|
||||
# Previous month data (for opening balance)
|
||||
prev_data = customer_previous.get(template_name, {'unallocated': 0.0, 'allocated': 0.0})
|
||||
opening = prev_data['unallocated'] # Closing of previous month = unallocated amount
|
||||
|
||||
# Current month data
|
||||
curr_data = customer_current.get(template_name, {'unallocated': 0.0, 'allocated': 0.0})
|
||||
minus = curr_data['allocated'] # Payments (allocated amount)
|
||||
|
||||
# Sales Invoice data for "+" (new invoices)
|
||||
plus = customer_si.get(template_name, 0.0)
|
||||
|
||||
# Calculate closing
|
||||
closing = opening + plus - minus
|
||||
|
||||
result_dict[customer][f'{prefix}_opening'] = opening
|
||||
result_dict[customer][f'{prefix}_plus'] = plus
|
||||
result_dict[customer][f'{prefix}_minus'] = minus
|
||||
result_dict[customer][f'{prefix}_closing'] = closing
|
||||
|
||||
# Convert to list and filter out zero balances
|
||||
result = []
|
||||
for customer, data in result_dict.items():
|
||||
# Only include if there's some activity or outstanding balance
|
||||
if (abs(data['opening_balance']) >= 0.01 or
|
||||
# Check if there's any activity
|
||||
has_activity = (
|
||||
abs(data['opening_balance']) >= 0.01 or
|
||||
abs(data['closing_balance']) >= 0.01 or
|
||||
abs(data['new_invoices']) >= 0.01 or
|
||||
abs(data['payments']) >= 0.01 or
|
||||
abs(data['edv_daxil_18']) >= 0.01 or
|
||||
abs(data['edv_azadolma']) >= 0.01 or
|
||||
abs(data['edv_0']) >= 0.01 or
|
||||
abs(data['edv_18']) >= 0.01):
|
||||
abs(data['payments']) >= 0.01
|
||||
)
|
||||
|
||||
# Also check tax template activity
|
||||
for prefix in template_map.values():
|
||||
if (abs(data[f'{prefix}_opening']) >= 0.01 or
|
||||
abs(data[f'{prefix}_closing']) >= 0.01 or
|
||||
abs(data[f'{prefix}_plus']) >= 0.01 or
|
||||
abs(data[f'{prefix}_minus']) >= 0.01):
|
||||
has_activity = True
|
||||
break
|
||||
|
||||
if has_activity:
|
||||
result.append(data)
|
||||
|
||||
return sorted(result, key=lambda x: x['customer'])
|
||||
|
|
|
|||
Loading…
Reference in New Issue