diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 070c93f096..4d6cccf3df 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.7.0' +__version__ = '8.7.1' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/accounts/doctype/account/account.js b/erpnext/accounts/doctype/account/account.js index ed7e39af22..ca46d6b0e5 100644 --- a/erpnext/accounts/doctype/account/account.js +++ b/erpnext/accounts/doctype/account/account.js @@ -68,7 +68,8 @@ frappe.ui.form.on('Account', { } }); }); - } else if (cint(frm.doc.is_group) == 0) { + } else if (cint(frm.doc.is_group) == 0 + && frappe.boot.user.can_read.indexOf("GL Entry") !== -1) { cur_frm.add_custom_button(__('Ledger'), function () { frappe.route_options = { "account": frm.doc.name, diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index b1a41297f8..76e66d0906 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -718,7 +718,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-04-27 13:18:06.617940", + "modified": "2017-08-03 12:40:09.611951", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", @@ -786,7 +786,7 @@ } ], "quick_entry": 1, - "read_only": 1, + "read_only": 0, "read_only_onload": 0, "search_fields": "voucher_no,account,posting_date,against_voucher", "show_name_in_global_search": 0, diff --git a/erpnext/accounts/doctype/gl_entry/test_gl_entry.js b/erpnext/accounts/doctype/gl_entry/test_gl_entry.js new file mode 100644 index 0000000000..2986e5e4e3 --- /dev/null +++ b/erpnext/accounts/doctype/gl_entry/test_gl_entry.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: GL Entry", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially('GL Entry', [ + // insert a new GL Entry + () => frappe.tests.make([ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index e768c2719e..589bc40cd5 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -510,7 +510,7 @@ class PurchaseInvoice(BuyingController): i += 1 - if self.update_stock and valuation_tax: + if self.auto_accounting_for_stock and self.update_stock and valuation_tax: for cost_center, amount in valuation_tax.items(): gl_entries.append( self.get_gl_dict({ diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 90b36e0688..01071c53fc 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import frappe import unittest, copy from frappe.utils import nowdate, add_days, flt +from frappe.model.dynamic_links import get_dynamic_link_map from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry, get_qty_after_transaction from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import unlink_payment_on_cancel_of_invoice from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile @@ -119,6 +120,10 @@ class TestSalesInvoice(unittest.TestCase): pe.insert() pe.submit() + link_data = get_dynamic_link_map().get('Sales Invoice', []) + link_doctypes = [d.parent for d in link_data] + self.assertEquals(link_doctypes[-1], 'GL Entry') + unlink_payment_on_cancel_of_invoice(0) si = frappe.get_doc('Sales Invoice', si.name) self.assertRaises(frappe.LinkExistsError, si.cancel) diff --git a/erpnext/hr/doctype/process_payroll/process_payroll.py b/erpnext/hr/doctype/process_payroll/process_payroll.py index b58c7872cc..7575ee45b4 100644 --- a/erpnext/hr/doctype/process_payroll/process_payroll.py +++ b/erpnext/hr/doctype/process_payroll/process_payroll.py @@ -311,7 +311,7 @@ class ProcessPayroll(Document): journal_entry.submit() jv_name = journal_entry.name self.update_salary_slip_status(jv_name = jv_name) - except Exception, e: + except Exception as e: frappe.msgprint(e) return jv_name @@ -339,7 +339,12 @@ class ProcessPayroll(Document): "debit_in_account_currency": total_salary_amount.rounded_total }) journal_entry.set("accounts", account_amt_list) - return journal_entry.as_dict() + return journal_entry.as_dict() + else: + frappe.msgprint( + _("There are no submitted Salary Slips to process."), + title="Error", indicator="red" + ) def update_salary_slip_status(self, jv_name = None): ss_list = self.get_sal_slip_list(ss_status=1) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index d018968083..6a14569a3b 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -428,4 +428,6 @@ erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs erpnext.patches.v8_5.remove_quotations_route_in_sidebar erpnext.patches.v8_5.update_existing_data_in_project_type erpnext.patches.v8_5.update_customer_group_in_POS_profile -erpnext.patches.v8_6.update_timesheet_company_from_PO \ No newline at end of file +erpnext.patches.v8_6.update_timesheet_company_from_PO +erpnext.patches.v8_6.set_write_permission_for_quotation_for_sales_manager +erpnext.patches.v8_5.remove_project_type_property_setter \ No newline at end of file diff --git a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py index 2ae74cdbbc..5dedc81d54 100644 --- a/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py +++ b/erpnext/patches/v8_0/set_sales_invoice_serial_number_from_delivery_note.py @@ -26,7 +26,7 @@ def execute(): if not sales_invoice or not serial_nos: continue - serial_nos = ["'%s'"%no for no in serial_nos.split("\n")] + serial_nos = ["'%s'"%frappe.db.escape(no) for no in serial_nos.split("\n")] frappe.db.sql(""" UPDATE @@ -36,7 +36,7 @@ def execute(): WHERE name in ({serial_nos}) """.format( - sales_invoice=sales_invoice, + sales_invoice=frappe.db.escape(sales_invoice), serial_nos=",".join(serial_nos) ) ) \ No newline at end of file diff --git a/erpnext/patches/v8_5/remove_project_type_property_setter.py b/erpnext/patches/v8_5/remove_project_type_property_setter.py new file mode 100644 index 0000000000..11db783497 --- /dev/null +++ b/erpnext/patches/v8_5/remove_project_type_property_setter.py @@ -0,0 +1,17 @@ +import frappe + +def execute(): + ps = frappe.db.get_value('Property Setter', dict(doc_type='Project', field_name='project_type', + property='options')) + if ps: + frappe.delete_doc('Property Setter', ps) + + project_types = frappe.db.sql_list('select distinct project_type from tabProject') + + for project_type in project_types: + if not frappe.db.exists("Project Type", project_type): + p_type = frappe.get_doc({ + "doctype": "Project Type", + "project_type": project_type + }) + p_type.insert() \ No newline at end of file diff --git a/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py new file mode 100644 index 0000000000..c2320ec04c --- /dev/null +++ b/erpnext/patches/v8_6/set_write_permission_for_quotation_for_sales_manager.py @@ -0,0 +1,11 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + # Set write permission to permlevel 1 for sales manager role in Quotation doctype + frappe.db.sql(""" update `tabCustom DocPerm` set `tabCustom DocPerm`.write = 1 + where `tabCustom DocPerm`.parent = 'Quotation' and `tabCustom DocPerm`.role = 'Sales Manager' + and `tabCustom DocPerm`.permlevel = 1 """) diff --git a/erpnext/selling/doctype/quotation/quotation.json b/erpnext/selling/doctype/quotation/quotation.json index 21090230dd..313041352a 100644 --- a/erpnext/selling/doctype/quotation/quotation.json +++ b/erpnext/selling/doctype/quotation/quotation.json @@ -2572,7 +2572,7 @@ "istable": 0, "max_attachments": 1, "menu_index": 0, - "modified": "2017-07-19 13:49:33.388736", + "modified": "2017-08-02 18:15:38.198698", "modified_by": "Administrator", "module": "Selling", "name": "Quotation", @@ -2638,7 +2638,7 @@ "set_user_permissions": 0, "share": 0, "submit": 0, - "write": 0 + "write": 1 }, { "amend": 1, diff --git a/erpnext/shopping_cart/product.py b/erpnext/shopping_cart/product.py index 1999a4aa43..912467ff2a 100644 --- a/erpnext/shopping_cart/product.py +++ b/erpnext/shopping_cart/product.py @@ -85,7 +85,7 @@ def get_price(item_code, template_item_code, price_list, qty=1): if pricing_rule: if pricing_rule.pricing_rule_for == "Discount Percentage": - price[0].price_list_rate = flt(price[0].price_list_rate * (1.0 - (pricing_rule.discount_percentage / 100.0))) + price[0].price_list_rate = flt(price[0].price_list_rate * (1.0 - (flt(pricing_rule.discount_percentage) / 100.0))) if pricing_rule.pricing_rule_for == "Price": price[0].price_list_rate = pricing_rule.price_list_rate