fixed 2 other reports
This commit is contained in:
parent
ff5140a8c5
commit
0335d577c7
|
|
@ -24,8 +24,8 @@ def get_data(filters):
|
||||||
if not assets_data:
|
if not assets_data:
|
||||||
return []
|
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 = []
|
data = []
|
||||||
|
|
@ -41,21 +41,10 @@ def get_data(filters):
|
||||||
|
|
||||||
# Находим баланс для этого актива
|
# Находим баланс для этого актива
|
||||||
asset_balance = next((bal for bal in asset_balances if bal['asset'] == asset['name']), {})
|
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_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))
|
net_asset_value_as_on_to_date = flt(asset_balance.get('net_asset_value_as_on_to_date', 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
|
|
||||||
)
|
|
||||||
|
|
||||||
# Инициализируем все колонки нулями
|
# Инициализируем все колонки нулями
|
||||||
for article in tax_exempt_articles:
|
for article in tax_exempt_articles:
|
||||||
|
|
@ -68,7 +57,7 @@ def get_data(filters):
|
||||||
if asset['tax_exempt_tax_article']:
|
if asset['tax_exempt_tax_article']:
|
||||||
article_key = get_field_key(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_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
|
row[f"{article_key}_insured"] = row.insured_value
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
@ -158,12 +147,27 @@ def get_field_key(tax_article):
|
||||||
return "article_other"
|
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):
|
def get_establishment_year_tax_exempt_assets(filters, tax_exempt_articles):
|
||||||
"""Получает активы с tax exempt статьями ТОЛЬКО года создания компании"""
|
"""Получает активы с tax exempt статьями ТОЛЬКО года создания компании"""
|
||||||
|
|
||||||
|
version_info = check_erpnext_version()
|
||||||
|
|
||||||
conditions = []
|
conditions = []
|
||||||
values = []
|
values = []
|
||||||
|
|
||||||
# Фильтр по компании
|
# Фильтр по компании
|
||||||
if filters.get("company"):
|
if filters.get("company"):
|
||||||
conditions.append("a.company = %s")
|
conditions.append("a.company = %s")
|
||||||
|
|
@ -188,19 +192,20 @@ def get_establishment_year_tax_exempt_assets(filters, tax_exempt_articles):
|
||||||
where_clause = ""
|
where_clause = ""
|
||||||
if conditions:
|
if conditions:
|
||||||
where_clause = "WHERE " + " AND ".join(conditions)
|
where_clause = "WHERE " + " AND ".join(conditions)
|
||||||
|
|
||||||
# Исключаем капитализированные активы (как в стандартном отчете)
|
# Исключаем капитализированные активы только если есть поддержка
|
||||||
exclude_capitalized = """
|
if version_info["has_capitalization"]:
|
||||||
AND NOT EXISTS(
|
exclude_capitalized = """
|
||||||
SELECT 1 FROM `tabAsset Capitalization Asset Item` acai
|
AND NOT EXISTS(
|
||||||
JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name
|
SELECT 1 FROM `tabAsset Capitalization Asset Item` acai
|
||||||
WHERE acai.asset = a.name
|
JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name
|
||||||
AND ac.posting_date < %s
|
WHERE acai.asset = a.name
|
||||||
AND ac.docstatus = 1
|
AND ac.posting_date < %s
|
||||||
)
|
AND ac.docstatus = 1
|
||||||
"""
|
)
|
||||||
where_clause += exclude_capitalized
|
"""
|
||||||
values.append(filters.get("from_date"))
|
where_clause += exclude_capitalized
|
||||||
|
values.append(filters.get("from_date"))
|
||||||
|
|
||||||
query = f"""
|
query = f"""
|
||||||
SELECT
|
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)
|
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:
|
if not asset_names:
|
||||||
return []
|
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))
|
asset_placeholders = ", ".join(["%s"] * len(asset_names))
|
||||||
|
purchase_amount_field = version_info["purchase_amount_field"]
|
||||||
# Используем ту же логику что в стандартном отчете для расчета остатков
|
|
||||||
query = f"""
|
# Базовый запрос без капитализации
|
||||||
SELECT
|
capitalization_check = ""
|
||||||
a.name as asset,
|
if version_info["has_capitalization"]:
|
||||||
IFNULL(SUM(CASE WHEN a.purchase_date < %s THEN
|
capitalization_check = """
|
||||||
CASE WHEN IFNULL(a.disposal_date, 0) = 0 OR a.disposal_date >= %s THEN
|
and not exists(
|
||||||
a.gross_purchase_amount
|
select 1 from `tabAsset Capitalization Asset Item` acai
|
||||||
ELSE
|
join `tabAsset Capitalization` ac on acai.parent=ac.name
|
||||||
0
|
where acai.asset = a.name
|
||||||
END
|
and ac.posting_date < %s
|
||||||
ELSE
|
and ac.docstatus=1
|
||||||
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
|
|
||||||
)
|
)
|
||||||
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 = [
|
values = [
|
||||||
filters.get("from_date"), # value_as_on_from_date condition 1
|
filters.get("from_date"), # cost_as_on_from_date condition 1
|
||||||
filters.get("from_date"), # value_as_on_from_date condition 2
|
filters.get("from_date"), # cost_as_on_from_date condition 2
|
||||||
filters.get("from_date"), # value_of_new_purchase
|
filters.get("from_date"), # cost_of_new_purchase
|
||||||
filters.get("from_date"), # value_of_sold_asset condition 1
|
filters.get("from_date"), # cost_of_sold_asset condition 1
|
||||||
filters.get("to_date"), # value_of_sold_asset condition 2
|
filters.get("to_date"), # cost_of_sold_asset condition 2
|
||||||
filters.get("from_date"), # value_of_scrapped_asset condition 1
|
filters.get("from_date"), # cost_of_scrapped_asset condition 1
|
||||||
filters.get("to_date"), # value_of_scrapped_asset condition 2
|
filters.get("to_date"), # cost_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("company"), # company filter
|
filters.get("company"), # company filter
|
||||||
filters.get("to_date"), # purchase_date filter
|
filters.get("to_date"), # purchase_date filter
|
||||||
*asset_names, # asset names for IN clause
|
*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)
|
return frappe.db.sql(query, values, as_dict=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ def get_data(filters):
|
||||||
if not assets_data:
|
if not assets_data:
|
||||||
return []
|
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 = []
|
data = []
|
||||||
|
|
@ -41,21 +41,10 @@ def get_data(filters):
|
||||||
|
|
||||||
# Находим баланс для этого актива
|
# Находим баланс для этого актива
|
||||||
asset_balance = next((bal for bal in asset_balances if bal['asset'] == asset['name']), {})
|
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_new_purchase = flt(asset_balance.get('value_of_new_purchase', 0))
|
||||||
value_of_sold_asset = flt(asset_balance.get('value_of_sold_asset', 0))
|
net_asset_value_as_on_to_date = flt(asset_balance.get('net_asset_value_as_on_to_date', 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
|
|
||||||
)
|
|
||||||
|
|
||||||
# Инициализируем все колонки нулями
|
# Инициализируем все колонки нулями
|
||||||
for asset_type in taxable_asset_types:
|
for asset_type in taxable_asset_types:
|
||||||
|
|
@ -67,8 +56,8 @@ def get_data(filters):
|
||||||
# Заполняем колонки для соответствующего типа актива
|
# Заполняем колонки для соответствующего типа актива
|
||||||
if asset['taxable_asset_type']:
|
if asset['taxable_asset_type']:
|
||||||
asset_type_key = get_field_key(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_from"] = value_of_new_purchase
|
||||||
row[f"{asset_type_key}_value_to"] = value_as_on_to_date
|
row[f"{asset_type_key}_value_to"] = net_asset_value_as_on_to_date
|
||||||
row[f"{asset_type_key}_insured"] = row.insured_value
|
row[f"{asset_type_key}_insured"] = row.insured_value
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
@ -126,12 +115,27 @@ def get_field_key(asset_type):
|
||||||
return "other_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):
|
def get_taxable_assets(filters, taxable_asset_types):
|
||||||
"""Получает активы с типом 'Vergiyə cəlb olunan əsas vəsaitlər' исключая активы года создания компании"""
|
"""Получает активы с типом 'Vergiyə cəlb olunan əsas vəsaitlər' исключая активы года создания компании"""
|
||||||
|
|
||||||
|
version_info = check_erpnext_version()
|
||||||
|
|
||||||
conditions = []
|
conditions = []
|
||||||
values = []
|
values = []
|
||||||
|
|
||||||
# Фильтр по компании
|
# Фильтр по компании
|
||||||
if filters.get("company"):
|
if filters.get("company"):
|
||||||
conditions.append("a.company = %s")
|
conditions.append("a.company = %s")
|
||||||
|
|
@ -160,19 +164,20 @@ def get_taxable_assets(filters, taxable_asset_types):
|
||||||
where_clause = ""
|
where_clause = ""
|
||||||
if conditions:
|
if conditions:
|
||||||
where_clause = "WHERE " + " AND ".join(conditions)
|
where_clause = "WHERE " + " AND ".join(conditions)
|
||||||
|
|
||||||
# Исключаем капитализированные активы (как в стандартном отчете)
|
# Исключаем капитализированные активы только если есть поддержка
|
||||||
exclude_capitalized = """
|
if version_info["has_capitalization"]:
|
||||||
AND NOT EXISTS(
|
exclude_capitalized = """
|
||||||
SELECT 1 FROM `tabAsset Capitalization Asset Item` acai
|
AND NOT EXISTS(
|
||||||
JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name
|
SELECT 1 FROM `tabAsset Capitalization Asset Item` acai
|
||||||
WHERE acai.asset = a.name
|
JOIN `tabAsset Capitalization` ac ON acai.parent = ac.name
|
||||||
AND ac.posting_date < %s
|
WHERE acai.asset = a.name
|
||||||
AND ac.docstatus = 1
|
AND ac.posting_date < %s
|
||||||
)
|
AND ac.docstatus = 1
|
||||||
"""
|
)
|
||||||
where_clause += exclude_capitalized
|
"""
|
||||||
values.append(filters.get("from_date"))
|
where_clause += exclude_capitalized
|
||||||
|
values.append(filters.get("from_date"))
|
||||||
|
|
||||||
query = f"""
|
query = f"""
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -192,102 +197,231 @@ def get_taxable_assets(filters, taxable_asset_types):
|
||||||
return frappe.db.sql(query, values, as_dict=True)
|
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:
|
if not asset_names:
|
||||||
return []
|
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))
|
asset_placeholders = ", ".join(["%s"] * len(asset_names))
|
||||||
|
purchase_amount_field = version_info["purchase_amount_field"]
|
||||||
# Используем ту же логику что в стандартном отчете для расчета остатков
|
|
||||||
query = f"""
|
# Базовый запрос без капитализации
|
||||||
SELECT
|
capitalization_check = ""
|
||||||
a.name as asset,
|
if version_info["has_capitalization"]:
|
||||||
IFNULL(SUM(CASE WHEN a.purchase_date < %s THEN
|
capitalization_check = """
|
||||||
CASE WHEN IFNULL(a.disposal_date, 0) = 0 OR a.disposal_date >= %s THEN
|
and not exists(
|
||||||
a.gross_purchase_amount
|
select 1 from `tabAsset Capitalization Asset Item` acai
|
||||||
ELSE
|
join `tabAsset Capitalization` ac on acai.parent=ac.name
|
||||||
0
|
where acai.asset = a.name
|
||||||
END
|
and ac.posting_date < %s
|
||||||
ELSE
|
and ac.docstatus=1
|
||||||
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
|
|
||||||
)
|
)
|
||||||
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 = [
|
values = [
|
||||||
filters.get("from_date"), # value_as_on_from_date condition 1
|
filters.get("from_date"), # cost_as_on_from_date condition 1
|
||||||
filters.get("from_date"), # value_as_on_from_date condition 2
|
filters.get("from_date"), # cost_as_on_from_date condition 2
|
||||||
filters.get("from_date"), # value_of_new_purchase
|
filters.get("from_date"), # cost_of_new_purchase
|
||||||
filters.get("from_date"), # value_of_sold_asset condition 1
|
filters.get("from_date"), # cost_of_sold_asset condition 1
|
||||||
filters.get("to_date"), # value_of_sold_asset condition 2
|
filters.get("to_date"), # cost_of_sold_asset condition 2
|
||||||
filters.get("from_date"), # value_of_scrapped_asset condition 1
|
filters.get("from_date"), # cost_of_scrapped_asset condition 1
|
||||||
filters.get("to_date"), # value_of_scrapped_asset condition 2
|
filters.get("to_date"), # cost_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("company"), # company filter
|
filters.get("company"), # company filter
|
||||||
filters.get("to_date"), # purchase_date filter
|
filters.get("to_date"), # purchase_date filter
|
||||||
*asset_names, # asset names for IN clause
|
*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)
|
return frappe.db.sql(query, values, as_dict=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue