add salary component export button and default setup from JSON

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ali 2026-03-26 14:46:40 +04:00
parent 116efda4f2
commit 7cd7b5d887
5 changed files with 70 additions and 16 deletions

View File

@ -0,0 +1,23 @@
import frappe
SKIP_FIELDS = {"name", "creation", "modified", "modified_by", "owner", "docstatus", "idx"}
@frappe.whitelist()
def export_salary_components():
components = frappe.get_all("Salary Component", fields=["name"])
result = []
for c in components:
doc = frappe.get_doc("Salary Component", c.name)
data = doc.as_dict()
for field in SKIP_FIELDS:
data.pop(field, None)
# accounts — company-specific, не экспортируем
data.pop("accounts", None)
result.append(data)
return result

View File

@ -31,6 +31,7 @@ doctype_js = {
doctype_list_js = { doctype_list_js = {
"Currency Exchange": "public/js/currency_exchange_list.js", "Currency Exchange": "public/js/currency_exchange_list.js",
"Salary Component": "public/js/salary_component_list.js",
} }
extend_doctype_class = { extend_doctype_class = {
@ -80,7 +81,7 @@ doc_events = {
# Asset categories are now created automatically via Company.on_update event # Asset categories are now created automatically via Company.on_update event
# setup_wizard_complete = "jey_erp.setup.setup_wizard_handler.setup_wizard_complete_handler" # setup_wizard_complete = "jey_erp.setup.setup_wizard_handler.setup_wizard_complete_handler"
setup_wizard_complete = "jey_erp.setup.setup_wizard_handler.create_test_salary_component" setup_wizard_complete = "jey_erp.setup.setup_wizard_handler.create_default_salary_components"
after_migrate = "jey_erp.hooks.after_migrate_combined" after_migrate = "jey_erp.hooks.after_migrate_combined"

View File

@ -0,0 +1,21 @@
frappe.listview_settings["Salary Component"] = {
onload: function (listview) {
listview.page.add_inner_button(__("Export Defaults"), function () {
frappe.call({
method: "jey_erp.custom.salary_component_export.export_salary_components",
callback: function (r) {
if (!r.message) return;
const json = JSON.stringify(r.message, null, 2);
const blob = new Blob([json], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "salary_components.json";
a.click();
URL.revokeObjectURL(url);
},
});
});
},
};

View File

@ -1,25 +1,34 @@
import json
import os
import frappe import frappe
SALARY_COMPONENTS_JSON = os.path.join(
os.path.dirname(os.path.dirname(__file__)),
"default_data",
"salary_components.json",
)
def create_test_salary_component(args):
if frappe.db.exists("Salary Component", "TEST COMP"): def create_default_salary_components(args):
if not os.path.exists(SALARY_COMPONENTS_JSON):
return return
company = args.get("company_name") or frappe.db.get_single_value("Global Defaults", "default_company") company = args.get("company_name") or frappe.db.get_single_value("Global Defaults", "default_company")
doc = frappe.get_doc({ with open(SALARY_COMPONENTS_JSON, encoding="utf-8") as f:
"doctype": "Salary Component", components = json.load(f)
"salary_component": "TEST COMP",
"salary_component_abbr": "TC", for data in components:
"type": "Earning", name = data.get("salary_component")
"accounts": [ if not name or frappe.db.exists("Salary Component", name):
{ continue
"company": company,
"account": None, # можно указать конкретный счёт data["doctype"] = "Salary Component"
} data["accounts"] = [{"company": company, "account": None}] if company else []
] if company else [],
}) frappe.get_doc(data).insert(ignore_permissions=True)
doc.insert(ignore_permissions=True)
frappe.db.commit() frappe.db.commit()