Merge pull request #3716 from tmimori/develop
Removed HTML from messages
diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py
index 8153912..75c353d 100644
--- a/erpnext/accounts/report/gross_profit/gross_profit.py
+++ b/erpnext/accounts/report/gross_profit/gross_profit.py
@@ -174,12 +174,12 @@
return flt(row.qty) * item_rate
else:
- if row.update_stock or row.dn_detail:
+ my_sle = self.sle.get((item_code, row.warehouse))
+ if (row.update_stock or row.dn_detail) and my_sle:
parenttype, parent, item_row = row.parenttype, row.parent, row.item_row
if row.dn_detail:
parenttype, parent, item_row = "Delivery Note", row.delivery_note, row.dn_detail
-
- my_sle = self.sle.get((item_code, row.warehouse))
+
for i, sle in enumerate(my_sle):
# find the stock valution rate from stock ledger entry
if sle.voucher_type == parenttype and parent == sle.voucher_no and \
diff --git a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
index ea9569f..eb770a8 100644
--- a/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
+++ b/erpnext/manufacturing/doctype/manufacturing_settings/manufacturing_settings.json
@@ -16,6 +16,14 @@
"precision": ""
},
{
+ "description": "Disables creation of time logs against Production Orders.\nOperations shall not be tracked against Production Order",
+ "fieldname": "disable_capacity_planning",
+ "fieldtype": "Check",
+ "label": "Disable Capacity Planning and Time Tracking",
+ "permlevel": 0,
+ "precision": ""
+ },
+ {
"description": "Plan time logs outside Workstation Working Hours.",
"fieldname": "allow_overtime",
"fieldtype": "Check",
@@ -72,7 +80,7 @@
"is_submittable": 0,
"issingle": 1,
"istable": 0,
- "modified": "2015-06-15 05:52:22.986958",
+ "modified": "2015-07-23 08:12:33.889753",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing Settings",
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js
index 17fa202..d366377 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.js
+++ b/erpnext/manufacturing/doctype/production_order/production_order.js
@@ -186,27 +186,16 @@
},
bom_no: function() {
- if (this.frm.doc.track_operations) {
- return this.frm.call({
- doc: this.frm.doc,
- method: "set_production_order_operations"
- });
- }
+ return this.frm.call({
+ doc: this.frm.doc,
+ method: "set_production_order_operations"
+ });
},
qty: function() {
frappe.ui.form.trigger("Production Order", 'bom_no')
},
- track_operations: function(doc) {
- if (doc.track_operations) {
- frappe.ui.form.trigger("Production Order", 'bom_no')
- }
- else {
- doc.operations =[];
- }
- },
-
show_time_logs: function(doc, cdt, cdn) {
var child = locals[cdt][cdn]
frappe.route_options = {"operation_id": child.name};
@@ -262,7 +251,8 @@
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.json b/erpnext/manufacturing/doctype/production_order/production_order.json
index 75aab99..e07ac5b 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.json
+++ b/erpnext/manufacturing/doctype/production_order/production_order.json
@@ -74,14 +74,6 @@
"permlevel": 0
},
{
- "default": "1",
- "fieldname": "track_operations",
- "fieldtype": "Check",
- "label": "Track Operations",
- "permlevel": 0,
- "precision": ""
- },
- {
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
@@ -215,7 +207,7 @@
"read_only": 1
},
{
- "depends_on": "track_operations",
+ "depends_on": "",
"fieldname": "operations_section",
"fieldtype": "Section Break",
"label": "Operations",
@@ -234,7 +226,7 @@
"read_only": 1
},
{
- "depends_on": "track_operations",
+ "depends_on": "operations",
"fieldname": "section_break_22",
"fieldtype": "Section Break",
"label": "Operation Cost",
@@ -368,7 +360,7 @@
"idx": 1,
"in_create": 0,
"is_submittable": 1,
- "modified": "2015-07-13 05:28:23.259016",
+ "modified": "2015-07-21 07:45:53.206902",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Production Order",
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 93ce5e1..13cc523 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.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
@@ -174,17 +177,12 @@
def set_production_order_operations(self):
"""Fetch operations from BOM and set in 'Production Order'"""
- if not self.bom_no:
+ if not self.bom_no or cint(frappe.db.get_single_value("Manufacturing Settings", "disable_capacity_planning")):
return
self.set('operations', [])
operations = frappe.db.sql("""select operation, description, workstation, idx,
hour_rate, time_in_mins, "Pending" as status from `tabBOM Operation`
where parent = %s order by idx""", self.bom_no, as_dict=1)
- if operations:
- self.track_operations=1
- else:
- self.track_operations=0
- frappe.msgprint(_("Cannot 'track operations' as selected BOM does not have Operations."))
self.set('operations', operations)
self.calculate_time()
@@ -325,10 +323,12 @@
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 34d584a..b91b2e1 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 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 @@
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/patches.txt b/erpnext/patches.txt
index c735507..7629123 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -173,7 +173,6 @@
erpnext.patches.v5_0.update_item_desc_in_invoice
erpnext.patches.v5_1.fix_against_account
erpnext.patches.v5_1.fix_credit_days_based_on
-erpnext.patches.v5_1.track_operations
execute:frappe.rename_doc("DocType", "Salary Manager", "Process Payroll", force=True)
erpnext.patches.v5_1.rename_roles
erpnext.patches.v5_1.default_bom
diff --git a/erpnext/patches/v5_1/track_operations.py b/erpnext/patches/v5_1/track_operations.py
deleted file mode 100644
index 0a12142..0000000
--- a/erpnext/patches/v5_1/track_operations.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import unicode_literals
-
-import frappe
-
-def execute():
- frappe.reload_doctype("Production Order")
- frappe.db.sql("""Update `tabProduction Order` as po set track_operations=1 where
- exists(select name from `tabProduction Order Operation` as po_operation where po_operation.parent = po.name )""")
\ No newline at end of file
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index fb1ec3d..cae0571 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -201,9 +201,7 @@
def check_if_operations_completed(self):
"""Check if Time Logs are completed against before manufacturing to capture operating costs."""
prod_order = frappe.get_doc("Production Order", self.production_order)
- if not prod_order.track_operations:
- return
-
+
for d in prod_order.get("operations"):
total_completed_qty = flt(self.fg_completed_qty) + flt(prod_order.produced_qty)
if total_completed_qty > flt(d.completed_qty):
diff --git a/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js b/erpnext/stock/doctype/stock_reconciliation/stock_reconciliation.js
index c0ae213..f833a25 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.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