Merge pull request #2329 from neilLasrado/material-issue

Material Issue added to Material Request #2320
This commit is contained in:
Nabin Hait 2014-11-10 12:04:01 +05:30
commit 012cc2cfe1
7 changed files with 95 additions and 22 deletions

View File

@ -91,3 +91,4 @@ erpnext.patches.v4_2.update_requested_and_ordered_qty
erpnext.patches.v4_2.party_model
erpnext.patches.v5_0.update_frozen_accounts_permission_role
erpnext.patches.v5_0.update_dn_against_doc_fields
execute:frappe.db.sql("update `tabMaterial Request` set material_request_type = 'Material Transfer' where material_request_type = 'Transfer'")

View File

@ -42,9 +42,13 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
this.make_supplier_quotation,
frappe.boot.doctype_icons["Supplier Quotation"]);
if(doc.material_request_type === "Transfer" && doc.status === "Submitted")
if(doc.material_request_type === "Material Transfer" && doc.status === "Submitted")
cur_frm.add_custom_button(__("Transfer Material"), this.make_stock_entry,
frappe.boot.doctype_icons["Stock Entry"]);
if(doc.material_request_type === "Material Issue" && doc.status === "Submitted")
cur_frm.add_custom_button(__("Issue Material"), this.make_stock_entry,
frappe.boot.doctype_icons["Stock Entry"]);
if(flt(doc.per_ordered, 2) < 100) {
if(doc.material_request_type === "Purchase")
@ -165,7 +169,7 @@ erpnext.buying.MaterialRequestController = erpnext.buying.BuyingController.exten
// for backward compatibility: combine new and previous states
$.extend(cur_frm.cscript, new erpnext.buying.MaterialRequestController({frm: cur_frm}));
cur_frm.cscript.qty = function(doc, cdt, cdn) {
cur_frm.cscript.qty = function(cdt, cdn) {
var d = locals[cdt][cdn];
if (flt(d.qty) < flt(d.min_order_qty))
alert(__("Warning: Material Requested Qty is less than Minimum Order Qty"));

View File

@ -17,7 +17,7 @@
"fieldtype": "Select",
"in_list_view": 1,
"label": "Type",
"options": "Purchase\nTransfer",
"options": "Purchase\nMaterial Transfer\nMaterial Issue",
"permlevel": 0,
"reqd": 1
},
@ -235,7 +235,7 @@
"icon": "icon-ticket",
"idx": 1,
"is_submittable": 1,
"modified": "2014-09-09 05:35:31.735821",
"modified": "2014-10-27 12:16:38.833386",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request",

View File

@ -73,7 +73,7 @@ class MaterialRequest(BuyingController):
from erpnext.utilities import validate_status
validate_status(self.status, ["Draft", "Submitted", "Stopped", "Cancelled"])
self.validate_value("material_request_type", "in", ["Purchase", "Transfer"])
self.validate_value("material_request_type", "in", ["Purchase", "Material Transfer", "Material Issue"])
pc_obj = frappe.get_doc('Purchase Common')
pc_obj.validate_for_items(self)
@ -112,7 +112,7 @@ class MaterialRequest(BuyingController):
frappe.db.set(self,'status','Cancelled')
def update_completed_qty(self, mr_items=None):
if self.material_request_type != "Transfer":
if self.material_request_type == "Purchase":
return
item_doclist = self.get("indent_details")
@ -294,12 +294,19 @@ def make_supplier_quotation(source_name, target_doc=None):
@frappe.whitelist()
def make_stock_entry(source_name, target_doc=None):
def update_item(obj, target, source_parent):
qty = flt(obj.qty) - flt(obj.ordered_qty) \
if flt(obj.qty) > flt(obj.ordered_qty) else 0
target.qty = qty
target.transfer_qty = qty
target.conversion_factor = 1
target.qty = flt(obj.qty) - flt(obj.ordered_qty)
target.transfer_qty = flt(obj.qty) - flt(obj.ordered_qty)
if source_parent.material_request_type == "Material Transfer":
target.t_warehouse = obj.warehouse
else:
target.s_warehouse = obj.warehouse
def set_missing_values(source, target):
target.purpose = "Material Transfer"
target.purpose = source.material_request_type
target.run_method("get_stock_and_rate")
doclist = get_mapped_doc("Material Request", source_name, {
@ -307,7 +314,7 @@ def make_stock_entry(source_name, target_doc=None):
"doctype": "Stock Entry",
"validation": {
"docstatus": ["=", 1],
"material_request_type": ["=", "Transfer"]
"material_request_type": ["in", ["Material Transfer", "Material Issue"]]
}
},
"Material Request Item": {
@ -316,7 +323,6 @@ def make_stock_entry(source_name, target_doc=None):
"name": "material_request_item",
"parent": "material_request",
"uom": "stock_uom",
"warehouse": "t_warehouse"
},
"postprocess": update_item
}

View File

@ -51,14 +51,14 @@ class TestMaterialRequest(unittest.TestCase):
mr.name)
mr = frappe.get_doc("Material Request", mr.name)
mr.material_request_type = "Transfer"
mr.material_request_type = "Material Transfer"
mr.submit()
se = make_stock_entry(mr.name)
self.assertEquals(se.doctype, "Stock Entry")
self.assertEquals(len(se.get("mtn_details")), len(mr.get("indent_details")))
def _insert_stock_entry(self, qty1, qty2):
def _insert_stock_entry(self, qty1, qty2, warehouse = None ):
se = frappe.get_doc({
"company": "_Test Company",
"doctype": "Stock Entry",
@ -77,7 +77,7 @@ class TestMaterialRequest(unittest.TestCase):
"stock_uom": "_Test UOM 1",
"transfer_qty": qty1,
"uom": "_Test UOM 1",
"t_warehouse": "_Test Warehouse 1 - _TC",
"t_warehouse": warehouse or "_Test Warehouse 1 - _TC",
},
{
"conversion_factor": 1.0,
@ -89,7 +89,7 @@ class TestMaterialRequest(unittest.TestCase):
"stock_uom": "_Test UOM 1",
"transfer_qty": qty2,
"uom": "_Test UOM 1",
"t_warehouse": "_Test Warehouse 1 - _TC",
"t_warehouse": warehouse or "_Test Warehouse 1 - _TC",
}
]
})
@ -168,7 +168,7 @@ class TestMaterialRequest(unittest.TestCase):
# submit material request of type Purchase
mr = frappe.copy_doc(test_records[0])
mr.material_request_type = "Transfer"
mr.material_request_type = "Material Transfer"
mr.insert()
mr.submit()
@ -257,7 +257,7 @@ class TestMaterialRequest(unittest.TestCase):
# submit material request of type Purchase
mr = frappe.copy_doc(test_records[0])
mr.material_request_type = "Transfer"
mr.material_request_type = "Material Transfer"
mr.insert()
mr.submit()
@ -330,9 +330,9 @@ class TestMaterialRequest(unittest.TestCase):
self.assertEquals(current_requested_qty_item2, existing_requested_qty_item2 + 3.0)
def test_incorrect_mapping_of_stock_entry(self):
# submit material request of type Purchase
# submit material request of type Transfer
mr = frappe.copy_doc(test_records[0])
mr.material_request_type = "Transfer"
mr.material_request_type = "Material Transfer"
mr.insert()
mr.submit()
@ -363,6 +363,17 @@ class TestMaterialRequest(unittest.TestCase):
se = frappe.copy_doc(se_doc)
self.assertRaises(frappe.MappingMismatchError, se.insert)
# submit material request of type Transfer
mr = frappe.copy_doc(test_records[0])
mr.material_request_type = "Material Issue"
mr.insert()
mr.submit()
# map a stock entry
from erpnext.stock.doctype.material_request.material_request import make_stock_entry
se_doc = make_stock_entry(mr.name)
self.assertEquals(se_doc.get("mtn_details")[0].s_warehouse, "_Test Warehouse - _TC")
def test_warehouse_company_validation(self):
from erpnext.stock.utils import InvalidWarehouseCompany
mr = frappe.copy_doc(test_records[0])
@ -372,6 +383,56 @@ class TestMaterialRequest(unittest.TestCase):
def _get_requested_qty(self, item_code, warehouse):
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "indented_qty"))
def test_make_stock_entry_for_Material_Issue(self):
from erpnext.stock.doctype.material_request.material_request import make_stock_entry
mr = frappe.copy_doc(test_records[0]).insert()
self.assertRaises(frappe.ValidationError, make_stock_entry,
mr.name)
mr = frappe.get_doc("Material Request", mr.name)
mr.material_request_type = "Material Issue"
mr.submit()
se = make_stock_entry(mr.name)
self.assertEquals(se.doctype, "Stock Entry")
self.assertEquals(len(se.get("mtn_details")), len(mr.get("indent_details")))
def test_compleated_qty_for_issue(self):
def _get_requested_qty():
return flt(frappe.db.get_value("Bin", {"item_code": "_Test Item Home Desktop 100",
"warehouse": "_Test Warehouse - _TC"}, "indented_qty"))
from erpnext.stock.doctype.material_request.material_request import make_stock_entry
existing_requested_qty = _get_requested_qty()
mr = frappe.copy_doc(test_records[0])
mr.material_request_type = "Material Issue"
mr.submit()
#testing bin value after material request is submitted
self.assertEquals(_get_requested_qty(), existing_requested_qty + 54.0)
# receive items to allow issue
self._insert_stock_entry(60, 6, "_Test Warehouse - _TC")
# make stock entry against MR
se_doc = make_stock_entry(mr.name)
se_doc.fiscal_year = "_Test Fiscal Year 2014"
se_doc.get("mtn_details")[0].qty = 60.0
se_doc.insert()
se_doc.submit()
# check if per complete is as expected
mr.load_from_db()
self.assertEquals(mr.get("indent_details")[0].ordered_qty, 60.0)
self.assertEquals(mr.get("indent_details")[1].ordered_qty, 3.0)
#testing bin requested qty after issuing stock against material request
self.assertEquals(_get_requested_qty(), existing_requested_qty)
test_dependencies = ["Currency Exchange"]
test_records = frappe.get_test_records('Material Request')

