added item group rename
This commit is contained in:
parent
15e78d19e5
commit
64096d7c5a
|
|
@ -39,6 +39,9 @@ def after_migrate_combined():
|
|||
|
||||
from jey_erp.custom_fields import create_custom_fields
|
||||
create_custom_fields()
|
||||
from jey_erp.overrides.custom_install import rename_item_groups
|
||||
rename_item_groups()
|
||||
|
||||
|
||||
fixtures = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,172 @@
|
|||
import frappe
|
||||
import urllib.parse
|
||||
|
||||
def rename_item_groups():
|
||||
"""
|
||||
Переименовывает группы номенклатур: и названия, и ID на азербайджанский
|
||||
"""
|
||||
|
||||
# Маппинг: старый_ID -> {"new_name": "название", "new_id": "тоже_название"}
|
||||
translation_map = {
|
||||
"All Item Groups": {
|
||||
"new_name": "Bütün Məhsul Qrupları",
|
||||
},
|
||||
"Products": {
|
||||
"new_name": "Məhsullar",
|
||||
},
|
||||
"Raw Material": {
|
||||
"new_name": "Xammal",
|
||||
},
|
||||
"Services": {
|
||||
"new_name": "Xidmətlər",
|
||||
},
|
||||
"Sub Assemblies": {
|
||||
"new_name": "Alt Montajlar",
|
||||
},
|
||||
"Consumable": {
|
||||
"new_name": "İstehlak Malları",
|
||||
}
|
||||
}
|
||||
|
||||
# ID будет точно таким же, как и название (на азербайджанском)
|
||||
for key, value in translation_map.items():
|
||||
new_name = value["new_name"]
|
||||
# ID = название (без URL-encoding)
|
||||
value["new_id"] = new_name
|
||||
|
||||
try:
|
||||
updated_count = 0
|
||||
renamed_count = 0
|
||||
|
||||
frappe.flags.ignore_permissions = True
|
||||
frappe.flags.ignore_links = True
|
||||
frappe.flags.ignore_validate_update_after_submit = True
|
||||
|
||||
# Получаем все группы, отсортированные по иерархии
|
||||
all_groups = frappe.get_all(
|
||||
"Item Group",
|
||||
fields=["name", "item_group_name", "parent_item_group", "lft", "rgt"],
|
||||
order_by="lft" # От корневых к дочерним
|
||||
)
|
||||
|
||||
# Создаем маппинг для обновления родительских ссылок
|
||||
id_mapping = {}
|
||||
groups_to_process = []
|
||||
|
||||
# Собираем информацию о группах для переименования
|
||||
for old_id, translation in translation_map.items():
|
||||
new_name = translation["new_name"]
|
||||
new_id = translation["new_id"]
|
||||
|
||||
# Находим группу по текущему ID
|
||||
existing_group = None
|
||||
for group in all_groups:
|
||||
if group.name == old_id:
|
||||
existing_group = group
|
||||
break
|
||||
|
||||
if existing_group:
|
||||
id_mapping[old_id] = new_id
|
||||
groups_to_process.append({
|
||||
"old_id": old_id,
|
||||
"new_id": new_id,
|
||||
"new_name": new_name,
|
||||
"lft": existing_group.lft,
|
||||
"current_parent": existing_group.parent_item_group
|
||||
})
|
||||
|
||||
# Обрабатываем группы в правильном порядке (от корневых к дочерним)
|
||||
for group_info in sorted(groups_to_process, key=lambda x: x["lft"]):
|
||||
old_id = group_info["old_id"]
|
||||
new_id = group_info["new_id"]
|
||||
new_name = group_info["new_name"]
|
||||
current_parent = group_info["current_parent"]
|
||||
|
||||
# Проверяем, не существует ли уже группа с новым ID
|
||||
if frappe.db.exists("Item Group", new_id):
|
||||
continue
|
||||
|
||||
try:
|
||||
# Обновляем родительскую ссылку если родитель тоже переименовывается
|
||||
updated_parent = current_parent
|
||||
if current_parent and current_parent in id_mapping:
|
||||
updated_parent = id_mapping[current_parent]
|
||||
|
||||
# Сначала обновляем название
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabItem Group`
|
||||
SET item_group_name = %s
|
||||
WHERE name = %s
|
||||
""", (new_name, old_id))
|
||||
|
||||
updated_count += 1
|
||||
|
||||
# Теперь переименовываем ID
|
||||
if old_id != new_id:
|
||||
# Используем низкоуровневые SQL запросы для избежания проверок
|
||||
|
||||
# 1. Обновляем основную запись
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabItem Group`
|
||||
SET name = %s
|
||||
WHERE name = %s
|
||||
""", (new_id, old_id))
|
||||
|
||||
# 2. Обновляем parent_item_group ссылки
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabItem Group`
|
||||
SET parent_item_group = %s
|
||||
WHERE parent_item_group = %s
|
||||
""", (new_id, old_id))
|
||||
|
||||
# 3. Обновляем ссылки в товарах
|
||||
frappe.db.sql("""
|
||||
UPDATE `tabItem`
|
||||
SET item_group = %s
|
||||
WHERE item_group = %s
|
||||
""", (new_id, old_id))
|
||||
|
||||
# 4. Обновляем другие возможные ссылки
|
||||
other_tables = [
|
||||
("tabItem Default", "parent_item_group"),
|
||||
("tabPurchase Invoice Item", "item_group"),
|
||||
("tabSales Invoice Item", "item_group"),
|
||||
("tabDelivery Note Item", "item_group"),
|
||||
("tabPurchase Receipt Item", "item_group")
|
||||
]
|
||||
|
||||
for table, field in other_tables:
|
||||
if frappe.db.has_column(table, field):
|
||||
frappe.db.sql(f"""
|
||||
UPDATE `{table}`
|
||||
SET `{field}` = %s
|
||||
WHERE `{field}` = %s
|
||||
""", (new_id, old_id))
|
||||
|
||||
renamed_count += 1
|
||||
|
||||
except Exception as process_error:
|
||||
continue
|
||||
|
||||
# Сохраняем изменения
|
||||
frappe.db.commit()
|
||||
|
||||
# Очищаем кэш
|
||||
frappe.clear_cache()
|
||||
|
||||
# Перестраиваем дерево
|
||||
try:
|
||||
from frappe.utils.nestedset import rebuild_tree
|
||||
rebuild_tree("Item Group", "parent_item_group")
|
||||
except Exception as tree_error:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
frappe.log_error(f"URL-encoded Item Groups Error: {str(e)}")
|
||||
frappe.db.rollback()
|
||||
raise
|
||||
|
||||
finally:
|
||||
frappe.flags.ignore_permissions = False
|
||||
frappe.flags.ignore_links = False
|
||||
frappe.flags.ignore_validate_update_after_submit = False
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
# your_app/patches/replace_install_function.py
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import frappe
|
||||
from frappe.desk.doctype.global_search_settings.global_search_settings import (
|
||||
update_global_search_doctypes,
|
||||
)
|
||||
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
||||
from frappe.utils import cstr, getdate
|
||||
|
||||
from erpnext.accounts.doctype.account.account import RootNotEditable
|
||||
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||
|
||||
|
||||
def _(x, *args, **kwargs):
|
||||
"""Redefine the translation function to return the string as is.
|
||||
|
||||
We want to create english records but still mark the strings as translatable.
|
||||
The respective DocTypes have 'Translate Link Fields' enabled."""
|
||||
return x
|
||||
|
||||
|
||||
def read_lines(filename: str) -> list[str]:
|
||||
"""Return a list of lines from a file in the data directory."""
|
||||
return (Path(__file__).parent.parent / "data" / filename).read_text().splitlines()
|
||||
|
||||
|
||||
def custom_install(country=None):
|
||||
"""Ваша замененная функция install - вставьте сюда ваш код"""
|
||||
records = [
|
||||
# ensure at least an empty Address Template exists for this Country
|
||||
{"doctype": "Address Template", "country": country},
|
||||
# item group
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Bütün Element Qrupları"),
|
||||
"is_group": 1,
|
||||
"parent_item_group": "",
|
||||
},
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Məhsullar"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("Bütün Element Qrupları"),
|
||||
"show_in_website": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Xammal"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("Bütün Element Qrupları"),
|
||||
},
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Xidmətlər"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("Bütün Element Qrupları"),
|
||||
},
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("Alt məclislər"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("Bütün Element Qrupları"),
|
||||
},
|
||||
{
|
||||
"doctype": "Item Group",
|
||||
"item_group_name": _("İstehlak materialı"),
|
||||
"is_group": 0,
|
||||
"parent_item_group": _("Bütün Element Qrupları"),
|
||||
},
|
||||
# Stock Entry Type
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Material Issue"),
|
||||
"purpose": "Material Issue",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Material Receipt"),
|
||||
"purpose": "Material Receipt",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Material Transfer"),
|
||||
"purpose": "Material Transfer",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Manufacture"),
|
||||
"purpose": "Manufacture",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Repack"),
|
||||
"purpose": "Repack",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{"doctype": "Stock Entry Type", "name": "Disassemble", "purpose": "Disassemble", "is_standard": 1},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Send to Subcontractor"),
|
||||
"purpose": "Send to Subcontractor",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Material Transfer for Manufacture"),
|
||||
"purpose": "Material Transfer for Manufacture",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
"doctype": "Stock Entry Type",
|
||||
"name": _("Material Consumption for Manufacture"),
|
||||
"purpose": "Material Consumption for Manufacture",
|
||||
"is_standard": 1,
|
||||
},
|
||||
# territory: with two default territories, one for home country and one named Rest of the World
|
||||
{
|
||||
"doctype": "Territory",
|
||||
"territory_name": _("All Territories"),
|
||||
"is_group": 1,
|
||||
"name": _("All Territories"),
|
||||
"parent_territory": "",
|
||||
},
|
||||
{
|
||||
"doctype": "Territory",
|
||||
"territory_name": country.replace("'", ""),
|
||||
"is_group": 0,
|
||||
"parent_territory": _("All Territories"),
|
||||
},
|
||||
{
|
||||
"doctype": "Territory",
|
||||
"territory_name": _("Rest Of The World"),
|
||||
"is_group": 0,
|
||||
"parent_territory": _("All Territories"),
|
||||
},
|
||||
# customer group
|
||||
{
|
||||
"doctype": "Customer Group",
|
||||
"customer_group_name": _("All Customer Groups"),
|
||||
"is_group": 1,
|
||||
"name": _("All Customer Groups"),
|
||||
"parent_customer_group": "",
|
||||
},
|
||||
{
|
||||
"doctype": "Customer Group",
|
||||
"customer_group_name": _("Individual"),
|
||||
"is_group": 0,
|
||||
"parent_customer_group": _("All Customer Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Customer Group",
|
||||
"customer_group_name": _("Commercial"),
|
||||
"is_group": 0,
|
||||
"parent_customer_group": _("All Customer Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Customer Group",
|
||||
"customer_group_name": _("Non Profit"),
|
||||
"is_group": 0,
|
||||
"parent_customer_group": _("All Customer Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Customer Group",
|
||||
"customer_group_name": _("Government"),
|
||||
"is_group": 0,
|
||||
"parent_customer_group": _("All Customer Groups"),
|
||||
},
|
||||
# supplier group
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("All Supplier Groups"),
|
||||
"is_group": 1,
|
||||
"name": _("All Supplier Groups"),
|
||||
"parent_supplier_group": "",
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Xidmətlər"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Local"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Xammal"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Electrical"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Hardware"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Pharmaceutical"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
{
|
||||
"doctype": "Supplier Group",
|
||||
"supplier_group_name": _("Distributor"),
|
||||
"is_group": 0,
|
||||
"parent_supplier_group": _("All Supplier Groups"),
|
||||
},
|
||||
# Sales Person
|
||||
{
|
||||
"doctype": "Sales Person",
|
||||
"sales_person_name": _("Sales Team"),
|
||||
"is_group": 1,
|
||||
"parent_sales_person": "",
|
||||
},
|
||||
# Mode of Payment
|
||||
{
|
||||
"doctype": "Mode of Payment",
|
||||
"mode_of_payment": "Check" if country == "United States" else _("Cheque"),
|
||||
"type": "Bank",
|
||||
},
|
||||
{"doctype": "Mode of Payment", "mode_of_payment": _("Cash"), "type": "Cash"},
|
||||
{"doctype": "Mode of Payment", "mode_of_payment": _("Credit Card"), "type": "Bank"},
|
||||
{"doctype": "Mode of Payment", "mode_of_payment": _("Wire Transfer"), "type": "Bank"},
|
||||
{"doctype": "Mode of Payment", "mode_of_payment": _("Bank Draft"), "type": "Bank"},
|
||||
# Activity Type
|
||||
{"doctype": "Activity Type", "activity_type": _("Planning")},
|
||||
{"doctype": "Activity Type", "activity_type": _("Research")},
|
||||
{"doctype": "Activity Type", "activity_type": _("Proposal Writing")},
|
||||
{"doctype": "Activity Type", "activity_type": _("Execution")},
|
||||
{"doctype": "Activity Type", "activity_type": _("Communication")},
|
||||
{
|
||||
"doctype": "Item Attribute",
|
||||
"attribute_name": _("Size"),
|
||||
"item_attribute_values": [
|
||||
{"attribute_value": _("Extra Small"), "abbr": "XS"},
|
||||
{"attribute_value": _("Small"), "abbr": "S"},
|
||||
{"attribute_value": _("Medium"), "abbr": "M"},
|
||||
{"attribute_value": _("Large"), "abbr": "L"},
|
||||
{"attribute_value": _("Extra Large"), "abbr": "XL"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"doctype": "Item Attribute",
|
||||
"attribute_name": _("Colour"),
|
||||
"item_attribute_values": [
|
||||
{"attribute_value": _("Red"), "abbr": "RED"},
|
||||
{"attribute_value": _("Green"), "abbr": "GRE"},
|
||||
{"attribute_value": _("Blue"), "abbr": "BLU"},
|
||||
{"attribute_value": _("Black"), "abbr": "BLA"},
|
||||
{"attribute_value": _("White"), "abbr": "WHI"},
|
||||
],
|
||||
},
|
||||
# Issue Priority
|
||||
{"doctype": "Issue Priority", "name": _("Low")},
|
||||
{"doctype": "Issue Priority", "name": _("Medium")},
|
||||
{"doctype": "Issue Priority", "name": _("High")},
|
||||
{"doctype": "Email Account", "email_id": "sales@example.com", "append_to": "Opportunity"},
|
||||
{"doctype": "Email Account", "email_id": "support@example.com", "append_to": "Issue"},
|
||||
{"doctype": "Party Type", "party_type": "Customer", "account_type": "Receivable"},
|
||||
{"doctype": "Party Type", "party_type": "Supplier", "account_type": "Payable"},
|
||||
{"doctype": "Party Type", "party_type": "Employee", "account_type": "Payable"},
|
||||
{"doctype": "Party Type", "party_type": "Shareholder", "account_type": "Payable"},
|
||||
{"doctype": "Opportunity Type", "name": _("Sales")},
|
||||
{"doctype": "Opportunity Type", "name": _("Support")},
|
||||
{"doctype": "Opportunity Type", "name": _("Maintenance")},
|
||||
{"doctype": "Project Type", "project_type": _("Internal")},
|
||||
{"doctype": "Project Type", "project_type": _("External")},
|
||||
{"doctype": "Project Type", "project_type": _("Other")},
|
||||
{"doctype": "Print Heading", "print_heading": _("Credit Note")},
|
||||
{"doctype": "Print Heading", "print_heading": _("Debit Note")},
|
||||
# Share Management
|
||||
{"doctype": "Share Type", "title": _("Equity")},
|
||||
{"doctype": "Share Type", "title": _("Preference")},
|
||||
# Market Segments
|
||||
{"doctype": "Market Segment", "market_segment": _("Lower Income")},
|
||||
{"doctype": "Market Segment", "market_segment": _("Middle Income")},
|
||||
{"doctype": "Market Segment", "market_segment": _("Upper Income")},
|
||||
# Warehouse Type
|
||||
{"doctype": "Warehouse Type", "name": "Transit"},
|
||||
]
|
||||
|
||||
for doctype, title_field, filename in (
|
||||
("Designation", "designation_name", "designation.txt"),
|
||||
("Sales Stage", "stage_name", "sales_stage.txt"),
|
||||
("Industry Type", "industry", "industry_type.txt"),
|
||||
("UTM Source", "name", "marketing_source.txt"),
|
||||
("Sales Partner Type", "sales_partner_type", "sales_partner_type.txt"),
|
||||
):
|
||||
records += [{"doctype": doctype, title_field: title} for title in read_lines(filename)]
|
||||
|
||||
base_path = frappe.get_app_path("erpnext", "stock", "doctype")
|
||||
response = frappe.read_file(os.path.join(base_path, "delivery_trip/dispatch_notification_template.html"))
|
||||
|
||||
records += [
|
||||
{
|
||||
"doctype": "Email Template",
|
||||
"name": _("Dispatch Notification"),
|
||||
"response": response,
|
||||
"subject": _("Your order is out for delivery!"),
|
||||
"owner": frappe.session.user,
|
||||
}
|
||||
]
|
||||
|
||||
# Records for the Supplier Scorecard
|
||||
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
|
||||
|
||||
make_default_records()
|
||||
make_records(records)
|
||||
set_up_address_templates(default_country=country)
|
||||
|
||||
# Импортируем функции из оригинального модуля
|
||||
from erpnext.setup.setup_wizard.operations.install_fixtures import (
|
||||
update_selling_defaults,
|
||||
update_buying_defaults,
|
||||
add_uom_data,
|
||||
update_item_variant_settings
|
||||
)
|
||||
|
||||
update_selling_defaults()
|
||||
update_buying_defaults()
|
||||
add_uom_data()
|
||||
update_item_variant_settings()
|
||||
update_global_search_doctypes()
|
||||
|
||||
|
||||
def execute():
|
||||
"""Функция для применения monkey patch"""
|
||||
import erpnext.setup.setup_wizard.operations.install_fixtures as install_fixtures
|
||||
|
||||
# Заменяем функцию install на вашу кастомную версию
|
||||
install_fixtures.install = custom_install
|
||||
|
||||
frappe.logger().info("Custom install function has been applied via monkey patching")
|
||||
Loading…
Reference in New Issue