Browse Source

Merge branch 'master' into improvements/return-tickets

* master:
  changed name variables in can_open_cash_register? function because was causing conflicts
  added a parcial to open cash in sales form when it not open, and lock cash register when is only 1
  method to check if exists an open cash register
  changed the way we get the open_cash, now we use on session
  ticket was throwing an error
Jose Miguel Ledon Nieblas 9 năm trước cách đây
mục cha
commit
d2eb4c1045

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 50 - 92
app/controllers/cash_outs_controller.rb


+ 90 - 84
app/controllers/cash_registers_moves_controller.rb

@@ -1,27 +1,26 @@
 class CashRegistersMovesController < ApplicationController
   before_action :set_cash_registers_move, only: [:show, :edit, :update, :destroy]
 
-
   # GET /cash_registers_moves/new
   def new
     @cash_registers_move = CashRegistersMove.new
 
     if params[:sale].present?
       @sale = Sale.find(params[:sale])
-      @credito = Credit.where(:customer_id => @sale.customer_id, :status => "0").sum(:rest)
+      @credito = Credit.where(customer_id: @sale.customer_id, status: "0").sum(:rest)
       @cash_registers_move.open_cash_register_id = @sale.open_cash_register_id
     elsif params[:products_return].present?
       @products_return = ProductsReturn.find(params[:products_return])
     end
 
-    @cash_id = PaymentMethod.find_by(:isCash => 1).id
+    @cash_id = PaymentMethod.find_by(isCash: 1).id
 
     if @sale.present?
       if @sale.saletype == 'reserved'
         if @sale.parcial?
           # esto quiere decir que la venta ya tiene un anticipo, se debe mostrar modal
           # para abonar al apartado o liquidarlo
-          @payments = CashRegistersMove.where(:sale_id => @sale.id, :status => 1)
+          @payments = CashRegistersMove.where(sale_id: @sale.id, status: 1)
           render 'liquidate_reserved_sale'
         else
           # registrar apartado
@@ -34,13 +33,14 @@ class CashRegistersMovesController < ApplicationController
         render 'new'
       end
     elsif @products_return.present?
-      @open_cash_register_id = current_user.pointsale.get_open_cash_register.id
+      @open_cash_register_id = session[:open_cash_register_id]
       render 'products_return_payment'
     end
   end
 
   # POST /cash_registers_moves
   # POST /cash_registers_moves.json
+  # rubocop:disable Metrics/BlockLength
   def create
     @cash_registers_move = CashRegistersMove.new(cash_registers_move_params)
     @sale = Sale.find(params[:cash_registers_move][:sale_id]) if params[:cash_registers_move][:sale_id].present?
@@ -56,17 +56,17 @@ class CashRegistersMovesController < ApplicationController
         @cash_registers_move.move_type = :ingreso
 
         if @sale.cash?
-          @sale.update_attributes(:status => :paid)
+          @sale.update_attributes(status: :paid)
           @cash_registers_move.concept = :sale
         elsif @sale.reserved?
           @cash_registers_move.status = :inactive
           @cash_registers_move.concept = :reserved_payment
-          @cash_registers_move.open_cash_register_id = Pointsale.find(current_user.pointsale_id).open_cash_registers.where("open_cash_registers.status = 0").last.id
+          @cash_registers_move.open_cash_register_id = session[:open_cash_register_id]
         end
 
         if credit.present?
           save_when_is_credit(credit)
-          @cash_registers_move.open_cash_register_id = Pointsale.find(current_user.pointsale_id).open_cash_registers.where("open_cash_registers.status = 0").last.id
+          @cash_registers_move.open_cash_register_id = session[:open_cash_register_id]
         end
 
         message = "movimiento de efectivo por venta con folio #{@cash_registers_move.sale.sale_code}"
@@ -109,7 +109,7 @@ class CashRegistersMovesController < ApplicationController
       end
     end
   end
-
+  # rubocop:enable Metrics/BlockLength
 
   # DELETE /cash_registers_moves/1
   # DELETE /cash_registers_moves/1.json
@@ -127,12 +127,12 @@ class CashRegistersMovesController < ApplicationController
       @products_return = ProductsReturn.find(params[:products_return_id]) if params[:products_return_id].present?
 
       if @sale.present?
-        if CashRegistersMove.where(:sale_id => @sale.id).update_all(:status => 1)
-          @sale.update_attributes(:status => :paid)
+        if CashRegistersMove.where(sale_id: @sale.id).update_all(status: 1)
+          @sale.update_attributes(status: :paid)
           message = "Venta registrada correctamente."
         end
       elsif @products_return.present?
-        CashRegistersMove.where(:products_return_id => @products_return.id).update_all(:status => 1)
+        CashRegistersMove.where(products_return_id: @products_return.id).update_all(status: 1)
         message = "Devolución registrada correctamente."
       end
 
@@ -140,12 +140,12 @@ class CashRegistersMovesController < ApplicationController
     end
   end
 
-  #funcion que se manda llamar cuando se clickea en 'Abonar' al crear apartado
+  # funcion que se manda llamar cuando se clickea en 'Abonar' al crear apartado
   def confirm_reserve
     respond_to do |format|
       @sale = Sale.find(params[:sale_id])
-      if CashRegistersMove.where(:sale_id => @sale.id).update_all(:status => 1)
-        @sale.update_attributes(:status => :parcial)
+      if CashRegistersMove.where(sale_id: @sale.id).update_all(status: 1)
+        @sale.update_attributes(status: :parcial)
         format.js { flash[:success] = "Apartado agregado al cliente #{@sale.customer.nick_name} correctamente." }
       end
     end
@@ -155,39 +155,39 @@ class CashRegistersMovesController < ApplicationController
     respond_to do |format|
       @sale = Sale.find(params[:sale_id])
       @new_moves_array = Array.new
-      @new_moves = CashRegistersMove.where(:sale_id => @sale.id, :status => 0)
+      @new_moves = CashRegistersMove.where(sale_id: @sale.id, status: 0)
       @new_moves.each do |move|
         @new_moves_array << move.id
       end
-      if @new_moves.update_all(:status => 1)
+      if @new_moves.update_all(status: 1)
         # if @sale.reserve_debt == 0
         if @sale.reserve_debt <= 0
-          @sale.update_attributes(:status => :paid)
+          @sale.update_attributes(status: :paid)
         end
         format.js { flash[:success] = "Abono al apartado #{@sale.sale_code} agregado correctamente." }
       end
     end
   end
 
+  # rubocop:disable Metrics/BlockLength
   def delete_credit_payment
     respond_to do |format|
       payment = CreditPayment.find(params[:credit_payment_id])
-      cashmoves = CashRegistersMove.where(:credit_payment_id => payment.id)
+      cashmoves = CashRegistersMove.where(credit_payment_id: payment.id)
 
-      openregister = OpenCashRegister.find_by(:id => cashmoves.first.open_cash_register_id)
+      openregister = OpenCashRegister.find_by(id: cashmoves.first.open_cash_register_id)
       if openregister.open?
-        payment.update_attributes(:status => :cancelled)
-        #
+        payment.update_attributes(status: :cancelled)
         credit = Credit.find(params[:credit])
         sale = Sale.find(credit.sale_id)
         sum = payment.quantity + credit.rest
-        if(credit.total < sum)
-          credit.update_attributes(:rest => credit.total)
-          sale.update_attributes(:status => :notpaid)
+        if credit.total < sum
+          credit.update_attributes(rest: credit.total)
+          sale.update_attributes(status: :notpaid)
         else
-          credit.update_attributes(:rest => sum)
-          if sale.total = credit.rest
-            sale.update_attributes(:status => :notpaid)
+          credit.update_attributes(rest: sum)
+          if sale.total == credit.rest
+            sale.update_attributes(status: :notpaid)
           end
         end
         cashmoves.each do |move|
@@ -195,14 +195,15 @@ class CashRegistersMovesController < ApplicationController
           new_cash_move.move_type = :egreso
           new_cash_move.save
         end
-      format.html { redirect_to customer_sales_path(:customer_id => payment.customer_id), notice: "Movimiento de efectivo realizado correctamente." }
-      format.js { flash[:success] = "Movimiento de efectivo realizado correctamente." }
+        format.html { redirect_to customer_sales_path(customer_id: payment.customer_id), notice: "Movimiento de efectivo realizado correctamente." }
+        format.js { flash[:success] = "Movimiento de efectivo realizado correctamente." }
       else
-        format.html { redirect_to customer_sales_path(:customer_id => payment.customer_id), notice: "No se pudo realizar el movimiento." }
+        format.html { redirect_to customer_sales_path(customer_id: payment.customer_id), notice: "No se pudo realizar el movimiento." }
         format.js { flash[:success] = "NO se pudo realizar el movimiento." }
       end
     end
   end
+  # rubocop:enable Metrics/BlockLength
 
   def add_quick_payment
     # type 1 es abono a credito, 2 es abono a apartado
@@ -211,76 +212,81 @@ class CashRegistersMovesController < ApplicationController
       debtors_ids = Credit.debtors
       @customers = Customer.find(debtors_ids.map { |m| m[0] })
     else
