356 lines
9.8 KiB
Python
356 lines
9.8 KiB
Python
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# License: MIT. See LICENSE
|
|
import getpass
|
|
|
|
import frappe
|
|
from frappe.geo.doctype.country.country import import_country_and_currency
|
|
from frappe.utils import cint
|
|
from frappe.utils.caching import site_cache
|
|
from frappe.utils.password import update_password
|
|
|
|
|
|
def before_install():
|
|
frappe.reload_doc("core", "doctype", "doctype_state")
|
|
frappe.reload_doc("core", "doctype", "docfield")
|
|
frappe.reload_doc("core", "doctype", "docperm")
|
|
frappe.reload_doc("core", "doctype", "doctype_action")
|
|
frappe.reload_doc("core", "doctype", "doctype_link")
|
|
frappe.reload_doc("desk", "doctype", "form_tour_step")
|
|
frappe.reload_doc("desk", "doctype", "form_tour")
|
|
frappe.reload_doc("core", "doctype", "doctype")
|
|
frappe.clear_cache()
|
|
|
|
|
|
def after_install():
|
|
create_user_type()
|
|
install_basic_docs()
|
|
|
|
from frappe.core.doctype.file.utils import make_home_folder
|
|
from frappe.core.doctype.language.language import sync_languages
|
|
|
|
make_home_folder()
|
|
import_country_and_currency()
|
|
sync_languages()
|
|
|
|
# save default print setting
|
|
print_settings = frappe.get_doc("Print Settings")
|
|
print_settings.save()
|
|
|
|
# all roles to admin
|
|
frappe.get_doc("User", "Administrator").add_roles(*frappe.get_all("Role", pluck="name"))
|
|
|
|
# update admin password
|
|
update_password("Administrator", get_admin_password())
|
|
|
|
if not frappe.conf.skip_setup_wizard:
|
|
# only set home_page if the value doesn't exist in the db
|
|
if not frappe.db.get_default("desktop:home_page"):
|
|
frappe.db.set_default("desktop:home_page", "setup-wizard")
|
|
|
|
# clear test log
|
|
from frappe.tests.utils.generators import _clear_test_log
|
|
|
|
_clear_test_log()
|
|
|
|
add_standard_navbar_items()
|
|
|
|
frappe.db.commit()
|
|
|
|
|
|
def create_user_type():
|
|
for user_type in ["System User", "Website User"]:
|
|
if not frappe.db.exists("User Type", user_type):
|
|
frappe.get_doc({"doctype": "User Type", "name": user_type, "is_standard": 1}).insert(
|
|
ignore_permissions=True
|
|
)
|
|
|
|
|
|
def install_basic_docs():
|
|
# core users / roles
|
|
install_docs = [
|
|
{
|
|
"doctype": "User",
|
|
"name": "Administrator",
|
|
"first_name": "Administrator",
|
|
"email": "admin@example.com",
|
|
"enabled": 1,
|
|
"is_admin": 1,
|
|
"roles": [{"role": "Administrator"}],
|
|
"thread_notify": 0,
|
|
"send_me_a_copy": 0,
|
|
},
|
|
{
|
|
"doctype": "User",
|
|
"name": "Guest",
|
|
"first_name": "Guest",
|
|
"email": "guest@example.com",
|
|
"enabled": 1,
|
|
"is_guest": 1,
|
|
"roles": [{"role": "Guest"}],
|
|
"thread_notify": 0,
|
|
"send_me_a_copy": 0,
|
|
},
|
|
{
|
|
"doctype": "Workflow State",
|
|
"workflow_state_name": "Pending",
|
|
"icon": "question-sign",
|
|
"style": "",
|
|
},
|
|
{
|
|
"doctype": "Workflow State",
|
|
"workflow_state_name": "Approved",
|
|
"icon": "ok-sign",
|
|
"style": "Success",
|
|
},
|
|
{
|
|
"doctype": "Workflow State",
|
|
"workflow_state_name": "Rejected",
|
|
"icon": "remove",
|
|
"style": "Danger",
|
|
},
|
|
{"doctype": "Workflow Action Master", "workflow_action_name": "Approve"},
|
|
{"doctype": "Workflow Action Master", "workflow_action_name": "Reject"},
|
|
{"doctype": "Workflow Action Master", "workflow_action_name": "Review"},
|
|
]
|
|
|
|
for d in install_docs:
|
|
try:
|
|
frappe.get_doc(d).insert(ignore_if_duplicate=True)
|
|
except frappe.NameError:
|
|
pass
|
|
|
|
|
|
def get_admin_password():
|
|
return frappe.conf.get("admin_password") or getpass.getpass("Set Administrator password: ")
|
|
|
|
|
|
def before_tests():
|
|
if len(frappe.get_installed_apps()) > 1:
|
|
# don't run before tests if any other app is installed
|
|
return
|
|
|
|
frappe.db.truncate("Custom Field")
|
|
frappe.db.truncate("Event")
|
|
|
|
frappe.clear_cache()
|
|
|
|
# complete setup if missing
|
|
if not frappe.is_setup_complete():
|
|
complete_setup_wizard()
|
|
|
|
frappe.db.set_single_value("Website Settings", "disable_signup", 0)
|
|
frappe.db.commit()
|
|
frappe.clear_cache()
|
|
|
|
|
|
def complete_setup_wizard():
|
|
from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
|
|
|
|
setup_complete(
|
|
{
|
|
"language": "English",
|
|
"email": "test@erpnext.com",
|
|
"full_name": "Test User",
|
|
"password": "test",
|
|
"country": "United States",
|
|
"timezone": "America/New_York",
|
|
"currency": "USD",
|
|
"enable_telemtry": 1,
|
|
}
|
|
)
|
|
|
|
|
|
def add_standard_navbar_items():
|
|
navbar_settings = frappe.get_single("Navbar Settings")
|
|
|
|
# don't add settings/help options if they're already present
|
|
if navbar_settings.settings_dropdown and navbar_settings.help_dropdown:
|
|
return
|
|
|
|
navbar_settings.settings_dropdown = []
|
|
navbar_settings.help_dropdown = []
|
|
|
|
for item in frappe.get_hooks("standard_navbar_items"):
|
|
navbar_settings.append("settings_dropdown", item)
|
|
|
|
for item in frappe.get_hooks("standard_help_items"):
|
|
navbar_settings.append("help_dropdown", item)
|
|
|
|
navbar_settings.save()
|
|
|
|
|
|
def auto_generate_icons_and_sidebar(app_name=None):
|
|
"""Auto Create desktop icons and workspace sidebars."""
|
|
from frappe.desk.doctype.desktop_icon.desktop_icon import create_desktop_icons
|
|
from frappe.desk.doctype.workspace_sidebar.workspace_sidebar import (
|
|
create_workspace_sidebar_for_workspaces,
|
|
)
|
|
|
|
try:
|
|
print("Creating Desktop Icons")
|
|
create_desktop_icons()
|
|
print("Creating Workspace Sidebars")
|
|
create_workspace_sidebar_for_workspaces()
|
|
# Save the generated icons
|
|
frappe.db.commit() # nosemgrep
|
|
# Save the genreated sidebar links
|
|
frappe.db.commit() # nosemgrep
|
|
except Exception as e:
|
|
print(f"Error creating icons {e}")
|
|
|
|
|
|
def delete_desktop_icon_and_sidebar(app_name, dry_run=False):
|
|
frappe.get_hooks(app_name=app_name)
|
|
app_title = frappe.get_hooks(app_name=app_name)["app_title"][0]
|
|
icons_to_be_deleted = frappe.get_all(
|
|
"Desktop Icon",
|
|
pluck="name",
|
|
or_filters=[
|
|
["Desktop Icon", "name", "=", app_title],
|
|
["Desktop Icon", "parent_icon", "=", app_title],
|
|
],
|
|
)
|
|
print("Deleting Desktop Icons")
|
|
for icon in icons_to_be_deleted:
|
|
frappe.delete_doc_if_exists("Desktop Icon", icon)
|
|
# Delete icons
|
|
sidebar_to_be_deleted = frappe.get_all("Workspace Sidebar", pluck="name", filters={"app": app_name})
|
|
print("Deleting Workspace Sidebars")
|
|
for icon in sidebar_to_be_deleted:
|
|
frappe.delete_doc_if_exists("Workspace Sidebar", icon)
|
|
|
|
if dry_run:
|
|
# Delete icons and sidebars
|
|
frappe.db.commit() # nosemgrep
|
|
|
|
|
|
@site_cache()
|
|
def auto_generate_sidebar_from_module():
|
|
"""Auto generate sidebar from module"""
|
|
sidebars = []
|
|
for module in frappe.get_all("Module Def", pluck="name"):
|
|
if not (
|
|
frappe.db.exists("Workspace Sidebar", {"module": module})
|
|
or frappe.db.exists("Workspace Sidebar", {"name": module})
|
|
):
|
|
module_info = get_module_info(module)
|
|
sidebar_items = create_sidebar_items(module_info)
|
|
sidebar = frappe.new_doc("Workspace Sidebar")
|
|
sidebar.title = module
|
|
sidebar.items = sidebar_items
|
|
sidebar.module = module
|
|
sidebar.header_icon = "hammer"
|
|
sidebar.app = frappe.local.module_app.get(frappe.scrub(module), None)
|
|
sidebars.append(sidebar)
|
|
return sidebars
|
|
|
|
|
|
def get_module_info(module_name):
|
|
entities = ["Workspace", "Dashboard", "DocType", "Report", "Page"]
|
|
module_info = {}
|
|
|
|
for entity in entities:
|
|
module_info[entity] = {}
|
|
filters = [{"module": module_name}]
|
|
pluck = "name"
|
|
fieldnames = ["name"]
|
|
if entity.lower() == "doctype":
|
|
filters.append({"istable": 0})
|
|
if entity.lower() == "page":
|
|
fieldnames.append("title")
|
|
pluck = None
|
|
module_info[entity] = frappe.get_all(
|
|
entity, filters=filters, fields=fieldnames, pluck=pluck, order_by="creation asc"
|
|
)
|
|
|
|
# if module info has no workspaces, then move doctypes to the front
|
|
if not module_info.get("Workspace"):
|
|
module_info = {
|
|
"DocType": module_info.get("DocType"),
|
|
"Workspace": module_info.get("Workspace"),
|
|
"Report": module_info.get("Report"),
|
|
"Dashboard": module_info.get("Dashboard"),
|
|
"Page": module_info.get("Page"),
|
|
}
|
|
top_doctypes = choose_top_doctypes(module_info.get("DocType"))
|
|
if top_doctypes:
|
|
module_info["DocType"] = choose_top_doctypes(module_info.get("DocType"))
|
|
return module_info
|
|
|
|
|
|
def choose_top_doctypes(doctype_names):
|
|
doctype_limit = 3
|
|
if len(doctype_names) > doctype_limit:
|
|
try:
|
|
doctype_count_map = {}
|
|
for doctype in doctype_names:
|
|
doctype_count_map[doctype] = frappe.db.count(doctype)
|
|
top_doctypes = [
|
|
name
|
|
for name, count in sorted(doctype_count_map.items(), key=lambda x: x[1], reverse=True)[
|
|
:doctype_limit
|
|
]
|
|
]
|
|
return top_doctypes
|
|
except frappe.db.ProgrammingError:
|
|
# catches table not found errors
|
|
return None
|
|
|
|
|
|
def create_sidebar_items(module_info):
|
|
sidebar_items = []
|
|
idx = 1
|
|
|
|
section_entities = {"report": "Reports", "dashboard": "Dashboards", "page": "Pages"}
|
|
|
|
for entity, items in module_info.items():
|
|
section_break_added = False
|
|
entity_lower = entity.lower()
|
|
|
|
if entity_lower in section_entities:
|
|
if entity_lower == "report":
|
|
section_break = add_section_breaks("Reports", idx)
|
|
elif entity_lower in ("dashboard", "page") and len(items) > 1:
|
|
section_break = add_section_breaks(section_entities[entity_lower], idx)
|
|
section_break_added = True
|
|
sidebar_items.append(section_break)
|
|
idx += 1
|
|
|
|
for item in items:
|
|
print(entity, item)
|
|
item_info = {"label": item, "type": "Link", "link_type": entity, "link_to": item, "idx": idx}
|
|
|
|
if entity_lower == "report":
|
|
item_info["child"] = 1
|
|
item_info["icon"] = "table"
|
|
|
|
if entity_lower == "page":
|
|
item_info["label"] = item.get("title")
|
|
item_info["link_to"] = item.get("name")
|
|
|
|
if entity_lower == "workspace":
|
|
item_info["icon"] = "home"
|
|
item_info["icon"] = "wallpaper"
|
|
|
|
if entity_lower == "page":
|
|
item_info["icon"] = "panel-top"
|
|
|
|
if entity_lower == "doctype" and "settings" in item.lower():
|
|
item_info["icon"] = "settings"
|
|
|
|
if section_break_added:
|
|
item_info["child"] = 1
|
|
|
|
sidebar_item = frappe.new_doc("Workspace Sidebar Item")
|
|
sidebar_item.update(item_info)
|
|
sidebar_items.append(sidebar_item)
|
|
|
|
idx += 1
|
|
|
|
return sidebar_items
|
|
|
|
|
|
def add_section_breaks(label, idx):
|
|
section_break = frappe.new_doc("Workspace Sidebar Item")
|
|
section_break.update({"label": label, "type": "Section Break", "idx": idx})
|
|
return section_break
|