brotherton-erpnext/erpnext/setup/page/setup_wizard/setup_wizard.py

581 lines
17 KiB
Python
Raw Normal View History

# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
2013-10-08 12:29:11 +00:00
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe, json, copy
2013-10-08 12:29:11 +00:00
2014-04-22 10:00:05 +00:00
from frappe.utils import cstr, flt, getdate
from frappe import _
2014-02-14 10:17:51 +00:00
from frappe.utils.file_manager import save_file
2015-02-12 13:28:28 +00:00
from frappe.translate import (set_default_language, get_dict,
get_lang_dict, send_translations, get_language_from_code)
2014-09-09 07:08:21 +00:00
from frappe.geo.country_info import get_country_info
2014-04-21 08:13:11 +00:00
from frappe.utils.nestedset import get_root_of
2015-04-01 16:31:54 +00:00
from .default_website import website_maker
import install_fixtures
from .sample_data import make_sample_data
from erpnext.accounts.utils import FiscalYearError
2013-10-08 12:29:11 +00:00
2014-02-14 10:17:51 +00:00
@frappe.whitelist()
2013-10-08 12:29:11 +00:00
def setup_account(args=None):
2014-05-12 07:07:32 +00:00
try:
if frappe.db.sql("select name from tabCompany"):
frappe.throw(_("Setup Already Complete!!"))
2014-04-07 09:39:09 +00:00
2014-05-12 07:07:32 +00:00
if not args:
args = frappe.local.form_dict
if isinstance(args, basestring):
args = json.loads(args)
2014-04-07 09:39:09 +00:00
2014-05-12 07:07:32 +00:00
args = frappe._dict(args)
if args.language and args.language != "english":
2014-05-12 07:07:32 +00:00
set_default_language(args.language)
2014-05-12 07:07:32 +00:00
install_fixtures.install(args.get("country"))
2014-05-12 07:07:32 +00:00
update_user_name(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_fiscal_year_and_company(args)
frappe.local.message_log = []
create_users(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
set_defaults(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_territories()
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_price_lists(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_feed_and_todo()
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_email_digest()
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_letter_head(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_taxes(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_items(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_customers(args)
frappe.local.message_log = []
2014-05-12 07:07:32 +00:00
create_suppliers(args)
frappe.local.message_log = []
2013-10-08 12:29:11 +00:00
2014-05-12 07:07:32 +00:00
frappe.db.set_default('desktop:home_page', 'desktop')
2014-10-15 08:25:37 +00:00
website_maker(args.company_name.strip(), args.company_tagline, args.name)
2014-05-12 07:07:32 +00:00
create_logo(args)
2014-04-07 09:39:09 +00:00
2015-04-01 16:31:54 +00:00
frappe.db.commit()
login_as_first_user(args)
2014-05-12 07:07:32 +00:00
frappe.db.commit()
2014-05-21 09:52:15 +00:00
2015-03-20 08:48:09 +00:00
frappe.clear_cache()
if args.get("add_sample_data"):
try:
make_sample_data()
except FiscalYearError:
pass
2014-05-12 07:07:32 +00:00
except:
2014-10-13 06:02:41 +00:00
if args:
traceback = frappe.get_traceback()
for hook in frappe.get_hooks("setup_wizard_exception"):
frappe.get_attr(hook)(traceback, args)
2014-05-12 07:07:32 +00:00
raise
2014-04-07 09:39:09 +00:00
2014-05-21 09:52:15 +00:00
else:
for hook in frappe.get_hooks("setup_wizard_success"):
frappe.get_attr(hook)(args)
def update_user_name(args):
2013-10-08 12:53:05 +00:00
if args.get("email"):
2013-10-08 12:29:11 +00:00
args['name'] = args.get("email")
2014-02-14 10:17:51 +00:00
frappe.flags.mute_emails = True
2015-04-07 05:33:58 +00:00
doc = frappe.get_doc({
"doctype":"User",
2013-10-08 12:29:11 +00:00
"email": args.get("email"),
"first_name": args.get("first_name"),
"last_name": args.get("last_name")
2015-04-07 05:33:58 +00:00
})
doc.flags.no_welcome_mail = True
doc.insert()
2014-02-14 10:17:51 +00:00
frappe.flags.mute_emails = False
from frappe.auth import _update_password
2013-10-08 12:29:11 +00:00
_update_password(args.get("email"), args.get("password"))
else:
2014-02-14 10:17:51 +00:00
args['name'] = frappe.session.user
2013-10-08 12:29:11 +00:00
# Update User
2014-04-07 09:39:09 +00:00
if not args.get('last_name') or args.get('last_name')=='None':
2013-10-08 12:29:11 +00:00
args['last_name'] = None
frappe.db.sql("""update `tabUser` SET first_name=%(first_name)s,
2013-10-08 12:29:11 +00:00
last_name=%(last_name)s WHERE name=%(name)s""", args)
2014-04-07 09:39:09 +00:00
if args.get("attach_user"):
attach_user = args.get("attach_user").split(",")
if len(attach_user)==3:
filename, filetype, content = attach_user
fileurl = save_file(filename, content, "User", args.get("name"), decode=True).file_url
frappe.db.set_value("User", args.get("name"), "user_image", fileurl)
2014-04-07 09:39:09 +00:00
2013-10-08 12:29:11 +00:00
add_all_roles_to(args.get("name"))
2014-04-07 09:39:09 +00:00
2013-10-08 12:29:11 +00:00
def create_fiscal_year_and_company(args):
curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
frappe.get_doc({
2013-10-08 12:29:11 +00:00
"doctype":"Fiscal Year",
'year': curr_fiscal_year,
'year_start_date': args.get('fy_start_date'),
'year_end_date': args.get('fy_end_date'),
}).insert()
2013-10-08 12:29:11 +00:00
# Company
frappe.get_doc({
2013-10-08 12:29:11 +00:00
"doctype":"Company",
'domain': args.get("industry"),
2014-10-15 08:25:37 +00:00
'company_name':args.get('company_name').strip(),
2013-10-08 12:29:11 +00:00
'abbr':args.get('company_abbr'),
'default_currency':args.get('currency'),
'country': args.get('country'),
'chart_of_accounts': args.get(('chart_of_accounts')),
}).insert()
2014-04-07 09:39:09 +00:00
2015-01-19 12:04:33 +00:00
# Bank Account
2013-10-08 12:29:11 +00:00
args["curr_fiscal_year"] = curr_fiscal_year
2014-04-07 09:39:09 +00:00
2013-10-08 12:29:11 +00:00
def create_price_lists(args):
2014-05-13 15:32:47 +00:00
for pl_type, pl_name in (("Selling", _("Standard Selling")), ("Buying", _("Standard Buying"))):
frappe.get_doc({
"doctype": "Price List",
2014-05-13 15:32:47 +00:00
"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"],
"territories": [{
2014-04-21 08:13:11 +00:00
"territory": get_root_of("Territory")
}]
}).insert()
2014-04-07 09:39:09 +00:00
2013-10-08 12:29:11 +00:00
def set_defaults(args):
# enable default currency
2014-02-26 07:05:33 +00:00
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
2014-04-07 09:39:09 +00:00
2014-03-28 11:14:37 +00:00
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
global_defaults.update({
2013-10-08 12:29:11 +00:00
'current_fiscal_year': args.curr_fiscal_year,
'default_currency': args.get('currency'),
2014-10-15 08:25:37 +00:00
'default_company':args.get('company_name').strip(),
"country": args.get("country"),
2013-10-08 12:29:11 +00:00
})
2013-10-08 12:29:11 +00:00
global_defaults.save()
2014-04-07 09:39:09 +00:00
number_format = get_country_info(args.get("country")).get("number_format", "#,###.##")
# replace these as float number formats, as they have 0 precision
# and are currency number formats and not for floats
if number_format=="#.###":
number_format = "#.###,##"
elif number_format=="#,###":
number_format = "#,###.##"
system_settings = frappe.get_doc("System Settings", "System Settings")
system_settings.update({
"language": args.get("language"),
"time_zone": args.get("timezone"),
"float_precision": 3,
2015-05-25 05:20:48 +00:00
"email_footer_address": args.get("company"),
'date_format': frappe.db.get_value("Country", args.get("country"), "date_format"),
'number_format': number_format,
2015-04-06 13:59:16 +00:00
'enable_scheduler': 1 if not frappe.flags.in_test else 0
})
system_settings.save()
2014-03-28 11:14:37 +00:00
accounts_settings = frappe.get_doc("Accounts Settings")
accounts_settings.auto_accounting_for_stock = 1
2013-10-08 12:29:11 +00:00
accounts_settings.save()
2014-03-28 11:14:37 +00:00
stock_settings = frappe.get_doc("Stock Settings")
stock_settings.item_naming_by = "Item Code"
stock_settings.valuation_method = "FIFO"
2014-05-16 18:37:45 +00:00
stock_settings.stock_uom = _("Nos")
stock_settings.auto_indent = 1
stock_settings.auto_insert_price_list_rate_if_missing = 1
2013-10-08 12:29:11 +00:00
stock_settings.save()
2014-04-07 09:39:09 +00:00
2014-03-28 11:14:37 +00:00
selling_settings = frappe.get_doc("Selling Settings")
selling_settings.cust_master_name = "Customer Name"
selling_settings.so_required = "No"
selling_settings.dn_required = "No"
2013-10-08 12:29:11 +00:00
selling_settings.save()
2014-03-28 11:14:37 +00:00
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
2013-10-08 12:29:11 +00:00
buying_settings.save()
2014-03-28 11:14:37 +00:00
notification_control = frappe.get_doc("Notification Control")
notification_control.quotation = 1
notification_control.sales_invoice = 1
notification_control.purchase_order = 1
2013-10-08 12:29:11 +00:00
notification_control.save()
2014-03-28 11:14:37 +00:00
hr_settings = frappe.get_doc("HR Settings")
hr_settings.emp_created_by = "Naming Series"
2013-10-08 12:29:11 +00:00
hr_settings.save()
def create_feed_and_todo():
2015-03-03 09:15:52 +00:00
"""update Activity feed and create todo for creation of item, customer, vendor"""
2014-09-09 10:45:35 +00:00
frappe.get_doc({
"doctype": "Feed",
2015-01-05 10:49:12 +00:00
"feed_type": "Comment",
2014-09-09 10:45:35 +00:00
"subject": "ERPNext Setup Complete!"
}).insert(ignore_permissions=True)
2013-10-08 12:29:11 +00:00
def create_email_digest():
from frappe.utils.user import get_system_managers
system_managers = get_system_managers(only_name=True)
2014-04-07 09:39:09 +00:00
if not system_managers:
2013-10-08 12:29:11 +00:00
return
2014-04-07 09:39:09 +00:00
2014-02-26 07:05:33 +00:00
companies = frappe.db.sql_list("select name FROM `tabCompany`")
2013-12-18 07:52:18 +00:00
for company in companies:
2014-02-26 07:05:33 +00:00
if not frappe.db.exists("Email Digest", "Default Weekly Digest - " + company):
2014-03-28 11:14:37 +00:00
edigest = frappe.get_doc({
2013-10-08 12:29:11 +00:00
"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)
2014-04-07 09:39:09 +00:00
2013-10-08 12:29:11 +00:00
edigest.insert()
2014-04-07 09:39:09 +00:00
# scheduler errors digest
2013-12-18 07:52:18 +00:00
if companies:
edigest = frappe.new_doc("Email Digest")
edigest.update({
2013-12-18 07:52:18 +00:00
"name": "Scheduler Errors",
"company": companies[0],
"frequency": "Daily",
"recipient_list": "\n".join(system_managers),
"scheduler_errors": 1,
"enabled": 1
})
edigest.insert()
2014-04-07 09:39:09 +00:00
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)
2013-10-08 12:29:11 +00:00
else:
fy = cstr(start_year) + '-' + cstr(start_year + 1)
return fy
2013-10-08 12:29:11 +00:00
def create_taxes(args):
for i in xrange(1,6):
if args.get("tax_" + str(i)):
2014-04-22 10:00:05 +00:00
# replace % in case someone also enters the % symbol
tax_rate = (args.get("tax_rate_" + str(i)) or "").replace("%", "")
2014-05-03 10:52:25 +00:00
try:
2014-11-14 12:43:17 +00:00
tax_group = frappe.db.get_value("Account", {"company": args.get("company_name"),
2015-04-23 07:44:17 +00:00
"is_group": 1, "account_type": "Tax", "root_type": "Liability"})
2014-11-14 12:43:17 +00:00
if tax_group:
account = make_tax_head(args, i, tax_group, tax_rate)
make_sales_and_purchase_tax_templates(account)
2014-05-03 10:52:25 +00:00
except frappe.NameError, e:
if e.args[2][0]==1062:
pass
else:
raise
def make_tax_head(args, i, tax_group, tax_rate):
return frappe.get_doc({
"doctype":"Account",
"company": args.get("company_name").strip(),
"parent_account": tax_group,
"account_name": args.get("tax_" + str(i)),
"is_group": 0,
"report_type": "Balance Sheet",
"account_type": "Tax",
"tax_rate": flt(tax_rate) if tax_rate else None
}).insert(ignore_permissions=True)
def make_sales_and_purchase_tax_templates(account):
doc = {
"doctype": "Sales Taxes and Charges Template",
"title": account.name,
"taxes": [{
"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(doc)).insert()
# Purchase
doc["doctype"] = "Purchase Taxes and Charges Template"
frappe.get_doc(copy.deepcopy(doc)).insert()
2013-10-08 12:29:11 +00:00
def create_items(args):
for i in xrange(1,6):
item = args.get("item_" + str(i))
if item:
item_group = args.get("item_group_" + str(i))
is_sales_item = args.get("is_sales_item_" + str(i))
is_purchase_item = args.get("is_purchase_item_" + str(i))
is_stock_item = item_group!=_("Services")
default_warehouse = ""
if is_stock_item:
2015-01-10 10:33:49 +00:00
default_warehouse = frappe.db.get_value("Warehouse", filters={
"warehouse_name": _("Finished Goods") if is_sales_item else _("Stores"),
"company": args.get("company_name").strip()
})
2015-04-23 07:44:17 +00:00
try:
frappe.get_doc({
"doctype":"Item",
"item_code": item,
"item_name": item,
"description": item,
"is_sales_item": 1 if is_sales_item else 0,
"is_purchase_item": 1 if is_purchase_item else 0,
2015-04-23 07:44:17 +00:00
"show_in_website": 1,
"is_stock_item": is_stock_item and 1 or 0,
2015-04-23 07:44:17 +00:00
"item_group": item_group,
"stock_uom": args.get("item_uom_" + str(i)),
"default_warehouse": default_warehouse
}).insert()
if args.get("item_img_" + str(i)):
item_image = args.get("item_img_" + str(i)).split(",")
if len(item_image)==3:
filename, filetype, content = item_image
fileurl = save_file(filename, content, "Item", item, decode=True).file_url
frappe.db.set_value("Item", item, "image", fileurl)
if args.get("item_price_" + str(i)):
item_price = flt(args.get("item_price_" + str(i)))
if is_sales_item:
price_list_name = frappe.db.get_value("Price List", {"selling": 1})
make_item_price(item, price_list_name, item_price)
if is_purchase_item:
price_list_name = frappe.db.get_value("Price List", {"buying": 1})
make_item_price(item, price_list_name, item_price)
2015-04-23 07:44:17 +00:00
except frappe.NameError:
pass
2013-10-08 12:29:11 +00:00
def make_item_price(item, price_list_name, item_price):
frappe.get_doc({
"doctype": "Item Price",
"price_list": price_list_name,
"item_code": item,
"price_list_rate": item_price
}).insert()
2013-10-08 12:29:11 +00:00
def create_customers(args):
for i in xrange(1,6):
customer = args.get("customer_" + str(i))
if customer:
2015-04-23 07:44:17 +00:00
try:
2014-03-28 11:14:37 +00:00
frappe.get_doc({
2015-04-23 07:44:17 +00:00
"doctype":"Customer",
"customer_name": customer,
"customer_type": "Company",
"customer_group": _("Commercial"),
"territory": args.get("country"),
"company": args.get("company_name").strip()
2013-10-08 12:29:11 +00:00
}).insert()
2014-04-07 09:39:09 +00:00
2015-04-23 07:44:17 +00:00
if args.get("customer_contact_" + str(i)):
2015-07-23 07:09:44 +00:00
create_contact(args.get("customer_contact_" + str(i)),
"customer", customer)
2015-04-23 07:44:17 +00:00
except frappe.NameError:
pass
2013-10-08 12:29:11 +00:00
def create_suppliers(args):
for i in xrange(1,6):
supplier = args.get("supplier_" + str(i))
if supplier:
2015-04-23 07:44:17 +00:00
try:
2014-03-28 11:14:37 +00:00
frappe.get_doc({
2015-04-23 07:44:17 +00:00
"doctype":"Supplier",
"supplier_name": supplier,
"supplier_type": _("Local"),
"company": args.get("company_name").strip()
2013-10-08 12:29:11 +00:00
}).insert()
2015-04-23 07:44:17 +00:00
if args.get("supplier_contact_" + str(i)):
2015-07-23 07:09:44 +00:00
create_contact(args.get("supplier_contact_" + str(i)),
"supplier", supplier)
2015-04-23 07:44:17 +00:00
except frappe.NameError:
pass
2015-07-23 07:09:44 +00:00
def create_contact(contact, party_type, party):
"""Create contact based on given contact name"""
contact = contact.strip().split(" ")
frappe.get_doc({
"doctype":"Contact",
party_type: party,
"first_name":contact[0],
"last_name": len(contact) > 1 and contact[1] or ""
}).insert()
def create_letter_head(args):
if args.get("attach_letterhead"):
frappe.get_doc({
"doctype":"Letter Head",
"letter_head_name": _("Standard"),
"is_default": 1
}).insert()
2014-04-07 09:39:09 +00:00
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)
2014-04-07 09:39:09 +00:00
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
2015-03-24 12:04:58 +00:00
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").strip()))
2013-10-08 12:29:11 +00:00
def add_all_roles_to(name):
2014-03-27 10:42:56 +00:00
user = frappe.get_doc("User", name)
2014-02-26 07:05:33 +00:00
for role in frappe.db.sql("""select name from tabRole"""):
2014-05-28 13:19:13 +00:00
if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner", "Employee"]:
2014-03-27 10:42:56 +00:00
d = user.append("user_roles")
2013-10-08 12:29:11 +00:00
d.role = role[0]
2014-03-27 10:42:56 +00:00
user.save()
2013-10-08 12:29:11 +00:00
def create_territories():
"""create two default territories, one for home country and one named Rest of the World"""
2014-02-14 10:17:51 +00:00
from frappe.utils.nestedset import get_root_of
2014-04-04 06:30:36 +00:00
country = frappe.db.get_default("country")
2013-10-08 12:29:11 +00:00
root_territory = get_root_of("Territory")
for name in (country, _("Rest Of The World")):
2014-02-26 07:05:33 +00:00
if name and not frappe.db.exists("Territory", name):
2014-03-28 11:14:37 +00:00
frappe.get_doc({
2013-10-08 12:29:11 +00:00
"doctype": "Territory",
"territory_name": name.replace("'", ""),
"parent_territory": root_territory,
"is_group": "No"
2014-04-07 09:39:09 +00:00
}).insert()
def login_as_first_user(args):
2015-02-17 14:25:17 +00:00
if args.get("email") and hasattr(frappe.local, "login_manager"):
2015-04-02 13:25:36 +00:00
frappe.local.login_manager.login_as(args.get("email"))
def create_users(args):
# create employee for self
emp = frappe.get_doc({
"doctype": "Employee",
"full_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)
for i in xrange(1,5):
email = args.get("user_email_" + str(i))
fullname = args.get("user_fullname_" + str(i))
if email:
if not fullname:
fullname = email.split("@")[0]
parts = fullname.split(" ", 1)
user = frappe.get_doc({
"doctype": "User",
"email": email,
"first_name": parts[0],
"last_name": parts[1] if len(parts) > 1 else "",
"enabled": 1,
"user_type": "System User"
})
# default roles
user.append_roles("Projects User", "Stock User", "Support Team")
if args.get("user_sales_" + str(i)):
user.append_roles("Sales User", "Sales Manager", "Accounts User")
if args.get("user_purchaser_" + str(i)):
user.append_roles("Purchase User", "Purchase Manager", "Accounts User")
if args.get("user_accountant_" + str(i)):
user.append_roles("Accounts Manager", "Accounts User")
user.flags.delay_emails = True
if not frappe.db.get_value("User", email):
user.insert(ignore_permissions=True)
# create employee
emp = frappe.get_doc({
"doctype": "Employee",
"full_name": fullname,
"user_id": email,
"status": "Active",
"company": args.get("company_name")
})
emp.flags.ignore_mandatory = True
emp.insert(ignore_permissions = True)
@frappe.whitelist()
def load_messages(language):
frappe.clear_cache()
set_default_language(language)
m = get_dict("page", "setup-wizard")
m.update(get_dict("boot"))
2014-08-27 09:23:54 +00:00
send_translations(m)
return frappe.local.lang
@frappe.whitelist()
def load_languages():
2015-02-12 13:28:28 +00:00
return {
"default_language": get_language_from_code(frappe.local.lang),
"languages": sorted(get_lang_dict().keys())
}