jey_erp/jey_erp/asset.py

302 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import frappe
import json
import os
@frappe.whitelist()
def get_tax_exempt_articles(doctype, txt, searchfield, start, page_len, filters):
"""Возвращает список налоговых статей для tax exempt assets"""
# Ключевые части названий для поиска
allowed_patterns = [
'199.1',
'199.4.1',
'199.4.2',
'199.4.3',
'199.4.4',
'199.5',
'199.7',
'199.8',
'199.9',
'199.11',
'199.14',
'199.15',
'199.16',
'199.17',
'199.18',
'199.19',
'199.20',
'227.1',
'Qanunla təsdiq olunmuş hasilatın pay bölgüsü',
'Xüsusi iqtisadi zonalar',
'Azərbaycan Respublikasının tərəfdar çıxdığı beynəlxalq müqavilələr'
]
# Строим условие для поиска
conditions = []
for pattern in allowed_patterns:
conditions.append(f"name LIKE '%{pattern}%'")
# Добавляем поисковый текст если есть
where_clause = f"({' OR '.join(conditions)})"
if txt:
where_clause += f" AND name LIKE '%{txt}%'"
# Выполняем запрос
result = frappe.db.sql(f"""
SELECT name
FROM `tabTax Article`
WHERE {where_clause}
ORDER BY name
LIMIT {start}, {page_len}
""")
return result
@frappe.whitelist()
def get_land_tax_articles(doctype, txt, searchfield, start, page_len, filters):
"""Возвращает список налоговых статей для земельных участков"""
# Ключевые части названий для поиска земельных участков
allowed_patterns = [
'Vergi Məcəlləsinin 207.3-cü maddəsinə əsasən',
'Vergi Məcəlləsinin 207.4-cü maddəsinə əsasən',
'Vergi Məcəlləsinin 207.5-ci maddəsinə əsasən',
'Vergi Məcəlləsinin 207.6-cı maddəsinə əsasən',
'Vergi Məcəlləsinin 207.7-ci maddəsinə əsasən',
'Vergi Məcəlləsinin 207.8-ci maddəsinə əsasən',
'Vergi Məcəlləsinin 207.9-cu maddəsinə əsasən',
'Vergi Məcəlləsinin 207.10-cu maddəsinə əsasən',
'Vergi Məcəlləsinin 207.11-ci maddəsinə əsasən',
'Vergi məcəlləsinin 207.12-ci maddəsinə əsasən',
'Vergi Məcəlləsinin 227.1-ci maddəsinə əsasən'
]
# Строим условие для поиска
conditions = []
for pattern in allowed_patterns:
conditions.append(f"name LIKE '%{pattern}%'")
# Добавляем поисковый текст если есть
where_clause = f"({' OR '.join(conditions)})"
if txt:
where_clause += f" AND name LIKE '%{txt}%'"
# Выполняем запрос
result = frappe.db.sql(f"""
SELECT name
FROM `tabTax Article`
WHERE {where_clause}
ORDER BY name
LIMIT {start}, {page_len}
""")
return result
# ===============================
# СЕЛЬСКОХОЗЯЙСТВЕННЫЕ ЗЕМЛИ
# ===============================
@frappe.whitelist()
def calculate_gross_purchase_amount(hectare, cadastral_district_name, quality_groups, agricultural_land_purpose):
"""
Рассчитывает Gross Purchase Amount для сельскохозяйственных земель
Формула: hectare × балл × наценка
"""
try:
# Валидация входных данных
if not hectare or not cadastral_district_name or not quality_groups or not agricultural_land_purpose:
frappe.throw("Не все поля заполнены для расчета")
# Получаем балл из JSON файла
score = get_cadastral_score(cadastral_district_name, quality_groups)
# Определяем наценку
markup = get_markup_coefficient(agricultural_land_purpose)
# Расчет по формуле
result = float(hectare) * score * markup
return {
'gross_purchase_amount': result,
'calculation_details': {
'hectare': float(hectare),
'score': score,
'markup': markup,
'formula': f"{hectare} × {score} × {markup} = {result}"
}
}
except Exception as e:
frappe.throw(f"Ошибка при расчете: {str(e)}")
def get_cadastral_score(cadastral_district_name, quality_group):
"""
Извлекает балл из JSON файла на основе названия кадастрового района и группы качества
"""
try:
# Путь к JSON файлу
json_file_path = frappe.get_app_path('jey_erp', 'data', 'cadastral_points_data.json')
# Читаем JSON файл
with open(json_file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
# Поиск соответствующего региона
for region in data.get('cadastral_regions', []):
if region.get('region_name') == cadastral_district_name:
# Получаем балл для указанной группы качества
quality_groups = region.get('quality_groups', {})
score = quality_groups.get(quality_group)
# Если балл null или не найден, возвращаем 0
return score if score is not None else 0
# Если регион не найден
frappe.throw(f"Кадастровый район '{cadastral_district_name}' не найден в базе данных")
except FileNotFoundError:
frappe.throw("Файл с кадастровыми данными не найден. Обратитесь к администратору системы")
except json.JSONDecodeError:
frappe.throw("Ошибка чтения файла с кадастровыми данными")
except Exception as e:
frappe.throw(f"Ошибка при получении кадастрового балла: {str(e)}")
def get_markup_coefficient(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
}
coefficient = markup_map.get(agricultural_land_purpose)
if coefficient is None:
frappe.throw(f"Неизвестный тип назначения земли: {agricultural_land_purpose}")
return coefficient
# ===============================
# ПРОМЫШЛЕННЫЕ/КОММЕРЧЕСКИЕ ЗЕМЛИ
# ===============================
@frappe.whitelist()
def calculate_industrial_gross_purchase_amount(hectare, territorial_unit_name, industrial_land_purpose):
"""
Рассчитывает Gross Purchase Amount для промышленных земель
Формула: (площадь_в_м² ÷ 100) × балл (прогрессивная система)
"""
try:
# Валидация входных данных
if not hectare or not territorial_unit_name or not industrial_land_purpose:
frappe.throw("Не все поля заполнены для расчета")
# Используем значение как есть - это квадратные метры
area_sqm = float(hectare)
# Получаем баллы из JSON файла
score_data = get_industrial_land_scores(territorial_unit_name, industrial_land_purpose)
# Рассчитываем по прогрессивной формуле
calculation_result = calculate_industrial_land_formula(area_sqm, score_data)
return {
'gross_purchase_amount': calculation_result['total'],
'calculation_details': calculation_result
}
except Exception as e:
frappe.throw(f"Ошибка при расчете: {str(e)}")
def get_industrial_land_scores(territorial_unit_name, industrial_land_purpose):
"""
Извлекает баллы из JSON файла для промышленных земель
"""
try:
# Путь к JSON файлу
json_file_path = frappe.get_app_path('jey_erp', 'data', 'industrial_land_data.json')
# Читаем JSON файл
with open(json_file_path, 'r', encoding='utf-8') as file:
data = json.load(file)
# Поиск соответствующего региона
for region in data.get('industrial_land_regions', []):
if region.get('settlement_name') == territorial_unit_name:
# Получаем баллы для указанного назначения земли
land_purpose_rates = region.get('land_purpose_rates', {})
purpose_rates = land_purpose_rates.get(industrial_land_purpose)
if purpose_rates:
return {
'up_to_10000': purpose_rates.get('up_to_10000_sqm', 0),
'above_10000': purpose_rates.get('above_10000_sqm', 0)
}
# Если регион или назначение не найдено
frappe.throw(f"Не найдены данные для территории '{territorial_unit_name}' и назначения '{industrial_land_purpose}'")
except FileNotFoundError:
frappe.throw("Файл с данными промышленных земель не найден. Обратитесь к администратору системы")
except json.JSONDecodeError:
frappe.throw("Ошибка чтения файла с данными промышленных земель")
except Exception as e:
frappe.throw(f"Ошибка при получении баллов промышленной земли: {str(e)}")
def calculate_industrial_land_formula(area_sqm, score_data):
"""
Рассчитывает стоимость по прогрессивной формуле для промышленных земель
"""
up_to_10000_score = score_data['up_to_10000']
above_10000_score = score_data['above_10000']
calculation_parts = []
total = 0
if area_sqm <= 10000:
# Вся площадь до 10000 м²
part_result = (area_sqm / 100) * up_to_10000_score
total = part_result
calculation_parts.append({
'area': area_sqm,
'score': up_to_10000_score,
'formula': f"{area_sqm} ÷ 100 × {up_to_10000_score} = {part_result}",
'result': part_result
})
formula_text = f"{area_sqm} ÷ 100 × {up_to_10000_score} = {total}"
else:
# Прогрессивная система: до 10000 м² + свыше 10000 м²
# Первые 10000 м²
part1_result = (10000 / 100) * up_to_10000_score
calculation_parts.append({
'area': 10000,
'score': up_to_10000_score,
'formula': f"10000 ÷ 100 × {up_to_10000_score} = {part1_result}",
'result': part1_result
})
# Оставшаяся площадь свыше 10000 м²
remaining_area = area_sqm - 10000
part2_result = (remaining_area / 100) * above_10000_score
calculation_parts.append({
'area': remaining_area,
'score': above_10000_score,
'formula': f"{remaining_area} ÷ 100 × {above_10000_score} = {part2_result}",
'result': part2_result
})
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}"
return {
'total': total,
'area_sqm': area_sqm,
'formula': formula_text,
'calculation_parts': calculation_parts,
'scores_used': score_data
}