0
Friends, I have a form that uses nested_attributes and I use Gem Cocoon. I have 3 models involved. Variation Containing Stock, Order, Containing Order and Parent of Detail Containing Order Detail.
The rescue is working properly, however I need to update each item’s stock before saving.
Campos:
Details:
t.string "order_id"
t.string "cod_produto"
t.string "desc_produto"
t.string "cod_cor"
t.string "desc_cor"
t.string "desc_tamanho"
t.decimal "preco"
t.integer "quantidade"
t.datetime "created_at"
t.datetime "updated_at"
t.float "total"
Orders:
t.string "customer_id"
t.decimal "valor_total"
t.integer "item_total"
t.string "order_num"
t.datetime "created_at"
t.datetime "updated_at"
Variations:
create_table "variations", force: true do |t|
t.string "product_id"
t.string "size_id"
t.string "color_id"
t.integer "quantity"
t.string "barcode"
t.datetime "created_at"
t.datetime "updated_at"
do
The models are:
order.Rb
class Order < ActiveRecord::Base
has_many :details, dependent: :destroy
belongs_to :customer
accepts_nested_attributes_for :details, reject_if: proc { |attributes| attributes['cod_produto'].blank? }, :allow_destroy => true
validates :customer_id, :presence => true
after_validation :sum_details
after_create :set_order_num
private
def set_order_num
update(order_num: "#{Date.current.year}-#{self.id}")
end
def sum_details
total = 0
qtd = 0
self.details.each do |d|
total += (d.quantidade * d.preco) if d.quantidade.present?
qtd += d.quantidade if d.quantidade.present?
end
self.valor_total = total
self.item_total = qtd
end
end
Detail.Rb
class Detail < ActiveRecord::Base
belongs_to :order
after_validation :update_quantity
before_save :get_quantity
private
def get_quantity
@qtd = self.quantidade
end
def update_quantity
if self.quantidade > 0
self.quantidade = self.quantidade - @qtd
end
end
end
What I need to do is: before saving the Detail model (remembering that it is a child form of the order model), I need to find the amount of a product that is in the Variations model and update its quantity. To do this you have to take the Detail model the cod_product + cod_color + desc_size and look for the Barcode field in the variation model to update your stock. I’m using before_save to try to catch the amount but even this isn’t working... Could someone give some light ?
Thank you
EDITED: Inclusion of controllers:
orders_controller.Rb
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
require "json"
def consulta_produto
@variacao = Variation.find_by(barcode:params[:barcode])
if @variacao.present?
hash = {:cod_produto => @variacao.product.cod ,:desc_produto => @variacao.product.descricao,:cod_cor => @variacao.color.cod, :desc_cor => @variacao.color.descricao,:desc_tamanho => @variacao.size.descricao,:preco => @variacao.product.price }
render :json => { :resultado => hash }
else
render :json => {:resultado => "error"}
end
end
# GET /orders
# GET /orders.json
def index
@orders = Order.all
end
# GET /orders/1
# GET /orders/1.json
def show
end
# GET /orders/new
def new
@order = Order.new
end
# GET /orders/1/edit
def edit
end
# POST /orders
# POST /orders.json
def create
@order = Order.new(order_params)
respond_to do |format|
if @order.save
format.html { redirect_to @order, notice: 'Order was successfully created.' }
format.json { render :show, status: :created, location: @order }
else
format.html { render :new }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /orders/1
# PATCH/PUT /orders/1.json
def update
respond_to do |format|
if @order.update(order_params)
format.html { redirect_to @order, notice: 'Order was successfully updated.' }
format.json { render :show, status: :ok, location: @order }
else
format.html { render :edit }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
end
# DELETE /orders/1
# DELETE /orders/1.json
def destroy
@order.destroy
respond_to do |format|
format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_order
@order = Order.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def order_params
params.require(:order).permit(:customer_id, :valor_total, :item_total, :order_num, details_attributes: [:id,:order_id, :cod_produto, :desc_produto, :cod_cor, :desc_cor, :desc_tamanho,:preco,:quantidade,:total, :_destroy])
end
end
details_controller.Rb
before_action :set_detail, only: [:show, :edit, :update, :destroy]
# GET /details
# GET /details.json
def index
@details = Detail.all
end
# GET /details/1
# GET /details/1.json
def show
end
# GET /details/new
def new
@detail = Detail.new
end
# GET /details/1/edit
def edit
end
# POST /details
# POST /details.json
def create
@detail = Detail.new(detail_params)
respond_to do |format|
if @detail.save
format.html { redirect_to @detail, notice: 'Detail was successfully created.' }
format.json { render :show, status: :created, location: @detail }
else
format.html { render :new }
format.json { render json: @detail.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /details/1
# PATCH/PUT /details/1.json
def update
respond_to do |format|
if @detail.update(detail_params)
format.html { redirect_to @detail, notice: 'Detail was successfully updated.' }
format.json { render :show, status: :ok, location: @detail }
else
format.html { render :edit }
format.json { render json: @detail.errors, status: :unprocessable_entity }
end
end
end
# DELETE /details/1
# DELETE /details/1.json
def destroy
@detail.destroy
respond_to do |format|
format.html { redirect_to details_url, notice: 'Detail was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_detail
@detail = Detail.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def detail_params
params.require(:detail).permit(:order_id, :cod_produto, :desc_produto, :cod_cor, :desc_cor, :desc_tamanho, :preco, :quantidade)
end
variations_controller.Rb
class VariationsController < ApplicationController
before_action :set_variation, only: [:show, :edit, :update, :destroy]
# require 'barby/outputter/cairo_outputter'
# def barcode_output( order )
# barcode_string = order.barcode
# barcode = Barby::Code128B.new(barcode_string)
# # PNG OUTPUT
# data = barcode.to_image(height: 15, margin: 5).to_data_url
# end
# GET /variations
# GET /variations.json
def export
@data = Variation.order(:created_at)
# @data = Variation.select(:barcode).order(created_at: :desc)
respond_to do |format|
format.html { redirect_to root_url }
format.csv { send_data @data.to_csv }
end
end
def index
# @barcode = Barby::Code128B.new("160P10") rescue nil
# @outputter = Barby::HtmlOutputter.new(@barcode)
# @blob = Barby::PngOutputter.new(@barcode).to_png #Raw PNG data
# @barcode = Barby::HtmlOutputter.new('160P10')
# @barcode_for_html = Barby::HtmlOutputter.new(@barcode)
@variations = Variation.all
# @import = Variation::Import.new
respond_to do |format|
format.html
format.csv { send_data @variations}
end
# def import
# @import = Variation::Import.new variation_import_params
# if @import.save
# redirect_to variations_path, notice: "Importados #{@import.imported_count} Cod Barras"
# else
# @variations = Variation.all
# flash[:alert] = "Foram encontrados #{@import.errors.count} erros no CSV"
# render action: index
# end
# end
# require 'barby/outputter/png_outputter'
# blob = Barby::PngOutputter.new("12345").to_png #Raw PNG data
# File.open('barcode.png', 'wb'){|f| f.write blob }
#Convenience method
# File.open('barcode2.png', 'wb'){|f| f.write barcode.to_png }
# @barcode = Barby::EAN13.new('000000000')
# @barcode_for_html = Barby::CairoOutputter.new("0123456789")
# Variation.new.barcode # => Barby::Code39 object
# Variation.new.barcode_data # => <Barby::Code39 object>.to_png
end
# GET /variations/1
# GET /variations/1.json
def show
end
# GET /variations/new
def new
@variation = Variation.new
# @variacoes_js = Variation.joins(:color, :product, :size).includes(:color, :product, :size)
# # ActiveRecord::Base.include_root_in_json = true
# gon.variacoes = @variacoes_js.to_json
# @tamanhos = Size.order(:descricao).select(:id,:descricao)
# gon.tamanhos = @tamanhos.to_json
# @produtos = Product.order(:cod).select(:cod,:descricao)
# gon.produtos = @produtos.to_json
end
# GET /variations/1/edit
def edit
end
# POST /variations
# POST /variations.json
def create
@variation = Variation.new(variation_params)
respond_to do |format|
if @variation.save
format.html { redirect_to variations_path, notice: 'Variation was successfully created.' }
format.json { render :index, status: :created, location: @variation }
else
format.html { render :new }
format.json { render json: @variation.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /variations/1
# PATCH/PUT /variations/1.json
def update
respond_to do |format|
if @variation.update(variation_params)
format.html { redirect_to @variation, notice: 'Variation was successfully updated.' }
format.json { render :show, status: :ok, location: @variation }
else
format.html { render :edit }
format.json { render json: @variation.errors, status: :unprocessable_entity }
end
end
end
# DELETE /variations/1
# DELETE /variations/1.json
def destroy
@variation.destroy
respond_to do |format|
format.html { redirect_to variations_url, notice: 'Variation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_variation
@variation = Variation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def variation_params
params.require(:variation).permit(:product_id, :size_id, :color_id, :quantity, :barcode)
end
def variation_import_params
params.require(:variation_import).permit(:file)
end
end
vc can add more information to facilitate help, for example: 1) what is the result of executing your code? (everything is 0?); 2) how the parameters are coming to your controller?
– Peoplee
Include the controllers in the question. As for the result it is simply not entering before_save.I put a debug point there but it does not reach. The way I thought about doing but do not know how it is to take the amount of each Detail, search the variation and update the variation with that new quantity, adding or subtracting. if the amount of Detail > 0 then I decrease in the stock (variation) if <0 I sum (because there was devolucao). How would that be ?
– gmadeira
a hint is: if you are not entering before_save then some is wrong in the controller and the object is not being saved. Put a Debugger in the create from Ordercontroller and see if the parameters are arriving correctly
– Peoplee
Yes the parameters are ok in the create’s Debugger. I placed a Debugger in before_save and on the console I tried to recover the amount, but from the error: (rdb:1) self.quantity *** Nametory Exception: Undefined method `quantity' for Activesupport::Callbacks::Filters::Before:Class (rdb:1) self Activesupport::Callbacks::Filters::Before
– gmadeira