-      @sales = Pointsale.find(current_user.pointsale_id).sales.where(:saletype => 2, :status => 3).select(:customer_id).distinct
+      @sales = Pointsale.find(current_user.pointsale_id).sales.where(saletype: 2, status: 3).select(:customer_id).distinct
+      # rubocop:disable Style/SymbolProc
       @customers = Customer.find(@sales.map { |m| m.customer_id })
+      # rubocop:enable Style/SymbolProc
     end
   end
 
   def create_quick_debt_payment
     @customer = Customer.find(params[:customer_id])
     @sale = @customer.sales.where('saletype = 0 and status != 1 and status != 2').order('date_sale DESC').last
-    redirect_to new_cash_registers_move_path(:sale => @sale, :customer => @customer)
+    redirect_to new_cash_registers_move_path(sale: @sale, customer: @customer)
   end
 
   private
-    # Use callbacks to share common setup or constraints between actions.
-    def set_cash_registers_move
-      @cash_registers_move = CashRegistersMove.find(params[:id])
-    end
 
-    # Never trust parameters from the scary internet, only allow the white list through.
-    def cash_registers_move_params
-      params.require(:cash_registers_move).permit(:payment_method_id, :quantity, :open_cash_register_id, :sale_id, :cardnumber, :ticket, :received, :change, :products_return_id)
-    end
-
-    def save_when_is_credit(credit)
-      abono = @cash_registers_move.quantity
-      @credit_payment = CreditPayment.new
-      @credit_payment.credit_id = credit.id
-      @credit_payment.customer_id = credit.customer_id
-      @credit_payment.pointsale_id = credit.pointsale_id
-      @credit_payment.status = :active
-      @credit_payment.date_payment = Date.today
-      @credit_payment.user_id = current_user.id
-
-      if @credit_payment.save
-        @cash_registers_move.credit_payment_id = @credit_payment.id
-        @cash_registers_move.concept = :credit_payment
-        @debt = Credit.where(:customer_id => credit.customer_id).sum(:rest)
-        if abono >= credit.rest #si se paga más del adeudo de este crédito
-          abono = abono - credit.rest
+  # Use callbacks to share common setup or constraints between actions.
+  def set_cash_registers_move
+    @cash_registers_move = CashRegistersMove.find(params[:id])
+  end
 
-          # @debt = credit.rest
-          credit.update_attributes(:rest => 0)
-          @sale.update_attributes(:status => :paid)
+  # Never trust parameters from the scary internet, only allow the white list through.
+  def cash_registers_move_params
+    params.require(:cash_registers_move).permit(:payment_method_id, :quantity, :open_cash_register_id, :sale_id, :cardnumber, :ticket, :received, :change, :products_return_id)
+  end
 
-          while abono > 0 do
-            nextcredit = Credit.where("customer_id = #{credit.customer_id} and rest > 0").order("sale_id ASC")
-            if nextcredit.first.present?
-              if abono <= nextcredit.first.rest
-                nextcredit.first.update_attributes(:rest => nextcredit.first.rest - abono)
-                sale = Sale.find_by_id(nextcredit.first.sale_id)
-                sale.update_attributes(:status => :parcial)
-                abono = abono - nextcredit.first.rest
-              else
-                abono = abono - nextcredit.first.rest
-                # @debt = nextcredit.first.rest
-                nextcredit.first.update_attributes(:rest => 0)
-                sale = Sale.find_by_id(nextcredit.sale_id)
-                sale.update_attributes(:status => :paid)
-              end
+  def save_when_is_credit(credit)
+    abono = @cash_registers_move.quantity
+    @credit_payment = CreditPayment.new
+    @credit_payment.credit_id = credit.id
+    @credit_payment.customer_id = credit.customer_id
+    @credit_payment.pointsale_id = credit.pointsale_id
+    @credit_payment.status = :active
+    @credit_payment.date_payment = Date.today
+    @credit_payment.user_id = current_user.id
+
+    if @credit_payment.save
+      @cash_registers_move.credit_payment_id = @credit_payment.id
+      @cash_registers_move.concept = :credit_payment
+      @debt = Credit.where(customer_id: credit.customer_id).sum(:rest)
+      if abono >= credit.rest # si se paga mas del adeudo de este credito
+        abono -= credit.rest
+
+        # @debt = credit.rest
+        credit.update_attributes(rest: 0)
+        @sale.update_attributes(status: :paid)
+
+        # rubocop:disable Style/WhileUntilDo
+        while abono > 0 do
+          nextcredit = Credit.where("customer_id = #{credit.customer_id} and rest > 0").order("sale_id ASC")
+          # rubocop:disable Metrics/BlockNesting
+          if nextcredit.first.present?
+            if abono <= nextcredit.first.rest
+              nextcredit.first.update_attributes(rest: nextcredit.first.rest - abono)
+              sale = Sale.find_by_id(nextcredit.first.sale_id)
+              sale.update_attributes(status: :parcial)
+              abono -= nextcredit.first.rest
             else
-              abono = 0 #si ya no hay deuda
+              abono -= nextcredit.first.rest
+              # @debt = nextcredit.first.rest
+              nextcredit.first.update_attributes(rest: 0)
+              sale = Sale.find_by_id(nextcredit.sale_id)
+              sale.update_attributes(status: :paid)
             end
+          else
+            abono = 0 # si ya no hay deuda
           end
-
-        else
-          @cash_registers_move.quantity = abono
-          abono = credit.rest - abono
-          credit.update_attributes(:rest => abono)
-          @sale.update_attributes(:status => :parcial)
+          # rubocop:enable Metrics/BlockNesting
         end
+        # rubocop:enable Style/WhileUntilDo
+      else
+        @cash_registers_move.quantity = abono
+        abono = credit.rest - abono
+        credit.update_attributes(rest: abono)
+        @sale.update_attributes(status: :parcial)
       end
     end
+  end
 end
-

+ 20 - 21
app/controllers/dashboard_controller.rb

@@ -1,24 +1,23 @@
 class DashboardController < ApplicationController
   def index
     @open_cash = false
-  	if current_user.usertype == 'A'
+    if current_user.usertype == 'A'
       # obtener ingresos por punto de venta
       @incomings = ActionController::Base.helpers.sanitize(CashRegistersMove.incomings_per_period('day'))
       # obtener ranking de productos y prepararlo para mandarlo al view
       @product_ranking = Array.new
       most_selled_products = Product.most_selled_products('week', current_user)
       most_selled_products.each do |product, quantity|
-        obj = {:product => product, :quantity => quantity}
-       @product_ranking << obj
+        obj = { product: product, quantity: quantity }
+        @product_ranking << obj
       end
-      @product_ranking =  ActionController::Base.helpers.sanitize(@product_ranking.to_json)
-
-  	elsif current_user.usertype == 'G'
+      @product_ranking = ActionController::Base.helpers.sanitize(@product_ranking.to_json)
+    elsif current_user.usertype == 'G'
       # obtener ranking de vendedores y prepararlo para mandarlo al view
       @sellers_ranking = Array.new
       sellers = Seller.get_ranking('week', current_user.pointsale)
       sellers.each do |seller, total|
-        obj = {:seller => seller, :total => total}
+        obj = { seller: seller, total: total }
         @sellers_ranking << obj
       end
       @sellers_ranking = ActionController::Base.helpers.sanitize(@sellers_ranking.to_json)
@@ -26,14 +25,14 @@ class DashboardController < ApplicationController
       @product_ranking = Array.new
       most_selled_products = Product.most_selled_products('week', current_user)
       most_selled_products.each do |product, quantity|
-        obj = {:product => product, :quantity => quantity}
-       @product_ranking << obj
+        obj = { product: product, quantity: quantity }
+        @product_ranking << obj
       end
-      @product_ranking =  ActionController::Base.helpers.sanitize(@product_ranking.to_json)
+      @product_ranking = ActionController::Base.helpers.sanitize(@product_ranking.to_json)
     elsif current_user.usertype == 'C'
-      opened_cash_user = OpenCashRegister.where(:user_id => current_user.id, :status => 0).any?
-      @open_cash = true if opened_cash_user == false
-    end  
+      @need_to_open_cash = current_user.pointsale.can_open_cash_register?
+      session[:open_cash_register_id] = current_user.pointsale.get_open_cash_register.id unless @need_to_open_cash
+    end
   end
 
   def get_chart_data_for_dashboard
@@ -41,27 +40,27 @@ class DashboardController < ApplicationController
       puts "incomings"
       incomings = CashRegistersMove.incomings_per_period(params[:period])
       @incomings = ActionController::Base.helpers.sanitize(incomings)
-      render :text =>  @incomings     
+      render text: @incomings
     elsif params[:chart] == 'products'
       puts "products"
       @product_ranking = Array.new
       most_selled_products = Product.most_selled_products(params[:period], current_user)
       most_selled_products.each do |product, quantity|
-        obj = {:product => product, :quantity => quantity}
-       @product_ranking << obj
+        obj = { product: product, quantity: quantity }
+        @product_ranking << obj
       end
