Преглед изворни кода

Merge branch 'issues/new-product' of SML/pos-boutique into master

josemiguel пре 9 година
родитељ
комит
926062575e

+ 342 - 353
app/controllers/products_controller.rb

@@ -1,355 +1,344 @@
 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_categories, only: [:create, :update]
-	before_action :get_attrs, only: [:show, :edit, :update]
-	before_action :get_filters, only: [:index, :show, :edit, :new]
-
-	skip_before_action :get_categories, :only => [:edit_from_purchase]
-	# 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).joins(:product).select(:name, :id, :product_id, :attributes_json, :sku)
-		@variants_json = Array.new
-		@variants.each do |v|
-			@variants_json.push({:name => v.sku + " " + v.name + " <br><small>" + Product.find(v.product_id).display_attributes + "</small>", :price => Product.find(v.product_id).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
-		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
-		@with_presentation = true
-	end
-
-	# POST /products
-	# POST /products.json
-	def create
-		@with_presentation = true
-		@product = Product.new(product_params)
-		if @product.presentation
-			@product.is_parent = true
-		end
-		respond_to do |format|
-			message = 'El producto ' + @product.sku + ' fue creado.'
-			@product.audit_comment = message
-			if @product.save
-				@product.save_variants
-				##--- Para cuando se agrega un producto desde purchase
-				if params[:remoto] == "true"
-					##--- 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
-					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
-
-	# PATCH/PUT /products/1
-	# PATCH/PUT /products/1.json
-	def update
-		respond_to do |format|
-			@product.skip_sku_validation = true
-			message = 'El producto ' + @product.sku + ' fue modificado.'
-			@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}" + "A"
-						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
-
-		respond_to do |format|
-			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
-			@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
-		if !@product.parent_id.nil?
-			@product = Product.find(@product.parent_id)
-		end
-
-		message = "Se ha modificado el precio de venta base del producto " + @product.name
-			respond_to do |format|
-				if @product.update(product_params)
-					@product.children.each_with_index do |variant, index|
-					variant.update_attributes(product_params)
-					variant.save
-				end
-					@product.audit_comment = message
-						format.json { head :no_content }
-						format.js {  flash[:success] = message }
-					else
-						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])
-			unless @product.blank?
-				format.js
-			else
-				format.js {head :ok}
-			end
-
-		end
-	end
-
-
-	def product_track  #--Seguimiento de productos
-		# @sales =  SalesDetail.new
-		product_id = params[:product_id]
-		pointsale_id = params[:pointsale_id]
-		if product_id.present?
-			respond_to do |format|
-				if !pointsale_id.present?
-					@sales = SalesDetail.includes(:sale).where( :sales =>{status:1 }, :sales_details =>{product_id: product_id}).order("sales_details.id DESC")
-				else
-					@sales = Pointsale.find(pointsale_id).sales_details.includes(:sale).where(:sales =>{status:1 }, :sales_details =>{product_id: product_id}).order("sales_details.id DESC")
-				end
-				format.js
-			end
-		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
-			if params[:current_page].blank?
-				@current_page = 1
-			else
-				@current_page = params[:current_page]
-			end
-			@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, :categorias, :category_ids, :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 get_categories
-			@categories = Array.new
-			unless params[:product][:category_ids].blank?
-				@categories << Category.find(params[:product][:category_ids])
-				@product.categories = @categories
-			end
-		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?
-				availableProduct = AvailableProduct.new
-				availableProduct.pointsale_id = @pre_purchase.pointsale_id
-			else
-				availableProduct = WarehouseStock.new
-		    availableProduct.warehouse_id = @pre_purchase.warehouse_id
-			end
-			availableProduct.product_id = @pre_purchase.product_id
-			availableProduct.stock_min = params[:stock_min]
-			availableProduct.stock_max = params[:stock_max]
-			availableProduct.save
-	  end
-
-		def get_attrs
-			@attrs = Array.new
-			@product.variants_attributes.each do |attri|
-				@attrs << attri.context
-			end
-		end
+  ##--- 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_categories, only: [:create, :update]
+  before_action :get_attrs, only: [:show, :edit, :update]
+  before_action :get_filters, only: [:index, :show, :edit, :new]
+
+  skip_before_action :get_categories, only:  [:edit_from_purchase]
+  # 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).joins(:product).select(:name, :id, :product_id, :attributes_json, :sku)
+    @variants_json = Array.new
+    @variants.each do |v|
+      @variants_json.push
+      {
+        name:  v.sku + " " + v.name + " <br><small>" + Product.find(v.product_id).display_attributes + "</small>",
+        price:  Product.find(v.product_id).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
+    @with_presentation = true
+  end
+
+  # POST /products
+  # POST /products.json
+  def create
+    @with_presentation = true
+    @product = Product.new(product_params)
+    if @product.presentation
+      @product.is_parent = true
+    end
+    message = 'El producto ' + @product.sku + ' fue creado.'
+    @product.audit_comment = message
+    respond_to do |format|
+      if @product.save
+        @product.save_variants
+        ##--- Para cuando se agrega un producto desde purchase
+        if params[:remoto] == "true"
+          ##--- 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
+          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
+
+  # PATCH/PUT /products/1
+  # PATCH/PUT /products/1.json
+  def update
+    respond_to do |format|
+      @product.skip_sku_validation = true
+      message = 'El producto ' + @product.sku + ' fue modificado.'
+      @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"
+            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
+    respond_to do |format|
+      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
+      @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
+
+    message = "Se ha modificado el precio de venta base del producto " + @product.name
+    respond_to do |format|
+      if @product.update(product_params)
+        @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
+        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]
+    if product_id.present?
+      respond_to do |format|
+        @sales = pointsale_id.present? ? @sales = Pointsale.find(pointsale_id).sales_details.includes(:sale).where(sales: { status: 1 }, sales_details: { product_id: product_id }).order("sales_details.id DESC") : SalesDetail.includes(:sale).where(sales: { status: 1 }, sales_details: { product_id: product_id }).order("sales_details.id DESC")
+        format.js
+      end
+    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, :categorias, :category_ids, :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 get_categories
+    @categories = Array.new
+    unless params[:product][:category_ids].blank?
+      @categories << Category.find(params[:product][:category_ids])
+      @product.categories = @categories
+    end
+  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

