diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js index 17fa202a4d4..151854c30af 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.js +++ b/erpnext/manufacturing/doctype/production_order/production_order.js @@ -262,7 +262,8 @@ cur_frm.fields_dict['production_item'].get_query = function(doc) { return { filters:[ ['Item', 'is_pro_applicable', '=', 'Yes'], - ['Item', 'has_variants', '=', 'No'] + ['Item', 'has_variants', '=', 'No'], + ['Item', 'end_of_life', '>=', frappe.datetime.nowdate()] ] } } diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 93ce5e16f64..c2cbbfd9d6f 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -9,10 +9,13 @@ from frappe import _ from frappe.model.document import Document from erpnext.manufacturing.doctype.bom.bom import validate_bom_no from dateutil.relativedelta import relativedelta +from erpnext.stock.doctype.item.item import validate_end_of_life class OverProductionError(frappe.ValidationError): pass class StockOverProductionError(frappe.ValidationError): pass class OperationTooLongError(frappe.ValidationError): pass +class ProductionNotApplicableError(frappe.ValidationError): pass +class ItemHasVariantError(frappe.ValidationError): pass from erpnext.manufacturing.doctype.workstation.workstation import WorkstationHolidayError, NotInWorkingHoursError from erpnext.projects.doctype.time_log.time_log import OverlapError @@ -325,10 +328,12 @@ class ProductionOrder(Document): def validate_production_item(self): if frappe.db.get_value("Item", self.production_item, "is_pro_applicable")=='No': - frappe.throw(_("Item is not allowed to have Production Order.")) + frappe.throw(_("Item is not allowed to have Production Order."), ProductionNotApplicableError) if frappe.db.get_value("Item", self.production_item, "has_variants"): - frappe.throw(_("Production Order cannot be raised against a Item Template")) + frappe.throw(_("Production Order cannot be raised against a Item Template"), ItemHasVariantError) + + validate_end_of_life(self.production_item) @frappe.whitelist() def get_item_details(item): diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py index 34d584a94aa..b91b2e12c83 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py @@ -7,7 +7,8 @@ import unittest import frappe from frappe.utils import flt, get_datetime, time_diff_in_hours from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory -from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry, make_time_log +from erpnext.manufacturing.doctype.production_order.production_order \ + import make_stock_entry, make_time_log, ProductionNotApplicableError,ItemHasVariantError from erpnext.stock.doctype.stock_entry import test_stock_entry from erpnext.projects.doctype.time_log.time_log import OverProductionLoggedError @@ -135,6 +136,22 @@ class TestProductionOrder(unittest.TestCase): prod_order.set_production_order_operations() self.assertEqual(prod_order.planned_operating_cost, cost*2) + def test_production_item(self): + frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", "No") + + prod_order = make_prod_order_test_record(item="_Test FG Item", qty=1, do_not_save=True) + self.assertRaises(ProductionNotApplicableError, prod_order.save) + + frappe.db.set_value("Item", "_Test FG Item", "is_pro_applicable", "Yes") + frappe.db.set_value("Item", "_Test FG Item", "end_of_life", "2000-1-1") + + self.assertRaises(frappe.ValidationError, prod_order.save) + + frappe.db.set_value("Item", "_Test FG Item", "end_of_life", None) + + prod_order = make_prod_order_test_record(item="_Test Variant Item", qty=1, do_not_save=True) + self.assertRaises(ItemHasVariantError, prod_order.save) + def make_prod_order_test_record(**args): args = frappe._dict(args) diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js index c0ae213b875..f833a251be4 100644 --- a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js +++ b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js @@ -98,3 +98,11 @@ cur_frm.cscript.company = function(doc, cdt, cdn) { cur_frm.cscript.posting_date = function(doc, cdt, cdn){ erpnext.get_fiscal_year(doc.company, doc.posting_date); } + +cur_frm.fields_dict.items.grid.get_field('item_code').get_query = function(doc, cdt, cdn) { + return { + filters:[ + ['Item', 'end_of_life', '>=', frappe.datetime.nowdate()] + ] + } +} \ No newline at end of file