-      @product_ranking =  ActionController::Base.helpers.sanitize(@product_ranking.to_json)  
-      render :text =>  @product_ranking    
+      @product_ranking = ActionController::Base.helpers.sanitize(@product_ranking.to_json)
+      render text: @product_ranking
     elsif params[:chart] == 'sellers'
       puts "sellers"
       @sellers_ranking = Array.new
       sellers = Seller.get_ranking(params[:period], current_user.pointsale)
       sellers.each do |seller, total|
-        obj = {:seller => seller, :total => total}
+        obj = { seller: seller, total: total }
         @sellers_ranking << obj
       end
-      @sellers_ranking = ActionController::Base.helpers.sanitize(@sellers_ranking.to_json) 
-      render :text =>  @sellers_ranking        
+      @sellers_ranking = ActionController::Base.helpers.sanitize(@sellers_ranking.to_json)
+      render text: @sellers_ranking
     end
   end
 end

+ 2 - 2
app/controllers/expenses_controller.rb

@@ -20,7 +20,7 @@ class ExpensesController < ApplicationController
     when "G"
       @expenses = Pointsale.find(current_user.pointsale_id).expenses.includes(:expensesconcept, :open_cash_register).order("id DESC ")
     when "C"
-      @expenses = Expense.where(open_cash_register_id: current_user.get_open_cash_register.id).includes(:expensesconcept).order("id DESC ")
+      @expenses = Expense.where(open_cash_register_id: session[:open_cash_register_id]).includes(:expensesconcept).order("id DESC ")
     end
   end
 
@@ -34,7 +34,7 @@ class ExpensesController < ApplicationController
     @concept_purchase_payment = Expensesconcept.find_by(expense_from_purchase: 1)
     if current_user.usertype == 'C'
       @is_cashier = true
-      @expense.open_cash_register_id = current_user.get_open_cash_register.id
+      @expense.open_cash_register_id = session[:open_cash_register_id]
     end
   end
 

+ 13 - 15
app/controllers/open_cash_registers_controller.rb

@@ -9,17 +9,13 @@ class OpenCashRegistersController < ApplicationController
 
   # GET /open_cash_registers/1
   # GET /open_cash_registers/1.json
-  def show
-  end
+  def show; end
 
   # GET /open_cash_registers/new
-  def new
-
-  end
+  def new; end
 
   # GET /open_cash_registers/1/edit
-  def edit
-  end
+  def edit; end
 
   # POST /open_cash_registers
   # POST /open_cash_registers.json
@@ -30,6 +26,7 @@ class OpenCashRegistersController < ApplicationController
     respond_to do |format|
       @open_cash_register.audit_comment = "Caja #{@open_cash_register.cash_register.name} abierta con #{@open_cash_register.initial_cash}"
       if @open_cash_register.save
+        session[:open_cash_register_id] = @open_cash_register.id
         format.json { head :no_content }
         format.js
       else
@@ -64,13 +61,14 @@ class OpenCashRegistersController < ApplicationController
   end
 
   private
-    # Use callbacks to share common setup or constraints between actions.
-    def set_open_cash_register
-      @open_cash_register = OpenCashRegister.find(params[:id])
-    end
 
-    # Never trust parameters from the scary internet, only allow the white list through.
-    def open_cash_register_params
-      params.require(:open_cash_register).permit(:cash_register_id, :initial_cash, :final_cash, :status)
-    end
+  # Use callbacks to share common setup or constraints between actions.
+  def set_open_cash_register
+    @open_cash_register = OpenCashRegister.find(params[:id])
+  end
+
+  # Never trust parameters from the scary internet, only allow the white list through.
+  def open_cash_register_params
+    params.require(:open_cash_register).permit(:cash_register_id, :initial_cash, :final_cash, :status)
+  end
 end

+ 120 - 177
app/controllers/sales_controller.rb

@@ -4,8 +4,8 @@ class SalesController < ApplicationController
   ##--- Breadcrum_rails
   add_breadcrumb I18n.t("breadcrumbs." + controller_name), :sales_path
   add_breadcrumb "Nueva " + I18n.t("breadcrumbs." + controller_name).singularize, :new_sale_path, only: :new
-  add_breadcrumb "Detalle de la " + I18n.t("breadcrumbs." + controller_name).singularize , :sale_path, only: :show
-  add_breadcrumb "Editar " + I18n.t("breadcrumbs." + controller_name).singularize , :edit_sale_path, only: :edit
+  add_breadcrumb "Detalle de la " + I18n.t("breadcrumbs." + controller_name).singularize, :sale_path, only: :show
+  add_breadcrumb "Editar " + I18n.t("breadcrumbs." + controller_name).singularize, :edit_sale_path, only: :edit
 
   before_action :set_sale, only: [:show, :edit, :update, :destroy]
   before_action :get_filters, only: [:index, :show, :edit, :new, :sales_reserved]
@@ -15,29 +15,21 @@ class SalesController < ApplicationController
   def index
     today = Date.current
     thirty_day_ago = today - 30
-    if current_user.usertype == 'A'
-      @sales = Sale.includes(:customer, :user, :seller).where(:date_sale => thirty_day_ago..today).where('saletype != 2').order(" created_at DESC ")
-    else
-      @sales = Pointsale.find(current_user.pointsale_id).sales.includes(:customer, :user, :seller).where(:date_sale => thirty_day_ago..today).where('saletype != 2').order(" created_at DESC ")
-    end
+    @sales = current_user.usertype == 'A' ? Sale.includes(:customer, :user, :seller).where(date_sale: thirty_day_ago..today).where('saletype != 2').order(" created_at DESC ") : Pointsale.find(current_user.pointsale_id).sales.includes(:customer, :user, :seller).where(date_sale: thirty_day_ago..today).where('saletype != 2').order(" created_at DESC ")
   end
 
   def sales_reserved
     beg_of_month = Date.current.beginning_of_month
     end_of_month = Date.current.end_of_month
-    if current_user.usertype == 'A'
-      @sales = Sale.where(:saletype => 2).order(" created_at DESC ")
-    else
-      @sales = Pointsale.find(current_user.pointsale_id).sales.where(:saletype => 2).order(" created_at DESC")
-    end
+    @sales = current_user.usertype == 'A' ? Sale.where(saletype: 2).order(" created_at DESC ") : Pointsale.find(current_user.pointsale_id).sales.where(saletype: 2).order(" created_at DESC")
   end
 
   # GET /sales/1
   # GET /sales/1.json
   def show
-    @payments = CashRegistersMove.where(:sale_id => @sale.id, :status => 1)
+    @payments = CashRegistersMove.where(sale_id: @sale.id, status: 1)
     # saca la devolucion si es que hay.
-    @products_return = ProductsReturn.find_by(:sale_id => @sale.id)
+    @products_return = ProductsReturn.find_by(sale_id: @sale.id)
     @returned_prods_ids = Array.new
     @returned_prods_ids = @products_return.products_return_ins.pluck(:product_id) if @products_return.present?
   end
@@ -46,18 +38,16 @@ class SalesController < ApplicationController
   def new
     @sale = Sale.new
     @sale.sales_details.new
-    @general_public_id = Customer.find_by(:is_public => 1).id
-    @pre_sales = PreSale.where(:user_id => current_user.id)
+    @general_public_id = Customer.find_by(is_public: 1).id
+    @pre_sales = PreSale.where(user_id: current_user.id)
     @sale.saletype = 'cash'
-    #se desactivan cuando tienen pre sales, para mantener la congruencia de los datos.
+    # se desactivan cuando tienen pre sales, para mantener la congruencia de los datos.
     @disabled_select = false
     @disabled_button = true
     @enable_radios = true
-    if current_user.usertype != "G"
-      @open_cash_register = current_user.get_open_cash_register
-    end
-
-    if @pre_sales.size > 0
+    @opened_cash_registers = Pointsale.find(current_user.pointsale_id).open_cash_registers.abiertas
+    @sale.open_cash_register_id = session[:open_cash_register_id] || nil
+    if @pre_sales.present?
       @sale.saletype = @pre_sales[0].sale_type
       @sale.customer_id = @pre_sales[0].customer_id
       @sale.open_cash_register_id = @pre_sales[0].open_cash_register_id
@@ -68,17 +58,17 @@ class SalesController < ApplicationController
   end
 
   # GET /sales/1/edit
-  def edit
-  end
+  def edit; end
 
   # POST /sales
   # POST /sales.json
+  # rubocop:disable Metrics/BlockLength
   def create
     respond_to do |format|
       @sale = Sale.new(sale_params)
-      @pre_sales = PreSale.where(:user_id => current_user.id)
+      @pre_sales = PreSale.where(user_id: current_user.id)
       @sale.user_id = current_user.id
-      @sale.open_cash_register_id = current_user.pointsale.get_open_cash_register.id
+      @sale.open_cash_register_id = session[:open_cash_register_id]
       @sale.status = :notpaid
       @sale.expiration_date = Date.today + @pos_config.days_cancel_reserved if @sale.reserved?
 
@@ -101,28 +91,27 @@ class SalesController < ApplicationController
           @sale.sales_details << detail
           pre_sale.destroy
           # actualizar stock del producto
