From ba2133cba2e5a26b15900623706b7eb4c29257c1 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 19 Oct 2015 19:19:50 +0530 Subject: [PATCH 01/17] [minor][fix] set default fiscal year for holiday list calendar view --- erpnext/hr/doctype/holiday_list/holiday_list_calendar.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/hr/doctype/holiday_list/holiday_list_calendar.js b/erpnext/hr/doctype/holiday_list/holiday_list_calendar.js index d7e9adc5fc3..dee64de5259 100644 --- a/erpnext/hr/doctype/holiday_list/holiday_list_calendar.js +++ b/erpnext/hr/doctype/holiday_list/holiday_list_calendar.js @@ -14,7 +14,8 @@ frappe.views.calendar["Holiday List"] = { "fieldtype": "Link", "fieldname": "fiscal_year", "options": "Fiscal Year", - "label": __("Fiscal Year") + "label": __("Fiscal Year"), + "default": frappe.defaults.get_user_default("fiscal_year") } ], get_events_method: "erpnext.hr.doctype.holiday_list.holiday_list.get_events" From 25956d62820710362a34ede196bb70fa53bdf7aa Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 08:12:07 +0530 Subject: [PATCH 02/17] [fix] Item thumbnail --- erpnext/stock/doctype/item/item.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index faae960343e..65a4b91d36a 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -86,11 +86,16 @@ class Item(WebsiteGenerator): self.thumbnail = None if self.website_image and not self.thumbnail: - file_doc = frappe.get_doc("File", { - "file_url": self.website_image, - "attached_to_doctype": "Item", - "attached_to_name": self.name - }) + file_doc = None + + try: + file_doc = frappe.get_doc("File", { + "file_url": self.website_image, + "attached_to_doctype": "Item", + "attached_to_name": self.name + }) + except frappe.DoesNotExistError: + pass # for CSV import if not file_doc: From 3395e7a2e4e039c4d8dba97d819434891f211b66 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 08:48:30 +0530 Subject: [PATCH 03/17] [fix] Daily digest date format --- erpnext/setup/doctype/email_digest/templates/default.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/email_digest/templates/default.html b/erpnext/setup/doctype/email_digest/templates/default.html index cf35e460d32..3aad2025290 100644 --- a/erpnext/setup/doctype/email_digest/templates/default.html +++ b/erpnext/setup/doctype/email_digest/templates/default.html @@ -12,7 +12,7 @@

{{ title }}

-

{% if frequency == "Daily "%} +

