Skipping ERPNext Setup Wizard and Initializing

I’m currently working on setting up ERPNext using Docker, and I am looking for assistance on skipping the setup wizard and initialize the app with required data, for instance company information, country, currency, etc and any other data.

I have been exploring ways to streamline the deployment, and I would like to bypass the setup wizard to automate the initialization. Specifically, I am using Docker-Compose for this purpose. I’ve found I can skip the setup wizard using the config skip_setup_wizard=1 but I still need to initialize the app. So here are my two questions:

  1. Is there a mechanism in place, possibly utilizing bench, to initialize the app and bypass the setup wizard?
  2. As a last resort, if I were to run an SQL query to initialize the initial database, how can I achieve that? Additionally, do I still need to explicitly skip the setup wizard in this scenario?

If any community members have experience or insights into this process, I would greatly appreciate your guidance. Please share any relevant documentation, tips, or steps that can help me skip the setup wizard and initialize ERPNext seamlessly using Docker utilizing the community avail Docker Image.

You could:

  • Initialize a bench, which installs the frappe app (the framework).
  • Take a snapshot of the database (with whatever method fits you).
  • Create a site.
  • Take another snapshot of the database.
  • Install erpnext.
  • Take another snapshot of the database.
  • Run the setup wizard. Possibly also any other configuration you might want to set up for your purpose.
  • Take another snapshot of the database.
  • Now compare the data of the database snapshots to understand the changes which the setup wizard applied. Depending on the snapshot method used, you might need to create some DB diff tool.
  • You could also take a look at the file system. There might be changes as well (the most obvious ones are the site configuration files).
  • With what you found and learned, you can add “find” and “grep” copiously to better understand how it was done. That might give you additional ideas.
  • Enjoy your increased knowledge as a developer and/or admin.
  • See if your original intent can be accomplished with this. Test.
  • Share the results, e.g. here!

Thanks @Peer for your thoughtful suggestions.

I’ve seen this recommendations

Point#4 and #3 looks interesting to me, is there examples out there using the same approach?

Yes, you could use these.

Scripting (points 3 and 4) gives access to the database.
But in order to know where to change what, you need to know where to apply which changes. That’s what my suggestions are about.

There is a setup_complete function that I use along with some short-lived environment variables at the time of deployment.

Note that you need to know the name of the Chart of Accounts, which you can find when you do the initial setup manually. After that it can all be automated.

import os
from frappe.desk.page.setup_wizard.setup_wizard import setup_complete as setup_erpnext
from frappe.utils import cint

def auto_setup_erpnext():
    admin_email = None

    if frappe.db.exists("Company", "Some Company GmbH"):
        return

    if cint(os.environ.get("AUTO_SETUP")) != 1:
        return

    if not os.environ.get("SITE"):
        frappe.throw("ERPNext Configuration Failed: SITE not configured")

    if not os.environ.get("SITE_PASSWORD"):
        frappe.throw("ERPNext Configuration Failed: SITE_PASSWORD not configured")

    admin_email = "admin@" + os.environ.get("SITE")

    today_date = frappe.utils.today()

    args = {
	"language": "Deutsch",
        "country": "Germany",
        "timezone": "Europe/Berlin",
        "currency": "EUR",
        "full_name": "Administrator",
        "email": admin_email,
        "password": os.environ.get("SITE_PASSWORD"),
        "company_name": "Some Company GmbH",
        "company_abbr": "SC",
        "chart_of_accounts": "SKR04 mit Kontonummern",
        "fy_start_date": frappe.utils.get_year_start(today_date),
        "fy_end_date": frappe.utils.get_year_ending(today_date),
        "setup_demo": 0,
        "enable_telemetry": 0,
    }

    setup_status = setup_erpnext(args=args)

    if setup_status.get("status") != "ok":
        frappe.throw("ERPNext setup failed")

I also disable onboarding. Maybe there is a cleaner way to do this but I’m doing it like this for now:

def disable_onboarding():
    frappe.db.sql("""UPDATE `tabOnboarding Step` SET is_skipped=1""")
    onboarding_status = {}
    tour_list = frappe.get_list("Form Tour", filters={"track_steps": 1})
    for tour in tour_list:
        steps_complete = frappe.db.count(
            "Form Tour Step", filters={"parent": tour.name, "ui_tour": 1}
        )
	onboarding_status[tour.name] = {
            "is_complete": True,
            "steps_complete": steps_complete,
        }

    onboarding_status_json = json.dumps(onboarding_status, separators=(",", ":"))

    user_list = frappe.get_list("User")
    for user in user_list:
        frappe.db.set_value(
            "User", user.name, "onboarding_status", onboarding_status_json
        )

We do this more or less in our CI for unit testing. It’s pretty similar to Frappe’s approach but we also want to populate enough data so that it’s reasonable to demo.

Instructions are in the “Setup test data” section of the readme.

Setup script