Anand Doshi | 885e074 | 2015-03-03 14:55:30 +0530 | [diff] [blame] | 1 | # Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 2 | # License: GNU General Public License v3. See license.txt |
| 3 | |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 4 | |
Rushabh Mehta | 793ba6b | 2014-02-14 15:47:51 +0530 | [diff] [blame] | 5 | import frappe |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 6 | from frappe.query_builder import DocType |
| 7 | from frappe.query_builder.functions import Sum |
| 8 | from frappe.query_builder.utils import Table |
Ankush Menat | 77be982 | 2022-02-11 11:29:37 +0530 | [diff] [blame] | 9 | from frappe.utils import cstr, flt, now, nowdate, nowtime |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 10 | from pypika.queries import QueryBuilder |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 11 | |
Nabin Hait | a77b8c9 | 2020-12-21 14:45:50 +0530 | [diff] [blame] | 12 | from erpnext.controllers.stock_controller import create_repost_item_valuation_entry |
Chillar Anand | 915b343 | 2021-09-02 16:44:59 +0530 | [diff] [blame] | 13 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 14 | |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 15 | def repost(only_actual=False, allow_negative_stock=False, allow_zero_rate=False, only_bin=False): |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 16 | """ |
| 17 | Repost everything! |
| 18 | """ |
Anand Doshi | e9baaa6 | 2014-02-26 12:35:33 +0530 | [diff] [blame] | 19 | frappe.db.auto_commit_on_many_writes = 1 |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 20 | |
Nabin Hait | ca471f4 | 2013-11-20 13:14:12 +0530 | [diff] [blame] | 21 | if allow_negative_stock: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 22 | existing_allow_negative_stock = frappe.db.get_value( |
| 23 | "Stock Settings", None, "allow_negative_stock" |
| 24 | ) |
Nabin Hait | 249bbbc | 2014-11-26 15:35:08 +0530 | [diff] [blame] | 25 | frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 26 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 27 | item_warehouses = frappe.db.sql( |
| 28 | """ |
Nabin Hait | 001edb4 | 2019-09-26 16:44:35 +0530 | [diff] [blame] | 29 | select distinct item_code, warehouse |
| 30 | from |
| 31 | (select item_code, warehouse from tabBin |
| 32 | union |
| 33 | select item_code, warehouse from `tabStock Ledger Entry`) a |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 34 | """ |
| 35 | ) |
Nabin Hait | 001edb4 | 2019-09-26 16:44:35 +0530 | [diff] [blame] | 36 | for d in item_warehouses: |
| 37 | try: |
| 38 | repost_stock(d[0], d[1], allow_zero_rate, only_actual, only_bin, allow_negative_stock) |
| 39 | frappe.db.commit() |
Ankush Menat | 694ae81 | 2021-09-01 14:40:56 +0530 | [diff] [blame] | 40 | except Exception: |
Nabin Hait | 001edb4 | 2019-09-26 16:44:35 +0530 | [diff] [blame] | 41 | frappe.db.rollback() |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 42 | |
Nabin Hait | ca471f4 | 2013-11-20 13:14:12 +0530 | [diff] [blame] | 43 | if allow_negative_stock: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 44 | frappe.db.set_value( |
| 45 | "Stock Settings", None, "allow_negative_stock", existing_allow_negative_stock |
| 46 | ) |
Anand Doshi | e9baaa6 | 2014-02-26 12:35:33 +0530 | [diff] [blame] | 47 | frappe.db.auto_commit_on_many_writes = 0 |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 48 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 49 | |
| 50 | def repost_stock( |
| 51 | item_code, |
| 52 | warehouse, |
| 53 | allow_zero_rate=False, |
| 54 | only_actual=False, |
| 55 | only_bin=False, |
| 56 | allow_negative_stock=False, |
| 57 | ): |
Nabin Hait | 001edb4 | 2019-09-26 16:44:35 +0530 | [diff] [blame] | 58 | |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 59 | if not only_bin: |
Nabin Hait | 001edb4 | 2019-09-26 16:44:35 +0530 | [diff] [blame] | 60 | repost_actual_qty(item_code, warehouse, allow_zero_rate, allow_negative_stock) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 61 | |
Nabin Hait | 2348a5f | 2014-10-15 15:31:33 +0530 | [diff] [blame] | 62 | if item_code and warehouse and not only_actual: |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 63 | qty_dict = { |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 64 | "reserved_qty": get_reserved_qty(item_code, warehouse), |
| 65 | "indented_qty": get_indented_qty(item_code, warehouse), |
| 66 | "ordered_qty": get_ordered_qty(item_code, warehouse), |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 67 | "planned_qty": get_planned_qty(item_code, warehouse), |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 68 | } |
| 69 | if only_bin: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 70 | qty_dict.update({"actual_qty": get_balance_qty_from_sle(item_code, warehouse)}) |
Rushabh Mehta | c4d4c7f | 2015-10-14 17:37:28 +0530 | [diff] [blame] | 71 | |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 72 | update_bin_qty(item_code, warehouse, qty_dict) |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 73 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 74 | |
Deepesh Garg | 2a9c5ba | 2020-04-30 10:38:58 +0530 | [diff] [blame] | 75 | def repost_actual_qty(item_code, warehouse, allow_zero_rate=False, allow_negative_stock=False): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 76 | create_repost_item_valuation_entry( |
| 77 | { |
| 78 | "item_code": item_code, |
| 79 | "warehouse": warehouse, |
| 80 | "posting_date": "1900-01-01", |
| 81 | "posting_time": "00:01", |
| 82 | "allow_negative_stock": allow_negative_stock, |
| 83 | "allow_zero_rate": allow_zero_rate, |
| 84 | } |
| 85 | ) |
| 86 | |
Rushabh Mehta | c4d4c7f | 2015-10-14 17:37:28 +0530 | [diff] [blame] | 87 | |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 88 | def get_balance_qty_from_sle(item_code, warehouse): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 89 | balance_qty = frappe.db.sql( |
| 90 | """select qty_after_transaction from `tabStock Ledger Entry` |
Nabin Hait | a77b8c9 | 2020-12-21 14:45:50 +0530 | [diff] [blame] | 91 | where item_code=%s and warehouse=%s and is_cancelled=0 |
Aditya Hase | 0c16424 | 2019-01-07 22:07:13 +0530 | [diff] [blame] | 92 | order by posting_date desc, posting_time desc, creation desc |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 93 | limit 1""", |
| 94 | (item_code, warehouse), |
| 95 | ) |
Rushabh Mehta | c4d4c7f | 2015-10-14 17:37:28 +0530 | [diff] [blame] | 96 | |
Nabin Hait | b7e46c4 | 2015-10-12 16:46:29 +0530 | [diff] [blame] | 97 | return flt(balance_qty[0][0]) if balance_qty else 0.0 |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 98 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 99 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 100 | def get_reserved_qty(item_code, warehouse): |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 101 | def append_open_so_query(q: QueryBuilder, child_table: Table) -> QueryBuilder: |
| 102 | return ( |
| 103 | q.inner_join(SalesOrder) |
| 104 | .on(SalesOrder.name == child_table.parent) |
| 105 | .where(SalesOrder.docstatus == 1) |
| 106 | .where(SalesOrder.status != "Closed") |
| 107 | ) |
| 108 | |
Devin Slauenwhite | 494bbf0 | 2022-06-17 13:51:33 -0400 | [diff] [blame] | 109 | SalesOrder = DocType("Sales Order") |
| 110 | SalesOrderItem = DocType("Sales Order Item") |
| 111 | PackedItem = DocType("Packed Item") |
| 112 | |
| 113 | dont_reserve_qty_on_sales_return = frappe.db.get_single_value( |
| 114 | "Selling Settings", "dont_reserve_sales_order_qty_on_sales_return" |
| 115 | ) |
| 116 | |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 117 | tab = ( |
| 118 | frappe.qb.from_(SalesOrderItem) |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 119 | .where(SalesOrderItem.item_code == item_code) |
| 120 | .where(SalesOrderItem.warehouse == warehouse) |
| 121 | ) |
Devin Slauenwhite | 494bbf0 | 2022-06-17 13:51:33 -0400 | [diff] [blame] | 122 | for field, cond in [ |
| 123 | (SalesOrderItem.stock_qty.as_("dnpi_qty"), 1), |
| 124 | (SalesOrderItem.qty.as_("so_item_qty"), 1), |
| 125 | (SalesOrderItem.delivered_qty.as_("so_item_delivered_qty"), 1), |
| 126 | (SalesOrderItem.returned_qty.as_("so_item_returned_qty"), dont_reserve_qty_on_sales_return), |
| 127 | (SalesOrderItem.parent, 1), |
| 128 | (SalesOrderItem.name, 1), |
| 129 | ]: |
| 130 | if cond: |
| 131 | tab = tab.select(field) |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 132 | tab = append_open_so_query(tab, SalesOrderItem) |
| 133 | |
| 134 | dnpi = ( |
| 135 | frappe.qb.from_(PackedItem) |
| 136 | .select(PackedItem.qty, PackedItem.parent_detail_docname, PackedItem.parent, PackedItem.name) |
| 137 | .where(PackedItem.item_code == item_code) |
| 138 | .where(PackedItem.warehouse == warehouse) |
| 139 | ) |
Devin Slauenwhite | 591b591 | 2022-06-17 15:27:17 -0400 | [diff] [blame^] | 140 | dnpi = append_open_so_query(dnpi, PackedItem) |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 141 | |
Devin Slauenwhite | 494bbf0 | 2022-06-17 13:51:33 -0400 | [diff] [blame] | 142 | dnpi_parent = frappe.qb.from_(dnpi).select(dnpi.qty.as_("dnpi_qty")) |
| 143 | for key, so_item_field, cond in [ |
| 144 | ("so_item_qty", "qty", 1), |
| 145 | ("so_item_delivered_qty", "delivered_qty", 1), |
| 146 | ("so_item_returned_qty", "returned_qty", dont_reserve_qty_on_sales_return), |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 147 | ]: |
Devin Slauenwhite | 494bbf0 | 2022-06-17 13:51:33 -0400 | [diff] [blame] | 148 | if cond: |
| 149 | dnpi_parent = dnpi_parent.select( |
| 150 | ( |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 151 | frappe.qb.from_(SalesOrderItem) |
| 152 | .select(SalesOrderItem[so_item_field]) |
| 153 | .where(SalesOrderItem.name == dnpi.parent_detail_docname) |
| 154 | .where(SalesOrderItem.delivered_by_supplier == 0) |
Devin Slauenwhite | 494bbf0 | 2022-06-17 13:51:33 -0400 | [diff] [blame] | 155 | ).as_(key) |
| 156 | ) |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 157 | dnpi_parent = dnpi_parent.select(dnpi.parent, dnpi.name) |
| 158 | |
| 159 | dnpi_parent = dnpi_parent + tab |
| 160 | |
| 161 | q = ( |
| 162 | frappe.qb.from_(dnpi_parent) |
| 163 | .select( |
| 164 | Sum( |
| 165 | dnpi_parent.dnpi_qty |
| 166 | * ( |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 167 | ( |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 168 | dnpi_parent.so_item_qty |
| 169 | - dnpi_parent.so_item_delivered_qty |
Devin Slauenwhite | 494bbf0 | 2022-06-17 13:51:33 -0400 | [diff] [blame] | 170 | - (dnpi_parent.so_item_returned_qty if dont_reserve_qty_on_sales_return else 0) |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 171 | ) |
| 172 | / dnpi_parent.so_item_qty |
| 173 | ) |
| 174 | ) |
| 175 | ) |
| 176 | .where(dnpi_parent.so_item_qty >= dnpi_parent.so_item_delivered_qty) |
Devin Slauenwhite | 0328874 | 2022-06-17 14:45:33 -0400 | [diff] [blame] | 177 | ) |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 178 | |
Devin Slauenwhite | f3f26d2 | 2022-06-17 11:51:21 -0400 | [diff] [blame] | 179 | reserved_qty = q.run() |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 180 | return flt(reserved_qty[0][0]) if reserved_qty else 0 |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 181 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 182 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 183 | def get_indented_qty(item_code, warehouse): |
Nabin Hait | 7eaa7f2 | 2020-04-17 10:52:28 +0530 | [diff] [blame] | 184 | # Ordered Qty is always maintained in stock UOM |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 185 | inward_qty = frappe.db.sql( |
| 186 | """ |
Nabin Hait | 03af029 | 2020-04-16 20:11:32 +0530 | [diff] [blame] | 187 | select sum(mr_item.stock_qty - mr_item.ordered_qty) |
Nabin Hait | 4acd431 | 2014-11-04 15:32:31 +0530 | [diff] [blame] | 188 | from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr |
| 189 | where mr_item.item_code=%s and mr_item.warehouse=%s |
Nabin Hait | 7eaa7f2 | 2020-04-17 10:52:28 +0530 | [diff] [blame] | 190 | and mr.material_request_type in ('Purchase', 'Manufacture', 'Customer Provided', 'Material Transfer') |
Nabin Hait | 03af029 | 2020-04-16 20:11:32 +0530 | [diff] [blame] | 191 | and mr_item.stock_qty > mr_item.ordered_qty and mr_item.parent=mr.name |
| 192 | and mr.status!='Stopped' and mr.docstatus=1 |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 193 | """, |
| 194 | (item_code, warehouse), |
| 195 | ) |
Nabin Hait | 7eaa7f2 | 2020-04-17 10:52:28 +0530 | [diff] [blame] | 196 | inward_qty = flt(inward_qty[0][0]) if inward_qty else 0 |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 197 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 198 | outward_qty = frappe.db.sql( |
| 199 | """ |
Nabin Hait | 03af029 | 2020-04-16 20:11:32 +0530 | [diff] [blame] | 200 | select sum(mr_item.stock_qty - mr_item.ordered_qty) |
| 201 | from `tabMaterial Request Item` mr_item, `tabMaterial Request` mr |
| 202 | where mr_item.item_code=%s and mr_item.warehouse=%s |
Nabin Hait | 7eaa7f2 | 2020-04-17 10:52:28 +0530 | [diff] [blame] | 203 | and mr.material_request_type = 'Material Issue' |
Nabin Hait | 03af029 | 2020-04-16 20:11:32 +0530 | [diff] [blame] | 204 | and mr_item.stock_qty > mr_item.ordered_qty and mr_item.parent=mr.name |
| 205 | and mr.status!='Stopped' and mr.docstatus=1 |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 206 | """, |
| 207 | (item_code, warehouse), |
| 208 | ) |
Nabin Hait | 7eaa7f2 | 2020-04-17 10:52:28 +0530 | [diff] [blame] | 209 | outward_qty = flt(outward_qty[0][0]) if outward_qty else 0 |
marination | 815c36a | 2020-03-26 14:49:28 +0530 | [diff] [blame] | 210 | |
Nabin Hait | 7eaa7f2 | 2020-04-17 10:52:28 +0530 | [diff] [blame] | 211 | requested_qty = inward_qty - outward_qty |
Nabin Hait | 03af029 | 2020-04-16 20:11:32 +0530 | [diff] [blame] | 212 | |
| 213 | return requested_qty |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 214 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 215 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 216 | def get_ordered_qty(item_code, warehouse): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 217 | ordered_qty = frappe.db.sql( |
| 218 | """ |
Anand Doshi | 602e825 | 2015-11-16 19:05:46 +0530 | [diff] [blame] | 219 | select sum((po_item.qty - po_item.received_qty)*po_item.conversion_factor) |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 220 | from `tabPurchase Order Item` po_item, `tabPurchase Order` po |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 221 | where po_item.item_code=%s and po_item.warehouse=%s |
Anand Doshi | 602e825 | 2015-11-16 19:05:46 +0530 | [diff] [blame] | 222 | and po_item.qty > po_item.received_qty and po_item.parent=po.name |
patilsangram | bf2b511 | 2016-02-22 16:24:23 +0530 | [diff] [blame] | 223 | and po.status not in ('Closed', 'Delivered') and po.docstatus=1 |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 224 | and po_item.delivered_by_supplier = 0""", |
| 225 | (item_code, warehouse), |
| 226 | ) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 227 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 228 | return flt(ordered_qty[0][0]) if ordered_qty else 0 |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 229 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 230 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 231 | def get_planned_qty(item_code, warehouse): |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 232 | planned_qty = frappe.db.sql( |
| 233 | """ |
Zarrar | 13ddc7e | 2018-03-20 12:38:43 +0530 | [diff] [blame] | 234 | select sum(qty - produced_qty) from `tabWork Order` |
Conor | 74a782d | 2022-06-17 06:31:27 -0500 | [diff] [blame] | 235 | where production_item = %s and fg_warehouse = %s and status not in ('Stopped', 'Completed', 'Closed') |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 236 | and docstatus=1 and qty > produced_qty""", |
| 237 | (item_code, warehouse), |
| 238 | ) |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 239 | |
| 240 | return flt(planned_qty[0][0]) if planned_qty else 0 |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 241 | |
| 242 | |
Nabin Hait | 7f3f2a0 | 2014-09-01 18:16:05 +0530 | [diff] [blame] | 243 | def update_bin_qty(item_code, warehouse, qty_dict=None): |
Rushabh Mehta | 1f84799 | 2013-12-12 19:12:19 +0530 | [diff] [blame] | 244 | from erpnext.stock.utils import get_bin |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 245 | |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 246 | bin = get_bin(item_code, warehouse) |
| 247 | mismatch = False |
marination | 815c36a | 2020-03-26 14:49:28 +0530 | [diff] [blame] | 248 | for field, value in qty_dict.items(): |
| 249 | if flt(bin.get(field)) != flt(value): |
| 250 | bin.set(field, flt(value)) |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 251 | mismatch = True |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 252 | |
Ankush Menat | 77be982 | 2022-02-11 11:29:37 +0530 | [diff] [blame] | 253 | bin.modified = now() |
Nabin Hait | eea2b34 | 2013-10-11 18:31:33 +0530 | [diff] [blame] | 254 | if mismatch: |
Himanshu Mishra | f56aac6 | 2018-08-08 18:32:03 +0530 | [diff] [blame] | 255 | bin.set_projected_qty() |
| 256 | bin.db_update() |
| 257 | bin.clear_cache() |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 258 | |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 259 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 260 | def set_stock_balance_as_per_serial_no( |
| 261 | item_code=None, posting_date=None, posting_time=None, fiscal_year=None |
| 262 | ): |
| 263 | if not posting_date: |
| 264 | posting_date = nowdate() |
| 265 | if not posting_time: |
| 266 | posting_time = nowtime() |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 267 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 268 | condition = " and item.name='%s'" % item_code.replace("'", "'") if item_code else "" |
| 269 | |
| 270 | bin = frappe.db.sql( |
| 271 | """select bin.item_code, bin.warehouse, bin.actual_qty, item.stock_uom |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 272 | from `tabBin` bin, tabItem item |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 273 | where bin.item_code = item.name and item.has_serial_no = 1 %s""" |
| 274 | % condition |
| 275 | ) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 276 | |
| 277 | for d in bin: |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 278 | serial_nos = frappe.db.sql( |
| 279 | """select count(name) from `tabSerial No` |
| 280 | where item_code=%s and warehouse=%s and docstatus < 2""", |
| 281 | (d[0], d[1]), |
| 282 | ) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 283 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 284 | sle = frappe.db.sql( |
| 285 | """select valuation_rate, company from `tabStock Ledger Entry` |
Nabin Hait | a77b8c9 | 2020-12-21 14:45:50 +0530 | [diff] [blame] | 286 | where item_code = %s and warehouse = %s and is_cancelled = 0 |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 287 | order by posting_date desc limit 1""", |
| 288 | (d[0], d[1]), |
| 289 | ) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 290 | |
| 291 | sle_dict = { |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 292 | "doctype": "Stock Ledger Entry", |
| 293 | "item_code": d[0], |
| 294 | "warehouse": d[1], |
| 295 | "transaction_date": nowdate(), |
| 296 | "posting_date": posting_date, |
| 297 | "posting_time": posting_time, |
| 298 | "voucher_type": "Stock Reconciliation (Manual)", |
| 299 | "voucher_no": "", |
| 300 | "voucher_detail_no": "", |
| 301 | "actual_qty": flt(serial_nos[0][0]) - flt(d[2]), |
| 302 | "stock_uom": d[3], |
| 303 | "incoming_rate": sle and flt(serial_nos[0][0]) > flt(d[2]) and flt(sle[0][0]) or 0, |
| 304 | "company": sle and cstr(sle[0][1]) or 0, |
| 305 | "batch_no": "", |
| 306 | "serial_no": "", |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 307 | } |
| 308 | |
| 309 | sle_doc = frappe.get_doc(sle_dict) |
Anand Doshi | 6dfd430 | 2015-02-10 14:41:27 +0530 | [diff] [blame] | 310 | sle_doc.flags.ignore_validate = True |
| 311 | sle_doc.flags.ignore_links = True |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 312 | sle_doc.insert() |
| 313 | |
| 314 | args = sle_dict.copy() |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 315 | args.update({"sle_id": sle_doc.name}) |
Nabin Hait | 6298536 | 2014-04-04 12:05:16 +0530 | [diff] [blame] | 316 | |
Ankush Menat | 494bd9e | 2022-03-28 18:52:46 +0530 | [diff] [blame] | 317 | create_repost_item_valuation_entry( |
| 318 | { |
| 319 | "item_code": d[0], |
| 320 | "warehouse": d[1], |
| 321 | "posting_date": posting_date, |
| 322 | "posting_time": posting_time, |
| 323 | } |
| 324 | ) |
| 325 | |
nabinhait | 5c38488 | 2014-07-14 11:43:00 +0530 | [diff] [blame] | 326 | |
nabinhait | 7700c62 | 2014-07-14 14:21:21 +0530 | [diff] [blame] | 327 | def reset_serial_no_status_and_warehouse(serial_nos=None): |
nabinhait | 5c38488 | 2014-07-14 11:43:00 +0530 | [diff] [blame] | 328 | if not serial_nos: |
Nabin Hait | c865f22 | 2015-09-21 09:18:43 +0530 | [diff] [blame] | 329 | serial_nos = frappe.db.sql_list("""select name from `tabSerial No` where docstatus = 0""") |
nabinhait | 5c38488 | 2014-07-14 11:43:00 +0530 | [diff] [blame] | 330 | for serial_no in serial_nos: |
| 331 | try: |
| 332 | sr = frappe.get_doc("Serial No", serial_no) |
nabinhait | b0a8d00 | 2014-07-14 11:56:03 +0530 | [diff] [blame] | 333 | last_sle = sr.get_last_sle() |
| 334 | if flt(last_sle.actual_qty) > 0: |
| 335 | sr.warehouse = last_sle.warehouse |
Nabin Hait | 7f3f2a0 | 2014-09-01 18:16:05 +0530 | [diff] [blame] | 336 | |
nabinhait | 5c38488 | 2014-07-14 11:43:00 +0530 | [diff] [blame] | 337 | sr.via_stock_ledger = True |
| 338 | sr.save() |
Ankush Menat | 694ae81 | 2021-09-01 14:40:56 +0530 | [diff] [blame] | 339 | except Exception: |
nabinhait | 5c38488 | 2014-07-14 11:43:00 +0530 | [diff] [blame] | 340 | pass |