From 2f7cb82ca040e3bff433a11b2a2a4e28d802d7d0 Mon Sep 17 00:00:00 2001 From: Revant Nandgaonkar Date: Sat, 26 Aug 2017 09:58:15 +0530 Subject: [PATCH 1/9] [Fix] POS Scanner Search item based on key press instead of 1sec wait Fast Scanning needs this to avoid 1sec delay --- erpnext/accounts/page/pos/pos.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index d69a306670..ee4644a51e 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -426,11 +426,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }); this.serach_item.make_input(); - this.serach_item.$input.on("keyup", function () { - setTimeout(function () { + this.serach_item.$input.on("keypress", function (event) { + if((me.serach_item.$input.val() != "") && (event.which == 13)){ me.items = me.get_items(); me.make_item_list(); - }, 1000); + } }); this.search_item_group = this.wrapper.find('.search-item-group'); From 2558daf6b772c38c3e0a7393d506543ea9428ab5 Mon Sep 17 00:00:00 2001 From: Revant Nandgaonkar Date: Sat, 26 Aug 2017 15:52:35 +0530 Subject: [PATCH 2/9] Allow search without keypress enter --- erpnext/accounts/page/pos/pos.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index ee4644a51e..d576406ffc 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -427,7 +427,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ this.serach_item.make_input(); this.serach_item.$input.on("keypress", function (event) { - if((me.serach_item.$input.val() != "") && (event.which == 13)){ + if((me.serach_item.$input.val() != "") || (event.which == 13)){ me.items = me.get_items(); me.make_item_list(); } From 8fbc08f91f8f630a642fbfa6836cc7b8af3f3389 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 28 Aug 2017 16:52:20 +0530 Subject: [PATCH 3/9] Decrease timeout to 400 --- erpnext/accounts/page/pos/pos.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index d576406ffc..e362db0738 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -426,11 +426,16 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }); this.serach_item.make_input(); + this.serach_item.$input.on("keypress", function (event) { - if((me.serach_item.$input.val() != "") || (event.which == 13)){ - me.items = me.get_items(); - me.make_item_list(); - } + + clearTimeout(me.last_search_timeout); + me.last_search_timeout = setTimeout(() => { + if((me.serach_item.$input.val() != "") || (event.which == 13)) { + me.items = me.get_items(); + me.make_item_list(); + } + }, 400); }); this.search_item_group = this.wrapper.find('.search-item-group'); From 1a947dbf6a3e8814176b0af2caa8f9a8935fff89 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Tue, 29 Aug 2017 13:48:27 +0100 Subject: [PATCH 4/9] Item Name not loaded in Material Request via BOM (#10535) (#10555) * adds item_name to child table * adds two new functions to utils: - first_row_is_empty: to check if first row in child table is empty - remove_empty_first_row: to remove the empty first row in a child table * removes empty first row after getting from BOM * ui test --- erpnext/public/js/utils.js | 28 ++++++++++++++++++- .../material_request/material_request.js | 2 ++ .../tests/test_material_request_from_bom.js | 28 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index eaf064b26c..a333ca82d6 100644 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -125,7 +125,33 @@ $.extend(erpnext.utils, { } }); } - } + }, + + /** + * Checks if the first row of a given child table is empty + * @param child_table - Child table Doctype + * @return {Boolean} + **/ + first_row_is_empty: function(child_table){ + if($.isArray(child_table) && child_table.length > 0) { + return !child_table[0].item_code; + } + return false; + }, + + /** + * Removes the first row of a child table if it is empty + * @param {_Frm} frm - The current form + * @param {String} child_table_name - The child table field name + * @return {Boolean} + **/ + remove_empty_first_row: function(frm, child_table_name){ + const rows = frm['doc'][child_table_name]; + if (this.first_row_is_empty(rows)){ + frm['doc'][child_table_name] = rows.splice(1); + } + return rows; + }, }); erpnext.utils.map_current_doc = function(opts) { diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js index fc0b9b2106..7043fb7ba8 100644 --- a/erpnext/stock/doctype/material_request/material_request.js +++ b/erpnext/stock/doctype/material_request/material_request.js @@ -153,9 +153,11 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten if(!r.message) { frappe.throw(__("BOM does not contain any stock item")) } else { + erpnext.utils.remove_empty_first_row(cur_frm, "items"); $.each(r.message, function(i, item) { var d = frappe.model.add_child(cur_frm.doc, "Material Request Item", "items"); d.item_code = item.item_code; + d.item_name = item.item_name; d.description = item.description; d.warehouse = values.warehouse; d.uom = item.stock_uom; diff --git a/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js b/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js new file mode 100644 index 0000000000..d8b39fe5aa --- /dev/null +++ b/erpnext/stock/doctype/material_request/tests/test_material_request_from_bom.js @@ -0,0 +1,28 @@ +QUnit.module('manufacturing'); + +QUnit.test("test material request get items from BOM", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => frappe.set_route('Form', 'BOM'), + () => frappe.timeout(3), + () => frappe.click_button('Get Items from BOM'), + () => frappe.timeout(3), + () => { + assert.ok(cur_dialog, 'dialog appeared'); + }, + () => cur_dialog.set_value('bom', 'Laptop'), + () => cur_dialog.set_value('warehouse', 'Laptop Scrap Warehouse'), + () => frappe.click_button('Get Items from BOM'), + () => frappe.timeout(3), + () => { + assert.ok(cur_frm.doc.items[0].item_code, "First row is not empty"); + assert.ok(cur_frm.doc.items[0].item_name, "Item name is not empty"); + assert.equal(cur_frm.doc.items[0].item_name, "Laptop", cur_frm.doc.items[0].item_name); + }, + () => cur_frm.doc.items[0].schedule_date = '2017-12-12', + () => cur_frm.save(), + () => done() + ]); +}); + From de278635a3a75d43893120e1b52a8c36e921156a Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Thu, 31 Aug 2017 13:36:56 +0530 Subject: [PATCH 5/9] [hotfix] fixes for UnicodeDecodeError (#10620) --- .../doctype/account/chart_of_accounts/chart_of_accounts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py index adb7bc1338..1e694e7e3a 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/chart_of_accounts.py @@ -78,6 +78,7 @@ def get_chart(chart_template, existing_company=None): for folder in folders: path = os.path.join(os.path.dirname(__file__), folder) for fname in os.listdir(path): + fname = frappe.as_unicode(fname) if fname.endswith(".json"): with open(os.path.join(path, fname), "r") as f: chart = f.read() @@ -105,6 +106,7 @@ def get_charts_for_country(country): path = os.path.join(os.path.dirname(__file__), folder) for fname in os.listdir(path): + fname = frappe.as_unicode(fname) if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"): with open(os.path.join(path, fname), "r") as f: _get_chart_name(f.read()) From 3c635e219e94f0cbc6070416f18bf211fd8811cc Mon Sep 17 00:00:00 2001 From: krnkris Date: Thu, 31 Aug 2017 10:47:46 +0200 Subject: [PATCH 6/9] =?UTF-8?q?Rename=20fr=5Fplan=5Fcomptable=5Fg=C3=A9n?= =?UTF-8?q?=C3=A9ral.json=20to=20fr=5Fplan=5Fcomptable=5Fgeneral.json=20(#?= =?UTF-8?q?10601)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...an_comptable_général.json => fr_plan_comptable_general.json} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename erpnext/accounts/doctype/account/chart_of_accounts/verified/{fr_plan_comptable_général.json => fr_plan_comptable_general.json} (99%) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_général.json b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json similarity index 99% rename from erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_général.json rename to erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json index d7b464a381..f6015f3744 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_général.json +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json @@ -1607,4 +1607,4 @@ "root_type": "Income" } } -} \ No newline at end of file +} From 56e31d05e960415fe1ad21611bc880490524ceb6 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 31 Aug 2017 14:19:58 +0530 Subject: [PATCH 7/9] [Fix] POS customer field is hang while searching customer, make error log if sync has failed (#10607) --- erpnext/accounts/doctype/sales_invoice/pos.py | 29 ++++++++++++------- erpnext/accounts/page/pos/pos.js | 15 ++++------ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index f36fdf7907..2b3459ad27 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -320,8 +320,7 @@ def make_invoice(doc_list={}, email_queue_list={}, customers_list={}): si_doc.set_posting_time = 1 si_doc.customer = get_customer_id(doc) si_doc.due_date = doc.get('posting_date') - submit_invoice(si_doc, name, doc) - name_list.append(name) + name_list = submit_invoice(si_doc, name, doc, name_list) else: name_list.append(name) @@ -475,19 +474,29 @@ def validate_item(doc): frappe.db.commit() -def submit_invoice(si_doc, name, doc): +def submit_invoice(si_doc, name, doc, name_list): try: si_doc.insert() si_doc.submit() frappe.db.commit() + name_list.append(name) except Exception as e: if frappe.message_log: frappe.message_log.pop() frappe.db.rollback() - save_invoice(e, si_doc, name) + frappe.log_error(frappe.get_traceback()) + name_list = save_invoice(e, si_doc, name, name_list) -def save_invoice(e, si_doc, name): - if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): - si_doc.docstatus = 0 - si_doc.flags.ignore_mandatory = True - si_doc.due_date = si_doc.posting_date - si_doc.insert() + return name_list + +def save_invoice(e, si_doc, name, name_list): + try: + if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}): + si_doc.docstatus = 0 + si_doc.flags.ignore_mandatory = True + si_doc.due_date = si_doc.posting_date + si_doc.insert() + name_list.append(name) + except Exception: + frappe.log_error(frappe.get_traceback()) + + return name_list diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index e362db0738..33b41e9ee4 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -732,14 +732,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ input = input.toLowerCase(); item = this.get_item(item.value); - var searchtext = - Object.keys(item) - .filter(key => ['customer_name', 'customer_group', 'value', 'label', 'email_id', 'phone', 'mobile_no'].includes(key)) - .map(key => item[key]) - .join(" ") - .toLowerCase(); - - return searchtext.includes(input) + return item.searchtext.includes(input) }, item: function (item, input) { var d = this.get_item(item.value); @@ -813,7 +806,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ territory: c.territory, phone: contact ? contact["phone"] : '', mobile_no: contact ? contact["mobile_no"] : '', - email_id: contact ? contact["email_id"] : '' + email_id: contact ? contact["email_id"] : '', + searchtext: ['customer_name', 'customer_group', 'value', + 'label', 'email_id', 'phone', 'mobile_no'] + .map(key => c[key]).join(' ') + .toLowerCase() } }); From 7f8a259beb22bced6097ff1edef7605b93815b46 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Thu, 31 Aug 2017 10:00:15 +0100 Subject: [PATCH 8/9] Fixer Always Fetches Latest Exchange Rate Even When Date is Specified (#10596) (#10597) * test that confirms the bug. Same test should pass after fix * make use of correct api url --- .../setup/doctype/currency_exchange/test_currency_exchange.py | 3 ++- erpnext/setup/utils.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py index d4c9df380f..a477379ded 100644 --- a/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py @@ -44,4 +44,5 @@ class TestCurrencyExchange(unittest.TestCase): # Exchange rate as on 15th Dec, 2015, should be fetched from fixer.io exchange_rate = get_exchange_rate("USD", "INR", "2015-12-15") - self.assertFalse(exchange_rate==60) \ No newline at end of file + self.assertFalse(exchange_rate == 60) + self.assertEqual(exchange_rate, 66.894) \ No newline at end of file diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 888099fc4f..bdbf3f4ec2 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -83,7 +83,8 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None): if not value: import requests - response = requests.get("http://api.fixer.io/latest", params={ + api_url = "http://api.fixer.io/{0}".format(transaction_date) + response = requests.get(api_url, params={ "base": from_currency, "symbols": to_currency }) From 2a4328b4f5dbc51aba01e0ae729096686b9aee66 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Thu, 31 Aug 2017 16:01:47 +0600 Subject: [PATCH 9/9] bumped to version 8.10.1 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index cf6ca02e7f..542743dde2 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '8.10.0' +__version__ = '8.10.1' def get_default_company(user=None): '''Get default company for user'''