Skip to content

Commit

Permalink
count the total stock
Browse files Browse the repository at this point in the history
  • Loading branch information
puppe1990 committed Nov 18, 2024
1 parent 021657b commit 0432b79
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 16 deletions.
132 changes: 127 additions & 5 deletions app/controllers/stocks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,31 @@ def index
@stocks_with_data = collection
end
format.csv do
GenerateStocksCsvJob.perform_later(current_tenant, current_user.email)
flash[:notice] = "CSV is being generated and will be emailed to you shortly."
redirect_to stocks_path
if params[:detailed]
begin
csv_data = generate_detailed_csv
send_data csv_data,
filename: "detailed_stock_calculations_#{Date.today}.csv",
type: 'text/csv; charset=utf-8',
disposition: 'attachment'
rescue => e
Rails.logger.error "Error generating CSV: #{e.message}"
flash[:error] = "Erro ao gerar o CSV. Por favor, tente novamente."
redirect_to stocks_path
end
else
begin
csv_data = generate_regular_csv
send_data csv_data,
filename: "stock_calculations_#{Date.today}.csv",
type: 'text/csv; charset=utf-8',
disposition: 'attachment'
rescue => e
Rails.logger.error "Error generating CSV: #{e.message}"
flash[:error] = "Erro ao gerar o CSV. Por favor, tente novamente."
redirect_to stocks_path
end
end
end
end
end
Expand Down Expand Up @@ -76,6 +98,48 @@ def collection
.filter_by_sku(params['sku'])
.joins(:product)

# Calculate total balance for null tipo_estoque products
default_warehouse_id = '9023657532' # ID for Estoque São Paulo Base
null_tipo_stocks = Stock.where(account_id: current_tenant)
.joins(:product)
.includes(:product)
.where(products: { tipo_estoque: nil })
.includes(:balances)
.to_a

Rails.logger.info "Starting balance calculations..."

@total_null_balance = null_tipo_stocks.sum do |stock|
balance = stock.balances.find { |b| b.deposit_id.to_s == default_warehouse_id }
next 0 unless balance

# Get the base physical balance
physical_balance = balance.physical_balance

# Calculate the actual balance based on conditions
actual_balance = if stock.discounted_warehouse_sku_id == "#{default_warehouse_id}_#{stock.product.sku}"
# If discounted, subtract 1000 first
discounted = physical_balance - 1000
# If the discounted value is negative, don't count this stock
discounted <= 0 ? 0 : discounted
else
# If not discounted, apply the regular rules
if physical_balance >= 1000
physical_balance - 1000
elsif physical_balance <= 0
0
else
physical_balance
end
end

Rails.logger.info "SKU: #{stock.product.sku} | Physical Balance: #{physical_balance} | Actual Balance: #{actual_balance} | Discounted?: #{stock.discounted_warehouse_sku_id.present?}"

actual_balance
end

Rails.logger.info "Total balance calculated: #{@total_null_balance}"

stocks = case @default_tipo_estoque
when 'null'
stocks.where(products: { tipo_estoque: nil })
Expand All @@ -99,8 +163,6 @@ def collection
.group(:sku)
.sum(:quantity)

default_warehouse_id = '9023657532' # ID for Estoque São Paulo Base

total_in_production = Stock.total_in_production_for_all

stocks_with_forecasts = stocks.map do |stock|
Expand Down Expand Up @@ -158,4 +220,64 @@ def set_stock
flash[:alert] = "Stock not found"
redirect_to stocks_path
end

def generate_detailed_csv
require 'csv'

default_warehouse_id = '9023657532'
stocks = Stock.where(account_id: current_tenant)
.includes(:product, :balances)
.joins(:product)
.where(products: { tipo_estoque: nil })

CSV.generate(headers: true, col_sep: ';', encoding: 'UTF-8') do |csv|
csv << [
'SKU', 'Saldo Físico'
]

stocks.each do |stock|
begin
balance = stock.balances.find { |b| b.deposit_id.to_s == default_warehouse_id }
next unless balance

physical_balance = if stock.discounted_warehouse_sku_id == "#{default_warehouse_id}_#{stock.product.sku}"
stock.discounted_balance(balance)
else
balance.physical_balance
end

csv << [
stock.product.sku,
physical_balance || 0
]
rescue => e
Rails.logger.error "Error processing stock #{stock.id}: #{e.message}"
next
end
end
end
end

