From 537c3a79ab14a73a3fb37cfb9f6f03ec4fb5da3f Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Fri, 2 Aug 2019 21:46:11 +0530 Subject: [PATCH 1/9] fix: Show correct label instead of showing undefined (#18561) --- .../doctype/sales_order/sales_order.js | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 84c1693d20c..247c9e11d5d 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -262,27 +262,44 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( }); return; } else { - var fields = [ - {fieldtype:'Table', fieldname: 'items', - description: __('Select BOM and Qty for Production'), - fields: [ - {fieldtype:'Read Only', fieldname:'item_code', - label: __('Item Code'), in_list_view:1}, - {fieldtype:'Link', fieldname:'bom', options: 'BOM', reqd: 1, - label: __('Select BOM'), in_list_view:1, get_query: function(doc) { - return {filters: {item: doc.item_code}}; - }}, - {fieldtype:'Float', fieldname:'pending_qty', reqd: 1, - label: __('Qty'), in_list_view:1}, - {fieldtype:'Data', fieldname:'sales_order_item', reqd: 1, - label: __('Sales Order Item'), hidden:1} - ], - data: r.message, - get_data: function() { - return r.message + const fields = [{ + label: 'Items', + fieldtype: 'Table', + fieldname: 'items', + description: __('Select BOM and Qty for Production'), + fields: [{ + fieldtype: 'Read Only', + fieldname: 'item_code', + label: __('Item Code'), + in_list_view: 1 + }, { + fieldtype: 'Link', + fieldname: 'bom', + options: 'BOM', + reqd: 1, + label: __('Select BOM'), + in_list_view: 1, + get_query: function (doc) { + return { filters: { item: doc.item_code } }; } + }, { + fieldtype: 'Float', + fieldname: 'pending_qty', + reqd: 1, + label: __('Qty'), + in_list_view: 1 + }, { + fieldtype: 'Data', + fieldname: 'sales_order_item', + reqd: 1, + label: __('Sales Order Item'), + hidden: 1 + }], + data: r.message, + get_data: () => { + return r.message } - ] + }] var d = new frappe.ui.Dialog({ title: __('Select Items to Manufacture'), fields: fields, From b7611699764e799dece22eadcbca71a0a665ea62 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sat, 3 Aug 2019 13:40:37 +0530 Subject: [PATCH 2/9] fix: Error handling in taxes and totals --- erpnext/controllers/taxes_and_totals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 34677ebc3e3..f925f94e8d8 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -77,7 +77,7 @@ class calculate_taxes_and_totals(object): item.net_rate = item.rate - if not item.qty and self.doc.is_return: + if not item.qty and self.doc.get("is_return"): item.amount = flt(-1 * item.rate, item.precision("amount")) else: item.amount = flt(item.rate * item.qty, item.precision("amount")) From 74f31c667772c242b4cc4f82f162cb38aaa1ec9e Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 5 Aug 2019 10:03:32 +0530 Subject: [PATCH 3/9] fix(employee-advance): update employee advance on change in expense claim (#18589) * fix(employee-advance): update employee advance on rejection/cancellation of expense claim * fix(expense-claim): display appropriate buttons only if linked transactions are valid * Update employee_advance.py --- .../employee_advance/employee_advance.py | 17 ++++++++++++----- .../hr/doctype/expense_claim/expense_claim.js | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/erpnext/hr/doctype/employee_advance/employee_advance.py b/erpnext/hr/doctype/employee_advance/employee_advance.py index 1c8b5f96626..7813da78ca4 100644 --- a/erpnext/hr/doctype/employee_advance/employee_advance.py +++ b/erpnext/hr/doctype/employee_advance/employee_advance.py @@ -64,13 +64,20 @@ class EmployeeAdvance(Document): def update_claimed_amount(self): claimed_amount = frappe.db.sql(""" - select sum(ifnull(allocated_amount, 0)) - from `tabExpense Claim Advance` - where employee_advance = %s and docstatus=1 and allocated_amount > 0 + SELECT sum(ifnull(allocated_amount, 0)) + FROM `tabExpense Claim Advance` eca, `tabExpense Claim` ec + WHERE + eca.employee_advance = %s + AND ec.approval_status="Approved" + AND ec.name = eca.parent + AND ec.docstatus=1 + AND eca.allocated_amount > 0 """, self.name)[0][0] or 0 - if claimed_amount: - frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount)) + frappe.db.set_value("Employee Advance", self.name, "claimed_amount", flt(claimed_amount)) + self.reload() + self.set_status() + frappe.db.set_value("Employee Advance", self.name, "status", self.status) @frappe.whitelist() def get_due_advance_amount(employee, posting_date): diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.js b/erpnext/hr/doctype/expense_claim/expense_claim.js index 51bcf9f904f..cfdb813cb8c 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.js +++ b/erpnext/hr/doctype/expense_claim/expense_claim.js @@ -178,7 +178,7 @@ frappe.ui.form.on("Expense Claim", { refresh: function(frm) { frm.trigger("toggle_fields"); - if(frm.doc.docstatus == 1) { + if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") { frm.add_custom_button(__('Accounting Ledger'), function() { frappe.route_options = { voucher_no: frm.doc.name, @@ -189,7 +189,7 @@ frappe.ui.form.on("Expense Claim", { }, __("View")); } - if (frm.doc.docstatus===1 + if (frm.doc.docstatus===1 && !cint(frm.doc.is_paid) && cint(frm.doc.grand_total) > 0 && (cint(frm.doc.total_amount_reimbursed) < cint(frm.doc.total_sanctioned_amount)) && frappe.model.can_create("Payment Entry")) { frm.add_custom_button(__('Payment'), From 94f4d81b70d9eddf8bde900e37f18fcd52474630 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:08:02 +0530 Subject: [PATCH 4/9] fix: Quotation list in customer portal (#18580) * fix: Quotation list in customer portal Customers were not able to see their quotations because of the recent customer field removal from quotation * fix: Remove duplicate code --- .../controllers/website_list_for_contact.py | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index ed48fd1ab4a..187eaed107f 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -77,7 +77,7 @@ def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_len if or_filters: for r in frappe.get_list(doctype, fields=fields,filters=filters, or_filters=or_filters, - limit_start=limit_start, limit_page_length=limit_page_length, + limit_start=limit_start, limit_page_length=limit_page_length, ignore_permissions=ignore_permissions, order_by=order_by): data.append(r) @@ -130,38 +130,56 @@ def get_customers_suppliers(doctype, user): suppliers = [] meta = frappe.get_meta(doctype) + customer_field_name = get_customer_field_name(doctype) + + has_customer_field = meta.has_field(customer_field_name) + has_supplier_field = meta.has_field('supplier') + if has_common(["Supplier", "Customer"], frappe.get_roles(user)): contacts = frappe.db.sql(""" - select + select `tabContact`.email_id, `tabDynamic Link`.link_doctype, `tabDynamic Link`.link_name - from + from `tabContact`, `tabDynamic Link` where `tabContact`.name=`tabDynamic Link`.parent and `tabContact`.email_id =%s """, user, as_dict=1) - customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] \ - if meta.get_field("customer") else None - suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] \ - if meta.get_field("supplier") else None + customers = [c.link_name for c in contacts if c.link_doctype == 'Customer'] + suppliers = [c.link_name for c in contacts if c.link_doctype == 'Supplier'] elif frappe.has_permission(doctype, 'read', user=user): - customers = [customer.name for customer in frappe.get_list("Customer")] \ - if meta.get_field("customer") else None - suppliers = [supplier.name for supplier in frappe.get_list("Customer")] \ - if meta.get_field("supplier") else None + customer_list = frappe.get_list("Customer") + customers = suppliers = [customer.name for customer in customer_list] - return customers, suppliers + return customers if has_customer_field else None, \ + suppliers if has_supplier_field else None def has_website_permission(doc, ptype, user, verbose=False): doctype = doc.doctype customers, suppliers = get_customers_suppliers(doctype, user) if customers: - return frappe.get_all(doctype, filters=[(doctype, "customer", "in", customers), - (doctype, "name", "=", doc.name)]) and True or False + return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers)) elif suppliers: fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier' - return frappe.get_all(doctype, filters=[(doctype, fieldname, "in", suppliers), - (doctype, "name", "=", doc.name)]) and True or False + return frappe.db.exists(doctype, filters={ + 'name': doc.name, + fieldname: ["in", suppliers] + }) else: return False + +def get_customer_filter(doc, customers): + doctype = doc.doctype + filters = frappe._dict() + filters.name = doc.name + filters[get_customer_field_name(doctype)] = ['in', customers] + if doctype == 'Quotation': + filters.party_type = 'Customer' + return filters + +def get_customer_field_name(doctype): + if doctype == 'Quotation': + return 'party_name' + else: + return 'customer' \ No newline at end of file From 342c77c8511b6038a5336a4e838b5423ea35efc5 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:11:07 +0530 Subject: [PATCH 5/9] fix: Customer price list not honored in shopping cart (#18555) --- erpnext/shopping_cart/cart.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 6fdc649e3f5..e98466b6769 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -202,13 +202,12 @@ def _get_cart_quotation(party=None): if quotation: qdoc = frappe.get_doc("Quotation", quotation[0].name) else: - [company, price_list] = frappe.db.get_value("Shopping Cart Settings", None, ["company", "price_list"]) + company = frappe.db.get_value("Shopping Cart Settings", None, ["company"]) qdoc = frappe.get_doc({ "doctype": "Quotation", "naming_series": get_shopping_cart_settings().quotation_series or "QTN-CART-", "quotation_to": party.doctype, "company": company, - "selling_price_list": price_list, "order_type": "Shopping Cart", "status": "Draft", "docstatus": 0, From 6f7a5e525d68e02c8c3c66cf9d24434fd84f1058 Mon Sep 17 00:00:00 2001 From: Deepesh Garg <42651287+deepeshgarg007@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:14:37 +0530 Subject: [PATCH 6/9] fix: Make conversion rate optional for non itemized items (#18538) --- erpnext/buying/utils.py | 14 ++++++++------ erpnext/controllers/buying_controller.py | 4 +++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/buying/utils.py b/erpnext/buying/utils.py index 9ad1c5cf85c..52f33672bec 100644 --- a/erpnext/buying/utils.py +++ b/erpnext/buying/utils.py @@ -30,7 +30,9 @@ def update_last_purchase_rate(doc, is_submit): # for it to be considered for latest purchase rate if flt(d.conversion_factor): last_purchase_rate = flt(d.base_rate) / flt(d.conversion_factor) - else: + # Check if item code is present + # Conversion factor should not be mandatory for non itemized items + elif d.item_code: frappe.throw(_("UOM Conversion factor is required in row {0}").format(d.idx)) # update last purchsae rate @@ -84,13 +86,13 @@ def get_linked_material_requests(items): items = json.loads(items) mr_list = [] for item in items: - material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name, - (mr_item.qty - mr_item.ordered_qty) AS qty, + material_request = frappe.db.sql("""SELECT distinct mr.name AS mr_name, + (mr_item.qty - mr_item.ordered_qty) AS qty, mr_item.item_code AS item_code, - mr_item.name AS mr_item + mr_item.name AS mr_item FROM `tabMaterial Request` mr, `tabMaterial Request Item` mr_item WHERE mr.name = mr_item.parent - AND mr_item.item_code = %(item)s + AND mr_item.item_code = %(item)s AND mr.material_request_type = 'Purchase' AND mr.per_ordered < 99.99 AND mr.docstatus = 1 @@ -98,6 +100,6 @@ def get_linked_material_requests(items): ORDER BY mr_item.item_code ASC""",{"item": item}, as_dict=1) if material_request: mr_list.append(material_request) - + return mr_list diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 917c901cfcb..74427436fa4 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -395,7 +395,9 @@ class BuyingController(StockController): def set_qty_as_per_stock_uom(self): for d in self.get("items"): if d.meta.get_field("stock_qty"): - if not d.conversion_factor: + # Check if item code is present + # Conversion factor should not be mandatory for non itemized items + if not d.conversion_factor and d.item_code: frappe.throw(_("Row {0}: Conversion Factor is mandatory").format(d.idx)) d.stock_qty = flt(d.qty) * flt(d.conversion_factor) From 55025d4dc97f7eb8a418036295be25d82cbfe367 Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 5 Aug 2019 10:16:10 +0530 Subject: [PATCH 7/9] fix(sales-order): update items (#18537) * fix(sales-order): update items * fix: minor changes --- erpnext/controllers/accounts_controller.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index be25d56129f..7ebf73721d0 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1112,6 +1112,10 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name): .format(child_item.idx, child_item.item_code)) else: child_item.rate = flt(d.get("rate")) + if flt(child_item.price_list_rate): + child_item.discount_percentage = flt((1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0, \ + child_item.precision("discount_percentage")) + child_item.flags.ignore_validate_update_after_submit = True child_item.save() From edb3cdbb59c03de82ddb115c6151f87f4e34794d Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Mon, 5 Aug 2019 10:27:48 +0530 Subject: [PATCH 8/9] fix: query (#18465) --- .../doctype/payment_entry/payment_entry.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 8a17c075b48..440529ab760 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -613,13 +613,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre orders = [] if voucher_type: - ref_field = "base_grand_total" if party_account_currency == company_currency else "grand_total" + if party_account_currency == company_currency: + grand_total_field = "base_grand_total" + rounded_total_field = "base_rounded_total" + else: + grand_total_field = "grand_total" + rounded_total_field = "rounded_total" orders = frappe.db.sql(""" select name as voucher_no, - {ref_field} as invoice_amount, - ({ref_field} - advance_paid) as outstanding_amount, + if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) as invoice_amount, + (if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) - advance_paid) as outstanding_amount, transaction_date as posting_date from `tab{voucher_type}` @@ -627,17 +632,18 @@ def get_orders_to_be_billed(posting_date, party_type, party, party_account_curre {party_type} = %s and docstatus = 1 and ifnull(status, "") != "Closed" - and {ref_field} > advance_paid + and if({rounded_total_field}, {rounded_total_field}, {grand_total_field}) > advance_paid and abs(100 - per_billed) > 0.01 {condition} order by transaction_date, name """.format(**{ - "ref_field": ref_field, + "rounded_total_field": rounded_total_field, + "grand_total_field": grand_total_field, "voucher_type": voucher_type, "party_type": scrub(party_type), "condition": condition - }), party, as_dict=True) + }), (party), as_dict=True) order_list = [] for d in orders: From cf4c7b406ad183e37a375f238e330e82f3f8c2a9 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Wed, 7 Aug 2019 16:37:49 +0550 Subject: [PATCH 9/9] bumped to version 11.1.53 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index d3ceb09eaa0..bfe8539d5ee 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '11.1.52' +__version__ = '11.1.53' def get_default_company(user=None): '''Get default company for user'''