diff --git a/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.js b/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.js index aeb8f7d..415ff5b 100644 --- a/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.js +++ b/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.js @@ -1,8 +1,5 @@ frappe.ui.form.on('Land tax declaration', { il: function(frm) { - console.log('=== НАЧАЛО: Изменение года ==='); - console.log('Выбранный год:', frm.doc.il); - if (frm.doc.il) { reload_assets_for_year(frm, frm.doc.il); } @@ -10,36 +7,21 @@ frappe.ui.form.on('Land tax declaration', { }); function reload_assets_for_year(frm, year) { - console.log('=== reload_assets_for_year ==='); - console.log('Год для загрузки:', year); - - // Clear existing tables - console.log('Очистка таблиц əlavə_1 и əlavə_2'); frm.clear_table('əlavə_1'); frm.clear_table('əlavə_2'); frm.refresh_fields(); - // Load assets for the specified year - console.log('Запуск параллельной загрузки активов...'); Promise.all([ load_agricultural_assets_for_year(frm, 'əlavə_1', year), load_industrial_assets_for_year(frm, 'əlavə_2', year) ]).then(() => { - console.log('✅ Все активы успешно загружены и обработаны'); frm.refresh_fields(); }).catch((error) => { - console.error('❌ Ошибка при загрузке активов:', error); + console.error('Error loading assets:', error); }); } -// =============================== -// AGRICULTURAL ASSETS (əlavə_1) -// =============================== - function load_agricultural_assets_for_year(frm, table_fieldname, year) { - console.log('=== load_agricultural_assets_for_year ==='); - console.log('Таблица:', table_fieldname, 'Год:', year); - return new Promise((resolve, reject) => { frappe.call({ method: 'taxes_az.taxes_az.doctype.land_tax_declaration.land_tax_declaration.get_assets_for_year', @@ -48,19 +30,13 @@ function load_agricultural_assets_for_year(frm, table_fieldname, year) { year: year }, callback: function(response) { - console.log('Ответ от сервера (сельхоз активы):', response); - if (response.message && response.message.length > 0) { - console.log(`Найдено ${response.message.length} сельхоз активов`); - console.log('Список активов:', response.message); process_agricultural_assets_silent(frm, table_fieldname, response.message, resolve); } else { - console.log('⚠️ Сельхоз активы не найдены для года', year); resolve(); } }, error: function(error) { - console.error('❌ Ошибка загрузки сельхоз активов:', error); resolve(); } }); @@ -68,20 +44,12 @@ function load_agricultural_assets_for_year(frm, table_fieldname, year) { } function process_agricultural_assets_silent(frm, table_fieldname, assets, resolve) { - console.log('=== process_agricultural_assets_silent ==='); - console.log('Количество активов для обработки:', assets.length); - let agricultural_purposes = {}; let processed_count = 0; let unique_purposes = get_unique_purposes(assets); - console.log('Уникальных назначений найдено:', unique_purposes.size); - console.log('Список уникальных назначений:', Array.from(unique_purposes)); - if (unique_purposes.size > 0) { unique_purposes.forEach(purpose_id => { - console.log(`Загрузка данных для назначения ID: "${purpose_id}"`); - frappe.call({ method: 'frappe.client.get', args: { @@ -89,28 +57,20 @@ function process_agricultural_assets_silent(frm, table_fieldname, assets, resolv name: purpose_id }, callback: function(agri_response) { - console.log(`Ответ для назначения ID "${purpose_id}":`, agri_response); - if (agri_response.message) { agricultural_purposes[purpose_id] = { name: agri_response.message.name, purpose_name: agri_response.message.purpose_name }; - console.log(`✅ Назначение загружено:`, agricultural_purposes[purpose_id]); - } else { - console.warn(`⚠️ Назначение ID "${purpose_id}" не найдено в базе`); } processed_count++; - console.log(`Прогресс загрузки назначений: ${processed_count}/${unique_purposes.size}`); if (processed_count === unique_purposes.size) { - console.log('Все назначения загружены, начинаем группировку'); group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, agricultural_purposes, resolve); } }, error: function(error) { - console.error(`❌ Ошибка загрузки назначения ID "${purpose_id}":`, error); processed_count++; if (processed_count === unique_purposes.size) { group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, agricultural_purposes, resolve); @@ -119,13 +79,11 @@ function process_agricultural_assets_silent(frm, table_fieldname, assets, resolv }); }); } else { - console.log('⚠️ Нет уникальных назначений, пропускаем группировку'); group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, agricultural_purposes, resolve); } } function get_unique_purposes(assets) { - console.log('=== get_unique_purposes ==='); let unique_purposes = new Set(); assets.forEach(asset => { @@ -134,20 +92,14 @@ function get_unique_purposes(assets) { } }); - console.log('Найдено уникальных назначений:', unique_purposes.size); return unique_purposes; } function group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, agricultural_purposes, resolve) { - console.log('=== group_and_create_agricultural_rows_silent ==='); - console.log('Активов для группировки:', assets.length); - console.log('Загруженных назначений:', Object.keys(agricultural_purposes).length); - let grouped_assets = {}; assets.forEach(function(asset) { let group_key = create_agricultural_group_key(asset, agricultural_purposes); - console.log(`Актив "${asset.name}" → Ключ группы: "${group_key}"`); if (!grouped_assets[group_key]) { grouped_assets[group_key] = { @@ -156,7 +108,6 @@ function group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, count: 0, asset_names: [] }; - console.log(`Создана новая группа: "${group_key}"`); } grouped_assets[group_key].total_area += (asset.area || 0); @@ -165,34 +116,18 @@ function group_and_create_agricultural_rows_silent(frm, table_fieldname, assets, }); let total_groups = Object.keys(grouped_assets).length; - console.log(`Создано групп: ${total_groups}`); - - // Детальная информация по группам - Object.entries(grouped_assets).forEach(([key, group]) => { - console.log(`Группа "${key}":`, { - количество_активов: group.count, - общая_площадь: group.total_area, - активы: group.asset_names - }); - }); - let completed_calculations = 0; if (total_groups === 0) { - console.log('⚠️ Нет групп для создания строк'); resolve(); return; } Object.entries(grouped_assets).forEach(function([group_key, group]) { - console.log(`Создание строки для группы: "${group_key}"`); - create_agricultural_row_with_calculation_silent(frm, table_fieldname, group.asset, agricultural_purposes, group.total_area, group, function() { completed_calculations++; - console.log(`Прогресс создания строк: ${completed_calculations}/${total_groups}`); if (completed_calculations === total_groups) { - console.log('✅ Все сельхоз строки созданы'); resolve(); } }); @@ -213,97 +148,59 @@ function create_agricultural_group_key(asset, agricultural_purposes) { asset.agricultural_land_purpose || '' ]; - console.log('Создание ключа из частей:', key_parts); return key_parts.join('|'); } function create_agricultural_row_with_calculation_silent(frm, table_fieldname, asset, agricultural_purposes, total_area, group_info, callback) { - console.log('=== create_agricultural_row_with_calculation_silent ==='); - console.log('Актив:', asset.name, 'Общая площадь:', total_area); - let row = frm.add_child(table_fieldname); - console.log('Строка добавлена в таблицу'); fill_agricultural_row_fields(row, asset, agricultural_purposes, total_area, group_info); - console.log('Поля строки заполнены:', row); - calculate_agricultural_tax_for_row_silent(row, asset, total_area, group_info, callback, agricultural_purposes); } function fill_agricultural_row_fields(row, asset, agricultural_purposes, total_area, group_info) { - console.log('=== fill_agricultural_row_fields ==='); - if (asset.agricultural_purpose && agricultural_purposes[asset.agricultural_purpose]) { let purpose_doc = agricultural_purposes[asset.agricultural_purpose]; if (purpose_doc.purpose_name) { let mapped_value = get_select_option_value(purpose_doc.purpose_name); row.bəyannaməsətrininkoduvəadı = mapped_value; - console.log('Назначение:', mapped_value); } } if (asset.cadastral_district_code) { row.torpaqsahəsininyerləşdiyikadastrqiymətrayonununkodu = asset.cadastral_district_code; - console.log('Код кадастрового района:', asset.cadastral_district_code); } if (asset.cadastral_district_name) { row.torpaqsahəsininyerləşdiyikadastrqiymətrayonununadı = asset.cadastral_district_name; - console.log('Название кадастрового района:', asset.cadastral_district_name); } if (asset.quality_groups) { row.keyfiyyətqrupu = asset.quality_groups; - console.log('Группа качества:', asset.quality_groups); } if (asset.agricultural_land_purpose) { - console.log('Тип использования земли:', asset.agricultural_land_purpose); if (asset.agricultural_land_purpose === 'Əkin, dinc və çoxillik əkmələr') { row.torpaqsahəsinintəyinatıəkindincçoxillikəkmələr = 1; row.torpaqsahəsinintəyinatıbiçənəkörüşotlaqlar = 0; - console.log('→ Пахотная земля'); } else if (asset.agricultural_land_purpose === 'Biçənək, örüş və otlaqlar') { row.torpaqsahəsinintəyinatıəkindincçoxillikəkmələr = 0; row.torpaqsahəsinintəyinatıbiçənəkörüşotlaqlar = 1; - console.log('→ Пастбище'); } } if (total_area > 0) { row.torpaqsahəsi6001kodlarüzrəkvmetrlə6002kodlarüzrəhektarlaümumi = total_area; - - let unit = 'единиц'; - if (asset.agricultural_purpose && agricultural_purposes[asset.agricultural_purpose]) { - let purpose_name = agricultural_purposes[asset.agricultural_purpose].purpose_name; - if (purpose_name === 'Təyinatı üzrə istifadə edilməyən kənd təsərrüfatı torpaqları üzrə hesablanmış vergi məbləği') { - unit = 'кв.м'; - } else { - unit = 'га'; - } - } - console.log('Общая площадь:', total_area, unit); } } function calculate_agricultural_tax_for_row_silent(row, asset, total_area, group_info, callback, agricultural_purposes) { - console.log('=== calculate_agricultural_tax_for_row_silent ==='); - let agricultural_purpose_name = null; if (asset.agricultural_purpose && agricultural_purposes && agricultural_purposes[asset.agricultural_purpose]) { agricultural_purpose_name = agricultural_purposes[asset.agricultural_purpose].purpose_name; } - console.log('Параметры расчета:', { - area: total_area, - cadastral_district_name: asset.cadastral_district_name, - quality_groups: asset.quality_groups, - agricultural_land_purpose: asset.agricultural_land_purpose, - agricultural_purpose_name: agricultural_purpose_name - }); - if (!asset.cadastral_district_name || !asset.quality_groups || !asset.agricultural_land_purpose) { - console.warn('⚠️ Не все поля заполнены, пропускаем расчет налога'); callback(); return; } @@ -318,55 +215,30 @@ function calculate_agricultural_tax_for_row_silent(row, asset, total_area, group agricultural_purpose_name: agricultural_purpose_name }, callback: function(response) { - console.log('Результат расчета налога:', response); - if (response.message && 'tax_amount' in response.message) { row.vergiməbləğimanatla = response.message.tax_amount; - console.log(`✅ Налог рассчитан: ${response.message.tax_amount} манат`); - - if (response.message.calculation_details) { - console.log('Детали расчета:', response.message.calculation_details); - } - } else { - console.warn('⚠️ Налог не рассчитан'); } callback(); }, error: function(error) { - console.error('❌ Ошибка расчета налога:', error); callback(); } }); } function get_select_option_value(purpose_name) { - console.log('=== get_select_option_value ==='); - console.log('Входное назначение:', purpose_name); - if (purpose_name === 'Təyinatı üzrə istifadə edilməyən kənd təsərrüfatı torpaqları üzrə hesablanmış vergi məbləği') { - let result = '600.1 Təyinatı üzrə istifadə edilməyən kənd təsərrüfatı torpaqları üzrə hesablanmış vergi məbləği'; - console.log('→ Маппинг на:', result); - return result; + return '600.1 Təyinatı üzrə istifadə edilməyən kənd təsərrüfatı torpaqları üzrə hesablanmış vergi məbləği'; } if (purpose_name === 'Təyinatı üzrə istifadə edilən və ya irriqasiya, meliorasiya və digər aqrotexniki səbəblərdən təyinatı üzrə istifadə edilməsi mümkün olmayan kənd təsərrüfatı torpaqları üzrə verginin məbləği') { - let result = '600.2 Təyinatı üzrə istifadə edilən və ya irriqasiya, meliorasiya və digər aqrotexniki səbəblərdən təyinatı üzrə istifadə edilməsi mümkün olmayan kənd təsərrüfatı torpaqları üzrə verginin məbləği'; - console.log('→ Маппинг на:', result); - return result; + return '600.2 Təyinatı üzrə istifadə edilən və ya irriqasiya, meliorasiya və digər aqrotexniki səbəblərdən təyinatı üzrə istifadə edilməsi mümkün olmayan kənd təsərrüfatı torpaqları üzrə verginin məbləği'; } - console.log('→ Маппинг не найден, возвращаем как есть'); return purpose_name; } -// =============================== -// INDUSTRIAL ASSETS (əlavə_2) -// =============================== - function load_industrial_assets_for_year(frm, table_fieldname, year) { - console.log('=== load_industrial_assets_for_year ==='); - console.log('Таблица:', table_fieldname, 'Год:', year); - return new Promise((resolve, reject) => { frappe.call({ method: 'taxes_az.taxes_az.doctype.land_tax_declaration.land_tax_declaration.get_assets_for_year', @@ -375,19 +247,13 @@ function load_industrial_assets_for_year(frm, table_fieldname, year) { year: year }, callback: function(response) { - console.log('Ответ от сервера (промышленные активы):', response); - if (response.message && response.message.length > 0) { - console.log(`Найдено ${response.message.length} промышленных активов`); - console.log('Список активов:', response.message); group_and_create_industrial_rows_silent(frm, table_fieldname, response.message, resolve); } else { - console.log('⚠️ Промышленные активы не найдены для года', year); resolve(); } }, error: function(error) { - console.error('❌ Ошибка загрузки промышленных активов:', error); resolve(); } }); @@ -395,62 +261,40 @@ function load_industrial_assets_for_year(frm, table_fieldname, year) { } function group_and_create_industrial_rows_silent(frm, table_fieldname, assets, resolve) { - console.log('=== group_and_create_industrial_rows_silent ==='); - console.log('Активов для группировки:', assets.length); - let grouped_assets = {}; assets.forEach(function(asset) { let group_key = create_industrial_group_key(asset); - console.log(`Актив "${asset.name}" → Ключ группы: "${group_key}"`); if (!grouped_assets[group_key]) { grouped_assets[group_key] = { asset: asset, total_area: 0, - total_tax_exempt_area: 0, // ← ДОБАВЛЕНО + total_tax_exempt_area: 0, count: 0, asset_names: [] }; - console.log(`Создана новая группа: "${group_key}"`); } 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].total_tax_exempt_area += (asset.tax_exempt_area || 0); grouped_assets[group_key].count += 1; grouped_assets[group_key].asset_names.push(asset.name); }); let total_groups = Object.keys(grouped_assets).length; - console.log(`Создано групп: ${total_groups}`); - - // Детальная информация по группам - Object.entries(grouped_assets).forEach(([key, group]) => { - console.log(`Группа "${key}":`, { - количество_активов: group.count, - общая_площадь: group.total_area, - tax_exempt_area: group.total_tax_exempt_area, // ← ДОБАВЛЕНО - активы: group.asset_names - }); - }); - let completed_calculations = 0; if (total_groups === 0) { - console.log('⚠️ Нет групп для создания строк'); resolve(); return; } Object.entries(grouped_assets).forEach(function([group_key, group]) { - console.log(`Создание строки для группы: "${group_key}"`); - create_industrial_row_with_calculation_silent(frm, table_fieldname, group.asset, group.total_area, group, function() { completed_calculations++; - console.log(`Прогресс создания строк: ${completed_calculations}/${total_groups}`); if (completed_calculations === total_groups) { - console.log('✅ Все промышленные строки созданы'); resolve(); } }); @@ -465,77 +309,59 @@ function create_industrial_group_key(asset) { asset.mining_note ? 'mining' : 'no_mining' ]; - console.log('Создание ключа из частей:', key_parts); return key_parts.join('|'); } function create_industrial_row_with_calculation_silent(frm, table_fieldname, asset, total_area, group_info, callback) { - console.log('=== create_industrial_row_with_calculation_silent ==='); - console.log('Актив:', asset.name, 'Общая площадь:', total_area, 'кв.м'); - console.log('Tax-exempt площадь:', group_info.total_tax_exempt_area, 'кв.м'); // ← ДОБАВЛЕНО - let row = frm.add_child(table_fieldname); - console.log('Строка добавлена в таблицу'); fill_industrial_row_fields(row, asset, total_area, group_info); - console.log('Поля строки заполнены:', row); - calculate_industrial_tax_for_row_silent(row, asset, total_area, group_info, callback); } function fill_industrial_row_fields(row, asset, total_area, group_info) { - console.log('=== fill_industrial_row_fields ==='); - if (asset.territorial_unit_code) { row.torpaqsahəsininyerləşdiyiəraziməntəqəsininkodu = parseFloat(asset.territorial_unit_code) || 0; - console.log('Код территориальной единицы:', asset.territorial_unit_code); } if (asset.territorial_unit_name) { row.torpaqsahəsininyerləşdiyiəraziməntəqəsininadı = asset.territorial_unit_name; - console.log('Название территориальной единицы:', asset.territorial_unit_name); } if (asset.industrial_land_purpose) { - console.log('Назначение земли:', asset.industrial_land_purpose); if (asset.industrial_land_purpose === 'Sənaye, tikinti, nəqliyyat, rabitə, ticarət-məişət xid-ti və dig. xüs. təy-tlı sahələr') { row.torpaqsahəsinintəyinatısənayətikinti = 1; row.torpaqsahəsinintəyinatıyaşayışfondları = 0; - console.log('→ Промышленное назначение'); } else if (asset.industrial_land_purpose === 'Yaşayış fondları, həyətyanı və bağsahələri üzrə sahələr') { row.torpaqsahəsinintəyinatısənayətikinti = 0; row.torpaqsahəsinintəyinatıyaşayışfondları = 1; - console.log('→ Жилое назначение'); } } if (asset.mining_note !== undefined) { row.faydalıqazıntıçıxarılmasıbarədəqeyd = asset.mining_note ? 1 : 0; - console.log('Полезные ископаемые:', asset.mining_note ? 'Да' : 'Нет'); } if (total_area > 0) { row.torpaqsahəsikvmetrləümumisahə = total_area; - console.log('Общая площадь:', total_area, 'м²'); } - // ← ДОБАВЛЕНО: Заполнение tax_exempt_area if (group_info.total_tax_exempt_area > 0) { row.torpaqsahəsikvmetrləocümlədənvergiyəcəlbolunmayansahə = group_info.total_tax_exempt_area; - console.log('Tax-exempt площадь:', group_info.total_tax_exempt_area, 'м²'); } } function calculate_industrial_tax_for_row_silent(row, asset, total_area, group_info, callback) { - console.log('=== calculate_industrial_tax_for_row_silent ==='); - console.log('Параметры расчета:', { - area_sqm: total_area, - territorial_unit_name: asset.territorial_unit_name, - industrial_land_purpose: asset.industrial_land_purpose - }); + 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) { - console.warn('⚠️ Не все поля заполнены, пропускаем расчет налога'); callback(); return; } @@ -543,27 +369,17 @@ function calculate_industrial_tax_for_row_silent(row, asset, total_area, group_i frappe.call({ method: 'taxes_az.taxes_az.doctype.land_tax_declaration.land_tax_declaration.calculate_industrial_tax', args: { - area_sqm: total_area, + area_sqm: taxable_area, territorial_unit_name: asset.territorial_unit_name, industrial_land_purpose: asset.industrial_land_purpose }, callback: function(response) { - console.log('Результат расчета налога:', response); - if (response.message && 'tax_amount' in response.message) { row.vergiməbləğimanatla = response.message.tax_amount; - console.log(`✅ Налог рассчитан: ${response.message.tax_amount} манат`); - - if (response.message.calculation_details) { - console.log('Детали расчета:', response.message.calculation_details); - } - } else { - console.warn('⚠️ Налог не рассчитан'); } callback(); }, error: function(error) { - console.error('❌ Ошибка расчета налога:', error); callback(); } }); diff --git a/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.py b/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.py index bbe726a..dc47044 100644 --- a/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.py +++ b/taxes_az/taxes_az/doctype/land_tax_declaration/land_tax_declaration.py @@ -8,15 +8,9 @@ class Landtaxdeclaration(Document): @frappe.whitelist() def get_doctype_fields_info(): - """Gets information about fields of əlavə_1 table and Asset""" - - frappe.log_error("Fields Info Start", "Начало получения метаданных полей") - result = {} try: - # Get metadata for əlavə_1 table - frappe.log_error("Elave1 Metadata", "Получение метаданных для Land tax declaration Elave 1") elave1_meta = frappe.get_meta('Land tax declaration Elave 1') result['elave1_fields'] = [] @@ -31,10 +25,6 @@ def get_doctype_fields_info(): } result['elave1_fields'].append(field_info) - frappe.log_error("Elave1 Fields Count", f"Найдено полей в Elave 1: {len(result['elave1_fields'])}") - - # Get metadata for əlavə_2 table - frappe.log_error("Elave2 Metadata", "Получение метаданных для Land tax declaration Elave 2") elave2_meta = frappe.get_meta('Land tax declaration Elave 2') result['elave2_fields'] = [] @@ -49,10 +39,6 @@ def get_doctype_fields_info(): } result['elave2_fields'].append(field_info) - frappe.log_error("Elave2 Fields Count", f"Найдено полей в Elave 2: {len(result['elave2_fields'])}") - - # Get metadata for Asset - frappe.log_error("Asset Metadata", "Получение метаданных для Asset") asset_meta = frappe.get_meta('Asset') result['asset_fields'] = [] @@ -67,82 +53,31 @@ def get_doctype_fields_info(): } result['asset_fields'].append(field_info) - frappe.log_error("Asset Fields Count", f"Найдено полей в Asset: {len(result['asset_fields'])}") - frappe.log_error("Fields Info Success", "Метаданные успешно получены") - return result except Exception as e: - frappe.log_error("Fields Info Error", f"Ошибка в get_doctype_fields_info: {str(e)}\n{frappe.get_traceback()}") return {'error': str(e)} -# =============================== -# AGRICULTURAL LAND CALCULATIONS -# =============================== - @frappe.whitelist() def calculate_agricultural_tax(area_value, cadastral_district_name, quality_groups, agricultural_land_purpose, agricultural_purpose_name=None): - """ - Calculates tax for agricultural land - Formula: hectare × score × markup - - area_value: может быть в гектарах или кв.м в зависимости от назначения - agricultural_purpose_name: название назначения для определения единицы измерения - """ - params_info = ( - f"Параметры расчета:\n" - f" - area_value: {area_value}\n" - f" - agricultural_purpose_name: {agricultural_purpose_name}\n" - f" - cadastral_district_name: {cadastral_district_name}\n" - f" - quality_groups: {quality_groups}\n" - f" - agricultural_land_purpose: {agricultural_land_purpose}" - ) - frappe.log_error("Agri Tax Start", params_info) - try: - # Input validation if area_value is None or not cadastral_district_name or not quality_groups or not agricultural_land_purpose: - error_msg = "Не все поля заполнены для расчета" - frappe.log_error("Agri Tax Valid", error_msg) - frappe.throw(error_msg) + frappe.throw("Not all fields are filled for calculation") - # Конвертируем площадь в гектары если нужно hectare_value = float(area_value) - original_unit = "неизвестно" + original_unit = "unknown" - # Если неиспользуемые земли - area_value в кв.м, конвертируем в гектары 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 hectare_value > 0: hectare_value = float(area_value) / 10000 - original_unit = "кв.м" - frappe.log_error("Area Convert", f"Неиспользуемые земли: {area_value} кв.м → {hectare_value} гектар") + original_unit = "sq.m" else: - # Используемые земли - уже в гектарах - original_unit = "гектары" - frappe.log_error("Area Direct", f"Используемые земли: {area_value} гектар (без конвертации)") + original_unit = "hectares" - # Get score from JSON file - frappe.log_error("Get Cadastral", f"Получение балла для района '{cadastral_district_name}', группа '{quality_groups}'") score = get_cadastral_score(cadastral_district_name, quality_groups) - frappe.log_error("Score Retrieved", f"Получен балл: {score}") - - # Determine markup - frappe.log_error("Get Markup", f"Получение коэффициента для назначения '{agricultural_land_purpose}'") markup = get_markup_coefficient(agricultural_land_purpose) - frappe.log_error("Markup Retrieved", f"Получен коэффициент: {markup}") - - # Calculate using formula (всегда в гектарах) result = hectare_value * score * markup - calc_summary = ( - f"Расчет завершен:\n" - f"Исходная площадь: {area_value} {original_unit}\n" - f"Площадь для расчета: {hectare_value} га\n" - f"Формула: {hectare_value} га × {score} × {markup} = {result}\n" - f"Результат: {result} манат" - ) - frappe.log_error("Agri Tax Done", calc_summary) - return { 'tax_amount': result, 'calculation_details': { @@ -151,222 +86,94 @@ def calculate_agricultural_tax(area_value, cadastral_district_name, quality_grou 'hectare': hectare_value, 'score': score, 'markup': markup, - 'formula': f"{hectare_value} га × {score} × {markup} = {result}" + 'formula': f"{hectare_value} ha × {score} × {markup} = {result}" } } except Exception as e: - frappe.log_error("Agri Tax Error", f"Ошибка: {str(e)}\n{frappe.get_traceback()}") - frappe.throw(f"Ошибка при расчете: {str(e)}") + frappe.throw(f"Calculation error: {str(e)}") def get_cadastral_score(cadastral_district_name, quality_group): - """ - Extracts score from JSON file based on cadastral district name and quality group - """ - search_info = ( - f"Поиск балла:\n" - f"Район: {cadastral_district_name}\n" - f"Группа качества: {quality_group}" - ) - frappe.log_error("Cadastral Search", search_info) - try: - # Path to JSON file json_file_path = frappe.get_app_path('taxes_az', 'data', 'cadastral_points_data.json') - frappe.log_error("JSON Path", f"Путь к JSON: {json_file_path}") - # Read JSON file with open(json_file_path, 'r', encoding='utf-8') as file: data = json.load(file) - regions_count = len(data.get('cadastral_regions', [])) - frappe.log_error("JSON Loaded", f"JSON загружен, регионов: {regions_count}") - - # Find corresponding region for region in data.get('cadastral_regions', []): if region.get('region_name') == cadastral_district_name: - frappe.log_error("Region Found", f"Регион найден: {cadastral_district_name}") - - # Get score for specified quality group quality_groups = region.get('quality_groups', {}) score = quality_groups.get(quality_group) - - score_info = ( - f"Группы качества в регионе: {list(quality_groups.keys())}\n" - f"Балл для группы '{quality_group}': {score}" - ) - frappe.log_error("Score Found", score_info) - - # If score is null or not found, return 0 return score if score is not None else 0 - # If region not found - error_msg = f"Кадастровый район '{cadastral_district_name}' не найден в базе данных" - frappe.log_error("Region Not Found", error_msg) - frappe.throw(error_msg) + frappe.throw(f"Cadastral district '{cadastral_district_name}' not found in database") except FileNotFoundError: - error_msg = f"Файл не найден: {json_file_path}" - frappe.log_error("JSON Not Found", error_msg) - frappe.throw("Файл кадастровых данных не найден. Обратитесь к администратору") - except json.JSONDecodeError as e: - frappe.log_error("JSON Parse Err", f"Ошибка парсинга JSON: {str(e)}") - frappe.throw("Ошибка чтения файла кадастровых данных") + frappe.throw("Cadastral data file not found. Contact administrator") + except json.JSONDecodeError: + frappe.throw("Error reading cadastral data file") except Exception as e: - frappe.log_error("Cadastral Error", f"Ошибка: {str(e)}\n{frappe.get_traceback()}") - frappe.throw(f"Ошибка получения кадастрового балла: {str(e)}") + frappe.throw(f"Error getting cadastral score: {str(e)}") def get_markup_coefficient(agricultural_land_purpose): - """ - Determines markup coefficient based on land use purpose - """ - frappe.log_error("Markup Search", f"Назначение: {agricultural_land_purpose}") - markup_map = { "Əkin, dinc və çoxillik əkmələr": 0.06, - "Biçənək, örüş və otlaqlar": 0.006 # 0.06 / 10 + "Biçənək, örüş və otlaqlar": 0.006 } coefficient = markup_map.get(agricultural_land_purpose) if coefficient is None: - available = list(markup_map.keys()) - error_msg = f"Неизвестный тип: {agricultural_land_purpose}\nДоступные: {available}" - frappe.log_error("Unknown Purpose", error_msg) - frappe.throw(f"Неизвестный тип назначения земли: {agricultural_land_purpose}") + frappe.throw(f"Unknown land purpose type: {agricultural_land_purpose}") - frappe.log_error("Markup Found", f"Коэффициент: {coefficient}") return coefficient -# =============================== -# INDUSTRIAL/COMMERCIAL LAND CALCULATIONS -# =============================== - @frappe.whitelist() def calculate_industrial_tax(area_sqm, territorial_unit_name, industrial_land_purpose): - """ - Calculates tax for industrial land - Formula: (area_in_sqm ÷ 100) × score (progressive system) - - area_sqm: площадь в квадратных метрах - """ - params_info = ( - f"Параметры расчета:\n" - f" - area_sqm (площадь в м²): {area_sqm}\n" - f" - territorial_unit_name: {territorial_unit_name}\n" - f" - industrial_land_purpose: {industrial_land_purpose}" - ) - frappe.log_error("Ind Tax Start", params_info) - try: - # Input validation if area_sqm is None or not territorial_unit_name or not industrial_land_purpose: - error_msg = "Не все поля заполнены для расчета" - frappe.log_error("Ind Tax Valid", error_msg) - frappe.throw(error_msg) + frappe.throw("Not all fields are filled for calculation") - # Use value as is - this is square meters area_sqm_float = float(area_sqm) - frappe.log_error("Area Converted", f"Площадь для расчета: {area_sqm_float} м²") - - # Get scores from JSON file - frappe.log_error("Get Ind Scores", f"Получение баллов для '{territorial_unit_name}', назначение '{industrial_land_purpose}'") score_data = get_industrial_land_scores(territorial_unit_name, industrial_land_purpose) - frappe.log_error("Scores Retrieved", f"Получены баллы: {score_data}") - - # Calculate using progressive formula - frappe.log_error("Progressive Calc", "Начало расчета по прогрессивной формуле") calculation_result = calculate_industrial_land_formula(area_sqm_float, score_data) - calc_summary = ( - f"Расчет завершен:\n" - f"Формула: {calculation_result['formula']}\n" - f"Результат: {calculation_result['total']} манат" - ) - frappe.log_error("Ind Tax Done", calc_summary) - return { 'tax_amount': calculation_result['total'], 'calculation_details': calculation_result } except Exception as e: - frappe.log_error("Ind Tax Error", f"Ошибка: {str(e)}\n{frappe.get_traceback()}") - frappe.throw(f"Ошибка при расчете: {str(e)}") + frappe.throw(f"Calculation error: {str(e)}") def get_industrial_land_scores(territorial_unit_name, industrial_land_purpose): - """ - Extracts scores from JSON file for industrial land - """ - search_info = ( - f"Поиск баллов:\n" - f"Территория: {territorial_unit_name}\n" - f"Назначение: {industrial_land_purpose}" - ) - frappe.log_error("Ind Score Search", search_info) - try: - # Path to JSON file json_file_path = frappe.get_app_path('taxes_az', 'data', 'industrial_land_data.json') - frappe.log_error("JSON Path", f"Путь к JSON: {json_file_path}") - # Read JSON file with open(json_file_path, 'r', encoding='utf-8') as file: data = json.load(file) - regions_count = len(data.get('industrial_land_regions', [])) - frappe.log_error("JSON Loaded", f"JSON загружен, регионов: {regions_count}") - - # Find corresponding region for region in data.get('industrial_land_regions', []): if region.get('settlement_name') == territorial_unit_name: - frappe.log_error("Region Found", f"Регион найден: {territorial_unit_name}") - - # Get scores for specified land purpose land_purpose_rates = region.get('land_purpose_rates', {}) purpose_rates = land_purpose_rates.get(industrial_land_purpose) if purpose_rates: - result = { + return { 'up_to_10000': purpose_rates.get('up_to_10000_sqm', 0), 'above_10000': purpose_rates.get('above_10000_sqm', 0) } - frappe.log_error("Rates Found", f"Получены ставки: {result}") - return result - else: - frappe.log_error("Purpose Not Found", f"Назначение '{industrial_land_purpose}' не найдено в регионе") - # If region or purpose not found - error_msg = ( - f"Данные не найдены:\n" - f"Территория: '{territorial_unit_name}'\n" - f"Назначение: '{industrial_land_purpose}'" - ) - frappe.log_error("Data Not Found", error_msg) - frappe.throw(f"Данные не найдены для территории '{territorial_unit_name}' и назначения '{industrial_land_purpose}'") + frappe.throw(f"Data not found for territory '{territorial_unit_name}' and purpose '{industrial_land_purpose}'") except FileNotFoundError: - error_msg = f"Файл не найден: {json_file_path}" - frappe.log_error("JSON Not Found", error_msg) - frappe.throw("Файл данных промышленных земель не найден. Обратитесь к администратору") - except json.JSONDecodeError as e: - frappe.log_error("JSON Parse Err", f"Ошибка парсинга JSON: {str(e)}") - frappe.throw("Ошибка чтения файла данных промышленных земель") + frappe.throw("Industrial land data file not found. Contact administrator") + except json.JSONDecodeError: + frappe.throw("Error reading industrial land data file") except Exception as e: - frappe.log_error("Ind Score Error", f"Ошибка: {str(e)}\n{frappe.get_traceback()}") - frappe.throw(f"Ошибка получения баллов промышленных земель: {str(e)}") + frappe.throw(f"Error getting industrial land scores: {str(e)}") def calculate_industrial_land_formula(area_sqm, score_data): - """ - Calculates cost using progressive formula for industrial land - """ - calc_info = ( - f"Прогрессивный расчет:\n" - f"Площадь: {area_sqm} м²\n" - f"Баллы: {score_data}" - ) - frappe.log_error("Formula Start", calc_info) - up_to_10000_score = score_data['up_to_10000'] above_10000_score = score_data['above_10000'] @@ -374,7 +181,6 @@ def calculate_industrial_land_formula(area_sqm, score_data): total = 0 if area_sqm <= 10000: - # All area up to 10000 sqm part_result = (area_sqm / 100) * up_to_10000_score total = part_result @@ -387,12 +193,7 @@ def calculate_industrial_land_formula(area_sqm, score_data): formula_text = f"{area_sqm} ÷ 100 × {up_to_10000_score} = {total}" - frappe.log_error("Simple Formula", f"Простой расчет (площадь ≤ 10000):\n{formula_text}") - else: - # Progressive system: up to 10000 sqm + above 10000 sqm - - # First 10000 sqm part1_result = (10000 / 100) * up_to_10000_score calculation_parts.append({ 'area': 10000, @@ -401,7 +202,6 @@ def calculate_industrial_land_formula(area_sqm, score_data): 'result': part1_result }) - # Remaining area above 10000 sqm remaining_area = area_sqm - 10000 part2_result = (remaining_area / 100) * above_10000_score calculation_parts.append({ @@ -413,52 +213,25 @@ def calculate_industrial_land_formula(area_sqm, score_data): total = part1_result + part2_result formula_text = f"(10000 ÷ 100 × {up_to_10000_score}) + ({remaining_area} ÷ 100 × {above_10000_score}) = {part1_result} + {part2_result} = {total}" - - progressive_info = ( - f"Прогрессивный расчет (площадь > 10000):\n" - f" Часть 1 (до 10000): {calculation_parts[0]['formula']}\n" - f" Часть 2 (свыше 10000): {calculation_parts[1]['formula']}\n" - f" Итого: {total}" - ) - frappe.log_error("Progressive", progressive_info) - result = { + return { 'total': total, 'area_sqm': area_sqm, 'formula': formula_text, 'calculation_parts': calculation_parts, 'scores_used': score_data } - - frappe.log_error("Formula Done", f"Расчет завершен, результат: {result}") - return result @frappe.whitelist() def get_assets_for_year(asset_type, year): - """ - Gets assets filtered by type and purchase year - """ - search_info = ( - f"Поиск активов:\n" - f"Тип актива: {asset_type}\n" - f"Год: {year}" - ) - frappe.log_error("Get Assets Start", search_info) - try: - # Convert year to int for comparison target_year = int(year) - frappe.log_error("Year Converted", f"Целевой год (int): {target_year}") - # Build filters filters = { 'docstatus': 1, 'custom_asset_type': asset_type } - frappe.log_error("Filters Set", f"Фильтры для поиска:\n - docstatus: 1\n - custom_asset_type: {asset_type}") - - # Get appropriate fields based on asset type if asset_type == 'Kənd təsərrüfatı təyinatlı torpaq sahələri': fields = [ 'name', @@ -471,8 +244,7 @@ def get_assets_for_year(asset_type, year): 'area', 'purchase_date' ] - asset_type_short = "Сельхоз земли" - else: # Industrial assets + else: fields = [ 'name', 'asset_name', @@ -481,26 +253,13 @@ def get_assets_for_year(asset_type, year): 'industrial_land_purpose', 'mining_note', 'area', - 'tax_exempt_area', # ← ДОБАВЛЕНО + 'tax_exempt_area', 'purchase_date' ] - asset_type_short = "Промышленные земли" - fields_info = ( - f"Тип: {asset_type_short}\n" - f"Поля для выборки:\n" + "\n".join([f" - {f}" for f in fields]) - ) - frappe.log_error("Fields Selected", fields_info) - - # Get all assets of the specified type - frappe.log_error("DB Query Start", "Выполнение запроса к БД...") assets = frappe.get_list('Asset', filters=filters, fields=fields) - frappe.log_error("DB Query Done", f"Получено активов из БД: {len(assets)}") - # Filter by purchase_date year filtered_assets = [] - skipped_no_date = 0 - skipped_wrong_year = 0 for asset in assets: if asset.get('purchase_date'): @@ -508,27 +267,8 @@ def get_assets_for_year(asset_type, year): if purchase_year == target_year: filtered_assets.append(asset) - area_value = asset.get('area', 0) - tax_exempt = asset.get('tax_exempt_area', 0) - frappe.log_error("Asset Matched", f"Актив подходит: {asset['name']} (дата: {asset['purchase_date']}, площадь: {area_value}, tax_exempt: {tax_exempt})") - else: - skipped_wrong_year += 1 - frappe.log_error("Asset Skipped", f"Актив пропущен: {asset['name']} (год: {purchase_year}, нужен {target_year})") - else: - skipped_no_date += 1 - frappe.log_error("Asset No Date", f"Актив без даты: {asset['name']}") - - summary = ( - f"Результаты фильтрации:\n" - f"Всего из БД: {len(assets)}\n" - f"Подходят по году {target_year}: {len(filtered_assets)}\n" - f"Пропущено (другой год): {skipped_wrong_year}\n" - f"Пропущено (нет даты): {skipped_no_date}" - ) - frappe.log_error("Get Assets Done", summary) return filtered_assets except Exception as e: - frappe.log_error("Get Assets Error", f"Ошибка: {str(e)}\n{frappe.get_traceback()}") return [] \ No newline at end of file