diff --git a/erpnext/__init__.py b/erpnext/__init__.py index c4c319fa63..0090e7557a 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '7.2.29' +__version__ = '7.2.30' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 66b3dd0a94..f8c9c0a841 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -169,7 +169,7 @@ def make_variant_item_code(template_item_code, variant): item_attribute = frappe.db.sql("""select i.numeric_values, v.abbr from `tabItem Attribute` i left join `tabItem Attribute Value` v on (i.name=v.parent) - where i.name=%(attribute)s and v.attribute_value=%(attribute_value)s""", { + where i.name=%(attribute)s and (v.attribute_value=%(attribute_value)s or i.numeric_values = 1)""", { "attribute": attr.attribute, "attribute_value": attr.attribute_value }, as_dict=True) @@ -180,11 +180,8 @@ def make_variant_item_code(template_item_code, variant): # frappe.bold(attr.attribute_value)), title=_('Invalid Attribute'), # exc=InvalidItemAttributeValueError) - if item_attribute[0].numeric_values: - # don't generate item code if one of the attributes is numeric - return - - abbreviations.append(item_attribute[0].abbr) + abbr_or_value = cstr(attr.attribute_value) if item_attribute[0].numeric_values else item_attribute[0].abbr + abbreviations.append(abbr_or_value) if abbreviations: variant.item_code = "{0}-{1}".format(template_item_code, "-".join(abbreviations)) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 4b20ec8d81..f5bc7dbc04 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -51,7 +51,9 @@ class SalesOrder(SellingController): # validate transaction date v/s delivery date if self.delivery_date: if getdate(self.transaction_date) > getdate(self.delivery_date): - frappe.throw(_("Expected Delivery Date cannot be before Sales Order Date")) + frappe.msgprint(_("Expected Delivery Date is be before Sales Order Date"), + indicator='orange', + title=_('Warning')) def validate_po(self): # validate p.o date v/s delivery date @@ -82,7 +84,8 @@ class SalesOrder(SellingController): unique_chk_list = set(check_list) if len(unique_chk_list) != len(check_list) and \ not cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")): - frappe.msgprint(_("Warning: Same item has been entered multiple times.")) + frappe.msgprint(_("Same item has been entered multiple times"), + title=_("Warning"), indicator='orange') def product_bundle_has_stock_item(self, product_bundle): """Returns true if product bundle has stock item""" diff --git a/erpnext/setup/setup_wizard/domainify.py b/erpnext/setup/setup_wizard/domainify.py index 59636758ca..69aaf752d4 100644 --- a/erpnext/setup/setup_wizard/domainify.py +++ b/erpnext/setup/setup_wizard/domainify.py @@ -22,8 +22,8 @@ def get_domain(domain): }, 'Retail': { - 'desktop_icons': ['POS', 'Item', 'Customer', 'Sales Invoice', 'Purchase Order', 'Warranty Claim', - 'Accounts', 'Buying', 'ToDo'], + 'desktop_icons': ['POS', 'Item', 'Customer', 'Sales Invoice', 'Purchase Order', + 'Warranty Claim', 'Accounts', 'Task', 'Buying', 'ToDo'], 'remove_roles': ['Manufacturing User', 'Manufacturing Manager', 'Academics User'], 'properties': [ {'doctype': 'Item', 'fieldname': 'manufacturing', 'property': 'hidden', 'value': 1}, @@ -36,7 +36,7 @@ def get_domain(domain): }, 'Distribution': { - 'desktop_icons': ['Item', 'Customer', 'Supplier', 'Lead', 'Sales Order', + 'desktop_icons': ['Item', 'Customer', 'Supplier', 'Lead', 'Sales Order', 'Task', 'Sales Invoice', 'CRM', 'Selling', 'Buying', 'Stock', 'Accounts', 'HR', 'ToDo'], 'remove_roles': ['Manufacturing User', 'Manufacturing Manager', 'Academics User'], 'set_value': [ @@ -46,8 +46,8 @@ def get_domain(domain): }, 'Services': { - 'desktop_icons': ['Project', 'Timesheet', 'Customer', 'Sales Order', 'Sales Invoice', 'Lead', 'Opportunity', - 'Expense Claim', 'Employee', 'HR', 'ToDo'], + 'desktop_icons': ['Project', 'Timesheet', 'Customer', 'Sales Order', 'Sales Invoice', + 'Lead', 'Opportunity', 'Task', 'Expense Claim', 'Employee', 'HR', 'ToDo'], 'remove_roles': ['Manufacturing User', 'Manufacturing Manager', 'Academics User'], 'properties': [ {'doctype': 'Item', 'fieldname': 'is_stock_item', 'property': 'default', 'value': 0}, @@ -59,10 +59,10 @@ def get_domain(domain): }, 'Education': { 'desktop_icons': ['Student', 'Program', 'Course', 'Student Group', 'Instructor', - 'Fees', 'ToDo', 'Schools'], + 'Fees', 'Task', 'ToDo', 'Schools'], 'allow_roles': ['Academics User', 'Accounts User', 'Accounts Manager', 'Item Manager', 'Website Manager', 'HR User', 'HR Manager', 'Purchase User', 'Purchase Manager', - 'Student'], + 'Student', 'Projects User'], 'default_portal_role': 'Student' }, } diff --git a/erpnext/setup/setup_wizard/sample_data.py b/erpnext/setup/setup_wizard/sample_data.py index 955f6633ca..cfc6726d1c 100644 --- a/erpnext/setup/setup_wizard/sample_data.py +++ b/erpnext/setup/setup_wizard/sample_data.py @@ -6,9 +6,11 @@ from __future__ import unicode_literals import frappe from frappe.utils.make_random import add_random_children import frappe.utils -import random +import random, os, json +from frappe import _ +from markdown2 import markdown -def make_sample_data(): +def make_sample_data(args): """Create a few opportunities, quotes, material requests, issues, todos, projects to help the user get started""" items = frappe.get_all("Item", {'is_sales_item': 1}) @@ -22,7 +24,8 @@ def make_sample_data(): make_opportunity(items, customer) make_quote(items, customer) - make_projects() + make_projects(args.get('domain')) + import_email_alert() if items and warehouses: make_material_request(frappe.get_all("Item")) @@ -84,42 +87,91 @@ def make_material_request(items): def make_issue(): pass -def make_projects(): +def make_projects(domain): + current_date = frappe.utils.nowdate() project = frappe.get_doc({ "doctype": "Project", "project_name": "ERPNext Implementation", }) - current_date = frappe.utils.nowdate() - project.set("tasks", [ + + tasks = [ + { + "title": "Explore ERPNext", + "start_date": current_date, + "end_date": current_date, + "file": "explore.md" + }] + + if domain == 'Education': + tasks += [ { - "title": "Explore ERPNext", - "start_date": frappe.utils.add_days(current_date, 1), - "end_date": frappe.utils.add_days(current_date, 2) + "title": _("Setup your School in ERPNext"), + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 1), + "file": "school_masters.md" }, { - "title": "Run Sales Cycle", - "start_date": frappe.utils.add_days(current_date, 2), - "end_date": frappe.utils.add_days(current_date, 3) + "title": "Setup Master Data", + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 1), + "file": "school_masters.md" + }] + + else: + tasks += [ + { + "title": "Setup Your Company", + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 1), + "file": "masters.md" }, { - "title": "Run Billing Cycle", - "start_date": frappe.utils.add_days(current_date, 3), - "end_date": frappe.utils.add_days(current_date, 4) + "title": "Start Tracking your Sales", + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 2), + "file": "sales.md" }, { - "title": "Run Purchase Cycle", - "start_date": frappe.utils.add_days(current_date, 4), - "end_date": frappe.utils.add_days(current_date, 5) + "title": "Start Managing Purchases", + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 3), + "file": "purchase.md" }, { "title": "Import Data", - "start_date": frappe.utils.add_days(current_date, 5), - "end_date": frappe.utils.add_days(current_date, 6) + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 4), + "file": "import_data.md" }, { "title": "Go Live!", - "start_date": frappe.utils.add_days(current_date, 6), - "end_date": frappe.utils.add_days(current_date, 7) - }]) + "start_date": current_date, + "end_date": frappe.utils.add_days(current_date, 5), + "file": "go_live.md" + }] + + for t in tasks: + with open (os.path.join(os.path.dirname(__file__), "tasks", t['file'])) as f: + t['description'] = markdown(f.read()) + del t['file'] + + project.append('tasks', t) project.insert(ignore_permissions=True) + +def import_email_alert(): + '''Import email alert for task start''' + with open (os.path.join(os.path.dirname(__file__), "tasks/task_alert.json")) as f: + email_alert = frappe.get_doc(json.loads(f.read())[0]) + email_alert.insert() + + # trigger the first message! + from frappe.email.doctype.email_alert.email_alert import trigger_daily_alerts + trigger_daily_alerts() + +def test_sample(): + frappe.db.sql('delete from `tabEmail Alert`') + frappe.db.sql('delete from tabProject') + frappe.db.sql('delete from tabTask') + make_projects('Education') + import_email_alert() \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py index 664c08989e..26509ed901 100644 --- a/erpnext/setup/setup_wizard/setup_wizard.py +++ b/erpnext/setup/setup_wizard/setup_wizard.py @@ -60,7 +60,7 @@ def setup_complete(args=None): if args.get("add_sample_data"): try: - make_sample_data() + make_sample_data(args) frappe.clear_cache() except: # clear message diff --git a/erpnext/setup/setup_wizard/tasks/explore.md b/erpnext/setup/setup_wizard/tasks/explore.md new file mode 100644 index 0000000000..ce6cb60673 --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/explore.md @@ -0,0 +1,7 @@ +Thanks for checking this out! ❤️ + +If you are evaluating an ERP system for the first time, this is going to be quite a task! But don't worry, ERPNext is awesome. + +First, get familiar with the surroundings. ERPNext covers a *lot of features*, go to the home page and click on the "Explore" icon. + +All the best! \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/tasks/go_live.md b/erpnext/setup/setup_wizard/tasks/go_live.md new file mode 100644 index 0000000000..0a934a436f --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/go_live.md @@ -0,0 +1,18 @@ +Ready to go live with ERPNext? 🏁🏁🏁 + +Here are the steps: + +1. Sync up your **Chart of Accounts** +3. Add your opening stock using **Stock Reconciliation** +4. Add your open invoices (both sales and purchase) +3. Add your opening account balances by making a **Journal Entry** + +If you need help for going live, sign up for an account at erpnext.com or find a partner to help you with this. + +Or you can watch these videos 📺: + +Setup your chart of accounts: https://www.youtube.com/watch?v=AcfMCT7wLLo + +Add Open Stock: https://www.youtube.com/watch?v=nlHX0ZZ84Lw + +Add Opening Balances: https://www.youtube.com/watch?v=nlHX0ZZ84Lw diff --git a/erpnext/setup/setup_wizard/tasks/import_data.md b/erpnext/setup/setup_wizard/tasks/import_data.md new file mode 100644 index 0000000000..c5b85c9673 --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/import_data.md @@ -0,0 +1,5 @@ +Lets import some data! 💪💪 + +If you are already running a business, you most likely have your Items, Customers or Suppliers in some spreadsheet file somewhere, import it into ERPNext with the Data Import Tool. + +Watch this video to get started: https://www.youtube.com/watch?v=Ta2Xx3QoK3E diff --git a/erpnext/setup/setup_wizard/tasks/masters.md b/erpnext/setup/setup_wizard/tasks/masters.md new file mode 100644 index 0000000000..6ade15907c --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/masters.md @@ -0,0 +1,7 @@ +Start building a model of your business in ERPNext by adding your Items and Customers. + +These videos 📺 will help you get started: + +Adding Customers and Suppliers: https://www.youtube.com/watch?v=zsrrVDk6VBs + +Adding Items and Prices: https://www.youtube.com/watch?v=FcOsV-e8ymE \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/tasks/purchase.md b/erpnext/setup/setup_wizard/tasks/purchase.md new file mode 100644 index 0000000000..3f3bc3b274 --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/purchase.md @@ -0,0 +1,10 @@ +How to manage your purchasing in ERPNext 🛒🛒🛒: + +1. Add a few **Suppliers** +2. Find out what you need by making **Material Requests**. +3. Now start placing orders via **Purchase Order**. +4. When your suppliers deliver, make **Purchase Receipts** + +Now never run out of stock again! 😎 + +Watch this video 📺 to get an overview: https://www.youtube.com/watch?v=4TN9kPyfIqM \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/tasks/sales.md b/erpnext/setup/setup_wizard/tasks/sales.md new file mode 100644 index 0000000000..15268fa968 --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/sales.md @@ -0,0 +1,8 @@ +Start managing your sales with ERPNext 🔔🔔🔔: + +1. Add potential business contacts as **Leads** +2. Udpate your deals in pipeline in **Opportunities** +3. Send proposals to your leads or customers with **Quotations** +4. Track confirmed orders with **Sales Orders** + +Watch this video 📺 to get an overview: https://www.youtube.com/watch?v=o9XCSZHJfpA diff --git a/erpnext/setup/setup_wizard/tasks/school_import_data.md b/erpnext/setup/setup_wizard/tasks/school_import_data.md new file mode 100644 index 0000000000..c465b812c8 --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/school_import_data.md @@ -0,0 +1,5 @@ +Lets import some data! 💪💪 + +If you are already running a school, you most likely have your Students in some spreadsheet file somewhere. Import it into ERPNext with the Data Import Tool. + +Watch this video to get started: https://www.youtube.com/watch?v=Ta2Xx3QoK3E \ No newline at end of file diff --git a/erpnext/setup/setup_wizard/tasks/school_masters.md b/erpnext/setup/setup_wizard/tasks/school_masters.md new file mode 100644 index 0000000000..91039352b0 --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/school_masters.md @@ -0,0 +1,9 @@ +Lets start making things in ERPNext that are representative of your institution. + +1. Make a list of **Programs** that you offer +1. Add a few **Courses** that your programs cover +1. Create **Academic Terms** and **Academic Years** +1. Start adding **Students** +1. Group your students into **Batches** + +Watch this video to learn more about ERPNext Schools: https://www.youtube.com/watch?v=f6foQOyGzdA diff --git a/erpnext/setup/setup_wizard/tasks/task_alert.json b/erpnext/setup/setup_wizard/tasks/task_alert.json new file mode 100644 index 0000000000..dca68455ca --- /dev/null +++ b/erpnext/setup/setup_wizard/tasks/task_alert.json @@ -0,0 +1,28 @@ +[ + { + "attach_print": 0, + "condition": "doc.status in ('Open', 'Overdue')", + "date_changed": "exp_end_date", + "days_in_advance": 0, + "docstatus": 0, + "doctype": "Email Alert", + "document_type": "Task", + "enabled": 1, + "event": "Days After", + "is_standard": 0, + "message": "
Task due today:
\n\n\nThis is a notification for a task that is due today, and a sample Email Alert. In ERPNext you can setup email alerts on anything, Invoices, Orders, Leads, Opportunities, so you never miss a thing.\n
To edit this, and setup other alerts, just type Email Alert in the search bar.