From 2de1cfc1c1e4c9dd7b92cbdb63a08a638b60c1ba Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 5 Jul 2013 10:23:00 +0530 Subject: [PATCH] [mapper] material request - PO/supp quote/stock entry --- .../doctype/purchase_order/purchase_order.js | 8 ++- .../doctype/purchase_order/purchase_order.py | 19 ------ .../doctype/purchase_order/purchase_order.txt | 37 +++++++++- .../supplier_quotation/supplier_quotation.js | 6 ++ .../supplier_quotation/supplier_quotation.py | 14 ---- .../supplier_quotation/supplier_quotation.txt | 21 ++++-- .../material_request/material_request.js | 53 ++++++++------- .../material_request/material_request.py | 68 ++++++++++++++++++- .../material_request/test_material_request.py | 32 +++++++++ 9 files changed, 192 insertions(+), 66 deletions(-) diff --git a/buying/doctype/purchase_order/purchase_order.js b/buying/doctype/purchase_order/purchase_order.js index 442925131a..fd420cae41 100644 --- a/buying/doctype/purchase_order/purchase_order.js +++ b/buying/doctype/purchase_order/purchase_order.js @@ -83,7 +83,13 @@ cur_frm.cscript.get_last_purchase_rate = function(doc, cdt, cdn){ } -//========================= Make Purchase Receipt ======================================================= +cur_frm.cscript.get_items = function(doc, dt, dn) { + wn.model.map_current_doc({ + method: "stock.doctype.material_request.material_request.make_purchase_order", + source_name: cur_frm.doc.indent_no, + }) +} + cur_frm.cscript['Make Purchase Receipt'] = function() { n = wn.model.make_new_doc_and_get_name('Purchase Receipt'); $c('dt_map', args={ diff --git a/buying/doctype/purchase_order/purchase_order.py b/buying/doctype/purchase_order/purchase_order.py index 908df67403..fba448c23d 100644 --- a/buying/doctype/purchase_order/purchase_order.py +++ b/buying/doctype/purchase_order/purchase_order.py @@ -21,7 +21,6 @@ from webnotes.utils import cstr, flt from webnotes.model.bean import getlist from webnotes.model.code import get_obj from webnotes import msgprint -from buying.utils import get_last_purchase_details sql = webnotes.conn.sql @@ -72,24 +71,6 @@ class DocType(BuyingController): def get_bin_details(self, arg = ''): return get_obj(dt='Purchase Common').get_bin_details(arg) - # Pull Material Request - def get_indent_details(self): - if self.doc.indent_no: - get_obj('DocType Mapper','Material Request-Purchase Order').dt_map('Material Request','Purchase Order',self.doc.indent_no, self.doc, self.doclist, "[['Material Request','Purchase Order'],['Material Request Item', 'Purchase Order Item']]") - for d in getlist(self.doclist, 'po_details'): - if d.item_code and not d.purchase_rate: - last_purchase_details = get_last_purchase_details(d.item_code, self.doc.name) - if last_purchase_details: - conversion_factor = d.conversion_factor or 1.0 - conversion_rate = self.doc.fields.get('conversion_rate') or 1.0 - d.purchase_ref_rate = last_purchase_details['purchase_ref_rate'] * conversion_factor - d.discount_rate = last_purchase_details['discount_rate'] - d.purchase_rate = last_purchase_details['purchase_rate'] * conversion_factor - d.import_ref_rate = d.purchase_ref_rate / conversion_rate - d.import_rate = d.purchase_rate / conversion_rate - else: - d.purchase_ref_rate = d.discount_rate = d.purchase_rate = d.import_ref_rate = d.import_rate = 0.0 - def get_supplier_quotation_items(self): if self.doc.supplier_quotation: get_obj("DocType Mapper", "Supplier Quotation-Purchase Order").dt_map("Supplier Quotation", diff --git a/buying/doctype/purchase_order/purchase_order.txt b/buying/doctype/purchase_order/purchase_order.txt index b2bf1464aa..6fd2161399 100644 --- a/buying/doctype/purchase_order/purchase_order.txt +++ b/buying/doctype/purchase_order/purchase_order.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-21 16:16:39", "docstatus": 0, - "modified": "2013-07-04 10:48:54", + "modified": "2013-07-04 18:10:21", "modified_by": "Administrator", "owner": "Administrator" }, @@ -31,7 +31,6 @@ "parent": "Purchase Order", "parentfield": "permissions", "parenttype": "DocType", - "permlevel": 0, "read": 1, "report": 1 }, @@ -208,7 +207,6 @@ "label": "Get Items", "no_copy": 0, "oldfieldtype": "Button", - "options": "get_indent_details", "print_hide": 1 }, { @@ -789,15 +787,37 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", + "permlevel": 1, "role": "Material User", "submit": 0, "write": 0 }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 0, + "role": "Material User", + "submit": 0, + "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "role": "Purchase Manager", + "submit": 0, + "write": 0 + }, { "amend": 1, "cancel": 1, "create": 1, "doctype": "DocPerm", + "permlevel": 0, "role": "Purchase Manager", "submit": 1, "write": 1 @@ -807,13 +827,24 @@ "cancel": 1, "create": 1, "doctype": "DocPerm", + "permlevel": 0, "role": "Purchase User", "submit": 1, "write": 1 }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "role": "All", + "submit": 0 + }, { "doctype": "DocPerm", "match": "supplier", + "permlevel": 0, "role": "Supplier" } ] \ No newline at end of file diff --git a/buying/doctype/supplier_quotation/supplier_quotation.js b/buying/doctype/supplier_quotation/supplier_quotation.js index 0ed85ff2f9..92db302288 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/buying/doctype/supplier_quotation/supplier_quotation.js @@ -31,6 +31,12 @@ erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.ext cur_frm.add_custom_button("Make Purchase Order", cur_frm.cscript.make_purchase_order); } }, + get_items: function() { + wn.model.map_current_doc({ + method: "stock.doctype.material_request.material_request.make_supplier_quotation", + source_name: cur_frm.doc.indent_no, + }) + } }); // for backward compatibility: combine new and previous states diff --git a/buying/doctype/supplier_quotation/supplier_quotation.py b/buying/doctype/supplier_quotation/supplier_quotation.py index 421ecd0d44..b8cf7cbac8 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.py +++ b/buying/doctype/supplier_quotation/supplier_quotation.py @@ -17,7 +17,6 @@ from __future__ import unicode_literals import webnotes from webnotes.model.code import get_obj -from setup.utils import get_company_currency from controllers.buying_controller import BuyingController class DocType(BuyingController): @@ -49,19 +48,6 @@ class DocType(BuyingController): def on_trash(self): pass - - def get_indent_details(self): - if self.doc.indent_no: - mapper = get_obj("DocType Mapper", "Material Request-Supplier Quotation") - mapper.dt_map("Material Request", "Supplier Quotation", self.doc.indent_no, - self.doc, self.doclist, """[['Material Request', 'Supplier Quotation'], - ['Material Request Item', 'Supplier Quotation Item']]""") - - from webnotes.model.bean import getlist - for d in getlist(self.doclist, self.fname): - if d.item_code and not d.purchase_rate: - d.purchase_ref_rate = d.discount_rate = d.purchase_rate = 0.0 - d.import_ref_rate = d.import_rate = 0.0 def validate_fiscal_year(self): get_obj(dt = 'Purchase Common').validate_fiscal_year( \ diff --git a/buying/doctype/supplier_quotation/supplier_quotation.txt b/buying/doctype/supplier_quotation/supplier_quotation.txt index d9ecf602de..5f2e95ee8c 100644 --- a/buying/doctype/supplier_quotation/supplier_quotation.txt +++ b/buying/doctype/supplier_quotation/supplier_quotation.txt @@ -2,7 +2,7 @@ { "creation": "2013-05-21 16:16:45", "docstatus": 0, - "modified": "2013-07-04 10:51:05", + "modified": "2013-07-04 18:47:51", "modified_by": "Administrator", "owner": "Administrator" }, @@ -31,7 +31,6 @@ "parent": "Supplier Quotation", "parentfield": "permissions", "parenttype": "DocType", - "permlevel": 0, "read": 1, "report": 1 }, @@ -191,8 +190,7 @@ "fieldtype": "Button", "hidden": 0, "label": "Get Items", - "oldfieldtype": "Button", - "options": "get_indent_details" + "oldfieldtype": "Button" }, { "doctype": "DocField", @@ -644,6 +642,7 @@ "cancel": 1, "create": 1, "doctype": "DocPerm", + "permlevel": 0, "role": "Manufacturing Manager", "submit": 1, "write": 1 @@ -653,6 +652,7 @@ "cancel": 1, "create": 1, "doctype": "DocPerm", + "permlevel": 0, "role": "Purchase Manager", "submit": 1, "write": 1 @@ -662,6 +662,7 @@ "cancel": 0, "create": 1, "doctype": "DocPerm", + "permlevel": 0, "role": "Purchase User", "submit": 0, "write": 1 @@ -671,6 +672,7 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", + "permlevel": 0, "role": "Material User", "submit": 0, "write": 0 @@ -680,8 +682,19 @@ "cancel": 0, "create": 0, "doctype": "DocPerm", + "permlevel": 0, "role": "Supplier", "submit": 0, "write": 0 + }, + { + "amend": 0, + "cancel": 0, + "create": 0, + "doctype": "DocPerm", + "permlevel": 1, + "role": "All", + "submit": 0, + "write": 0 } ] \ No newline at end of file diff --git a/stock/doctype/material_request/material_request.js b/stock/doctype/material_request/material_request.js index 3446b02ad4..6de7a295e7 100644 --- a/stock/doctype/material_request/material_request.js +++ b/stock/doctype/material_request/material_request.js @@ -36,23 +36,27 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten if(doc.docstatus == 1 && doc.status != 'Stopped'){ if(doc.material_request_type === "Purchase") - cur_frm.add_custom_button("Make Supplier Quotation", cur_frm.cscript.make_supplier_quotation); + cur_frm.add_custom_button("Make Supplier Quotation", + cur_frm.cscript.make_supplier_quotation); if(doc.material_request_type === "Transfer" && doc.status === "Submitted") cur_frm.add_custom_button("Transfer Material", cur_frm.cscript.make_stock_entry); if(flt(doc.per_ordered, 2) < 100) { if(doc.material_request_type === "Purchase") - cur_frm.add_custom_button('Make Purchase Order', cur_frm.cscript['Make Purchase Order']); + cur_frm.add_custom_button('Make Purchase Order', + cur_frm.cscript.make_purchase_order); - cur_frm.add_custom_button('Stop Material Request', cur_frm.cscript['Stop Material Request']); + cur_frm.add_custom_button('Stop Material Request', + cur_frm.cscript['Stop Material Request']); } cur_frm.add_custom_button('Send SMS', cur_frm.cscript.send_sms); } if(doc.docstatus == 1 && doc.status == 'Stopped') - cur_frm.add_custom_button('Unstop Material Request', cur_frm.cscript['Unstop Material Request']); + cur_frm.add_custom_button('Unstop Material Request', + cur_frm.cscript['Unstop Material Request']); if(doc.material_request_type === "Transfer") { cur_frm.toggle_display("sales_order_no", false); @@ -66,6 +70,27 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten calculate_taxes_and_totals: function() { return; + }, + + make_purchase_order: function() { + wn.model.open_mapped_doc({ + method: "stock.doctype.material_request.material_request.make_purchase_order", + source_name: cur_frm.doc.name + }) + }, + + make_supplier_quotation: function() { + wn.model.open_mapped_doc({ + method: "stock.doctype.material_request.material_request.make_supplier_quotation", + source_name: cur_frm.doc.name + }) + }, + + make_stock_entry: function() { + wn.model.open_mapped_doc({ + method: "stock.doctype.material_request.material_request.make_stock_entry", + source_name: cur_frm.doc.name + }) } }); @@ -96,26 +121,6 @@ cur_frm.cscript['Unstop Material Request'] = function(){ if (check) { $c('runserverobj', args={'method':'update_status', 'arg': 'Submitted','docs': wn.model.compress(make_doclist(doc.doctype, doc.name))}, function(r,rt) { cur_frm.refresh(); - }); } }; - -cur_frm.cscript['Make Purchase Order'] = function() { - wn.model.open_mapped_doc({ - method: "stock.doctype.material_request.material_request.make_purchase_order", - source_name: cur_frm.doc.name - }) -} - -cur_frm.cscript.make_supplier_quotation = function() { - cur_frm.map([ - ["Material Request", "Supplier Quotation"], - ["Material Request Item", "Supplier Quotation Item"]]); -}; - -cur_frm.cscript.make_stock_entry = function() { - cur_frm.map([ - ["Material Request", "Stock Entry"], - ["Material Request Item", "Stock Entry Detail"]]); -}; diff --git a/stock/doctype/material_request/material_request.py b/stock/doctype/material_request/material_request.py index 269c4c54d7..3f3c212b8e 100644 --- a/stock/doctype/material_request/material_request.py +++ b/stock/doctype/material_request/material_request.py @@ -250,6 +250,10 @@ def make_purchase_order(source_name, target_doclist=None): def update_item(obj, target): target.conversion_factor = 1 target.qty = flt(obj.qty) - flt(obj.ordered_qty) + + def set_missing_values(source, target): + po = webnotes.bean(target) + po.run_method("set_missing_values") doclist = get_mapped_doclist("Material Request", source_name, { "Material Request": { @@ -269,6 +273,68 @@ def make_purchase_order(source_name, target_doclist=None): }, "postprocess": update_item } - }, target_doclist) + }, target_doclist, set_missing_values) + + return [d.fields for d in doclist] + +@webnotes.whitelist() +def make_supplier_quotation(source_name, target_doclist=None): + from webnotes.model.mapper import get_mapped_doclist + + def set_missing_values(source, target): + sq = webnotes.bean(target) + sq.run_method("set_missing_values") + + doclist = get_mapped_doclist("Material Request", source_name, { + "Material Request": { + "doctype": "Supplier Quotation", + "validation": { + "docstatus": ["=", 1], + "material_request_type": ["=", "Purchase"] + } + }, + "Material Request Item": { + "doctype": "Supplier Quotation Item", + "field_map": { + "name": "prevdoc_detail_docname", + "parent": "prevdoc_docname", + "parenttype": "prevdoc_doctype" + } + } + }, target_doclist, set_missing_values) + + return [d.fields for d in doclist] + +@webnotes.whitelist() +def make_stock_entry(source_name, target_doclist=None): + from webnotes.model.mapper import get_mapped_doclist + + def set_purpose(source, target): + target[0].purpose = "Material Transfer" + + def update_item(source, target): + target.conversion_factor = 1 + target.qty = flt(source.qty) - flt(source.ordered_qty) + + + doclist = get_mapped_doclist("Material Request", source_name, { + "Material Request": { + "doctype": "Stock Entry", + "validation": { + "docstatus": ["=", 1], + "material_request_type": ["=", "Transfer"] + } + }, + "Material Request Item": { + "doctype": "Stock Entry Detail", + "field_map": { + "name": "material_request_item", + "parent": "material_request", + "uom": "stock_uom", + "warehouse": "t_warehouse" + }, + "postprocess": update_item + } + }, target_doclist, set_purpose) return [d.fields for d in doclist] \ No newline at end of file diff --git a/stock/doctype/material_request/test_material_request.py b/stock/doctype/material_request/test_material_request.py index f26773b0c8..daf31ad969 100644 --- a/stock/doctype/material_request/test_material_request.py +++ b/stock/doctype/material_request/test_material_request.py @@ -20,6 +20,38 @@ class TestMaterialRequest(unittest.TestCase): self.assertEquals(po[0]["doctype"], "Purchase Order") self.assertEquals(len(po), len(mr.doclist)) + + def test_make_supplier_quotation(self): + from stock.doctype.material_request.material_request import make_supplier_quotation + + mr = webnotes.bean(copy=test_records[0]).insert() + + self.assertRaises(webnotes.ValidationError, make_supplier_quotation, + mr.doc.name) + + mr = webnotes.bean("Material Request", mr.doc.name) + mr.submit() + sq = make_supplier_quotation(mr.doc.name) + + self.assertEquals(sq[0]["doctype"], "Supplier Quotation") + self.assertEquals(len(sq), len(mr.doclist)) + + + def test_make_stock_entry(self): + from stock.doctype.material_request.material_request import make_stock_entry + + mr = webnotes.bean(copy=test_records[0]).insert() + + self.assertRaises(webnotes.ValidationError, make_stock_entry, + mr.doc.name) + + mr = webnotes.bean("Material Request", mr.doc.name) + mr.doc.material_request_type = "Transfer" + mr.submit() + se = make_stock_entry(mr.doc.name) + + self.assertEquals(se[0]["doctype"], "Stock Entry") + self.assertEquals(len(se), len(mr.doclist)) def _test_expected(self, doclist, expected_values): for i, expected in enumerate(expected_values):