| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465 |
- class SalesController < ApplicationController
- ##--- Abilities
- load_and_authorize_resource
- ##--- 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
- before_action :set_sale, only: [:show, :edit, :update, :destroy]
- before_action :get_filters, only: [:index, :show, :edit, :new, :sales_reserved]
- # GET /sales
- # GET /sales.json
- 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
- 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
- end
- # GET /sales/1
- # GET /sales/1.json
- def show
- @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)
- @returned_prods_ids = Array.new
- @returned_prods_ids = @products_return.products_return_ins.pluck(:product_id) if @products_return.present?
- end
- # GET /sales/new
- 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)
- @sale.saletype = 'cash'
- #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
- @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
- @disabled_select = true
- @disabled_button = false
- @enable_radios = false
- end
- end
- # GET /sales/1/edit
- def edit
- end
- # POST /sales
- # POST /sales.json
- def create
- respond_to do |format|
- @sale = Sale.new(sale_params)
- @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.status = :notpaid
- @sale.expiration_date = Date.today + @pos_config.days_cancel_reserved if @sale.reserved?
- @sale.audit_comment = "Venta #{@sale.sale_code} por #{@sale.total} creada."
- if @sale.save
- # agregar detalles de la venta
- @pre_sales.each do |pre_sale|
- detail = SalesDetail.new
- detail.product_id = pre_sale.product_id
- detail.unit_price = pre_sale.unit_price
- detail.quantity = pre_sale.quantity
- detail.amount = pre_sale.amount
- detail.tax = pre_sale.tax
- detail.discount = pre_sale.discount
- detail.total = pre_sale.total
- detail.special_price_id = pre_sale.special_price_id
- detail.status = :active
- @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
- end
- 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) }
- elsif @sale.credit?
- credit = Credit.new
- credit.customer_id = @sale.customer_id
- credit.pointsale_id = current_user.pointsale_id
- credit.sale_id = @sale.id
- credit.total = @sale.total
- credit.rest = @sale.total
- credit.status = "active"
- credit.credit_note = @sale.credit_note if @sale.credit_note.present?
- credit.save
- 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) }
- end
- else
- format.js
- format.json { render json: @sale.errors, status: :unprocessable_entity }
- end
- end
- end
- # PATCH/PUT /sales/1
- # PATCH/PUT /sales/1.json
- def update
- respond_to do |format|
- if @sale.update(sale_params)
- format.html { redirect_to @sale, notice: 'Venta modificada.' }
- format.json { render :show, status: :ok, location: @sale }
- else
- format.html { render :edit }
- format.json { render json: @sale.errors, status: :unprocessable_entity }
- end
- end
- end
- # DELETE /sales/1
- # DELETE /sales/1.json
- def destroy
- respond_to do |format|
- @sale.audit_comment = "Venta #{@sale.sale_code} cancelada."
- if @sale.update_attributes(:status => :cancelled)
- if @sale.reserved?
- return_cash = params[:return_cash]
- if return_cash == 'true'
- 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.quantity = quantity_to_return
- new_cash_move.move_type = :egreso
- new_cash_move.sale_id = @sale.id
- new_cash_move.concept = :sale
- new_cash_move.status = :active
- new_cash_move.save
- else
- moves.destroy_all
- end
- 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
- 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.quantity = moves.sum(:quantity)
- new_cash_move.move_type = :egreso
- new_cash_move.sale_id = moves[0].sale_id
- new_cash_move.concept = :sale
- new_cash_move.ticket = moves[0].sale.sale_code
- new_cash_move.status = :active
- new_cash_move.save
- else
- moves.destroy_all
- end
- end
- elsif @sale.credit?
- credit = Credit.find_by(:sale_id => @sale.id, :customer_id => @sale.customer_id)
- credit.update_attributes(:status => :cancelled)
- end
- @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
- 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.json { head :no_content }
- end
- end
- end
- 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
- 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])
- 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" }
- 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
- format.js
- end
- end
- def return_expired
- @sale = Sale.find(params[:sale_id])
- respond_to do |format|
- 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
- end
- format.html { redirect_to sales_reserved_url, warning: "Productos reingresados al inventario del apartado #{@sale.sale_code}." }
- format.json { head :no_content }
- end
- end
- end
- 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) }
- end
- end
- def cancel_reserved_sale
- @sale = Sale.find(params[:sale_id])
- end
- def print_receipt
- #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'
- end
- end
- end
- def print_reserve_receipt
- #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'
- end
- end
- end
- def print_credit_receipt
- #ticket para credito
- respond_to do |format|
- sale = Sale.find(params[:sale_id])
- debt = 0
- sale.customer.credits.activos.each do |credit|
- debt += credit.rest
- 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'
- end
- end
- end
- def print_partial_payment_receipt
- #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'
- end
- end
- end
- def print_credit_payment_receipt
- #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
- quantity = cash_move.quantity
- 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'
- end
- end
- end
- def add_haggle
- @pre_sale = PreSale.find(params[:pre_sale])
- @suggested_haggle = (@pos_config.haggle_in_sale_percent.to_f / 100) * @pre_sale.unit_price
- end
- def create_haggle
- respond_to do |format|
- @pre_sale = PreSale.find(params[:pre_sale])
- @pre_sale.haggle = params[:haggle].to_f
- @pre_sale.get_totals
- if @pre_sale.save
- format.js
- end
- end
- end
- 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")
- 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
- 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
- # 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
|