diff --git a/jey_erp/custom/create_asset_categories.py b/jey_erp/custom/create_asset_categories.py index c0c892e..04604d3 100644 --- a/jey_erp/custom/create_asset_categories.py +++ b/jey_erp/custom/create_asset_categories.py @@ -21,82 +21,26 @@ def get_system_asset_categories(): def create_asset_categories(): """ - Создает категории активов с настройками счетов + УСТАРЕЛО: Функция оставлена для обратной совместимости. + Новые установки используют хук setup_wizard_complete. + + Создает категории активов для первой компании в системе. """ - # Проверка существования таблицы Company if not frappe.db.table_exists("Company"): frappe.log_error("Company table not found", "Asset Categories Patch") return - + # Получаем первую компанию company = frappe.get_all("Company", limit=1) if not company: frappe.log_error("No company found in the system", "Asset Categories Patch") return - + company_name = company[0].name - # Получаем список системных категорий - asset_categories = get_system_asset_categories() - - # Находим нужные счета - try: - accumulated_depreciation = get_account_by_name( - "Tikililər üzrə yığılmış amortizasiya", - company_name - ) - depreciation_expense = get_account_by_name( - "Amortizasiya xərci", - company_name - ) - fixed_asset = get_account_by_name( - "Digər uzunmüddətli aktivlər", - company_name - ) - except Exception as e: - frappe.log_error(f"Required accounts not found: {str(e)}", "Asset Categories Patch") - return - - # Создаем категории активов - created_count = 0 - skipped_count = 0 - - for category_name in asset_categories: - try: - if not frappe.db.exists("Asset Category", category_name): - asset_category = frappe.new_doc("Asset Category") - asset_category.asset_category_name = category_name - asset_category.enable_cwip_accounting = 0 - - # Добавляем accounts - asset_category.append("accounts", { - "company_name": company_name, - "fixed_asset_account": fixed_asset, - "accumulated_depreciation_account": accumulated_depreciation, - "depreciation_expense_account": depreciation_expense, - "capital_work_in_progress_account": "" - }) - - asset_category.insert(ignore_permissions=True) - created_count += 1 - - frappe.msgprint(f"Created Asset Category: {category_name}") - else: - skipped_count += 1 - except Exception as e: - frappe.log_error( - f"Failed to create Asset Category '{category_name}': {str(e)}", - "Asset Categories Patch" - ) - - # Коммитим все изменения разом - frappe.db.commit() - - # Выводим итоговую информацию - message = f"Asset Categories Patch completed. Created: {created_count}, Skipped: {skipped_count}" - print(message) - frappe.msgprint(message) + # Используем новую функцию + _create_categories_for_company(company_name) def get_account_by_name(account_name, company): @@ -116,6 +60,112 @@ def get_account_by_name(account_name, company): return account +def create_asset_categories_for_company(company_name): + """ + Создает категории активов для конкретной компании. + Вызывается как фоновая задача после setup wizard. + + Args: + company_name: Название компании + """ + try: + # Проверяем, что компания существует + if not frappe.db.exists("Company", company_name): + frappe.log_error( + f"Company '{company_name}' not found", + "Asset Categories Creation" + ) + return + + # Проверка идемпотентности: если категории уже есть, не создаем + system_categories = get_system_asset_categories() + existing_categories = frappe.db.count( + "Asset Category", + filters={"asset_category_name": ["in", system_categories]} + ) + + if existing_categories > 0: + frappe.log_error( + f"Asset categories already exist ({existing_categories} found). Skipping creation.", + "Asset Categories Creation - Info" + ) + return + + # Создаем категории + _create_categories_for_company(company_name) + + except Exception as e: + # Не пробрасываем исключение - это фоновая задача + frappe.log_error( + f"Failed to create asset categories for {company_name}: {str(e)}", + "Asset Categories Creation - Error" + ) + + +def _create_categories_for_company(company_name): + """ + Внутренняя функция для создания категорий активов. + Извлечена из create_asset_categories для переиспользования. + """ + asset_categories = get_system_asset_categories() + + # Находим нужные счета + try: + accumulated_depreciation = get_account_by_name( + "Tikililər üzrə yığılmış amortizasiya", + company_name + ) + depreciation_expense = get_account_by_name( + "Amortizasiya xərci", + company_name + ) + fixed_asset = get_account_by_name( + "Digər uzunmüddətli aktivlər", + company_name + ) + except Exception as e: + frappe.log_error( + f"Required accounts not found for {company_name}: {str(e)}", + "Asset Categories Creation - Error" + ) + return + + # Создаем категории + created_count = 0 + skipped_count = 0 + + for category_name in asset_categories: + try: + if not frappe.db.exists("Asset Category", category_name): + asset_category = frappe.new_doc("Asset Category") + asset_category.asset_category_name = category_name + asset_category.enable_cwip_accounting = 0 + + asset_category.append("accounts", { + "company_name": company_name, + "fixed_asset_account": fixed_asset, + "accumulated_depreciation_account": accumulated_depreciation, + "depreciation_expense_account": depreciation_expense, + "capital_work_in_progress_account": "" + }) + + asset_category.insert(ignore_permissions=True) + created_count += 1 + else: + skipped_count += 1 + except Exception as e: + frappe.log_error( + f"Failed to create Asset Category '{category_name}': {str(e)}", + "Asset Categories Creation - Error" + ) + + frappe.db.commit() + + message = f"Asset Categories created for {company_name}. Created: {created_count}, Skipped: {skipped_count}" + frappe.log_error(message, "Asset Categories Creation - Success") + print(message) + + def prevent_delete_system_asset_categories(doc, method): """ Запрещает удаление системных категорий активов diff --git a/jey_erp/hooks.py b/jey_erp/hooks.py index a92acee..22442a2 100644 --- a/jey_erp/hooks.py +++ b/jey_erp/hooks.py @@ -54,6 +54,11 @@ doc_events = { } } +# Setup Wizard +# ------------ + +setup_wizard_complete = "jey_erp.setup.setup_wizard_handler.setup_wizard_complete_handler" + after_migrate = "jey_erp.hooks.after_migrate_combined" def after_migrate_combined(): @@ -64,10 +69,12 @@ def after_migrate_combined(): show_item_tax_template_in_sales_invoice() from jey_erp.custom.vat_calculations import patch_sales_documents patch_sales_documents() - from jey_erp.custom.create_asset_categories import create_asset_categories - create_asset_categories() + # REMOVED: Asset categories creation moved to setup_wizard_complete hook + # from jey_erp.custom.create_asset_categories import create_asset_categories + # create_asset_categories() -after_install = "jey_erp.custom.create_asset_categories.create_asset_categories" +# REMOVED: Asset categories creation moved to setup_wizard_complete hook +# after_install = "jey_erp.custom.create_asset_categories.create_asset_categories" fixtures = [ { diff --git a/jey_erp/patches.txt b/jey_erp/patches.txt index f15c3a9..419bef0 100644 --- a/jey_erp/patches.txt +++ b/jey_erp/patches.txt @@ -3,4 +3,5 @@ # Read docs to understand patches: https://frappeframework.com/docs/v14/user/en/database-migrations [post_model_sync] -# Patches added in this section will be executed after doctypes are migrated \ No newline at end of file +# Patches added in this section will be executed after doctypes are migrated +jey_erp.patches.create_asset_categories_post_migration \ No newline at end of file diff --git a/jey_erp/patches/create_asset_categories_post_migration.py b/jey_erp/patches/create_asset_categories_post_migration.py new file mode 100644 index 0000000..3dfacb5 --- /dev/null +++ b/jey_erp/patches/create_asset_categories_post_migration.py @@ -0,0 +1,36 @@ +import frappe + + +def execute(): + """ + Патч для создания категорий активов на существующих установках. + Выполняется при bench migrate после обновления кода. + """ + # Проверяем, что патч не был уже выполнен + system_categories = [ + "Binalar, tikililər və qurğular", + "Maşınlar və avadanlıqlar", + "Yüksək texnologiyalar məhsulu olan hesablama texnikası", + "Nəqliyyat vasitələri", + "Digər əsas vəsaitlər", + "Düzən torpaqlar", + "Dağ torpaqlar", + "Orta və yüksək dağ torpaqlar", + "Şəhərin mövcud hüdudundan kənarda olan kənd təsərrüfatı təyinatlı torpaqlar", + "Sənaye, tikinti, nəqliyyat, rabitə, ticarət-məişət xidməti və digər xüsusi təyinatlı torpaq sahələri" + ] + + # Если хотя бы одна категория существует, считаем что патч уже выполнен + if frappe.db.exists("Asset Category", {"asset_category_name": system_categories[0]}): + return + + # Проверяем, что компания существует + companies = frappe.get_all("Company", limit=1) + if not companies: + return # Нет компании - патч не нужен + + company_name = companies[0].name + + # Импортируем и запускаем создание + from jey_erp.custom.create_asset_categories import create_asset_categories_for_company + create_asset_categories_for_company(company_name) diff --git a/jey_erp/setup/__init__.py b/jey_erp/setup/__init__.py new file mode 100644 index 0000000..de76b0a --- /dev/null +++ b/jey_erp/setup/__init__.py @@ -0,0 +1 @@ +# Empty file to make this a Python package diff --git a/jey_erp/setup/setup_wizard_handler.py b/jey_erp/setup/setup_wizard_handler.py new file mode 100644 index 0000000..836c311 --- /dev/null +++ b/jey_erp/setup/setup_wizard_handler.py @@ -0,0 +1,43 @@ +import frappe + + +def setup_wizard_complete_handler(args): + """ + Вызывается после завершения ERPNext setup wizard. + Ставит в очередь фоновую задачу для создания категорий активов. + + Args: + args: Словарь с параметрами визарда, включая: + - company_name: Название созданной компании + - country: Выбранная страна + - currency: Валюта по умолчанию + """ + company_name = args.get("company_name") + + if not company_name: + # Fallback: получаем первую компанию + companies = frappe.get_all("Company", limit=1) + if companies: + company_name = companies[0].name + else: + frappe.log_error( + "Company name not found in setup wizard args and no companies exist", + "Asset Categories Setup" + ) + return + + # Ставим в очередь фоновую задачу (некритично, не блокирует визард) + frappe.enqueue( + "jey_erp.custom.create_asset_categories.create_asset_categories_for_company", + queue="default", + timeout=300, + enqueue_after_commit=True, + at_front=False, # Некритично, может подождать + company_name=company_name + ) + + frappe.msgprint( + f"Категории активов будут созданы в фоновом режиме для {company_name}", + title="Настройка выполняется", + indicator="blue" + )