View File

@ -219,7 +219,7 @@ class StockEntry(StockController):
if not self.posting_date or not self.posting_time:
frappe.throw(_("Posting date and posting time is mandatory"))
allow_negative_stock = cint(frappe.db.get_default("allow_negative_stock"))
allow_negative_stock = cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
for d in self.get('mtn_details'):
d.transfer_qty = flt(d.transfer_qty)
@ -625,7 +625,8 @@ class StockEntry(StockController):
mreq_item = frappe.db.get_value("Material Request Item",
{"name": item.material_request_item, "parent": item.material_request},
["item_code", "warehouse", "idx"], as_dict=True)
if mreq_item.item_code != item.item_code or mreq_item.warehouse != item.t_warehouse:
if mreq_item.item_code != item.item_code or \
mreq_item.warehouse != (item.s_warehouse if self.purpose== "Material Issue" else item.t_warehouse):
frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx),
frappe.MappingMismatchError)

View File

@ -87,7 +87,7 @@ def update_entries_after(args, allow_zero_rate=False, verbose=1):
stock_value_difference = 0.0
for sle in entries_to_fix:
if sle.serial_no or not cint(frappe.db.get_default("allow_negative_stock")):
if sle.serial_no or not cint(frappe.db.get_value("Stock Settings", None, "allow_negative_stock")):
# validate negative stock for serialized items, fifo valuation
# or when negative stock is not allowed for moving average
if not validate_negative_stock(qty_after_transaction, sle):