-          stockProduct = AvailableProduct.find_by(:product_id => detail.product_id, :pointsale_id => @sale.get_pointsale.id)
-          unless stockProduct.blank?
-            if stockProduct.stock.present?
-              stockProduct.stock = stockProduct.stock - detail.quantity
-              stockProduct.save
-            else
-              errors.add(:base, "No se tiene registrado el stock de alguno de los productos, es necesario configurarlo antes de generar una venta")
-              format.json { render json: @sale.errors.values, status: :unprocessable_entity }
-            end
-            # guardar en bitacora de inventario
-            move = InventoriesMove.new
-            move.product_id = detail.product_id
-            move.sale_id = @sale.id
-            move.quantity = detail.quantity
-            move.move_type = "outgoing"
-            move.reason = "sale"
-            move.save
+          stock_product = AvailableProduct.find_by(product_id: detail.product_id, pointsale_id: @sale.get_pointsale.id)
+          next if stock_product.blank?
+          if stock_product.stock.present?
+            stock_product.stock = stock_product.stock - detail.quantity
+            stock_product.save
+          else
+            errors.add(:base, "No se tiene registrado el stock de alguno de los productos, es necesario configurarlo antes de generar una venta")
+            format.json { render json: @sale.errors.values, status: :unprocessable_entity }
           end
+          # guardar en bitacora de inventario
+          move = InventoriesMove.new
+          move.product_id = detail.product_id
+          move.sale_id = @sale.id
+          move.quantity = detail.quantity
+          move.move_type = "outgoing"
+          move.reason = "sale"
+          move.save
         end
         # dependiendo el tipo de venta: contado/credito determina que hacer
         if @sale.cash?
-          format.js { redirect_to new_cash_registers_move_path(:sale => @sale.id) }
+          format.js { redirect_to new_cash_registers_move_path(sale: @sale.id) }
         elsif @sale.credit?
           credit = Credit.new
           credit.customer_id = @sale.customer_id
@@ -136,7 +125,7 @@ class SalesController < ApplicationController
           flash[:success] = "Venta a credito registrada al cliente: #{@sale.customer.nick_name} por $ #{@sale.total}"
           format.js { render 'create_credit_sale' }
         elsif @sale.reserved?
-          format.js { redirect_to new_cash_registers_move_path(:sale => @sale.id) }
+          format.js { redirect_to new_cash_registers_move_path(sale: @sale.id) }
         end
       else
         format.js
@@ -144,6 +133,7 @@ class SalesController < ApplicationController
       end
     end
   end
+  # rubocop:enable Metrics/BlockLength
 
   # PATCH/PUT /sales/1
   # PATCH/PUT /sales/1.json
@@ -161,21 +151,23 @@ class SalesController < ApplicationController
 
   # DELETE /sales/1
   # DELETE /sales/1.json
+  # rubocop:disable Metrics/BlockLength
   def destroy
     respond_to do |format|
       @sale.audit_comment = "Venta #{@sale.sale_code} cancelada."
-      if @sale.update_attributes(:status => :cancelled)
+      if @sale.update_attributes(status: :cancelled)
+        # rubocop:disable Metrics/BlockNesting
         if @sale.reserved?
           return_cash = params[:return_cash]
           if return_cash == 'true'
-            moves = CashRegistersMove.where(:sale_id => @sale.id, :move_type => 1)
+            moves = CashRegistersMove.where(sale_id: @sale.id, move_type: 1)
             if moves.present?
               if moves[0].open_cash_register.closed?
                 quantity_to_return = moves.sum(:quantity)
                 new_cash_move = CashRegistersMove.new
                 new_cash_move.skip_received_validation = true
-                new_cash_move.open_cash_register_id = current_user.get_open_cash_register.id
-                new_cash_move.payment_method_id = PaymentMethod.find_by(:isCash => 1).id
+                new_cash_move.open_cash_register_id = session[:open_cash_register_id]
+                new_cash_move.payment_method_id = PaymentMethod.find_by(isCash: 1).id
                 new_cash_move.quantity = quantity_to_return
                 new_cash_move.move_type = :egreso
                 new_cash_move.sale_id = @sale.id
@@ -188,15 +180,15 @@ class SalesController < ApplicationController
             end
           end
         elsif @sale.cash?
-          #checa si hay pagos de esta venta
-          moves = CashRegistersMove.where(:sale_id => @sale.id)
-          #si la caja sigue abierta, solo elimina los moves, si ya cortó, genera un egreso por esa cantidad
+          # checa si hay pagos de esta venta
+          moves = CashRegistersMove.where(sale_id: @sale.id)
+          # si la caja sigue abierta, solo elimina los moves, si ya corto, genera un egreso por esa cantidad
           if moves.present?
             if moves[0].open_cash_register.closed?
               new_cash_move = CashRegistersMove.new
               new_cash_move.skip_received_validation = true
-              new_cash_move.open_cash_register_id = current_user.pointsale.get_open_cash_register.id
-              new_cash_move.payment_method_id = PaymentMethod.find_by(:isCash => true).id
+              new_cash_move.open_cash_register_id = session[:open_cash_register_id]
+              new_cash_move.payment_method_id = PaymentMethod.find_by(isCash: true).id
               new_cash_move.quantity = moves.sum(:quantity)
               new_cash_move.move_type = :egreso
               new_cash_move.sale_id = moves[0].sale_id
@@ -209,68 +201,57 @@ class SalesController < ApplicationController
             end
           end
         elsif @sale.credit?
-          credit = Credit.find_by(:sale_id => @sale.id, :customer_id => @sale.customer_id)
-          credit.update_attributes(:status => :cancelled)
+          credit = Credit.find_by(sale_id: @sale.id, customer_id: @sale.customer_id)
+          credit.update_attributes(status: :cancelled)
         end
+        # rubocop:enable Metrics/BlockNesting
         @sale.sales_details.each do |detail|
-          detail.update_attributes(:status => :inactive)
-          stockProduct = AvailableProduct.find_by(:product_id => detail.product_id, :pointsale_id => @sale.get_pointsale.id)
-          unless stockProduct.blank?
-            # sumarle al stock del producto
-            stock = stockProduct.stock + detail.quantity
-            stockProduct.update_attributes(:stock => stock)
-            # guardar en bitacora de inventario
-            move = InventoriesMove.new
-            move.product_id = detail.product_id
-            move.sale_id = @sale.id
-            move.quantity = detail.quantity
-            move.move_type = "incoming"
-            move.reason = @sale.reserved? ? "sale_reserved_cancelled" : "sale_cancel"
-            move.save
-          end
+          detail.update_attributes(status: :inactive)
+          stock_product = AvailableProduct.find_by(product_id: detail.product_id, pointsale_id: @sale.get_pointsale.id)
+          next if stock_product.blank?
+          # sumarle al stock del producto
+          stock = stock_product.stock + detail.quantity
+          stock_product.update_attributes(stock: stock)
+          # guardar en bitacora de inventario
+          move = InventoriesMove.new
+          move.product_id = detail.product_id
+          move.sale_id = @sale.id
+          move.quantity = detail.quantity
+          move.move_type = "incoming"
+          move.reason = @sale.reserved? ? "sale_reserved_cancelled" : "sale_cancel"
+          move.save
         end
-        format.html { redirect_to (@sale.reserved? ? sales_reserved_path : sales_url),
-            warning: (@sale.reserved? ? "Apartado con folio #{@sale.sale_code} cancelado." : "Venta con folio #{@sale.sale_code} cancelado.") }
+        format.html { redirect_to (@sale.reserved? ? sales_reserved_path : sales_url), warning: (@sale.reserved? ? "Apartado con folio #{@sale.sale_code} cancelado." : "Venta con folio #{@sale.sale_code} cancelado.") }
         format.json { head :no_content }
       end
     end
   end
+  # rubocop:enable Metrics/BlockLength
 
   def find_sales_by_date
     respond_to do |format|
-      startDate = DateTime.parse(params[:begin_date])
-      endDate = DateTime.parse(params[:end_date])
-
-      if current_user.usertype == 'A'
-        @sales = Sale.where(:date_sale => startDate..endDate).where('saletype != 2').order(" created_at DESC ")
-      else
-        @sales = Pointsale.find(current_user.pointsale_id).sales.where(:date_sale => startDate..endDate).where('saletype != 2').order(" created_at DESC ")
-      end
+      start_date = DateTime.parse(params[:begin_date])
+      end_date = DateTime.parse(params[:end_date])
+      @sales = current_user.usertype == 'A' ? Sale.where(date_sale: start_date..end_date).where('saletype != 2').order(" created_at DESC ") : Pointsale.find(current_user.pointsale_id).sales.where(date_sale: start_date..end_date).where('saletype != 2').order(" created_at DESC ")
       format.js
     end
   end
 
   def find_customer_sales_by_date
     respond_to do |format|
-      startDate = DateTime.parse(params[:begin_date])
-      endDate = DateTime.parse(params[:end_date])
+      start_date = DateTime.parse(params[:begin_date])
+      end_date = DateTime.parse(params[:end_date])
       cliente = params[:cliente]
-
-      @sales = Sale.where(:date_sale => startDate..endDate, :customer_id => cliente).where('saletype != 2').order(" id DESC ")
-
-      format.js { render :action => "find_sales_by_date" }
+      @sales = Sale.where(date_sale: start_date..end_date, customer_id: cliente).where('saletype != 2').order(" id DESC ")
+      format.js { render action: "find_sales_by_date" }
     end
   end
 
   def find_reserved_sales_by_date
     respond_to do |format|