+ 18 - 16
app/models/product.rb

@@ -174,26 +174,28 @@ class Product < ActiveRecord::Base
 		combinations = self.get_combinations(combinations, attributes)
 
 		##--- recorrer combinaciones para crear las variantes de productos
-		combinations.each_with_index do |combination, index|
-			@products_variant = Product.new
-			@products_variant = self.dup
-			@products_variant.parent_id = self.id
-			@products_variant.is_parent = false
-			@products_variant.sku = self.sku + "#{index + 1}" + "A"
-			@products_variant.category_ids = self.category_ids
-			attributes_json = {}
+		unless combinations.nil?
+			combinations.each_with_index do |combination, index|
+				@products_variant = Product.new
+				@products_variant = self.dup
+				@products_variant.parent_id = self.id
+				@products_variant.is_parent = false
+				@products_variant.sku = self.sku + "#{index + 1}" + "A"
+				@products_variant.category_ids = self.category_ids
+				attributes_json = {}
 
-			if combination.is_a?(Array)
-				combination.each do |attrib|
-					attributes_json = @products_variant.assign_attributes_to_variant(attrib, self.id, attributes_json)
+				if combination.is_a?(Array)
+					combination.each do |attrib|
+						attributes_json = @products_variant.assign_attributes_to_variant(attrib, self.id, attributes_json)
+					end
+				else
+					attributes_json = @products_variant.assign_attributes_to_variant(combination, self.id, attributes_json)
 				end
-			else
-				attributes_json = @products_variant.assign_attributes_to_variant(combination, self.id, attributes_json)
-			end
 
-			@products_variant.attributes_json = attributes_json.to_json
-			@products_variant.save
+				@products_variant.attributes_json = attributes_json.to_json
+				@products_variant.save
 
