From 5e3f5d8bcce20566099406586dc5e7929d39fd68 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 17 Jan 2022 22:15:12 +0530 Subject: [PATCH 1/4] fix: purchase to Stock UOM conversion on Production Plan #28570 (#29325) fix: purchase to Stock UOM conversion on Production Plan (cherry picked from commit 9cd26fbb6a0e5977c35774dc641728beb7b0d655) Co-authored-by: Maxwell Morais --- .../doctype/production_plan/production_plan.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index a63ed999e44..a78bd1f9e66 100644 --- a/erpnext/manufacturing/doctype/production_plan/production_plan.py +++ b/erpnext/manufacturing/doctype/production_plan/production_plan.py @@ -970,7 +970,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() From d5d7f67ac24089b8453f1d40773ece84f3f568a3 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 17 Jan 2022 22:16:41 +0530 Subject: [PATCH 2/4] fix: cover case when all material needs to be bought (#29326) (#29327) When material request is to be made for purchase qty should be converted to purchase UOM (cherry picked from commit 48f3d535561efd4d2f3d7b0e38c00d23c68cc517) Co-authored-by: Ankush Menat --- .../doctype/production_plan/production_plan.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/erpnext/manufacturing/doctype/production_plan/production_plan.py b/erpnext/manufacturing/doctype/production_plan/production_plan.py index a78bd1f9e66..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 @@ -971,8 +967,8 @@ def get_materials_from_other_locations(item, warehouses, new_mr_items, company): if required_qty: stock_uom, purchase_uom = frappe.db.get_value( - 'Item', - item['item_code'], + 'Item', + item['item_code'], ['stock_uom', 'purchase_uom'] ) From d7f16c4924642ff60b223eaf2fdfdd374b266c05 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 18 Jan 2022 11:17:32 +0530 Subject: [PATCH 3/4] refactor: convert CTE validation to python (#29324) Some old servers running on mariadb <10.2 can't work with CTEs hence reverting to basic python code Co-authored-by: Ankush Menat --- erpnext/stock/stock_ledger.py | 41 ++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) 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 From 69fded250c9dfb3e82f670a405ef5416c799b185 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 18 Jan 2022 13:33:29 +0530 Subject: [PATCH 4/4] fix: enable allow negative stock by default in reposts (#29331) (#29333) Negative stock validation is done BEFORE reposting as such it's not required to be performed again and most likely this fails on old intermediate data where user has no clue why it failed. (cherry picked from commit fabe0bce15b3bb1941316072304b244161de3a3e) Co-authored-by: Ankush Menat --- .../repost_item_valuation/repost_item_valuation.json | 11 ++++++----- .../repost_item_valuation/repost_item_valuation.py | 3 +-- 2 files changed, 7 insertions(+), 7 deletions(-) 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":