diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 3394124980..fdd74e8474 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '9.2.21' +__version__ = '9.2.22' def get_default_company(user=None): '''Get default company for user''' diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 9555d515fb..0fe7f7c04d 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -400,7 +400,8 @@ class calculate_taxes_and_totals(object): for tax in self.doc.get("taxes"): if tax.charge_type == "Actual": - actual_taxes_dict.setdefault(tax.idx, tax.tax_amount) + tax_amount = self.get_tax_amount_if_for_valuation_or_deduction(tax.tax_amount, tax) + actual_taxes_dict.setdefault(tax.idx, tax_amount) elif tax.row_id in actual_taxes_dict: actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100 actual_taxes_dict.setdefault(tax.idx, actual_tax_amount) diff --git a/erpnext/manufacturing/doctype/production_order/production_order.js b/erpnext/manufacturing/doctype/production_order/production_order.js index 48fb7e735d..fb7ced98fa 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.js +++ b/erpnext/manufacturing/doctype/production_order/production_order.js @@ -165,6 +165,7 @@ frappe.ui.form.on("Production Order", { item: frm.doc.production_item, project: frm.doc.project }, + freeze: true, callback: function(r) { if(r.message) { frm.set_value('sales_order', ""); @@ -194,6 +195,7 @@ frappe.ui.form.on("Production Order", { return frm.call({ doc: frm.doc, method: "get_items_and_operations_from_bom", + freeze: true, callback: function(r) { if(r.message["set_scrap_wh_mandatory"]){ frm.toggle_reqd("scrap_warehouse", true); diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 91d7eb6728..7c56d97974 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -44,10 +44,7 @@ class ProductionOrder(Document): validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"]) - if not self.get("required_items"): - self.set_required_items() - else: - self.set_available_qty() + self.set_required_items(reset_only_qty = len(self.get("required_items"))) def validate_sales_order(self): if self.sales_order: @@ -61,6 +58,19 @@ class ProductionOrder(Document): pk_item.item_code=%s ) """, (self.sales_order, self.production_item, self.production_item), as_dict=1) + if not so: + so = frappe.db.sql(""" + select + so.name, so_item.delivery_date, so.project + from + `tabSales Order` so, `tabSales Order Item` so_item, `tabPacked Item` packed_item + where so.name=%s + and so.name=so_item.parent + and so.name=packed_item.parent + and so_item.item_code = packed_item.parent_item + and so.docstatus = 1 and packed_item.item_code=%s + """, (self.sales_order, self.production_item), as_dict=1) + if len(so): if not self.expected_delivery_date: self.expected_delivery_date = so[0].delivery_date @@ -441,21 +451,27 @@ class ProductionOrder(Document): if self.wip_warehouse: d.available_qty_at_wip_warehouse = get_latest_stock_qty(d.item_code, self.wip_warehouse) - def set_required_items(self): + def set_required_items(self, reset_only_qty=False): '''set required_items for production to keep track of reserved qty''' - self.required_items = [] + if not reset_only_qty: + self.required_items = [] + if self.bom_no and self.qty: item_dict = get_bom_items_as_dict(self.bom_no, self.company, qty=self.qty, fetch_exploded = self.use_multi_level_bom) - for item in sorted(item_dict.values(), key=lambda d: d['idx']): - self.append('required_items', { - 'item_code': item.item_code, - 'item_name': item.item_name, - 'description': item.description, - 'required_qty': item.qty, - 'source_warehouse': item.source_warehouse or item.default_warehouse - }) + if reset_only_qty: + for d in self.get("required_items"): + d.required_qty = item_dict.get(d.item_code).get("qty") + else: + for item in sorted(item_dict.values(), key=lambda d: d['idx']): + self.append('required_items', { + 'item_code': item.item_code, + 'item_name': item.item_name, + 'description': item.description, + 'required_qty': item.qty, + 'source_warehouse': item.source_warehouse or item.default_warehouse + }) self.set_available_qty() diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 6a08dbf3ec..580e5faea8 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -535,9 +535,11 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ var actual_taxes_dict = {}; $.each(this.frm.doc["taxes"] || [], function(i, tax) { - if (tax.charge_type == "Actual") - actual_taxes_dict[tax.idx] = tax.tax_amount; - else if (actual_taxes_dict[tax.row_id] !== null) { + if (tax.charge_type == "Actual") { + var tax_amount = (tax.category == "Valuation") ? 0.0 : tax.tax_amount; + tax_amount *= (tax.add_deduct_tax == "Deduct") ? -1.0 : 1.0; + actual_taxes_dict[tax.idx] = tax_amount; + } else if (actual_taxes_dict[tax.row_id] !== null) { var actual_tax_amount = flt(actual_taxes_dict[tax.row_id]) * flt(tax.rate) / 100; actual_taxes_dict[tax.idx] = actual_tax_amount; } diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 573e9d9bec..1c3354c212 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -793,10 +793,15 @@ def make_production_orders(items, sales_order, company, project=None): out = [] for i in items: + if not i.get("bom"): + frappe.throw(_("Please select BOM against item {0}").format(i.get("item_code"))) + if not i.get("pending_qty"): + frappe.throw(_("Please select Qty against item {0}").format(i.get("item_code"))) + production_order = frappe.get_doc(dict( doctype='Production Order', production_item=i['item_code'], - bom_no=i['bom'], + bom_no=i.get('bom'), qty=i['pending_qty'], company=company, sales_order=sales_order, diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 14d6d4225a..40fc44d71d 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -341,7 +341,7 @@ frappe.ui.form.on('Stock Entry Detail', { 'item_code' : d.item_code, 'warehouse' : cstr(d.s_warehouse) || cstr(d.t_warehouse), 'transfer_qty' : d.transfer_qty, - 'serial_no ' : d.serial_no, + 'serial_no' : d.serial_no, 'bom_no' : d.bom_no, 'expense_account' : d.expense_account, 'cost_center' : d.cost_center,