class ProductsController < ApplicationController
##--- Abilities
load_and_authorize_resource
##--- Breadcrum_rails
add_breadcrumb I18n.t("breadcrumbs." + controller_name), :products_path, only: [:index, :new, :show, :edit]
add_breadcrumb "Nuevo " + I18n.t("breadcrumbs." + controller_name).singularize, :new_product_path, only: :new
add_breadcrumb "Detalle del " + I18n.t("breadcrumbs." + controller_name).singularize, :product_path, only: :show
add_breadcrumb "Editar " + I18n.t("breadcrumbs." + controller_name).singularize, :edit_product_path, only: :edit
add_breadcrumb "Seguimiento de productos", :product_track_path, only: :product_track
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_action :set_product_id, only: [:list_prices, :list_prices_variants, :edit_variants, :update_variants, :edit_from_purchase, :update_from_purchase, :update_status]
before_action :get_attrs, only: [:show, :edit, :update]
before_action :get_filters, only: [:index, :show, :edit, :new]
# GET /products
# GET /products.json
def index
respond_to do |format|
format.html
format.json { render json: ProductsDatatable.new(view_context, current_user) }
end
end
def list_prices
if @product.presentation
# @available_products = @product.get_available_children(false)
@pointsales = @product.get_available_children(true)
end
end
def list_prices_variants
children = Product.where("parent_id = ? and status != 0 ", params[:product_id]).pluck(:id)
@variants = AvailableProduct.where("pointsale_id = ? and product_id IN (?)", params[:pointsale_id], children).includes(:product)
@variants_json = Array.new
@variants.each do |v|
@variants_json.push(name: v.product.sku + " " + v.product.name + "
" + v.product.display_attributes + "", price: v.product.get_price_sale(params[:pointsale_id]), available_product_id: v.id)
end
render json: @variants_json.to_json
end
def edit_variants; end
def update_variants
if @product.is_parent
@product.update_attributes_to_variants(params[:new_size_list], params[:new_color_list], params[:new_style_list])
@product.save_new_attributes(params[:mynewsizes], params[:mynewcolors], params[:mynewstyles])
end
respond_to do |format|
if @product.save(validate: false)
format.html { redirect_to products_url, success: 'Se modificaron las variantes del producto ' + @product.sku + ' - ' + @product.name + '.' }
format.json { render :show, status: :ok, location: @product }
else
format.html { render :edit_variants }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# GET /products/1
# GET /products/1.json
def show; end
# GET /products/new
def new
@product = Product.new
# Default unit is 'Pieza'
@product.unit = Unit.where(unit: 'Pieza').first
if params[:remoto].present?
@remoto = params[:remoto]
@pointsale = params[:pointsale]
@warehouse = params[:warehouse]
@supplier = params[:supplier]
@exchange = params[:exchange]
end
@product.price_base = nil
@product.price_sale = nil
end
# GET /products/1/edit
def edit
has_variants = @product.children.any?
@with_presentation = has_variants ? true : false # si aun no tiene variantes, permitir clickear el switch
end
# POST /products
# POST /products.json
# rubocop:disable Metrics/BlockLength
def create
@product = Product.new(product_params)
if @product.presentation
@product.is_parent = true
end
message = 'El producto ' + @product.sku + ' fue creado.'
@product.category_id = params[:sub_category_id].present? ? params[:sub_category_id] : params[:product][:category_id]
@product.audit_comment = message
respond_to do |format|
if @product.save
unless @product.is_parent?
@product.generate_barcode
@product.save
end
##--- Para cuando se agrega un producto desde purchase
if params[:remoto] == "true"
@product.save_variants_no_thread(current_user)
##--- Guardar pre_purchase
@pre_purchases = Array.new
if @product.presentation && @product.is_parent
@product.children.each do |variant|
save_pre_purchase(variant)
set_available
@pre_purchases << @pre_purchase
end
else
save_pre_purchase(@product)
set_available
@pre_purchases << @pre_purchase
end
format.json { head :no_content }
format.js
else
@product.save_variants(current_user)
# crear available product para el p.v, cuando es sin variantes
if current_user.usertype == 'G' && !@product.presentation && !@product.is_parent
AvailableProduct.create(product_id: @product.id, pointsale_id: current_user.pointsale_id, stock: 0)
end
format.html { redirect_to products_url, success: message }
format.json { render :show, status: :created, location: @product }
end
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# rubocop:enable Metrics/BlockLength
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
@product.skip_sku_validation = true
@product.is_parent = params[:product][:presentation] == 'true' ? true : false
message = 'El producto ' + @product.sku + ' fue modificado.'
if params[:sub_category_id].present?
params[:product][:category_id] = params[:sub_category_id]
end
@product.audit_comment = message
if @product.update(product_params)
if @product.is_parent
@product.children.each_with_index do |variant, index|
variant.skip_sku_validation = true
params_to_edit = product_params
params_to_edit[:sku] = @product.sku + (index + 1).to_s + "A"
params_to_edit[:barcode] = variant.barcode
variant.update_attributes(params_to_edit)
end
end
format.html { redirect_to products_url, success: message }
format.json { render :show, status: :ok, location: @product }
else
format.html { render :edit }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
def edit_from_purchase
purchase_in_dollars = params[:is_in_dollars]
exchange = params[:exchange].to_f
if purchase_in_dollars == "true"
@product.price_base_dollars = params[:product][:price_base].to_f
price_in_peso = @product.price_base_dollars * exchange
@product.price_base = @product.price_base.present? ? price_in_peso : nil
@suggested_price_sale = (price_in_peso * (@pos_config.gain_margin / 100)) + price_in_peso
else
@product.price_base = params[:product][:price_base].to_f
price_in_dollars = @product.price_base / exchange if exchange != 0
@product.price_base_dollars = @product.price_base_dollars.present? ? price_in_dollars : nil
@suggested_price_sale = (@product.price_base * (@pos_config.gain_margin / 100)) + @product.price_base
end
@suggested_price_sale = 0 if @suggested_price_sale.nil?
respond_to do |format|
@product.audit_comment = 'El producto ' + @product.sku + ' fue modificado.'
@product.save
format.json { head :no_content }
format.js
end
end
def update_from_purchase
##--- Si el producto es hijo, sacar el registro del padre para cambiar todos los valores
unless @product.parent_id.nil?
@product = Product.find(@product.parent_id)
end
@product.price_base = params[:product][:price_base].to_f
@product.price_sale = params[:product][:price_sale].to_f
message = "Se ha modificado el precio de venta base del producto " + @product.name
respond_to do |format|
if @product.save
@product.children.each do |variant|
variant.update_attributes(product_params)
variant.save
end
@product.audit_comment = message
format.json { head :no_content }
format.js { flash[:success] = message }
else
@suggested_price_sale = params[:suggested_price_sale].to_f
format.js { render :edit_from_purchase }
format.json { render json: @available_product.errors, status: :unprocessable_entity }
end
end
end
def update_status
product = @product
if product.active?
product.status = 2
elsif product.inactive?
product.status = 1
end
if product.presentation
product.children.each do |pv|
pv.status = product.status
pv.save(validate: false)
end
end
respond_to do |format|
message = "El producto " + product.name + " fue " + (product.active? ? "activado" : "desactivado") + "."
product.audit_comment = message
if product.save(validate: false)
format.html { redirect_to products_url, warning: message }
# format.json { render :show, status: :ok, location: @pointsale }
format.json { head :no_content }
else
format.html { redirect_to products_url }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
respond_to do |format|
message = "El producto " + @product.name + " fue eliminado."
@product.audit_comment = message
if @product.update_attributes(status: 0)
if @product.is_parent
@product.children.each_with_index do |variant|
variant.update_attributes(status: 0)
variant.save
end
end
format.html { redirect_to products_url, warning: message }
format.json { head :no_content }
else
format.html { redirect_to products_url }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
def validate_unique_barcode
respond_to do |format|
@product = Product.find_by(barcode: params[:barcode])
if @product.blank?
format.js { head :ok }
else
format.js
end
end
end
def product_track
#--Seguimiento de productos
# @sales = SalesDetail.new
product_id = params[:product_id]
pointsale_id = params[:pointsale_id]
start_date = DateTime.parse(params[:start_date]) if params[:start_date].present?
end_date = DateTime.parse(params[:end_date]) if params[:end_date].present?
if product_id.present?
respond_to do |format|
@sales = pointsale_id.present? ? Pointsale.find(pointsale_id).sales_details.includes(:sale).where('sales.status > 1 and sales_details.product_id = ? and sales.date_sale BETWEEN ? AND ?', product_id, start_date, end_date).order("sales_details.id DESC") : SalesDetail.find_by_sql("SELECT sales_details.* FROM sales_details INNER JOIN sales ON sales_details.sale_id = sales.id INNER JOIN open_cash_registers ON sales.open_cash_register_id = open_cash_registers.id INNER JOIN cash_registers ON open_cash_registers.cash_register_id = cash_registers.id WHERE ( sales.status > 1 AND sales_details.product_id = #{product_id} and sales.date_sale BETWEEN '#{start_date}' AND '#{end_date}') ORDER BY sales_details.ID DESC")
@purchases = pointsale_id.present? ? PurchaseDetail.joins(:purchase).where('purchases.pointsale_id = ? AND purchases.status != 1 and purchase_details.product_id = ? and purchases.purchase_date BETWEEN ? AND ?', pointsale_id, product_id, start_date, end_date).order('purchase_details.id DESC') : PurchaseDetail.find_by_sql("SELECT purchase_details.* FROM purchase_details INNER JOIN purchases ON purchase_details.purchase_id = purchases.id WHERE ( purchases.status != 1 AND purchase_details.product_id = #{product_id} and purchases.purchase_date BETWEEN '#{start_date}' AND '#{end_date}') ORDER BY purchase_details.ID DESC")
@total_quantity = pointsale_id.present? ? @sales.sum(:quantity) : ActiveRecord::Base.connection.select_value("SELECT SUM(quantity) as quantity FROM sales LEFT OUTER JOIN sales_details ON sales_details.sale_id = sales.id WHERE (sales.status > 1 and sales_details.product_id = #{product_id} and sales.date_sale BETWEEN '#{start_date}' AND '#{end_date}')")
@total_quantity_purchases = pointsale_id.present? ? @purchases.sum(:quantity) : ActiveRecord::Base.connection.select_value("SELECT SUM(quantity) as quantity FROM purchases LEFT OUTER JOIN purchase_details ON purchase_details.purchase_id = purchases.id WHERE (purchases.status != 1 and purchase_details.product_id = #{product_id} and purchases.purchase_date BETWEEN '#{start_date}' AND '#{end_date}')")
@total_sales = pointsale_id.present? ? @sales.sum(:total) : ActiveRecord::Base.connection.select_value("SELECT SUM(sales.total) as total FROM sales LEFT OUTER JOIN sales_details ON sales_details.sale_id = sales.id WHERE (sales.status > 1 and sales_details.product_id = #{product_id})")
format.js
end
end
end
def labels_list
@product = Product.find(params[:product_id])
if @product.presentation
@pointsales = @product.get_available_children(true)
end
end
def print_labels
@products = JSON.parse params[:products]
@pointsale_id = params[:pointsale_id]
@products.each do |obj|
obj['product'] = Product.find(obj['id'])
obj['price'] = @pointsale_id.present? ? obj['product'].get_price_sale(@pointsale_id) : obj['product'].price_sale
end
file_name = "etiquetas_#{Time.now.to_i}"
pdf = render_to_string pdf: file_name, template: "products/print_labels.pdf.erb", layout: 'labels.html.erb', locals: { objs: @products }, show_as_html: params.key?('debug'), page_width: '62mm', page_height: '300mm'
unless Dir.exist?(Rails.public_path.join("pdfs"))
Dir.mkdir(Rails.public_path.join("pdfs"))
end
save_path = Rails.public_path.join("pdfs", "#{file_name}.pdf")
File.open(save_path, 'wb') do |file|
file << pdf
end
respond_to do |format|
format.js { render action: "print_labels", locals: { pdf_path: "pdfs/#{file_name}.pdf" } }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
def set_product_id
@product = Product.find(params[:product_id])
end
def get_filters
@current_page = params[:current_page].blank? ? 1 : params[:current_page]
@filter = params[:filter]
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:sku, :name, :description, :price_base, :price_sale, :img_product, :img_product_cache, :presentation, :inventory, :unit_id, :content, :status, :category_id, :sub_category_id, :include_purchase_tax, :include_sale_tax, :barcode, :is_in_dollars, :price_base_dollars, size_list: [], color_list: [], style_list: [], available_products_attributes: [:id, :price_sale])
end
def save_pre_purchase(product)
@pre_purchase = PrePurchase.new
@pre_purchase.supplier_id = params[:supplier]
@pre_purchase.pointsale_id = params[:pointsale] if params[:pointsale].present?
@pre_purchase.warehouse_id = params[:warehouse] if params[:warehouse].present?
@pre_purchase.exchange = params[:exchange] if params[:exchange].present?
@pre_purchase.user_id = current_user.id
@pre_purchase.product_id = product.id
@pre_purchase.quantity = 1
@pre_purchase.get_totals
@pre_purchase.save
end
def set_available
##--- agregar a productos disponibles ya sea punto de venta o almacen
if params[:pointsale].present?
available_product = AvailableProduct.new
available_product.pointsale_id = @pre_purchase.pointsale_id
else
available_product = WarehouseStock.new
available_product.warehouse_id = @pre_purchase.warehouse_id
end
available_product.product_id = @pre_purchase.product_id
available_product.stock_min = params[:stock_min]
available_product.stock_max = params[:stock_max]
available_product.save
end
def get_attrs
@attrs = Array.new
@product.variants_attributes.each do |attri|
@attrs << attri.context
end
end
end