From 3fc3305251162108183e5348b961c0ebee31700f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 11 Apr 2017 16:00:48 +0530 Subject: [PATCH 01/16] 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 8a019807572447a6aa0f431d50137a32d43b1580 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 18 Apr 2017 13:11:10 +0530 Subject: [PATCH 02/16] 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 03/16] 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 019501e4a04d24ed74b92820e7e272d58ee0c5b3 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Wed, 19 Apr 2017 17:53:31 +0530 Subject: [PATCH 04/16] [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 05/16] 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 06/16] [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 07/16] 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 08/16] [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 09/16] 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 10/16] 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 11/16] 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 12/16] 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 13/16] 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 14/16] [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 15/16] [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 16/16] [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); },