From 8f1391dc96b630b0842ee998750e06dcdce8ea71 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 31 Aug 2015 12:42:05 +0530 Subject: [PATCH] [enhancement] calendar for sales order and other related fixes #3542 --- .../current/calendar_for_sales_order.md | 1 + erpnext/hooks.py | 2 +- .../production_order/production_order.py | 28 ++++++------ .../production_order_calendar.js | 9 ++++ erpnext/projects/doctype/task/task.py | 20 ++++----- erpnext/projects/doctype/time_log/time_log.py | 15 ++----- .../doctype/sales_order/sales_order.py | 21 +++++++++ .../sales_order/sales_order_calendar.js | 45 +++++++++++++++++++ 8 files changed, 101 insertions(+), 40 deletions(-) create mode 100644 erpnext/change_log/current/calendar_for_sales_order.md create mode 100644 erpnext/selling/doctype/sales_order/sales_order_calendar.js diff --git a/erpnext/change_log/current/calendar_for_sales_order.md b/erpnext/change_log/current/calendar_for_sales_order.md new file mode 100644 index 0000000000..0b244c85a8 --- /dev/null +++ b/erpnext/change_log/current/calendar_for_sales_order.md @@ -0,0 +1 @@ +- Added Calendar and Gantt Views for Sales Order based on Delivery Date diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 7a6a535283..80abe0d47b 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -51,7 +51,7 @@ my_account_context = "erpnext.shopping_cart.utils.update_my_account_context" 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 6299736d95..19746fc304 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -329,15 +329,15 @@ class ProductionOrder(Document): 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 @@ def make_stock_entry(production_order_id, purpose, qty=None): @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 make_time_log(name, operation, from_time=None, to_time=None, qty=None, proj 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 a43b25e344..2832494805 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 @@ frappe.views.calendar["Production Order"] = { "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 fcd756ba6d..28cfcd3050 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -42,7 +42,7 @@ class Task(Document): 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 @@ class Task(Document): @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 6e937c09e7..ed8930701b 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 @@ def get_events(start, end, filters=None): :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 0b5eb37589..065d32938f 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -471,3 +471,24 @@ def make_maintenance_visit(source_name, target_doc=None): }, 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 0000000000..8724daae80 --- /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"; + } + } +}