diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index a63ed999e44..e903e9baf84 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -948,10 +948,6 @@ def get_materials_from_other_locations(item, warehouses, new_mr_items, company): locations = get_available_item_locations(item.get("item_code"), warehouses, item.get("quantity"), company, ignore_validation=True) - if not locations: - new_mr_items.append(item) - return - required_qty = item.get("quantity") for d in locations: if required_qty <=0: return @@ -970,7 +966,25 @@ def get_materials_from_other_locations(item, warehouses, new_mr_items, company): new_mr_items.append(new_dict) if required_qty: + stock_uom, purchase_uom = frappe.db.get_value( + 'Item', + item['item_code'], + ['stock_uom', 'purchase_uom'] + ) + + if purchase_uom != stock_uom and purchase_uom == item['uom']: + conversion_factor = get_uom_conversion_factor(item['item_code'], item['uom']) + if not (conversion_factor or frappe.flags.show_qty_in_stock_uom): + frappe.throw(_("UOM Conversion factor ({0} -> {1}) not found for item: {2}") + .format(purchase_uom, stock_uom, item['item_code'])) + + required_qty = required_qty / conversion_factor + + if frappe.db.get_value("UOM", purchase_uom, "must_be_whole_number"): + required_qty = ceil(required_qty) + item["quantity"] = required_qty + new_mr_items.append(item) @frappe.whitelist() diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json index cd7e63b18b2..0ba97d59a14 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.json @@ -1,7 +1,7 @@ { "actions": [], "autoname": "REPOST-ITEM-VAL-.######", - "creation": "2020-10-22 22:27:07.742161", + "creation": "2022-01-11 15:03:38.273179", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", @@ -129,7 +129,7 @@ "reqd": 1 }, { - "default": "0", + "default": "1", "fieldname": "allow_negative_stock", "fieldtype": "Check", "label": "Allow Negative Stock" @@ -177,7 +177,7 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], - "modified": "2021-11-24 02:18:10.524560", + "modified": "2022-01-18 10:57:33.450907", "modified_by": "Administrator", "module": "Stock", "name": "Repost Item Valuation", @@ -227,5 +227,6 @@ } ], "sort_field": "modified", - "sort_order": "DESC" -} + "sort_order": "DESC", + "states": [] +} \ No newline at end of file diff --git a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py index 5ad8f443203..3b76301b4cc 100644 --- a/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py +++ b/erpnext/stock/doctype/repost_item_valuation/repost_item_valuation.py @@ -27,8 +27,7 @@ class RepostItemValuation(Document): self.item_code = None self.warehouse = None - self.allow_negative_stock = self.allow_negative_stock or \ - cint(frappe.db.get_single_value("Stock Settings", "allow_negative_stock")) + self.allow_negative_stock = 1 def set_company(self): if self.based_on == "Transaction": diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index f43d82d8b59..b47097553ba 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -7,7 +7,7 @@ import json import frappe from frappe import _ from frappe.model.meta import get_field_precision -from frappe.utils import cint, cstr, flt, get_link_to_form, getdate, now, nowdate +from frappe.utils import cint, cstr, flt, get_datetime, get_link_to_form, getdate, now, nowdate from six import iteritems import erpnext @@ -1139,26 +1139,31 @@ def get_future_sle_with_negative_qty(args): def get_future_sle_with_negative_batch_qty(args): - return frappe.db.sql(""" - with batch_ledger as ( - select - posting_date, posting_time, voucher_type, voucher_no, - sum(actual_qty) over (order by posting_date, posting_time, creation) as cumulative_total - from `tabStock Ledger Entry` - where - item_code = %(item_code)s - and warehouse = %(warehouse)s - and batch_no=%(batch_no)s - and is_cancelled = 0 - order by posting_date, posting_time, creation - ) - select * from batch_ledger + batch_ledger = frappe.db.sql(""" + select + posting_date, posting_time, voucher_type, voucher_no, actual_qty + from `tabStock Ledger Entry` where - cumulative_total < 0.0 - and timestamp(posting_date, posting_time) >= timestamp(%(posting_date)s, %(posting_time)s) - limit 1 + item_code = %(item_code)s + and warehouse = %(warehouse)s + and batch_no=%(batch_no)s + and is_cancelled = 0 + order by timestamp(posting_date, posting_time), creation """, args, as_dict=1) + cumulative_total = 0.0 + current_posting_datetime = get_datetime(str(args.posting_date) + " " + str(args.posting_time)) + for entry in batch_ledger: + cumulative_total += entry.actual_qty + if cumulative_total > -1e-6: + continue + + if (get_datetime(str(entry.posting_date) + " " + str(entry.posting_time)) + >= current_posting_datetime): + + entry.cumulative_total = cumulative_total + return [entry] + def _round_off_if_near_zero(number: float, precision: int = 6) -> float: """ Rounds off the number to zero only if number is close to zero for decimal