blob: bc53878fb926375bae4ec41dc2ab9706654dcea7 [file] [log] [blame]
Rohit Waghchauree6143ab2023-03-13 14:51:43 +05301import frappe
2from frappe.query_builder.functions import CombineDatetime, Sum
3from frappe.utils import flt
Rohit Waghchaurec1132d12023-03-24 10:14:09 +05304from frappe.utils.deprecations import deprecated
Rohit Waghchauref4cfc582023-04-11 13:22:15 +05305from pypika import Order
Rohit Waghchauree6143ab2023-03-13 14:51:43 +05306
7
8class DeprecatedSerialNoValuation:
Rohit Waghchaurec1132d12023-03-24 10:14:09 +05309 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053010 def calculate_stock_value_from_deprecarated_ledgers(self):
rohitwaghchaurea5232d92024-03-01 22:26:54 +053011 if not frappe.db.get_value(
12 "Stock Ledger Entry", {"serial_no": ("is", "set"), "is_cancelled": 0}, "name"
13 ):
14 return
15
rohitwaghchaure63792382024-03-04 12:04:41 +053016 serial_nos = self.get_filterd_serial_nos()
17 if not serial_nos:
18 return
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053019
20 actual_qty = flt(self.sle.actual_qty)
21
22 stock_value_change = 0
23 if actual_qty < 0:
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053024 if not self.sle.is_cancelled:
25 outgoing_value = self.get_incoming_value_for_serial_nos(serial_nos)
26 stock_value_change = -1 * outgoing_value
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053027
28 self.stock_value_change += stock_value_change
29
rohitwaghchaure63792382024-03-04 12:04:41 +053030 def get_filterd_serial_nos(self):
31 serial_nos = []
32 non_filtered_serial_nos = self.get_serial_nos()
33
34 # If the serial no inwarded using the Serial and Batch Bundle, then the serial no should not be considered
35 for serial_no in non_filtered_serial_nos:
36 if serial_no and serial_no not in self.serial_no_incoming_rate:
37 serial_nos.append(serial_no)
38
39 return serial_nos
40
Rohit Waghchaurec1132d12023-03-24 10:14:09 +053041 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053042 def get_incoming_value_for_serial_nos(self, serial_nos):
rohitwaghchaure63792382024-03-04 12:04:41 +053043 from erpnext.stock.utils import get_combine_datetime
44
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053045 # get rate from serial nos within same company
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053046 incoming_values = 0.0
rohitwaghchaurea5232d92024-03-01 22:26:54 +053047 for serial_no in serial_nos:
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053048 table = frappe.qb.DocType("Stock Ledger Entry")
rohitwaghchaurea5232d92024-03-01 22:26:54 +053049 stock_ledgers = (
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053050 frappe.qb.from_(table)
rohitwaghchaurea5232d92024-03-01 22:26:54 +053051 .select(table.incoming_rate, table.actual_qty, table.stock_value_difference)
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053052 .where(
53 (
54 (table.serial_no == serial_no)
55 | (table.serial_no.like(serial_no + "\n%"))
56 | (table.serial_no.like("%\n" + serial_no))
57 | (table.serial_no.like("%\n" + serial_no + "\n%"))
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053058 )
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053059 & (table.company == self.sle.company)
rohitwaghchaure63792382024-03-04 12:04:41 +053060 & (table.warehouse == self.sle.warehouse)
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053061 & (table.serial_and_batch_bundle.isnull())
rohitwaghchaure63792382024-03-04 12:04:41 +053062 & (table.actual_qty > 0)
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053063 & (table.is_cancelled == 0)
rohitwaghchaure63792382024-03-04 12:04:41 +053064 & table.posting_datetime
65 <= get_combine_datetime(self.sle.posting_date, self.sle.posting_time)
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053066 )
rohitwaghchaurea5232d92024-03-01 22:26:54 +053067 .orderby(table.posting_datetime, order=Order.desc)
rohitwaghchaure63792382024-03-04 12:04:41 +053068 .limit(1)
rohitwaghchaurea5232d92024-03-01 22:26:54 +053069 ).run(as_dict=1)
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053070
rohitwaghchaurea5232d92024-03-01 22:26:54 +053071 for sle in stock_ledgers:
rohitwaghchaure63792382024-03-04 12:04:41 +053072 self.serial_no_incoming_rate[serial_no] += flt(sle.incoming_rate)
rohitwaghchaurea5232d92024-03-01 22:26:54 +053073 incoming_values += self.serial_no_incoming_rate[serial_no]
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053074
75 return incoming_values
76
77
78class DeprecatedBatchNoValuation:
Rohit Waghchaurec1132d12023-03-24 10:14:09 +053079 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053080 def calculate_avg_rate_from_deprecarated_ledgers(self):
Rohit Waghchaure5bb31732023-03-21 10:54:41 +053081 entries = self.get_sle_for_batches()
82 for ledger in entries:
Rohit Waghchauref704eb72023-03-30 11:32:39 +053083 self.stock_value_differece[ledger.batch_no] += flt(ledger.batch_value)
Rohit Waghchaure86da3062023-03-20 14:15:34 +053084 self.available_qty[ledger.batch_no] += flt(ledger.batch_qty)
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053085
Rohit Waghchaurec1132d12023-03-24 10:14:09 +053086 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053087 def get_sle_for_batches(self):
Rohit Waghchauref704eb72023-03-30 11:32:39 +053088 if not self.batchwise_valuation_batches:
89 return []
90
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053091 sle = frappe.qb.DocType("Stock Ledger Entry")
92
93 timestamp_condition = CombineDatetime(sle.posting_date, sle.posting_time) < CombineDatetime(
94 self.sle.posting_date, self.sle.posting_time
95 )
96 if self.sle.creation:
97 timestamp_condition |= (
98 CombineDatetime(sle.posting_date, sle.posting_time)
99 == CombineDatetime(self.sle.posting_date, self.sle.posting_time)
100 ) & (sle.creation < self.sle.creation)
101
Rohit Waghchaurec2d74612023-03-29 11:40:36 +0530102 query = (
Rohit Waghchauree6143ab2023-03-13 14:51:43 +0530103 frappe.qb.from_(sle)
104 .select(
105 sle.batch_no,
106 Sum(sle.stock_value_difference).as_("batch_value"),
107 Sum(sle.actual_qty).as_("batch_qty"),
108 )
109 .where(
110 (sle.item_code == self.sle.item_code)
Rohit Waghchauree6143ab2023-03-13 14:51:43 +0530111 & (sle.warehouse == self.sle.warehouse)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530112 & (sle.batch_no.isin(self.batchwise_valuation_batches))
113 & (sle.batch_no.isnotnull())
Rohit Waghchauree6143ab2023-03-13 14:51:43 +0530114 & (sle.is_cancelled == 0)
115 )
116 .where(timestamp_condition)
117 .groupby(sle.batch_no)
Rohit Waghchaurec2d74612023-03-29 11:40:36 +0530118 )
119
120 if self.sle.name:
121 query = query.where(sle.name != self.sle.name)
122
123 return query.run(as_dict=True)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530124
125 @deprecated
126 def calculate_avg_rate_for_non_batchwise_valuation(self):
127 if not self.non_batchwise_valuation_batches:
128 return
129
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530130 self.non_batchwise_balance_value = 0.0
131 self.non_batchwise_balance_qty = 0.0
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530132
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530133 self.set_balance_value_for_non_batchwise_valuation_batches()
134
135 for batch_no, ledger in self.batch_nos.items():
136 if batch_no not in self.non_batchwise_valuation_batches:
137 continue
138
Rohit Waghchauref968f0f2023-06-14 23:22:22 +0530139 if not self.non_batchwise_balance_qty:
140 continue
141
Akhil Narang3effaf22024-03-27 11:37:26 +0530142 self.batch_avg_rate[batch_no] = self.non_batchwise_balance_value / self.non_batchwise_balance_qty
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530143
144 stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty
145 self.stock_value_change += stock_value_change
146
147 frappe.db.set_value(
148 "Serial and Batch Entry",
149 ledger.name,
150 {
151 "stock_value_difference": stock_value_change,
152 "incoming_rate": self.batch_avg_rate[batch_no],
153 },
154 )
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530155
156 @deprecated
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530157 def set_balance_value_for_non_batchwise_valuation_batches(self):
158 self.set_balance_value_from_sl_entries()
159 self.set_balance_value_from_bundle()
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530160
161 @deprecated
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530162 def set_balance_value_from_sl_entries(self) -> None:
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530163 sle = frappe.qb.DocType("Stock Ledger Entry")
164 batch = frappe.qb.DocType("Batch")
165
166 timestamp_condition = CombineDatetime(sle.posting_date, sle.posting_time) < CombineDatetime(
167 self.sle.posting_date, self.sle.posting_time
168 )
169 if self.sle.creation:
170 timestamp_condition |= (
171 CombineDatetime(sle.posting_date, sle.posting_time)
172 == CombineDatetime(self.sle.posting_date, self.sle.posting_time)
173 ) & (sle.creation < self.sle.creation)
174
175 query = (
176 frappe.qb.from_(sle)
177 .inner_join(batch)
178 .on(sle.batch_no == batch.name)
179 .select(
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530180 sle.batch_no,
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530181 Sum(sle.actual_qty).as_("batch_qty"),
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530182 Sum(sle.stock_value_difference).as_("batch_value"),
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530183 )
184 .where(
185 (sle.item_code == self.sle.item_code)
186 & (sle.warehouse == self.sle.warehouse)
187 & (sle.batch_no.isnotnull())
188 & (batch.use_batchwise_valuation == 0)
189 & (sle.is_cancelled == 0)
190 )
191 .where(timestamp_condition)
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530192 .groupby(sle.batch_no)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530193 )
194
195 if self.sle.name:
196 query = query.where(sle.name != self.sle.name)
197
198 for d in query.run(as_dict=True):
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530199 self.non_batchwise_balance_value += flt(d.batch_value)
200 self.non_batchwise_balance_qty += flt(d.batch_qty)
201 self.available_qty[d.batch_no] += flt(d.batch_qty)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530202
203 @deprecated
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530204 def set_balance_value_from_bundle(self) -> None:
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530205 bundle = frappe.qb.DocType("Serial and Batch Bundle")
206 bundle_child = frappe.qb.DocType("Serial and Batch Entry")
207 batch = frappe.qb.DocType("Batch")
208
Akhil Narang3effaf22024-03-27 11:37:26 +0530209 timestamp_condition = CombineDatetime(bundle.posting_date, bundle.posting_time) < CombineDatetime(
210 self.sle.posting_date, self.sle.posting_time
211 )
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530212
213 if self.sle.creation:
214 timestamp_condition |= (
215 CombineDatetime(bundle.posting_date, bundle.posting_time)
216 == CombineDatetime(self.sle.posting_date, self.sle.posting_time)
217 ) & (bundle.creation < self.sle.creation)
218
219 query = (
220 frappe.qb.from_(bundle)
221 .inner_join(bundle_child)
222 .on(bundle.name == bundle_child.parent)
223 .inner_join(batch)
224 .on(bundle_child.batch_no == batch.name)
225 .select(
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530226 bundle_child.batch_no,
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530227 Sum(bundle_child.qty).as_("batch_qty"),
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530228 Sum(bundle_child.stock_value_difference).as_("batch_value"),
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530229 )
230 .where(
231 (bundle.item_code == self.sle.item_code)
232 & (bundle.warehouse == self.sle.warehouse)
233 & (bundle_child.batch_no.isnotnull())
234 & (batch.use_batchwise_valuation == 0)
235 & (bundle.is_cancelled == 0)
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530236 & (bundle.docstatus == 1)
Rohit Waghchauref8bf4aa2023-04-02 13:13:42 +0530237 & (bundle.type_of_transaction.isin(["Inward", "Outward"]))
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530238 )
239 .where(timestamp_condition)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530240 .groupby(bundle_child.batch_no)
241 )
242
243 if self.sle.serial_and_batch_bundle:
244 query = query.where(bundle.name != self.sle.serial_and_batch_bundle)
245
Rohit Waghchaure34233342024-03-21 20:28:16 +0530246 query = query.where(bundle.voucher_type != "Pick List")
247
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530248 for d in query.run(as_dict=True):
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530249 self.non_batchwise_balance_value += flt(d.batch_value)
250 self.non_batchwise_balance_qty += flt(d.batch_qty)
251 self.available_qty[d.batch_no] += flt(d.batch_qty)