-      startDate = DateTime.parse(params[:begin_date])
-      endDate = DateTime.parse(params[:end_date])
-      if current_user.usertype == 'A'
-        @sales = Sale.where(:date_sale => startDate..endDate, :saletype => 2).order(" created_at DESC ")
-      else
-        @sales = Pointsale.find(current_user.pointsale_id).sales.where(:date_sale => startDate..endDate).where('saletype = 2').order(" created_at DESC ")
-      end
+      start_date = DateTime.parse(params[:begin_date])
+      end_date = DateTime.parse(params[:end_date])
+      @sales = current_user.usertype == 'A' ? Sale.where(date_sale: start_date..end_date, saletype: 2).order(" created_at DESC ") : Pointsale.find(current_user.pointsale_id).sales.where(date_sale: start_date..end_date).where('saletype = 2').order(" created_at DESC ")
       format.js
     end
   end
@@ -278,23 +259,22 @@ class SalesController < ApplicationController
   def return_expired
     @sale = Sale.find(params[:sale_id])
     respond_to do |format|
-      if @sale.update_attributes(:status => :cancelled_by_expiration)
+      if @sale.update_attributes(status: :cancelled_by_expiration)
         @sale.sales_details.each do |detail|
-          detail.update_attributes(:status => :inactive)
-          stockProduct = AvailableProduct.find_by(:product_id => detail.product_id, :pointsale_id => @sale.get_pointsale.id)
-          unless stockProduct.blank?
-            # sumarle al stock del producto
-            stock = stockProduct.stock + detail.quantity
-            stockProduct.update_attributes(:stock => stock)
-            # guardar en bitacora de inventario
-            move = InventoriesMove.new
-            move.product_id = detail.product_id
-            move.sale_id = @sale.id
-            move.quantity = detail.quantity
-            move.move_type = "incoming"
-            move.reason = "sale_expired"
-            move.save
-          end
+          detail.update_attributes(status: :inactive)
+          stock_product = AvailableProduct.find_by(product_id: detail.product_id, pointsale_id: @sale.get_pointsale.id)
+          next if stock_product.blank?
+          # sumarle al stock del producto
+          stock = stock_product.stock + detail.quantity
+          stock_product.update_attributes(stock: stock)
+          # guardar en bitacora de inventario
+          move = InventoriesMove.new
+          move.product_id = detail.product_id
+          move.sale_id = @sale.id
+          move.quantity = detail.quantity
+          move.move_type = "incoming"
+          move.reason = "sale_expired"
+          move.save
         end
         format.html { redirect_to sales_reserved_url, warning: "Productos reingresados al inventario del apartado #{@sale.sale_code}." }
         format.json { head :no_content }
@@ -305,8 +285,8 @@ class SalesController < ApplicationController
   def liquidate_reserve
     respond_to do |format|
       @sale = Sale.find(params[:sale_id])
-      @payments = CashRegistersMove.where(:sale_id => @sale.id, :status => 1)
-      format.js { redirect_to new_cash_registers_move_path(:sale => @sale.id) }
+      @payments = CashRegistersMove.where(sale_id: @sale.id, status: 1)
+      format.js { redirect_to new_cash_registers_move_path(sale: @sale.id) }
     end
   end
 
@@ -315,41 +295,29 @@ class SalesController < ApplicationController
   end
 
   def print_receipt
-    #ticket para la venta
+    # ticket para la venta
     respond_to do |format|
       sale = Sale.find(params[:sale_id])
       format.pdf do
-        render pdf: "ticket_venta_#{sale.id}",
-          template: "sales/receipt.pdf.erb",
-          layout: 'receipt.html.erb',
-          locals: { :sale => sale },
-          show_as_html: params.key?('debug'),
-          page_width: '80mm',
-          page_height: '300mm'
+        render pdf: "ticket_venta_#{sale.id}", template: "sales/receipt.pdf.erb", layout: 'receipt.html.erb', locals: { sale: sale }, show_as_html: params.key?('debug'), page_width: '80mm', page_height: '300mm'
       end
     end
   end
 
   def print_reserve_receipt
-    #ticket para apartado
+    # ticket para apartado
     respond_to do |format|
       sale = Sale.find(params[:sale_id])
       # debt = sale.cash_registers_moves.first.quantity
       debt = sale.cash_registers_moves.sum(:quantity)
       format.pdf do
-        render pdf: "ticket_apartado_#{sale.id}",
-          template: "sales/receipt_reserve.pdf.erb",
-          layout: 'receipt.html.erb',
-          locals: { :sale => sale, :debt => debt },
-          show_as_html: params.key?('debug'),
-          page_width: '80mm',
-          page_height: '300mm'
+        render pdf: "ticket_apartado_#{sale.id}", template: "sales/receipt_reserve.pdf.erb", layout: 'receipt.html.erb', locals: { sale: sale, debt: debt }, show_as_html: params.key?('debug'), page_width: '80mm', page_height: '300mm'
       end
     end
   end
 
   def print_credit_receipt
-    #ticket para credito
+    # ticket para credito
     respond_to do |format|
       sale = Sale.find(params[:sale_id])
       debt = 0
@@ -359,52 +327,34 @@ class SalesController < ApplicationController
       end
 
       format.pdf do
-        render pdf: "ticket_credito_#{sale.id}",
-          template: "sales/receipt_credit.pdf.erb",
-          layout: 'receipt.html.erb',
-          locals: { :sale => sale, :debt => debt },
-          show_as_html: params.key?('debug'),
-          page_width: '80mm',
-          page_height: '300mm'
+        render pdf: "ticket_credito_#{sale.id}", template: "sales/receipt_credit.pdf.erb", layout: 'receipt.html.erb', locals: { sale: sale, debt: debt }, show_as_html: params.key?('debug'), page_width: '80mm', page_height: '300mm'
       end
     end
   end
 
   def print_partial_payment_receipt
-    #ticket para abonos a apartado
+    # ticket para abonos a apartado
     respond_to do |format|
       sale = Sale.find(params[:sale_id])
       new_moves = CashRegistersMove.where(id: params[:new_moves_array])
       quantity = new_moves.sum(:quantity)
       format.pdf do
-        render pdf: "ticket_abono_apartado_#{sale.id}",
-          template: "sales/receipt_partial_payment.pdf.erb",
-          layout: 'receipt.html.erb',
-          locals: { :sale => sale, :new_payments_quantity => quantity, :moves => new_moves },
-          show_as_html: params.key?('debug'),
-          page_width: '80mm',
-          page_height: '300mm'
+        render pdf: "ticket_abono_apartado_#{sale.id}", template: "sales/receipt_partial_payment.pdf.erb", layout: 'receipt.html.erb', locals: { sale: sale, new_payments_quantity: quantity, moves: new_moves }, show_as_html: params.key?('debug'), page_width: '80mm', page_height: '300mm'
       end
     end
   end
 
   def print_credit_payment_receipt
-    #ticket para abonos a credito
+    # ticket para abonos a credito
     respond_to do |format|
       sale = Sale.find(params[:sale_id])
       deuda = params[:debts]
-      cash_move = CashRegistersMove.where(:sale_id => sale.id).last
+      cash_move = CashRegistersMove.where(sale_id: sale.id).last
       quantity = cash_move.quantity
-      debt = Credit.where(:customer_id => sale.customer_id).sum(:rest)
+      debt = Credit.where(customer_id: sale.customer_id).sum(:rest)
 
       format.pdf do
-        render pdf: "ticket_abono_credito_#{sale.id}",
-          template: "sales/receipt_credit_payment.pdf.erb",
-          layout: 'receipt.html.erb',
-          locals: { :sale => sale, :new_payment => quantity, :debt => debt, :deuda => deuda, :move => cash_move },
-          show_as_html: params.key?('debug'),
-          page_width: '80mm',
-          page_height: '300mm'
+        render pdf: "ticket_abono_credito_#{sale.id}", template: "sales/receipt_credit_payment.pdf.erb", layout: 'receipt.html.erb', locals: { sale: sale, new_payment: quantity, debt: debt, deuda: deuda, move: cash_move }, show_as_html: params.key?('debug'), page_width: '80mm', page_height: '300mm'
       end
     end
   end
@@ -417,7 +367,7 @@ class SalesController < ApplicationController
   def create_haggle
     respond_to do |format|
       @pre_sale = PreSale.find(params[:pre_sale])
-      @pre_sale.haggle =  params[:haggle].to_f
+      @pre_sale.haggle = params[:haggle].to_f
       @pre_sale.get_totals
       if @pre_sale.save
         format.js
@@ -428,38 +378,31 @@ class SalesController < ApplicationController
   def find_sales_by_dates_or_code
     respond_to do |format|
       if params[:sale_code].present?
-        @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(:sale_code => params[:sale_code], :saletype => 1).order("id DESC")
+        @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(sale_code: params[:sale_code], saletype: 1).order("id DESC")
       else
         start_date = DateTime.parse(params[:start_date])
         end_date = DateTime.parse(params[:end_date])
         product_id = params[:product_id]
