From aa7ce883edb4afbff5273a2d930f71b8fc57d81e Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 6 May 2019 15:59:34 +0530 Subject: [PATCH 1/4] fix: Dont include disabled items in cache --- erpnext/portal/product_configurator/item_variants_cache.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/erpnext/portal/product_configurator/item_variants_cache.py b/erpnext/portal/product_configurator/item_variants_cache.py index 0e0b8c95e1d..f33c8d605b4 100644 --- a/erpnext/portal/product_configurator/item_variants_cache.py +++ b/erpnext/portal/product_configurator/item_variants_cache.py @@ -66,15 +66,14 @@ class ItemVariantsCacheManager: as_list=1 ) - disabled_items = [i.name for i in frappe.db.get_all('Item', {'disabled': 1})] + disabled_items = set([i.name for i in frappe.db.get_all('Item', {'disabled': 1})]) attribute_value_item_map = frappe._dict({}) item_attribute_value_map = frappe._dict({}) + item_variants_data = [r for r in item_variants_data if r[0] not in disabled_items] for row in item_variants_data: item_code, attribute, attribute_value = row - if item_code in disabled_items: - continue # (attr, value) => [item1, item2] attribute_value_item_map.setdefault((attribute, attribute_value), []).append(item_code) # item => {attr1: value1, attr2: value2} From ff9177a6ceb4930c5e4bba86a2c89b827d242c3e Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Mon, 6 May 2019 15:59:51 +0530 Subject: [PATCH 2/4] fix: Handle attribute filter when no items found --- erpnext/portal/product_configurator/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/portal/product_configurator/utils.py b/erpnext/portal/product_configurator/utils.py index 405a6d8c31c..15d5e9fa0d3 100644 --- a/erpnext/portal/product_configurator/utils.py +++ b/erpnext/portal/product_configurator/utils.py @@ -257,7 +257,8 @@ def get_items_with_selected_attributes(item_code, selected_attributes): items = [] for attribute, value in selected_attributes.items(): - items.append(set(attribute_value_item_map[(attribute, value)])) + filtered_items = attribute_value_item_map.get((attribute, value), []) + items.append(set(filtered_items)) return set.intersection(*items) From a90fe810b3ac46e485302ddcda2bc5eb50e3c63a Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 7 May 2019 12:37:38 +0530 Subject: [PATCH 3/4] fix(UX): Cancel tasks if project is cancelled (#17497) --- erpnext/projects/doctype/project/project.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/erpnext/projects/doctype/project/project.js b/erpnext/projects/doctype/project/project.js index 6de6454a0e8..528c7cd0c71 100644 --- a/erpnext/projects/doctype/project/project.js +++ b/erpnext/projects/doctype/project/project.js @@ -109,6 +109,18 @@ frappe.ui.form.on("Project", { } }); }, + + status: function(frm) { + if (frm.doc.status === 'Cancelled') { + frappe.confirm(__('Set tasks in this project as cancelled?'), () => { + frm.doc.tasks = frm.doc.tasks.map(task => { + task.status = 'Cancelled'; + return task; + }); + frm.refresh_field('tasks'); + }); + } + } }); frappe.ui.form.on("Project Task", { From 23fecc0dbbabb1c07a836ae7e676edf4b26434eb Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Tue, 7 May 2019 12:38:24 +0530 Subject: [PATCH 4/4] perf: Task import with Project (#17496) When tasks are imported with their Project set, import slows down as number of tasks increase. This is largely due to `load_tasks` being called in Project which is only required when Form loads. So, we can skip it during import. Also, converted some get_doc calls to get_cached_doc. --- erpnext/projects/doctype/project/project.py | 3 +++ erpnext/projects/doctype/task/task.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 39222ac6910..61db3e118a8 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -35,6 +35,9 @@ class Project(Document): def load_tasks(self): """Load `tasks` from the database""" + if frappe.flags.in_import: + return + self.tasks = [] for task in self.get_tasks(): task_map = { diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 84ee7151989..fa9a5a59af5 100755 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -105,7 +105,7 @@ class Task(NestedSet): def update_project(self): if self.project and not self.flags.from_project: - frappe.get_doc("Project", self.project).update_project() + frappe.get_cached_doc("Project", self.project).update_project() def check_recursion(self): if self.flags.ignore_recursion_check: return @@ -150,7 +150,7 @@ class Task(NestedSet): def populate_depends_on(self): if self.parent_task: - parent = frappe.get_doc('Task', self.parent_task) + parent = frappe.get_cached_doc('Task', self.parent_task) if not self.name in [row.task for row in parent.depends_on]: parent.append("depends_on", { "doctype": "Task Depends On",