[Setup Wizard] Use setup stages (#12000)
* setup working with packages imports for operations * setup stages * use setup_stages hook * remove commit from app setup
This commit is contained in:
parent
82035c6c7a
commit
8b0b56dda4
@ -26,7 +26,7 @@ doctype_js = {
|
|||||||
|
|
||||||
# setup wizard
|
# setup wizard
|
||||||
setup_wizard_requires = "assets/erpnext/js/setup_wizard.js"
|
setup_wizard_requires = "assets/erpnext/js/setup_wizard.js"
|
||||||
setup_wizard_complete = "erpnext.setup.setup_wizard.setup_wizard.setup_complete"
|
setup_wizard_stages = "erpnext.setup.setup_wizard.setup_wizard.get_setup_stages"
|
||||||
setup_wizard_test = "erpnext.setup.setup_wizard.test_setup_wizard.run_setup_wizard_test"
|
setup_wizard_test = "erpnext.setup.setup_wizard.test_setup_wizard.run_setup_wizard_test"
|
||||||
|
|
||||||
before_install = "erpnext.setup.install.check_setup_wizard_not_completed"
|
before_install = "erpnext.setup.install.check_setup_wizard_not_completed"
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import frappe
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
def execute():
|
def execute():
|
||||||
from erpnext.setup.setup_wizard.install_fixtures import default_lead_sources
|
from erpnext.setup.setup_wizard.operations.install_fixtures import default_lead_sources
|
||||||
|
|
||||||
frappe.reload_doc('selling', 'doctype', 'lead_source')
|
frappe.reload_doc('selling', 'doctype', 'lead_source')
|
||||||
|
|
||||||
|
|||||||
0
erpnext/setup/setup_wizard/data/__init__.py
Normal file
0
erpnext/setup/setup_wizard/data/__init__.py
Normal file
0
erpnext/setup/setup_wizard/operations/__init__.py
Normal file
0
erpnext/setup/setup_wizard/operations/__init__.py
Normal file
125
erpnext/setup/setup_wizard/operations/company_setup.py
Normal file
125
erpnext/setup/setup_wizard/operations/company_setup.py
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import cstr, getdate
|
||||||
|
from frappe.utils.file_manager import save_file
|
||||||
|
from .default_website import website_maker
|
||||||
|
from erpnext.accounts.doctype.account.account import RootNotEditable
|
||||||
|
|
||||||
|
def create_fiscal_year_and_company(args):
|
||||||
|
if (args.get('fy_start_date')):
|
||||||
|
curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype":"Fiscal Year",
|
||||||
|
'year': curr_fiscal_year,
|
||||||
|
'year_start_date': args.get('fy_start_date'),
|
||||||
|
'year_end_date': args.get('fy_end_date'),
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
if (args.get('company_name')):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype":"Company",
|
||||||
|
'company_name':args.get('company_name'),
|
||||||
|
'enable_perpetual_inventory': 1,
|
||||||
|
'abbr':args.get('company_abbr'),
|
||||||
|
'default_currency':args.get('currency'),
|
||||||
|
'country': args.get('country'),
|
||||||
|
'create_chart_of_accounts_based_on': 'Standard Template',
|
||||||
|
'chart_of_accounts': args.get('chart_of_accounts'),
|
||||||
|
'domain': args.get('domains')[0]
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
def enable_shopping_cart(args):
|
||||||
|
# Needs price_lists
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Shopping Cart Settings",
|
||||||
|
"enabled": 1,
|
||||||
|
'company': args.get('company_name') ,
|
||||||
|
'price_list': frappe.db.get_value("Price List", {"selling": 1}),
|
||||||
|
'default_customer_group': _("Individual"),
|
||||||
|
'quotation_series': "QTN-",
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
def create_bank_account(args):
|
||||||
|
if args.get("bank_account"):
|
||||||
|
company_name = args.get('company_name')
|
||||||
|
bank_account_group = frappe.db.get_value("Account",
|
||||||
|
{"account_type": "Bank", "is_group": 1, "root_type": "Asset",
|
||||||
|
"company": company_name})
|
||||||
|
if bank_account_group:
|
||||||
|
bank_account = frappe.get_doc({
|
||||||
|
"doctype": "Account",
|
||||||
|
'account_name': args.get("bank_account"),
|
||||||
|
'parent_account': bank_account_group,
|
||||||
|
'is_group':0,
|
||||||
|
'company': company_name,
|
||||||
|
"account_type": "Bank",
|
||||||
|
})
|
||||||
|
try:
|
||||||
|
return bank_account.insert()
|
||||||
|
except RootNotEditable:
|
||||||
|
frappe.throw(_("Bank account cannot be named as {0}").format(args.get("bank_account")))
|
||||||
|
except frappe.DuplicateEntryError:
|
||||||
|
# bank account same as a CoA entry
|
||||||
|
pass
|
||||||
|
|
||||||
|
def create_email_digest():
|
||||||
|
from frappe.utils.user import get_system_managers
|
||||||
|
system_managers = get_system_managers(only_name=True)
|
||||||
|
if not system_managers:
|
||||||
|
return
|
||||||
|
|
||||||
|
companies = frappe.db.sql_list("select name FROM `tabCompany`")
|
||||||
|
for company in companies:
|
||||||
|
if not frappe.db.exists("Email Digest", "Default Weekly Digest - " + company):
|
||||||
|
edigest = frappe.get_doc({
|
||||||
|
"doctype": "Email Digest",
|
||||||
|
"name": "Default Weekly Digest - " + company,
|
||||||
|
"company": company,
|
||||||
|
"frequency": "Weekly",
|
||||||
|
"recipient_list": "\n".join(system_managers)
|
||||||
|
})
|
||||||
|
|
||||||
|
for df in edigest.meta.get("fields", {"fieldtype": "Check"}):
|
||||||
|
if df.fieldname != "scheduler_errors":
|
||||||
|
edigest.set(df.fieldname, 1)
|
||||||
|
|
||||||
|
edigest.insert()
|
||||||
|
|
||||||
|
# scheduler errors digest
|
||||||
|
if companies:
|
||||||
|
edigest = frappe.new_doc("Email Digest")
|
||||||
|
edigest.update({
|
||||||
|
"name": "Scheduler Errors",
|
||||||
|
"company": companies[0],
|
||||||
|
"frequency": "Daily",
|
||||||
|
"recipient_list": "\n".join(system_managers),
|
||||||
|
"scheduler_errors": 1,
|
||||||
|
"enabled": 1
|
||||||
|
})
|
||||||
|
edigest.insert()
|
||||||
|
|
||||||
|
def create_logo(args):
|
||||||
|
if args.get("attach_logo"):
|
||||||
|
attach_logo = args.get("attach_logo").split(",")
|
||||||
|
if len(attach_logo)==3:
|
||||||
|
filename, filetype, content = attach_logo
|
||||||
|
fileurl = save_file(filename, content, "Website Settings", "Website Settings",
|
||||||
|
decode=True).file_url
|
||||||
|
frappe.db.set_value("Website Settings", "Website Settings", "brand_html",
|
||||||
|
"<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name") ))
|
||||||
|
|
||||||
|
def create_website(args):
|
||||||
|
if args.get('setup_website'):
|
||||||
|
website_maker(args)
|
||||||
|
|
||||||
|
def get_fy_details(fy_start_date, fy_end_date):
|
||||||
|
start_year = getdate(fy_start_date).year
|
||||||
|
if start_year == getdate(fy_end_date).year:
|
||||||
|
fy = cstr(start_year)
|
||||||
|
else:
|
||||||
|
fy = cstr(start_year) + '-' + cstr(start_year + 1)
|
||||||
|
return fy
|
||||||
126
erpnext/setup/setup_wizard/operations/defaults_setup.py
Normal file
126
erpnext/setup/setup_wizard/operations/defaults_setup.py
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.utils import cstr, getdate
|
||||||
|
from frappe.core.doctype.communication.comment import add_info_comment
|
||||||
|
|
||||||
|
def set_default_settings(args):
|
||||||
|
# enable default currency
|
||||||
|
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
|
||||||
|
|
||||||
|
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
|
||||||
|
global_defaults.update({
|
||||||
|
'current_fiscal_year': get_fy_details(args.get('fy_start_date'), args.get('fy_end_date')),
|
||||||
|
'default_currency': args.get('currency'),
|
||||||
|
'default_company':args.get('company_name') ,
|
||||||
|
"country": args.get("country"),
|
||||||
|
})
|
||||||
|
|
||||||
|
global_defaults.save()
|
||||||
|
|
||||||
|
system_settings = frappe.get_doc("System Settings")
|
||||||
|
system_settings.email_footer_address = args.get("company_name")
|
||||||
|
system_settings.save()
|
||||||
|
|
||||||
|
domain_settings = frappe.get_single('Domain Settings')
|
||||||
|
domain_settings.set_active_domains(args.get('domains'))
|
||||||
|
domain_settings.save()
|
||||||
|
|
||||||
|
stock_settings = frappe.get_doc("Stock Settings")
|
||||||
|
stock_settings.item_naming_by = "Item Code"
|
||||||
|
stock_settings.valuation_method = "FIFO"
|
||||||
|
stock_settings.default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})
|
||||||
|
stock_settings.stock_uom = _("Nos")
|
||||||
|
stock_settings.auto_indent = 1
|
||||||
|
stock_settings.auto_insert_price_list_rate_if_missing = 1
|
||||||
|
stock_settings.automatically_set_serial_nos_based_on_fifo = 1
|
||||||
|
stock_settings.save()
|
||||||
|
|
||||||
|
selling_settings = frappe.get_doc("Selling Settings")
|
||||||
|
selling_settings.cust_master_name = "Customer Name"
|
||||||
|
selling_settings.so_required = "No"
|
||||||
|
selling_settings.dn_required = "No"
|
||||||
|
selling_settings.allow_multiple_items = 1
|
||||||
|
selling_settings.save()
|
||||||
|
|
||||||
|
buying_settings = frappe.get_doc("Buying Settings")
|
||||||
|
buying_settings.supp_master_name = "Supplier Name"
|
||||||
|
buying_settings.po_required = "No"
|
||||||
|
buying_settings.pr_required = "No"
|
||||||
|
buying_settings.maintain_same_rate = 1
|
||||||
|
buying_settings.allow_multiple_items = 1
|
||||||
|
buying_settings.save()
|
||||||
|
|
||||||
|
notification_control = frappe.get_doc("Notification Control")
|
||||||
|
notification_control.quotation = 1
|
||||||
|
notification_control.sales_invoice = 1
|
||||||
|
notification_control.purchase_order = 1
|
||||||
|
notification_control.save()
|
||||||
|
|
||||||
|
hr_settings = frappe.get_doc("HR Settings")
|
||||||
|
hr_settings.emp_created_by = "Naming Series"
|
||||||
|
hr_settings.save()
|
||||||
|
|
||||||
|
def set_no_copy_fields_in_variant_settings():
|
||||||
|
# set no copy fields of an item doctype to item variant settings
|
||||||
|
doc = frappe.get_doc('Item Variant Settings')
|
||||||
|
doc.set_default_fields()
|
||||||
|
doc.save()
|
||||||
|
|
||||||
|
def create_price_lists(args):
|
||||||
|
for pl_type, pl_name in (("Selling", _("Standard Selling")), ("Buying", _("Standard Buying"))):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Price List",
|
||||||
|
"price_list_name": pl_name,
|
||||||
|
"enabled": 1,
|
||||||
|
"buying": 1 if pl_type == "Buying" else 0,
|
||||||
|
"selling": 1 if pl_type == "Selling" else 0,
|
||||||
|
"currency": args["currency"]
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
def create_employee_for_self(args):
|
||||||
|
if frappe.session.user == 'Administrator':
|
||||||
|
return
|
||||||
|
|
||||||
|
# create employee for self
|
||||||
|
emp = frappe.get_doc({
|
||||||
|
"doctype": "Employee",
|
||||||
|
"employee_name": " ".join(filter(None, [args.get("first_name"), args.get("last_name")])),
|
||||||
|
"user_id": frappe.session.user,
|
||||||
|
"status": "Active",
|
||||||
|
"company": args.get("company_name")
|
||||||
|
})
|
||||||
|
emp.flags.ignore_mandatory = True
|
||||||
|
emp.insert(ignore_permissions = True)
|
||||||
|
|
||||||
|
def create_territories():
|
||||||
|
"""create two default territories, one for home country and one named Rest of the World"""
|
||||||
|
from frappe.utils.nestedset import get_root_of
|
||||||
|
country = frappe.db.get_default("country")
|
||||||
|
root_territory = get_root_of("Territory")
|
||||||
|
|
||||||
|
for name in (country, _("Rest Of The World")):
|
||||||
|
if name and not frappe.db.exists("Territory", name):
|
||||||
|
frappe.get_doc({
|
||||||
|
"doctype": "Territory",
|
||||||
|
"territory_name": name.replace("'", ""),
|
||||||
|
"parent_territory": root_territory,
|
||||||
|
"is_group": "No"
|
||||||
|
}).insert()
|
||||||
|
|
||||||
|
def create_feed_and_todo():
|
||||||
|
"""update Activity feed and create todo for creation of item, customer, vendor"""
|
||||||
|
add_info_comment(**{
|
||||||
|
"subject": _("ERPNext Setup Complete!")
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_fy_details(fy_start_date, fy_end_date):
|
||||||
|
start_year = getdate(fy_start_date).year
|
||||||
|
if start_year == getdate(fy_end_date).year:
|
||||||
|
fy = cstr(start_year)
|
||||||
|
else:
|
||||||
|
fy = cstr(start_year) + '-' + cstr(start_year + 1)
|
||||||
|
return fy
|
||||||
@ -248,7 +248,7 @@ def install(country=None):
|
|||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
from erpnext.setup.setup_wizard.industry_type import get_industry_types
|
from erpnext.setup.setup_wizard.data.industry_type import get_industry_types
|
||||||
records += [{"doctype":"Industry Type", "industry": d} for d in get_industry_types()]
|
records += [{"doctype":"Industry Type", "industry": d} for d in get_industry_types()]
|
||||||
# records += [{"doctype":"Operation", "operation": d} for d in get_operations()]
|
# records += [{"doctype":"Operation", "operation": d} for d in get_operations()]
|
||||||
|
|
||||||
95
erpnext/setup/setup_wizard/operations/taxes_setup.py
Normal file
95
erpnext/setup/setup_wizard/operations/taxes_setup.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe, copy, os, json
|
||||||
|
from frappe.utils import flt
|
||||||
|
from erpnext.accounts.doctype.account.account import RootNotEditable
|
||||||
|
|
||||||
|
def create_sales_tax(args):
|
||||||
|
country_wise_tax = get_country_wise_tax(args.get("country"))
|
||||||
|
if country_wise_tax and len(country_wise_tax) > 0:
|
||||||
|
for sales_tax, tax_data in country_wise_tax.items():
|
||||||
|
make_tax_account_and_template(
|
||||||
|
args.get("company_name"),
|
||||||
|
tax_data.get('account_name'),
|
||||||
|
tax_data.get('tax_rate'), sales_tax)
|
||||||
|
|
||||||
|
def make_tax_account_and_template(company, account_name, tax_rate, template_name=None):
|
||||||
|
try:
|
||||||
|
if not isinstance(account_name, (list, tuple)):
|
||||||
|
account_name = [account_name]
|
||||||
|
tax_rate = [tax_rate]
|
||||||
|
|
||||||
|
accounts = []
|
||||||
|
for i, name in enumerate(account_name):
|
||||||
|
tax_account = make_tax_account(company, account_name[i], tax_rate[i])
|
||||||
|
if tax_account:
|
||||||
|
accounts.append(tax_account)
|
||||||
|
|
||||||
|
if accounts:
|
||||||
|
make_sales_and_purchase_tax_templates(accounts, template_name)
|
||||||
|
except frappe.NameError:
|
||||||
|
pass
|
||||||
|
except RootNotEditable:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def make_tax_account(company, account_name, tax_rate):
|
||||||
|
tax_group = get_tax_account_group(company)
|
||||||
|
if tax_group:
|
||||||
|
return frappe.get_doc({
|
||||||
|
"doctype":"Account",
|
||||||
|
"company": company,
|
||||||
|
"parent_account": tax_group,
|
||||||
|
"account_name": account_name,
|
||||||
|
"is_group": 0,
|
||||||
|
"report_type": "Balance Sheet",
|
||||||
|
"root_type": "Liability",
|
||||||
|
"account_type": "Tax",
|
||||||
|
"tax_rate": flt(tax_rate) if tax_rate else None
|
||||||
|
}).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
def make_sales_and_purchase_tax_templates(accounts, template_name=None):
|
||||||
|
if not template_name:
|
||||||
|
template_name = accounts[0].name
|
||||||
|
|
||||||
|
sales_tax_template = {
|
||||||
|
"doctype": "Sales Taxes and Charges Template",
|
||||||
|
"title": template_name,
|
||||||
|
"company": accounts[0].company,
|
||||||
|
'taxes': []
|
||||||
|
}
|
||||||
|
|
||||||
|
for account in accounts:
|
||||||
|
sales_tax_template['taxes'].append({
|
||||||
|
"category": "Valuation and Total",
|
||||||
|
"charge_type": "On Net Total",
|
||||||
|
"account_head": account.name,
|
||||||
|
"description": "{0} @ {1}".format(account.account_name, account.tax_rate),
|
||||||
|
"rate": account.tax_rate
|
||||||
|
})
|
||||||
|
# Sales
|
||||||
|
frappe.get_doc(copy.deepcopy(sales_tax_template)).insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
# Purchase
|
||||||
|
purchase_tax_template = copy.deepcopy(sales_tax_template)
|
||||||
|
purchase_tax_template["doctype"] = "Purchase Taxes and Charges Template"
|
||||||
|
|
||||||
|
doc = frappe.get_doc(purchase_tax_template)
|
||||||
|
doc.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
def get_tax_account_group(company):
|
||||||
|
tax_group = frappe.db.get_value("Account",
|
||||||
|
{"account_name": "Duties and Taxes", "is_group": 1, "company": company})
|
||||||
|
if not tax_group:
|
||||||
|
tax_group = frappe.db.get_value("Account", {"is_group": 1, "root_type": "Liability",
|
||||||
|
"account_type": "Tax", "company": company})
|
||||||
|
|
||||||
|
return tax_group
|
||||||
|
|
||||||
|
def get_country_wise_tax(country):
|
||||||
|
data = {}
|
||||||
|
with open (os.path.join(os.path.dirname(__file__), "..", "data", "country_wise_tax.json")) as countrywise_tax:
|
||||||
|
data = json.load(countrywise_tax).get(country)
|
||||||
|
|
||||||
|
return data
|
||||||
@ -2,393 +2,139 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, copy
|
|
||||||
|
|
||||||
import os
|
import frappe
|
||||||
import json
|
|
||||||
from frappe.utils import cstr, flt, getdate
|
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils.file_manager import save_file
|
from operations import install_fixtures, taxes_setup, defaults_setup, company_setup, sample_data
|
||||||
from .default_website import website_maker
|
|
||||||
import install_fixtures
|
def get_setup_stages(args=None):
|
||||||
from .sample_data import make_sample_data
|
if frappe.db.sql("select name from tabCompany"):
|
||||||
from erpnext.accounts.doctype.account.account import RootNotEditable
|
stages = [
|
||||||
from frappe.core.doctype.communication.comment import add_info_comment
|
{
|
||||||
from erpnext.setup.doctype.company.company import install_country_fixtures
|
'status': _('Wrapping up'),
|
||||||
|
'fail_msg': _('Failed to login'),
|
||||||
|
'tasks': [
|
||||||
|
{
|
||||||
|
'fn': fin,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to login")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
stages = [
|
||||||
|
{
|
||||||
|
'status': _('Installing presets'),
|
||||||
|
'fail_msg': _('Failed to install presets'),
|
||||||
|
'tasks': [
|
||||||
|
{
|
||||||
|
'fn': stage_fixtures,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to install presets")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'status': _('Setting up company and taxes'),
|
||||||
|
'fail_msg': _('Failed to setup company'),
|
||||||
|
'tasks': [
|
||||||
|
{
|
||||||
|
'fn': setup_company,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to setup company")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'fn': setup_taxes,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to setup taxes")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'status': _('Setting defaults'),
|
||||||
|
'fail_msg': 'Failed to set defaults',
|
||||||
|
'tasks': [
|
||||||
|
{
|
||||||
|
'fn': stage_three,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to set defaults")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'status': _('Making website'),
|
||||||
|
'fail_msg': _('Failed to create website'),
|
||||||
|
'tasks': [
|
||||||
|
{
|
||||||
|
'fn': stage_four,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to create website")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'status': _('Wrapping up'),
|
||||||
|
'fail_msg': _('Failed to login'),
|
||||||
|
'tasks': [
|
||||||
|
{
|
||||||
|
'fn': fin,
|
||||||
|
'args': args,
|
||||||
|
'fail_msg': _("Failed to login")
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
return stages
|
||||||
|
|
||||||
def setup_complete(args=None):
|
def setup_complete(args=None):
|
||||||
if frappe.db.sql("select name from tabCompany"):
|
stage_fixtures(args)
|
||||||
frappe.throw(_("Setup Already Complete!!"))
|
setup_company(args)
|
||||||
|
setup_taxes(args)
|
||||||
|
stage_three(args)
|
||||||
|
stage_four(args)
|
||||||
|
fin(args)
|
||||||
|
|
||||||
|
def stage_fixtures(args):
|
||||||
install_fixtures.install(args.get("country"))
|
install_fixtures.install(args.get("country"))
|
||||||
|
|
||||||
create_price_lists(args)
|
def setup_company(args):
|
||||||
create_fiscal_year_and_company(args)
|
defaults_setup.create_price_lists(args)
|
||||||
create_sales_tax(args)
|
company_setup.create_fiscal_year_and_company(args)
|
||||||
create_employee_for_self(args)
|
company_setup.enable_shopping_cart(args)
|
||||||
set_defaults(args)
|
company_setup.create_bank_account(args)
|
||||||
create_territories()
|
|
||||||
create_feed_and_todo()
|
|
||||||
create_email_digest()
|
|
||||||
create_letter_head(args)
|
|
||||||
set_no_copy_fields_in_variant_settings()
|
|
||||||
|
|
||||||
if args.get('setup_website'):
|
def setup_taxes(args):
|
||||||
website_maker(args)
|
taxes_setup.create_sales_tax(args)
|
||||||
|
|
||||||
create_logo(args)
|
def stage_three(args):
|
||||||
|
defaults_setup.create_employee_for_self(args)
|
||||||
|
defaults_setup.set_default_settings(args)
|
||||||
|
defaults_setup.create_territories()
|
||||||
|
defaults_setup.create_feed_and_todo()
|
||||||
|
defaults_setup.set_no_copy_fields_in_variant_settings()
|
||||||
|
|
||||||
|
def stage_four(args):
|
||||||
|
company_setup.create_website(args)
|
||||||
|
company_setup.create_email_digest()
|
||||||
|
company_setup.create_logo(args)
|
||||||
|
|
||||||
|
def fin(args):
|
||||||
frappe.local.message_log = []
|
frappe.local.message_log = []
|
||||||
|
|
||||||
domains = args.get('domains')
|
|
||||||
domain_settings = frappe.get_single('Domain Settings')
|
|
||||||
domain_settings.set_active_domains(domains)
|
|
||||||
|
|
||||||
frappe.db.commit()
|
|
||||||
login_as_first_user(args)
|
login_as_first_user(args)
|
||||||
|
|
||||||
frappe.db.commit()
|
make_sample_data(args.get('domains'))
|
||||||
frappe.clear_cache()
|
|
||||||
|
|
||||||
|
def make_sample_data(domains):
|
||||||
try:
|
try:
|
||||||
make_sample_data(domains)
|
sample_data.make_sample_data(domains)
|
||||||
frappe.clear_cache()
|
|
||||||
except:
|
except:
|
||||||
# clear message
|
# clear message
|
||||||
if frappe.message_log:
|
if frappe.message_log:
|
||||||
frappe.message_log.pop()
|
frappe.message_log.pop()
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def create_fiscal_year_and_company(args):
|
|
||||||
if (args.get('fy_start_date')):
|
|
||||||
curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype":"Fiscal Year",
|
|
||||||
'year': curr_fiscal_year,
|
|
||||||
'year_start_date': args.get('fy_start_date'),
|
|
||||||
'year_end_date': args.get('fy_end_date'),
|
|
||||||
}).insert()
|
|
||||||
args["curr_fiscal_year"] = curr_fiscal_year
|
|
||||||
|
|
||||||
# Company
|
|
||||||
if (args.get('company_name')):
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype":"Company",
|
|
||||||
'company_name':args.get('company_name'),
|
|
||||||
'enable_perpetual_inventory': 1,
|
|
||||||
'abbr':args.get('company_abbr'),
|
|
||||||
'default_currency':args.get('currency'),
|
|
||||||
'country': args.get('country'),
|
|
||||||
'create_chart_of_accounts_based_on': 'Standard Template',
|
|
||||||
'chart_of_accounts': args.get('chart_of_accounts'),
|
|
||||||
'domain': args.get('domains')[0]
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
#Enable shopping cart
|
|
||||||
enable_shopping_cart(args)
|
|
||||||
|
|
||||||
# Bank Account
|
|
||||||
create_bank_account(args)
|
|
||||||
|
|
||||||
def enable_shopping_cart(args):
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Shopping Cart Settings",
|
|
||||||
"enabled": 1,
|
|
||||||
'company': args.get('company_name') ,
|
|
||||||
'price_list': frappe.db.get_value("Price List", {"selling": 1}),
|
|
||||||
'default_customer_group': _("Individual"),
|
|
||||||
'quotation_series': "QTN-",
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
def create_bank_account(args):
|
|
||||||
if args.get("bank_account"):
|
|
||||||
company_name = args.get('company_name')
|
|
||||||
bank_account_group = frappe.db.get_value("Account",
|
|
||||||
{"account_type": "Bank", "is_group": 1, "root_type": "Asset",
|
|
||||||
"company": company_name})
|
|
||||||
if bank_account_group:
|
|
||||||
bank_account = frappe.get_doc({
|
|
||||||
"doctype": "Account",
|
|
||||||
'account_name': args.get("bank_account"),
|
|
||||||
'parent_account': bank_account_group,
|
|
||||||
'is_group':0,
|
|
||||||
'company': company_name,
|
|
||||||
"account_type": "Bank",
|
|
||||||
})
|
|
||||||
try:
|
|
||||||
return bank_account.insert()
|
|
||||||
except RootNotEditable:
|
|
||||||
frappe.throw(_("Bank account cannot be named as {0}").format(args.get("bank_account")))
|
|
||||||
except frappe.DuplicateEntryError:
|
|
||||||
# bank account same as a CoA entry
|
|
||||||
pass
|
|
||||||
|
|
||||||
def create_price_lists(args):
|
|
||||||
for pl_type, pl_name in (("Selling", _("Standard Selling")), ("Buying", _("Standard Buying"))):
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Price List",
|
|
||||||
"price_list_name": pl_name,
|
|
||||||
"enabled": 1,
|
|
||||||
"buying": 1 if pl_type == "Buying" else 0,
|
|
||||||
"selling": 1 if pl_type == "Selling" else 0,
|
|
||||||
"currency": args["currency"]
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
def set_defaults(args):
|
|
||||||
# enable default currency
|
|
||||||
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
|
|
||||||
|
|
||||||
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
|
|
||||||
global_defaults.update({
|
|
||||||
'current_fiscal_year': args.get('curr_fiscal_year'),
|
|
||||||
'default_currency': args.get('currency'),
|
|
||||||
'default_company':args.get('company_name') ,
|
|
||||||
"country": args.get("country"),
|
|
||||||
})
|
|
||||||
|
|
||||||
global_defaults.save()
|
|
||||||
|
|
||||||
system_settings = frappe.get_doc("System Settings")
|
|
||||||
system_settings.email_footer_address = args.get("company")
|
|
||||||
system_settings.save()
|
|
||||||
|
|
||||||
stock_settings = frappe.get_doc("Stock Settings")
|
|
||||||
stock_settings.item_naming_by = "Item Code"
|
|
||||||
stock_settings.valuation_method = "FIFO"
|
|
||||||
stock_settings.default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})
|
|
||||||
stock_settings.stock_uom = _("Nos")
|
|
||||||
stock_settings.auto_indent = 1
|
|
||||||
stock_settings.auto_insert_price_list_rate_if_missing = 1
|
|
||||||
stock_settings.automatically_set_serial_nos_based_on_fifo = 1
|
|
||||||
stock_settings.save()
|
|
||||||
|
|
||||||
selling_settings = frappe.get_doc("Selling Settings")
|
|
||||||
selling_settings.cust_master_name = "Customer Name"
|
|
||||||
selling_settings.so_required = "No"
|
|
||||||
selling_settings.dn_required = "No"
|
|
||||||
selling_settings.allow_multiple_items = 1
|
|
||||||
selling_settings.save()
|
|
||||||
|
|
||||||
buying_settings = frappe.get_doc("Buying Settings")
|
|
||||||
buying_settings.supp_master_name = "Supplier Name"
|
|
||||||
buying_settings.po_required = "No"
|
|
||||||
buying_settings.pr_required = "No"
|
|
||||||
buying_settings.maintain_same_rate = 1
|
|
||||||
buying_settings.allow_multiple_items = 1
|
|
||||||
buying_settings.save()
|
|
||||||
|
|
||||||
notification_control = frappe.get_doc("Notification Control")
|
|
||||||
notification_control.quotation = 1
|
|
||||||
notification_control.sales_invoice = 1
|
|
||||||
notification_control.purchase_order = 1
|
|
||||||
notification_control.save()
|
|
||||||
|
|
||||||
hr_settings = frappe.get_doc("HR Settings")
|
|
||||||
hr_settings.emp_created_by = "Naming Series"
|
|
||||||
hr_settings.save()
|
|
||||||
|
|
||||||
def create_feed_and_todo():
|
|
||||||
"""update Activity feed and create todo for creation of item, customer, vendor"""
|
|
||||||
add_info_comment(**{
|
|
||||||
"subject": _("ERPNext Setup Complete!")
|
|
||||||
})
|
|
||||||
|
|
||||||
def create_email_digest():
|
|
||||||
from frappe.utils.user import get_system_managers
|
|
||||||
system_managers = get_system_managers(only_name=True)
|
|
||||||
if not system_managers:
|
|
||||||
return
|
|
||||||
|
|
||||||
companies = frappe.db.sql_list("select name FROM `tabCompany`")
|
|
||||||
for company in companies:
|
|
||||||
if not frappe.db.exists("Email Digest", "Default Weekly Digest - " + company):
|
|
||||||
edigest = frappe.get_doc({
|
|
||||||
"doctype": "Email Digest",
|
|
||||||
"name": "Default Weekly Digest - " + company,
|
|
||||||
"company": company,
|
|
||||||
"frequency": "Weekly",
|
|
||||||
"recipient_list": "\n".join(system_managers)
|
|
||||||
})
|
|
||||||
|
|
||||||
for df in edigest.meta.get("fields", {"fieldtype": "Check"}):
|
|
||||||
if df.fieldname != "scheduler_errors":
|
|
||||||
edigest.set(df.fieldname, 1)
|
|
||||||
|
|
||||||
edigest.insert()
|
|
||||||
|
|
||||||
# scheduler errors digest
|
|
||||||
if companies:
|
|
||||||
edigest = frappe.new_doc("Email Digest")
|
|
||||||
edigest.update({
|
|
||||||
"name": "Scheduler Errors",
|
|
||||||
"company": companies[0],
|
|
||||||
"frequency": "Daily",
|
|
||||||
"recipient_list": "\n".join(system_managers),
|
|
||||||
"scheduler_errors": 1,
|
|
||||||
"enabled": 1
|
|
||||||
})
|
|
||||||
edigest.insert()
|
|
||||||
|
|
||||||
def get_fy_details(fy_start_date, fy_end_date):
|
|
||||||
start_year = getdate(fy_start_date).year
|
|
||||||
if start_year == getdate(fy_end_date).year:
|
|
||||||
fy = cstr(start_year)
|
|
||||||
else:
|
|
||||||
fy = cstr(start_year) + '-' + cstr(start_year + 1)
|
|
||||||
return fy
|
|
||||||
|
|
||||||
def create_sales_tax(args):
|
|
||||||
country_wise_tax = get_country_wise_tax(args.get("country"))
|
|
||||||
if country_wise_tax and len(country_wise_tax) > 0:
|
|
||||||
for sales_tax, tax_data in country_wise_tax.items():
|
|
||||||
make_tax_account_and_template(
|
|
||||||
args.get("company_name"),
|
|
||||||
tax_data.get('account_name'),
|
|
||||||
tax_data.get('tax_rate'), sales_tax)
|
|
||||||
|
|
||||||
# Tax utils start
|
|
||||||
def make_tax_account_and_template(company, account_name, tax_rate, template_name=None):
|
|
||||||
try:
|
|
||||||
if not isinstance(account_name, (list, tuple)):
|
|
||||||
account_name = [account_name]
|
|
||||||
tax_rate = [tax_rate]
|
|
||||||
|
|
||||||
accounts = []
|
|
||||||
for i, name in enumerate(account_name):
|
|
||||||
tax_account = make_tax_account(company, account_name[i], tax_rate[i])
|
|
||||||
if tax_account:
|
|
||||||
accounts.append(tax_account)
|
|
||||||
|
|
||||||
if accounts:
|
|
||||||
make_sales_and_purchase_tax_templates(accounts, template_name)
|
|
||||||
except frappe.NameError:
|
|
||||||
pass
|
|
||||||
except RootNotEditable:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def make_tax_account(company, account_name, tax_rate):
|
|
||||||
tax_group = get_tax_account_group(company)
|
|
||||||
if tax_group:
|
|
||||||
return frappe.get_doc({
|
|
||||||
"doctype":"Account",
|
|
||||||
"company": company,
|
|
||||||
"parent_account": tax_group,
|
|
||||||
"account_name": account_name,
|
|
||||||
"is_group": 0,
|
|
||||||
"report_type": "Balance Sheet",
|
|
||||||
"root_type": "Liability",
|
|
||||||
"account_type": "Tax",
|
|
||||||
"tax_rate": flt(tax_rate) if tax_rate else None
|
|
||||||
}).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
def make_sales_and_purchase_tax_templates(accounts, template_name=None):
|
|
||||||
if not template_name:
|
|
||||||
template_name = accounts[0].name
|
|
||||||
|
|
||||||
sales_tax_template = {
|
|
||||||
"doctype": "Sales Taxes and Charges Template",
|
|
||||||
"title": template_name,
|
|
||||||
"company": accounts[0].company,
|
|
||||||
'taxes': []
|
|
||||||
}
|
|
||||||
|
|
||||||
for account in accounts:
|
|
||||||
sales_tax_template['taxes'].append({
|
|
||||||
"category": "Valuation and Total",
|
|
||||||
"charge_type": "On Net Total",
|
|
||||||
"account_head": account.name,
|
|
||||||
"description": "{0} @ {1}".format(account.account_name, account.tax_rate),
|
|
||||||
"rate": account.tax_rate
|
|
||||||
})
|
|
||||||
# Sales
|
|
||||||
frappe.get_doc(copy.deepcopy(sales_tax_template)).insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
# Purchase
|
|
||||||
purchase_tax_template = copy.deepcopy(sales_tax_template)
|
|
||||||
purchase_tax_template["doctype"] = "Purchase Taxes and Charges Template"
|
|
||||||
|
|
||||||
doc = frappe.get_doc(purchase_tax_template)
|
|
||||||
doc.insert(ignore_permissions=True)
|
|
||||||
|
|
||||||
def get_tax_account_group(company):
|
|
||||||
tax_group = frappe.db.get_value("Account",
|
|
||||||
{"account_name": "Duties and Taxes", "is_group": 1, "company": company})
|
|
||||||
if not tax_group:
|
|
||||||
tax_group = frappe.db.get_value("Account", {"is_group": 1, "root_type": "Liability",
|
|
||||||
"account_type": "Tax", "company": company})
|
|
||||||
|
|
||||||
return tax_group
|
|
||||||
|
|
||||||
# Tax utils end
|
|
||||||
|
|
||||||
def get_country_wise_tax(country):
|
|
||||||
data = {}
|
|
||||||
with open (os.path.join(os.path.dirname(__file__), "data", "country_wise_tax.json")) as countrywise_tax:
|
|
||||||
data = json.load(countrywise_tax).get(country)
|
|
||||||
|
|
||||||
return data
|
|
||||||
|
|
||||||
def create_letter_head(args):
|
|
||||||
if args.get("attach_letterhead"):
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype":"Letter Head",
|
|
||||||
"letter_head_name": _("Standard"),
|
|
||||||
"is_default": 1
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
attach_letterhead = args.get("attach_letterhead").split(",")
|
|
||||||
if len(attach_letterhead)==3:
|
|
||||||
filename, filetype, content = attach_letterhead
|
|
||||||
fileurl = save_file(filename, content, "Letter Head", _("Standard"), decode=True).file_url
|
|
||||||
frappe.db.set_value("Letter Head", _("Standard"), "content", "<img src='%s' style='max-width: 100%%;'>" % fileurl)
|
|
||||||
|
|
||||||
def set_no_copy_fields_in_variant_settings():
|
|
||||||
# set no copy fields of an item doctype to item variant settings
|
|
||||||
doc = frappe.get_doc('Item Variant Settings')
|
|
||||||
doc.set_default_fields()
|
|
||||||
doc.save()
|
|
||||||
|
|
||||||
def create_logo(args):
|
|
||||||
if args.get("attach_logo"):
|
|
||||||
attach_logo = args.get("attach_logo").split(",")
|
|
||||||
if len(attach_logo)==3:
|
|
||||||
filename, filetype, content = attach_logo
|
|
||||||
fileurl = save_file(filename, content, "Website Settings", "Website Settings",
|
|
||||||
decode=True).file_url
|
|
||||||
frappe.db.set_value("Website Settings", "Website Settings", "brand_html",
|
|
||||||
"<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name") ))
|
|
||||||
|
|
||||||
def create_territories():
|
|
||||||
"""create two default territories, one for home country and one named Rest of the World"""
|
|
||||||
from frappe.utils.nestedset import get_root_of
|
|
||||||
country = frappe.db.get_default("country")
|
|
||||||
root_territory = get_root_of("Territory")
|
|
||||||
for name in (country, _("Rest Of The World")):
|
|
||||||
if name and not frappe.db.exists("Territory", name):
|
|
||||||
frappe.get_doc({
|
|
||||||
"doctype": "Territory",
|
|
||||||
"territory_name": name.replace("'", ""),
|
|
||||||
"parent_territory": root_territory,
|
|
||||||
"is_group": "No"
|
|
||||||
}).insert()
|
|
||||||
|
|
||||||
def login_as_first_user(args):
|
def login_as_first_user(args):
|
||||||
if args.get("email") and hasattr(frappe.local, "login_manager"):
|
if args.get("email") and hasattr(frappe.local, "login_manager"):
|
||||||
frappe.local.login_manager.login_as(args.get("email"))
|
frappe.local.login_manager.login_as(args.get("email"))
|
||||||
|
|
||||||
def create_employee_for_self(args):
|
|
||||||
if frappe.session.user == 'Administrator':
|
|
||||||
return
|
|
||||||
|
|
||||||
# create employee for self
|
|
||||||
emp = frappe.get_doc({
|
|
||||||
"doctype": "Employee",
|
|
||||||
"employee_name": " ".join(filter(None, [args.get("first_name"), args.get("last_name")])),
|
|
||||||
"user_id": frappe.session.user,
|
|
||||||
"status": "Active",
|
|
||||||
"company": args.get("company_name")
|
|
||||||
})
|
|
||||||
emp.flags.ignore_mandatory = True
|
|
||||||
emp.insert(ignore_permissions = True)
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user