-        if product_id.present?
-          @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(:date_sale => start_date..end_date, :saletype => 1).joins(:sales_details).where('sales_details.product_id = (?)', product_id).order("id DESC")
-        else
-          @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(:date_sale => start_date..end_date, :saletype => 1).joins(:sales_details).order("id DESC")
-        end
+        @sales = product_id.present? ? Pointsale.find(current_user.pointsale_id).sales.activas.where(date_sale: start_date..end_date, saletype: 1).joins(:sales_details).where('sales_details.product_id = (?)', product_id).order("id DESC") : Pointsale.find(current_user.pointsale_id).sales.activas.where(date_sale: start_date..end_date, saletype: 1).joins(:sales_details).order("id DESC")
       end
       format.js
     end
   end
 
   private
-    # Use callbacks to share common setup or constraints between actions.
-    def set_sale
-      @sale = Sale.find(params[:id])
-    end
 
-    def get_filters
-      if params[:current_page].blank?
-        @current_page = 1
-      else
-        @current_page = params[:current_page]
-      end
-      @filter = params[:filter]
-    end
+  # Use callbacks to share common setup or constraints between actions.
+  def set_sale
+    @sale = Sale.find(params[:id])
+  end
 
-    # Never trust parameters from the scary internet, only allow the white list through.
-    def sale_params
-      params.require(:sale).permit(:customer_id, :saletype, :amount, :tax, :discount, :total, :date_sale, :user_id, :seller_id, :sale_code, :credit_note)
-    end
+  def get_filters
+    @current_page = params[:current_page].blank? ? 1 : params[:filter]
+    @filter = params[:filter]
+  end
+
+  # Never trust parameters from the scary internet, only allow the white list through.
+  def sale_params
+    params.require(:sale).permit(:customer_id, :saletype, :amount, :tax, :discount, :total, :date_sale, :user_id, :seller_id, :sale_code, :credit_note)
   end
+end

+ 85 - 78
app/models/pointsale.rb

@@ -1,93 +1,100 @@
 class Pointsale < ActiveRecord::Base
-	##--- Associaciones
-	has_and_belongs_to_many :expensesconcepts
-	has_and_belongs_to_many :products,  :join_table => :available_products
-	has_many :purchases
-	has_many :pre_purchases
-	has_many :suppliers, :through => :purchases
-	has_many :inventories
-	has_many :users
-	has_many :credits
-	has_many :credit_payments
-	has_many :cash_registers
-	has_many :open_cash_registers, :through => :cash_registers
-	has_many :cash_outs, :through => :open_cash_registers
-	has_many :sales, :through => :open_cash_registers
-	has_many :expenses, :through => :open_cash_registers
-	has_many :sales_details, :through => :sales
-	has_many :product_wastes
-	has_many :transfers
-	has_many :sellers
-	has_many :products_returns
+  ##--- Associaciones
+  has_and_belongs_to_many :expensesconcepts
+  has_and_belongs_to_many :products, join_table: :available_products
+  has_many :purchases
+  has_many :pre_purchases
+  has_many :suppliers, through: :purchases
+  has_many :inventories
+  has_many :users
+  has_many :credits
+  has_many :credit_payments
+  has_many :cash_registers
+  has_many :open_cash_registers, through: :cash_registers
+  has_many :cash_outs, through: :open_cash_registers
+  has_many :sales, through: :open_cash_registers
+  has_many :expenses, through: :open_cash_registers
+  has_many :sales_details, through: :sales
+  has_many :product_wastes
+  has_many :transfers
+  has_many :sellers
+  has_many :products_returns
 
-	has_many :sales_details, :through => :sales
+  has_many :sales_details, through: :sales
 
-	accepts_nested_attributes_for :users
-	validates_associated :users , :on => :create
-	#has_attached_file :img_pointsale, :styles => { :medium => "250x80>", :thumb => "50x50>" }, :default_url => "/images/:style/missing.png"
+  accepts_nested_attributes_for :users
+  validates_associated :users, on: :create
+  # has_attached_file :img_pointsale, :styles => { :medium => "250x80>", :thumb => "50x50>" }, :default_url => "/images/:style/missing.png"
 
-	enum status: [ :erased, :active, :inactive ]
+  enum status: [:erased, :active, :inactive]
 
-	attr_accessor :skip_name_validation
-	attr_accessor :skip_products_validation
+  attr_accessor :skip_name_validation
+  attr_accessor :skip_products_validation
 
-	mount_uploader :img_pointsale, ImageUploader
+  mount_uploader :img_pointsale, ImageUploader
 
-	##--- Llevar registro de Actividad del usuario
-	audited
+  ##--- Llevar registro de Actividad del usuario
+  audited
 
-	##--- Validaciones previas de guardar
-	validates :name , presence: { message: "Debe capturar el nombre del punto de venta." },  unless: :skip_name_validation
-	validates :prefix, presence: { message: "Debe indicar el prefijo del punto de venta." },
-		length: {
-			maximum: 3, too_long: "El maximo de caracteres debe ser %{count}.",
-			minimum: 3, too_short: "El minimo de caracteres debe ser %{count}."
-		},
-		uniqueness: { message: "El prefijo ya fue utilizado, favor de especificar otro." }
-	#validates_attachment_content_type :img_pointsale, :content_type => /\Aimage\/.*\Z/
+  ##--- Validaciones previas de guardar
+  validates :name, presence: { message: "Debe capturar el nombre del punto de venta." }, unless: :skip_name_validation
+  validates :prefix, presence: { message: "Debe indicar el prefijo del punto de venta." }, length: { maximum: 3, too_long: "El maximo de caracteres debe ser %{count}.", minimum: 3, too_short: "El minimo de caracteres debe ser %{count}." }, uniqueness: { message: "El prefijo ya fue utilizado, favor de especificar otro." }
+  # validates_attachment_content_type :img_pointsale, :content_type => /\Aimage\/.*\Z/
 
-	##--- Tipo de vistas / consultas
-	scope :vigentes, -> { where("status != 0").order(" status ASC, name ASC") }
-	scope :activos, -> { where( "status = 1").order(" name ASC") }
-	scope :ignore_current, ->(pointsale_id) { where.not(id: pointsale_id) }
-	# def has_stock
+  ##--- Tipo de vistas / consultas
+  scope :vigentes, -> { where("status != 0").order("status ASC, name ASC") }
+  scope :activos, -> { where("status = 1").order("name ASC") }
+  scope :ignore_current, ->(pointsale_id) { where.not(id: pointsale_id) }
+  # def has_stock
 
-	def total_products(pointsale_id)
-		unless pointsale_id.nil?
-			Pointsale.find(pointsale_id).products.where("stock > 0").sum(:stock).to_i
-		end
-	end
+  def total_products(pointsale_id)
+    unless pointsale_id.nil?
+      Pointsale.find(pointsale_id).products.where("stock > 0").sum(:stock).to_i
+    end
+  end
 
-	def self.get_pointsale(id, option)
-		if option == "open_cash_register"
-			Pointsale.open_cash_registers.find(id)
-		end
-	end
+  def self.get_pointsale(id, option)
+    if option == "open_cash_register"
+      Pointsale.open_cash_registers.find(id)
+    end
+  end
 
-	def get_open_cash_register
-		# OpenCashRegister.where(:status => 0, :user_id => self.id)
-		self.open_cash_registers.where(:status => 0).last
-	end
+  def get_open_cash_register
+    open_cash_registers.where(status: 0).last
+  end
 
-	def self.delete_duplicates_available
-		ActiveRecord::Base.connection.exec_query('SELECT DISTINCT (a.product_id), a.pointsale_id,
-			COUNT (a.product_id) AS productos FROM available_products AS a WHERE
-			(SELECT COUNT (b.product_id) FROM available_products as b
-			WHERE b.product_id = a.product_id AND b.pointsale_id = a.pointsale_id
-			GROUP BY b.product_id, b.pointsale_id ) > 1 GROUP BY a.product_id, a.pointsale_id
-			ORDER BY productos DESC').each do | row |
+  def can_open_cash_register?
+    crs = cash_registers.activos
+    if crs.size == 1
+      # solo hay una caja, checar si esta abierta
+      # si esta abierta entonces, regresar false, para que no puedan abrirla otra vez
+      !open_cash_registers.abiertas.any?
+    else
+      # mas de una caja, checar si hay alguna que se pueda abrir
+      opened_cash_registers = OpenCashRegister.where(cash_register_id: crs.pluck(:id), status: 0)
+      # si el punto de venta tiene 2 cajas y nomas esta abierta una, regresar true para que puedan abrir la otra
+      crs.size > opened_cash_registers.size ? true : false
+    end
+  end
 
-			availables = AvailableProduct.where(:product_id => row["product_id"], :pointsale_id => row["pointsale_id"]).order('stock desc')
-			con_mayor_stock = availables[0]
-			diferentes = 0
-			availables.each do |ap|
-				if ap.id != con_mayor_stock.id
-					if ap.stock == 0 || ap.stock == con_mayor_stock.stock
-						ap.destroy
-					end
-				end
-			end
-		end
-		return 'termine carnalit0'
-	end
+  def self.delete_duplicates_available
+    ActiveRecord::Base.connection.exec_query('SELECT DISTINCT (a.product_id), a.pointsale_id,
+      COUNT (a.product_id) AS productos FROM available_products AS a WHERE
+      (SELECT COUNT (b.product_id) FROM available_products as b
+      WHERE b.product_id = a.product_id AND b.pointsale_id = a.pointsale_id
+      GROUP BY b.product_id, b.pointsale_id ) > 1 GROUP BY a.product_id, a.pointsale_id
+      ORDER BY productos DESC').each do |row|
+
+      availables = AvailableProduct.where(product_id: row["product_id"], pointsale_id: row["pointsale_id"]).order('stock desc')
+      con_mayor_stock = availables[0]
+      diferentes = 0
+      availables.each do |ap|
+        next unless ap.id != con_mayor_stock.id
+        if ap.stock.zero? || ap.stock == con_mayor_stock.stock
+          ap.destroy
+        end
+      end
+    end
+    'termine carnalit0'
+  end
 end

+ 44 - 44
app/views/cash_outs/receipt.pdf.erb

@@ -2,22 +2,22 @@
 	#products_table {
 	  border-collapse: collapse;
 	  page-break-inside:auto;
-	}   
+	}
 	#products_table tr {
