From d17bea0a31419336a48a3eeccd60cc381f54c1ab Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Wed, 4 Oct 2017 14:30:12 +0530 Subject: [PATCH 1/5] [hotfix] check minimum actual start time and actual end time before updating PO Operations (#11041) * [hotfix] check minimum actual start time and actual end time before updating PO Operations * Update production_order.py --- .../doctype/production_order/production_order.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index f04fddfae3..f4d37760d3 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -370,8 +370,13 @@ class ProductionOrder(Document): self.actual_start_date = None self.actual_end_date = None if self.get("operations"): - self.actual_start_date = min([d.actual_start_time for d in self.get("operations") if d.actual_start_time]) - self.actual_end_date = max([d.actual_end_time for d in self.get("operations") if d.actual_end_time]) + actual_start_dates = [d.actual_start_time for d in self.get("operations") if d.actual_start_time] + if actual_start_dates: + self.actual_start_date = min(actual_start_dates) + + actual_end_dates = [d.actual_end_time for d in self.get("operations") if d.actual_end_time] + if actual_end_dates: + self.actual_end_date = max(actual_end_dates) def delete_timesheet(self): for timesheet in frappe.get_all("Timesheet", ["name"], {"production_order": self.name}): @@ -621,4 +626,4 @@ def stop_unstop(production_order, status): frappe.msgprint(_("Production Order has been {0}").format(status)) pro_order.notify_update() - return pro_order.status \ No newline at end of file + return pro_order.status From 5049edb494b55bbf3ff63e600d049b2645d9255a Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 4 Oct 2017 14:33:12 +0530 Subject: [PATCH 2/5] [Fix] Discount and serial no search issue (#11040) --- .../page/point_of_sale/point_of_sale.js | 34 ++++++++++++++----- .../page/point_of_sale/point_of_sale.py | 19 ++++++++--- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js index 5eb822621e..1b0b9eb392 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.js +++ b/erpnext/selling/page/point_of_sale/point_of_sale.js @@ -763,28 +763,41 @@ class POSCart { // }); this.wrapper.find('.additional_discount_percentage').on('change', (e) => { + const discount_percentage = flt(e.target.value, + precision("additional_discount_percentage")); + frappe.model.set_value(this.frm.doctype, this.frm.docname, - 'additional_discount_percentage', e.target.value) + 'additional_discount_percentage', discount_percentage) .then(() => { let discount_wrapper = this.wrapper.find('.discount_amount'); - discount_wrapper.val(this.frm.doc.discount_amount); + discount_wrapper.val(flt(this.frm.doc.discount_amount, + precision('discount_amount'))); discount_wrapper.trigger('change'); }); }); this.wrapper.find('.discount_amount').on('change', (e) => { + const discount_amount = flt(e.target.value, precision('discount_amount')); frappe.model.set_value(this.frm.doctype, this.frm.docname, - 'discount_amount', flt(e.target.value)); + 'discount_amount', discount_amount); this.frm.trigger('discount_amount') .then(() => { - let discount_wrapper = this.wrapper.find('.additional_discount_percentage'); - discount_wrapper.val(this.frm.doc.additional_discount_percentage); + this.update_discount_fields(); this.update_taxes_and_totals(); this.update_grand_total(); }); }); } + update_discount_fields() { + let discount_wrapper = this.wrapper.find('.additional_discount_percentage'); + let discount_amt_wrapper = this.wrapper.find('.discount_amount'); + discount_wrapper.val(flt(this.frm.doc.additional_discount_percentage, + precision('additional_discount_percentage'))); + discount_amt_wrapper.val(flt(this.frm.doc.discount_amount, + precision('discount_amount'))); + } + set_selected_item($item) { this.selected_item = $item; this.$cart_items.find('.list-item').removeClass('current-item qty disc rate'); @@ -848,7 +861,7 @@ class POSItems { this.search_field = frappe.ui.form.make_control({ df: { fieldtype: 'Data', - label: 'Search Item (Ctrl + I)', + label: 'Search Item ( Ctrl + i )', placeholder: 'Search by item code, serial number, batch no or barcode' }, parent: this.wrapper.find('.search-field'), @@ -945,16 +958,21 @@ class POSItems { if(serial_no) { this.events.update_cart(items[0].item_code, 'serial_no', serial_no); - this.search_field.set_value(''); + this.reset_search_field(); } if(batch_no) { this.events.update_cart(items[0].item_code, 'batch_no', batch_no); - this.search_field.set_value(''); + this.reset_search_field(); } }); } + reset_search_field() { + this.search_field.set_value(''); + this.search_field.$input.trigger("input"); + } + bind_events() { var me = this; this.wrapper.on('click', '.pos-item-wrapper', function() { diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.py b/erpnext/selling/page/point_of_sale/point_of_sale.py index d74f1f06e3..5694ad9af2 100644 --- a/erpnext/selling/page/point_of_sale/point_of_sale.py +++ b/erpnext/selling/page/point_of_sale/point_of_sale.py @@ -24,6 +24,8 @@ def get_items(start, page_length, price_list, item_group, search_value=""): if batch_no_data: batch_no, item_code = batch_no_data + item_code, condition = get_conditions(item_code, serial_no, batch_no) + lft, rgt = frappe.db.get_value('Item Group', item_group, ['lft', 'rgt']) # locate function is used to sort by closest match from the beginning of the value res = frappe.db.sql("""select i.name as item_code, i.item_name, i.image as item_image, @@ -36,11 +38,11 @@ def get_items(start, page_length, price_list, item_group, search_value=""): where i.disabled = 0 and i.has_variants = 0 and i.is_sales_item = 1 and i.item_group in (select name from `tabItem Group` where lft >= {lft} and rgt <= {rgt}) - and (i.item_code like %(item_code)s - or i.item_name like %(item_code)s or i.barcode like %(item_code)s) - limit {start}, {page_length}""".format(start=start, page_length=page_length, lft=lft, rgt=rgt), + and {condition} + limit {start}, {page_length}""".format(start=start, + page_length=page_length, lft=lft, rgt=rgt, condition=condition), { - 'item_code': '%%%s%%'%(frappe.db.escape(item_code)), + 'item_code': item_code, 'price_list': price_list } , as_dict=1) @@ -60,6 +62,15 @@ def get_items(start, page_length, price_list, item_group, search_value=""): return res +def get_conditions(item_code, serial_no, batch_no): + if serial_no or batch_no: + return frappe.db.escape(item_code), "i.item_code = %(item_code)s" + + condition = """(i.item_code like %(item_code)s + or i.item_name like %(item_code)s or i.barcode like %(item_code)s)""" + + return '%%%s%%'%(frappe.db.escape(item_code)), condition + @frappe.whitelist() def submit_invoice(doc): if isinstance(doc, basestring): From eaec4695f780eeb831c542c28b2430553a56b2d4 Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Wed, 4 Oct 2017 14:34:45 +0530 Subject: [PATCH 3/5] [hotfix] filter doctype if the doctype has subscription field (#11038) --- .../doctype/subscription/subscription.js | 6 ++++++ .../doctype/subscription/subscription.py | 18 +++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/subscription/subscription.js b/erpnext/accounts/doctype/subscription/subscription.js index 9c5b264bc0..15927d5961 100644 --- a/erpnext/accounts/doctype/subscription/subscription.js +++ b/erpnext/accounts/doctype/subscription/subscription.js @@ -3,6 +3,12 @@ frappe.ui.form.on('Subscription', { setup: function(frm) { + frm.fields_dict['reference_doctype'].get_query = function(doc) { + return { + query: "erpnext.accounts.doctype.subscription.subscription.subscription_doctype_query" + }; + }; + frm.fields_dict['reference_document'].get_query = function() { return { filters: { diff --git a/erpnext/accounts/doctype/subscription/subscription.py b/erpnext/accounts/doctype/subscription/subscription.py index 352a0aa87c..0e14e84b9d 100644 --- a/erpnext/accounts/doctype/subscription/subscription.py +++ b/erpnext/accounts/doctype/subscription/subscription.py @@ -276,4 +276,20 @@ def stop_resume_subscription(subscription, status): doc.update_status(status) doc.save() - return doc.status \ No newline at end of file + return doc.status + +def subscription_doctype_query(doctype, txt, searchfield, start, page_len, filters): + return frappe.db.sql("""select parent from `tabDocField` + where fieldname = 'subscription' + and parent like %(txt)s + order by + if(locate(%(_txt)s, parent), locate(%(_txt)s, parent), 99999), + parent + limit %(start)s, %(page_len)s""".format(**{ + 'key': searchfield, + }), { + 'txt': "%%%s%%" % txt, + '_txt': txt.replace("%", ""), + 'start': start, + 'page_len': page_len + }) \ No newline at end of file From 4d68e03a97c84e82bc4d6dbd2cb2d09b4c8cb93a Mon Sep 17 00:00:00 2001 From: Revant Nandgaonkar Date: Wed, 4 Oct 2017 14:35:21 +0530 Subject: [PATCH 4/5] [Fix] Job Opening Web Form breadcrumb (#11029) --- erpnext/hr/doctype/job_opening/job_opening.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/job_opening/job_opening.py b/erpnext/hr/doctype/job_opening/job_opening.py index 3d935f55e6..60c911a016 100644 --- a/erpnext/hr/doctype/job_opening/job_opening.py +++ b/erpnext/hr/doctype/job_opening/job_opening.py @@ -21,7 +21,7 @@ class JobOpening(WebsiteGenerator): self.route = frappe.scrub(self.job_title).replace('_', '-') def get_context(self, context): - context.parents = [{'name': 'jobs', 'title': _('All Jobs') }] + context.parents = [{'route': 'jobs', 'title': _('All Jobs') }] def get_list_context(context): context.title = _("Jobs") From c83e793ce81967bdcad777f9a2a1b05105e327f5 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 4 Oct 2017 15:22:31 +0600 Subject: [PATCH 5/5] bumped to version 9.0.8 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index edbd9a25be..ef1e4ed921 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '9.0.7' +__version__ = '9.0.8' def get_default_company(user=None): '''Get default company for user'''