tax exempt now in formula for land tax decl

This commit is contained in:
Ali 2025-11-28 16:20:49 +04:00
parent 4f69e9bc6c
commit fd54a5e9f2
2 changed files with 64 additions and 31 deletions

View File

@ -145,20 +145,22 @@ function get_unique_purposes(assets) {
function group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, agricultural_purposes, resolve) { function group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, agricultural_purposes, resolve) {
let grouped_assets = {}; let grouped_assets = {};
assets.forEach(function(asset) { assets.forEach(function(asset) {
let group_key = create_agricultural_group_key(asset, agricultural_purposes); let group_key = create_agricultural_group_key(asset, agricultural_purposes);
if (!grouped_assets[group_key]) { if (!grouped_assets[group_key]) {
grouped_assets[group_key] = { grouped_assets[group_key] = {
asset: asset, asset: asset,
total_area: 0, total_area: 0,
total_tax_exempt_area: 0,
count: 0, count: 0,
asset_names: [] asset_names: []
}; };
} }
grouped_assets[group_key].total_area += (asset.area || 0); grouped_assets[group_key].total_area += (asset.area || 0);
grouped_assets[group_key].total_tax_exempt_area += (asset.tax_exempt_area || 0);
grouped_assets[group_key].count += 1; grouped_assets[group_key].count += 1;
grouped_assets[group_key].asset_names.push(asset.name); grouped_assets[group_key].asset_names.push(asset.name);
}); });
@ -262,7 +264,8 @@ function calculate_agricultural_tax_for_row_silent(row, asset, total_area, group
cadastral_district_name: asset.cadastral_district_name, cadastral_district_name: asset.cadastral_district_name,
quality_groups: asset.quality_groups, quality_groups: asset.quality_groups,
agricultural_land_purpose: asset.agricultural_land_purpose, agricultural_land_purpose: asset.agricultural_land_purpose,
agricultural_purpose_name: agricultural_purpose_name agricultural_purpose_name: agricultural_purpose_name,
tax_exempt_area: group_info.total_tax_exempt_area || 0
}, },
callback: function(response) { callback: function(response) {
if (response.message && 'tax_amount' in response.message) { if (response.message && 'tax_amount' in response.message) {
@ -402,26 +405,18 @@ function fill_industrial_row_fields(row, asset, total_area, group_info) {
} }
function calculate_industrial_tax_for_row_silent(row, asset, total_area, group_info, callback) { function calculate_industrial_tax_for_row_silent(row, asset, total_area, group_info, callback) {
let tax_exempt_area = group_info.total_tax_exempt_area || 0;
let taxable_area = total_area - tax_exempt_area;
if (taxable_area <= 0) {
row.vergiməbləğimanatla = 0;
callback();
return;
}
if (!asset.territorial_unit_name || !asset.industrial_land_purpose) { if (!asset.territorial_unit_name || !asset.industrial_land_purpose) {
callback(); callback();
return; return;
} }
frappe.call({ frappe.call({
method: 'taxes_az.taxes_az.doctype.land_tax_declaration.land_tax_declaration.calculate_industrial_tax', method: 'taxes_az.taxes_az.doctype.land_tax_declaration.land_tax_declaration.calculate_industrial_tax',
args: { args: {
area_sqm: taxable_area, area_sqm: total_area,
territorial_unit_name: asset.territorial_unit_name, territorial_unit_name: asset.territorial_unit_name,
industrial_land_purpose: asset.industrial_land_purpose industrial_land_purpose: asset.industrial_land_purpose,
tax_exempt_area: group_info.total_tax_exempt_area || 0
}, },
callback: function(response) { callback: function(response) {
if (response.message && 'tax_amount' in response.message) { if (response.message && 'tax_amount' in response.message) {

View File

@ -59,17 +59,35 @@ def get_doctype_fields_info():
return {'error': str(e)} return {'error': str(e)}
@frappe.whitelist() @frappe.whitelist()
def calculate_agricultural_tax(area_value, cadastral_district_name, quality_groups, agricultural_land_purpose, agricultural_purpose_name=None): def calculate_agricultural_tax(area_value, cadastral_district_name, quality_groups, agricultural_land_purpose, agricultural_purpose_name=None, tax_exempt_area=None):
try: try:
if area_value is None: if area_value is None:
frappe.throw("Area value is required") frappe.throw("Area value is required")
area_float = float(area_value) area_float = float(area_value)
# Вычитаем освобожденную от налогов площадь
if tax_exempt_area:
try:
exempt_float = float(tax_exempt_area)
area_float = max(0, area_float - exempt_float)
except (ValueError, TypeError):
frappe.log_error(f"Invalid tax_exempt_area value: {tax_exempt_area}")
# Если вся площадь освобождена, возвращаем 0
if area_float <= 0:
return {
'tax_amount': 0,
'calculation_details': {
'area_sqm': area_float,
'formula': 'All area is tax-exempt'
}
}
# Для неиспользуемых земель: Area × 2% # Для неиспользуемых земель: Area × 2%
if agricultural_purpose_name == 'Təyinatı üzrə istifadə edilməyən kənd təsərrüfatı torpaqları üzrə hesablanmış vergi məbləği': if agricultural_purpose_name == 'Təyinatı üzrə istifadə edilməyən kənd təsərrüfatı torpaqları üzrə hesablanmış vergi məbləği':
result = area_float * 0.02 result = area_float * 0.02
return { return {
'tax_amount': result, 'tax_amount': result,
'calculation_details': { 'calculation_details': {
@ -78,16 +96,16 @@ def calculate_agricultural_tax(area_value, cadastral_district_name, quality_grou
'formula': f"{area_float} sq.m × 0.02 = {result}" 'formula': f"{area_float} sq.m × 0.02 = {result}"
} }
} }
# Для используемых земель: Hectare × Score × Markup # Для используемых земель: Hectare × Score × Markup
if not cadastral_district_name or not quality_groups or not agricultural_land_purpose: if not cadastral_district_name or not quality_groups or not agricultural_land_purpose:
frappe.throw("Not all fields are filled for calculation") frappe.throw("Not all fields are filled for calculation")
hectare_value = float(area_value) hectare_value = area_float
score = get_cadastral_score(cadastral_district_name, quality_groups) score = get_cadastral_score(cadastral_district_name, quality_groups)
markup = get_markup_coefficient(agricultural_land_purpose) markup = get_markup_coefficient(agricultural_land_purpose)
result = hectare_value * score * markup result = hectare_value * score * markup
return { return {
'tax_amount': result, 'tax_amount': result,
'calculation_details': { 'calculation_details': {
@ -97,7 +115,7 @@ def calculate_agricultural_tax(area_value, cadastral_district_name, quality_grou
'formula': f"{hectare_value} ha × {score} × {markup} = {result}" 'formula': f"{hectare_value} ha × {score} × {markup} = {result}"
} }
} }
except Exception as e: except Exception as e:
frappe.throw(f"Calculation error: {str(e)}") frappe.throw(f"Calculation error: {str(e)}")
@ -137,20 +155,39 @@ def get_markup_coefficient(agricultural_land_purpose):
return coefficient return coefficient
@frappe.whitelist() @frappe.whitelist()
def calculate_industrial_tax(area_sqm, territorial_unit_name, industrial_land_purpose): def calculate_industrial_tax(area_sqm, territorial_unit_name, industrial_land_purpose, tax_exempt_area=None):
try: try:
if area_sqm is None or not territorial_unit_name or not industrial_land_purpose: if area_sqm is None or not territorial_unit_name or not industrial_land_purpose:
frappe.throw("Not all fields are filled for calculation") frappe.throw("Not all fields are filled for calculation")
area_sqm_float = float(area_sqm) area_sqm_float = float(area_sqm)
# Вычитаем освобожденную от налогов площадь
if tax_exempt_area:
try:
exempt_float = float(tax_exempt_area)
area_sqm_float = max(0, area_sqm_float - exempt_float)
except (ValueError, TypeError):
frappe.log_error(f"Invalid tax_exempt_area value: {tax_exempt_area}")
# Если вся площадь освобождена, возвращаем 0
if area_sqm_float <= 0:
return {
'tax_amount': 0,
'calculation_details': {
'area_sqm': area_sqm_float,
'formula': 'All area is tax-exempt'
}
}
score_data = get_industrial_land_scores(territorial_unit_name, industrial_land_purpose) score_data = get_industrial_land_scores(territorial_unit_name, industrial_land_purpose)
calculation_result = calculate_industrial_land_formula(area_sqm_float, score_data) calculation_result = calculate_industrial_land_formula(area_sqm_float, score_data)
return { return {
'tax_amount': calculation_result['total'], 'tax_amount': calculation_result['total'],
'calculation_details': calculation_result 'calculation_details': calculation_result
} }
except Exception as e: except Exception as e:
frappe.throw(f"Calculation error: {str(e)}") frappe.throw(f"Calculation error: {str(e)}")
@ -242,14 +279,15 @@ def get_assets_for_year(asset_type, year):
if asset_type == 'Kənd təsərrüfatı təyinatlı torpaq sahələri': if asset_type == 'Kənd təsərrüfatı təyinatlı torpaq sahələri':
fields = [ fields = [
'name', 'name',
'asset_name', 'asset_name',
'agricultural_purpose', 'agricultural_purpose',
'cadastral_district_name', 'cadastral_district_name',
'cadastral_district_code', 'cadastral_district_code',
'quality_groups', 'quality_groups',
'agricultural_land_purpose', 'agricultural_land_purpose',
'area', 'area',
'tax_exempt_area',
'purchase_date' 'purchase_date'
] ]
else: else: