Merge pull request #3971 from anandpdoshi/fix-item-variant-attributes
Attributes in the variant should be in the same order as in the Template
diff --git a/erpnext/__version__.py b/erpnext/__version__.py
index 889fbef..7a61e5f 100644
--- a/erpnext/__version__.py
+++ b/erpnext/__version__.py
@@ -1,2 +1,2 @@
from __future__ import unicode_literals
-__version__ = '5.8.2'
+__version__ = '6.0.0'
diff --git a/erpnext/change_log/current/collapsible_sections.md b/erpnext/change_log/current/collapsible_sections.md
deleted file mode 100644
index 9c7fb30..0000000
--- a/erpnext/change_log/current/collapsible_sections.md
+++ /dev/null
@@ -1,2 +0,0 @@
-- Most transaction forms will now have collapsibe sections so that forms appear to be more organized and you can easily locate parts to be edited.
-- The document title on most transactions can be edited so that you can set meaningful titles to all transactions like Sales Invoice and also edit it to denote status.
diff --git a/erpnext/change_log/v6/v6_0_0.md b/erpnext/change_log/v6/v6_0_0.md
new file mode 100644
index 0000000..bb8cd5d
--- /dev/null
+++ b/erpnext/change_log/v6/v6_0_0.md
@@ -0,0 +1,4 @@
+- Added Calendar and Gantt Views for Sales Order based on Delivery Date
+- Most transaction forms will now have collapsibe sections so that forms appear to be more organized and you can easily locate parts to be edited.
+- The document title on most transactions can be edited so that you can set meaningful titles to all transactions like Sales Invoice and also edit it to denote status.
+- Allow user to disable warnings for "Multiple Items" and "Multiple Sales Order against a Customer's Purchase Order" via Sales and Purchase Settings. Sponsored by: **[McLean Images](http://www.mcleanimages.com.au/)**
diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py
index 04c12f7..6c98202 100644
--- a/erpnext/controllers/queries.py
+++ b/erpnext/controllers/queries.py
@@ -268,7 +268,7 @@
{0}
{match_conditions}
order by expiry_date, name desc
- limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args, debug=1)
+ limit %(start)s, %(page_len)s""".format(cond, match_conditions=get_match_cond(doctype)), args)
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
filter_list = []
diff --git a/erpnext/hooks.py b/erpnext/hooks.py
index 7a6a535..f7f9197 100644
--- a/erpnext/hooks.py
+++ b/erpnext/hooks.py
@@ -27,7 +27,7 @@
"""
app_icon = "icon-th"
app_color = "#e74c3c"
-app_version = "5.8.2"
+app_version = "6.0.0"
github_link = "https://github.com/frappe/erpnext"
error_report_email = "support@erpnext.com"
@@ -51,7 +51,7 @@
email_append_to = ["Job Applicant", "Opportunity", "Issue"]
-calendars = ["Task", "Production Order", "Time Log", "Leave Application"]
+calendars = ["Task", "Production Order", "Time Log", "Leave Application", "Sales Order"]
website_generators = ["Item Group", "Item", "Sales Partner"]
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 6299736..19746fc 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -329,15 +329,15 @@
frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError)
validate_end_of_life(self.production_item)
-
+
def validate_qty(self):
if not self.qty > 0:
frappe.throw(_("Quantity to Manufacture must be greater than 0."))
-
+
def validate_operation_time(self):
for d in self.operations:
if not d.time_in_mins > 0:
- frappe.throw(_("Operation Time must be greater than 0 for Operation {0}".format(d.operation)))
+ frappe.throw(_("Operation Time must be greater than 0 for Operation {0}".format(d.operation)))
@frappe.whitelist()
def get_item_details(item):
@@ -381,19 +381,17 @@
@frappe.whitelist()
def get_events(start, end, filters=None):
- from frappe.desk.reportview import build_match_conditions
- if not frappe.has_permission("Production Order"):
- frappe.msgprint(_("No Permission"), raise_exception=1)
+ """Returns events for Gantt / Calendar view rendering.
- conditions = build_match_conditions("Production Order")
- conditions = conditions and (" and " + conditions) or ""
- if filters:
- filters = json.loads(filters)
- for key in filters:
- if filters[key]:
- conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"'
+ :param start: Start date-time.
+ :param end: End date-time.
+ :param filters: Filters (JSON).
+ """
+ from frappe.desk.calendar import get_event_conditions
+ conditions = get_event_conditions("Production Order", filters)
- data = frappe.db.sql("""select name, production_item, planned_start_date, planned_end_date
+ data = frappe.db.sql("""select name, production_item, planned_start_date,
+ planned_end_date, status
from `tabProduction Order`
where ((ifnull(planned_start_date, '0000-00-00')!= '0000-00-00') \
and (planned_start_date between %(start)s and %(end)s) \
@@ -427,4 +425,4 @@
def get_default_warehouse():
wip_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_wip_warehouse")
fg_warehouse = frappe.db.get_single_value("Manufacturing Settings", "default_fg_warehouse")
- return {"wip_warehouse": wip_warehouse, "fg_warehouse": fg_warehouse}
\ No newline at end of file
+ return {"wip_warehouse": wip_warehouse, "fg_warehouse": fg_warehouse}
diff --git a/erpnext/manufacturing/doctype/production_order/production_order_calendar.js b/erpnext/manufacturing/doctype/production_order/production_order_calendar.js
index a43b25e..2832494 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order_calendar.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order_calendar.js
@@ -10,6 +10,15 @@
"allDay": "allDay"
},
gantt: true,
+ get_css_class: function(data) {
+ if(data.status==="Completed") {
+ return "success";
+ } else if(data.status==="In Process") {
+ return "warning";
+ } else {
+ return "danger";
+ }
+ },
filters: [
{
"fieldtype": "Link",
diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py
index fcd756b..28cfcd3 100644
--- a/erpnext/projects/doctype/task/task.py
+++ b/erpnext/projects/doctype/task/task.py
@@ -42,7 +42,7 @@
for d in self.depends_on:
if frappe.db.get_value("Task", d.task, "status") != "Closed":
frappe.throw(_("Cannot close task as its dependant task {0} is not closed.").format(d.task))
-
+
from frappe.desk.form.assign_to import clear
clear(self.doctype, self.name)
@@ -107,18 +107,14 @@
@frappe.whitelist()
def get_events(start, end, filters=None):
- from frappe.desk.reportview import build_match_conditions
- if not frappe.has_permission("Task"):
- frappe.msgprint(_("No Permission"), raise_exception=1)
+ """Returns events for Gantt / Calendar view rendering.
- conditions = build_match_conditions("Task")
- conditions = conditions and (" and " + conditions) or ""
-
- if filters:
- filters = json.loads(filters)
- for key in filters:
- if filters[key]:
- conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"'
+ :param start: Start date-time.
+ :param end: End date-time.
+ :param filters: Filters (JSON).
+ """
+ from frappe.desk.calendar import get_event_conditions
+ conditions = get_event_conditions("Task", filters)
data = frappe.db.sql("""select name, exp_start_date, exp_end_date,
subject, status, project from `tabTask`
diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py
index 6e937c0..ed89307 100644
--- a/erpnext/projects/doctype/time_log/time_log.py
+++ b/erpnext/projects/doctype/time_log/time_log.py
@@ -2,7 +2,7 @@
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
-import frappe, json
+import frappe
from frappe import _
from frappe.utils import cstr, flt, get_datetime, get_time, getdate
from dateutil.relativedelta import relativedelta
@@ -248,17 +248,8 @@
:param end: End date-time.
:param filters: Filters like workstation, project etc.
"""
- from frappe.desk.reportview import build_match_conditions
- if not frappe.has_permission("Time Log"):
- frappe.msgprint(_("No Permission"), raise_exception=1)
-
- conditions = build_match_conditions("Time Log")
- conditions = conditions and (" and " + conditions) or ""
- if filters:
- filters = json.loads(filters)
- for key in filters:
- if filters[key]:
- conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"'
+ from frappe.desk.calendar import get_event_conditions
+ conditions = get_event_conditions("Time Log", filters)
data = frappe.db.sql("""select name, from_time, to_time,
activity_type, task, project, production_order, workstation from `tabTime Log`
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 0b5eb37..065d329 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -471,3 +471,24 @@
}, target_doc)
return doclist
+
+@frappe.whitelist()
+def get_events(start, end, filters=None):
+ """Returns events for Gantt / Calendar view rendering.
+
+ :param start: Start date-time.
+ :param end: End date-time.
+ :param filters: Filters (JSON).
+ """
+ from frappe.desk.calendar import get_event_conditions
+ conditions = get_event_conditions("Sales Order", filters)
+
+ data = frappe.db.sql("""select name, customer_name, delivery_status, billing_status, delivery_date
+ from `tabSales Order`
+ where (ifnull(delivery_date, '0000-00-00')!= '0000-00-00') \
+ and (delivery_date between %(start)s and %(end)s) {conditions}
+ """.format(conditions=conditions), {
+ "start": start,
+ "end": end
+ }, as_dict=True, update={"allDay": 0})
+ return data
diff --git a/erpnext/selling/doctype/sales_order/sales_order_calendar.js b/erpnext/selling/doctype/sales_order/sales_order_calendar.js
new file mode 100644
index 0000000..8724daa
--- /dev/null
+++ b/erpnext/selling/doctype/sales_order/sales_order_calendar.js
@@ -0,0 +1,45 @@
+// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
+// License: GNU General Public License v3. See license.txt
+
+frappe.views.calendar["Sales Order"] = {
+ field_map: {
+ "start": "delivery_date",
+ "end": "delivery_date",
+ "id": "name",
+ "title": "customer_name",
+ "allDay": "allDay"
+ },
+ gantt: true,
+ filters: [
+ {
+ "fieldtype": "Link",
+ "fieldname": "customer",
+ "options": "Customer",
+ "label": __("Customer")
+ },
+ {
+ "fieldtype": "Select",
+ "fieldname": "delivery_status",
+ "options": "Not Delivered\nFully Delivered\nPartly Delivered\nClosed\nNot Applicable",
+ "label": __("Delivery Status")
+ },
+ {
+ "fieldtype": "Select",
+ "fieldname": "billing_status",
+ "options": "Not Billed\nFully Billed\nPartly Billed\nClosed",
+ "label": __("Billing Status")
+ },
+ ],
+ get_events_method: "erpnext.selling.doctype.sales_order.sales_order.get_events",
+ get_css_class: function(data) {
+ if(data.status=="Stopped") {
+ return "";
+ } if(data.delivery_status=="Not Delivered") {
+ return "danger";
+ } else if(data.delivery_status=="Partly Delivered") {
+ return "warning";
+ } else if(data.delivery_status=="Fully Delivered") {
+ return "success";
+ }
+ }
+}
diff --git a/erpnext/setup/doctype/company/delete_company_transactions.py b/erpnext/setup/doctype/company/delete_company_transactions.py
index 87c1375..f7334b1 100644
--- a/erpnext/setup/doctype/company/delete_company_transactions.py
+++ b/erpnext/setup/doctype/company/delete_company_transactions.py
@@ -6,6 +6,7 @@
from frappe.utils import cint
from frappe import _
+from frappe.desk.notifications import clear_notifications
@frappe.whitelist()
def delete_company_transactions(company_name):
@@ -16,11 +17,16 @@
frappe.throw(_("Transactions can only be deleted by the creator of the Company"), frappe.PermissionError)
delete_bins(company_name)
+
+ delete_time_logs(company_name)
for doctype in frappe.db.sql_list("""select parent from
tabDocField where fieldtype='Link' and options='Company'"""):
- if doctype not in ("Account", "Cost Center", "Warehouse", "Budget Detail", "Party Account"):
+ if doctype not in ("Account", "Cost Center", "Warehouse", "Budget Detail", "Party Account", "Employee"):
delete_for_doctype(doctype, company_name)
+
+ # Clear notification counts
+ clear_notifications()
def delete_for_doctype(doctype, company_name):
meta = frappe.get_meta(doctype)
@@ -60,3 +66,20 @@
def delete_bins(company_name):
frappe.db.sql("""delete from tabBin where warehouse in
(select name from tabWarehouse where company=%s)""", company_name)
+
+def delete_time_logs(company_name):
+ # Delete Time Logs as it is linked to Production Order / Project / Task, which are linked to company
+ frappe.db.sql("""
+ delete from `tabTime Log`
+ where
+ (ifnull(project, '') != ''
+ and exists(select name from `tabProject` where name=`tabTime Log`.project and company=%(company)s))
+ or (ifnull(task, '') != ''
+ and exists(select name from `tabTask` where name=`tabTime Log`.task and company=%(company)s))
+ or (ifnull(production_order, '') != ''
+ and exists(select name from `tabProduction Order`
+ where name=`tabTime Log`.production_order and company=%(company)s))
+ or (ifnull(sales_invoice, '') != ''
+ and exists(select name from `tabSales Invoice`
+ where name=`tabTime Log`.sales_invoice and company=%(company)s))
+ """, {"company": company_name})
\ No newline at end of file
diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py
index 0cec77b..40c2729 100644
--- a/erpnext/stock/get_item_details.py
+++ b/erpnext/stock/get_item_details.py
@@ -212,7 +212,7 @@
price_list_rate = get_price_list_rate_for(args, item_doc.name)
if not price_list_rate and item_doc.variant_of:
price_list_rate = get_price_list_rate_for(args, item_doc.variant_of)
-
+
if not price_list_rate:
if args.price_list and args.rate:
insert_item_price(args)
@@ -231,12 +231,16 @@
if frappe.db.get_value("Price List", args.price_list, "currency") == args.currency \
and cint(frappe.db.get_single_value("Stock Settings", "auto_insert_price_list_rate_if_missing")):
if frappe.has_permission("Item Price", "write"):
+
+ price_list_rate = args.rate / args.conversion_factor \
+ if args.get("conversion_factor") else args.rate
+
item_price = frappe.get_doc({
"doctype": "Item Price",
"price_list": args.price_list,
"item_code": args.item_code,
"currency": args.currency,
- "price_list_rate": args.rate
+ "price_list_rate": price_list_rate
})
item_price.insert()
frappe.msgprint("Item Price added for {0} in Price List {1}".format(args.item_code,
diff --git a/setup.py b/setup.py
index 6a420c3..bfa2fa7 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-version = "5.8.2"
+version = "6.0.0"
with open("requirements.txt", "r") as f:
install_requires = f.readlines()