def generate_regular_csv
CSV.generate(headers: true, col_sep: ';', encoding: 'UTF-8') do |csv|
csv << ['id', 'SKU', 'Saldo Total', 'Saldo Virtual Total', 'Quantidade Vendida dos Últimos 30 dias',
'Previsão para os Próximos 30 dias', 'Produto']

stocks = Stock.where(account_id: current_tenant)
.includes(:product, :balances)
.joins(:product)
.where(products: { tipo_estoque: nil })
.sort_by(&:calculate_basic_forecast)
.reverse!

stocks.each do |stock|
next if stock.total_balance.zero? && stock.count_sold.zero?

row = [stock.id, stock.sku, stock.total_balance, stock.total_virtual_balance, stock.count_sold,
stock.calculate_basic_forecast,
stock.product.name]
csv << row
end
end
end
end
53 changes: 42 additions & 11 deletions app/views/stocks/index.html.erb
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
<%- model_class = Stock -%>
<div class="section-header row-cols-2">
<div class="page-header">
<h1><%= t('stocks.two') %></h1>
</div>
<div class="d-flex justify-content-end">
<%= button_to "Gerar Previsão de Venda", stocks_path(format: "csv"), class: "btn btn-success", method: :get %>
<div class="section-header">
<div class="d-flex justify-content-between align-items-center w-100">
<div class="d-flex align-items-center">
<h1 class="me-3"><%= t('stocks.two') %></h1>
<div class="total-balance-counter">
<h4>Total de Estoque (Tipo Null): <span class="badge bg-primary"><%= number_with_delimiter(@total_null_balance) %></span></h4>
</div>
</div>
<div class="d-flex gap-2">
<%= button_to stocks_path(format: "csv", detailed: true),
class: "btn btn-info",
method: :get,
form: { target: '_blank' } do %>
<i class="fas fa-download"></i> Cálculo Detalhado
<% end %>
<%= button_to stocks_path(format: "csv"),
class: "btn btn-success",
method: :get do %>
Gerar Previsão de Venda
<% end %>
</div>
</div>
</div>

Expand All @@ -27,8 +42,19 @@
options_for_select([['30 dias', '30'], ['15 dias', '15'], ['7 dias', '7']], @default_period_filter),
class: "form-select" %>
</div>

<div class="col-md-2">
<%= select_tag "tipo_estoque",
options_for_select([
['Tipo Null', 'null'],
['Tipo V', 'V'],
['Tipo P', 'P'],
['Todos', 'all']
], @default_tipo_estoque),
class: "form-select" %>
</div>

<div class="col-md-3">
<div class="col-md-2">
<%= text_field_tag "sku", @default_sku_filter,
placeholder: "Filtrar por SKU",
class: "form-control" %>
Expand Down Expand Up @@ -65,7 +91,7 @@
<% sao_paulo_base = stock.balances.find { |b| b.deposit_id.to_s == '9023657532' } %>
<tr>
<td>
<% if sao_paulo_base %>
<% if sao_paulo_base && !stock.product.composed? %>
<%= check_box_tag "discount_#{stock.id}_#{sao_paulo_base.deposit_id}", 1,
stock.discounted_warehouse_sku_id == "#{sao_paulo_base.deposit_id}_#{stock.product.sku}",
class: 'discount-checkbox',
Expand All @@ -84,11 +110,16 @@
</td>
<td class="in-production"><%= data[:total_in_production] %></td>
<td><%= data[:total_sold] %></td>
<td class="forecast"><%= data[:total_forecast] %></td>
<td class="forecast"><%= stock.product.composed? ? 'N/A' : data[:total_forecast] %></td>
<td class="number-of-rolls">
<%= (data[:total_forecast].to_f / (stock.product.number_of_pieces_per_fabric_roll || 1)).ceil %>
<%= stock.product.composed? ? 'N/A' : (data[:total_forecast].to_f / (stock.product.number_of_pieces_per_fabric_roll || 1)).ceil %>
</td>
<td>
<%= stock.product.name %>
<% if stock.product.composed? %>
<span class="badge bg-info">Composto</span>
<% end %>
</td>
<td><%= stock.product.name %></td>
<td>
<%= link_to icon('fas fa-eye'), stock, title: t('show'), class: 'btn btn-info', data: { toggle: 'tooltip', turbo: false } %>
</td>
Expand Down

0 comments on commit 0432b79

Please sign in to comment.