added vat allocation report
This commit is contained in:
parent
cc63adb04e
commit
a403b17ffb
|
|
@ -0,0 +1,256 @@
|
||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
**taxes_az** is a Frappe/ERPNext application for managing Azerbaijan tax declarations and compliance. It integrates with Azerbaijan's E-Taxes system (new.e-taxes.gov.az) to automate tax filing, company profile management, and tax calculations.
|
||||||
|
|
||||||
|
## Development Environment
|
||||||
|
|
||||||
|
This is a Frappe app that must be developed within a Frappe bench environment.
|
||||||
|
|
||||||
|
### Common Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Development server (run from bench directory)
|
||||||
|
cd /home/frappe/frappe-bench
|
||||||
|
bench start
|
||||||
|
|
||||||
|
# Database migrations
|
||||||
|
bench --site [site-name] migrate
|
||||||
|
|
||||||
|
# Install/reinstall app
|
||||||
|
bench --site [site-name] install-app taxes_az
|
||||||
|
bench --site [site-name] reinstall-app taxes_az
|
||||||
|
|
||||||
|
# Console access
|
||||||
|
bench --site [site-name] console
|
||||||
|
|
||||||
|
# Clear cache
|
||||||
|
bench --site [site-name] clear-cache
|
||||||
|
|
||||||
|
# Build assets (after JS/CSS changes)
|
||||||
|
bench build --app taxes_az
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
bench --site [site-name] run-tests --app taxes_az
|
||||||
|
```
|
||||||
|
|
||||||
|
### Post-migration Hook
|
||||||
|
|
||||||
|
The app automatically creates Item Groups after migration via:
|
||||||
|
```python
|
||||||
|
after_migrate = "taxes_az.create_item_group.create_item_groups"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Core Integration Modules
|
||||||
|
|
||||||
|
#### 1. E-Taxes Authentication (`taxes_az/auth.py`)
|
||||||
|
- Handles authentication with Azerbaijan E-Taxes API
|
||||||
|
- Token management and renewal (endpoint: `https://new.e-taxes.gov.az/api/po/auth/public/v1/renew`)
|
||||||
|
- Activity tracking with 10-minute timeout
|
||||||
|
- Key functions:
|
||||||
|
- `record_etaxes_activity()` - Tracks user activity for session management
|
||||||
|
- Authentication state stored in "Asan Login" doctype
|
||||||
|
|
||||||
|
#### 2. Company E-Taxes Integration (`taxes_az/company_etaxes.py`)
|
||||||
|
- Fetches company profile data from E-Taxes
|
||||||
|
- Handles special gambling activity logic (codes: 92000, 9200003, 9200004, 9200001, 9200002, 9200005)
|
||||||
|
- Key functions:
|
||||||
|
- `force_update_gambling_fields()` - Special handling for gambling companies
|
||||||
|
- Client-side counterpart: `taxes_az/client/company.js`
|
||||||
|
|
||||||
|
### DocTypes Structure
|
||||||
|
|
||||||
|
The app contains **199 doctypes** organized into main categories:
|
||||||
|
|
||||||
|
#### Tax Declarations (Main Documents)
|
||||||
|
- **Declaration of Value Added Tax** - VAT declarations with 10+ child tables for different sections (elave1-10, bolme, hesabat, etc.)
|
||||||
|
- **Declaration of Simplified Tax** - Simplified tax with calculation child tables
|
||||||
|
- **Declaration of Mining Tax** - Mining resource tax with wholesale pricing tables
|
||||||
|
- **Excise Declaration** - Excise tax with extensive child tables for different product categories
|
||||||
|
- **Income Tax Return** - Corporate income tax with 5+ child tables
|
||||||
|
- **Property Tax Return** - Property/land tax declarations
|
||||||
|
- **Export Declaration** - Export-related tax declarations
|
||||||
|
- **Withholding Tax declarations** - Various withholding tax types
|
||||||
|
|
||||||
|
#### Supporting Doctypes
|
||||||
|
- **Certificate on Non-Emergence of Tax Liability** - Tax clearance certificates (4 variations: tediyye, tediyye2, tediyye3, tediyye_4)
|
||||||
|
- **Company metadata** - Additional activity, affiliate organizations, business objects, non-resident services
|
||||||
|
- **Business Classification** - NACE-style activity codes
|
||||||
|
- **Main Type of Activity** - Primary business activity classifier
|
||||||
|
- **Agricultural Purpose Type** - Agricultural land use types
|
||||||
|
- **EQM Codes** - E-Taxes specific codes
|
||||||
|
- **Tax Article** - Tax article/clause definitions
|
||||||
|
|
||||||
|
#### Utility Doctypes
|
||||||
|
- **XML Mapping Tool** - Maps Frappe doctypes to E-Taxes XML formats
|
||||||
|
- **VAT Allocation** - VAT distribution logic
|
||||||
|
- **Tax Article Items Report** - Links items to tax articles
|
||||||
|
|
||||||
|
### XML Mapping System
|
||||||
|
|
||||||
|
The app includes a sophisticated XML mapping system (`taxes_az/public/js/xml_mapping/`) to convert Frappe documents to E-Taxes XML format:
|
||||||
|
|
||||||
|
- **xml_parser.js** - Parses E-Taxes XML templates
|
||||||
|
- **field_generator.js** - Generates mapping field UI
|
||||||
|
- **doctype_field_selector.js** - Selects Frappe fields for mapping
|
||||||
|
- **mapping_storage.js** - Stores mapping rules
|
||||||
|
- **xml_generator.js** - Generates final XML from mapped data
|
||||||
|
|
||||||
|
Usage: Create an XML Mapping Tool document, upload E-Taxes XML template, map fields to Frappe doctype fields, then generate XML for submission.
|
||||||
|
|
||||||
|
### Reports
|
||||||
|
|
||||||
|
Located in `taxes_az/taxes_az/report/`:
|
||||||
|
|
||||||
|
- **land_tax_report** - Land/property tax calculations by tax article
|
||||||
|
- **customer_outstanding_balance** - Outstanding customer balances
|
||||||
|
- **fuel_products_purchase_report** - Fuel/oil product purchases
|
||||||
|
- **mining_resources_stock_report** - Mining resources inventory
|
||||||
|
- **gaming_revenue_report** - Gaming/gambling revenue (for gambling companies)
|
||||||
|
- **sport_and_lottery_report** - Sports betting and lottery reporting
|
||||||
|
- **taxable_assets_report** / **tax_exempt_assets_report** - Asset tax status
|
||||||
|
- **tax_articles_revenue_report** - Revenue by tax article
|
||||||
|
- **sales_invoice_info_report** / **payment_entry_info_report** - Transaction reporting
|
||||||
|
|
||||||
|
### Item Groups
|
||||||
|
|
||||||
|
The app manages specialized item groups for Azerbaijan tax purposes:
|
||||||
|
- **Neft Məhsulları** (Oil Products) - Includes fuel types
|
||||||
|
- **Faydalı qazıntılar** (Mining Resources) - 20+ types of minerals with units
|
||||||
|
- **İdman, mərc və lotoreya oyunları** (Gaming) - Sports betting and lottery
|
||||||
|
|
||||||
|
These are created via `create_item_group.py` after migration.
|
||||||
|
|
||||||
|
## Frappe Framework Conventions
|
||||||
|
|
||||||
|
### DocType Structure
|
||||||
|
Each doctype folder contains:
|
||||||
|
- `{doctype_name}.json` - Field definitions
|
||||||
|
- `{doctype_name}.py` - Server-side controller
|
||||||
|
- `{doctype_name}.js` - Client-side controller
|
||||||
|
- `test_{doctype_name}.py` - Unit tests (optional)
|
||||||
|
|
||||||
|
### Naming Conventions
|
||||||
|
- Child table doctypes often have parent name + description (e.g., `declaration_of_value_added_tax_elave_1`)
|
||||||
|
- Azerbaijani terms used extensively in doctype names
|
||||||
|
|
||||||
|
### Hooks Registration
|
||||||
|
|
||||||
|
Hooks are defined in `taxes_az/hooks.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Custom JS for doctypes
|
||||||
|
doctype_js = {
|
||||||
|
"XML Mapping Tool": [
|
||||||
|
"public/js/xml_mapping/xml_parser.js",
|
||||||
|
"public/js/xml_mapping/field_generator.js",
|
||||||
|
"public/js/xml_mapping/doctype_field_selector.js",
|
||||||
|
"public/js/xml_mapping/mapping_storage.js",
|
||||||
|
"public/js/xml_mapping/xml_generator.js"
|
||||||
|
],
|
||||||
|
"Company": "client/company.js",
|
||||||
|
"Item Group": "public/js/item_group.js"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Document events
|
||||||
|
doc_events = {
|
||||||
|
"Item Group": {
|
||||||
|
"on_trash": "taxes_az.item_group.validate_item_group_deletion"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fixtures (master data)
|
||||||
|
fixtures = [
|
||||||
|
{"doctype": "Client Script", "filters": [["module", "=", "Taxes Az"]]},
|
||||||
|
{"doctype": "Main type of activity"},
|
||||||
|
{"doctype": "Business Classification"}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Working with E-Taxes API
|
||||||
|
|
||||||
|
### Authentication Flow
|
||||||
|
1. User authenticates via ASAN Login (Azerbaijan's e-government system)
|
||||||
|
2. Tokens stored in "Asan Login" doctype with `is_default` flag
|
||||||
|
3. Activity tracked every API call to prevent timeout
|
||||||
|
4. Automatic token renewal via `RENEW_URL`
|
||||||
|
|
||||||
|
### API Integration Pattern
|
||||||
|
```python
|
||||||
|
# Always record activity before E-Taxes API calls
|
||||||
|
from taxes_az.auth import record_etaxes_activity
|
||||||
|
record_etaxes_activity()
|
||||||
|
|
||||||
|
# Make API call with proper headers
|
||||||
|
headers = {
|
||||||
|
"Accept": "application/json, text/plain, */*",
|
||||||
|
"Cache-Control": "no-cache",
|
||||||
|
"Referer": "https://new.e-taxes.gov.az/eportal/az/login/asan"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Special Business Logic
|
||||||
|
|
||||||
|
### Gambling Companies
|
||||||
|
Companies with main_activity in gambling codes must have either `seller` or `organizer` checkbox enabled. This is enforced in both Python (`company_etaxes.py`) and JavaScript (`client/company.js`).
|
||||||
|
|
||||||
|
### Tax Declaration Dependencies
|
||||||
|
Many tax declarations have complex child table structures. When modifying declarations:
|
||||||
|
1. Check all related child tables (elave, bolme, hisse, vergi_hesab, etc.)
|
||||||
|
2. Update calculation logic in parent doctype
|
||||||
|
3. Ensure XML mapping includes all child table fields if used for E-Taxes submission
|
||||||
|
|
||||||
|
## File Structure Reference
|
||||||
|
|
||||||
|
```
|
||||||
|
taxes_az/
|
||||||
|
├── taxes_az/ # Main module
|
||||||
|
│ ├── auth.py # E-Taxes authentication
|
||||||
|
│ ├── company_etaxes.py # Company integration
|
||||||
|
│ ├── create_item_group.py # Item group creation
|
||||||
|
│ ├── item_group.py # Item group validation
|
||||||
|
│ ├── hooks.py # Frappe hooks
|
||||||
|
│ ├── client/ # Client scripts
|
||||||
|
│ │ └── company.js
|
||||||
|
│ ├── public/js/
|
||||||
|
│ │ ├── xml_mapping/ # XML mapping system
|
||||||
|
│ │ └── item_group.js
|
||||||
|
│ ├── data/ # JSON data files
|
||||||
|
│ │ ├── industrial_land_data.json
|
||||||
|
│ │ └── cadastral_points_data.json
|
||||||
|
│ ├── fixtures/ # Master data
|
||||||
|
│ └── taxes_az/ # Nested module (doctypes/reports)
|
||||||
|
│ ├── doctype/ # 199 doctypes
|
||||||
|
│ ├── report/ # Custom reports
|
||||||
|
│ └── print_format/ # Print templates
|
||||||
|
├── convert-int-to-float.js # Utility scripts
|
||||||
|
├── float-change.js
|
||||||
|
└── fixtures.json # Fixture configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
|
||||||
|
- **Frappe Framework** (~=15.0.0) - Managed by bench
|
||||||
|
- **ERPNext** - Expected to be installed (uses Company, Item Group, Asset doctypes)
|
||||||
|
- Python 3.10+
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
Run tests for specific doctypes:
|
||||||
|
```bash
|
||||||
|
bench --site [site-name] run-tests --doctype "Declaration of Value Added Tax"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Language Note
|
||||||
|
|
||||||
|
The codebase uses a mix of:
|
||||||
|
- **Russian** - Comments and some internal documentation
|
||||||
|
- **Azerbaijani** - DocType names, field labels, Item Group names
|
||||||
|
- **English** - Code, function names, technical terms
|
||||||
|
|
||||||
|
When adding new features, follow existing language conventions for each context.
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright (c) 2025, Jey Soft and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.query_reports["VAT Allocation Report"] = {
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"fieldname": "company",
|
||||||
|
"label": __("Company"),
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "Company",
|
||||||
|
"default": frappe.defaults.get_user_default("Company"),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "year",
|
||||||
|
"label": __("Year"),
|
||||||
|
"fieldtype": "Int",
|
||||||
|
"default": new Date().getFullYear(),
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "month",
|
||||||
|
"label": __("Month"),
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember",
|
||||||
|
"default": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][new Date().getMonth()],
|
||||||
|
"reqd": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"add_total_row": 0,
|
||||||
|
"columns": [],
|
||||||
|
"creation": "2025-11-26 12:00:00.000000",
|
||||||
|
"disable_prepared_report": 0,
|
||||||
|
"disabled": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Report",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": "Yes",
|
||||||
|
"json": "{}",
|
||||||
|
"letter_head": "",
|
||||||
|
"modified": "2025-11-26 12:00:00.000000",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Taxes Az",
|
||||||
|
"name": "VAT Allocation Report",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"prepared_report": 0,
|
||||||
|
"ref_doctype": "VAT allocation",
|
||||||
|
"report_name": "VAT Allocation Report",
|
||||||
|
"report_type": "Script Report",
|
||||||
|
"roles": [
|
||||||
|
{
|
||||||
|
"role": "System Manager"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
# Copyright (c) 2025, Jey Soft and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import flt
|
||||||
|
|
||||||
|
|
||||||
|
def execute(filters=None):
|
||||||
|
"""Main function for report execution"""
|
||||||
|
columns = get_columns()
|
||||||
|
data = get_data(filters)
|
||||||
|
return columns, data
|
||||||
|
|
||||||
|
|
||||||
|
def get_columns():
|
||||||
|
"""Define 13 columns: 1 ID + 12 data columns"""
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
"label": _("VAT Allocation"),
|
||||||
|
"fieldname": "vat_allocation",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"options": "VAT allocation",
|
||||||
|
"width": 150
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
# Column Group 1: Ayın əvvəlinə (начало месяца)
|
||||||
|
columns.extend([
|
||||||
|
{"label": _("Ayın əvvəlinə 18%"), "fieldname": "prev_month_18", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Ayın əvvəlinə 0%"), "fieldname": "prev_month_0", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Ayın əvvəlinə Azad"), "fieldname": "prev_month_azad", "fieldtype": "Currency", "width": 130}
|
||||||
|
])
|
||||||
|
|
||||||
|
# Column Group 2: Yaranan borc (возникший долг)
|
||||||
|
columns.extend([
|
||||||
|
{"label": _("Yaranan borc 18%"), "fieldname": "unallocated_18", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Yaranan borc 0%"), "fieldname": "unallocated_0", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Yaranan borc Azad"), "fieldname": "unallocated_azad", "fieldtype": "Currency", "width": 130}
|
||||||
|
])
|
||||||
|
|
||||||
|
# Column Group 3: Silənən borc (погашенный долг)
|
||||||
|
columns.extend([
|
||||||
|
{"label": _("Silənən borc 18%"), "fieldname": "allocated_18", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Silənən borc 0%"), "fieldname": "allocated_0", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Silənən borc Azad"), "fieldname": "allocated_azad", "fieldtype": "Currency", "width": 130}
|
||||||
|
])
|
||||||
|
|
||||||
|
# Column Group 4: Ayın sonuna (конец месяца)
|
||||||
|
columns.extend([
|
||||||
|
{"label": _("Ayın sonuna 18%"), "fieldname": "balance_18", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Ayın sonuna 0%"), "fieldname": "balance_0", "fieldtype": "Currency", "width": 130},
|
||||||
|
{"label": _("Ayın sonuna Azad"), "fieldname": "balance_azad", "fieldtype": "Currency", "width": 130}
|
||||||
|
])
|
||||||
|
|
||||||
|
return columns
|
||||||
|
|
||||||
|
|
||||||
|
def get_data(filters):
|
||||||
|
"""Get VAT allocation documents and calculate values"""
|
||||||
|
|
||||||
|
# Validate filters
|
||||||
|
if not filters.get('company'):
|
||||||
|
frappe.throw(_("Company is required"))
|
||||||
|
if not filters.get('year'):
|
||||||
|
frappe.throw(_("Year is required"))
|
||||||
|
if not filters.get('month'):
|
||||||
|
frappe.throw(_("Month is required"))
|
||||||
|
|
||||||
|
# Find VAT allocation document (max one result due to autoname format)
|
||||||
|
vat_name = f"VAT-{filters.get('year')}-{filters.get('month')}"
|
||||||
|
|
||||||
|
if not frappe.db.exists("VAT allocation", vat_name):
|
||||||
|
return []
|
||||||
|
|
||||||
|
# Check if submitted
|
||||||
|
docstatus = frappe.db.get_value("VAT allocation", vat_name, "docstatus")
|
||||||
|
if docstatus != 1:
|
||||||
|
return []
|
||||||
|
|
||||||
|
row = calculate_row_data(vat_name)
|
||||||
|
return [row] if row else []
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_row_data(vat_allocation_name):
|
||||||
|
"""Calculate all values for one VAT allocation document"""
|
||||||
|
|
||||||
|
# Get data from sales_invoice_previous_table
|
||||||
|
prev_month_data = frappe.db.sql("""
|
||||||
|
SELECT
|
||||||
|
item_tax_template,
|
||||||
|
SUM(amount) as total_amount,
|
||||||
|
SUM(allocated_amount) as total_allocated
|
||||||
|
FROM `tabVAT allocation sales invoice`
|
||||||
|
WHERE parent = %(parent)s
|
||||||
|
AND parentfield = 'sales_invoice_previous_table'
|
||||||
|
GROUP BY item_tax_template
|
||||||
|
""", {"parent": vat_allocation_name}, as_dict=1)
|
||||||
|
|
||||||
|
# Get data from sales_invoice_table
|
||||||
|
current_month_data = frappe.db.sql("""
|
||||||
|
SELECT
|
||||||
|
item_tax_template,
|
||||||
|
SUM(unallocated_amount) as total_unallocated
|
||||||
|
FROM `tabVAT allocation sales invoice`
|
||||||
|
WHERE parent = %(parent)s
|
||||||
|
AND parentfield = 'sales_invoice_table'
|
||||||
|
GROUP BY item_tax_template
|
||||||
|
""", {"parent": vat_allocation_name}, as_dict=1)
|
||||||
|
|
||||||
|
# Initialize row
|
||||||
|
row = {
|
||||||
|
'vat_allocation': vat_allocation_name,
|
||||||
|
'prev_month_18': 0.0,
|
||||||
|
'prev_month_0': 0.0,
|
||||||
|
'prev_month_azad': 0.0,
|
||||||
|
'unallocated_18': 0.0,
|
||||||
|
'unallocated_0': 0.0,
|
||||||
|
'unallocated_azad': 0.0,
|
||||||
|
'allocated_18': 0.0,
|
||||||
|
'allocated_0': 0.0,
|
||||||
|
'allocated_azad': 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process previous month data
|
||||||
|
for item in prev_month_data:
|
||||||
|
template = (item.item_tax_template or '').strip()
|
||||||
|
amount = flt(item.total_amount)
|
||||||
|
allocated = flt(item.total_allocated)
|
||||||
|
|
||||||
|
if template in ['ƏDV 18%', 'ƏDV daxil 18%']:
|
||||||
|
row['prev_month_18'] += amount
|
||||||
|
row['allocated_18'] += allocated
|
||||||
|
elif template == 'ƏDV 0%':
|
||||||
|
row['prev_month_0'] += amount
|
||||||
|
row['allocated_0'] += allocated
|
||||||
|
elif template == 'ƏDV-dən azadolma':
|
||||||
|
row['prev_month_azad'] += amount
|
||||||
|
row['allocated_azad'] += allocated
|
||||||
|
|
||||||
|
# Process current month data
|
||||||
|
for item in current_month_data:
|
||||||
|
template = (item.item_tax_template or '').strip()
|
||||||
|
unallocated = flt(item.total_unallocated)
|
||||||
|
|
||||||
|
if template in ['ƏDV 18%', 'ƏDV daxil 18%']:
|
||||||
|
row['unallocated_18'] += unallocated
|
||||||
|
elif template == 'ƏDV 0%':
|
||||||
|
row['unallocated_0'] += unallocated
|
||||||
|
elif template == 'ƏDV-dən azadolma':
|
||||||
|
row['unallocated_azad'] += unallocated
|
||||||
|
|
||||||
|
# Calculate balances
|
||||||
|
row['balance_18'] = (row['prev_month_18'] + row['unallocated_18']) - row['allocated_18']
|
||||||
|
row['balance_0'] = (row['prev_month_0'] + row['unallocated_0']) - row['allocated_0']
|
||||||
|
row['balance_azad'] = (row['prev_month_azad'] + row['unallocated_azad']) - row['allocated_azad']
|
||||||
|
|
||||||
|
return row
|
||||||
Loading…
Reference in New Issue