diff --git a/taxes_az/taxes_az/report/tax_exempt_assets_establishment_year_report/tax_exempt_assets_establishment_year_report.py b/taxes_az/taxes_az/report/tax_exempt_assets_establishment_year_report/tax_exempt_assets_establishment_year_report.py index 2658ae3..a2400b9 100644 --- a/taxes_az/taxes_az/report/tax_exempt_assets_establishment_year_report/tax_exempt_assets_establishment_year_report.py +++ b/taxes_az/taxes_az/report/tax_exempt_assets_establishment_year_report/tax_exempt_assets_establishment_year_report.py @@ -24,8 +24,8 @@ def get_data(filters): if not assets_data: return [] - # Получаем расчеты остатков для этих активов - asset_balances = get_asset_balances(filters, [asset['name'] for asset in assets_data]) + # Получаем расчеты балансов для этих активов из стандартного отчета + asset_balances = get_asset_balances_from_standard_report(filters, [asset['name'] for asset in assets_data]) # Формируем итоговые данные data = [] @@ -41,21 +41,10 @@ def get_data(filters): # Находим баланс для этого актива asset_balance = next((bal for bal in asset_balances if bal['asset'] == asset['name']), {}) - - # Рассчитываем остатки на начало и конец периода + + # Берем значения из стандартного отчета value_as_on_from_date = flt(asset_balance.get('value_as_on_from_date', 0)) - value_of_new_purchase = flt(asset_balance.get('value_of_new_purchase', 0)) - value_of_sold_asset = flt(asset_balance.get('value_of_sold_asset', 0)) - value_of_scrapped_asset = flt(asset_balance.get('value_of_scrapped_asset', 0)) - value_of_capitalized_asset = flt(asset_balance.get('value_of_capitalized_asset', 0)) - - value_as_on_to_date = ( - value_as_on_from_date + - value_of_new_purchase - - value_of_sold_asset - - value_of_scrapped_asset - - value_of_capitalized_asset - ) + net_asset_value_as_on_to_date = flt(asset_balance.get('net_asset_value_as_on_to_date', 0)) # Инициализируем все колонки нулями for article in tax_exempt_articles: @@ -68,7 +57,7 @@ def get_data(filters): if asset['tax_exempt_tax_article']: article_key = get_field_key(asset['tax_exempt_tax_article']) row[f"{article_key}_value_from"] = value_as_on_from_date - row[f"{article_key}_value_to"] = value_as_on_to_date + row[f"{article_key}_value_to"] = net_asset_value_as_on_to_date row[f"{article_key}_insured"] = row.insured_value data.append(row) @@ -158,12 +147,27 @@ def get_field_key(tax_article): return "article_other" +def check_erpnext_version(): + """Проверяет версию ERPNext и определяет, какое поле использовать для стоимости актива""" + # Проверяем наличие колонки net_purchase_amount + columns = frappe.db.get_table_columns("Asset") + has_net_purchase_amount = "net_purchase_amount" in columns + has_capitalization = "Asset Capitalization" in frappe.get_all("DocType", pluck="name") + + return { + "purchase_amount_field": "net_purchase_amount" if has_net_purchase_amount else "gross_purchase_amount", + "has_capitalization": has_capitalization + } + + def get_establishment_year_tax_exempt_assets(filters, tax_exempt_articles): """Получает активы с tax exempt статьями ТОЛЬКО года создания компании""" - + + version_info = check_erpnext_version() + conditions = [] values = [] - + # Фильтр по компании if filters.get("company"): conditions.append("a.company = %s") @@ -188,19 +192,20 @@ def get_establishment_year_tax_exempt_assets(filters, tax_exempt_articles): where_clause = "" if conditions: where_clause = "WHERE " + " AND ".join(conditions) - - # Исключаем капитализированные активы (как в стандартном отчете) - exclude_capitalized = """ - AND NOT EXISTS( - SELECT 1 FROM `tabAsset Capitalization Asset Item` acai - JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name - WHERE acai.asset = a.name - AND ac.posting_date < %s - AND ac.docstatus = 1 - ) - """ - where_clause += exclude_capitalized - values.append(filters.get("from_date")) + + # Исключаем капитализированные активы только если есть поддержка + if version_info["has_capitalization"]: + exclude_capitalized = """ + AND NOT EXISTS( + SELECT 1 FROM `tabAsset Capitalization Asset Item` acai + JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name + WHERE acai.asset = a.name + AND ac.posting_date < %s + AND ac.docstatus = 1 + ) + """ + where_clause += exclude_capitalized + values.append(filters.get("from_date")) query = f""" SELECT @@ -220,102 +225,230 @@ def get_establishment_year_tax_exempt_assets(filters, tax_exempt_articles): return frappe.db.sql(query, values, as_dict=True) -def get_asset_balances(filters, asset_names): - """Рассчитывает остатки активов на основе стандартной логики""" - +def get_asset_balances_from_standard_report(filters, asset_names): + """Получает балансы активов используя логику стандартного отчета Asset Depreciations and Balances""" + if not asset_names: return [] - + + version_info = check_erpnext_version() + + # Получаем детали активов + asset_details = get_asset_details_for_tax_exempt(filters, asset_names, version_info) + + # Получаем депрециацию активов + asset_depreciation = get_asset_depreciation_for_tax_exempt(filters, asset_names) + + # Объединяем данные + result = [] + + for asset_detail in asset_details: + asset_name = asset_detail.get('name') + + # Находим депреciацию для актива + depreciation = next( + (dep for dep in asset_depreciation if dep['asset'] == asset_name), + {} + ) + + # Рассчитываем значения по логике стандартного отчета + value_as_on_from_date = flt(asset_detail.get('cost_as_on_from_date', 0)) + + value_as_on_to_date = ( + value_as_on_from_date + + flt(asset_detail.get('cost_of_new_purchase', 0)) - + flt(asset_detail.get('cost_of_sold_asset', 0)) - + flt(asset_detail.get('cost_of_scrapped_asset', 0)) + ) + + accumulated_depreciation_as_on_from_date = flt(depreciation.get('accumulated_depreciation_as_on_from_date', 0)) + + accumulated_depreciation_as_on_to_date = ( + accumulated_depreciation_as_on_from_date + + flt(depreciation.get('depreciation_amount_during_the_period', 0)) - + flt(depreciation.get('depreciation_eliminated_during_the_period', 0)) + ) + + net_asset_value_as_on_to_date = value_as_on_to_date - accumulated_depreciation_as_on_to_date + + result.append({ + 'asset': asset_name, + 'value_as_on_from_date': value_as_on_from_date, + 'net_asset_value_as_on_to_date': net_asset_value_as_on_to_date + }) + + return result + + +def get_asset_details_for_tax_exempt(filters, asset_names, version_info): + """Получает детали активов (совместимо со старой и новой версией)""" + asset_placeholders = ", ".join(["%s"] * len(asset_names)) - - # Используем ту же логику что в стандартном отчете для расчета остатков - query = f""" - SELECT - a.name as asset, - IFNULL(SUM(CASE WHEN a.purchase_date < %s THEN - CASE WHEN IFNULL(a.disposal_date, 0) = 0 OR a.disposal_date >= %s THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_as_on_from_date, - - IFNULL(SUM(CASE WHEN a.purchase_date >= %s THEN - a.gross_purchase_amount - ELSE - 0 - END), 0) as value_of_new_purchase, - - IFNULL(SUM(CASE WHEN IFNULL(a.disposal_date, 0) != 0 - AND a.disposal_date >= %s - AND a.disposal_date <= %s THEN - CASE WHEN a.status = "Sold" THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_of_sold_asset, - - IFNULL(SUM(CASE WHEN IFNULL(a.disposal_date, 0) != 0 - AND a.disposal_date >= %s - AND a.disposal_date <= %s THEN - CASE WHEN a.status = "Scrapped" THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_of_scrapped_asset, - - IFNULL(SUM(CASE WHEN IFNULL(a.disposal_date, 0) != 0 - AND a.disposal_date >= %s - AND a.disposal_date <= %s THEN - CASE WHEN a.status = "Capitalized" THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_of_capitalized_asset - FROM - `tabAsset` a - WHERE - a.docstatus = 1 - AND a.company = %s - AND a.purchase_date <= %s - AND a.name IN ({asset_placeholders}) - AND NOT EXISTS( - SELECT 1 FROM `tabAsset Capitalization Asset Item` acai - JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name - WHERE acai.asset = a.name - AND ac.posting_date < %s - AND ac.docstatus = 1 + purchase_amount_field = version_info["purchase_amount_field"] + + # Базовый запрос без капитализации + capitalization_check = "" + if version_info["has_capitalization"]: + capitalization_check = """ + and not exists( + select 1 from `tabAsset Capitalization Asset Item` acai + join `tabAsset Capitalization` ac on acai.parent=ac.name + where acai.asset = a.name + and ac.posting_date < %s + and ac.docstatus=1 ) - GROUP BY a.name + """ + + query = f""" + SELECT a.name, + ifnull(sum(case when a.purchase_date < %s then + case when ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %s then + a.{purchase_amount_field} + else + 0 + end + else + 0 + end), 0) as cost_as_on_from_date, + ifnull(sum(case when a.purchase_date >= %s then + a.{purchase_amount_field} + else + 0 + end), 0) as cost_of_new_purchase, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 + and a.disposal_date >= %s + and a.disposal_date <= %s then + case when a.status = "Sold" then + a.{purchase_amount_field} + else + 0 + end + else + 0 + end), 0) as cost_of_sold_asset, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 + and a.disposal_date >= %s + and a.disposal_date <= %s then + case when a.status = "Scrapped" then + a.{purchase_amount_field} + else + 0 + end + else + 0 + end), 0) as cost_of_scrapped_asset + from `tabAsset` a + where a.docstatus=1 and a.company=%s and a.purchase_date <= %s + and a.name IN ({asset_placeholders}) + {capitalization_check} + group by a.name """ - + values = [ - filters.get("from_date"), # value_as_on_from_date condition 1 - filters.get("from_date"), # value_as_on_from_date condition 2 - filters.get("from_date"), # value_of_new_purchase - filters.get("from_date"), # value_of_sold_asset condition 1 - filters.get("to_date"), # value_of_sold_asset condition 2 - filters.get("from_date"), # value_of_scrapped_asset condition 1 - filters.get("to_date"), # value_of_scrapped_asset condition 2 - filters.get("from_date"), # value_of_capitalized_asset condition 1 - filters.get("to_date"), # value_of_capitalized_asset condition 2 + filters.get("from_date"), # cost_as_on_from_date condition 1 + filters.get("from_date"), # cost_as_on_from_date condition 2 + filters.get("from_date"), # cost_of_new_purchase + filters.get("from_date"), # cost_of_sold_asset condition 1 + filters.get("to_date"), # cost_of_sold_asset condition 2 + filters.get("from_date"), # cost_of_scrapped_asset condition 1 + filters.get("to_date"), # cost_of_scrapped_asset condition 2 filters.get("company"), # company filter filters.get("to_date"), # purchase_date filter *asset_names, # asset names for IN clause - filters.get("from_date") # capitalization exclusion ] - + + # Добавляем значение для капитализации если нужно + if version_info["has_capitalization"]: + values.append(filters.get("from_date")) + + return frappe.db.sql(query, values, as_dict=True) + + +def get_asset_depreciation_for_tax_exempt(filters, asset_names): + """Получает депреciацию активов (совместимо со старой и новой версией)""" + + asset_placeholders = ", ".join(["%s"] * len(asset_names)) + + query = f""" + SELECT results.name as asset, + sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date, + sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period, + sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period + from (SELECT a.name as name, + ifnull(sum(case when gle.posting_date < %s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %s) then + gle.debit + else + 0 + end), 0) as accumulated_depreciation_as_on_from_date, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %s + and a.disposal_date <= %s and gle.posting_date <= a.disposal_date then + gle.debit + else + 0 + end), 0) as depreciation_eliminated_during_the_period, + ifnull(sum(case when gle.posting_date >= %s and gle.posting_date <= %s + and (ifnull(a.disposal_date, 0) = 0 or gle.posting_date <= a.disposal_date) then + gle.debit + else + 0 + end), 0) as depreciation_amount_during_the_period + from `tabGL Entry` gle + join `tabAsset` a on + gle.against_voucher = a.name + join `tabAsset Category Account` aca on + aca.parent = a.asset_category and aca.company_name = %s + join `tabCompany` company on + company.name = %s + where + a.docstatus=1 + and a.company=%s + and a.purchase_date <= %s + and gle.debit != 0 + and gle.is_cancelled = 0 + and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account) + and a.name IN ({asset_placeholders}) + group by a.name + union + SELECT a.name as name, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and (a.disposal_date < %s or a.disposal_date > %s) then + 0 + else + a.opening_accumulated_depreciation + end), 0) as accumulated_depreciation_as_on_from_date, + ifnull(sum(case when a.disposal_date >= %s and a.disposal_date <= %s then + a.opening_accumulated_depreciation + else + 0 + end), 0) as depreciation_eliminated_during_the_period, + 0 as depreciation_amount_during_the_period + from `tabAsset` a + where a.docstatus=1 and a.company=%s and a.purchase_date <= %s + and a.name IN ({asset_placeholders}) + group by a.name) as results + group by results.name + """ + + values = [ + filters.get("from_date"), # accumulated_depreciation_as_on_from_date condition 1 + filters.get("from_date"), # accumulated_depreciation_as_on_from_date condition 2 + filters.get("from_date"), # depreciation_eliminated_during_the_period condition 1 + filters.get("to_date"), # depreciation_eliminated_during_the_period condition 2 + filters.get("from_date"), # depreciation_amount_during_the_period condition 1 + filters.get("to_date"), # depreciation_amount_during_the_period condition 2 + filters.get("company"), # aca.company_name + filters.get("company"), # company.name + filters.get("company"), # a.company + filters.get("to_date"), # a.purchase_date + *asset_names, # asset names for IN clause (first union) + filters.get("from_date"), # disposal_date condition (second union) + filters.get("to_date"), # disposal_date condition (second union) + filters.get("from_date"), # disposal_date condition (second union) + filters.get("to_date"), # disposal_date condition (second union) + filters.get("company"), # a.company (second union) + filters.get("to_date"), # a.purchase_date (second union) + *asset_names # asset names for IN clause (second union) + ] + return frappe.db.sql(query, values, as_dict=True) diff --git a/taxes_az/taxes_az/report/taxable_assets_report/taxable_assets_report.py b/taxes_az/taxes_az/report/taxable_assets_report/taxable_assets_report.py index a0216e1..56cf121 100644 --- a/taxes_az/taxes_az/report/taxable_assets_report/taxable_assets_report.py +++ b/taxes_az/taxes_az/report/taxable_assets_report/taxable_assets_report.py @@ -24,8 +24,8 @@ def get_data(filters): if not assets_data: return [] - # Получаем расчеты остатков для этих активов - asset_balances = get_asset_balances(filters, [asset['name'] for asset in assets_data]) + # Получаем расчеты балансов для этих активов из стандартного отчета + asset_balances = get_asset_balances_from_standard_report(filters, [asset['name'] for asset in assets_data]) # Формируем итоговые данные data = [] @@ -41,21 +41,10 @@ def get_data(filters): # Находим баланс для этого актива asset_balance = next((bal for bal in asset_balances if bal['asset'] == asset['name']), {}) - - # Рассчитываем остатки на начало и конец периода - value_as_on_from_date = flt(asset_balance.get('value_as_on_from_date', 0)) + + # Берем значения из стандартного отчета value_of_new_purchase = flt(asset_balance.get('value_of_new_purchase', 0)) - value_of_sold_asset = flt(asset_balance.get('value_of_sold_asset', 0)) - value_of_scrapped_asset = flt(asset_balance.get('value_of_scrapped_asset', 0)) - value_of_capitalized_asset = flt(asset_balance.get('value_of_capitalized_asset', 0)) - - value_as_on_to_date = ( - value_as_on_from_date + - value_of_new_purchase - - value_of_sold_asset - - value_of_scrapped_asset - - value_of_capitalized_asset - ) + net_asset_value_as_on_to_date = flt(asset_balance.get('net_asset_value_as_on_to_date', 0)) # Инициализируем все колонки нулями for asset_type in taxable_asset_types: @@ -67,8 +56,8 @@ def get_data(filters): # Заполняем колонки для соответствующего типа актива if asset['taxable_asset_type']: asset_type_key = get_field_key(asset['taxable_asset_type']) - row[f"{asset_type_key}_value_from"] = value_as_on_from_date - row[f"{asset_type_key}_value_to"] = value_as_on_to_date + row[f"{asset_type_key}_value_from"] = value_of_new_purchase + row[f"{asset_type_key}_value_to"] = net_asset_value_as_on_to_date row[f"{asset_type_key}_insured"] = row.insured_value data.append(row) @@ -126,12 +115,27 @@ def get_field_key(asset_type): return "other_asset_type" +def check_erpnext_version(): + """Проверяет версию ERPNext и определяет, какое поле использовать для стоимости актива""" + # Проверяем наличие колонки net_purchase_amount + columns = frappe.db.get_table_columns("Asset") + has_net_purchase_amount = "net_purchase_amount" in columns + has_capitalization = "Asset Capitalization" in frappe.get_all("DocType", pluck="name") + + return { + "purchase_amount_field": "net_purchase_amount" if has_net_purchase_amount else "gross_purchase_amount", + "has_capitalization": has_capitalization + } + + def get_taxable_assets(filters, taxable_asset_types): """Получает активы с типом 'Vergiyə cəlb olunan əsas vəsaitlər' исключая активы года создания компании""" - + + version_info = check_erpnext_version() + conditions = [] values = [] - + # Фильтр по компании if filters.get("company"): conditions.append("a.company = %s") @@ -160,19 +164,20 @@ def get_taxable_assets(filters, taxable_asset_types): where_clause = "" if conditions: where_clause = "WHERE " + " AND ".join(conditions) - - # Исключаем капитализированные активы (как в стандартном отчете) - exclude_capitalized = """ - AND NOT EXISTS( - SELECT 1 FROM `tabAsset Capitalization Asset Item` acai - JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name - WHERE acai.asset = a.name - AND ac.posting_date < %s - AND ac.docstatus = 1 - ) - """ - where_clause += exclude_capitalized - values.append(filters.get("from_date")) + + # Исключаем капитализированные активы только если есть поддержка + if version_info["has_capitalization"]: + exclude_capitalized = """ + AND NOT EXISTS( + SELECT 1 FROM `tabAsset Capitalization Asset Item` acai + JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name + WHERE acai.asset = a.name + AND ac.posting_date < %s + AND ac.docstatus = 1 + ) + """ + where_clause += exclude_capitalized + values.append(filters.get("from_date")) query = f""" SELECT @@ -192,102 +197,231 @@ def get_taxable_assets(filters, taxable_asset_types): return frappe.db.sql(query, values, as_dict=True) -def get_asset_balances(filters, asset_names): - """Рассчитывает остатки активов на основе стандартной логики""" - +def get_asset_balances_from_standard_report(filters, asset_names): + """Получает балансы активов используя логику стандартного отчета Asset Depreciations and Balances""" + if not asset_names: return [] - + + version_info = check_erpnext_version() + + # Получаем детали активов + asset_details = get_asset_details_for_taxable(filters, asset_names, version_info) + + # Получаем депрециацию активов + asset_depreciation = get_asset_depreciation_for_taxable(filters, asset_names) + + # Объединяем данные + result = [] + + for asset_detail in asset_details: + asset_name = asset_detail.get('name') + + # Находим депреciацию для актива + depreciation = next( + (dep for dep in asset_depreciation if dep['asset'] == asset_name), + {} + ) + + # Рассчитываем значения по логике стандартного отчета + value_as_on_from_date = flt(asset_detail.get('cost_as_on_from_date', 0)) + value_of_new_purchase = flt(asset_detail.get('cost_of_new_purchase', 0)) + + value_as_on_to_date = ( + value_as_on_from_date + + value_of_new_purchase - + flt(asset_detail.get('cost_of_sold_asset', 0)) - + flt(asset_detail.get('cost_of_scrapped_asset', 0)) + ) + + accumulated_depreciation_as_on_from_date = flt(depreciation.get('accumulated_depreciation_as_on_from_date', 0)) + + accumulated_depreciation_as_on_to_date = ( + accumulated_depreciation_as_on_from_date + + flt(depreciation.get('depreciation_amount_during_the_period', 0)) - + flt(depreciation.get('depreciation_eliminated_during_the_period', 0)) + ) + + net_asset_value_as_on_to_date = value_as_on_to_date - accumulated_depreciation_as_on_to_date + + result.append({ + 'asset': asset_name, + 'value_of_new_purchase': value_of_new_purchase, + 'net_asset_value_as_on_to_date': net_asset_value_as_on_to_date + }) + + return result + + +def get_asset_details_for_taxable(filters, asset_names, version_info): + """Получает детали активов (совместимо со старой и новой версией)""" + asset_placeholders = ", ".join(["%s"] * len(asset_names)) - - # Используем ту же логику что в стандартном отчете для расчета остатков - query = f""" - SELECT - a.name as asset, - IFNULL(SUM(CASE WHEN a.purchase_date < %s THEN - CASE WHEN IFNULL(a.disposal_date, 0) = 0 OR a.disposal_date >= %s THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_as_on_from_date, - - IFNULL(SUM(CASE WHEN a.purchase_date >= %s THEN - a.gross_purchase_amount - ELSE - 0 - END), 0) as value_of_new_purchase, - - IFNULL(SUM(CASE WHEN IFNULL(a.disposal_date, 0) != 0 - AND a.disposal_date >= %s - AND a.disposal_date <= %s THEN - CASE WHEN a.status = "Sold" THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_of_sold_asset, - - IFNULL(SUM(CASE WHEN IFNULL(a.disposal_date, 0) != 0 - AND a.disposal_date >= %s - AND a.disposal_date <= %s THEN - CASE WHEN a.status = "Scrapped" THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_of_scrapped_asset, - - IFNULL(SUM(CASE WHEN IFNULL(a.disposal_date, 0) != 0 - AND a.disposal_date >= %s - AND a.disposal_date <= %s THEN - CASE WHEN a.status = "Capitalized" THEN - a.gross_purchase_amount - ELSE - 0 - END - ELSE - 0 - END), 0) as value_of_capitalized_asset - FROM - `tabAsset` a - WHERE - a.docstatus = 1 - AND a.company = %s - AND a.purchase_date <= %s - AND a.name IN ({asset_placeholders}) - AND NOT EXISTS( - SELECT 1 FROM `tabAsset Capitalization Asset Item` acai - JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name - WHERE acai.asset = a.name - AND ac.posting_date < %s - AND ac.docstatus = 1 + purchase_amount_field = version_info["purchase_amount_field"] + + # Базовый запрос без капитализации + capitalization_check = "" + if version_info["has_capitalization"]: + capitalization_check = """ + and not exists( + select 1 from `tabAsset Capitalization Asset Item` acai + join `tabAsset Capitalization` ac on acai.parent=ac.name + where acai.asset = a.name + and ac.posting_date < %s + and ac.docstatus=1 ) - GROUP BY a.name + """ + + query = f""" + SELECT a.name, + ifnull(sum(case when a.purchase_date < %s then + case when ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %s then + a.{purchase_amount_field} + else + 0 + end + else + 0 + end), 0) as cost_as_on_from_date, + ifnull(sum(case when a.purchase_date >= %s then + a.{purchase_amount_field} + else + 0 + end), 0) as cost_of_new_purchase, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 + and a.disposal_date >= %s + and a.disposal_date <= %s then + case when a.status = "Sold" then + a.{purchase_amount_field} + else + 0 + end + else + 0 + end), 0) as cost_of_sold_asset, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 + and a.disposal_date >= %s + and a.disposal_date <= %s then + case when a.status = "Scrapped" then + a.{purchase_amount_field} + else + 0 + end + else + 0 + end), 0) as cost_of_scrapped_asset + from `tabAsset` a + where a.docstatus=1 and a.company=%s and a.purchase_date <= %s + and a.name IN ({asset_placeholders}) + {capitalization_check} + group by a.name """ - + values = [ - filters.get("from_date"), # value_as_on_from_date condition 1 - filters.get("from_date"), # value_as_on_from_date condition 2 - filters.get("from_date"), # value_of_new_purchase - filters.get("from_date"), # value_of_sold_asset condition 1 - filters.get("to_date"), # value_of_sold_asset condition 2 - filters.get("from_date"), # value_of_scrapped_asset condition 1 - filters.get("to_date"), # value_of_scrapped_asset condition 2 - filters.get("from_date"), # value_of_capitalized_asset condition 1 - filters.get("to_date"), # value_of_capitalized_asset condition 2 + filters.get("from_date"), # cost_as_on_from_date condition 1 + filters.get("from_date"), # cost_as_on_from_date condition 2 + filters.get("from_date"), # cost_of_new_purchase + filters.get("from_date"), # cost_of_sold_asset condition 1 + filters.get("to_date"), # cost_of_sold_asset condition 2 + filters.get("from_date"), # cost_of_scrapped_asset condition 1 + filters.get("to_date"), # cost_of_scrapped_asset condition 2 filters.get("company"), # company filter filters.get("to_date"), # purchase_date filter *asset_names, # asset names for IN clause - filters.get("from_date") # capitalization exclusion ] - + + # Добавляем значение для капитализации если нужно + if version_info["has_capitalization"]: + values.append(filters.get("from_date")) + + return frappe.db.sql(query, values, as_dict=True) + + +def get_asset_depreciation_for_taxable(filters, asset_names): + """Получает депреciацию активов (совместимо со старой и новой версией)""" + + asset_placeholders = ", ".join(["%s"] * len(asset_names)) + + query = f""" + SELECT results.name as asset, + sum(results.accumulated_depreciation_as_on_from_date) as accumulated_depreciation_as_on_from_date, + sum(results.depreciation_eliminated_during_the_period) as depreciation_eliminated_during_the_period, + sum(results.depreciation_amount_during_the_period) as depreciation_amount_during_the_period + from (SELECT a.name as name, + ifnull(sum(case when gle.posting_date < %s and (ifnull(a.disposal_date, 0) = 0 or a.disposal_date >= %s) then + gle.debit + else + 0 + end), 0) as accumulated_depreciation_as_on_from_date, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and a.disposal_date >= %s + and a.disposal_date <= %s and gle.posting_date <= a.disposal_date then + gle.debit + else + 0 + end), 0) as depreciation_eliminated_during_the_period, + ifnull(sum(case when gle.posting_date >= %s and gle.posting_date <= %s + and (ifnull(a.disposal_date, 0) = 0 or gle.posting_date <= a.disposal_date) then + gle.debit + else + 0 + end), 0) as depreciation_amount_during_the_period + from `tabGL Entry` gle + join `tabAsset` a on + gle.against_voucher = a.name + join `tabAsset Category Account` aca on + aca.parent = a.asset_category and aca.company_name = %s + join `tabCompany` company on + company.name = %s + where + a.docstatus=1 + and a.company=%s + and a.purchase_date <= %s + and gle.debit != 0 + and gle.is_cancelled = 0 + and gle.account = ifnull(aca.depreciation_expense_account, company.depreciation_expense_account) + and a.name IN ({asset_placeholders}) + group by a.name + union + SELECT a.name as name, + ifnull(sum(case when ifnull(a.disposal_date, 0) != 0 and (a.disposal_date < %s or a.disposal_date > %s) then + 0 + else + a.opening_accumulated_depreciation + end), 0) as accumulated_depreciation_as_on_from_date, + ifnull(sum(case when a.disposal_date >= %s and a.disposal_date <= %s then + a.opening_accumulated_depreciation + else + 0 + end), 0) as depreciation_eliminated_during_the_period, + 0 as depreciation_amount_during_the_period + from `tabAsset` a + where a.docstatus=1 and a.company=%s and a.purchase_date <= %s + and a.name IN ({asset_placeholders}) + group by a.name) as results + group by results.name + """ + + values = [ + filters.get("from_date"), # accumulated_depreciation_as_on_from_date condition 1 + filters.get("from_date"), # accumulated_depreciation_as_on_from_date condition 2 + filters.get("from_date"), # depreciation_eliminated_during_the_period condition 1 + filters.get("to_date"), # depreciation_eliminated_during_the_period condition 2 + filters.get("from_date"), # depreciation_amount_during_the_period condition 1 + filters.get("to_date"), # depreciation_amount_during_the_period condition 2 + filters.get("company"), # aca.company_name + filters.get("company"), # company.name + filters.get("company"), # a.company + filters.get("to_date"), # a.purchase_date + *asset_names, # asset names for IN clause (first union) + filters.get("from_date"), # disposal_date condition (second union) + filters.get("to_date"), # disposal_date condition (second union) + filters.get("from_date"), # disposal_date condition (second union) + filters.get("to_date"), # disposal_date condition (second union) + filters.get("company"), # a.company (second union) + filters.get("to_date"), # a.purchase_date (second union) + *asset_names # asset names for IN clause (second union) + ] + return frappe.db.sql(query, values, as_dict=True)