blob: ab38c151b6415dfc09fbabb8a7c9e97d276a04cb [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
16 serial_nos = self.get_serial_nos()
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053017
18 actual_qty = flt(self.sle.actual_qty)
19
20 stock_value_change = 0
21 if actual_qty < 0:
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053022 if not self.sle.is_cancelled:
23 outgoing_value = self.get_incoming_value_for_serial_nos(serial_nos)
24 stock_value_change = -1 * outgoing_value
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053025
26 self.stock_value_change += stock_value_change
27
Rohit Waghchaurec1132d12023-03-24 10:14:09 +053028 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053029 def get_incoming_value_for_serial_nos(self, serial_nos):
30 # get rate from serial nos within same company
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053031 incoming_values = 0.0
rohitwaghchaurea5232d92024-03-01 22:26:54 +053032 for serial_no in serial_nos:
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053033 table = frappe.qb.DocType("Stock Ledger Entry")
rohitwaghchaurea5232d92024-03-01 22:26:54 +053034 stock_ledgers = (
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053035 frappe.qb.from_(table)
rohitwaghchaurea5232d92024-03-01 22:26:54 +053036 .select(table.incoming_rate, table.actual_qty, table.stock_value_difference)
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053037 .where(
38 (
39 (table.serial_no == serial_no)
40 | (table.serial_no.like(serial_no + "\n%"))
41 | (table.serial_no.like("%\n" + serial_no))
42 | (table.serial_no.like("%\n" + serial_no + "\n%"))
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053043 )
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053044 & (table.company == self.sle.company)
45 & (table.serial_and_batch_bundle.isnull())
Rohit Waghchauref4cfc582023-04-11 13:22:15 +053046 & (table.is_cancelled == 0)
47 )
rohitwaghchaurea5232d92024-03-01 22:26:54 +053048 .orderby(table.posting_datetime, order=Order.desc)
49 ).run(as_dict=1)
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053050
rohitwaghchaurea5232d92024-03-01 22:26:54 +053051 for sle in stock_ledgers:
52 self.serial_no_incoming_rate[serial_no] += (
53 flt(sle.incoming_rate)
54 if sle.actual_qty > 0
55 else (sle.stock_value_difference / sle.actual_qty) * -1
56 )
57 incoming_values += self.serial_no_incoming_rate[serial_no]
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053058
59 return incoming_values
60
61
62class DeprecatedBatchNoValuation:
Rohit Waghchaurec1132d12023-03-24 10:14:09 +053063 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053064 def calculate_avg_rate_from_deprecarated_ledgers(self):
Rohit Waghchaure5bb31732023-03-21 10:54:41 +053065 entries = self.get_sle_for_batches()
66 for ledger in entries:
Rohit Waghchauref704eb72023-03-30 11:32:39 +053067 self.stock_value_differece[ledger.batch_no] += flt(ledger.batch_value)
Rohit Waghchaure86da3062023-03-20 14:15:34 +053068 self.available_qty[ledger.batch_no] += flt(ledger.batch_qty)
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053069
Rohit Waghchaurec1132d12023-03-24 10:14:09 +053070 @deprecated
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053071 def get_sle_for_batches(self):
Rohit Waghchauref704eb72023-03-30 11:32:39 +053072 if not self.batchwise_valuation_batches:
73 return []
74
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053075 sle = frappe.qb.DocType("Stock Ledger Entry")
76
77 timestamp_condition = CombineDatetime(sle.posting_date, sle.posting_time) < CombineDatetime(
78 self.sle.posting_date, self.sle.posting_time
79 )
80 if self.sle.creation:
81 timestamp_condition |= (
82 CombineDatetime(sle.posting_date, sle.posting_time)
83 == CombineDatetime(self.sle.posting_date, self.sle.posting_time)
84 ) & (sle.creation < self.sle.creation)
85
Rohit Waghchaurec2d74612023-03-29 11:40:36 +053086 query = (
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053087 frappe.qb.from_(sle)
88 .select(
89 sle.batch_no,
90 Sum(sle.stock_value_difference).as_("batch_value"),
91 Sum(sle.actual_qty).as_("batch_qty"),
92 )
93 .where(
94 (sle.item_code == self.sle.item_code)
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053095 & (sle.warehouse == self.sle.warehouse)
Rohit Waghchauref704eb72023-03-30 11:32:39 +053096 & (sle.batch_no.isin(self.batchwise_valuation_batches))
97 & (sle.batch_no.isnotnull())
Rohit Waghchauree6143ab2023-03-13 14:51:43 +053098 & (sle.is_cancelled == 0)
99 )
100 .where(timestamp_condition)
101 .groupby(sle.batch_no)
Rohit Waghchaurec2d74612023-03-29 11:40:36 +0530102 )
103
104 if self.sle.name:
105 query = query.where(sle.name != self.sle.name)
106
107 return query.run(as_dict=True)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530108
109 @deprecated
110 def calculate_avg_rate_for_non_batchwise_valuation(self):
111 if not self.non_batchwise_valuation_batches:
112 return
113
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530114 self.non_batchwise_balance_value = 0.0
115 self.non_batchwise_balance_qty = 0.0
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530116
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530117 self.set_balance_value_for_non_batchwise_valuation_batches()
118
119 for batch_no, ledger in self.batch_nos.items():
120 if batch_no not in self.non_batchwise_valuation_batches:
121 continue
122
Rohit Waghchauref968f0f2023-06-14 23:22:22 +0530123 if not self.non_batchwise_balance_qty:
124 continue
125
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530126 self.batch_avg_rate[batch_no] = (
127 self.non_batchwise_balance_value / self.non_batchwise_balance_qty
128 )
129
130 stock_value_change = self.batch_avg_rate[batch_no] * ledger.qty
131 self.stock_value_change += stock_value_change
132
133 frappe.db.set_value(
134 "Serial and Batch Entry",
135 ledger.name,
136 {
137 "stock_value_difference": stock_value_change,
138 "incoming_rate": self.batch_avg_rate[batch_no],
139 },
140 )
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530141
142 @deprecated
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530143 def set_balance_value_for_non_batchwise_valuation_batches(self):
144 self.set_balance_value_from_sl_entries()
145 self.set_balance_value_from_bundle()
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530146
147 @deprecated
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530148 def set_balance_value_from_sl_entries(self) -> None:
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530149 sle = frappe.qb.DocType("Stock Ledger Entry")
150 batch = frappe.qb.DocType("Batch")
151
152 timestamp_condition = CombineDatetime(sle.posting_date, sle.posting_time) < CombineDatetime(
153 self.sle.posting_date, self.sle.posting_time
154 )
155 if self.sle.creation:
156 timestamp_condition |= (
157 CombineDatetime(sle.posting_date, sle.posting_time)
158 == CombineDatetime(self.sle.posting_date, self.sle.posting_time)
159 ) & (sle.creation < self.sle.creation)
160
161 query = (
162 frappe.qb.from_(sle)
163 .inner_join(batch)
164 .on(sle.batch_no == batch.name)
165 .select(
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530166 sle.batch_no,
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530167 Sum(sle.actual_qty).as_("batch_qty"),
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530168 Sum(sle.stock_value_difference).as_("batch_value"),
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530169 )
170 .where(
171 (sle.item_code == self.sle.item_code)
172 & (sle.warehouse == self.sle.warehouse)
173 & (sle.batch_no.isnotnull())
174 & (batch.use_batchwise_valuation == 0)
175 & (sle.is_cancelled == 0)
176 )
177 .where(timestamp_condition)
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530178 .groupby(sle.batch_no)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530179 )
180
181 if self.sle.name:
182 query = query.where(sle.name != self.sle.name)
183
184 for d in query.run(as_dict=True):
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530185 self.non_batchwise_balance_value += flt(d.batch_value)
186 self.non_batchwise_balance_qty += flt(d.batch_qty)
187 self.available_qty[d.batch_no] += flt(d.batch_qty)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530188
189 @deprecated
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530190 def set_balance_value_from_bundle(self) -> None:
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530191 bundle = frappe.qb.DocType("Serial and Batch Bundle")
192 bundle_child = frappe.qb.DocType("Serial and Batch Entry")
193 batch = frappe.qb.DocType("Batch")
194
195 timestamp_condition = CombineDatetime(
196 bundle.posting_date, bundle.posting_time
197 ) < CombineDatetime(self.sle.posting_date, self.sle.posting_time)
198
199 if self.sle.creation:
200 timestamp_condition |= (
201 CombineDatetime(bundle.posting_date, bundle.posting_time)
202 == CombineDatetime(self.sle.posting_date, self.sle.posting_time)
203 ) & (bundle.creation < self.sle.creation)
204
205 query = (
206 frappe.qb.from_(bundle)
207 .inner_join(bundle_child)
208 .on(bundle.name == bundle_child.parent)
209 .inner_join(batch)
210 .on(bundle_child.batch_no == batch.name)
211 .select(
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530212 bundle_child.batch_no,
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530213 Sum(bundle_child.qty).as_("batch_qty"),
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530214 Sum(bundle_child.stock_value_difference).as_("batch_value"),
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530215 )
216 .where(
217 (bundle.item_code == self.sle.item_code)
218 & (bundle.warehouse == self.sle.warehouse)
219 & (bundle_child.batch_no.isnotnull())
220 & (batch.use_batchwise_valuation == 0)
221 & (bundle.is_cancelled == 0)
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530222 & (bundle.docstatus == 1)
Rohit Waghchauref8bf4aa2023-04-02 13:13:42 +0530223 & (bundle.type_of_transaction.isin(["Inward", "Outward"]))
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530224 )
225 .where(timestamp_condition)
Rohit Waghchauref704eb72023-03-30 11:32:39 +0530226 .groupby(bundle_child.batch_no)
227 )
228
229 if self.sle.serial_and_batch_bundle:
230 query = query.where(bundle.name != self.sle.serial_and_batch_bundle)
231
232 for d in query.run(as_dict=True):
Rohit Waghchaure40ab3bd2023-06-01 16:08:49 +0530233 self.non_batchwise_balance_value += flt(d.batch_value)
234 self.non_batchwise_balance_qty += flt(d.batch_qty)
235 self.available_qty[d.batch_no] += flt(d.batch_qty)