{% if frequency == "Daily" %} {{ frappe.format_date(future_from_date) }} {% else %} {{ frappe.format_date(future_from_date) }} - {{ frappe.format_date(future_to_date) }} From 12af47918dd2d80dda739864cfc9f30415487b2a Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 12:02:28 +0530 Subject: [PATCH 04/17] [fix] rename tool --- erpnext/utilities/doctype/rename_tool/rename_tool.js | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/utilities/doctype/rename_tool/rename_tool.js b/erpnext/utilities/doctype/rename_tool/rename_tool.js index 7a914566a3a..2632ddd9d85 100644 --- a/erpnext/utilities/doctype/rename_tool/rename_tool.js +++ b/erpnext/utilities/doctype/rename_tool/rename_tool.js @@ -8,7 +8,6 @@ frappe.ui.form.on("Rename Tool", { method: "erpnext.utilities.doctype.rename_tool.rename_tool.get_doctypes", callback: function(r) { frm.set_df_property("select_doctype", "options", r.message); - frm.cscript.setup_upload(); } }); }, From 17dc249841bd9be9693c8397a53609b61b6d1e8d Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 12:11:26 +0530 Subject: [PATCH 05/17] [fix] rollback if exception in bulk rename --- erpnext/utilities/doctype/rename_tool/rename_tool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/utilities/doctype/rename_tool/rename_tool.py b/erpnext/utilities/doctype/rename_tool/rename_tool.py index 3f6f3e30c94..18cfebe5219 100644 --- a/erpnext/utilities/doctype/rename_tool/rename_tool.py +++ b/erpnext/utilities/doctype/rename_tool/rename_tool.py @@ -51,5 +51,6 @@ def upload(select_doctype=None, rows=None): rename_log.append("" + \ _("Failed: ") + row[0] + " -> " + row[1] + "") rename_log.append("" + repr(e) + "") + frappe.db.rollback() return rename_log From c35b35abca2b3c45fdc9c6f3510de5c417e07078 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 20 Oct 2015 10:56:53 +0530 Subject: [PATCH 06/17] [fix] Set higher precision for exchange rate field --- erpnext/accounts/doctype/gl_entry/gl_entry.json | 8 +++++--- .../journal_entry_account/journal_entry_account.json | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index 936d3465eb1..5f07df976f6 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -162,6 +162,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, + "precision": "", "print_hide": 0, "read_only": 0, "report_hide": 0, @@ -186,6 +187,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, + "precision": "", "print_hide": 0, "read_only": 0, "report_hide": 0, @@ -415,7 +417,7 @@ "ignore_user_permissions": 0, "in_filter": 1, "in_list_view": 0, - "label": "Is Opening", + "label": "Is Opening", "no_copy": 0, "oldfieldname": "is_opening", "oldfieldtype": "Select", @@ -439,7 +441,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Is Advance", + "label": "Is Advance", "no_copy": 0, "oldfieldname": "is_advance", "oldfieldtype": "Select", @@ -511,7 +513,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-10-02 07:38:51.117114", + "modified": "2015-10-20 12:10:59.771050", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", diff --git a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json index ebd48429f15..f2c1575464e 100644 --- a/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json +++ b/erpnext/accounts/doctype/journal_entry_account/journal_entry_account.json @@ -276,7 +276,7 @@ "label": "Exchange Rate", "no_copy": 0, "permlevel": 0, - "precision": "", + "precision": "6", "print_hide": 1, "read_only": 0, "report_hide": 0, @@ -345,6 +345,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, + "precision": "", "print_hide": 1, "read_only": 1, "report_hide": 0, @@ -412,6 +413,7 @@ "oldfieldtype": "Currency", "options": "Company:company:default_currency", "permlevel": 0, + "precision": "", "print_hide": 1, "read_only": 1, "report_hide": 0, @@ -451,7 +453,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Reference Type", + "label": "Reference Type", "no_copy": 0, "options": "\nSales Invoice\nPurchase Invoice\nJournal Entry\nSales Order\nPurchase Order\nExpense Claim", "permlevel": 0, @@ -517,7 +519,7 @@ "ignore_user_permissions": 0, "in_filter": 0, "in_list_view": 0, - "label": "Is Advance", + "label": "Is Advance", "no_copy": 1, "oldfieldname": "is_advance", "oldfieldtype": "Select", @@ -563,7 +565,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-10-02 07:38:54.406370", + "modified": "2015-10-20 12:10:22.203395", "modified_by": "Administrator", "module": "Accounts", "name": "Journal Entry Account", From 4d20f3029bfaba24dd2bb764c826191c2d7a7d89 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 20 Oct 2015 12:18:19 +0530 Subject: [PATCH 07/17] [fix] Set fieldtype of description field as Text in Landed Cost Item --- erpnext/stock/doctype/landed_cost_item/landed_cost_item.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json index 3dbe794117e..52ea1939f3e 100644 --- a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json +++ b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json @@ -35,7 +35,7 @@ "bold": 0, "collapsible": 0, "fieldname": "description", - "fieldtype": "Data", + "fieldtype": "Text", "hidden": 0, "ignore_user_permissions": 0, "in_filter": 0, @@ -216,7 +216,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-10-02 07:38:54.612684", + "modified": "2015-10-20 12:16:35.511559", "modified_by": "Administrator", "module": "Stock", "name": "Landed Cost Item", From 75bd0f7cfe45ffc5bd6bb8e9b418b57389d959f8 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 19 Oct 2015 16:50:22 +0530 Subject: [PATCH 08/17] Fixed issue in Item Variant for Numeric Attributes --- erpnext/controllers/item_variant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 38536cff32a..8cacfc9eba9 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -51,7 +51,7 @@ def validate_item_variant_attributes(item, args): frappe.throw(_("Increment for Attribute {0} cannot be 0").format(attribute)) is_in_range = from_range <= flt(value) <= to_range - precision = len(cstr(increment).split(".")[-1].rstrip("0")) + precision = len(cstr(value).split(".")[-1].rstrip("0")) #avoid precision error by rounding the remainder remainder = flt((flt(value) - from_range) % increment, precision) From e65ac00f365785df44b54092d44b722d8e13ac43 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 19 Oct 2015 19:13:03 +0530 Subject: [PATCH 09/17] Considered greater precision of value and increment --- erpnext/controllers/item_variant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 8cacfc9eba9..c80a5f305be 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -51,7 +51,7 @@ def validate_item_variant_attributes(item, args): frappe.throw(_("Increment for Attribute {0} cannot be 0").format(attribute)) is_in_range = from_range <= flt(value) <= to_range - precision = len(cstr(value).split(".")[-1].rstrip("0")) + precision = max(len(cstr(value).split(".")[-1].rstrip("0")), len(cstr(increment).split(".")[-1].rstrip("0"))) #avoid precision error by rounding the remainder remainder = flt((flt(value) - from_range) % increment, precision) From a4fad72a651950caa4a50d63fc7fdd99ce3efb48 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Tue, 20 Oct 2015 11:58:07 +0530 Subject: [PATCH 10/17] Considered greater precision of value and increment (better code) --- erpnext/controllers/item_variant.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index c80a5f305be..0e1d1268327 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -51,7 +51,7 @@ def validate_item_variant_attributes(item, args): frappe.throw(_("Increment for Attribute {0} cannot be 0").format(attribute)) is_in_range = from_range <= flt(value) <= to_range - precision = max(len(cstr(value).split(".")[-1].rstrip("0")), len(cstr(increment).split(".")[-1].rstrip("0"))) + precision = max(len(cstr(v).split(".")[-1].rstrip("0")) for v in (value, increment)) #avoid precision error by rounding the remainder remainder = flt((flt(value) - from_range) % increment, precision) From 17c633d00f3501fb815de7461acf6061f626c80b Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 14:26:44 +0530 Subject: [PATCH 11/17] [fix] Set fieldtype of description field as Text Editor in Landed Cost Item --- .../landed_cost_item/landed_cost_item.json | 410 +++++++++--------- 1 file changed, 205 insertions(+), 205 deletions(-) diff --git a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json index 52ea1939f3e..24a57f6b8e0 100644 --- a/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json +++ b/erpnext/stock/doctype/landed_cost_item/landed_cost_item.json @@ -1,227 +1,227 @@ { - "allow_copy": 0, - "allow_import": 0, - "allow_rename": 0, - "creation": "2013-02-22 01:28:02", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", + "allow_copy": 0, + "allow_import": 0, + "allow_rename": 0, + "creation": "2013-02-22 01:28:02", + "custom": 0, + "docstatus": 0, + "doctype": "DocType", "fields": [ { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "item_code", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Item Code", - "no_copy": 0, - "options": "Item", - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "item_code", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Item Code", + "no_copy": 0, + "options": "Item", + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "100px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "description", - "fieldtype": "Text", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Description", - "no_copy": 0, - "oldfieldname": "description", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_width": "300px", - "read_only": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "description", + "fieldtype": "Text Editor", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Description", + "no_copy": 0, + "oldfieldname": "description", + "oldfieldtype": "Data", + "permlevel": 0, + "print_hide": 0, + "print_width": "300px", + "read_only": 1, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0, "width": "120px" - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "purchase_receipt", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Purchase Receipt", - "no_copy": 1, - "options": "Purchase Receipt", - "permlevel": 0, - "print_hide": 1, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "purchase_receipt", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Purchase Receipt", + "no_copy": 1, + "options": "Purchase Receipt", + "permlevel": 0, + "print_hide": 1, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "col_break2", - "fieldtype": "Column Break", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "col_break2", + "fieldtype": "Column Break", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "qty", - "fieldtype": "Float", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Qty", - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "qty", + "fieldtype": "Float", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Qty", + "no_copy": 0, + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "rate", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Rate", - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "rate", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Rate", + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "amount", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Amount", - "no_copy": 0, - "oldfieldname": "amount", - "oldfieldtype": "Currency", - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "amount", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Amount", + "no_copy": 0, + "oldfieldname": "amount", + "oldfieldtype": "Currency", + "options": "Company:company:default_currency", + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "applicable_charges", - "fieldtype": "Currency", - "hidden": 0, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 1, - "label": "Applicable Charges", - "no_copy": 0, - "options": "Company:company:default_currency", - "permlevel": 0, - "print_hide": 0, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "applicable_charges", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 1, + "label": "Applicable Charges", + "no_copy": 0, + "options": "Company:company:default_currency", + "permlevel": 0, + "print_hide": 0, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 - }, + }, { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "fieldname": "purchase_receipt_item", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "in_filter": 0, - "in_list_view": 0, - "label": "Purchase Receipt Item", - "no_copy": 1, - "permlevel": 0, - "print_hide": 1, - "read_only": 1, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "fieldname": "purchase_receipt_item", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Purchase Receipt Item", + "no_copy": 1, + "permlevel": 0, + "print_hide": 1, + "read_only": 1, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, "unique": 0 } - ], - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 1, - "in_create": 0, - "in_dialog": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 1, - "modified": "2015-10-20 12:16:35.511559", - "modified_by": "Administrator", - "module": "Stock", - "name": "Landed Cost Item", - "owner": "wasim@webnotestech.com", - "permissions": [], - "read_only": 0, + ], + "hide_heading": 0, + "hide_toolbar": 0, + "idx": 1, + "in_create": 0, + "in_dialog": 0, + "is_submittable": 0, + "issingle": 0, + "istable": 1, + "modified": "2015-10-20 12:16:35.511560", + "modified_by": "Administrator", + "module": "Stock", + "name": "Landed Cost Item", + "owner": "wasim@webnotestech.com", + "permissions": [], + "read_only": 0, "read_only_onload": 0 -} \ No newline at end of file +} From 7b2b0cd73cf91e6c4180e854a3f0d06f1789f630 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Thu, 15 Oct 2015 18:07:51 +0530 Subject: [PATCH 12/17] [fix] Item Re-order if Bin does not exists and fixed Stock Projected Qty report to show per Warehouse Re-order level --- .../doctype/stock_entry/test_stock_entry.py | 10 +- erpnext/stock/reorder_item.py | 45 +++++---- .../stock_projected_qty.py | 96 ++++++++++--------- 3 files changed, 86 insertions(+), 65 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 252deaad36a..8a1f8c7f697 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -566,14 +566,14 @@ class TestStockEntry(unittest.TestCase): stock_entry = frappe.get_doc(make_stock_entry(production_order.name, "Manufacture", 1)) stock_entry.insert() self.assertTrue("_Test Variant Item-S" in [d.item_code for d in stock_entry.items]) - + def test_same_serial_nos_in_repack_or_manufacture_entries(self): s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC") serial_nos = s1.get("items")[0].serial_no - - s2 = make_stock_entry(item_code="_Test Serialized Item With Series", source="_Test Warehouse - _TC", + + s2 = make_stock_entry(item_code="_Test Serialized Item With Series", source="_Test Warehouse - _TC", qty=2, basic_rate=100, purpose="Repack", serial_no=serial_nos, do_not_save=True) - + s2.append("items", { "item_code": "_Test Serialized Item", "t_warehouse": "_Test Warehouse - _TC", @@ -584,7 +584,7 @@ class TestStockEntry(unittest.TestCase): "cost_center": "_Test Cost Center - _TC", "serial_no": serial_nos }) - + s2.submit() s2.cancel() diff --git a/erpnext/stock/reorder_item.py b/erpnext/stock/reorder_item.py index 51dd8c156cc..d4b0a204039 100644 --- a/erpnext/stock/reorder_item.py +++ b/erpnext/stock/reorder_item.py @@ -15,21 +15,37 @@ def reorder_item(): def _reorder_item(): material_requests = {"Purchase": {}, "Transfer": {}} - - item_warehouse_projected_qty = get_item_warehouse_projected_qty() - - warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse`""")) + warehouse_company = frappe._dict(frappe.db.sql("""select name, company from `tabWarehouse` + where disabled=0""")) default_company = (frappe.defaults.get_defaults().get("company") or frappe.db.sql("""select name from tabCompany limit 1""")[0][0]) + items_to_consider = frappe.db.sql_list("""select name from `tabItem` item + where is_stock_item=1 and has_variants=0 + and (is_purchase_item=1 or is_sub_contracted_item=1) + and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %(today)s) + and ((re_order_level is not null and re_order_level > 0) + or exists (select name from `tabItem Reorder` ir where ir.parent=item.name) + or (variant_of is not null and variant_of != '' + and exists (select name from `tabItem Reorder` ir where ir.parent=item.variant_of)) + )""", + {"today": nowdate()}) + + if not items_to_consider: + return + + item_warehouse_projected_qty = get_item_warehouse_projected_qty(items_to_consider) + def add_to_material_request(item_code, warehouse, reorder_level, reorder_qty, material_request_type): - if warehouse not in item_warehouse_projected_qty[item_code]: - # likely a disabled warehouse or a warehouse where BIN does not exist + if warehouse not in warehouse_company: + # a disabled warehouse return reorder_level = flt(reorder_level) reorder_qty = flt(reorder_qty) - projected_qty = item_warehouse_projected_qty[item_code][warehouse] + + # projected_qty will be 0 if Bin does not exist + projected_qty = flt(item_warehouse_projected_qty.get(item_code, {}).get(warehouse)) if reorder_level and projected_qty < reorder_level: deficiency = reorder_level - projected_qty @@ -44,7 +60,7 @@ def _reorder_item(): "reorder_qty": reorder_qty }) - for item_code in item_warehouse_projected_qty: + for item_code in items_to_consider: item = frappe.get_doc("Item", item_code) if item.variant_of and not item.get("reorder_levels"): @@ -62,18 +78,13 @@ def _reorder_item(): if material_requests: return create_material_request(material_requests) -def get_item_warehouse_projected_qty(): +def get_item_warehouse_projected_qty(items_to_consider): item_warehouse_projected_qty = {} for item_code, warehouse, projected_qty in frappe.db.sql("""select item_code, warehouse, projected_qty - from tabBin where ifnull(item_code, '') != '' and ifnull(warehouse, '') != '' - and exists (select name from `tabItem` - where `tabItem`.name = `tabBin`.item_code and - is_stock_item=1 and (is_purchase_item=1 or is_sub_contracted_item=1) and - (ifnull(end_of_life, '0000-00-00')='0000-00-00' or end_of_life > %s)) - and exists (select name from `tabWarehouse` - where `tabWarehouse`.name = `tabBin`.warehouse - and ifnull(disabled, 0)=0)""", nowdate()): + from tabBin where item_code in ({0}) + and (warehouse != "" and warehouse is not null)"""\ + .format(", ".join(["%s"] * len(items_to_consider))), items_to_consider): item_warehouse_projected_qty.setdefault(item_code, {})[warehouse] = flt(projected_qty) diff --git a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py index d7dcb231992..348cca2fd38 100644 --- a/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py +++ b/erpnext/stock/report/stock_projected_qty/stock_projected_qty.py @@ -6,48 +6,58 @@ import frappe from frappe import _ def execute(filters=None): - columns = get_columns() - - data = frappe.db.sql("""select - item.name, item.item_name, description, item_group, brand, warehouse, item.stock_uom, - actual_qty, planned_qty, indented_qty, ordered_qty, reserved_qty, - projected_qty, item.re_order_level, item.re_order_qty, - (item.re_order_level - projected_qty) as shortage_qty - from `tabBin` bin, - (select name, company from tabWarehouse - {warehouse_conditions}) wh, - (select name, item_name, description, stock_uom, item_group, - brand, re_order_level, re_order_qty - from `tabItem` {item_conditions}) item - where item_code = item.name and warehouse = wh.name - order by item.name, wh.name"""\ - .format(item_conditions=get_item_conditions(filters), - warehouse_conditions=get_warehouse_conditions(filters)), filters) - - return columns, data - + filters = frappe._dict(filters or {}) + return get_columns(), get_data(filters) + def get_columns(): - return [_("Item Code") + ":Link/Item:140", _("Item Name") + "::100", _("Description") + "::200", - _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100", _("Warehouse") + ":Link/Warehouse:120", - _("UOM") + ":Link/UOM:100", _("Actual Qty") + ":Float:100", _("Planned Qty") + ":Float:100", - _("Requested Qty") + ":Float:110", _("Ordered Qty") + ":Float:100", _("Reserved Qty") + ":Float:100", - _("Projected Qty") + ":Float:100", _("Reorder Level") + ":Float:100", _("Reorder Qty") + ":Float:100", + return [_("Item Code") + ":Link/Item:140", _("Item Name") + "::100", _("Description") + "::200", + _("Item Group") + ":Link/Item Group:100", _("Brand") + ":Link/Brand:100", _("Warehouse") + ":Link/Warehouse:120", + _("UOM") + ":Link/UOM:100", _("Actual Qty") + ":Float:100", _("Planned Qty") + ":Float:100", + _("Requested Qty") + ":Float:110", _("Ordered Qty") + ":Float:100", _("Reserved Qty") + ":Float:100", + _("Projected Qty") + ":Float:100", _("Reorder Level") + ":Float:100", _("Reorder Qty") + ":Float:100", _("Shortage Qty") + ":Float:100"] - -def get_item_conditions(filters): - conditions = [] - if filters.get("item_code"): - conditions.append("name=%(item_code)s") - if filters.get("brand"): - conditions.append("brand=%(brand)s") - - return "where {}".format(" and ".join(conditions)) if conditions else "" - -def get_warehouse_conditions(filters): - conditions = [] - if filters.get("company"): - conditions.append("company=%(company)s") - if filters.get("warehouse"): - conditions.append("name=%(warehouse)s") - - return "where {}".format(" and ".join(conditions)) if conditions else "" \ No newline at end of file + +def get_data(filters): + item_map = {} + warehouse_company = {} + data = [] + + for bin in get_bin_list(filters): + item = item_map.setdefault(bin.item_code, frappe.get_doc("Item", bin.item_code)) + company = warehouse_company.setdefault(bin.warehouse, frappe.db.get_value("Warehouse", bin.warehouse, "company")) + + if filters.brand and filters.brand != item.brand: + continue + + elif filters.company and filters.company != company: + continue + + re_order_level = re_order_qty = 0 + + if bin.warehouse==item.default_warehouse: + re_order_level = item.re_order_level or 0 + re_order_qty = item.re_order_qty or 0 + + for d in item.get("reorder_levels"): + if d.warehouse == bin.warehouse: + re_order_level = d.warehouse_reorder_level + re_order_qty = d.warehouse_reorder_qty + + data.append([item.name, item.item_name, item.description, item.item_group, item.brand, bin.warehouse, + item.stock_uom, bin.actual_qty, bin.planned_qty, bin.indented_qty, bin.ordered_qty, bin.reserved_qty, + bin.projected_qty, re_order_level, re_order_qty, re_order_level - bin.projected_qty]) + + return data + +def get_bin_list(filters): + bin_filters = frappe._dict() + if filters.item_code: + bin_filters.item_code = filters.item_code + if filters.warehouse: + bin_filters.warehouse = filters.warehouse + + bin_list = frappe.get_all("Bin", fields=["item_code", "warehouse", + "actual_qty", "planned_qty", "indented_qty", "ordered_qty", "reserved_qty", "projected_qty"], + filters=bin_filters, order_by="item_code, warehouse") + + return bin_list From 73286dd9f52dab5338352570050510b18d5e07d7 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 14:53:13 +0530 Subject: [PATCH 13/17] [minor] define email field for Issue --- erpnext/support/doctype/issue/issue.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/support/doctype/issue/issue.js b/erpnext/support/doctype/issue/issue.js index f92e4e69f94..28617cb6940 100644 --- a/erpnext/support/doctype/issue/issue.js +++ b/erpnext/support/doctype/issue/issue.js @@ -1,4 +1,8 @@ frappe.ui.form.on("Issue", { + "onload": function(frm) { + frm.email_field = "raised_by"; + }, + "refresh": function(frm) { if(frm.doc.status==="Open") { frm.add_custom_button("Close", function() { From c0f88e4caf1fd64e818218fc79e69215450a01cf Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Tue, 20 Oct 2015 12:15:14 +0530 Subject: [PATCH 14/17] Default value fot allow production order in Item master changed to 1 --- erpnext/stock/doctype/item/item.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index e761653508c..b36e34c0226 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -1647,7 +1647,7 @@ "allow_on_submit": 0, "bold": 0, "collapsible": 0, - "default": "", + "default": "1", "depends_on": "", "description": "", "fieldname": "is_pro_applicable", @@ -2113,7 +2113,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2015-10-19 03:04:49.445770", + "modified": "2015-10-20 12:14:43.315827", "modified_by": "Administrator", "module": "Stock", "name": "Item", From d4357e80d783c2bf23645c1294f96fa995bb3776 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Tue, 20 Oct 2015 16:02:31 +0530 Subject: [PATCH 15/17] Fixed Test Cases --- .../selling/doctype/sales_order/test_sales_order.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index ba5f025cfe0..4fa88d42b08 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -240,9 +240,9 @@ class TestSalesOrder(unittest.TestCase): from erpnext.stock.doctype.item.test_item import make_item from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle - make_item("_Test Service Product Bundle", {"is_stock_item": 0, "is_sales_item": 1}) - make_item("_Test Service Product Bundle Item 1", {"is_stock_item": 0, "is_sales_item": 1}) - make_item("_Test Service Product Bundle Item 2", {"is_stock_item": 0, "is_sales_item": 1}) + make_item("_Test Service Product Bundle", {"is_stock_item": 0, "is_pro_applicable": 0, "is_sales_item": 1}) + make_item("_Test Service Product Bundle Item 1", {"is_stock_item": 0, "is_pro_applicable": 0, "is_sales_item": 1}) + make_item("_Test Service Product Bundle Item 2", {"is_stock_item": 0, "is_pro_applicable": 0, "is_sales_item": 1}) make_product_bundle("_Test Service Product Bundle", ["_Test Service Product Bundle Item 1", "_Test Service Product Bundle Item 2"]) @@ -256,9 +256,9 @@ class TestSalesOrder(unittest.TestCase): from erpnext.stock.doctype.item.test_item import make_item from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle - make_item("_Test Mix Product Bundle", {"is_stock_item": 0, "is_sales_item": 1}) + make_item("_Test Mix Product Bundle", {"is_stock_item": 0, "is_pro_applicable": 0, "is_sales_item": 1}) make_item("_Test Mix Product Bundle Item 1", {"is_stock_item": 1, "is_sales_item": 1}) - make_item("_Test Mix Product Bundle Item 2", {"is_stock_item": 0, "is_sales_item": 1}) + make_item("_Test Mix Product Bundle Item 2", {"is_stock_item": 0, "is_pro_applicable": 0, "is_sales_item": 1}) make_product_bundle("_Test Mix Product Bundle", ["_Test Mix Product Bundle Item 1", "_Test Mix Product Bundle Item 2"]) @@ -267,7 +267,7 @@ class TestSalesOrder(unittest.TestCase): def test_auto_insert_price(self): from erpnext.stock.doctype.item.test_item import make_item - make_item("_Test Item for Auto Price List", {"is_stock_item": 0, "is_sales_item": 1}) + make_item("_Test Item for Auto Price List", {"is_stock_item": 0, "is_pro_applicable": 0, "is_sales_item": 1}) frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 1) item_price = frappe.db.get_value("Item Price", {"price_list": "_Test Price List", From 7c0eadb45138121ed9effb390cef8f74238b39d4 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 17:30:02 +0530 Subject: [PATCH 16/17] [fix] Patch template item to be shown in website, show variant's description and price on change of attribute --- erpnext/controllers/item_variant.py | 5 +- erpnext/patches.txt | 3 + erpnext/patches/v6_5/__init__.py | 1 + .../v6_5/show_in_website_for_template_item.py | 15 ++++ erpnext/shopping_cart/cart.py | 2 + erpnext/shopping_cart/product.py | 50 ++++++++----- erpnext/stock/doctype/item/item.py | 72 ++++++++++++++++--- erpnext/templates/generators/item.html | 15 ++-- erpnext/templates/includes/product_page.js | 11 ++- 9 files changed, 136 insertions(+), 38 deletions(-) create mode 100644 erpnext/patches/v6_5/__init__.py create mode 100644 erpnext/patches/v6_5/show_in_website_for_template_item.py diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 0e1d1268327..5890b5d1e9c 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -60,7 +60,7 @@ def validate_item_variant_attributes(item, args): if not (is_in_range and is_incremental): frappe.throw(_("Value for Attribute {0} must be within the range of {1} to {2} in the increments of {3}")\ .format(attribute, from_range, to_range, increment), InvalidItemAttributeValueError) - + elif value not in attribute_values.get(attribute, []): frappe.throw(_("Value {0} for Attribute {1} does not exist in the list of valid Item Attribute Values").format( value, attribute)) @@ -125,12 +125,11 @@ def copy_attributes_to_variant(item, variant): from frappe.model import no_value_fields for field in item.meta.fields: if field.fieldtype not in no_value_fields and (not field.no_copy)\ - and field.fieldname not in ("item_code", "item_name"): + and field.fieldname not in ("item_code", "item_name", "show_in_website"): if variant.get(field.fieldname) != item.get(field.fieldname): variant.set(field.fieldname, item.get(field.fieldname)) variant.variant_of = item.name variant.has_variants = 0 - variant.show_in_website = 0 if variant.attributes: variant.description += "\n" for d in variant.attributes: diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 6045e773844..6c299d81e83 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -224,5 +224,8 @@ erpnext.patches.v6_4.email_digest_update execute:frappe.delete_doc_if_exists("DocType", "Applicable Territory") execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Price List") execute:frappe.delete_doc_if_exists("DocType", "Shopping Cart Taxes and Charges Master") + erpnext.patches.v6_4.set_user_in_contact erpnext.patches.v6_4.make_image_thumbnail + +erpnext.patches.v6_5.show_in_website_for_template_item diff --git a/erpnext/patches/v6_5/__init__.py b/erpnext/patches/v6_5/__init__.py new file mode 100644 index 00000000000..baffc488252 --- /dev/null +++ b/erpnext/patches/v6_5/__init__.py @@ -0,0 +1 @@ +from __future__ import unicode_literals diff --git a/erpnext/patches/v6_5/show_in_website_for_template_item.py b/erpnext/patches/v6_5/show_in_website_for_template_item.py new file mode 100644 index 00000000000..48040ee949a --- /dev/null +++ b/erpnext/patches/v6_5/show_in_website_for_template_item.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals +import frappe +import frappe.website.render + +def execute(): + for item_code in frappe.db.sql_list("""select distinct variant_of from `tabItem` + where variant_of is not null and variant_of !='' and show_in_website=1"""): + + item = frappe.get_doc("Item", item_code) + item.db_set("show_in_website", 1, update_modified=False) + + item.get_route() + item.db_set("page_name", item.page_name, update_modified=False) + + frappe.website.render.clear_cache() diff --git a/erpnext/shopping_cart/cart.py b/erpnext/shopping_cart/cart.py index 22f920faa69..68bfd950c53 100644 --- a/erpnext/shopping_cart/cart.py +++ b/erpnext/shopping_cart/cart.py @@ -292,6 +292,7 @@ def get_customer(user=None): "customer_group": get_shopping_cart_settings().default_customer_group, "territory": get_root_of("Territory") }) + customer.ignore_mandatory = True customer.insert(ignore_permissions=True) contact = frappe.new_doc("Contact") @@ -300,6 +301,7 @@ def get_customer(user=None): "first_name": fullname, "email_id": user }) + contact.ignore_mandatory = True contact.insert(ignore_permissions=True) return customer diff --git a/erpnext/shopping_cart/product.py b/erpnext/shopping_cart/product.py index d7795d2f976..6a6cb693496 100644 --- a/erpnext/shopping_cart/product.py +++ b/erpnext/shopping_cart/product.py @@ -14,25 +14,11 @@ def get_product_info(item_code): if not is_cart_enabled(): return {} - cart_quotation = _get_cart_quotation() - - price_list = cart_quotation.selling_price_list - - warehouse = frappe.db.get_value("Item", item_code, "website_warehouse") - if warehouse: - in_stock = frappe.db.sql("""select actual_qty from tabBin where - item_code=%s and warehouse=%s""", (item_code, warehouse)) - if in_stock: - in_stock = in_stock[0][0] > 0 and 1 or 0 - else: - in_stock = -1 - - price = price_list and frappe.db.sql("""select price_list_rate, currency from - `tabItem Price` where item_code=%s and price_list=%s""", - (item_code, price_list), as_dict=1) or [] - - price = price and price[0] or None qty = 0 + cart_quotation = _get_cart_quotation() + template_item_code = frappe.db.get_value("Item", item_code, "variant_of") + in_stock = get_qty_in_stock(item_code, template_item_code) + price = get_price(item_code, template_item_code, cart_quotation.selling_price_list) if price: price["formatted_price"] = fmt_money(price["price_list_rate"], currency=price["currency"]) @@ -52,3 +38,31 @@ def get_product_info(item_code): "uom": frappe.db.get_value("Item", item_code, "stock_uom"), "qty": qty } + +def get_qty_in_stock(item_code, template_item_code): + warehouse = frappe.db.get_value("Item", item_code, "website_warehouse") + if not warehouse and template_item_code and template_item_code != item_code: + warehouse = frappe.db.get_value("Item", template_item_code, "website_warehouse") + + if warehouse: + in_stock = frappe.db.sql("""select actual_qty from tabBin where + item_code=%s and warehouse=%s""", (item_code, warehouse)) + if in_stock: + in_stock = in_stock[0][0] > 0 and 1 or 0 + + else: + in_stock = -1 + + return in_stock + +def get_price(item_code, template_item_code, price_list): + if price_list: + price = frappe.get_all("Item Price", fields=["price_list_rate", "currency"], + filters={"price_list": price_list, "item_code": item_code}) + + if not price: + price = frappe.get_all("Item Price", fields=["price_list_rate", "currency"], + filters={"price_list": price_list, "item_code": template_item_code}) + + if price: + return price[0] diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 65a4b91d36a..99f64171cc1 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals import frappe import json +import urllib from frappe import msgprint, _ from frappe.utils import cstr, flt, cint, getdate, now_datetime, formatdate from frappe.website.website_generator import WebsiteGenerator @@ -79,6 +80,7 @@ class Item(WebsiteGenerator): self.validate_name_with_item_group() self.update_item_price() self.update_variants() + self.update_template_item() def make_thumbnail(self): """Make a thumbnail of `website_image`""" @@ -113,18 +115,59 @@ class Item(WebsiteGenerator): self.thumbnail = file_doc.thumbnail_url def get_context(self, context): + if self.variant_of: + # redirect to template page! + template_item = frappe.get_doc("Item", self.variant_of) + frappe.flags.redirect_location = template_item.get_route() + "?variant=" + urllib.quote(self.name) + raise frappe.Redirect + context.parent_groups = get_parent_item_groups(self.item_group) + \ [{"name": self.name}] - if self.slideshow: - context.update(get_slideshow(self)) + self.set_variant_context(context) + + self.set_attribute_context(context) + + context.parents = self.get_parents(context) + + return context + + def set_variant_context(self, context): + if self.has_variants: + context.no_cache = True + + # load variants + # also used in set_attribute_context + context.variants = frappe.get_all("Item", + filters={"variant_of": self.name, "show_in_website": 1}, order_by="name asc") + + variant = frappe.form_dict.variant + if not variant: + # the case when the item is opened for the first time from its list + variant = context.variants[0] + + context.variant = frappe.get_doc("Item", variant) + + for fieldname in ("website_image", "web_long_description", "description", + "website_specifications"): + if context.variant.get(fieldname): + value = context.variant.get(fieldname) + if isinstance(value, list): + value = [d.as_dict() for d in value] + + context[fieldname] = value + + if self.slideshow: + if context.variant and context.variant.slideshow: + context.update(get_slideshow(context.variant)) + else: + context.update(get_slideshow(self)) + + def set_attribute_context(self, context): if self.has_variants: attribute_values_available = {} context.attribute_values = {} - - # load variants - context.variants = frappe.get_all("Item", - filters={"variant_of": self.name, "show_in_website": 1}) + context.selected_attributes = {} # load attributes for v in context.variants: @@ -136,6 +179,9 @@ class Item(WebsiteGenerator): if attr.attribute_value not in values: values.append(attr.attribute_value) + if v.name==context.variant.name: + context.selected_attributes[attr.attribute] = attr.attribute_value + # filter attributes, order based on attribute table for attr in self.attributes: values = context.attribute_values.setdefault(attr.attribute, []) @@ -149,10 +195,6 @@ class Item(WebsiteGenerator): context.variant_info = json.dumps(context.variants) - context.parents = self.get_parents(context) - - return context - def check_warehouse_is_set_for_stock_item(self): if self.is_stock_item==1 and not self.default_warehouse and frappe.get_all("Warehouse"): frappe.msgprint(_("Default Warehouse is mandatory for stock Item."), @@ -360,6 +402,16 @@ class Item(WebsiteGenerator): frappe.db.sql("""update `tabBOM Explosion Item` set description = %s where item_code = %s and docstatus < 2""",(self.description, self.name)) + def update_template_item(self): + """Set Show in Website for Template Item if True for its Variant""" + if self.variant_of and self.show_in_website: + template_item = frappe.get_doc("Item", self.variant_of) + + if not template_item.show_in_website: + template_item.show_in_website = 1 + template_item.flags.ignore_permissions = True + template_item.save() + def update_variants(self): if self.has_variants: updated = [] diff --git a/erpnext/templates/generators/item.html b/erpnext/templates/generators/item.html index f24b1a678b1..ccb992b804e 100644 --- a/erpnext/templates/generators/item.html +++ b/erpnext/templates/generators/item.html @@ -38,8 +38,11 @@ @@ -71,13 +74,13 @@ - {% if doc.get({"doctype":"Item Website Specification"}) -%} -