+			end
 		end
 
 	end

+ 7 - 18
app/views/products/_form.html.erb

@@ -295,7 +295,9 @@
 	var timeout = null;
 	var regex = /[a,e,i,o,u]/gi;
 	var skuEdit = "";
+
 	$(document).on('page:change', function() {
+
 		App.init();
 
 		$('.fileinput').fileinput();
@@ -310,21 +312,15 @@
 		<% end %>
 
 		presentaciones();
-		$('#product_size_list').tagsinput({
-			tagClass: 'label label-default'
-		});
-		$('#product_color_list').tagsinput({
-			tagClass: 'label label-primary'
-		});
-		$('#product_style_list').tagsinput({
-			tagClass: 'label label-success'
-		});
-
 		getVariants();
 		showPriceBaseInput(<%= @product.is_in_dollars? %>);
 
 	});
 
+	$('#product_size_list').on('change', function(event) { getVariants(); });
+	$('#product_color_list').on('change', function(event) { getVariants(); });
+	$('#product_style_list').on('change', function(event) { getVariants(); });
+
 	function presentaciones(){
 		console.log($('#product_presentation').is(':checked'));
 		if ($('#product_presentation').is(':checked')){
@@ -332,18 +328,11 @@
 		}
 		else{ $('.presentaciones').addClass('hidden'); }
 	}
+
 	$('#product_presentation').on('switchChange.bootstrapSwitch', function(event, state) {
 		presentaciones();
 	});
 