-		page-break-inside:avoid; page-break-after:auto; 
-	}	
+		page-break-inside:avoid; page-break-after:auto;
+	}
 </style>
 <div class='pdf-body'>
   	<header class='document-header'>
     	<h1 class='text-center'>
-    		<% if pointsale.img_pointsale.present? %>
-      			<%= wicked_pdf_image_tag_for_public(pointsale.img_pointsale(:medium), :style => "margin-top:10px") %> 
-  			<% elsif @pos_config.ticket_img.present? %>
-      			<%= wicked_pdf_image_tag_for_public(@pos_config.ticket_img(:medium), :style => "margin-top:10px") %> 
-      		<% end %>
-    	</h1>    	
+	     <% if pointsale.img_pointsale? %>
+	       <%= wicked_pdf_image_tag_for_public(pointsale.img_pointsale_url, :style => "margin-top:10px") %>
+	     <% elsif @pos_config.ticket_img? %>
+	       <%= wicked_pdf_image_tag_for_public(@pos_config.ticket_img_url, :style => "margin-top:10px") %>
+	     <% end %>
+    	</h1>
   	</header>
-	<h3 class="text-center">Corte de caja <%= pointsale.name %></h3> 
+	<h3 class="text-center">Corte de caja <%= pointsale.name %></h3>
 
 	<div class="resume" style="border-bottom:1px solid black;">
 		<h4 style="margin-top:5px;margin-bottom:5px">RESUMEN</h4>
@@ -30,13 +30,13 @@
 		<strong>Realizó:</strong>&nbsp;&nbsp;
 			<%= cash_out.user.first_name %><br>
 		<strong>Recibió:</strong>&nbsp;&nbsp;
-			<%= cash_out.received_by.first_name %><br>			
+			<%= cash_out.received_by.first_name %><br>
 		<strong>Articulos:</strong>&nbsp;&nbsp;
 			<%= cash_out.open_cash_register.products.count %>
 		<% if cash_out.observations.present? %>
 			<br> <strong>Observaciones:</strong>&nbsp;&nbsp;
-				<%= cash_out.observations %>			
-		<% end %>			
+				<%= cash_out.observations %>
+		<% end %>
 	</div>
 
 	<div style="border-bottom:1px solid black; margin-top:10px">
@@ -46,27 +46,27 @@
 					<th style="text-align:left">Fondo anterior</th>
 					<th style="text-align:center">Efectivo en caja</th>
 					<th style="text-align:center">Retiro</th>
-					<th style="text-align:right">Fondo</th>					
+					<th style="text-align:right">Fondo</th>
 				</tr>
 			</thead>
 			<tbody>
 				<tr>
-				
+
 					<td style="text-align:left">
-						<%= number_to_currency(initial_cash, precision: 2) %> 
-					</td>				
+						<%= number_to_currency(initial_cash, precision: 2) %>
+					</td>
 					<td style="text-align:center">
-						<%= number_to_currency(cash_out.physical_cash, precision: 2) %> 
-					</td>	
+						<%= number_to_currency(cash_out.physical_cash, precision: 2) %>
+					</td>
 					<td style="text-align:center">
-						<%= number_to_currency(cash_out.received_cash, precision: 2) %> 
+						<%= number_to_currency(cash_out.received_cash, precision: 2) %>
 					</td>
 					<td style="text-align:right">
-						<%= number_to_currency(cash_out.cash_fund, precision: 2) %> 
-					</td>											
-				</tr>			
+						<%= number_to_currency(cash_out.cash_fund, precision: 2) %>
+					</td>
+				</tr>
 			</tbody>
-		</table>		
+		</table>
 	</div>
 
 	<div style="border-bottom:1px solid black; margin-top:10px">
@@ -83,20 +83,20 @@
 				</thead>
 				<tbody>
 					<tr>
-						<td style="text-align:left"> 
+						<td style="text-align:left">
 							<%= number_to_currency(detail.incoming, precision: 2) %>
 						</td>
 						<td style="text-align:center">
 							<%= number_to_currency(detail.outgoing, precision: 2) %>
 						</td>
 						<td style="text-align:right">
-							<%= number_to_currency(detail.total, precision: 2) %> 
-						</td>	
-					</tr>			
+							<%= number_to_currency(detail.total, precision: 2) %>
+						</td>
+					</tr>
 				</tbody>
-			</table>		
-		<% end %>		
-	</div>		
+			</table>
+		<% end %>
+	</div>
 	<div class="products" style="border:0px">
 		<h4 style="margin-top:5px;margin-bottom:5px">SALIDA DE MERCANCÍA</h4>
 		<table cellspacing="0" id="products_table">
@@ -109,9 +109,9 @@
 			</thead>
 			<tbody>
 				<% @details.each_with_index do |detail, key| %>
-					<% if  @details[key -1].present? 
+					<% if  @details[key -1].present?
 						last_one_category = @details[key -1]['parent'].present? ? @details[key -1]['parent'] : @details[key -1]['category'] %>
-					<% else 
+					<% else
 						last_one_category = ""
 					%>
 					<% end %>
@@ -119,10 +119,10 @@
 					<% if last_one_category != current_category %>
 						<tr style="margin-top:3px;margin-bottom:10px">
 							<td colspan="3"> <strong> <%= current_category %> </strong> </td>
-						</tr>					
+						</tr>
 					<% end %>
 					<tr>
-						<td valign="bottom"> 
+						<td valign="bottom">
 							<%= detail['quantity'] %>
 						</td>
 						<td style="text-align:center">
@@ -131,14 +131,14 @@
 						</td>
 						<td style="text-align:right"  valign="center">
 							<strong><%= number_to_currency(detail['total'], precision: 2) %></strong>
-						</td>	
+						</td>
 					</tr>
 					<tr style="<%= 'border-bottom:1px solid black;font-size:10px' if detail["discount"] == 0%>">
 						<td> </td>
 						<td style="text-align:center">
 							Precio de venta unitario (<%= number_to_currency(detail["price_sale"], precision: 2) %>)
 						</td>
-						<td style="text-align:right"> 
+						<td style="text-align:right">
 						 	<%= number_to_currency(detail["total_without_discount"], precision: 2) %>
 						</td>
 					</tr>
@@ -146,12 +146,12 @@
 						<tr style="border-bottom:1px solid black;font-size:10px">
 							<td> </td>
 							<td style="text-align:center">Descuento acumulado:</td>
-							<td style="text-align:right"> 
+							<td style="text-align:right">
 							 	- <%= number_to_currency(detail["discount"], precision: 2) %>
 							</td>
 						</tr>
-					<% end %>										
-				<% end %>			
+					<% end %>
+				<% end %>
 			</tbody>
 		</table>
 	</div>
@@ -169,18 +169,18 @@
 				<tbody>
 					<% @expenses.each do |expense| %>
 						<tr>
-							<td style="text-align:left"> 
+							<td style="text-align:left">
 				                <strong> <%= expense.expensesconcept.name %></strong> <br>
-				                <%= expense.observations %>						
+				                <%= expense.observations %>
 							</td>
 							<td style="text-align:right">
 								<%= number_to_currency(expense.quantity, precision: 2) %>
-							</td>						
+							</td>
 						</tr>
 					<% end %>
 				</tbody>
 			</table>
-		</div>	
+		</div>
 	<% end %>
 	<div style="margin-top:5px;">
 		<span style="text-decoration:underline">Nota:</span> Los productos que se muestran en el listado de salidas de mercancía, son productos de <span style="font-style:italic;"> ventas, apartados y creditos </span> que fueron registrados durante este corte.

+ 4 - 4
app/views/dashboard/index.html.erb

@@ -46,9 +46,9 @@
 						<%= render 'dashboard/dashboard_for_manager' %>
 					<% elsif current_user.usertype == 'C' %>
 						<%= render partial: 'dashboard/dashboard_for_cashier' %>
-						<%if @open_cash == true %>
+						<%if @need_to_open_cash %>
 							<%= render partial: 'open_cash_registers/new', formats: [:js] %>
