feat(Sales/Purchase Order): optional to reference a Blanket Order (#19612)
This commit is contained in:
parent
114e0db419
commit
370cdc0170
@ -17,6 +17,8 @@ from erpnext.stock.doctype.material_request.material_request import make_purchas
|
|||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
||||||
from erpnext.controllers.status_updater import OverAllowanceError
|
from erpnext.controllers.status_updater import OverAllowanceError
|
||||||
|
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
|
||||||
|
|
||||||
|
|
||||||
class TestPurchaseOrder(unittest.TestCase):
|
class TestPurchaseOrder(unittest.TestCase):
|
||||||
def test_make_purchase_receipt(self):
|
def test_make_purchase_receipt(self):
|
||||||
@ -621,6 +623,27 @@ class TestPurchaseOrder(unittest.TestCase):
|
|||||||
self.assertEqual(po.schedule_date, add_days(nowdate(), 2))
|
self.assertEqual(po.schedule_date, add_days(nowdate(), 2))
|
||||||
|
|
||||||
|
|
||||||
|
def test_po_optional_blanket_order(self):
|
||||||
|
"""
|
||||||
|
Expected result: Blanket order Ordered Quantity should only be affected on Purchase Order with against_blanket_order = 1.
|
||||||
|
Second Purchase Order should not add on to Blanket Orders Ordered Quantity.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bo = make_blanket_order(blanket_order_type = "Purchasing", quantity = 10, rate = 10)
|
||||||
|
|
||||||
|
po = create_purchase_order(item_code= "_Test Item", qty = 5, against_blanket_order = 1)
|
||||||
|
po_doc = frappe.get_doc('Purchase Order', po.get('name'))
|
||||||
|
# To test if the PO has a Blanket Order
|
||||||
|
self.assertTrue(po_doc.items[0].blanket_order)
|
||||||
|
|
||||||
|
po = create_purchase_order(item_code= "_Test Item", qty = 5, against_blanket_order = 0)
|
||||||
|
po_doc = frappe.get_doc('Purchase Order', po.get('name'))
|
||||||
|
# To test if the PO does NOT have a Blanket Order
|
||||||
|
self.assertEqual(po_doc.items[0].blanket_order, None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def make_pr_against_po(po, received_qty=0):
|
def make_pr_against_po(po, received_qty=0):
|
||||||
pr = make_purchase_receipt(po)
|
pr = make_purchase_receipt(po)
|
||||||
pr.get("items")[0].qty = received_qty or 5
|
pr.get("items")[0].qty = received_qty or 5
|
||||||
@ -693,7 +716,8 @@ def create_purchase_order(**args):
|
|||||||
"qty": args.qty or 10,
|
"qty": args.qty or 10,
|
||||||
"rate": args.rate or 500,
|
"rate": args.rate or 500,
|
||||||
"schedule_date": add_days(nowdate(), 1),
|
"schedule_date": add_days(nowdate(), 1),
|
||||||
"include_exploded_items": args.get('include_exploded_items', 1)
|
"include_exploded_items": args.get('include_exploded_items', 1),
|
||||||
|
"against_blanket_order": args.against_blanket_order
|
||||||
})
|
})
|
||||||
if not args.do_not_save:
|
if not args.do_not_save:
|
||||||
po.insert()
|
po.insert()
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
"base_amount",
|
"base_amount",
|
||||||
"pricing_rules",
|
"pricing_rules",
|
||||||
"is_free_item",
|
"is_free_item",
|
||||||
"is_fixed_asset",
|
|
||||||
"section_break_29",
|
"section_break_29",
|
||||||
"net_rate",
|
"net_rate",
|
||||||
"net_amount",
|
"net_amount",
|
||||||
@ -67,6 +66,7 @@
|
|||||||
"supplier_quotation",
|
"supplier_quotation",
|
||||||
"supplier_quotation_item",
|
"supplier_quotation_item",
|
||||||
"col_break5",
|
"col_break5",
|
||||||
|
"against_blanket_order",
|
||||||
"blanket_order",
|
"blanket_order",
|
||||||
"blanket_order_rate",
|
"blanket_order_rate",
|
||||||
"item_group",
|
"item_group",
|
||||||
@ -511,6 +511,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order",
|
"fieldname": "blanket_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Blanket Order",
|
"label": "Blanket Order",
|
||||||
@ -518,6 +519,7 @@
|
|||||||
"options": "Blanket Order"
|
"options": "Blanket Order"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order_rate",
|
"fieldname": "blanket_order_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Blanket Order Rate",
|
"label": "Blanket Order Rate",
|
||||||
@ -703,16 +705,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
"fetch_from": "item_code.is_fixed_asset",
|
"fieldname": "against_blanket_order",
|
||||||
"fieldname": "is_fixed_asset",
|
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Is Fixed Asset",
|
"label": "Against Blanket Order"
|
||||||
"read_only": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-11-07 17:19:12.090355",
|
"modified": "2019-11-19 14:10:52.865006",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order Item",
|
"name": "Purchase Order Item",
|
||||||
|
@ -44,6 +44,8 @@ def make_sales_order(source_name):
|
|||||||
target.item_name = item.get("item_name")
|
target.item_name = item.get("item_name")
|
||||||
target.description = item.get("description")
|
target.description = item.get("description")
|
||||||
target.uom = item.get("stock_uom")
|
target.uom = item.get("stock_uom")
|
||||||
|
target.against_blanket_order = 1
|
||||||
|
target.blanket_order = source_name
|
||||||
|
|
||||||
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
||||||
"Blanket Order": {
|
"Blanket Order": {
|
||||||
@ -71,6 +73,8 @@ def make_purchase_order(source_name):
|
|||||||
target.description = item.get("description")
|
target.description = item.get("description")
|
||||||
target.uom = item.get("stock_uom")
|
target.uom = item.get("stock_uom")
|
||||||
target.warehouse = item.get("default_warehouse")
|
target.warehouse = item.get("default_warehouse")
|
||||||
|
target.against_blanket_order = 1
|
||||||
|
target.blanket_order = source_name
|
||||||
|
|
||||||
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
target_doc = get_mapped_doc("Blanket Order", source_name, {
|
||||||
"Blanket Order": {
|
"Blanket Order": {
|
||||||
|
@ -1716,6 +1716,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
against_blanket_order: function(doc, cdt, cdn) {
|
||||||
|
var item = locals[cdt][cdn];
|
||||||
|
if(!item.against_blanket_order) {
|
||||||
|
frappe.model.set_value(this.frm.doctype + " Item", item.name, "blanket_order", null);
|
||||||
|
frappe.model.set_value(this.frm.doctype + " Item", item.name, "blanket_order_rate", 0.00);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
blanket_order: function(doc, cdt, cdn) {
|
blanket_order: function(doc, cdt, cdn) {
|
||||||
var me = this;
|
var me = this;
|
||||||
var item = locals[cdt][cdn];
|
var item = locals[cdt][cdn];
|
||||||
|
@ -12,6 +12,7 @@ from erpnext.selling.doctype.sales_order.sales_order import make_work_orders
|
|||||||
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
from erpnext.controllers.accounts_controller import update_child_qty_rate
|
||||||
import json
|
import json
|
||||||
from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request
|
from erpnext.selling.doctype.sales_order.sales_order import make_raw_material_request
|
||||||
|
from erpnext.manufacturing.doctype.blanket_order.test_blanket_order import make_blanket_order
|
||||||
|
|
||||||
class TestSalesOrder(unittest.TestCase):
|
class TestSalesOrder(unittest.TestCase):
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
@ -819,6 +820,25 @@ class TestSalesOrder(unittest.TestCase):
|
|||||||
mr_doc = frappe.get_doc('Material Request',mr.get('name'))
|
mr_doc = frappe.get_doc('Material Request',mr.get('name'))
|
||||||
self.assertEqual(mr_doc.items[0].sales_order, so.name)
|
self.assertEqual(mr_doc.items[0].sales_order, so.name)
|
||||||
|
|
||||||
|
def test_so_optional_blanket_order(self):
|
||||||
|
"""
|
||||||
|
Expected result: Blanket order Ordered Quantity should only be affected on Sales Order with against_blanket_order = 1.
|
||||||
|
Second Sales Order should not add on to Blanket Orders Ordered Quantity.
|
||||||
|
"""
|
||||||
|
|
||||||
|
bo = make_blanket_order(blanket_order_type = "Selling", quantity = 10, rate = 10)
|
||||||
|
|
||||||
|
so = make_sales_order(item_code= "_Test Item", qty = 5, against_blanket_order = 1)
|
||||||
|
so_doc = frappe.get_doc('Sales Order', so.get('name'))
|
||||||
|
# To test if the SO has a Blanket Order
|
||||||
|
self.assertTrue(so_doc.items[0].blanket_order)
|
||||||
|
|
||||||
|
so = make_sales_order(item_code= "_Test Item", qty = 5, against_blanket_order = 0)
|
||||||
|
so_doc = frappe.get_doc('Sales Order', so.get('name'))
|
||||||
|
# To test if the SO does NOT have a Blanket Order
|
||||||
|
self.assertEqual(so_doc.items[0].blanket_order, None)
|
||||||
|
|
||||||
|
|
||||||
def make_sales_order(**args):
|
def make_sales_order(**args):
|
||||||
so = frappe.new_doc("Sales Order")
|
so = frappe.new_doc("Sales Order")
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
@ -845,7 +865,8 @@ def make_sales_order(**args):
|
|||||||
"warehouse": args.warehouse,
|
"warehouse": args.warehouse,
|
||||||
"qty": args.qty or 10,
|
"qty": args.qty or 10,
|
||||||
"uom": args.uom or None,
|
"uom": args.uom or None,
|
||||||
"rate": args.rate or 100
|
"rate": args.rate or 100,
|
||||||
|
"against_blanket_order": args.against_blanket_order
|
||||||
})
|
})
|
||||||
|
|
||||||
so.delivery_date = add_days(so.transaction_date, 10)
|
so.delivery_date = add_days(so.transaction_date, 10)
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
"target_warehouse",
|
"target_warehouse",
|
||||||
"prevdoc_docname",
|
"prevdoc_docname",
|
||||||
"col_break4",
|
"col_break4",
|
||||||
|
"against_blanket_order",
|
||||||
"blanket_order",
|
"blanket_order",
|
||||||
"blanket_order_rate",
|
"blanket_order_rate",
|
||||||
"planning_section",
|
"planning_section",
|
||||||
@ -574,6 +575,7 @@
|
|||||||
"report_hide": 1
|
"report_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order",
|
"fieldname": "blanket_order",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Blanket Order",
|
"label": "Blanket Order",
|
||||||
@ -581,6 +583,7 @@
|
|||||||
"options": "Blanket Order"
|
"options": "Blanket Order"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"depends_on": "eval:doc.against_blanket_order",
|
||||||
"fieldname": "blanket_order_rate",
|
"fieldname": "blanket_order_rate",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Blanket Order Rate",
|
"label": "Blanket Order Rate",
|
||||||
@ -741,11 +744,17 @@
|
|||||||
"fieldname": "image_section",
|
"fieldname": "image_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"label": "Image"
|
"label": "Image"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "against_blanket_order",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Against Blanket Order"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-10-10 08:46:26.244823",
|
"modified": "2019-11-19 14:19:29.491945",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order Item",
|
"name": "Sales Order Item",
|
||||||
|
@ -213,7 +213,8 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
project: "",
|
project: "",
|
||||||
qty: "",
|
qty: "",
|
||||||
stock_qty: "",
|
stock_qty: "",
|
||||||
conversion_factor: ""
|
conversion_factor: "",
|
||||||
|
against_blanket_order: 0/1
|
||||||
}
|
}
|
||||||
:param item: `item_code` of Item object
|
:param item: `item_code` of Item object
|
||||||
:return: frappe._dict
|
:return: frappe._dict
|
||||||
@ -302,7 +303,8 @@ def get_basic_details(args, item, overwrite_warehouse=True):
|
|||||||
"weight_per_unit":item.weight_per_unit,
|
"weight_per_unit":item.weight_per_unit,
|
||||||
"weight_uom":item.weight_uom,
|
"weight_uom":item.weight_uom,
|
||||||
"last_purchase_rate": item.last_purchase_rate if args.get("doctype") in ["Purchase Order"] else 0,
|
"last_purchase_rate": item.last_purchase_rate if args.get("doctype") in ["Purchase Order"] else 0,
|
||||||
"transaction_date": args.get("transaction_date")
|
"transaction_date": args.get("transaction_date"),
|
||||||
|
"against_blanket_order": args.get("against_blanket_order")
|
||||||
})
|
})
|
||||||
|
|
||||||
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
|
||||||
@ -996,6 +998,7 @@ def get_serial_no(args, serial_nos=None, sales_order=None):
|
|||||||
|
|
||||||
|
|
||||||
def update_party_blanket_order(args, out):
|
def update_party_blanket_order(args, out):
|
||||||
|
if out["against_blanket_order"]:
|
||||||
blanket_order_details = get_blanket_order_details(args)
|
blanket_order_details = get_blanket_order_details(args)
|
||||||
if blanket_order_details:
|
if blanket_order_details:
|
||||||
out.update(blanket_order_details)
|
out.update(blanket_order_details)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user