@@ -10,9 +10,31 @@ def index
10
10
@stocks_with_data = collection
11
11
end
12
12
format . csv do
13
- GenerateStocksCsvJob . perform_later ( current_tenant , current_user . email )
14
- flash [ :notice ] = "CSV is being generated and will be emailed to you shortly."
15
- redirect_to stocks_path
13
+ if params [ :detailed ]
14
+ begin
15
+ csv_data = generate_detailed_csv
16
+ send_data csv_data ,
17
+ filename : "detailed_stock_calculations_#{ Date . today } .csv" ,
18
+ type : 'text/csv; charset=utf-8' ,
19
+ disposition : 'attachment'
20
+ rescue => e
21
+ Rails . logger . error "Error generating CSV: #{ e . message } "
22
+ flash [ :error ] = "Erro ao gerar o CSV. Por favor, tente novamente."
23
+ redirect_to stocks_path
24
+ end
25
+ else
26
+ begin
27
+ csv_data = generate_regular_csv
28
+ send_data csv_data ,
29
+ filename : "stock_calculations_#{ Date . today } .csv" ,
30
+ type : 'text/csv; charset=utf-8' ,
31
+ disposition : 'attachment'
32
+ rescue => e
33
+ Rails . logger . error "Error generating CSV: #{ e . message } "
34
+ flash [ :error ] = "Erro ao gerar o CSV. Por favor, tente novamente."
35
+ redirect_to stocks_path
36
+ end
37
+ end
16
38
end
17
39
end
18
40
end
@@ -66,13 +88,68 @@ def collection
66
88
@default_situation_balance_filter = params [ 'balance_situation' ]
67
89
@default_sku_filter = params [ 'sku' ]
68
90
@default_period_filter = params [ 'period' ] || '30'
91
+ @default_tipo_estoque = params [ 'tipo_estoque' ] || 'null'
69
92
70
93
stocks = Stock . where ( account_id : current_tenant )
71
94
. includes ( :product , :balances )
72
95
. only_positive_price ( true )
73
96
. filter_by_status ( params [ 'status' ] )
74
97
. filter_by_total_balance_situation ( params [ 'balance_situation' ] )
75
98
. filter_by_sku ( params [ 'sku' ] )
99
+ . joins ( :product )
100
+
101
+ # Calculate total balance for null tipo_estoque products
102
+ default_warehouse_id = '9023657532' # ID for Estoque São Paulo Base
103
+ null_tipo_stocks = Stock . where ( account_id : current_tenant )
104
+ . joins ( :product )
105
+ . includes ( :product )
106
+ . where ( products : { tipo_estoque : nil } )
107
+ . includes ( :balances )
108
+ . to_a
109
+
110
+ Rails . logger . info "Starting balance calculations..."
111
+
112
+ @total_null_balance = null_tipo_stocks . sum do |stock |
113
+ balance = stock . balances . find { |b | b . deposit_id . to_s == default_warehouse_id }
114
+ next 0 unless balance
115
+
116
+ # Get the base physical balance
117
+ physical_balance = balance . physical_balance
118
+
119
+ # Calculate the actual balance based on conditions
120
+ actual_balance = if stock . discounted_warehouse_sku_id == "#{ default_warehouse_id } _#{ stock . product . sku } "
121
+ # If discounted, subtract 1000 first
122
+ discounted = physical_balance - 1000
123
+ # If the discounted value is negative, don't count this stock
124
+ discounted <= 0 ? 0 : discounted
125
+ else
126
+ # If not discounted, apply the regular rules
127
+ if physical_balance >= 1000
128
+ physical_balance - 1000
129
+ elsif physical_balance <= 0
130
+ 0
131
+ else
132
+ physical_balance
133
+ end
134
+ end
135
+
136
+ Rails . logger . info "SKU: #{ stock . product . sku } | Physical Balance: #{ physical_balance } | Actual Balance: #{ actual_balance } | Discounted?: #{ stock . discounted_warehouse_sku_id . present? } "
137
+
138
+ actual_balance
139
+ end
140
+
141
+ Rails . logger . info "Total balance calculated: #{ @total_null_balance } "
142
+
143
+ stocks = case @default_tipo_estoque
144
+ when 'null'
145
+ stocks . where ( products : { tipo_estoque : nil } )
146
+ when 'V'
147
+ stocks . where ( products : { tipo_estoque : 'V' } )
148
+ when 'P'
149
+ stocks . where ( products : { tipo_estoque : 'P' } )
150
+ else
151
+ stocks
152
+ end
76
153
77
154
@warehouses = Warehouse . where ( account_id : current_tenant ) . pluck ( :bling_id , :description ) . to_h
78
155
@@ -86,8 +163,6 @@ def collection
86
163
. group ( :sku )
87
164
. sum ( :quantity )
88
165
89
- default_warehouse_id = '9023657532' # ID for Estoque São Paulo Base
90
-
91
166
total_in_production = Stock . total_in_production_for_all
92
167
93
168
stocks_with_forecasts = stocks . map do |stock |
@@ -98,16 +173,20 @@ def collection
98
173
virtual_balance = default_balance ? default_balance . virtual_balance : 0
99
174
in_production = stock . total_in_production
100
175
101
- # Calculate discounted balances
102
- discounted_physical_balance = stock . discounted_balance ( default_balance ) if default_balance
103
- discounted_virtual_balance = stock . discounted_virtual_balance ( default_balance ) if default_balance
176
+ # Calculate discounted balances if default_balance exists
177
+ discounted_physical_balance = default_balance ? stock . discounted_balance ( default_balance ) : 0
178
+ discounted_virtual_balance = default_balance ? stock . discounted_virtual_balance ( default_balance ) : 0
104
179
105
- # Calculate adjusted balances
106
- adjusted_physical_balance = stock . adjusted_balance ( default_balance ) if default_balance
107
- adjusted_virtual_balance = stock . adjusted_virtual_balance ( default_balance ) if default_balance
180
+ # Calculate adjusted balances if default_balance exists
181
+ adjusted_physical_balance = default_balance ? stock . adjusted_balance ( default_balance ) : 0
182
+ adjusted_virtual_balance = default_balance ? stock . adjusted_virtual_balance ( default_balance ) : 0
108
183
109
- # Calculate forecast: total_sold - adjusted_physical_balance
110
- total_forecast = [ total_sold - adjusted_physical_balance , 0 ] . max if adjusted_physical_balance
184
+ # Calculate forecast only if we have adjusted_physical_balance
185
+ total_forecast = if adjusted_physical_balance && !stock . product . composed?
186
+ [ total_sold - adjusted_physical_balance , 0 ] . max
187
+ else
188
+ 0
189
+ end
111
190
112
191
[ stock , {
113
192
total_sold : total_sold ,
@@ -123,7 +202,8 @@ def collection
123
202
} ]
124
203
end
125
204
126
- sorted_stocks = stocks_with_forecasts . sort_by { |_ , data | -data [ :total_sold ] }
205
+ # Sort by total_sold, but handle nil values
206
+ sorted_stocks = stocks_with_forecasts . sort_by { |_ , data | -( data [ :total_sold ] || 0 ) }
127
207
128
208
@pagy , @stocks_with_data = pagy_array ( sorted_stocks , items : 20 )
129
209
@@ -140,4 +220,64 @@ def set_stock
140
220
flash [ :alert ] = "Stock not found"
141
221
redirect_to stocks_path
142
222
end
223
+
224
+ def generate_detailed_csv
225
+ require 'csv'
226
+
227
+ default_warehouse_id = '9023657532'
228
+ stocks = Stock . where ( account_id : current_tenant )
229
+ . includes ( :product , :balances )
230
+ . joins ( :product )
231
+ . where ( products : { tipo_estoque : nil } )
232
+
233
+ CSV . generate ( headers : true , col_sep : ';' , encoding : 'UTF-8' ) do |csv |
234
+ csv << [
235
+ 'SKU' , 'Saldo Físico'
236
+ ]
237
+
238
+ stocks . each do |stock |
239
+ begin
240
+ balance = stock . balances . find { |b | b . deposit_id . to_s == default_warehouse_id }
241
+ next unless balance
242
+
243
+ physical_balance = if stock . discounted_warehouse_sku_id == "#{ default_warehouse_id } _#{ stock . product . sku } "
244
+ stock . discounted_balance ( balance )
245
+ else
246
+ balance . physical_balance
247
+ end
248
+
249
+ csv << [
250
+ stock . product . sku ,
251
+ physical_balance || 0
252
+ ]
253
+ rescue => e
254
+ Rails . logger . error "Error processing stock #{ stock . id } : #{ e . message } "
255
+ next
256
+ end
257
+ end
258
+ end
259
+ end
260
+
261
+ def generate_regular_csv
262
+ CSV . generate ( headers : true , col_sep : ';' , encoding : 'UTF-8' ) do |csv |
263
+ csv << [ 'id' , 'SKU' , 'Saldo Total' , 'Saldo Virtual Total' , 'Quantidade Vendida dos Últimos 30 dias' ,
264
+ 'Previsão para os Próximos 30 dias' , 'Produto' ]
265
+
266
+ stocks = Stock . where ( account_id : current_tenant )
267
+ . includes ( :product , :balances )
268
+ . joins ( :product )
269
+ . where ( products : { tipo_estoque : nil } )
270
+ . sort_by ( &:calculate_basic_forecast )
271
+ . reverse!
272
+
273
+ stocks . each do |stock |
274
+ next if stock . total_balance . zero? && stock . count_sold . zero?
275
+
276
+ row = [ stock . id , stock . sku , stock . total_balance , stock . total_virtual_balance , stock . count_sold ,
277
+ stock . calculate_basic_forecast ,
278
+ stock . product . name ]
279
+ csv << row
280
+ end
281
+ end
282
+ end
143
283
end
0 commit comments