-
-	$('#product_size_list').on('itemAdded', function(event) { getVariants(); });
-	$('#product_size_list').on('itemRemoved', function(event) { getVariants(); });
-	$('#product_color_list').on('itemAdded', function(event) { getVariants(); });
-	$('#product_color_list').on('itemRemoved', function(event) { getVariants(); });
-	$('#product_style_list').on('itemAdded', function(event) { getVariants(); });
-	$('#product_style_list').on('itemRemoved', function(event) { getVariants(); });
-
 	function getVariants(){
 		sizes = $('#product_size_list').tagsinput('items');
 		colors = $('#product_color_list').tagsinput('items');

+ 96 - 98
app/views/products/_form_remote.html.erb

@@ -318,39 +318,45 @@
 </div>
 <% end %>
 <script type="text/javascript">
-  	var timeout = null;
+	var timeout = null;
 	var regex = /[a,e,i,o,u]/gi;
 	var skuEdit = "";
-	$(document).ready(function(){
+
+	$(document).ready(function() {
+
 		App.init();
 
-		$('body').barcodeListener().on('barcode.valid', function(e, code) {
-			if($('#product_barcode').length > 0) {
-				$('#product_barcode').val(code);
-				validateBarcode(code);
-			}
-		});
+		$('.fileinput').fileinput();
 
+		<% if @product.barcode.blank? %>
+			$('body').barcodeListener().on('barcode.valid', function(e, code) {
+				if($('#product_barcode').length > 0) {
+					$('#product_barcode').val(code);
+					validateBarcode(code);
+				}
+			});
+		<% end %>
 
 		presentaciones();
-		$('#product_size_list').tagsinput({
-            tagClass: 'label label-default'
-        });
-		$('#product_color_list').tagsinput({
-            tagClass: 'label label-primary'
-        });
-		$('#product_style_list').tagsinput({
-            tagClass: 'label label-success'
-        });
-    	getVariants();
+		getVariants();
+		showPriceBaseInput(<%= @product.is_in_dollars? %>);
 
 	});
 
 	$("#submit_remote").on( "click", function(e) {
-	   e.preventDefault();
-	   $('#product_remote_form').submit();
+	  e.preventDefault();
+	  $('#product_remote_form').submit();
 	});
 
+	function cerrarDialog() {
+		$('#dialog').modal('toggle');
+	}
+
+
+	$('#product_size_list').on('change', function(event) { getVariants(); });
+	$('#product_color_list').on('change', function(event) { getVariants(); });
+	$('#product_style_list').on('change', function(event) { getVariants(); });
+
 	function presentaciones(){
 		console.log($('#product_presentation').is(':checked'));
 		if ($('#product_presentation').is(':checked')){
@@ -358,17 +364,11 @@
 		}
 		else{ $('.presentaciones').addClass('hidden'); }
 	}
+
 	$('#product_presentation').on('switchChange.bootstrapSwitch', function(event, state) {
 		presentaciones();
 	});
 
-	$('#product_size_list').on('itemAdded', function(event) { getVariants(); });
-	$('#product_size_list').on('itemRemoved', function(event) { getVariants(); });
-	$('#product_color_list').on('itemAdded', function(event) { getVariants(); });
-	$('#product_color_list').on('itemRemoved', function(event) { getVariants(); });
-	$('#product_style_list').on('itemAdded', function(event) { getVariants(); });
-	$('#product_style_list').on('itemRemoved', function(event) { getVariants(); });
-
 	function getVariants(){
 		sizes = $('#product_size_list').tagsinput('items');
 		colors = $('#product_color_list').tagsinput('items');
@@ -377,45 +377,37 @@
 		variantes = (sizes.length > 0 ? sizes.length : 1)
 			* (colors.length > 0 ? colors.length : 1 )
 				* (styles.length > 0 ? styles.length : 1);
-		$('#variants').val(variantes);
+		$('#variants').html(variantes);
 		$('.alert-warning').removeClass('hidden');
 		$('#variantes').html(variantes);
 	}
 
-	function cerrarDialog() {
-		$('#dialog').modal('toggle');
-	}
-
 	$('#categorias').on('change', function() {
 		$('#product_sku').val('');
 		if($('#categorias').val()) {
-	      	$.ajax({
-		        type: "get",
-		        url:  '/getcategories/' + $(this).val(),
-		        dataType: 'json',
-		        success: function(data) {
-		        	$('#product_category_ids').empty();
-		        	if(data.length > 0) {
-		        		$('#product_category_ids').attr('disabled', false);
-		        		$('#product_category_ids').append("<option selected value='0'>Seleccione</option>")
-		        	} else {
-		        		$('#product_category_ids').attr('disabled', true);
-		        		$('#subcategory_hidden').val($('#categorias').val());
-		        		$('#product_category_ids').append("<option selected value='" + $('#categorias').val() +"'></option>")
-		        	}
-		        	for(i in data){
-	        			$('#product_category_ids').append("<option value='" + data[i].id +"'>" + data[i].category+ "</option>")
-		        	}
-		        	fillSKU();
-		        }
-	    	});
-    	}
+			$.ajax({
+				type: "get",
+				url:  '/getcategories/' + $(this).val(),
+				dataType: 'json',
+				success: function(data) {
+					$('#product_category_ids').empty();
+					if(data.length > 0) {
+						$('#product_category_ids').attr('disabled', false);
+						$('#product_category_ids').append("<option selected value='0'>Seleccione</option>")
+					} else {
+						$('#product_category_ids').attr('disabled', true);
+						$('#subcategory_hidden').val($('#categorias').val());
+						$('#product_category_ids').append("<option selected value='" + $('#categorias').val() +"'></option>")
+					}
+					for(i in data){
+						$('#product_category_ids').append("<option value='" + data[i].id +"'>" + data[i].category+ "</option>")
+					}
+					fillSKU();
+				}
+			});
+		}
 	});
 
-    $('#product_is_in_dollars').on('switchChange.bootstrapSwitch', function(event, state) {
-    	showPriceBaseInput(state);
-    });
-
 	$('#product_category_ids').on('change', function() {
 		$('#subcategory_hidden').val($(this).val());
 		fillSKU();
@@ -425,75 +417,81 @@
 		getSalePrice($(this));
 	});
 
+	$('#product_is_in_dollars').on('switchChange.bootstrapSwitch', function(event, state) {
+		showPriceBaseInput(state);
+	});
+
 	function getSalePrice(input){
 		clearTimeout(timeout);
 		timeout = setTimeout(function () {
 			var gainMargin = parseFloat($('#gain_margin').val());
 			var purchasePrice = parseFloat(input.val());
 			var gain = (gainMargin / 100) * purchasePrice
-			$('#product_price_sale').val(purchasePrice + gain);
+			$('#product_price_sale').val( (purchasePrice + gain).toFixed(2) );
 		}, 500);
 	}
 
+
 	function getProductId() {
 		$('#categorias').attr('disabled', true);
 		$.ajax({
 			type: "get",
 			url:  '/get_max_product_id',
-	        dataType: 'json',
-	        success: function(data) {
-    			$('#categorias').attr('disabled', false);
-	        	var sku = $('#product_sku').val();
-	        	if(sku.length && !$('#idproduct').val()) {
-	        		$('#product_sku').val(sku + "-" + data);
-	        	} else {
-	        		$('#product_sku').val(sku + "-" + $('#idproduct').val());
-	        	}
-	        }
+			dataType: 'json',
+			success: function(data) {
+				$('#categorias').attr('disabled', false);
+				var sku = $('#product_sku').val();
+				if(sku.length && !$('#idproduct').val()) {
+					$('#product_sku').val(sku + "-" + data);
+				} else {
+					$('#product_sku').val(sku + "-" + $('#idproduct').val());
+				}
+			},
 		});
 	}
 
 	function fillSKU() {
 		var sku = $('#product_sku').val();
-	    if(sku.length <= 3) {
-	    	$('#product_sku').val($('#categorias option:selected').text().substring(0,3).toUpperCase());
-	    	getProductId();
-	    }
-
-	    sku = $('#product_sku').val();
-	    if(sku.length >= 3 && $('#product_category_ids').val() != "0") {
-	    	var subcategory = $('#product_category_ids option:selected').text();
-	    	if(subcategory){
-		    	$('#product_sku').val(sku.substring(0,3) + '-' + subcategory.replace(regex, '')
-		    		.substring(0,3).toUpperCase());
-		    	getProductId();
-	    	}
-	    }
+		if(sku.length <= 3) {
+			$('#product_sku').val($('#categorias option:selected').text().substring(0,3).toUpperCase());
+			getProductId();
+		}
+
+		sku = $('#product_sku').val();
+		if(sku.length >= 3 && $('#product_category_ids').val() != "0") {
+			var subcategory = $('#product_category_ids option:selected').text();
+			if(subcategory){
+				$('#product_sku').val(sku.substring(0,3) + '-' + subcategory.replace(regex, '')
+					.substring(0,3).toUpperCase());
+				getProductId();
+			}
+		}
 	}
 
 	function validateBarcode(barcode) {
 		$.ajax({
-		  type: "get",
-		  url:  '/validate_unique_barcode/' + barcode,
-		  dataType: 'script',
-		  success: function(data) {
-		  }
+			type: "get",
+			url:  '/validate_unique_barcode/' + barcode,
+			dataType: 'script',
+			success: function(data) {
+			}
 		});
 	}
 
 	function showPriceBaseInput(state) {
-      //true es en dolares, false en pesos
-      if (state) {
-      	$('#price_base_usd_div').removeClass('hidden');
-      	$('#price_base_mxn_div').addClass('hidden');
-      	$('#product_price_base').val('');
-  	 	$('#product_price_sale').val('');
-      } else {
+		//true es en dolares, false en pesos
+		if (state) {
+		$('#price_base_usd_div').removeClass('hidden');
+		$('#price_base_mxn_div').addClass('hidden');
+		$('#product_price_base').val('');
+		 <% unless @product.persisted? %>
+			$('#product_price_sale').val('');
+		 <% end %>
+		} else {
 		$('#price_base_mxn_div').removeClass('hidden');
-      	$('#price_base_usd_div').addClass('hidden');
-      	$('#product_price_base_dollars').val('');
-      }
+		$('#price_base_usd_div').addClass('hidden');
+		$('#product_price_base_dollars').val('');
+		}
 	}
-
 </script>