Merge branch 'hotfix'
diff --git a/erpnext/__init__.py b/erpnext/__init__.py
index cf6ca02..542743d 100644
--- a/erpnext/__init__.py
+++ b/erpnext/__init__.py
@@ -4,7 +4,7 @@
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'''
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 adb7bc1..1e694e7 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 @@
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 @@
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())
diff --git "a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_g\303\251n\303\251ral.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\303\251n\303\251ral.json"
rename to erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_general.json
index d7b464a..f6015f3 100644
--- "a/erpnext/accounts/doctype/account/chart_of_accounts/verified/fr_plan_comptable_g\303\251n\303\251ral.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
+}
diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py
index f36fdf7..2b3459a 100644
--- a/erpnext/accounts/doctype/sales_invoice/pos.py
+++ b/erpnext/accounts/doctype/sales_invoice/pos.py
@@ -320,8 +320,7 @@
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 @@
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 d69a306..33b41e9 100644
--- a/erpnext/accounts/page/pos/pos.js
+++ b/erpnext/accounts/page/pos/pos.js
@@ -426,11 +426,16 @@
});
this.serach_item.make_input();
- this.serach_item.$input.on("keyup", function () {
- setTimeout(function () {
- me.items = me.get_items();
- me.make_item_list();
- }, 1000);
+
+ this.serach_item.$input.on("keypress", function (event) {
+
+ 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');
@@ -727,14 +732,7 @@
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);
@@ -808,7 +806,11 @@
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()
}
});
diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js
index eaf064b..a333ca8 100644
--- a/erpnext/public/js/utils.js
+++ b/erpnext/public/js/utils.js
@@ -125,7 +125,33 @@
}
});
}
- }
+ },
+
+ /**
+ * 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/setup/doctype/currency_exchange/test_currency_exchange.py b/erpnext/setup/doctype/currency_exchange/test_currency_exchange.py
index d4c9df3..a477379 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 @@
# 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 888099f..bdbf3f4 100644
--- a/erpnext/setup/utils.py
+++ b/erpnext/setup/utils.py
@@ -83,7 +83,8 @@
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
})
diff --git a/erpnext/stock/doctype/material_request/material_request.js b/erpnext/stock/doctype/material_request/material_request.js
index fc0b9b2..7043fb7 100644
--- a/erpnext/stock/doctype/material_request/material_request.js
+++ b/erpnext/stock/doctype/material_request/material_request.js
@@ -153,9 +153,11 @@
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 0000000..d8b39fe
--- /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()
+ ]);
+});
+