-						<% end %>					
+						<% end %>
 					<% end %>
 				</div>
 				<!-- END PAGE CONTENT INNER -->
@@ -57,5 +57,5 @@
 		<!-- END PAGE CONTENT BODY -->
 		<!-- END CONTENT BODY -->
 	</div>
-	<!-- END CONTENT -->	
-</div>
+	<!-- END CONTENT -->
+</div>

+ 36 - 21
app/views/open_cash_registers/_form.html.erb

@@ -3,30 +3,41 @@
     <div id="error_explanation"></div>
     <div class="row">
       <div class="col-md-12">
+        <%
+          available_cash = Array.new
+          open_cash_registers = current_user.pointsale.open_cash_registers.abiertas
+
+          current_user.pointsale.cash_registers.activos.each do |cash|
+            is_opened = OpenCashRegister.where(:cash_register_id => cash.id, :status => '0').any?
+            available_cash << cash if is_opened == false
+          end
+        %>
+        <% unless open_cash_registers.blank? %>
+          <div class="alert alert-warning">
+            <strong>Ya hay caja(s) abiertas en el punto de venta:</strong><br>
+              <% open_cash_registers.each do |open_cash| %>
+              -<%= open_cash.cash_register.name %> <br>
+              <% end %>
+          </div>
+        <% end %>
         <!-- caja registradora -->
         <div class="form-group">
           <%= f.label :cash_register_id, "Caja registradora", {:class=>"col-md-offset-1 col-md-3 control-label"} do %> Caja registradora
           <span class="required">*</span>
           <% end %>
           <div class="input-group col-md-4 select2-bootstrap-prepend">
-            <% 
-              available_cash = Array.new
-              CashRegister.where(:pointsale_id => current_user.pointsale_id, :status => '1').find_each do |cash|
-                is_opened = OpenCashRegister.where(:cash_register_id => cash.id, :status => '0').any?
-                available_cash << cash if is_opened == false
-              end
-            %>
-            <%= f.collection_select :cash_register_id, available_cash, :id, :name, {:prompt => "Seleccione"}, {:class => "form-control select2" } %>
+            <%= f.collection_select :cash_register_id, available_cash, :id, :name, {:prompt => "Seleccione", :selected => (available_cash[0] if available_cash.size == 1)}, {:class => "form-control select2", :disabled =>  (true if available_cash.size == 1) } %>
+            <%= f.hidden_field :cash_register_id, {:id=>'cash_id'} %>
           </div>
-        </div> 
+        </div>
         <!-- initial cash -->
         <div class="form-group">
           <%= f.label :initial_cash, "Efectivo inicial", {:class=>"col-md-offset-1 col-md-3 control-label"} do %> Efectivo inicial <span class="required">*</span>
-          <% end %> 
+          <% end %>
           <div class="col-md-4" style="padding-left: 0px;padding-right:0px">
             <%= f.number_field :initial_cash, {:class=>"form-control"} %>
           </div>
-        </div>        
+        </div>
       </div>
     </div>
     <h4 class="form-section" style="margin:20px 0px 10px 0px"></h4>
@@ -52,24 +63,27 @@
     "hideMethod": "fadeOut"
   }
 
+  if ($('#open_cash_register_cash_register_id').val()) {
+    getCashFund($('#open_cash_register_cash_register_id').val());
+    $('#cash_id').val($('#open_cash_register_cash_register_id').val());
+  }
+
   $('#open_cash_register_cash_register_id').on('change', function() {
     if ($(this).val() != "") {
-      getCashFund( $(this).val() );
-      $('#openCashButton').attr('disabled', false);
-
+      getCashFund($(this).val());
+      $('#cash_id').val($('#open_cash_register_cash_register_id').val());
     } else {
       $('#openCashButton').attr('disabled', true);
     }
   });
-  
 
-  function submitForm() {   
-    var cash = parseInt($('#open_cash_register_initial_cash').val());
+
+  function submitForm() {
     if ($('#open_cash_register_cash_register_id').val() != "") {
       $('#open_cash_register_form').submit();
     } else {
       toastr["warning"]("Se debe indicar efectivo inicial.");
-    }  
+    }
   }
 
   function getCashFund(id) {
@@ -79,7 +93,8 @@
       dataType: 'json',
       success: function(data) {
         $('#open_cash_register_initial_cash').val(data);
-      },      
-    }); 
+        $('#openCashButton').attr('disabled', false);
+      },
+    });
   }
-</script>
+</script>

+ 11 - 11
app/views/open_cash_registers/_new.js.erb

@@ -1,18 +1,18 @@
 
 <script>
 $(document).on("ready", function() {
-	
-		$('#dialog h3.modal-title').html("Activar caja registradora");
-		// Render the edit form
-		$('.modal-body').html('<%= j render("open_cash_registers/form") %>');
-		// Show the dynamic dialog
-		$('#dialog').modal("show");
 
-		// Set focus to the first element
-		$('#dialog').on('shown.bs.modal', function () {
-	       $('.first_input').focus();
-	       $('#open_cash_register_cash_register_id').select2();
-		 });
+   $('#dialog h3.modal-title').html("Activar caja registradora");
+   // Render the edit form
+   $('.modal-body').html('<%= j render("open_cash_registers/form") %>');
+   // Show the dynamic dialog
+   $('#dialog').modal("show");
+
+   // Set focus to the first element
+   $('#dialog').on('shown.bs.modal', function () {
+        $('.first_input').focus();
+        $('#open_cash_register_cash_register_id').select2();
+    });
 });
 
 </script>

+ 11 - 0
app/views/open_cash_registers/new.js.erb

@@ -0,0 +1,11 @@
+$('#dialog h3.modal-title').html("Activar caja registradora");
+ // Render the edit form
+ $('.modal-body').html('<%= j render("open_cash_registers/form") %>');
+ // Show the dynamic dialog
+ $('#dialog').modal("show");
+
+ 	// Set focus to the first element
+ 	$('#dialog').on('shown.bs.modal', function () {
+    $('.first_input').focus();
+    $('#open_cash_register_cash_register_id').select2();
+  });

+ 24 - 12
app/views/sales/_form.html.erb

@@ -5,6 +5,16 @@
 		<!-- este error explanation es cuando falla alguna validacion de la venta en sí -->
 		<div class="alert alert-danger hidden" id="error_explanation_for_sale"></div>
 		<div class="row">
+			<!-- cuando no hay caja abierta -->
+			<% if @opened_cash_registers.blank?%>
+				<div class="alert alert-block alert-danger fade in">
+	        <h4 class="alert-heading">¡AVISO! no hay caja abierta</h4>
+	        <p> Para realizar una venta es necesario abrir una caja registradora. </p>
+	        <p>
+	        	<%= link_to "Abrir caja", new_open_cash_register_path, :remote => true, :class => 'btn btn-primary' %>
+	        </p>
+	      </div>
+			<% end %>
 			<!-- boton para resetear datos -->
 			<div class="col-md-offset-10 col-md-2">
 				<button id="reset_pre_sales" type="button" class="btn btn-warning" <%= @disabled_button ? 'disabled' : '' %> onclick="deletePreSales()">Restaurar venta</button>
@@ -38,20 +48,22 @@
 					</div>
 				</div>
 				<!-- open cash register -->
-				<% if current_user.usertype == 'C' %>
-					<%= f.hidden_field :open_cash_register_id, :value => @open_cash_register.id %>
-				<% end %>
-				<% if current_user.usertype == 'G' %>
-					<div class="form-group">
-						<%= f.label :open_cash_register_id, "Caja registradora", {:class=>"col-md-3 control-label"} do %> Caja registradora
-						<span class="required">*</span>
-						<% end %>
-						<div class="input-group col-md-6 select2-bootstrap-prepend">
+			<!-- 	< % if current_user.usertype == 'C' %>
+					< %= f.hidden_field :open_cash_register_id, :value => @open_cash_register.id %>
+				< % end %> -->
+				<div class="form-group">
+					<%= f.label :open_cash_register_id, "Caja registradora", {:class=>"col-md-3 control-label"} do %> Caja registradora
+					<span class="required">*</span>
+					<% end %>
+					<div class="input-group col-md-6 select2-bootstrap-prepend">
+						<% if @sale.open_cash_register.nil? %>
 							<%= f.select :open_cash_register_id, Pointsale.find(current_user.pointsale_id).open_cash_registers.abiertas.map{|o| [o.cash_register.name, o.id]}, {:prompt => "Seleccione"}, { :class => 'form-control select2', :disabled => @disabled_select } %>
-							 <%= f.hidden_field :open_cash_register_id, {:id => 'open_cash'} %>
-						</div>
+						<% else %>
+              <%= f.select :open_cash_register_id, @opened_cash_registers.map{|o| [o.cash_register.name, o.id]}, {:include_blank => "Seleccione", :selected => @sale.open_cash_register.id}, {:class => "form-control", :disabled => true }   %>
+						<% end %>
+						<%= f.hidden_field :open_cash_register_id, {:id => 'open_cash'} %>
 					</div>
-				<% end %>
+				</div>
 				<!-- cliente -->
 				<div class="form-group">
 					<%= f.label :customer_id, "Cliente", {:class=>"col-md-3 control-label"} do %> Cliente