+ {% if website_specifications -%} +

{{ _("Specifications") }}

+ - {% for d in doc.get( - {"doctype":"Item Website Specification"}) -%} + {% for d in website_specifications -%} diff --git a/erpnext/templates/includes/product_page.js b/erpnext/templates/includes/product_page.js index 7468ffeff91..2345de46e39 100644 --- a/erpnext/templates/includes/product_page.js +++ b/erpnext/templates/includes/product_page.js @@ -9,7 +9,7 @@ frappe.ready(function() { type: "POST", method: "erpnext.shopping_cart.product.get_product_info", args: { - item_code: "{{ name }}" + item_code: get_item_code() }, callback: function(r) { $(".item-cart").toggleClass("hide", !!!r.message.price); @@ -63,6 +63,15 @@ frappe.ready(function() { }, }); }); + + $("[itemscope] .item-view-attribute select").on("change", function() { + var item_code = encodeURIComponent(get_item_code()); + if (window.location.search.indexOf(item_code)!==-1) { + return; + } + + frappe.load_via_ajax(window.location.pathname + "?variant=" + item_code); + }); }); var toggle_update_cart = function(qty) { From 3c3d69f905041e3b3c5a5d4e7c16bbfa30d773f0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Tue, 20 Oct 2015 18:23:37 +0600 Subject: [PATCH 17/17] bumped to version 6.5.2 --- erpnext/__version__.py | 2 +- erpnext/hooks.py | 2 +- setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/__version__.py b/erpnext/__version__.py index f4a63fa44e3..68def1b955c 100644 --- a/erpnext/__version__.py +++ b/erpnext/__version__.py @@ -1,2 +1,2 @@ from __future__ import unicode_literals -__version__ = '6.5.1' +__version__ = '6.5.2' diff --git a/erpnext/hooks.py b/erpnext/hooks.py index fed054cac67..defbfbc9b2b 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -29,7 +29,7 @@ blogs. """ app_icon = "icon-th" app_color = "#e74c3c" -app_version = "6.5.1" +app_version = "6.5.2" github_link = "https://github.com/frappe/erpnext" error_report_email = "support@erpnext.com" diff --git a/setup.py b/setup.py index 0241b700bdd..6af4e323b79 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -version = "6.5.1" +version = "6.5.2" with open("requirements.txt", "r") as f: install_requires = f.readlines()
{{ d.label }} {{ d.description }}