From ec60ebde6fed440ce31a5900325da0782aa9baf0 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 8 Jun 2015 12:48:11 -0400 Subject: [PATCH 1/7] [fix] Close assignment (ToDo) when Task status is changed to Closed --- erpnext/projects/doctype/task/task.py | 20 +++--- erpnext/projects/doctype/task/test_task.py | 75 +++++++++++++++------- 2 files changed, 65 insertions(+), 30 deletions(-) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index 456c40a97e..42717fd9e3 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -28,7 +28,11 @@ class Task(Document): def validate(self): self.validate_dates() - + + if self.status!=self.get_db_value("status") and self.status == "Closed": + from frappe.desk.form.assign_to import clear + clear(self.doctype, self.name) + def validate_dates(self): if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date): frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'")) @@ -41,17 +45,17 @@ class Task(Document): self.reschedule_dependent_tasks() self.update_percentage() self.update_project() - + def update_percentage(self): """update percent complete in project""" if self.project and not self.flags.from_project: project = frappe.get_doc("Project", self.project) project.run_method("update_percent_complete") - + def update_total_expense_claim(self): - self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim` + self.total_expense_claim = frappe.db.sql("""select sum(total_sanctioned_amount) from `tabExpense Claim` where project = %s and task = %s and approval_status = "Approved" and docstatus=1""",(self.project, self.name)) - + def update_time_and_costing(self): tl = frappe.db.sql("""select min(from_time) as start_date, max(to_time) as end_date, sum(billing_amount) as total_billing_amount, sum(costing_amount) as total_costing_amount, @@ -64,14 +68,14 @@ class Task(Document): self.actual_time= tl.time self.act_start_date= tl.start_date self.act_end_date= tl.end_date - + def update_project(self): if self.project and frappe.db.exists("Project", self.project): project = frappe.get_doc("Project", self.project) project.flags.dont_sync_tasks = True project.update_costing() project.save() - + def check_recursion(self): if self.flags.ignore_recursion_check: return check_list = [['task', 'parent'], ['parent', 'task']] @@ -88,7 +92,7 @@ class Task(Document): task_list.append(b[0]) if count == 15: break - + def reschedule_dependent_tasks(self): end_date = self.exp_end_date or self.act_end_date if end_date: diff --git a/erpnext/projects/doctype/task/test_task.py b/erpnext/projects/doctype/task/test_task.py index 8880763fa2..fced0a45ed 100644 --- a/erpnext/projects/doctype/task/test_task.py +++ b/erpnext/projects/doctype/task/test_task.py @@ -11,19 +11,19 @@ from erpnext.projects.doctype.task.task import CircularReferenceError class TestTask(unittest.TestCase): def test_circular_reference(self): - + task1 = frappe.new_doc('Task') task1.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 1", "exp_start_date": "2015-1-1", "exp_end_date": "2015-1-10" }) task1.save() - + task2 = frappe.new_doc('Task') task2.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 2", "exp_start_date": "2015-1-11", "exp_end_date": "2015-1-15", @@ -34,10 +34,10 @@ class TestTask(unittest.TestCase): ] }) task2.save() - + task3 = frappe.new_doc('Task') task3.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 2", "exp_start_date": "2015-1-11", "exp_end_date": "2015-1-15", @@ -53,13 +53,13 @@ class TestTask(unittest.TestCase): "task": task3.name }) self.assertRaises(CircularReferenceError, task1.save) - + task1.set("depends_on", []) task1.save() - + task4 = frappe.new_doc('Task') task4.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 1", "exp_start_date": "2015-1-1", "exp_end_date": "2015-1-15", @@ -74,20 +74,20 @@ class TestTask(unittest.TestCase): task3.append("depends_on", { "task": task4.name }) - + def test_reschedule_dependent_task(self): task1 = frappe.new_doc('Task') task1.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 1", "exp_start_date": "2015-1-1", "exp_end_date": "2015-1-10" }) task1.save() - + task2 = frappe.new_doc('Task') task2.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 2", "exp_start_date": "2015-1-11", "exp_end_date": "2015-1-15", @@ -98,10 +98,10 @@ class TestTask(unittest.TestCase): ] }) task2.save() - + task3 = frappe.new_doc('Task') task3.update({ - "status": "Open", + "status": "Open", "subject": "_Test Task 3", "exp_start_date": "2015-1-16", "exp_end_date": "2015-1-18", @@ -112,18 +112,18 @@ class TestTask(unittest.TestCase): ] }) task3.save() - + task1.update({ "exp_end_date": "2015-1-20" }) task1.save() - + self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21')) self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28')) - + time_log = frappe.new_doc('Time Log') time_log.update({ "from_time": "2015-1-1", @@ -131,18 +131,49 @@ class TestTask(unittest.TestCase): "task": task1.name }) time_log.submit() - + self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21')) self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28')) - + time_log.cancel() - + self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"), getdate('2015-1-21')) self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"), getdate('2015-1-25')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"), getdate('2015-1-26')) self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"), getdate('2015-1-28')) - \ No newline at end of file + + + def test_close_assignment(self): + task = frappe.new_doc("Task") + task.subject = "Test Close Assignment" + task.insert() + + def assign(): + from frappe.desk.form import assign_to + assign_to.add({ + "assign_to": "test@example.com", + "doctype": task.doctype, + "name": task.name, + "description": "Close this task" + }) + + def get_owner_and_status(): + return frappe.db.get_value("ToDo", filters={"reference_type": task.doctype, "reference_name": task.name, + "description": "Close this task"}, fieldname=("owner", "status"), as_dict=True) + + assign() + todo = get_owner_and_status() + self.assertEquals(todo.owner, "test@example.com") + self.assertEquals(todo.status, "Open") + + # assignment should be + task.load_from_db() + task.status = "Closed" + task.save() + todo = get_owner_and_status() + self.assertEquals(todo.owner, "test@example.com") + self.assertEquals(todo.status, "Closed") From b2f550ccb3edff5bf02b3bfb7e4f55cbfd3634b9 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 8 Jun 2015 17:56:22 +0530 Subject: [PATCH 2/7] Barcode added to Purchase Receipt --- erpnext/public/js/feature_setup.js | 3 ++- .../doctype/purchase_receipt/purchase_receipt.js | 15 +++++++++++++++ .../purchase_receipt_item.json | 15 ++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/erpnext/public/js/feature_setup.js b/erpnext/public/js/feature_setup.js index 5ab04ddfa2..664da664d3 100644 --- a/erpnext/public/js/feature_setup.js +++ b/erpnext/public/js/feature_setup.js @@ -81,7 +81,8 @@ erpnext.feature_setup.feature_dict = { 'Item': {'fields': ['barcode']}, 'Delivery Note': {'items': ['barcode']}, 'Sales Invoice': {'items': ['barcode']}, - 'Stock Entry': {'items': ['barcode']} + 'Stock Entry': {'items': ['barcode']}, + 'Purchase Receipt': {'items': ['barcode']} }, 'fs_item_group_in_details': { 'Delivery Note': {'items':['item_group']}, diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index fe41b4fb93..c85123c2ed 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -204,3 +204,18 @@ frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function(frm) { } frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes"); }); + +cur_frm.cscript.barcode = function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + if (d.barcode) { + frappe.call({ + method: "erpnext.stock.get_item_details.get_item_code", + args: {"barcode": d.barcode }, + callback: function(r) { + if (!r.exe){ + frappe.model.set_value(cdt, cdn, "item_code", r.message); + } + } + }); + } +} \ No newline at end of file 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 c48aa2c269..f53f50850e 100755 --- a/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json +++ b/erpnext/stock/doctype/purchase_receipt_item/purchase_receipt_item.json @@ -4,6 +4,19 @@ "docstatus": 0, "doctype": "DocType", "fields": [ + { + "fieldname": "barcode", + "fieldtype": "Data", + "label": "Barcode", + "permlevel": 0, + "precision": "" + }, + { + "fieldname": "section_break_2", + "fieldtype": "Section Break", + "permlevel": 0, + "precision": "" + }, { "fieldname": "item_code", "fieldtype": "Link", @@ -642,7 +655,7 @@ ], "idx": 1, "istable": 1, - "modified": "2015-06-02 14:19:13.528248", + "modified": "2015-06-08 08:21:18.024324", "modified_by": "Administrator", "module": "Stock", "name": "Purchase Receipt Item", From d015195617d906430de8cf00bb149b54d12fffe1 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Tue, 9 Jun 2015 15:21:50 +0530 Subject: [PATCH 3/7] fixes in barcode --- erpnext/public/js/controllers/transaction.js | 9 +++++++++ erpnext/selling/sales_common.js | 9 --------- .../doctype/purchase_receipt/purchase_receipt.js | 15 --------------- 3 files changed, 9 insertions(+), 24 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index e05245e7b0..ca0a6cb8d2 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -105,6 +105,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ } }, + barcode: function(doc, cdt, cdn) { + var d = locals[cdt][cdn]; + if(d.barcode=="" || d.barcode==null) { + // barcode cleared, remove item + d.item_code = ""; + } + this.item_code(doc, cdt, cdn); + }, + item_code: function(doc, cdt, cdn) { var me = this; var item = frappe.get_doc(cdt, cdn); diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 3ef85257f3..775eb4143f 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -124,15 +124,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ this.apply_pricing_rule(); }, - barcode: function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if(d.barcode=="" || d.barcode==null) { - // barcode cleared, remove item - d.item_code = ""; - } - this.item_code(doc, cdt, cdn); - }, - selling_price_list: function() { this.apply_price_list(); }, diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index c85123c2ed..fe41b4fb93 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -204,18 +204,3 @@ frappe.ui.form.on("Purchase Receipt", "is_subcontracted", function(frm) { } frm.toggle_reqd("supplier_warehouse", frm.doc.is_subcontracted==="Yes"); }); - -cur_frm.cscript.barcode = function(doc, cdt, cdn) { - var d = locals[cdt][cdn]; - if (d.barcode) { - frappe.call({ - method: "erpnext.stock.get_item_details.get_item_code", - args: {"barcode": d.barcode }, - callback: function(r) { - if (!r.exe){ - frappe.model.set_value(cdt, cdn, "item_code", r.message); - } - } - }); - } -} \ No newline at end of file From 82763f052f502d94a339ae588a8540b8c03b810d Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Mon, 8 Jun 2015 16:57:23 +0530 Subject: [PATCH 4/7] Status Indicators fixed in Material Request List --- .../stock/doctype/material_request/material_request.json | 4 ++-- .../doctype/material_request/material_request_list.js | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json index 894b9e1343..aec242f285 100644 --- a/erpnext/stock/doctype/material_request/material_request.json +++ b/erpnext/stock/doctype/material_request/material_request.json @@ -148,7 +148,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nStopped\nCancelled", + "options": "\nDraft\nSubmitted\nIssued\nOrdered\nTransfered\nStopped\nCancelled", "permlevel": 0, "print_hide": 1, "print_width": "100px", @@ -221,7 +221,7 @@ "icon": "icon-ticket", "idx": 1, "is_submittable": 1, - "modified": "2015-05-27 15:36:06.818491", + "modified": "2015-06-08 07:24:47.954499", "modified_by": "Administrator", "module": "Stock", "name": "Material Request", diff --git a/erpnext/stock/doctype/material_request/material_request_list.js b/erpnext/stock/doctype/material_request/material_request_list.js index 293d96026a..390e22272f 100644 --- a/erpnext/stock/doctype/material_request/material_request_list.js +++ b/erpnext/stock/doctype/material_request/material_request_list.js @@ -6,7 +6,13 @@ frappe.listview_settings['Material Request'] = { } else if(doc.docstatus==1 && flt(doc.per_ordered) < 100) { return [__("Pending"), "orange", "per_ordered,<,100"]; } else if(doc.docstatus==1 && flt(doc.per_ordered) == 100) { - return [__("Ordered"), "green", "per_ordered,=,100"]; + if (doc.material_request_type == "Purchase") { + return [__("Ordered"), "green", "per_ordered,=,100"]; + } else if (doc.material_request_type == "Material Transfer") { + return [__("Transfered"), "green", "per_ordered,=,100"]; + } else if (doc.material_request_type == "Material Issue") { + return [__("Issued"), "green", "per_ordered,=,100"]; + } } } }; From f64fae752f204240c9507747f1cf0d6f334f1497 Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Tue, 9 Jun 2015 15:17:33 +0530 Subject: [PATCH 5/7] fixes --- erpnext/patches/v5_0/item_variants.py | 33 +++++++++++++++++++ .../material_request/material_request.json | 4 +-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 erpnext/patches/v5_0/item_variants.py diff --git a/erpnext/patches/v5_0/item_variants.py b/erpnext/patches/v5_0/item_variants.py new file mode 100644 index 0000000000..aeaf729681 --- /dev/null +++ b/erpnext/patches/v5_0/item_variants.py @@ -0,0 +1,33 @@ +import frappe + +def execute(): + variant_item = frappe.db.get_all("Item", + fields=["name"], + filters={"has_variants": 1}) + + for d in variant_item: + pass + + def get_variant_item_codes(self): + """Get all possible suffixes for variants""" + variant_dict = {} + for d in self.attributes: + variant_dict.setdefault(d.attribute, []).append(d.attribute_value) + + all_attributes = [d.name for d in frappe.get_all("Item Attribute", order_by = "priority asc")] + + # sort attributes by their priority + attributes = filter(None, map(lambda d: d if d in variant_dict else None, all_attributes)) + + def add_attribute_suffixes(item_code, my_attributes, attributes): + attr = frappe.get_doc("Item Attribute", attributes[0]) + for value in attr.item_attribute_values: + if value.attribute_value in variant_dict[attr.name]: + _my_attributes = copy.deepcopy(my_attributes) + _my_attributes.append([attr.name, value.attribute_value]) + if len(attributes) > 1: + add_attribute_suffixes(item_code + "-" + value.abbr, _my_attributes, attributes[1:]) + else: + self.append('variants', {"variant": item_code + "-" + value.abbr, + "attributes": json.dumps(_my_attributes)}) + add_attribute_suffixes(self.item, [], attributes) \ No newline at end of file diff --git a/erpnext/stock/doctype/material_request/material_request.json b/erpnext/stock/doctype/material_request/material_request.json index aec242f285..a3026c4ca4 100644 --- a/erpnext/stock/doctype/material_request/material_request.json +++ b/erpnext/stock/doctype/material_request/material_request.json @@ -148,7 +148,7 @@ "no_copy": 1, "oldfieldname": "status", "oldfieldtype": "Select", - "options": "\nDraft\nSubmitted\nIssued\nOrdered\nTransfered\nStopped\nCancelled", + "options": "\nDraft\nSubmitted\nStopped\nCancelled", "permlevel": 0, "print_hide": 1, "print_width": "100px", @@ -221,7 +221,7 @@ "icon": "icon-ticket", "idx": 1, "is_submittable": 1, - "modified": "2015-06-08 07:24:47.954499", + "modified": "2015-06-09 05:47:05.934432", "modified_by": "Administrator", "module": "Stock", "name": "Material Request", From 5d288e407c7b4b3287eebf1af276834b10edff3d Mon Sep 17 00:00:00 2001 From: Neil Trini Lasrado Date: Tue, 9 Jun 2015 15:46:42 +0530 Subject: [PATCH 6/7] item variants patch removed --- erpnext/patches/v5_0/item_variants.py | 33 --------------------------- 1 file changed, 33 deletions(-) delete mode 100644 erpnext/patches/v5_0/item_variants.py diff --git a/erpnext/patches/v5_0/item_variants.py b/erpnext/patches/v5_0/item_variants.py deleted file mode 100644 index aeaf729681..0000000000 --- a/erpnext/patches/v5_0/item_variants.py +++ /dev/null @@ -1,33 +0,0 @@ -import frappe - -def execute(): - variant_item = frappe.db.get_all("Item", - fields=["name"], - filters={"has_variants": 1}) - - for d in variant_item: - pass - - def get_variant_item_codes(self): - """Get all possible suffixes for variants""" - variant_dict = {} - for d in self.attributes: - variant_dict.setdefault(d.attribute, []).append(d.attribute_value) - - all_attributes = [d.name for d in frappe.get_all("Item Attribute", order_by = "priority asc")] - - # sort attributes by their priority - attributes = filter(None, map(lambda d: d if d in variant_dict else None, all_attributes)) - - def add_attribute_suffixes(item_code, my_attributes, attributes): - attr = frappe.get_doc("Item Attribute", attributes[0]) - for value in attr.item_attribute_values: - if value.attribute_value in variant_dict[attr.name]: - _my_attributes = copy.deepcopy(my_attributes) - _my_attributes.append([attr.name, value.attribute_value]) - if len(attributes) > 1: - add_attribute_suffixes(item_code + "-" + value.abbr, _my_attributes, attributes[1:]) - else: - self.append('variants', {"variant": item_code + "-" + value.abbr, - "attributes": json.dumps(_my_attributes)}) - add_attribute_suffixes(self.item, [], attributes) \ No newline at end of file From 17452a1695ee0aa466efc6dc99c81fa459ba690f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 9 Jun 2015 16:26:20 +0600 Subject: [PATCH 7/7] bumped to version 5.0.20 --- 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 dc8b23eea5..82881782e6 100644 --- a/erpnext/__version__.py +++ b/erpnext/__version__.py @@ -1,2 +1,2 @@ from __future__ import unicode_literals -__version__ = '5.0.19' +__version__ = '5.0.20' diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 79856809dc..98e3a3bfb4 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -5,7 +5,7 @@ app_publisher = "Frappe Technologies Pvt. Ltd. and Contributors" app_description = "Open Source Enterprise Resource Planning for Small and Midsized Organizations" app_icon = "icon-th" app_color = "#e74c3c" -app_version = "5.0.19" +app_version = "5.0.20" error_report_email = "support@erpnext.com" diff --git a/setup.py b/setup.py index f43a11c6b2..01425c2e89 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ from setuptools import setup, find_packages -version = "5.0.19" +version = "5.0.20" with open("requirements.txt", "r") as f: install_requires = f.readlines()