From 3fc3305251162108183e5348b961c0ebee31700f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 11 Apr 2017 16:00:48 +0530 Subject: [PATCH 01/23] bom traversing: argument mutable issue --- erpnext/manufacturing/doctype/bom/bom.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index abb2817e4f0..b8a8ae8aea3 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -281,12 +281,15 @@ class BOM(WebsiteGenerator): return bom_list - def traverse_tree(self, bom_list=[]): + def traverse_tree(self, bom_list=None): def _get_children(bom_no): return [cstr(d[0]) for d in frappe.db.sql("""select bom_no from `tabBOM Item` where parent = %s and ifnull(bom_no, '') != ''""", bom_no)] count = 0 + if not bom_list: + bom_list = [] + if self.name not in bom_list: bom_list.append(self.name) From dc981dc546a798bdd9306d70e3c33dbf115d4607 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 3 Apr 2017 14:17:08 +0530 Subject: [PATCH 02/23] [fix] Auto serial no fecthed on the invoice even if stock update is disabled issue --- erpnext/controllers/accounts_controller.py | 8 +++++--- erpnext/patches.txt | 3 ++- ...ll_to_serial_nos_for_disabled_sales_invoices.py | 14 ++++++++++++++ erpnext/public/js/controllers/transaction.js | 10 +++++++--- erpnext/stock/get_item_details.py | 13 ++++++++++++- 5 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 910c19c9ca0..ecbf59da1b5 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -192,11 +192,13 @@ class AccountsController(TransactionBase): if (item.get(fieldname) is None or fieldname in force_item_fields): item.set(fieldname, value) - elif fieldname == "cost_center" and not item.get("cost_center"): + elif fieldname in ['cost_center', 'conversion_factor'] and not item.get(fieldname): item.set(fieldname, value) - elif fieldname == "conversion_factor" and not item.get("conversion_factor"): - item.set(fieldname, value) + elif fieldname == "serial_no": + stock_qty = item.get("stock_qty") * -1 if item.get("stock_qty") < 0 else item.get("stock_qty") + if stock_qty != len(item.get('serial_no').split('\n')): + item.set(fieldname, value) if ret.get("pricing_rule"): # if user changed the discount percentage then set user's discount percentage ? diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 9c2b1c49ad1..522c4fca9cf 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -385,4 +385,5 @@ erpnext.patches.v8_0.addresses_linked_to_lead execute:frappe.delete_doc('DocType', 'Purchase Common') erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice erpnext.patches.v8_0.update_supplier_address_in_stock_entry -erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate \ No newline at end of file +erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate +erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices \ No newline at end of file diff --git a/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py b/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py new file mode 100644 index 00000000000..197d6ded61a --- /dev/null +++ b/erpnext/patches/v8_0/set_null_to_serial_nos_for_disabled_sales_invoices.py @@ -0,0 +1,14 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe +from erpnext.stock.stock_balance import update_bin_qty, get_reserved_qty + +def execute(): + frappe.db.sql(""" + update + `tabSales Invoice Item` + set serial_no = NULL + where + parent in (select name from `tabSales Invoice` where update_stock = 0 and docstatus = 1)""") \ No newline at end of file diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 7e0dccc6a1c..a583f7d05b3 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -260,6 +260,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ customer: me.frm.doc.customer, supplier: me.frm.doc.supplier, currency: me.frm.doc.currency, + update_stock: in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0, conversion_rate: me.frm.doc.conversion_rate, price_list: me.frm.doc.selling_price_list || me.frm.doc.buying_price_list, @@ -275,7 +276,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ name: me.frm.doc.name, project: item.project || me.frm.doc.project, qty: item.qty, - stock_qty: item.stock_qty + stock_qty: item.stock_qty, + conversion_factor: item.conversion_factor } }, @@ -762,7 +764,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "ignore_pricing_rule": me.frm.doc.ignore_pricing_rule, "doctype": me.frm.doc.doctype, "name": me.frm.doc.name, - "is_return": cint(me.frm.doc.is_return) + "is_return": cint(me.frm.doc.is_return), + "update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0, }; }, @@ -781,7 +784,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "parent": d.parent, "pricing_rule": d.pricing_rule, "warehouse": d.warehouse, - "serial_no": d.serial_no + "serial_no": d.serial_no, + "conversion_factor": d.conversion_factor }); // if doctype is Quotation Item / Sales Order Iten then add Margin Type and rate in item_list diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 3ada10ba6be..c2e77df3fee 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -161,7 +161,7 @@ def get_basic_details(args, item): "min_order_qty": flt(item.min_order_qty) if args.doctype == "Material Request" else "", "conversion_factor": 1.0, "qty": args.qty or 1.0, - "stock_qty": 1.0, + "stock_qty": args.qty or 1.0, "price_list_rate": 0.0, "base_price_list_rate": 0.0, "rate": 0.0, @@ -172,10 +172,18 @@ def get_basic_details(args, item): "net_amount": 0.0, "discount_percentage": 0.0, "supplier": item.default_supplier, + "update_stock": args.get("update_stock") if args.get('doctype') in ['Sales Invoice', 'Purchase Invoice'] else 0, "delivered_by_supplier": item.delivered_by_supplier if args.get("doctype") in ["Sales Order", "Sales Invoice"] else 0, "is_fixed_asset": item.is_fixed_asset }) + # calculate conversion factor + conversion_factor = args.get("conversion_factor") or get_conversion_factor(item.item_code, args.uom).get("conversion_factor") or 1.0 + out.update({ + "conversion_factor": conversion_factor, + "stock_qty": out.qty * conversion_factor + }) + # if default specified in item is for another company, fetch from company for d in [["Account", "income_account", "default_income_account"], ["Account", "expense_account", "default_expense_account"], @@ -532,6 +540,9 @@ def get_serial_no(args): args = json.loads(args) args = frappe._dict(args) + if args.get('doctype') == 'Sales Invoice' and not args.get('update_stock'): + return "" + if args.get('warehouse') and args.get('stock_qty') and args.get('item_code'): if frappe.get_value('Item', {'item_code': args.item_code}, "has_serial_no") == 1: From d7de3c606b2448fe0df93f0b566ca90c07c283c6 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 17 Apr 2017 13:36:08 +0530 Subject: [PATCH 03/23] [fix] Pricing rule for pos --- erpnext/accounts/doctype/sales_invoice/pos.py | 21 +++++++---- erpnext/accounts/page/pos/pos.js | 37 +++++++++++++++++-- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 419c5579e0b..f1f997a7f69 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -32,7 +32,7 @@ def get_pos_data(): 'doc': doc, 'default_customer': pos_profile.get('customer'), 'items': get_items_list(pos_profile), - 'item_groups': get_item_group(pos_profile), + 'item_groups': get_item_groups(pos_profile), 'customers': customers, 'address': get_customers_address(customers), 'serial_no_data': get_serial_no_data(pos_profile, doc.company), @@ -132,7 +132,7 @@ def get_items_list(pos_profile): if pos_profile.get('item_groups'): # Get items based on the item groups defined in the POS profile for d in pos_profile.get('item_groups'): - item_groups.extend(get_child_nodes('Item Group', d.item_group)) + item_groups.extend([d.name for d in get_child_nodes('Item Group', d.item_group)]) cond = "item_group in (%s)"%(', '.join(['%s']*len(item_groups))) return frappe.db.sql(""" @@ -146,14 +146,19 @@ def get_items_list(pos_profile): disabled = 0 and has_variants = 0 and is_sales_item = 1 and {cond} """.format(cond=cond), tuple(item_groups), as_dict=1) -def get_item_group(pos_profile): +def get_item_groups(pos_profile): + item_group_dict = {} if pos_profile.get('item_groups'): item_groups = [] for d in pos_profile.get('item_groups'): item_groups.extend(get_child_nodes('Item Group', d.item_group)) - return item_groups else: - return frappe.db.sql_list("""Select name from `tabItem Group` order by name""") + item_groups = frappe.db.sql("""Select name, + lft, rgt from `tabItem Group` order by lft""", as_dict=1) + + for data in item_groups: + item_group_dict[data.name] = [data.lft, data.rgt] + return item_group_dict def get_customers_list(pos_profile): cond = "1=1" @@ -161,7 +166,7 @@ def get_customers_list(pos_profile): if pos_profile.get('customer_groups'): # Get customers based on the customer groups defined in the POS profile for d in pos_profile.get('customer_groups'): - customer_groups.extend(get_child_nodes('Customer Group', d.customer_group)) + customer_groups.extend([d.name for d in get_child_nodes('Customer Group', d.customer_group)]) cond = "customer_group in (%s)"%(', '.join(['%s']*len(customer_groups))) return frappe.db.sql(""" select name, customer_name, customer_group, @@ -187,8 +192,8 @@ def get_customers_address(customers): def get_child_nodes(group_type, root): lft, rgt = frappe.db.get_value(group_type, root, ["lft", "rgt"]) - return frappe.db.sql_list(""" Select name from `tab{tab}` where - lft >= {lft} and rgt <= {rgt}""".format(tab=group_type, lft=lft, rgt=rgt)) + return frappe.db.sql(""" Select name, lft, rgt from `tab{tab}` where + lft >= {lft} and rgt <= {rgt} order by lft""".format(tab=group_type, lft=lft, rgt=rgt), as_dict=1) def get_serial_no_data(pos_profile, company): # get itemwise serial no data diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index 670a577c4e7..70067614b6b 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -407,8 +407,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }); this.search_item_group = this.wrapper.find('.search-item-group'); - - var dropdown_html = me.item_groups.map(function(item_group) { + sorted_item_groups = this.get_sorted_item_groups() + var dropdown_html = sorted_item_groups.map(function(item_group) { return "
  • "+item_group+"
  • "; }).join(""); @@ -437,6 +437,15 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }) }, + get_sorted_item_groups: function() { + list = {} + $.each(this.item_groups, function(i, data) { + list[i] = data[0] + }) + + return Object.keys(list).sort(function(a,b){return list[a]-list[b]}) + }, + toggle_more_btn: function() { if(!this.items || this.items.length <= this.page_len) { this.wrapper.find(".btn-more").hide(); @@ -1091,9 +1100,9 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ // $(me.wrapper).find(".pos-item-wrapper").on("click", function () { $(this.wrapper).on("click", ".pos-item-wrapper", function () { me.item_code = ''; + me.customer_validate(); if($(me.pos_bill).is(":hidden")) return; - me.customer_validate(); if (me.frm.doc.docstatus == 0) { me.items = me.get_items($(this).attr("data-item-code")) me.add_to_cart(); @@ -1768,7 +1777,7 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ var me = this; return $.grep(this.pricing_rules, function (data) { if (item.qty >= data.min_qty && (item.qty <= (data.max_qty ? data.max_qty : item.qty))) { - if (data.item_code == item.item_code || in_list(['All Item Groups', item.item_group], data.item_group) || item.brand == data.brand) { + if (me.validate_item_condition(data, item)) { if (in_list(['Customer', 'Customer Group', 'Territory', 'Campaign'], data.applicable_for)) { return me.validate_condition(data) } else { @@ -1779,6 +1788,26 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ }) }, + validate_item_condition: function (data, item) { + var apply_on = frappe.model.scrub(data.apply_on); + + return (data.apply_on == 'Item Group') + ? this.validate_item_group(data.item_group, item.item_group) : (data[apply_on] == item[apply_on]); + }, + + validate_item_group: function (pr_item_group, cart_item_group) { + //pr_item_group = pricing rule's item group + //cart_item_group = cart item's item group + //this.item_groups has information about item group's lft and rgt + //for example: {'Foods': [12, 19]} + + pr_item_group = this.item_groups[pr_item_group] + cart_item_group = this.item_groups[cart_item_group] + + return (cart_item_group[0] >= pr_item_group[0] && + cart_item_group[1] <= pr_item_group[1]) + }, + validate_condition: function (data) { //This method check condition based on applicable for condition = this.get_mapper_for_pricing_rule(data)[data.applicable_for] From 5123a8519b03343c323034b6a011756fe03cf699 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Tue, 18 Apr 2017 10:33:40 +0530 Subject: [PATCH 04/23] [minor] check if joining date is available before validating attandance date --- erpnext/hr/doctype/attendance/attendance.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py index 72fa47dd815..458b2dd5c19 100644 --- a/erpnext/hr/doctype/attendance/attendance.py +++ b/erpnext/hr/doctype/attendance/attendance.py @@ -35,9 +35,11 @@ class Attendance(Document): frappe.throw(_("No leave record found for employee {0} for {1}").format(self.employee, self.attendance_date)) def validate_attendance_date(self): + date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining") + if getdate(self.attendance_date) > getdate(nowdate()): frappe.throw(_("Attendance can not be marked for future dates")) - elif getdate(self.attendance_date) < frappe.db.get_value("Employee", self.employee, "date_of_joining"): + elif date_of_joining and getdate(self.attendance_date) < getdate(date_of_joining): frappe.throw(_("Attendance date can not be less than employee's joining date")) def validate_employee(self): From 8a019807572447a6aa0f431d50137a32d43b1580 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 18 Apr 2017 13:11:10 +0530 Subject: [PATCH 05/23] Unlink Journal Entry reference from Asset --- .../accounts/doctype/journal_entry/journal_entry.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index a471c48c575..b9b8fc29685 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -72,6 +72,7 @@ class JournalEntry(AccountsController): self.update_expense_claim() self.update_employee_loan() self.unlink_advance_entry_reference() + self.unlink_asset_reference() def unlink_advance_entry_reference(self): for d in self.get("accounts"): @@ -81,6 +82,18 @@ class JournalEntry(AccountsController): d.reference_type = '' d.reference_name = '' d.db_update() + + def unlink_asset_reference(self): + for d in self.get("accounts"): + if d.reference_type=="Asset" and d.reference_name: + asset = frappe.get_doc("Asset", d.reference_name) + for s in asset.get("schedules"): + if s.journal_entry == self.name: + s.db_set("journal_entry", None) + asset.value_after_depreciation += s.depreciation_amount + + asset.db_set("value_after_depreciation", asset.value_after_depreciation) + asset.set_status() def validate_party(self): for d in self.get("accounts"): From 117be7ddd5208ad1eece3e4e61c4dbdf77b13aad Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 18 Apr 2017 14:02:07 +0530 Subject: [PATCH 06/23] Added a settings in Accounts Settings to disable booking depreciation entry automatically --- .../accounts_settings/accounts_settings.json | 64 +++++++++++++++++-- .../accounts/doctype/asset/depreciation.py | 4 ++ erpnext/accounts/doctype/asset/test_asset.py | 22 ++++++- erpnext/demo/user/fixed_asset.py | 3 + erpnext/patches.txt | 3 +- ...ooking_asset_depreciation_automatically.py | 9 +++ 6 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 7a4d40d6ee4..4f268a24ccf 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -25,7 +26,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Make Accounting Entry For Every Stock Movement", "length": 0, "no_copy": 0, @@ -33,6 +36,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -51,7 +55,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Accounts Frozen Upto", "length": 0, "no_copy": 0, @@ -59,6 +65,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -77,7 +84,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries", "length": 0, "no_copy": 0, @@ -86,6 +95,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -103,7 +113,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "length": 0, "no_copy": 0, "permlevel": 0, @@ -111,6 +123,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -129,7 +142,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 1, + "in_standard_filter": 0, "label": "Credit Controller", "length": 0, "no_copy": 0, @@ -138,6 +153,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -155,7 +171,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Check Supplier Invoice Number Uniqueness", "length": 0, "no_copy": 0, @@ -164,6 +182,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -181,7 +200,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Make Payment via Journal Entry", "length": 0, "no_copy": 0, @@ -190,6 +211,7 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -208,7 +230,9 @@ "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, + "in_standard_filter": 0, "label": "Unlink Payment on Cancellation of Invoice", "length": 0, "no_copy": 0, @@ -217,6 +241,37 @@ "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "default": "1", + "fieldname": "book_asset_depreciation_entry_automatically", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Book Asset Depreciation Entry Automatically", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, "search_index": 0, @@ -224,18 +279,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, - "icon": "fa fa-cog", + "icon": "icon-cog", "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2016-10-20 16:12:38.595075", + "modified": "2017-04-18 13:35:59.166250", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", @@ -251,7 +306,6 @@ "export": 0, "if_owner": 0, "import": 0, - "is_custom": 0, "permlevel": 0, "print": 1, "read": 1, @@ -266,6 +320,8 @@ "quick_entry": 1, "read_only": 0, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_order": "ASC", + "track_changes": 1, "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/accounts/doctype/asset/depreciation.py b/erpnext/accounts/doctype/asset/depreciation.py index 15c155c7ac5..397342dc46f 100644 --- a/erpnext/accounts/doctype/asset/depreciation.py +++ b/erpnext/accounts/doctype/asset/depreciation.py @@ -8,6 +8,10 @@ from frappe import _ from frappe.utils import flt, today, getdate def post_depreciation_entries(date=None): + # Return if automatic booking of asset depreciation is disabled + if not frappe.db.get_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically"): + return + if not date: date = today() for asset in get_depreciable_assets(date): diff --git a/erpnext/accounts/doctype/asset/test_asset.py b/erpnext/accounts/doctype/asset/test_asset.py index 51496b918c9..000bc5ccd25 100644 --- a/erpnext/accounts/doctype/asset/test_asset.py +++ b/erpnext/accounts/doctype/asset/test_asset.py @@ -166,6 +166,23 @@ class TestAsset(unittest.TestCase): self.assertEqual(gle, expected_gle) self.assertEqual(asset.get("value_after_depreciation"), 70000) + + def test_depreciation_entry_cancellation(self): + asset = frappe.get_doc("Asset", "Macbook Pro 1") + asset.submit() + post_depreciation_entries(date="2021-01-01") + + asset.load_from_db() + + # cancel depreciation entry + depr_entry = asset.get("schedules")[0].journal_entry + self.assertTrue(depr_entry) + frappe.get_doc("Journal Entry", depr_entry).cancel() + + asset.load_from_db() + depr_entry = asset.get("schedules")[0].journal_entry + self.assertFalse(depr_entry) + def test_scrap_asset(self): asset = frappe.get_doc("Asset", "Macbook Pro 1") @@ -297,4 +314,7 @@ def set_depreciation_settings_in_company(): company.depreciation_expense_account = "_Test Depreciations - _TC" company.disposal_account = "_Test Gain/Loss on Asset Disposal - _TC" company.depreciation_cost_center = "_Test Cost Center - _TC" - company.save() \ No newline at end of file + company.save() + + # Enable booking asset depreciation entry automatically + frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) \ No newline at end of file diff --git a/erpnext/demo/user/fixed_asset.py b/erpnext/demo/user/fixed_asset.py index bf3199ea5f9..b2db39c9f07 100644 --- a/erpnext/demo/user/fixed_asset.py +++ b/erpnext/demo/user/fixed_asset.py @@ -18,6 +18,9 @@ def work(): # fixed_asset.work() already run return + # Enable booking asset depreciation entry automatically + frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) + # post depreciation entries as on today post_depreciation_entries() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 522c4fca9cf..6881fd6db4d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -386,4 +386,5 @@ execute:frappe.delete_doc('DocType', 'Purchase Common') erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice erpnext.patches.v8_0.update_supplier_address_in_stock_entry erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate -erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices \ No newline at end of file +erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices +erpnext.patches.v8_0.enable_booking_asset_depreciation_automatically \ No newline at end of file diff --git a/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py b/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py new file mode 100644 index 00000000000..1088d702dd0 --- /dev/null +++ b/erpnext/patches/v8_0/enable_booking_asset_depreciation_automatically.py @@ -0,0 +1,9 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.db.set_value("Accounts Settings", None, + "book_asset_depreciation_entry_automatically", 1) \ No newline at end of file From 2704162f5a2540e9e62756a32c325983f23a6d92 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 19 Apr 2017 16:25:39 +0530 Subject: [PATCH 07/23] Fixes allowd on submit --- .../purchase_invoice_item/purchase_invoice_item.json | 4 ++-- .../doctype/sales_invoice_item/sales_invoice_item.json | 4 ++-- erpnext/selling/doctype/customer/test_customer.py | 7 ++++++- .../doctype/delivery_note_item/delivery_note_item.json | 4 ++-- .../purchase_receipt_item/purchase_receipt_item.json | 4 ++-- .../doctype/stock_entry_detail/stock_entry_detail.json | 4 ++-- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index bf370c86845..5e964ed6255 100755 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -1422,7 +1422,7 @@ "unique": 0 }, { - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, @@ -1939,7 +1939,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-17 13:44:17.460674", + "modified": "2017-04-19 11:54:16.112134", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index 205b61e8821..80f8b57fb99 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -1548,7 +1548,7 @@ "unique": 0 }, { - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, @@ -2094,7 +2094,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-05 23:28:13.520429", + "modified": "2017-04-19 11:53:26.682964", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Invoice Item", diff --git a/erpnext/selling/doctype/customer/test_customer.py b/erpnext/selling/doctype/customer/test_customer.py index 0d74d23eb4c..40ed6f98fe1 100644 --- a/erpnext/selling/doctype/customer/test_customer.py +++ b/erpnext/selling/doctype/customer/test_customer.py @@ -54,25 +54,30 @@ class TestCustomer(unittest.TestCase): self.assertEquals(value, details.get(key)) def test_rename(self): + # delete communication linked to these 2 customers for name in ("_Test Customer 1", "_Test Customer 1 Renamed"): frappe.db.sql("""delete from `tabCommunication` where communication_type='Comment' and reference_doctype=%s and reference_name=%s""", ("Customer", name)) + # add comments comment = frappe.get_doc("Customer", "_Test Customer 1").add_comment("Comment", "Test Comment for Rename") + # rename frappe.rename_doc("Customer", "_Test Customer 1", "_Test Customer 1 Renamed") + # check if customer renamed self.assertTrue(frappe.db.exists("Customer", "_Test Customer 1 Renamed")) self.assertFalse(frappe.db.exists("Customer", "_Test Customer 1")) - # test that comment gets renamed + # test that comment gets linked to renamed doc self.assertEquals(frappe.db.get_value("Communication", { "communication_type": "Comment", "reference_doctype": "Customer", "reference_name": "_Test Customer 1 Renamed" }), comment.name) + # rename back to original frappe.rename_doc("Customer", "_Test Customer 1 Renamed", "_Test Customer 1") def test_freezed_customer(self): diff --git a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json index 2649c49c08c..9738f9c24d4 100644 --- a/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json +++ b/erpnext/stock/doctype/delivery_note_item/delivery_note_item.json @@ -1644,7 +1644,7 @@ "width": "120px" }, { - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, @@ -1894,7 +1894,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-05 23:26:03.390869", + "modified": "2017-04-19 11:53:42.656700", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note Item", diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 91d1791cc77..27b7be97c29 100755 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -1630,7 +1630,7 @@ "unique": 0 }, { - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, @@ -1979,7 +1979,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-05 23:27:10.785444", + "modified": "2017-04-19 11:54:00.260885", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json index 6d99dc45c24..2f7779c1327 100644 --- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json +++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json @@ -1040,7 +1040,7 @@ "unique": 0 }, { - "allow_on_submit": 1, + "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, @@ -1225,7 +1225,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-05 23:25:26.885642", + "modified": "2017-04-19 11:54:31.645381", "modified_by": "Administrator", "module": "Stock", "name": "Stock Entry Detail", From 019501e4a04d24ed74b92820e7e272d58ee0c5b3 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 19 Apr 2017 17:53:31 +0530 Subject: [PATCH 08/23] [fix] Balance Sheet, linking account to general ledger is not working --- erpnext/public/js/financial_statements.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/public/js/financial_statements.js b/erpnext/public/js/financial_statements.js index 711520530a9..66daf0dfb4b 100644 --- a/erpnext/public/js/financial_statements.js +++ b/erpnext/public/js/financial_statements.js @@ -26,13 +26,14 @@ erpnext.financial_statements = { }, "open_general_ledger": function(data) { if (!data.account) return; + var project = $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; }) frappe.route_options = { "account": data.account, "company": frappe.query_report_filters_by_name.company.get_value(), "from_date": data.from_date || data.year_start_date, "to_date": data.to_date || data.year_end_date, - "project": $.grep(frappe.query_report.filters, function(e){ return e.df.fieldname == 'project'; })[0].$input.val() + "project": (project && project.length > 0) ? project[0].$input.val() : "" }; frappe.set_route("query-report", "General Ledger"); }, From 695327a5136d8e4e10b0333900c3cfb6738c22ba Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 19 Apr 2017 13:39:31 +0530 Subject: [PATCH 09/23] Duplicate dependencies when project is duplicated - fix frappe/erpnext#8274 --- erpnext/patches.txt | 3 +- .../patches/v8_0/set_project_copied_from.py | 9 +++++ erpnext/projects/doctype/project/project.json | 40 ++++++++++++++++--- erpnext/projects/doctype/project/project.py | 26 ++++++++++++ erpnext/projects/doctype/task/task.py | 4 +- 5 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 erpnext/patches/v8_0/set_project_copied_from.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 522c4fca9cf..2cd3a2cbf83 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -386,4 +386,5 @@ execute:frappe.delete_doc('DocType', 'Purchase Common') erpnext.patches.v8_0.update_stock_qty_value_in_purchase_invoice erpnext.patches.v8_0.update_supplier_address_in_stock_entry erpnext.patches.v8_0.rename_is_sample_item_to_allow_zero_valuation_rate -erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices \ No newline at end of file +erpnext.patches.v8_0.set_null_to_serial_nos_for_disabled_sales_invoices +erpnext.patches.v8_0.set_project_copied_from \ No newline at end of file diff --git a/erpnext/patches/v8_0/set_project_copied_from.py b/erpnext/patches/v8_0/set_project_copied_from.py new file mode 100644 index 00000000000..be589014ac2 --- /dev/null +++ b/erpnext/patches/v8_0/set_project_copied_from.py @@ -0,0 +1,9 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.db.sql(''' + UPDATE `tabProject` + SET copied_from=name + WHERE copied_from is NULL + ''') \ No newline at end of file diff --git a/erpnext/projects/doctype/project/project.json b/erpnext/projects/doctype/project/project.json index e809328df97..32a3ffd3351 100644 --- a/erpnext/projects/doctype/project/project.json +++ b/erpnext/projects/doctype/project/project.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 1, "autoname": "field:project_name", @@ -553,6 +554,35 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "copied_from", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Copied From", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -1052,7 +1082,7 @@ "search_index": 0, "set_only_once": 0, "unique": 0 - }, + }, { "allow_on_submit": 0, "bold": 0, @@ -1174,19 +1204,19 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-puzzle-piece", "idx": 29, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 4, - "modified": "2017-02-17 17:24:04.146872", - "modified_by": "Administrator", + "modified": "2017-04-19 13:16:32.462005", + "modified_by": "faris@erpnext.com", "module": "Projects", "name": "Project", "owner": "Administrator", @@ -1261,4 +1291,4 @@ "timeline_field": "customer", "track_changes": 0, "track_seen": 1 -} +} \ No newline at end of file diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 37734f18760..40493e1ed61 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -205,6 +205,32 @@ class Project(Document): def on_update(self): self.load_tasks() self.sync_tasks() + self.update_dependencies_on_duplicated_project() + + def update_dependencies_on_duplicated_project(self): + if self.flags.dont_sync_tasks: return + if not self.copied_from: + self.copied_from = self.name + + if self.name != self.copied_from and self.get('__unsaved'): + # duplicated project + dependency_map = {} + for task in self.tasks: + name, depends_on_tasks = frappe.db.get_value( + 'Task', { "subject": task.title, "project": self.copied_from }, ['name', 'depends_on_tasks'] + ) + depends_on_tasks = [x for x in depends_on_tasks.split(',') if x] + dependency_map[task.title] = [ x['subject'] for x in frappe.get_list( + 'Task Depends On', {"parent": name}, ['subject'])] + + for key, value in dependency_map.iteritems(): + task_name = frappe.db.get_value('Task', {"subject": key, "project": self.name }) + task_doc = frappe.get_doc('Task', task_name) + + for dt in value: + dt_name = frappe.db.get_value('Task', {"subject": dt, "project": self.name }) + task_doc.append('depends_on', {"task": dt_name}) + task_doc.save() def get_timeline_data(doctype, name): '''Return timeline for attendance''' diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 44c81a67c51..43240b20e72 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -53,9 +53,9 @@ class Task(Document): frappe.throw(_("Progress % for a task cannot be more than 100.")) def update_depends_on(self): - depends_on_tasks = "" + depends_on_tasks = self.depends_on_tasks or "" for d in self.depends_on: - if d.task: + if d.task and not d.task in depends_on_tasks: depends_on_tasks += d.task + "," self.depends_on_tasks = depends_on_tasks From f4f774d1df69661ece93bc11a6cf7c54993b3678 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 19 Apr 2017 13:37:20 +0530 Subject: [PATCH 10/23] [fix] offline_pos_name is not defined during print from the POS --- .../accounts/print_format/point_of_sale/point_of_sale.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/print_format/point_of_sale/point_of_sale.json b/erpnext/accounts/print_format/point_of_sale/point_of_sale.json index 6b603c80e23..b413321bfd4 100644 --- a/erpnext/accounts/print_format/point_of_sale/point_of_sale.json +++ b/erpnext/accounts/print_format/point_of_sale/point_of_sale.json @@ -7,10 +7,10 @@ "docstatus": 0, "doctype": "Print Format", "font": "Default", - "html": "\n\n

    \n\t{{ company }}
    \n\t{{ __(\"POS No : \") }}{{offline_pos_name}}
    \n

    \n

    \n\t{{ __(\"Date\") }}: {{ dateutil.global_date_format(posting_date) }}
    \n

    \n\n
    \n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t{% for item in items %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endfor %}\n\t\n
    {{ __(\"Item\") }}{{ __(\"Qty\") }}{{ __(\"Amount\") }}
    \n\t\t\t\t{{ item.item_name }}\n\t\t\t{{ format_number(item.qty, null,precision(\"difference\")) }}
    @ {{ format_currency(item.rate, currency) }}
    {{ format_currency(item.amount, currency) }}
    \n\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n
    \n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t
    \n\t\t\t\t{{ row.description }}\n\t\t\t\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t
    \n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t
    \n\t\t\t\t{{ __(\"Grand Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t
    \n\t\t\t\t{{ __(\"Paid Amount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t
    \n\n\n
    \n

    {{ terms }}

    \n

    {{ __(\"Thank you, please visit again.\") }}

    ", + "html": "\n\n

    \n\t{{ company }}
    \n\t{{ __(\"POS No : \") }} {{ offline_pos_name }}
    \n

    \n

    \n\t{{ __(\"Date\") }}: {{ dateutil.global_date_format(posting_date) }}
    \n

    \n\n
    \n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\t{% for item in items %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endfor %}\n\t\n
    {{ __(\"Item\") }}{{ __(\"Qty\") }}{{ __(\"Amount\") }}
    \n\t\t\t\t{{ item.item_name }}\n\t\t\t{{ format_number(item.qty, null,precision(\"difference\")) }}
    @ {{ format_currency(item.rate, currency) }}
    {{ format_currency(item.amount, currency) }}
    \n\n\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% for row in taxes %}\n\t\t{% if not row.included_in_print_rate %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t{% endfor %}\n\t\t{% if discount_amount %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t{% endif %}\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n
    \n\t\t\t\t{{ __(\"Net Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(total, currency) }}\n\t\t\t
    \n\t\t\t\t{{ row.description }}\n\t\t\t\n\t\t\t\t{{ format_currency(row.tax_amount, currency) }}\n\t\t\t
    \n\t\t\t\t{{ __(\"Discount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(discount_amount, currency) }}\n\t\t\t
    \n\t\t\t\t{{ __(\"Grand Total\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(grand_total, currency) }}\n\t\t\t
    \n\t\t\t\t{{ __(\"Paid Amount\") }}\n\t\t\t\n\t\t\t\t{{ format_currency(paid_amount, currency) }}\n\t\t\t
    \n\n\n
    \n

    {{ terms }}

    \n

    {{ __(\"Thank you, please visit again.\") }}

    ", "idx": 0, "line_breaks": 0, - "modified": "2017-04-17 12:12:00.153763", + "modified": "2017-04-19 13:28:05.129504", "modified_by": "Administrator", "module": "Accounts", "name": "Point of Sale", From 0633df587216ad2416345fd2f12078dd6277300b Mon Sep 17 00:00:00 2001 From: Kanchan Chauhan Date: Wed, 19 Apr 2017 13:04:53 +0530 Subject: [PATCH 11/23] Item variant searchable in website products --- erpnext/templates/pages/product_search.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/templates/pages/product_search.py b/erpnext/templates/pages/product_search.py index c0c39cf8de8..8766db3dfa6 100644 --- a/erpnext/templates/pages/product_search.py +++ b/erpnext/templates/pages/product_search.py @@ -20,10 +20,9 @@ def get_product_list(search=None, start=0, limit=12): query = """select name, item_name, item_code, route, website_image, thumbnail, item_group, description, web_long_description as website_description from `tabItem` - where show_in_website = 1 + where (show_in_website = 1 or show_variant_in_website = 1) and disabled=0 - and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %(today)s) - and (variant_of is null or variant_of = '')""" + and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %(today)s)""" # search term condition if search: From ba41242f1fcf16d8a614b8cbcf5932429fa4627f Mon Sep 17 00:00:00 2001 From: mbauskar Date: Wed, 19 Apr 2017 12:35:51 +0530 Subject: [PATCH 12/23] [fixes] fixed the pricing rule issue https://github.com/frappe/erpnext/issues/8493 --- erpnext/public/js/controllers/transaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index a583f7d05b3..ce3efc939c7 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -275,7 +275,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ doctype: me.frm.doc.doctype, name: me.frm.doc.name, project: item.project || me.frm.doc.project, - qty: item.qty, + qty: item.qty || 1, stock_qty: item.stock_qty, conversion_factor: item.conversion_factor } From 2e6f12b85082b47c65ed035b0ee42f7077c8d50a Mon Sep 17 00:00:00 2001 From: Julian Robbins Date: Tue, 18 Apr 2017 16:54:43 +0100 Subject: [PATCH 13/23] Update purchase-details.md --- erpnext/docs/user/manual/en/stock/item/purchase-details.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/docs/user/manual/en/stock/item/purchase-details.md b/erpnext/docs/user/manual/en/stock/item/purchase-details.md index 5749178448b..47983dfc625 100644 --- a/erpnext/docs/user/manual/en/stock/item/purchase-details.md +++ b/erpnext/docs/user/manual/en/stock/item/purchase-details.md @@ -1,4 +1,4 @@ -# purchase details +# Purchase Details # How Do I Track Warranty Status? From 2de3bf7a0f9550d6a1f17268e6592dad6bfd5eac Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 18 Apr 2017 20:11:41 +0530 Subject: [PATCH 14/23] Fixed indexes on sales and purchase transactions --- .../purchase_invoice_item.json | 5 +++-- .../doctype/purchase_order/purchase_order.json | 11 +++++++---- .../purchase_order_item/purchase_order_item.json | 10 ++++++---- .../doctype/quotation_item/quotation_item.json | 9 +++++---- .../selling/doctype/sales_order/sales_order.json | 14 +++++++------- .../doctype/sales_order_item/sales_order_item.json | 6 +++--- .../stock/doctype/delivery_note/delivery_note.json | 12 ++++++------ .../doctype/purchase_receipt/purchase_receipt.json | 4 ++-- .../purchase_receipt_item.json | 5 +++-- 9 files changed, 42 insertions(+), 34 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index bf370c86845..8d89828aad7 100755 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -757,6 +757,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, + "precision": "9", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, @@ -1508,7 +1509,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -1939,7 +1940,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-17 13:44:17.460674", + "modified": "2017-04-18 18:51:33.829468", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice Item", diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.json b/erpnext/buying/doctype/purchase_order/purchase_order.json index e776b3ea981..ecce1184d6d 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.json +++ b/erpnext/buying/doctype/purchase_order/purchase_order.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 1, "allow_rename": 0, "autoname": "naming_series:", @@ -341,7 +342,7 @@ "remember_last_selected_value": 1, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -1207,6 +1208,8 @@ "hidden": 0, "ignore_user_permissions": 0, "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, "in_list_view": 0, "in_standard_filter": 0, "label": "Link to material requests", @@ -3185,18 +3188,18 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "icon": "fa fa-file-text", "idx": 105, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 1, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-28 18:20:15.650815", + "modified": "2017-04-18 18:49:49.535066", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order", @@ -3294,4 +3297,4 @@ "title_field": "title", "track_changes": 0, "track_seen": 0 -} +} \ No newline at end of file diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 12d0da85d77..0037745817b 100755 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -1,5 +1,6 @@ { "allow_copy": 0, + "allow_guest_to_view": 0, "allow_import": 0, "allow_rename": 0, "autoname": "hash", @@ -98,7 +99,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -156,7 +157,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -799,6 +800,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, + "precision": "9", "print_hide": 1, "print_hide_if_no_value": 0, "print_width": "100px", @@ -1647,17 +1649,17 @@ "unique": 0 } ], + "has_web_view": 0, "hide_heading": 0, "hide_toolbar": 0, "idx": 1, "image_view": 0, "in_create": 0, - "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-02-17 16:44:55.434162", + "modified": "2017-04-18 18:49:08.604055", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", diff --git a/erpnext/selling/doctype/quotation_item/quotation_item.json b/erpnext/selling/doctype/quotation_item/quotation_item.json index cccef9c0437..3a7342738ae 100644 --- a/erpnext/selling/doctype/quotation_item/quotation_item.json +++ b/erpnext/selling/doctype/quotation_item/quotation_item.json @@ -128,7 +128,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "150px" @@ -813,6 +813,7 @@ "oldfieldtype": "Currency", "options": "currency", "permlevel": 0, + "precision": "9", "print_hide": 0, "print_hide_if_no_value": 0, "print_width": "100px", @@ -1483,7 +1484,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -1515,7 +1516,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "150px" @@ -1532,7 +1533,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2017-03-30 19:35:44.119169", + "modified": "2017-04-18 18:47:26.869235", "modified_by": "Administrator", "module": "Selling", "name": "Quotation Item", diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 950150fd367..7621f4c1e3c 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -313,7 +313,7 @@ "remember_last_selected_value": 1, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "150px" @@ -377,7 +377,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "160px" @@ -791,7 +791,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -821,7 +821,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -2321,7 +2321,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -2896,7 +2896,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "150px" @@ -3516,7 +3516,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-04-10 12:13:03.136885", + "modified": "2017-04-18 20:02:54.895559", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index 479f04e33f2..10096d0ae44 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -1397,7 +1397,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -1429,7 +1429,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -1871,7 +1871,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2017-03-30 16:18:49.367870", + "modified": "2017-04-18 18:43:47.150922", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.json b/erpnext/stock/doctype/delivery_note/delivery_note.json index 9d3bbf48f69..782996b4e63 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.json +++ b/erpnext/stock/doctype/delivery_note/delivery_note.json @@ -282,7 +282,7 @@ "remember_last_selected_value": 1, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "150px" @@ -853,7 +853,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -883,7 +883,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -2514,7 +2514,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -2908,7 +2908,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -3288,7 +3288,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-04-10 12:03:29.645642", + "modified": "2017-04-18 18:41:53.065755", "modified_by": "Administrator", "module": "Stock", "name": "Delivery Note", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json index 3877028378d..9cd512a1b6f 100755 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.json @@ -352,7 +352,7 @@ "remember_last_selected_value": 1, "report_hide": 0, "reqd": 1, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0, "width": "150px" @@ -2846,7 +2846,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-04-10 12:02:07.434102", + "modified": "2017-04-18 18:51:10.457027", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt", diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 91d1791cc77..758541096e2 100755 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -806,6 +806,7 @@ "length": 0, "no_copy": 0, "permlevel": 0, + "precision": "9", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -1804,7 +1805,7 @@ "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, - "search_index": 1, + "search_index": 0, "set_only_once": 0, "unique": 0 }, @@ -1979,7 +1980,7 @@ "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2017-04-05 23:27:10.785444", + "modified": "2017-04-18 18:50:40.551474", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From 8691e0777b47de160bd06832f3178bab80b0b6eb Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 19 Apr 2017 20:57:21 +0530 Subject: [PATCH 15/23] Update purchase_invoice_item.json --- .../doctype/purchase_invoice_item/purchase_invoice_item.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json index 8d89828aad7..213bad844ef 100755 --- a/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json +++ b/erpnext/accounts/doctype/purchase_invoice_item/purchase_invoice_item.json @@ -757,7 +757,6 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, - "precision": "9", "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 1, @@ -1954,4 +1953,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} From eef55185fc7e8876ec0f9d70845657e2e41d6b0b Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Wed, 19 Apr 2017 20:57:54 +0530 Subject: [PATCH 16/23] Update purchase_receipt_item.json --- .../doctype/purchase_receipt_item/purchase_receipt_item.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json index 758541096e2..028e2f59a16 100755 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -806,7 +806,6 @@ "length": 0, "no_copy": 0, "permlevel": 0, - "precision": "9", "print_hide": 0, "print_hide_if_no_value": 0, "read_only": 0, @@ -1994,4 +1993,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} From 61f4a8e7577bac65724af1c6a8ec420719b93ad0 Mon Sep 17 00:00:00 2001 From: CH Date: Tue, 18 Apr 2017 12:35:50 +0200 Subject: [PATCH 17/23] Make the address type translatable in the Address_HTML field --- erpnext/public/js/templates/address_list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/templates/address_list.html b/erpnext/public/js/templates/address_list.html index f9a317f1737..02b44b83d6d 100644 --- a/erpnext/public/js/templates/address_list.html +++ b/erpnext/public/js/templates/address_list.html @@ -2,7 +2,7 @@
    {% for(var i=0, l=addr_list.length; i - {%= i+1 %}. {%= addr_list[i].address_type!="Other" ? addr_list[i].address_type : addr_list[i].address_title %} + {%= i+1 %}. {%= addr_list[i].address_type!="Other" ? __(addr_list[i].address_type) : addr_list[i].address_title %} {% if(addr_list[i].is_primary_address) { %} ({%= __("Primary") %}){% } %} {% if(addr_list[i].is_shipping_address) { %} From 287fe81329106b4ae777c0a554f21ba28e334620 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 10 Apr 2017 19:15:57 +0530 Subject: [PATCH 18/23] [minor] calculate price list rate based on items uom --- .../doctype/pricing_rule/pricing_rule.py | 4 ++-- erpnext/controllers/accounts_controller.py | 5 ++++- erpnext/controllers/selling_controller.py | 6 +++--- erpnext/controllers/taxes_and_totals.py | 1 + .../public/js/controllers/taxes_and_totals.js | 2 +- erpnext/public/js/controllers/transaction.js | 17 ++++++++++++----- erpnext/stock/get_item_details.py | 16 ++++++++++------ 7 files changed, 33 insertions(+), 18 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 93685dbbaf9..3f8018f7a9a 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -143,7 +143,7 @@ def get_pricing_rule_for_item(args): }) if args.ignore_pricing_rule or not args.item_code: - if frappe.db.exists(args.doctype, args.name) and args.get("pricing_rule"): + if frappe.db.exists(args.doctype, args.name) or args.get("pricing_rule"): item_details = remove_pricing_rule(args, item_details) return item_details @@ -178,7 +178,7 @@ def get_pricing_rule_for_item(args): item_details.margin_rate_or_amount = pricing_rule.margin_rate_or_amount if pricing_rule.price_or_discount == "Price": item_details.update({ - "price_list_rate": pricing_rule.price/flt(args.conversion_rate) \ + "price_list_rate": (pricing_rule.price/flt(args.conversion_rate)) * args.conversion_factor or 1.0 \ if args.conversion_rate else 0.0, "discount_percentage": 0.0 }) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index ecbf59da1b5..bcdfe5f52b1 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -186,7 +186,6 @@ class AccountsController(TransactionBase): ret = get_item_details(args) - for fieldname, value in ret.items(): if item.meta.get_field(fieldname) and value is not None: if (item.get(fieldname) is None or fieldname in force_item_fields): @@ -200,6 +199,10 @@ class AccountsController(TransactionBase): if stock_qty != len(item.get('serial_no').split('\n')): item.set(fieldname, value) + elif fieldname in ["conversion_factor", "price_list_rate"]: + if for_validate and not item.get(fieldname): + item.set(fieldname, value) + if ret.get("pricing_rule"): # if user changed the discount percentage then set user's discount percentage ? item.set("discount_percentage", ret.get("discount_percentage")) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index af51f70147f..91f57f514c5 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -41,7 +41,7 @@ class SellingController(StockController): # set contact and address details for customer, if they are not mentioned self.set_missing_lead_customer_details() - self.set_price_list_and_item_details() + self.set_price_list_and_item_details(for_validate) def set_missing_lead_customer_details(self): if getattr(self, "customer", None): @@ -60,9 +60,9 @@ class SellingController(StockController): posting_date=self.get('transaction_date') or self.get('posting_date'), company=self.company)) - def set_price_list_and_item_details(self): + def set_price_list_and_item_details(self, for_validate): self.set_price_list_currency("Selling") - self.set_missing_item_details() + self.set_missing_item_details(for_validate=for_validate) def apply_shipping_rule(self): if self.shipping_rule: diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 0355c269d0b..362d07515bc 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -60,6 +60,7 @@ class calculate_taxes_and_totals(object): if item.doctype in ['Quotation Item', 'Sales Order Item', 'Delivery Note Item', 'Sales Invoice Item']: item.total_margin = self.calculate_margin(item) + item.rate = flt(item.total_margin * (1.0 - (item.discount_percentage / 100.0)), item.precision("rate"))\ if item.total_margin > 0 else item.rate diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 6f55a4411a3..08dd224fb14 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -7,7 +7,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ if(item.margin_type == "Percentage"){ item.total_margin = flt(item.price_list_rate) + flt(item.price_list_rate) * ( flt(item.margin_rate_or_amount) / 100); - }else{ + } else { item.total_margin = flt(item.price_list_rate) + flt(item.margin_rate_or_amount); } diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index ce3efc939c7..d84a4fcbd9b 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -284,6 +284,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ callback: function(r) { if(!r.exc) { me.frm.script_manager.trigger("price_list_rate", cdt, cdn); + me.toggle_conversion_factor(item); } } }); @@ -568,9 +569,17 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ frappe.model.round_floats_in(item, ["qty", "conversion_factor"]); item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item)); refresh_field("stock_qty", item.name, item.parentfield); + this.toggle_conversion_factor(item); + this.apply_price_list(); } }, + toggle_conversion_factor: function(item) { + // toggle read only property for conversion factor field if the uom and stock uom are same + this.frm.fields_dict.items.grid.toggle_enable("conversion_factor", + (item.uom != item.stock_uom)? true: false) + }, + qty: function(doc, cdt, cdn) { this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); this.conversion_factor(doc, cdt, cdn); @@ -766,6 +775,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "name": me.frm.doc.name, "is_return": cint(me.frm.doc.is_return), "update_stock": in_list(['Sales Invoice', 'Purchase Invoice'], me.frm.doc.doctype) ? cint(me.frm.doc.update_stock) : 0, + "conversion_factor": me.frm.doc.conversion_factor }; }, @@ -785,7 +795,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ "pricing_rule": d.pricing_rule, "warehouse": d.warehouse, "serial_no": d.serial_no, - "conversion_factor": d.conversion_factor + "conversion_factor": d.conversion_factor || 1.0 }); // if doctype is Quotation Item / Sales Order Iten then add Margin Type and rate in item_list @@ -812,16 +822,13 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ for(var i=0, l=children.length; i Date: Mon, 10 Apr 2017 19:16:07 +0530 Subject: [PATCH 19/23] [minor] fixes in test cases and added the test case for multiple uom in selling --- .../doctype/sales_invoice/test_records.json | 10 +++++----- .../sales_invoice/test_sales_invoice.py | 19 +++++++++++++++++++ erpnext/controllers/selling_controller.py | 4 ++-- .../doctype/quotation/test_records.json | 6 +++--- erpnext/stock/doctype/item/test_records.json | 10 ++++++++++ 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_records.json b/erpnext/accounts/doctype/sales_invoice/test_records.json index 732c4465a80..0b7b76d1b3b 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_records.json +++ b/erpnext/accounts/doctype/sales_invoice/test_records.json @@ -147,9 +147,9 @@ "price_list_rate": 50, "qty": 10, "rate": 50, - "uom": "_Test UOM", + "uom": "_Test UOM 1", "conversion_factor": 1, - "stock_uom": "_Test UOM" + "stock_uom": "_Test UOM 1" }, { "cost_center": "_Test Cost Center - _TC", @@ -273,9 +273,9 @@ "parentfield": "items", "price_list_rate": 62.5, "qty": 10, - "uom": "_Test UOM", - "conversion_factor": 1, - "stock_uom": "_Test UOM" + "uom": "_Test UOM 1", + "conversion_factor": 1, + "stock_uom": "_Test UOM 1" }, { diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 305b689e15b..0ada8478a10 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -1043,6 +1043,25 @@ class TestSalesInvoice(unittest.TestCase): #check outstanding after advance cancellation self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) + def test_multiple_uom_in_selling(self): + si = frappe.copy_doc(test_records[1]) + + si.items[0].uom = "_Test UOM 1" + si.items[0].conversion_factor = None + si.items[0].price_list_rate = None + si.save() + + expected_values = { + "keys": ["price_list_rate", "stock_uom", "uom", "conversion_factor", "rate", "amount", + "base_price_list_rate", "base_rate", "base_amount"], + "_Test Item": [1000, "_Test UOM", "_Test UOM 1", 10.0, 1000, 1000, 1000, 1000, 1000] + } + + # check if the conversion_factor and price_list_rate is calculated according to uom + for d in si.get("items"): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.get(k), expected_values[d.item_code][i]) + def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") args = frappe._dict(args) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 91f57f514c5..1cd705b8c47 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -41,7 +41,7 @@ class SellingController(StockController): # set contact and address details for customer, if they are not mentioned self.set_missing_lead_customer_details() - self.set_price_list_and_item_details(for_validate) + self.set_price_list_and_item_details(for_validate=for_validate) def set_missing_lead_customer_details(self): if getattr(self, "customer", None): @@ -60,7 +60,7 @@ class SellingController(StockController): posting_date=self.get('transaction_date') or self.get('posting_date'), company=self.company)) - def set_price_list_and_item_details(self, for_validate): + def set_price_list_and_item_details(self, for_validate=False): self.set_price_list_currency("Selling") self.set_missing_item_details(for_validate=for_validate) diff --git a/erpnext/selling/doctype/quotation/test_records.json b/erpnext/selling/doctype/quotation/test_records.json index 8a37dbb7d72..5637fb906c1 100644 --- a/erpnext/selling/doctype/quotation/test_records.json +++ b/erpnext/selling/doctype/quotation/test_records.json @@ -23,9 +23,9 @@ "parentfield": "items", "qty": 10.0, "rate": 100.0, - "uom": "_Test UOM", - "stock_uom": "_Test UOM", - "conversion_factor": 1.0 + "uom": "_Test UOM 1", + "stock_uom": "_Test UOM 1", + "conversion_factor": 1.0 } ], "quotation_to": "Customer", diff --git a/erpnext/stock/doctype/item/test_records.json b/erpnext/stock/doctype/item/test_records.json index aad8ed0fc27..2a1520e8ca3 100644 --- a/erpnext/stock/doctype/item/test_records.json +++ b/erpnext/stock/doctype/item/test_records.json @@ -24,6 +24,16 @@ "warehouse_reorder_qty": 20 } ], + "uoms": [ + { + "uom": "_Test UOM", + "conversion_factor": 1.0 + }, + { + "uom": "_Test UOM 1", + "conversion_factor": 10.0 + } + ], "stock_uom": "_Test UOM", "show_in_website": 1, "website_warehouse": "_Test Warehouse - _TC" From 8f3cc81302d9bde8aa4cbb8ff1c51074b0979fc2 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Tue, 18 Apr 2017 10:20:40 +0530 Subject: [PATCH 20/23] [minor] minor fixes in pricing_rule and set_missing_value --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 4 +++- erpnext/controllers/accounts_controller.py | 5 ++--- erpnext/public/js/controllers/transaction.js | 3 +-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index 3f8018f7a9a..5af0d9f1be6 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -23,6 +23,8 @@ class PricingRule(Document): self.validate_price_or_discount() self.validate_max_discount() + if not self.margin_type: self.margin_rate_or_amount = 0.0 + def validate_mandatory(self): for field in ["apply_on", "applicable_for"]: tocheck = frappe.scrub(self.get(field) or "") @@ -143,7 +145,7 @@ def get_pricing_rule_for_item(args): }) if args.ignore_pricing_rule or not args.item_code: - if frappe.db.exists(args.doctype, args.name) or args.get("pricing_rule"): + if args.get("pricing_rule"): item_details = remove_pricing_rule(args, item_details) return item_details diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index bcdfe5f52b1..742e59b4d69 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -199,9 +199,8 @@ class AccountsController(TransactionBase): if stock_qty != len(item.get('serial_no').split('\n')): item.set(fieldname, value) - elif fieldname in ["conversion_factor", "price_list_rate"]: - if for_validate and not item.get(fieldname): - item.set(fieldname, value) + elif fieldname == "conversion_factor" and not item.get("conversion_factor"): + item.set(fieldname, value) if ret.get("pricing_rule"): # if user changed the discount percentage then set user's discount percentage ? diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index d84a4fcbd9b..eec789a4ea8 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -570,7 +570,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item)); refresh_field("stock_qty", item.name, item.parentfield); this.toggle_conversion_factor(item); - this.apply_price_list(); + this.apply_price_list(item, true); } }, @@ -581,7 +581,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }, qty: function(doc, cdt, cdn) { - this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); this.conversion_factor(doc, cdt, cdn); }, From e42fb32f6fe9ee27fb47ee7b2442be922822906e Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 20 Apr 2017 08:45:09 +0530 Subject: [PATCH 21/23] Fixed allow_zero_valuation_rate patch --- .../v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py b/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py index 744cfed9983..e517df5fdb9 100644 --- a/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py +++ b/erpnext/patches/v8_0/rename_is_sample_item_to_allow_zero_valuation_rate.py @@ -9,4 +9,5 @@ def execute(): for doctype in doc_list: frappe.reload_doctype(doctype) - rename_field(doctype, "is_sample_item", "allow_zero_valuation_rate") \ No newline at end of file + if "is_sample_item" in frappe.db.get_table_columns(doctype): + rename_field(doctype, "is_sample_item", "allow_zero_valuation_rate") \ No newline at end of file From 825e053e6693cca9f5002a7baab13198a598a758 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 20 Apr 2017 08:50:27 +0530 Subject: [PATCH 22/23] Fixed project_copied_from patch --- erpnext/patches/v8_0/set_project_copied_from.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/erpnext/patches/v8_0/set_project_copied_from.py b/erpnext/patches/v8_0/set_project_copied_from.py index be589014ac2..d4287978cf8 100644 --- a/erpnext/patches/v8_0/set_project_copied_from.py +++ b/erpnext/patches/v8_0/set_project_copied_from.py @@ -2,8 +2,10 @@ from __future__ import unicode_literals import frappe def execute(): - frappe.db.sql(''' - UPDATE `tabProject` - SET copied_from=name - WHERE copied_from is NULL - ''') \ No newline at end of file + frappe.reload_doctype("Project") + + frappe.db.sql(''' + UPDATE `tabProject` + SET copied_from=name + WHERE copied_from is NULL + ''') \ No newline at end of file From 9afb53203fdec58f0229f3364b87dc93409d0928 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 20 Apr 2017 09:21:44 +0600 Subject: [PATCH 23/23] bumped to version 8.0.14 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 3f6504d7956..c06ccca3aa5 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals import frappe -__version__ = '8.0.13' +__version__ = '8.0.14' def get_default_company(user=None): '''Get default company for user'''