Jelajahi Sumber

Merge branch 'apply_rubocop' of SML/pos-boutique into master

Jose Miguel Ledon 7 tahun lalu
induk
melakukan
de125de5e4
56 mengubah file dengan 1931 tambahan dan 678 penghapusan
  1. 2 0
      .gitignore
  2. 9 0
      Gemfile
  3. 26 0
      Gemfile.lock
  4. 120 0
      app/controllers/application_controller.rb
  5. 236 10
      app/controllers/cash_outs_controller.rb
  6. 81 67
      app/controllers/cash_registers_moves_controller.rb
  7. 9 5
      app/controllers/customers_controller.rb
  8. 1 1
      app/controllers/pointsales_controller.rb
  9. 9 9
      app/controllers/sales_controller.rb
  10. 1 1
      app/controllers/units_controller.rb
  11. 8 0
      app/helpers/application_helper.rb
  12. 20 0
      app/helpers/cash_outs_helper.rb
  13. 13 0
      app/helpers/cash_registers_moves_helper.rb
  14. 65 42
      app/models/cash_registers_move.rb
  15. 4 4
      app/models/credit.rb
  16. 4 2
      app/models/credit_payment.rb
  17. 9 0
      app/models/invoice_detail.rb
  18. 6 6
      app/models/sale.rb
  19. 85 77
      app/views/billing_information/_form.html.erb
  20. 98 141
      app/views/cash_outs/_form.html.erb
  21. 36 0
      app/views/cash_outs/_general_public_invoice.html.erb
  22. 138 0
      app/views/cash_outs/cfdi_gpi.pdf.erb
  23. 5 0
      app/views/cash_outs/general_public_invoice.js.erb
  24. 1 0
      app/views/cash_outs/generate_gpi.js.erb
  25. 34 22
      app/views/cash_outs/index.html.erb
  26. 5 0
      app/views/cash_outs/print_invoice.js.erb
  27. 27 43
      app/views/cash_outs/show.html.erb
  28. 86 34
      app/views/cash_registers_moves/_abonoform.html.erb
  29. 7 9
      app/views/cash_registers_moves/_cash_registers_move.html.erb
  30. 72 10
      app/views/cash_registers_moves/_form.html.erb
  31. 118 63
      app/views/cash_registers_moves/_form_liquidate_reserved_sale.html.erb
  32. 94 30
      app/views/cash_registers_moves/_form_products_return.html.erb
  33. 20 20
      app/views/cash_registers_moves/create.js.erb
  34. 15 22
      app/views/customers/customer_sales.html.erb
  35. 1 1
      app/views/customers/debtors.html.erb
  36. 85 0
      app/views/layouts/cfdi.html.erb.html
  37. 36 0
      app/views/pointsales/_form.html.erb
  38. 8 8
      app/views/sales/receipt_credit_payment.pdf.erb
  39. 64 0
      config/application.rb
  40. 3 0
      config/routes.rb
  41. 7 0
      db/migrate/20181213183811_add_sales_invoice_column.rb
  42. 17 0
      db/migrate/20181213185244_create_invoice_details.rb
  43. 8 0
      db/migrate/20181213203152_add_invoice_columns_to_pointsale.rb
  44. 5 0
      db/migrate/20181213203326_add_column_to_billing_information.rb
  45. 5 0
      db/migrate/20181217171552_add_key_column_to_payment_method.rb
  46. 5 0
      db/migrate/20181217172147_add_key_column_to_products.rb
  47. 5 0
      db/migrate/20181217175547_add_key_column_to_unit.rb
  48. 8 0
      db/migrate/20181220182317_add_extra_info_columns_to_cash_registers_moves.rb
  49. 5 0
      db/migrate/20181221220426_add_cash_register_move_id_to_credit_payment.rb
  50. 82 50
      db/schema.rb
  51. 37 1
      db/seeds.rb
  52. TEMPAT SAMPAH
      facturacion/aaa010101aaa/aaa010101aaa__csd_01.cer
  53. TEMPAT SAMPAH
      facturacion/aaa010101aaa/aaa010101aaa__csd_01.key
  54. 3 0
      facturacion/cancelado.xml
  55. 3 0
      facturacion/generaxml.rb
  56. 80 0
      facturacion/timbrado.xml

+ 2 - 0
.gitignore

@@ -28,6 +28,8 @@ config/database.yml
 /bin/blockly_data/repos/
 /coverage
 public/system
+public/invoice
+public/uploads
 amada
 POS_variantes.bmpr
 POS_variantes.pdf

+ 9 - 0
Gemfile

@@ -38,6 +38,15 @@ gem 'jbuilder', '~> 2.0'
 # Gema para modificar la forma de mostrar el error resaltado en los input de la forma
 gem 'nokogiri'
 
+# dependencia de timbrado
+gem 'savon'
+
+# timbrado cfdi ProFact
+gem 'timbradocfdi', '~> 0.0.2'
+
+# numeros a letras CFDI
+gem 'number_to_words', '~> 1.2', '>= 1.2.1'
+
 ### javascripts y css
 # Use jquery as the JavaScript library
 gem 'sprockets-rails', require: 'sprockets/railtie'

+ 26 - 0
Gemfile.lock

@@ -48,6 +48,9 @@ GEM
       tzinfo (~> 1.1)
     acts-as-taggable-on (3.5.0)
       activerecord (>= 3.2, < 5)
+    akami (1.3.1)
+      gyoku (>= 0.4.0)
+      nokogiri
     arel (6.0.3)
     ast (2.3.0)
     audited (4.2.0)
@@ -118,6 +121,11 @@ GEM
       sass (>= 3.2)
     globalid (0.3.6)
       activesupport (>= 4.1.0)
+    gyoku (1.3.1)
+      builder (>= 2.1.2)
+    httpi (2.4.2)
+      rack
+      socksify
     i18n (0.7.0)
     iniparse (1.4.2)
     jbuilder (2.3.2)
@@ -148,6 +156,8 @@ GEM
     multi_json (1.11.2)
     nokogiri (1.6.6.2)
       mini_portile (~> 0.6.0)
+    nori (2.6.0)
+    number_to_words (1.2.1)
     orm_adapter (0.5.0)
     overcommit (0.37.0)
       childprocess (~> 0.5.8)
@@ -227,6 +237,14 @@ GEM
       sprockets (>= 2.8, < 4.0)
       sprockets-rails (>= 2.0, < 4.0)
       tilt (>= 1.1, < 3)
+    savon (2.11.1)
+      akami (~> 1.2)
+      builder (>= 2.1.2)
+      gyoku (~> 1.2)
+      httpi (~> 2.3)
+      nokogiri (>= 1.4.0)
+      nori (~> 2.4)
+      wasabi (~> 3.4)
     select2-rails (4.0.1)
       thor (~> 0.14)
     simple-line-icons-rails (0.0.1)
@@ -236,6 +254,7 @@ GEM
     simple_navigation_renderers (1.0.2)
       simple-navigation (~> 3.11)
     slop (3.6.0)
+    socksify (1.7.1)
     spring (1.4.0)
     sprockets (3.4.0)
       rack (> 1, < 3)
@@ -246,6 +265,7 @@ GEM
     thor (0.19.1)
     thread_safe (0.3.5)
     tilt (2.0.2)
+    timbradocfdi (0.0.2)
     toastr_rails (2.1.1)
     turbolinks (2.5.3)
       coffee-rails
@@ -263,6 +283,9 @@ GEM
     unicode-display_width (1.1.2)
     warden (1.2.4)
       rack (>= 1.0)
+    wasabi (3.5.0)
+      httpi (~> 2.0)
+      nokogiri (>= 1.4.2)
     web-console (2.2.1)
       activemodel (>= 4.0)
       binding_of_caller (>= 0.7.2)
@@ -306,6 +329,7 @@ DEPENDENCIES
   mini_magick
   momentjs-rails (>= 2.9.0)
   nokogiri
+  number_to_words (~> 1.2, >= 1.2.1)
   overcommit
   paperclip
   pdfjs_viewer-rails
@@ -318,11 +342,13 @@ DEPENDENCIES
   responders
   rubocop (~> 0.46.0)
   sass-rails (~> 5.0)
+  savon
   select2-rails
   simple-line-icons-rails
   simple_navigation_renderers
   spring
   sprockets-rails
+  timbradocfdi (~> 0.0.2)
   toastr_rails
   turbolinks
   twitter-typeahead-rails

+ 120 - 0
app/controllers/application_controller.rb

@@ -265,6 +265,126 @@ class ApplicationController < ActionController::Base
     render json: products
   end
 
+  ## ======= invoice methods =======
+  def check_directorys(t, move_type)
+    unless Dir.exist?(Rails.public_path.join("invoice", "cfdi")) # carpeta invoice
+      Dir.mkdir(Rails.public_path.join("invoice", "cfdi"))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi", t.strftime('%Y'))) # carpeta cfdi
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi", t.strftime("%Y")))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"))) # carpeta del año
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m")))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"), "xml")) # carpeta del mes
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}", "xml"))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"), "xml", move_type)) # carpeta de tipo de factura
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}/xml", move_type))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"), "pdf")) # carpeta para pdf
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}", "pdf"))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"), "pdf", move_type))
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}/pdf", move_type))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"), "qr"))
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}", "qr"))
+    end
+    unless Dir.exist?(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}", t.strftime("%m"), "qr", move_type))
+      Dir.mkdir(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}/qr", move_type))
+    end
+  end
+
+  def check_stamper_status
+    response = 500
+    uri = URI(Rails.application.config.issuing['stamper_uri'])
+    use_ssl = true
+    http = Net::HTTP.new(uri.host, uri.port)
+    http.use_ssl = use_ssl
+    http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+    http.start do
+      req = Net::HTTP::Get.new("/")
+      response = http.request(req)
+      return response.code
+    end
+  rescue
+    return 500
+  end
+
+  def create_invoice_qr(t, file_name, binary_qr, move_type)
+    File.open(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}/qr/#{move_type}", file_name), 'wb') do |file|
+      binary_data = Base64.decode64(binary_qr)
+      file << binary_data
+    end
+  end
+
+  def create_xml_stamped(t, file_name, stamped_xml, move_type)
+    File.open(Rails.public_path.join("invoice/cfdi/#{t.strftime('%Y')}/#{t.strftime('%m')}/xml/#{move_type}", file_name), 'w') do |file|
+      file << stamped_xml << "\n"
+    end
+  end
+
+  def get_attributes(created_at, amount, total, folio, payment_method_key, postal_code, serie, comprobante, pay_method)
+    attributes = {
+      "Version" => Rails.application.config.issuing['Version'].to_s,
+      "Serie" => serie,
+      "Folio" => folio,
+      "Fecha" => created_at,
+      "FormaPago" => payment_method_key,
+      "SubTotal" => amount,
+      "Moneda" => "MXN",
+      "Total" => total,
+      "TipoDeComprobante" => comprobante,
+      "MetodoPago" => pay_method,
+      "LugarExpedicion" => postal_code.to_s
+    }
+  end
+
+  def get_namespaces(type)
+    if type == "invoice" # factura
+      namespaces = {
+        "xmlns:tfd" => "http://www.sat.gob.mx/TimbreFiscalDigital",
+        "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
+        "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd"
+      }
+    elsif type == "complement" # complemento de pago
+      namespaces = {
+        "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
+        "xsi:schemaLocation" => "http://www.sat.gob.mx/cfd/3 http://www.sat.gob.mx/sitio_internet/cfd/3/cfdv33.xsd http://www.sat.gob.mx/Pagos http://www.sat.gob.mx/sitio_internet/cfd/Pagos/Pagos10.xsd"
+      }
+    end
+  end
+
+  def remove_invoice_files(uuid, file_id, url)
+    unless url.blank?
+      if File.exist?(Rails.root.join(url, "pdf", "#{uuid}_#{file_id}.pdf"))
+        File.delete(Rails.root.join(url, "pdf", "#{uuid}_#{file_id}.pdf"))
+      end
+      if File.exist?(Rails.root.join(url, "xml", "#{uuid}_#{file_id}.xml"))
+        File.delete(Rails.root.join(url, "xml", "#{uuid}_#{file_id}.xml"))
+      end
+    end
+  end
+
+  def remove_xml_origin(save_path)
+    if File.exist?(save_path)
+      File.delete(save_path)
+    end
+  end
+
+  def send_invoice(mail_attributes)
+    mail_response = InvoiceMailer.invoice_email_in(mail_attributes["name"], mail_attributes["email"], mail_attributes["attachments_name"], mail_attributes["attachments_url"]).deliver_now!
+    if mail_response.status.to_i == 250
+      return " Factura electrónica enviada exitosamente"
+    else
+      return " Error al enviar la factura electrónica"
+    end
+  rescue
+    return " [Revisar configuración de servicio de email]"
+  end
+  ## /////// invoice methods ///////
+
   protected
 
   def configure_permitted_parameters

File diff ditekan karena terlalu besar
+ 236 - 10
app/controllers/cash_outs_controller.rb


+ 81 - 67
app/controllers/cash_registers_moves_controller.rb

@@ -1,5 +1,6 @@
 class CashRegistersMovesController < ApplicationController
   before_action :set_cash_registers_move, only: [:show, :edit, :update, :destroy]
+  before_action :set_payment_methods, only: [:new, :register_payment]
 
   # GET /cash_registers_moves/new
   def new
@@ -7,7 +8,7 @@ class CashRegistersMovesController < ApplicationController
 
     if params[:sale].present?
       @sale = Sale.find(params[:sale])
-      @credito = Credit.where(customer_id: @sale.customer_id, status: "0").sum(:rest)
+      @credito = Credit.activos.where(customer_id: @sale.customer_id).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])
@@ -49,26 +50,28 @@ class CashRegistersMovesController < ApplicationController
     @products_return = ProductsReturn.find(params[:cash_registers_move][:products_return_id]) if params[:cash_registers_move][:products_return_id].present?
 
     respond_to do |format|
-      if @sale.present?
+      if !@cash_registers_move.valid?
+        format.js
+        format.json { render json: @cash_registers_move.errors, status: :unprocessable_entity }
+      elsif @sale.present?
         # calcular cambio cuando aplica.
         @cash_registers_move.calculate_quantities
-
+        @cash_registers_move.concept = :sale
         @cash_registers_move.move_type = :ingreso
 
+        if credit.present?
+          save_when_is_credit(@cash_registers_move, @sale)
+          @cash_registers_move.open_cash_register_id = session[:open_cash_register_id]
+        end
+
         if @sale.cash?
           @sale.update_attributes(status: :paid)
-          @cash_registers_move.concept = :sale
         elsif @sale.reserved?
           @cash_registers_move.status = :inactive
           @cash_registers_move.choose_concept_when_reserved
           @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 = session[:open_cash_register_id]
-        end
-
         message = "movimiento de efectivo por venta con folio #{@cash_registers_move.sale.sale_code}"
         @cash_registers_move.audit_comment = message
         if @cash_registers_move.save
@@ -88,7 +91,7 @@ class CashRegistersMovesController < ApplicationController
         if @cash_registers_move.save
           format.html { redirect_to purchases_path, success: 'Movimiento de efectivo realizado correctamente.' }
         else
-          format.html { render :new }
+          format.js
           format.json { render json: @cash_registers_move.errors, status: :unprocessable_entity }
         end
       elsif @products_return.present?
@@ -226,6 +229,14 @@ class CashRegistersMovesController < ApplicationController
     redirect_to new_cash_registers_move_path(sale: @sale, customer: @customer)
   end
 
+  def set_payment_methods
+    @is_cash = PaymentMethod.find_by(isCash: 1).id
+    @is_credit_card = PaymentMethod.find_by(method: "Tarjeta de credito").id
+    @is_debit_card = PaymentMethod.find_by(method: "Tarjeta de debito").id
+    @is_transfer = PaymentMethod.find_by(method: "Transferencia bancaria").id
+    @is_check = PaymentMethod.find_by(method: "Cheque").id
+  end
+
   private
 
   # Use callbacks to share common setup or constraints between actions.
@@ -235,68 +246,71 @@ class CashRegistersMovesController < ApplicationController
 
   # 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)
+    params.require(:cash_registers_move).permit(:payment_method_id, :quantity, :open_cash_register_id, :sale_id, :cardnumber, :ticket, :received, :change, :products_return_id, :bank_name, :check_number, :customer_account, :customer_code)
   end
 
-  def save_when_is_credit(credit)
-    abono = @cash_registers_move.quantity
-    abono_this_credit = abono >= credit.rest ? credit.rest : abono
-
-    # por si abonan dinero de mas, checar cuanto debe de ser de esta venta, y separarlo.
-    # @cash_registers_move.quantity = abono_this_credit
-    @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
-    # @credit_payment.quantity = abono_this_credit
-    @credit_payment.quantity = abono_this_credit
-
-    if @credit_payment.save
-      @cash_registers_move.credit_payment_id = @credit_payment.id
-      @cash_registers_move.concept = :credit_payment
-
-      if abono >= credit.rest # si se paga mas del adeudo de este credito
-        abono -= credit.rest
-
-        credit.update_attributes(rest: 0)
-        @sale.update_attributes(status: :paid)
+  def save_when_is_credit(cash_registers_move, sale)
+    if sale.paid?
+      sale = Sale.credit_pending(sale.customer_id).first
+    end
+    credit = Credit.find_by(sale_id: sale.id)
+    abono = cash_registers_move.received
+    total_debt = Credit.activos.where(customer_id: sale.customer_id)
+    @debt = total_debt.sum(:rest)
+    cash_registers_move.concept = :credit_payment
+    cash_registers_move.quantity = abono
+    cash_registers_move.change = 0
+    cash_registers_move.save
+
+    if abono >= total_debt.sum(:rest) # => liquidacion de la deuda total
+      nuevo_saldo = abono - total_debt.sum(:rest)
+      total_debt.each do |c|
+        sale = Sale.find_by_id(c.sale_id)
+        CreditPayment.create(credit_id: c.id, customer_id: sale.customer_id, pointsale_id: current_user.pointsale_id, status: "active", date_payment: Date.today, user_id: current_user.id, quantity: c.rest, cash_registers_move_id: cash_registers_move.id)
+        sale.update_attribute(:status, 2)
+      end
+      total_debt.update_all(rest: 0, status: 3)
+      cash_registers_move.update_attributes(change: nuevo_saldo, quantity: abono - nuevo_saldo) if cash_registers_move.payment_method.isCash?
+
+    elsif abono > credit.rest
+      CreditPayment.create(credit_id: credit.id, customer_id: sale.customer_id, pointsale_id: current_user.pointsale_id, status: "active", date_payment: Date.today, user_id: current_user.id, quantity: credit.rest, cash_registers_move_id: cash_registers_move.id)
+      abono -= credit.rest
+      credit.update_attributes(rest: 0, status: 3)
+      sale.update_attribute(:status, 2)
+      if abono > 0
+        new_debt(abono, cash_registers_move, sale)
+      elsif cash_registers_move.payment_method.isCash?
+        cash_registers_move.update_attributes(change: abono, quantity: cash_registers_move.quantity - abono)
+      end
+    else
+      CreditPayment.create(credit_id: credit.id, customer_id: sale.customer_id, pointsale_id: current_user.pointsale_id, status: "active", date_payment: Date.today, user_id: current_user.id, quantity: abono, cash_registers_move_id: cash_registers_move.id)
+      nuevo_saldo = credit.rest - abono
+      credit.update_attribute(:rest, nuevo_saldo)
+      sale.update_attribute(:status, 3)
+    end
+  end
 
-        # 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
-              next_credit_payment = CreditPayment.create(customer_id: credit.customer_id, credit_id: nextcredit.first.id, pointsale_id: credit.pointsale_id, quantity: abono, status: 0, date_payment: Date.today, user_id: current_user.id)
-              # next_credit_abono = @cash_registers_move.dup
-              # next_credit_abono.quantity = abono
-              # next_credit_abono.credit_payment_id = next_credit_payment.id
-              # next_credit_abono.save
-              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 -= 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
-          # rubocop:enable Metrics/BlockNesting
+  def new_debt(abono, cash_registers_move, sale)
+    until abono.zero?
+      next_sale = Sale.credit_pending(sale.customer_id).first
+      if next_sale.present?
+        credit = Credit.find_by(sale_id: next_sale.id)
+        if abono < credit.rest
+          cp = CreditPayment.create(credit_id: credit.id, customer_id: next_sale.customer_id, status: 0, date_payment: Date.today, user_id: current_user.id, quantity: abono, cash_registers_move_id: cash_registers_move.id)
+          nuevo_saldo = credit.rest - abono
+          abono = 0
+          credit.update_attribute(:rest, nuevo_saldo)
+          next_sale.update_attribute(:status, 3)
+        else
+          cp = CreditPayment.create(credit_id: credit.id, customer_id: next_sale.customer_id, status: 0, date_payment: Date.today, user_id: current_user.id, quantity: credit.rest, cash_registers_move_id: cash_registers_move.id)
+          abono -= credit.rest
+          credit.update_attributes(rest: 0, status: 3)
+          next_sale.update_attribute(:status, 2)
         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)
+        cash_registers_move.update_attribute(:change, abono)
+        abono = 0
       end
     end
-  end
+  end # new debt
 end

+ 9 - 5
app/controllers/customers_controller.rb

@@ -20,13 +20,17 @@ class CustomersController < ApplicationController
   end
 
   def debtors
-    @customers = Customer.where("customers.status != 0").includes(:sales, :credits).order('credits.id DESC')
+    @customers = Credit.joins(:customer).activos.select("customers.*").uniq
+    # @customers = Customer.where("customers.status != 0").includes(:sales, :credits).order('credits.id DESC')
   end
 
   def customer_sales
-    @custom = Customer.find(params[:customer_id])
-    @sales = Sale.where(customer_id: @custom.id, saletype: 0).order('created_at desc')
-    @credit = Credit.where(customer_id: @custom.id)
+    @customer = Customer.includes(:billing_information, :credits, :sales).find(params[:customer_id])
+    # @sales = Sale.where(customer_id: @custom.id, saletype: 0).order('created_at desc')
+    @sales = @customer.sales.includes(:seller, :credit)
+    @credits = @customer.credits
+    # @abonos = @customer.credit_payments.activos.select("credit_payments.*, sales.sale_code").order("credit_payments.created_at DESC")
+    # @credit = Credit.where(customer_id: @custom.id)
   end
 
   # apartados por cliente
@@ -130,6 +134,6 @@ class CustomersController < ApplicationController
 
   # Never trust parameters from the scary internet, only allow the white list through.
   def customer_params
-    params.require(:customer).permit(:nick_name, :phone, :email, :credit, :credit_limit, :time_limit, :notes, :status, billing_information_attributes: [:id, :name, :rfc, :address, :num_ext, :num_int, :zipcode, :state_id, :county_id, :city, :suburb], contact_attributes: [:id, :name, :last_name, :phone, :email])
+    params.require(:customer).permit(:nick_name, :phone, :email, :credit, :credit_limit, :time_limit, :notes, :status, billing_information_attributes: [:id, :name, :rfc, :address, :num_ext, :num_int, :zipcode, :state_id, :county_id, :city, :suburb, :cfdi_use_key], contact_attributes: [:id, :name, :last_name, :phone, :email])
   end
 end

+ 1 - 1
app/controllers/pointsales_controller.rb

@@ -207,6 +207,6 @@ class PointsalesController < ApplicationController
   end
 
   def pointsale_params
-    params.require(:pointsale).permit(:name, :address, :notes, :status, :prefix, :img_pointsale, :img_pointsale_cache, :ticket_footer, :haggle_percent, users_attributes: [:userid, :first_name, :last_name, :password, :email, :password_confirmation])
+    params.require(:pointsale).permit(:name, :address, :notes, :status, :prefix, :img_pointsale, :img_pointsale_cache, :ticket_footer, :haggle_percent, :tax_regime, :business_name, :federal_taxpayer_registration, :postal_code, users_attributes: [:userid, :first_name, :last_name, :password, :email, :password_confirmation])
   end
 end

+ 9 - 9
app/controllers/sales_controller.rb

@@ -66,16 +66,16 @@ class SalesController < ApplicationController
   # 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)
-      @sale.user_id = current_user.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?
-      @sale.audit_comment = "Venta #{@sale.sale_code} por #{@sale.total} creada."
+    @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 = session[:open_cash_register_id]
+    @sale.status = :notpaid
+    @sale.expiration_date = Date.today + @pos_config.days_cancel_reserved if @sale.reserved?
 
+    respond_to do |format|
       if @sale.save
+        @sale.audit_comment = "Venta #{@sale.sale_code} por #{@sale.total} creada."
         # agregar detalles de la venta
         @pre_sales.each do |pre_sale|
           detail = SalesDetail.new(product_id: pre_sale.product_id, unit_price: pre_sale.unit_price, quantity: pre_sale.quantity, amount: pre_sale.amount, tax: pre_sale.tax, discount: pre_sale.discount, total: pre_sale.total, special_price_id: pre_sale.special_price_id, status: :active, haggle: pre_sale.haggle, haggle_percent: pre_sale.haggle_percent)
@@ -314,7 +314,7 @@ class SalesController < ApplicationController
     # ticket para abonos a credito
     respond_to do |format|
       sale = Sale.find(params[:sale_id])
-      deuda = params[:debts]
+      deuda = params[:debts].to_f
       cash_move = CashRegistersMove.where(sale_id: sale.id).last
       quantity = cash_move.quantity
       debt = Credit.where(customer_id: sale.customer_id).sum(:rest)

+ 1 - 1
app/controllers/units_controller.rb

@@ -75,6 +75,6 @@ class UnitsController < ApplicationController
   end
 
   def unit_params
-    params.require(:unit).permit(:unit, :status)
+    params.require(:unit).permit(:unit, :status, :unit_key)
   end
 end

+ 8 - 0
app/helpers/application_helper.rb

@@ -11,4 +11,12 @@ module ApplicationHelper
   def wicked_pdf_barcode_image(img, options)
     image_tag "file://#{Rails.root.join('public', 'barcodes', img)}", options
   end
+
+  def wicked_pdf_image_tag_invoice(img, options = {})
+    image_tag "file://#{Rails.root.join('public', 'images', img)}", options
+  end
+
+  def wicked_pdf_image_tag_qr(img, options = {})
+    image_tag "file://#{Rails.root.join('public', img)}", options
+  end
 end

+ 20 - 0
app/helpers/cash_outs_helper.rb

@@ -19,4 +19,24 @@ module CashOutsHelper
       'DIFERENCIA POR DEVOLUCIÓN'
     end
   end
+
+  def move_concept_folio(move)
+    case move.concept
+    when "sale" then
+      content_tag(:span, move.sale.sale_code)
+    when "purchase" then
+      content_tag(:span, move.purchase.purchase_code)
+    when "expense" then
+      content_tag(:span, move.expense.expense_code)
+    # when "credit_payment" then
+    #   cp = CreditPayment.find_by(cash_registers_move_id: move.id)
+    #   unless cp.nil?
+    #     content_tag(:span, cp.id)
+    #   end
+    when "returned_money" then
+      content_tag(:span, ProductsReturn.find(move.products_return_id).return_code)
+    when "paid_product_change" then
+      content_tag(:span, ProductsReturn.find(move.products_return_id).return_code)
+    end
+  end
 end

+ 13 - 0
app/helpers/cash_registers_moves_helper.rb

@@ -1,2 +1,15 @@
 module CashRegistersMovesHelper
+  def display_additional_info(move)
+    case move.payment_method.method
+    when "Tarjeta de credito" then
+      "No. tarjeta: #{move.cardnumber}"
+    when "Tarjeta de debito" then
+      "No. tarjeta: #{move.cardnumber}"
+    when "Transferencia bancaria" then
+      "Referencia: #{move.customer_code}"
+    when "Cheque" then
+      s = "Folio de cheque: #{move.check_number}\nBanco: #{move.bank_name}\nCuenta: #{move.customer_account}"
+      s.gsub(/\n/, '<br />').html_safe
+    end
+  end
 end

+ 65 - 42
app/models/cash_registers_move.rb

@@ -20,8 +20,11 @@ class CashRegistersMove < ActiveRecord::Base
   validates_presence_of :quantity, message: "Debe indicar cantidad."
   validates_presence_of :payment_method_id, message: "Debe seleccionar método de pago."
   validates_presence_of :received, message: "Debe seleccionar monto recibido.", if: :in_cash?, unless: :skip_received_validation
+  validate :valid_info?, on: :create
 
-  scope :activos, -> { where("cash_registers_moves.status = ?", 1) }
+  scope :activos, -> { where(cash_registers_moves: { status: 1 }) }
+  scope :incomings, ->(open_cash_register) { includes(:open_cash_register).where(open_cash_register_id: open_cash_register, status: 1, move_type: 1) }
+  scope :outgoings, ->(open_cash_register) { includes(:open_cash_register).where(open_cash_register_id: open_cash_register, status: 1, move_type: 0) }
 
   def in_cash?
     cash_payment_id = PaymentMethod.find_by(isCash: 1).id
@@ -32,47 +35,68 @@ class CashRegistersMove < ActiveRecord::Base
     end
   end
 
-  # rubocop:disable Metrics/BlockNesting
-  def calculate_quantities
-    cash_payment_method_id = PaymentMethod.find_by(isCash: 1).id
-    # ventas
-    if sale.present?
-      if sale.cash?
-        if payment_method_id == cash_payment_method_id
-          sale_total = sale.total
-
-          already_paid = CashRegistersMove.where(sale_id: sale_id, open_cash_register_id: open_cash_register_id).sum(:quantity)
-          rest = sale_total - already_paid
-          if received.present?
-            self.change = rest > received ? 0 : received - rest
-            self.quantity = received > rest ? rest : received
-          end
-        else
-          self.quantity = received
-          self.change = 0
-        end
-      elsif sale.reserved? || sale.credit?
-        self.change = received.present? ? (received - quantity) : 0
+  def valid_info?
+    case payment_method.method
+    when "Tarjeta de credito", "Tarjeta de debito" then
+      if !cardnumber.present?
+        errors.add(:cardnumber, "Debe capturar los últimos 4 dígitos de la tarjeta.")
+      else
+        true
       end
-      # devoluciones
-    elsif products_return.present?
-      if payment_method_id == cash_payment_method_id
-        total = products_return.difference_amount
+    when "Transferencia bancaria" then
+      if !customer_code.present?
+        errors.add(:customer_code, "Debe capturar la referencia del cliente.")
+      else
+        true
+      end
+    when "Cheque" then
+      if !bank_name.present? || !check_number.present? || !customer_account.present?
+        errors.add(:base, "Debe capturar toda la información adicional del método de pago.")
+      else
+        true
+      end
+    else
+      true
+    end
+  end
 
+  def show_extras
+    case payment_method.method
+    when "Tarjeta de credito", "Tarjeta de debito" then # tarjetas
+      cardnumber
+    when "Transferencia bancaria" then # transferencia bancaria
+      "Referencia: #{customer_code}"
+    when "Cheque" then # cheque
+      "Banco: #{bank_name}"
+    when "Efectivo" then # efectivo
+      ""
+    end
+  end
+
+  def calculate_quantities
+    if payment_method.isCash?
+      if sale.present?
+        self.concept = :sale
+        total = sale.total
+        already_paid = CashRegistersMove.where(sale_id: sale_id, open_cash_register_id: open_cash_register_id).sum(:quantity)
+      elsif products_return.present?
+        total = products_return.difference_amount
         already_paid = CashRegistersMove.where(products_return_id: products_return_id, open_cash_register_id: open_cash_register_id).sum(:quantity)
+      end
 
-        rest = total - already_paid
-        if received.present?
-          self.change = received - (total - already_paid)
-          self.quantity = received > rest ? rest : received
-        end
-      else
-        self.quantity = received
-        self.change = 0
+      rest = total - already_paid
+      if sale.cash?
+        self.change = rest > received.to_f ? 0 : received.to_f - rest
+        self.quantity = received.to_f > rest ? rest : received.to_f
+      elsif sale.reserved? || sale.credit?
+        self.change = received.to_f > quantity ? received.to_f - quantity : 0
       end
+    else
+      # self.quantity = received.to_f
+      self.received = ""
+      self.change = 0
     end
   end
-  # rubocop:enable Metrics/BlockNesting
 
   def self.incomings_per_period(period)
     all_incomings = Array.new
@@ -101,12 +125,11 @@ class CashRegistersMove < ActiveRecord::Base
 
   def choose_concept_when_reserved
     reserve_has_moves = CashRegistersMove.where(sale_id: sale_id, move_type: 1, status: 1).any?
-    # rubocop:disable Style/ConditionalAssignment
-    if reserve_has_moves
-      self.concept = sale.reserve_debt > quantity ? :reserved_payment : :reserved_last_payment
-    else
-      self.concept = :reserved_first_payment
-    end
-    # rubocop:enable Style/ConditionalAssignment
+    self.concept =
+      if reserve_has_moves
+        sale.reserve_debt > quantity ? :reserved_payment : :reserved_last_payment
+      else
+        :reserved_first_payment
+      end
   end
 end

+ 4 - 4
app/models/credit.rb

@@ -4,11 +4,11 @@ class Credit < ActiveRecord::Base
   belongs_to :sale
 
   has_many :credit_payments
-  has_many :cash_registers_moves, :through => :credit_payments
+  has_many :cash_registers_moves, through: :credit_payments
 
-  enum status: [ :active, :cancelled, :expired ]
+  enum status: [:active, :cancelled, :expired, :liquidated]
 
-	scope :debtors, -> { where( "rest > 0").group(:customer_id).sum(:rest) }
+  scope :debtors, -> { where("rest > 0").group(:customer_id).sum(:rest) }
 
-	scope :activos, -> { where( "status != 1") }
+  scope :activos, -> { where(status: [0, 2]) }
 end

+ 4 - 2
app/models/credit_payment.rb

@@ -5,7 +5,9 @@ class CreditPayment < ActiveRecord::Base
   belongs_to :user
   belongs_to :credit
 
-	has_one :cash_registers_move
+  has_one :cash_registers_move
 
- 	enum status: [ :active, :cancelled ]
+  enum status: [:active, :cancelled]
+
+  scope :activos, -> { where(credit_payments: { status: 0 }) }
 end

+ 9 - 0
app/models/invoice_detail.rb

@@ -0,0 +1,9 @@
+class InvoiceDetail < ActiveRecord::Base
+  # has_and_belongs_to_many :credits, join_table: :invoice_credits
+
+  audited
+  enum status: [:cancelled, :active]
+
+  scope :activas, -> { where(invoice_details: { status: 1 }) }
+  scope :complementos, -> { activas.where(cfdi_type: "P") }
+end

+ 6 - 6
app/models/sale.rb

@@ -14,7 +14,7 @@ class Sale < ActiveRecord::Base
   has_many :products_returns
   has_many :pointsales, through: :open_cash_register
 
-    ##--- Llevar registro de Actividad del usuario
+  ##--- Llevar registro de Actividad del usuario
   audited
 
   enum status: [:notpaid, :cancelled, :paid, :parcial, :cancelled_by_expiration]
@@ -30,6 +30,7 @@ class Sale < ActiveRecord::Base
   accepts_nested_attributes_for :sales_details
 
   scope :activas, -> { where.not(sales: { status: 1 }) }
+  scope :credit_pending, ->(customer) { where(saletype: 0, status: [0, 3], customer_id: customer).order(:id) }
 
   def get_pointsale
     user.pointsale
@@ -62,7 +63,7 @@ class Sale < ActiveRecord::Base
       all_sales << obj
     end
     all_sales = all_sales.to_json
-    return all_sales
+    all_sales
   end
 
   def reserve_debt
@@ -71,17 +72,16 @@ class Sale < ActiveRecord::Base
   end
 
   def can_be_cancelled?(pos_config)
-    daysToCancel = pos_config.days_cancel_sale
-    if (date_sale + daysToCancel.days) >= Date.today && !cancelled?
+    if (date_sale + pos_config.days_cancel_sale.days) >= Date.today && !cancelled?
       # checar si la venta es de credito y ver si tiene pagos
       if credit?
         has_payments = CreditPayment.where(credit_id: credit.id).any?
         has_payments ? (return false) : (return true)
       else
-        return true
+        true
       end
     else
-      return false
+      false
     end
   end
 end

+ 85 - 77
app/views/billing_information/_form.html.erb

@@ -1,79 +1,87 @@
-			<h4 class="form-section">Información de facturación <small class="text-muted"> opcional</small></h4>
-			<div class="row">
-				<div class="form-group">
-					<%= b.label :name, "Razón social", {:class=>"col-md-3 control-label"} do %> Razón Social <span class="required">*</span>
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :name, {:class=>"form-control input-xlarge"} %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :rfc, "RFC", {:class=>"col-md-3 control-label"} do %> RFC <span class="required">*</span>
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :rfc, {:class=>"form-control input-small"} %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :address,  {:class=>"col-md-3 control-label"} do %> Dirección <!-- <span class="required">*</span> -->
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :address, {:class=>"form-control input-xlarge"} %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :num_ext,  {:class=>"col-md-3 control-label"} do %> No. Exterior <!-- <span class="required">*</span> -->
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :num_ext, {:class=>"form-control input-small"} %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :num_int, "No. Interior", {:class=>"col-md-3 control-label"} %> 
-					<div class="col-md-9">
-						<%= b.text_field :num_int, {:class=>"form-control input-small"} %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :zipcode, {:class=>"col-md-3 control-label"} do %> Código postal <span class="required">*</span>
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :zipcode, {:class=>"form-control input-small mask_number", :value => ((info.billing_information.nil? || info.billing_information.zipcode == 0) ? '' : info.billing_information.zipcode) } %>
-					</div>
-				</div>
+<h4 class="form-section">Información de facturación <small class="text-muted"> opcional</small></h4>
+<div class="row">
+  <div class="form-group">
+    <%= b.label :name, "Razón social", { class: "col-md-3 control-label" } do %> Razón Social <span class="required">*</span>
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :name, { class: "form-control input-xlarge" } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :cfdi_use_key, "UsoCFDI", { class: "col-md-3 control-label" } do %>
+      Uso de CFDI <span class="required">*</span>
+    <% end %>
+    <div class="col-md-9">
+      <%= b.select :cfdi_use_key, Rails.application.config.cfdiuse, { include_blank: "Seleccione", selected: ("Seleccione") }, { class: 'form-control input-xlarge' } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :rfc, "RFC", { class: "col-md-3 control-label" } do %> RFC <span class="required">*</span>
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :rfc, { class: "form-control input-medium" } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :address,  { class: "col-md-3 control-label" } do %> Dirección <!-- <span class="required">*</span> -->
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :address, { class: "form-control input-xlarge" } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :num_ext,  { class: "col-md-3 control-label" } do %> No. Exterior <!-- <span class="required">*</span> -->
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :num_ext, { class: "form-control input-small" } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :num_int, "No. Interior", { class: "col-md-3 control-label" } %>
+    <div class="col-md-9">
+      <%= b.text_field :num_int, { class: "form-control input-small" } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :zipcode, { class: "col-md-3 control-label" } do %> Código postal <span class="required">*</span>
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :zipcode, { class: "form-control input-small mask_number", :value => ((info.billing_information.nil? || info.billing_information.zipcode == 0) ? '' : info.billing_information.zipcode) } %>
+    </div>
+  </div>
 
-				<div class="form-group">
-					<%= b.label :state_id,  {:class=>"col-md-3 control-label"} do %>Estado <span class="required">*</span>
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.collection_select(:state_id, SpmxState.all, :id, :name , options ={:include_blank => "Seleccione"}, :class => "form-control input-medium state_id") %>
-					</div>
-				</div>
+  <div class="form-group">
+    <%= b.label :state_id,  { class: "col-md-3 control-label" } do %>Estado <span class="required">*</span>
+    <% end %>
+    <div class="col-md-9">
+      <%= b.collection_select(:state_id, SpmxState.all, :id, :name , options ={:include_blank => "Seleccione" }, :class => "form-control input-medium state_id") %>
+    </div>
+  </div>
 
-				<div class="form-group">
-					<%= b.label :county_id, {:class=>"col-md-3 control-label"} do %> Municipio <span class="required">*</span>
-					<% end %> 
-					<div class="col-md-9">
-						
-						<%= b.collection_select(:county_id, SpmxCounty.where(((info.billing_information.nil? || info.billing_information.state_id.nil?) ? "" : "state_id = #{info.billing_information.state_id}") ) , "id", "name", options ={:include_blank => "Seleccione"} , html_options ={ "data-opt-id" => "county_id", "data-option-dependent" => true, 
-							"data-option-observed" => "state_id",
-							"data-option-url" => "/getcounties/:state_id:.json",
-							"data-option-key-method" => :id,
-							"data-option-value-method" => :name, :class => "form-control input-medium county_id nestedselect"} ) %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :city,  {:class=>"col-md-3 control-label"} do %>Ciudad o localidad <!-- <span class="required">*</span> -->
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :city, {:class=>"form-control input-xlarge"} %>
-					</div>
-				</div>
-				<div class="form-group">
-					<%= b.label :suburb,  {:class=>"col-md-3 control-label"} do %>Colonia <!-- <span class="required">*</span> -->
-					<% end %> 
-					<div class="col-md-9">
-						<%= b.text_field :suburb, {:class=>"form-control input-xlarge"} %>
-					</div>
-				</div>
-			</div>
+  <div class="form-group">
+    <%= b.label :county_id, { class: "col-md-3 control-label" } do %> Municipio <span class="required">*</span>
+    <% end %>
+    <div class="col-md-9">
+
+      <%= b.collection_select(:county_id, SpmxCounty.where(((info.billing_information.nil? || info.billing_information.state_id.nil?) ? "" : "state_id = #{info.billing_information.state_id}") ) , "id", "name", options ={:include_blank => "Seleccione" } , html_options ={ "data-opt-id" => "county_id", "data-option-dependent" => true,
+        "data-option-observed" => "state_id",
+        "data-option-url" => "/getcounties/:state_id:.json",
+        "data-option-key-method" => :id,
+        "data-option-value-method" => :name, :class => "form-control input-medium county_id nestedselect" } ) %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :city,  { class: "col-md-3 control-label" } do %>Ciudad o localidad <!-- <span class="required">*</span> -->
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :city, { class: "form-control input-xlarge" } %>
+    </div>
+  </div>
+  <div class="form-group">
+    <%= b.label :suburb,  { class: "col-md-3 control-label" } do %>Colonia <!-- <span class="required">*</span> -->
+    <% end %>
+    <div class="col-md-9">
+      <%= b.text_field :suburb, { class: "form-control input-xlarge" } %>
+    </div>
+  </div>
+</div>

+ 98 - 141
app/views/cash_outs/_form.html.erb

@@ -34,80 +34,80 @@
       </ul>
     </div>
     <div class="col-md-offset-2 col-md-6" style="padding-right:0px">
-        <div class="form-group credit_limits">
-          <%= f.label :physical_cash, {:class=>"col-md-4 control-label"} do %>Efectivo en caja<span class="required">*</span> <% end %>
-          <div class="col-md-8">
-            <div class="input-group">
-              <span class="input-group-addon"> $ </span>
-              <%= f.text_field :physical_cash, {:class=>"form-control mask_decimal"} %>
-            </div>
-            <span class="help-block">Es el dinero que se tiene físicamente en caja. </span>
+      <div class="form-group credit_limits">
+        <%= f.label :physical_cash, {:class=>"col-md-4 control-label"} do %>Efectivo en caja<span class="required">*</span> <% end %>
+        <div class="col-md-8">
+          <div class="input-group">
+            <span class="input-group-addon"> $ </span>
+            <%= f.text_field :physical_cash, {:class=>"form-control mask_decimal"} %>
           </div>
+          <span class="help-block">Es el dinero que se tiene físicamente en caja. </span>
         </div>
-        <div class="form-group credit_limits">
-          <%= f.label :received_cash, {:class=>"col-md-4 control-label"} do %>Retiro de efectivo<span class="required">*</span> <% end %>
-          <div class="col-md-8">
-            <div class="input-group">
-              <span class="input-group-addon"> $ </span>
-              <%= f.text_field :received_cash, {:class=>"form-control mask_decimal", :onkeyup => "receivedAndFundCash()", :disabled => true} %>
-            </div>
+      </div>
+      <div class="form-group credit_limits">
+        <%= f.label :received_cash, {:class=>"col-md-4 control-label"} do %>Retiro de efectivo<span class="required">*</span> <% end %>
+        <div class="col-md-8">
+          <div class="input-group">
+            <span class="input-group-addon"> $ </span>
+            <%= f.text_field :received_cash, {:class=>"form-control mask_decimal", :onkeyup => "receivedAndFundCash()", :disabled => true} %>
           </div>
         </div>
-        <div class="form-group credit_limits">
-          <%= f.label :cash_fund, {:class=>"col-md-4 control-label"} do %>Fondo de caja<span class="required">*</span> <% end %>
-          <div class="col-md-8">
-            <div class="input-group">
-              <span class="input-group-addon"> $ </span>
-              <%= text_field_tag :cash_fund_display, '', class: "form-control mask_decimal", disabled: true %>
-                <!-- < %= f.hidden_field(:cash_fund) %> -->
-              <%= f.hidden_field :cash_fund, {:class=>"form-control mask_decimal"} %>
-            </div>
+      </div>
+      <div class="form-group credit_limits">
+        <%= f.label :cash_fund, {:class=>"col-md-4 control-label"} do %>Fondo de caja<span class="required">*</span> <% end %>
+        <div class="col-md-8">
+          <div class="input-group">
+            <span class="input-group-addon"> $ </span>
+            <%= text_field_tag :cash_fund_display, '', class: "form-control mask_decimal", disabled: true %>
+              <!-- < %= f.hidden_field(:cash_fund) %> -->
+            <%= f.hidden_field :cash_fund, {:class=>"form-control mask_decimal"} %>
           </div>
         </div>
-        <div class="form-group credit_limits">
-          <%= f.label :observations, {:class=>"col-md-4 control-label"} do %>Observaciones<span class="required" id="required_observations"></span> <% end %>
-          <div class="col-md-8">
-            <div class="input-group">
-              <span class="input-group-addon"> <i class="fa fa-comment-o"></i> </span>
-                <%= f.text_area :observations, {:class=>"form-control", :rows=>5 } %>
-            </div>
+      </div>
+      <div class="form-group credit_limits">
+        <%= f.label :observations, {:class=>"col-md-4 control-label"} do %>Observaciones<span class="required" id="required_observations"></span> <% end %>
+        <div class="col-md-8">
+          <div class="input-group">
+            <span class="input-group-addon"> <i class="fa fa-comment-o"></i> </span>
+              <%= f.text_area :observations, {:class=>"form-control", :rows=>5 } %>
           </div>
         </div>
+      </div>
     </div>
     <div class="row">
       <div class="col-md-12">
         <div class="table-scrollable">
-            <table class="table table-hover table-striped table-bordered" id="payment_methods_table">
-                <thead>
-                    <tr>
-                        <th> # </th>
-                        <th> Método de pago </th>
-                        <th> Total de ingresos (ventas) </th>
-                        <th> Total de egresos (gastos) </th>
-                        <th>Total (ventas y efectivo inicial)</th>
-                    </tr>
-                </thead>
-                <tbody>
-                  <% @payments.each_with_index do |payment, key| %>
-                    <tr id="payment_<%= payment['payment_method_id']%>">
-                      <td> <%= key +1 %> </td>
-                      <td> <%= payment["method"] %> </td>
-                      <td> <%= number_to_currency(payment["incoming"], precision: 2) %> </td>
-                      <td class="danger"> <%= number_to_currency(payment["outgoing"], precision: 2) %> </td>
-                      <td>
-                        <%= number_to_currency(payment["total"], precision: 2) %>
-                        <input class="hidden" value="<%= payment["total"] %>" id="<%=key + 1%>">
-                      </td>
-                    </tr>
-                        <%= f.fields_for :cash_out_details do |ff| %>
-                        <%= ff.hidden_field :payment_method_id, :value => payment["payment_method_id"] %>
-                        <%= ff.hidden_field :incoming, :value => payment["incoming"] %>
-                        <%= ff.hidden_field :outgoing, :value => payment["outgoing"] %>
-                        <%= ff.hidden_field :total, :value => payment["total"] %>
-                        <% end %>
+          <table class="table table-hover table-striped table-bordered" id="payment_methods_table">
+            <thead>
+              <tr>
+                <th> # </th>
+                <th> Método de pago </th>
+                <th> Total de ingresos (ventas) </th>
+                <th> Total de egresos (gastos) </th>
+                <th>Total (ventas y efectivo inicial)</th>
+              </tr>
+            </thead>
+            <tbody>
+              <% @payments.each_with_index do |payment, key| %>
+                <tr id="payment_<%= payment['payment_method_id']%>">
+                  <td> <%= key +1 %> </td>
+                  <td> <%= payment["method"] %> </td>
+                  <td> <%= number_to_currency(payment["incoming"], precision: 2) %> </td>
+                  <td class="danger"> <%= number_to_currency(payment["outgoing"], precision: 2) %> </td>
+                  <td>
+                    <%= number_to_currency(payment["total"], precision: 2) %>
+                    <input class="hidden" value="<%= payment["total"] %>" id="<%= key + 1 %>">
+                  </td>
+                </tr>
+                  <%= f.fields_for :cash_out_details do |ff| %>
+                    <%= ff.hidden_field :payment_method_id, :value => payment["payment_method_id"] %>
+                    <%= ff.hidden_field :incoming, :value => payment["incoming"] %>
+                    <%= ff.hidden_field :outgoing, :value => payment["outgoing"] %>
+                    <%= ff.hidden_field :total, :value => payment["total"] %>
                   <% end %>
-                </tbody>
-            </table>
+              <% end %>
+            </tbody>
+          </table>
         </div>
       </div>
     </div>
@@ -126,49 +126,17 @@
       </thead>
       <tbody>
         <% @incomings.each_with_index do |move, key| %>
-        <tr>
-          <td><%= key + 1 %></td>
-          <td>
-            <% case move.concept %>
-              <% when "sale",  "reserved_payment", "reserved_first_payment", "reserved_last_payment" %>
-                <%= move.sale.sale_code %>
-              <% when "purchase"%>
-                <%= move.purchase.purchase_code %>
-              <% when "expense"%>
-                <%= move.expense.expense_code %>
-              <% when "credit_payment"%>
-                <%= move.credit_payment.id %>
-              <% when "products_return"%>
-                <%= move.products_return.sale.sale_code %>
-            <% end %>
-          </td>
-          <td><%= move.open_cash_register.cash_register.name%></td>
-          <td><%= move.payment_method.method %></td>
-          <td><%= number_to_currency(move.quantity, precision: 2) %></td>
-          <td>
-            <% case move.concept %>
-              <% when "sale"%>
-                VENTA
-              <% when "purchase"%>
-                COMPRA CANCELADA
-              <% when "expense"%>
-                GASTO CANCELADO
-              <% when "credit_payment"%>
-                <strong>ABONO A CRÉDITO </strong><br>
-                cliente: <%= move.credit_payment.customer.nick_name %>
-              <% when "reserved_payment"%>
-                ABONO A APARTADO
-              <% when "reserved_first_payment" %>
-                ANTICIPO DE APARTADO
-              <% when "reserved_last_payment" %>
-                LIQUIDACIÓN DE APARTADO
-              <% when "products_return" %>
-                DIFERENCIA POR DEVOLUCIÓN
-            <% end %>
-          </td>
-          <td><%= l(move.created_at, :format => '%I:%M %p') %> </td>
-        </tr>
+          <tr <%= move.sale.cancelled? ? 'class=danger' : "" %>>
+            <td><%= key += 1 %></td>
+            <td><%= move_concept_folio(move) %></td>
+            <td><%= move.open_cash_register.cash_register.name %></td>
+            <td><%= move.payment_method.method %></td>
+            <td><%= number_to_currency(move.quantity, precision: 2) %></td>
+            <td><%= cash_move_type(move) %></td>
+            <td><%= l(move.created_at, format: '%I:%M %p') %> </td>
+          </tr>
         <% end %>
+        <!--  -->
       </tbody>
     </table>
 
@@ -187,42 +155,31 @@
       </thead>
       <tbody>
         <% @outgoings.each_with_index do |move, key| %>
-        <tr>
-          <td><%= key + 1 %></td>
-          <td>
-            <% case move.concept %>
-              <% when "sale",  "reserved_payment" %>
-                <%= move.sale.sale_code %>
-              <% when "purchase"%>
-                <%= move.purchase.purchase_code %>
-              <% when "expense"%>
-                <%= move.expense.expense_code %>
-              <% when "credit_payment"%>
-                <%= move.credit_payment.id %>
-            <% end %>
-          </td>
-          <td><%= move.open_cash_register.cash_register.name%></td>
-          <td><%= move.payment_method.method %></td>
-          <td><%= number_to_currency(move.quantity, precision: 2) %></td>
-          <td>
-            <% case move.concept %>
-              <% when "sale" %>
-                <% if move.sale.cash? %>
-                  VENTA CANCELADA
-                <% elsif move.sale.reserved? %>
-                  APARTADO CANCELADO
-                <% end %>
-              <% when "purchase"%>
-                COMPRA
-              <% when "expense"%>
-                <strong> <%= move.expense.expensesconcept.name %></strong> <br>
-                <%= move.expense.observations %>
-              <% when "credit_payment"%>
-                ABONO CANCELADO
-            <% end %>
-          </td>
-          <td><%= l(move.created_at, :format => '%I:%M %p') %> </td>
-        </tr>
+          <tr>
+            <td><%= key + 1 %></td>
+            <td><%= move_concept_folio(move) %></td>
+            <td><%= move.open_cash_register.cash_register.name %></td>
+            <td><%= move.payment_method.method %></td>
+            <td><%= number_to_currency(move.quantity, precision: 2) %></td>
+            <td>
+              <% case move.concept %>
+                <% when "sale" %>
+                  <% if move.sale.cash? %>
+                    VENTA CANCELADA
+                  <% elsif move.sale.reserved? %>
+                    APARTADO CANCELADO
+                  <% end %>
+                <% when "purchase" %>
+                  COMPRA
+                <% when "expense" %>
+                  <strong> <%= move.expense.expensesconcept.name %></strong> <br>
+                  <%= move.expense.observations %>
+                <% when "credit_payment" %>
+                  ABONO CANCELADO
+              <% end %>
+            </td>
+            <td><%= l(move.created_at, :format => '%I:%M %p') %> </td>
+          </tr>
         <% end %>
       </tbody>
     </table>
@@ -232,8 +189,8 @@
     <div style="margin-top: 30px">
       <div class="row">
         <div class="col-md-9">
-        <button type="button" class="btn green" onclick="addCashOut()" disabled id="submit_cash_out">Guardar</button>
-          <%= link_to 'Cancelar', root_path, {:class=>"btn default"} %>
+          <button type="button" class="btn green" onclick="addCashOut()" disabled id="submit_cash_out">Guardar</button>
+          <%= link_to 'Cancelar', root_path, { class: "btn default" } %>
         </div>
       </div>
     </div>

+ 36 - 0
app/views/cash_outs/_general_public_invoice.html.erb

@@ -0,0 +1,36 @@
+<div class="portlet-body form">
+  <%= form_tag(generate_gpi_path, method: "GET", remote: true, class: "form-horizontal", id: "general_public_invoice_form", onsubmit: "closeDialog()") do %>
+    <%= hidden_field_tag :generate, true %>
+    <div id="error_explanation"></div>
+    <div class="row">
+      <div class="col-md-12">
+        <!-- caja registradora -->
+        <div class="form-group">
+          <%= label_tag :total_for_invoice, "Total de ventas a contado", { class: "col-md-4 control-label" } do %> Total de ventas a contado <% end %>
+          <div class="col-md-8">
+            <div class="input-group">
+              <span class="input-group-addon"> $ </span>
+              <%= number_field_tag :total_for_invoice, format('%0.2f', @sales_total), { disabled: true, class: "form-control input-small" } %>
+              <%= hidden_field_tag :total_for_invoice, @sales_total %>
+              <%= hidden_field_tag :amount_for_invoice, @sales_amount %>
+              <%= hidden_field_tag :tax_for_invoice, @sales_tax %>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <h4 class="form-section" style="margin:20px 0px 10px 0px"></h4>
+    <div class="actions col-md-offset-3">
+      <!-- <button type="button" class="btn btn-success" onclick="submitForm()" id="gpibutton">Generar</button> -->
+      <%= submit_tag 'Generar factura', class: "btn btn-success" %>
+      <button type="button" class="btn default" onclick="closeDialog()" id="cancel">Cancelar</button>
+    </div>
+  <% end %>
+</div>
+
+<script>
+  function closeDialog() {
+    $(".modal-body").html('');
+    $('#dialog').modal('toggle');
+  }
+</script>

+ 138 - 0
app/views/cash_outs/cfdi_gpi.pdf.erb

@@ -0,0 +1,138 @@
+<div class='pdf-body' style="margin:50px;">
+  <header class='document-header'>
+  </header>
+  <section>
+    <article class="left-left logo" style="height:100px; width: 50%;margin-top: 2cm;">
+      <% if user.pointsale.img_pointsale? %>
+        <%= wicked_pdf_image_tag user.pointsale.img_pointsale_url, { width: 300, height: 80 } %>
+      <% end %>
+    </article>
+    <article style="width: 40%;float: right;text-align: right; margin-top: 2cm;">
+      <p style="margin: 5px; font-size: 14px; color: red;"><b>FACTURA</b></p>
+      <p style="margin: 5px; font-size: 11px;">Tipo de comprobante:&nbsp;<b><%= Rails.application.config.issuing['CveIngreso'].to_s %></b></p>
+      <p style="margin: 5px; font-size: 11px;">Serie: <b><%= doc.xpath("//@Serie")%></b> Folio: <b><%= doc.xpath("//@Folio")%></b></p>
+      <p style="margin: 5px; font-size: 11px;">Folio Fiscal (UUID):</b></p>
+      <p style="margin: 5px; font-size: 11px;"><b><%= doc.xpath("//cfdi:Complemento//@UUID")%></b></p>
+      <p style="margin: 5px; font-size: 11px;">No. de Serie del Certificado del CSD:</p>
+      <p style="margin: 5px; font-size: 11px;"><b><%= doc.xpath("//@NoCertificadoSAT") %></b></p>
+      <p style="margin: 5px; font-size: 11px;">C.P., fecha y hora de emision: </p>
+      <p style="margin: 5px; font-size: 11px;"><b><%= "#{doc.xpath('//cfdi:Comprobante/@LugarExpedicion')}, #{doc.xpath('//cfdi:Comprobante/@Fecha')}" %></b></p>
+      <p style="margin: 5px; font-size: 11px;">Id. Usu. - Usuario </p>
+      <p style="margin: 5px; font-size: 11px;"><b><%= "#{user.id} - #{user.first_name} #{user.last_name}" %></b></p>
+    </article>
+  </section>
+  <section style="margin-bottom: 5px;">
+    <article style="width: 40%;">
+    <fieldset style="border-color: #f2f2f2;"><legend><b>Emisor</b></legend>
+      <p style="margin: 5px; font-size: 10px;"><b><%= doc.xpath("//cfdi:Emisor/@Rfc")%></b></p>
+      <p style="margin: 5px; font-size: 10px;"><%= doc.xpath('//cfdi:Emisor/@Nombre') %></p>
+      <p style="margin: 5px; font-size: 10px;"><b><%= "#{doc.xpath('//cfdi:Emisor/@RegimenFiscal')} - #{Rails.application.config.issuing['regimenFiscal']}"%></b></p>
+    </fieldset>
+    </article>
+    <article style="width: 40%;">
+    <fieldset style="border-color: #f2f2f2;"><legend><b>Receptor</b></legend>
+      <p style="margin: 5px; font-size: 10px;"><b><%= doc.xpath("//cfdi:Receptor/@Rfc")%></b></p>
+    </fieldset>
+    </article>
+  </section>
+  <section class="products" style="height: auto;">
+    <table cellspacing="0" class="table">
+      <thead>
+        <tr>
+          <th style="text-align:center;font-weight:bold;width:5%;font-size:10px; padding: 2px;">Clave Prod.</th>
+          <th style="text-align:center;font-weight:bold;width:5%;font-size:10px; padding: 2px;">Cantidad</th>
+          <th style="text-align:center;font-weight:bold;width:5%;font-size:10px; padding: 2px;">Unidad de medida</th>
+          <th style="text-align:center;font-weight:bold;width:20%;font-size:10px; padding: 2px;">Descripcion</th>
+          <th colspan="2" style="text-align:center;font-weight:bold;width:10%;font-size:10px; padding: 2px;">Impuesto</th>
+          <th style="text-align:center;font-weight:bold;width:10%;font-size:10px; padding: 2px;">Precio unitario</th>
+          <th style="text-align:center;font-weight:bold;width:10%;font-size:10px; padding: 2px;">Importe</th>
+        </tr>
+      </thead>
+      <tbody>
+        <% concepts.each do |concept| %>
+        <tr>
+          <td style="font-size: 9px;">
+            <%= concept['ProductKey'] %>
+          </td>
+          <td style="font-size: 9px;">
+            <%= concept['Quantity'] %>
+          </td>
+          <td style="font-size: 9px;">
+            <%= concept['UnitKey'] %>
+          </td>
+          <td style="font-size: 9px; overflow:hidden;text-overflow:'';white-space:nowrap;max-width:200px;">
+            <%= concept['Description'] %>
+          </td>
+          <td style="font-size: 9px;">
+            <%= if concept['Tax'].to_f > 0.00; "002"; end; %>
+          </td>
+          <td style="font-size: 9px;">
+            <%= if concept['Tax'].to_f > 0.00 ; "$#{concept["Tax"].to_s}"; end; %>
+          </td>
+          <td style="font-size: 9px;">
+            <%= "$#{concept['Price']}" %>
+          </td>
+          <td style="font-size: 9px;">
+            <%= "$#{concept['Amount']}" %>
+          </td>
+        </tr>
+        <% end %>
+      </tbody>
+    </table>
+  </section>
+  <hr>
+  <section style="word-wrap: break-word;">
+    <article style="float:right;width: 17%;">
+      <p style="text-align:right; margin: 5px;font-size: 9px; background-color: #f2f2f2;">$ <%= doc.xpath("//cfdi:Comprobante/@SubTotal") %></p>
+      <p style="text-align:right; margin: 5px;font-size: 9px;">
+        <%= "#{doc.xpath('//cfdi:Impuestos/@TotalImpuestosTrasladados')}" if "$#{doc.xpath('//cfdi:Impuestos/@TotalImpuestosTrasladados')}"%><br></p>
+      <p style="text-align:right; margin: 5px;font-size: 9px; background-color: #f2f2f2;"><b>$<%= doc.xpath("//cfdi:Comprobante/@Total") %></b></p>
+    </article>
+    <article style="float:right; width: 10%;">
+      <p style="text-align:right; margin: 5px; font-size: 9px;"><b>Subtotal:</b></p>
+      <p style="text-align:right; margin: 5px; font-size: 9px;">IVA(16%):</p>
+      <p style="text-align:right; margin: 5px; font-size:9px;"><b>Total:</b></p>
+    </article>
+    <article style="float:right; width: 40%;">
+      <p style="font-size: 11px;"><b>Total con letra:</b></p>
+      <% numeros = doc.xpath("//cfdi:Comprobante/@Total").to_s.split('.') %>
+      <p style="font-size: 11px;">
+        <%= "#{numeros[0].to_i.to_words.split.each { |x| x.capitalize! }.join(' ')} Pesos #{numeros[1]}/100 M.N." %>
+      </p>
+    </article>
+    <article style="width: 30%;float:right;">
+      <p style="font-size: 10px;"><%= "#{doc.xpath('//@MetodoPago')}: Pago en una sola exhibición" %></p>
+      <% payment_method = PaymentMethod.find_by(payment_method_key: "#{doc.xpath('//cfdi:Comprobante/@FormaPago')}") %>
+      <p style="font-size: 10px;"><%= "#{doc.xpath('//cfdi:Comprobante/@FormaPago')} - #{payment_method.method}" %> </p>
+    </article>
+  </section>
+  <section style="word-wrap: break-word;">
+    <article style="width: 100%;">
+      <hr>
+      <p style="font-size: 9px;"><br><b>Sello Digital del CFDI:</b><br><%= doc.xpath("//@SelloCFD") %></p>
+      <p style="font-size: 9px;"><b>Sello del SAT:</b><br><%= doc.xpath("//@SelloSAT") %>
+      </p>
+    </article>
+  </section>
+  <section style="word-wrap: break-word;">
+    <article style="float:left;width: 20%; padding-top: 10px;">
+      <!-- < % wicked_pdf_image_tag("invoice_qr/qr_#{uuid}.png", width: "120", height: "120") %> -->
+      <%= wicked_pdf_image_tag_qr("#{qr_path}", width: "120", height: "120") %>
+    </article>
+    <article style="float:left;width: 80%">
+      <p style="font-size: 9px;">
+        <b >Cadena Original del complemento de certificación digital del SAT:</b><br>
+        <%= details %>
+      </p>
+      <p style="font-size: 9px;">
+        <b>No de Serie del Certificado del SAT:</b> <%= doc.xpath("//@NoCertificadoSAT") %>
+      </p>
+      <p style="font-size: 9px;">
+        <b>Fecha y hora de certificación:</b> <%= doc.xpath("//@FechaTimbrado") %>
+      </p>
+    </article>
+  </section>
+  <footer style="text-align:center;font-size:9px; margin-bottom: 3cm;">
+      <b>Este documento es una representación impresa de un CFDI</b>
+  </footer>
+</div>

+ 5 - 0
app/views/cash_outs/general_public_invoice.js.erb

@@ -0,0 +1,5 @@
+$('#dialog h3.modal-title').html("Factura a público general");
+// Render the edit form
+$('.modal-body').html('<%= j render("cash_outs/general_public_invoice") %>');
+// Show the dynamic dialog
+$('#dialog').modal("show");

+ 1 - 0
app/views/cash_outs/generate_gpi.js.erb

@@ -0,0 +1 @@
+location.reload();

+ 34 - 22
app/views/cash_outs/index.html.erb

@@ -115,29 +115,41 @@
                     </thead>
                     <tbody>
                       <% @cash_outs.each_with_index do |cash_out, key| %>
-                      <tr>
-                        <td><%= cash_out.id %></td>
-                        <% if current_user.usertype == "A" || current_user.usertype == "SS" %>
-                          <td>
-                          <%= OpenCashRegister.get_pointsale(cash_out.open_cash_register_id, "open_cash_register").name %>
-                          </td>
-                        <% end %>
-                        <td><%= cash_out.open_cash_register.cash_register.name %> </td>
-                        <td><%= number_to_currency(cash_out.amount_in, precision: 2) %> </td>
-                        <td><%= number_to_currency(cash_out.amount_out, precision: 2)  %></td>
-                        <td><%= number_to_currency(cash_out.amount_in - cash_out.amount_out, precision: 2)  %></td>
-                        <td><%= l(cash_out.created_at, :format => '%d/%B/%Y') %></td>
-                        <td><%= cash_out.user.first_name %></td>
-                        <td><%= (cash_out.received_by.blank? ? "" : cash_out.received_by.first_name) %></td>
-                        <td class="text-center">
-                          <%= link_to cash_out, {:class=>"btn btn-icon-only default filtros", :title=>"Ver corte de caja"} do %>
-                            <i class="fa fa-search"></i>
-                          <% end %>
-                          <%= link_to print_cash_out_receipt_path(cash_out.id, format: 'pdf'), {:class=>"btn btn-icon-only default", :target => "blank"} do %>
-                            <i class="fa fa-print"></i>
+                        <% horas_transcurridas = ((DateTime.now.to_time - cash_out.created_at.to_time).to_i/60)/60 %>
+                        <tr>
+                          <td><%= cash_out.id %></td>
+                          <% if current_user.usertype == "A" || current_user.usertype == "SS" %>
+                            <td>
+                            <%= OpenCashRegister.get_pointsale(cash_out.open_cash_register_id, "open_cash_register").name %>
+                            </td>
                           <% end %>
-                        </td>
-                      </tr>
+                          <td><%= cash_out.open_cash_register.cash_register.name %> </td>
+                          <td><%= number_to_currency(cash_out.amount_in, precision: 2) %> </td>
+                          <td><%= number_to_currency(cash_out.amount_out, precision: 2)  %></td>
+                          <td><%= number_to_currency(cash_out.amount_in - cash_out.amount_out, precision: 2)  %></td>
+                          <td><%= l(cash_out.created_at, :format => '%d/%B/%Y') %></td>
+                          <td><%= cash_out.user.first_name %></td>
+                          <td><%= (cash_out.received_by.blank? ? "" : cash_out.received_by.first_name) %></td>
+                          <td class="text-center">
+                            <%= link_to cash_out, {:class=>"btn btn-icon-only default filtros", :title=>"Ver corte de caja"} do %>
+                              <i class="fa fa-search"></i>
+                            <% end %>
+                            <%= link_to print_cash_out_receipt_path(cash_out.id, format: 'pdf'), {:class=>"btn btn-icon-only default", :target => "blank"} do %>
+                              <i class="fa fa-print"></i>
+                            <% end %>
+                            <% if can? :general_public_invoice, CashOut %>
+                              <% if cash_out.invoice_num.blank? && (cash_out.amount_in - cash_out.amount_out) > 0.0 && horas_transcurridas < 72 %>
+                                <%= link_to general_public_invoice_path(cash_out.id), remote: true, class: "btn btn-icon-only green", title: "Generar factura a público general" do %>
+                                  <i class="fa fa-envelope"></i>
+                                <% end %>
+                              <% elsif cash_out.invoice_num.present? %>
+                                <%= link_to print_gpi_path(cash_out.id), remote: true, class: "btn btn-icon-only default blue-madison", target: "blank", title: "Reimprimir factura" do %>
+                                  <i class="fa fa-file-text-o"></i>
+                                <% end %>
+                              <% end %>
+                            <% end %>
+                          </td>
+                        </tr>
                       <% end %>
                     </tbody>
                   </table>

+ 5 - 0
app/views/cash_outs/print_invoice.js.erb

@@ -0,0 +1,5 @@
+var invoice_window = window.open('<%= publicroot.reduced_path(file: "#{pdf_path}") %>', '_blank', '');
+
+// invoice_window.onload = function() {
+//  invoice_window.print();
+// };

+ 27 - 43
app/views/cash_outs/show.html.erb

@@ -240,28 +240,15 @@
 											</thead>
 											<tbody>
 								        <% @incomings.each_with_index do |move, key| %>
-									        <tr>
-									          <td><%= key + 1 %></td>
-									          <td>
-									            <% case move.concept %>
-        												<% when "sale",  "reserved_payment", "reserved_first_payment", "reserved_last_payment", "products_return" %>
-									                <%= move.sale.sale_code %>
-									              <% when "purchase"%>
-									                <%= move.purchase.purchase_code %>
-									              <% when "expense"%>
-									                <%= move.expense.expense_code %>
-									              <% when "credit_payment"%>
-									                <%= move.credit_payment.id %>
-									            <% end %>
-									          </td>
-									          <td><%= move.open_cash_register.cash_register.name%></td>
-									          <td><%= move.payment_method.method %></td>
-									          <td><%= number_to_currency(move.quantity, precision: 2) %></td>
-									          <td>
-                              <%= cash_move_type(move) %>
-							           		</td>
-									          <td><%= l(move.created_at, :format => '%I:%M %p') %> </td>
-									        </tr>
+								          <tr <%= move.sale.cancelled? ? 'class=danger' : "" %>>
+								            <td><%= key += 1 %></td>
+								            <td><%= move_concept_folio(move) %></td>
+								            <td><%= move.open_cash_register.cash_register.name %></td>
+								            <td><%= move.payment_method.method %></td>
+								            <td><%= number_to_currency(move.quantity, precision: 2) %></td>
+								            <td><%= cash_move_type(move) %></td>
+								            <td><%= l(move.created_at, format: '%I:%M %p') %> </td>
+								          </tr>
 								        <% end %>
 											</tbody>
 										</table>
@@ -290,33 +277,30 @@
 								        <% @outgoings.each_with_index do |move, key| %>
 									        <tr>
 									          <td><%= key + 1 %></td>
+									          <td><%= move_concept_folio(move) %></td>
+									          <td><%= move.open_cash_register.cash_register.name %></td>
+									          <td><%= move.payment_method.method %></td>
+									          <td><%= number_to_currency(move.quantity, precision: 2) %></td>
 									          <td>
 									            <% case move.concept %>
-									              <% when "sale",  "reserved_payment",  "credit_payment" %>
-									                <%= move.sale.sale_code %>
-									              <% when "purchase"%>
-									                <%= move.purchase.purchase_code %>
-									              <% when "expense"%>
-									                <%= move.expense.expense_code %>
+									              <% when "sale" %>
+									                <% if move.sale.cash? %>
+									                  VENTA CANCELADA
+									                <% elsif move.sale.reserved? %>
+									                  APARTADO CANCELADO
+									                <% end %>
+									              <% when "purchase" %>
+									                COMPRA
+									              <% when "expense" %>
+									                <strong> <%= move.expense.expensesconcept.name %></strong> <br>
+									                <%= move.expense.observations %>
+									              <% when "credit_payment" %>
+									                ABONO CANCELADO
 									            <% end %>
 									          </td>
-									          <td><%= move.open_cash_register.cash_register.name%></td>
-									          <td><%= move.payment_method.method %></td>
-									          <td><%= number_to_currency(move.quantity, precision: 2) %></td>
-									          <td>
-	                          	<% case move.concept %>
-	                          	<% when "sale" %>
-    	                        	Venta cancelada
-	                          	<% when "purchase" %>
-	                            	Compra
-	                          	<% when "expense" %>
-								                <strong> <%= move.expense.expensesconcept.name %></strong> <br>
-								                <%= move.expense.observations %>
-		                          <% end %>
-							           		</td>
 									          <td><%= l(move.created_at, :format => '%I:%M %p') %> </td>
 									        </tr>
-								        <% end %>
+									      <% end %>
 											</tbody>
 										</table>
 									</div>

+ 86 - 34
app/views/cash_registers_moves/_abonoform.html.erb

@@ -35,7 +35,7 @@
           <!-- recibido -->
           <div class="col-md-4">
             <div class="form-group">
-              <span class="help-block">monto recibido. </span>
+              <span class="help-block">Monto recibido </span>
               <div class="input-group col-md-11">
                 <span class="input-group-addon"> $ </span>
                 <%= f.number_field :received, { class: "form-control mask_decimal first_input", oninput: 'lock_button()' } %>
@@ -45,38 +45,56 @@
           <!-- cantidad -->
           <div class="col-md-4">
             <div class="form-group">
-              <span class="help-block">monto a ABONAR. </span>
+              <span class="help-block">Monto a ABONAR </span>
               <div class="input-group col-md-11">
                 <span class="input-group-addon"> $ </span>
                 <%= f.number_field :quantity, { class: "form-control mask_decimal", oninput: 'lock_button()' } %>
               </div>
             </div>
           </div>
-          <!-- metodo de pago -->
-          <div class="col-md-2">
-            <div class="form-group">
-              <span class="help-block">forma de pago. </span>
-              <div class="input-group col-md-12">
-                <%= f.select :payment_method_id, PaymentMethod.vigentes.map { |c| [c.method, c.id] }, {:include_blank => "Seleccione", :selected => @cash_id}, { class: "form-control" } %>
-              </div>
-            </div>
-          </div>
           <!-- boton agregar -->
           <div class="col-md-2" style="padding-right:0px; margin-top:30px">
             <button type="button" class="btn green pull-right" onclick="unlockSubmit()">Agregar</button>
           </div>
         </div>
+        <div class="col-md-4">
+          <div class="form-group">
+            <span class="help-block">Forma de pago </span>
+            <div class="input-group col-md-12">
+              <%= f.select :payment_method_id, PaymentMethod.vigentes.map { |c| [c.method, c.id] }, { include_blank: "Seleccione", selected: @cash_id }, { class: "form-control" } %>
+            </div>
+          </div>
+        </div>
         <!--  datos de la tarjeta cuando aplica -->
-        <div class="col-md-12" id="card_info" style="display: none;">
+        <div class="col-md-6" id="card_info" style="display: none;margin-top: 25px">
           <div class="form-group">
-            <%= f.label :cardnumber, { class: "col-md-3 control-label" } do %> Tarjeta: <span class="required">*</span>
-            <% end %>
+            <%= f.label :cardnumber, { class: "col-md-4 control-label" } do %> Tarjeta: <span class="required">*</span><% end %>
             <div class="col-md-8">
-              <%= f.text_field :cardnumber, { class: "form-control", maxlength: 4 } %>
-              <span class="help-block">Últimos 4 dígitos de la tarjeta. </span>
+              <%= f.text_field :cardnumber, { class: "form-control input-xsmall", maxlength: 4 } %>
+              <span class="help-block"><small>Últimos 4 dígitos de la tarjeta.</small></span>
             </div>
           </div>
         </div>
+        <!--  datos del cheque cuando aplica -->
+        <div class="col-md-12" id="check_info" style="display: none;padding-left: 10px">
+          <div class="form-group">
+            <%= f.label :bank_name, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Nombre del banco: <span class="required">*</span><% end %>
+            <%= f.text_field :bank_name, { class: "col-md-8 form-control", style: "width: 25%" } %>
+            <%= f.label :check_number, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Folio de cheque: <span class="required">*</span><% end %>
+            <%= f.text_field :check_number, { class: "col-md-8 form-control", style: "width: 25%" } %>
+          </div>
+          <div class="form-group">
+            <%= f.label :customer_account, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Número de cuenta: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_account, { class: "col-md-8 form-control input-medium", style: "width: 25%" } %>
+          </div>
+        </div>
+        <!--  datos de la transferencia cuando aplica -->
+        <div class="col-md-6" id="transfer_info" style="display: none;padding-left: 10px;margin-top: 25px">
+          <div class="form-group">
+            <%= f.label :customer_code, { class: "col-md-5 control-label" } do %> Referencia: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_code, class: "col-md-7 form-control input-small" %>
+          </div>
+        </div>
       </div>
       <!-- div para mostrar cambio -->
       <div class="col-md-offset-6 col-md-6">
@@ -97,7 +115,9 @@
 
 <% end %>
 <script type="text/javascript">
+  var totalInTable = 0;
   var timeout = null;
+
   $('#datetimepicker2').datetimepicker({
     icons: {
       date: "fa fa-calendar"
@@ -114,22 +134,58 @@
   $('#dialog .modal-dialog').removeClass('modal-lg');
 
   $('#cash_registers_move_payment_method_id').on('change', function() {
-    // $('#display_change').html(formatter.format(0));
+    var method = parseInt($(this).val());
     $('#display_change').html(accounting.formatMoney(0));
-
     $('#save_move').attr('disabled', true);
-    if ($(this).val() != <%= @cash_id %>) {
-      $("#card_info").fadeIn();
-      $('#cash_registers_move_received').attr('disabled', true);
-      $('#cash_registers_move_received').val("");
-    } else {
-      $("#card_info").fadeOut();
-      $("#cash_registers_move_cardnumber").val("");
-      $('#cash_registers_move_received').attr('disabled', false);
+
+    switch(method){
+      case 1:
+        // tarjeta de debito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 2:
+        // efectivo
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 3:
+        // transferencia bancaria
+        $('#transfer_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 5:
+        // cheque
+        $('#check_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        break;
+      case 4:
+        // tarjeta de credito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
     }
   });
 
-
   function unlockSubmit() {
     var method = $('#cash_registers_move_payment_method_id').val();
     var received = $('#cash_registers_move_received').val();
@@ -138,18 +194,14 @@
     var isReady = false;
 
     if (method == <%= @cash_id %>) {
-      var received = $('#cash_registers_move_received').val();
-      var quantity = $('#cash_registers_move_quantity').val();
       if(received && quantity && (quantity <= <%= @credito %> ) ) {
         change = received - quantity;
         isReady = true;
       } else {
         toastr["error"]("Hay datos que falta ingresar o la cantidad es incorrecta.");
       }
-    } else {
-      if (quantity) {
-        isReady = true;
-      }
+    } else if (quantity) {
+      isReady = true;
     }
 
     // $('#display_change').html(formatter.format(change));
@@ -157,7 +209,7 @@
 
     if (isReady) {
       $("#save_move").attr('disabled', false);
-    } else  {
+    } else {
       $("#save_move").attr('disabled', true);
     }
   }

+ 7 - 9
app/views/cash_registers_moves/_cash_registers_move.html.erb

@@ -1,10 +1,10 @@
 <tr id="cash_move_<%= @cash_registers_move.id %>">
-  	<% if (@cash_registers_move.sale.present? && (@cash_registers_move.sale.cash? || @cash_registers_move.sale.reserved?)) || @cash_registers_move.products_return.present? %>
-	  	<td>
-	  		<%= number_to_currency(@cash_registers_move.received, precision: 2) %>
-	  		<%= hidden_field_tag :received, @cash_registers_move.received %>
-	  	</td>
-  	<% end %>
+	<% if (@cash_registers_move.sale.present? && (@cash_registers_move.sale.cash? || @cash_registers_move.sale.reserved?)) || @cash_registers_move.products_return.present? %>
+  	<td>
+  		<%= number_to_currency(@cash_registers_move.received, precision: 2) %>
+  		<%= hidden_field_tag :received, @cash_registers_move.received %>
+  	</td>
+	<% end %>
   <td>
   	<%= hidden_field_tag :amount, @cash_registers_move.quantity %>
   	<%= number_to_currency(@cash_registers_move.quantity, precision: 2) %>
@@ -13,10 +13,8 @@
   	<%= hidden_field_tag :payment_type, @cash_registers_move.payment_method.id %>
   	<%= @cash_registers_move.payment_method.method %>
   </td>
-  <td> <%= @cash_registers_move.cardnumber %> </td>
+  <td> <%= display_additional_info(@cash_registers_move) %> </td>
   <td style="width: 5%" class="text-center">
     <button type="button" class="btn btn-icon-only btn-danger" onclick="deleteCashMove($(this))"><i class="fa fa-trash-o"></i></button>
   </td>
 </tr>
-
-

+ 72 - 10
app/views/cash_registers_moves/_form.html.erb

@@ -68,16 +68,35 @@
           <button id="addrowBtn" type="button" class="btn green pull-right" onclick="addRow()">Agregar pago</button>
         </div>
         <!--  datos de la tarjeta cuando aplica -->
-        <div class="col-md-12" id="card_info" style="display: none;">
+        <div class="col-md-6" id="card_info" style="display: none;margin-top: 25px">
           <div class="form-group">
-            <%= f.label :cardnumber, { class: "col-md-3 control-label" } do %> Tarjeta: <span class="required">*</span>
-            <% end %>
+            <%= f.label :cardnumber, { class: "col-md-4 control-label" } do %> Tarjeta: <span class="required">*</span><% end %>
             <div class="col-md-8">
-              <%= f.text_field :cardnumber, { class: "form-control input-small", maxlength: 4 } %>
-              <span class="help-block">Últimos 4 dígitos de la tarjeta. </span>
+              <%= f.text_field :cardnumber, { class: "form-control input-xsmall", maxlength: 4 } %>
+              <span class="help-block"><small>Últimos 4 dígitos de la tarjeta.</small></span>
             </div>
           </div>
         </div>
+        <!--  datos del cheque cuando aplica -->
+        <div class="col-md-12" id="check_info" style="display: none;padding-left: 10px">
+          <div class="form-group">
+            <%= f.label :bank_name, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Nombre del banco: <span class="required">*</span><% end %>
+            <%= f.text_field :bank_name, { class: "col-md-8 form-control", style: "width: 25%" } %>
+            <%= f.label :check_number, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Folio de cheque: <span class="required">*</span><% end %>
+            <%= f.text_field :check_number, { class: "col-md-8 form-control", style: "width: 25%" } %>
+          </div>
+          <div class="form-group">
+            <%= f.label :customer_account, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Número de cuenta: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_account, { class: "col-md-8 form-control input-medium", style: "width: 25%" } %>
+          </div>
+        </div>
+        <!--  datos de la transferencia cuando aplica -->
+        <div class="col-md-6" id="transfer_info" style="display: none;padding-left: 10px;margin-top: 25px">
+          <div class="form-group">
+            <%= f.label :customer_code, { class: "col-md-5 control-label" } do %> Referencia: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_code, class: "col-md-7 form-control input-small" %>
+          </div>
+        </div>
       </div>
       <div class="col-md-12">
         <table class="table table-striped table-hover table-bordered" id="payments_table">
@@ -148,11 +167,54 @@
   });
 
   $('#cash_registers_move_payment_method_id').on('change', function() {
-    if ($(this).val() != <%= @cash_id %>) {
-      $("#card_info").fadeIn();
-    } else {
-      $("#card_info").fadeOut();
-      $("#cash_registers_move_cardnumber").val("");
+    var method = parseInt($(this).val());
+    $('#display_change').html(accounting.formatMoney(0));
+
+    switch(method){
+      case 1:
+        // tarjeta de debito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 2:
+        // efectivo
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 3:
+        // transferencia bancaria
+        $('#transfer_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 5:
+        // cheque
+        $('#check_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        break;
+      case 4:
+        // tarjeta de credito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
     }
   });
 

+ 118 - 63
app/views/cash_registers_moves/_form_liquidate_reserved_sale.html.erb

@@ -28,26 +28,26 @@
       <div class="col-md-12">
         <h4 class="form-section" style="margin-bottom: 15px;margin-top: 15px;">Pagos anteriores</h4>
         <div class="table-scrollable table-scrollable-borderless">
-            <table class="table table-hover table-light">
-                <thead>
-                    <tr class="uppercase">
-                      <th>#</th>
-                      <th>Metodo de pago</th>
-                      <th>Monto</th>
-                      <th>Info. Adicional</th>
-                    </tr>
-                </thead>
-                <tbody>
-                  <% @payments.each_with_index do |payment, key| %>
-                    <tr>
-                      <td> <%= key + 1 %> </td>
-                      <td> <%= payment.payment_method.method %> </td>
-                      <td> <%= number_to_currency(payment.quantity, precision: 2) %> </td>
-                      <td> <%= payment.cardnumber %> </td>
-                    </tr>
-                  <% end %>
-                </tbody>
-            </table>
+          <table class="table table-hover table-light">
+              <thead>
+                <tr class="uppercase">
+                  <th>#</th>
+                  <th>Metodo de pago</th>
+                  <th>Monto</th>
+                  <th>Info. Adicional</th>
+                </tr>
+              </thead>
+              <tbody>
+                <% @payments.each_with_index do |payment, key| %>
+                  <tr>
+                    <td> <%= key + 1 %> </td>
+                    <td> <%= payment.payment_method.method %> </td>
+                    <td> <%= number_to_currency(payment.quantity, precision: 2) %> </td>
+                    <td> <%= payment.cardnumber %> </td>
+                  </tr>
+                <% end %>
+              </tbody>
+          </table>
         </div>
       </div>
       <div class="col-md-12">
@@ -68,7 +68,7 @@
           <!-- recibido -->
           <div class="col-md-4">
             <div class="form-group">
-              <span class="help-block">monto recibido. </span>
+              <span class="help-block">Monto recibido </span>
               <div class="input-group col-md-11">
                 <span class="input-group-addon"> $ </span>
                 <%= f.number_field :received, {:class=>"form-control mask_decimal first_input"} %>
@@ -78,7 +78,7 @@
           <!-- cantidad -->
           <div class="col-md-4">
             <div class="form-group">
-              <span class="help-block">monto a ABONAR. </span>
+              <span class="help-block">Monto a ABONAR </span>
               <div class="input-group col-md-11">
                 <span class="input-group-addon"> $ </span>
                 <%= f.number_field :quantity, {:class=>"form-control mask_decimal"} %>
@@ -88,9 +88,9 @@
           <!-- metodo de pago -->
           <div class="col-md-2">
             <div class="form-group">
-              <span class="help-block">forma de pago. </span>
+              <span class="help-block">Forma de pago </span>
               <div class="input-group col-md-12">
-                <%= f.select :payment_method_id, PaymentMethod.vigentes.map { |c| [c.method, c.id] }, {:include_blank => "Seleccione", :selected => @cash_id}, {:class => "form-control" }   %>
+                <%= f.select :payment_method_id, PaymentMethod.vigentes.map { |c| [c.method, c.id] }, { include_blank: "Seleccione", selected: @cash_id }, {:class => "form-control" } %>
               </div>
             </div>
           </div>
@@ -100,16 +100,35 @@
           </div>
         </div>
         <!--  datos de la tarjeta cuando aplica -->
-        <div class="col-md-offset-6 col-md-6" id="card_info" style="display: none;">
+        <div class="col-md-6" id="card_info" style="display: none;margin-top: 25px">
           <div class="form-group">
-            <%= f.label :cardnumber, {:class=>"col-md-2 control-label "} do %> Tarjeta: <span class="required">*</span>
-            <% end %>
-            <div class="col-md-6">
-              <%= f.text_field :cardnumber, { class: "form-control input-small", maxlength: 4 } %>
-              <span class="help-block">Últimos 4 dígitos de la tarjeta. </span>
+            <%= f.label :cardnumber, { class: "col-md-4 control-label" } do %> Tarjeta: <span class="required">*</span><% end %>
+            <div class="col-md-8">
+              <%= f.text_field :cardnumber, { class: "form-control input-xsmall", maxlength: 4 } %>
+              <span class="help-block"><small>Últimos 4 dígitos de la tarjeta.</small></span>
             </div>
           </div>
         </div>
+        <!--  datos del cheque cuando aplica -->
+        <div class="col-md-12" id="check_info" style="display: none;padding-left: 10px">
+          <div class="form-group">
+            <%= f.label :bank_name, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Nombre del banco: <span class="required">*</span><% end %>
+            <%= f.text_field :bank_name, { class: "col-md-8 form-control", style: "width: 25%" } %>
+            <%= f.label :check_number, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Folio de cheque: <span class="required">*</span><% end %>
+            <%= f.text_field :check_number, { class: "col-md-8 form-control", style: "width: 25%" } %>
+          </div>
+          <div class="form-group">
+            <%= f.label :customer_account, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Número de cuenta: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_account, { class: "col-md-8 form-control input-medium", style: "width: 25%" } %>
+          </div>
+        </div>
+        <!--  datos de la transferencia cuando aplica -->
+        <div class="col-md-6" id="transfer_info" style="display: none;padding-left: 10px;margin-top: 25px">
+          <div class="form-group">
+            <%= f.label :customer_code, { class: "col-md-5 control-label" } do %> Referencia: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_code, class: "col-md-7 form-control input-small" %>
+          </div>
+        </div>
       </div>
       <div class="col-md-12">
         <table class="table table-striped table-hover table-bordered" id="payments_table">
@@ -154,14 +173,54 @@
   });
 
   $('#cash_registers_move_payment_method_id').on('change', function() {
-    if ($(this).val() != <%= @cash_id %>) {
-      $("#card_info").fadeIn();
-      $('#cash_registers_move_received').attr('disabled', true);
-      $('#cash_registers_move_received').val("");
-    } else {
-      $("#card_info").fadeOut();
-      $("#cash_registers_move_cardnumber").val("");
-      $('#cash_registers_move_received').attr('disabled', false);
+    var method = parseInt($(this).val());
+    $('#display_change').html(accounting.formatMoney(0));
+
+    switch(method){
+      case 1:
+        // tarjeta de debito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 2:
+        // efectivo
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 3:
+        // transferencia bancaria
+        $('#transfer_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 5:
+        // cheque
+        $('#check_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        break;
+      case 4:
+        // tarjeta de credito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
     }
   });
 
@@ -176,13 +235,7 @@
     received = parseFloat($('#cash_registers_move_received').val());
     payment_method = $('#cash_registers_move_payment_method_id option:selected').val();
 
-    if (((quantity <= debt && quantity > 0) && (received >= quantity && payment_method == "2")) || (payment_method == "1" && quantity > 0) ) {
-      $('#cash_register_move_form').submit();
-    } else if (quantity > debt || quantity == 0) {
-      toastr["error"]("El monto a abonar no puede ser mayor al adeudo, ni puede ir en ceros");
-    } else if ((received <= 0 || quantity > received) && payment_method == "2") {
-      toastr["error"]("La cantidad recibida no puede ir en ceros, ni se puede abonar más de lo recibido");
-    }
+    $('#cash_register_move_form').submit();
   }
 
   function deleteCashMove(input) {
@@ -218,35 +271,37 @@
       totalInTable += parseFloat($(this).find("td:nth-child(2) input").val());
     });
 
-    // $('#display_debt').html(formatter.format(debt - totalInTable));
-    $('#display_debt').html(accounting.formatMoney(debt - totalInTable));
+    if (debt > totalInTable) {
+      $('#display_debt').html(accounting.formatMoney(debt - totalInTable));
+    } else {
+      $('#display_debt').html(accounting.formatMoney(0));
+    }
 
-    if ($("#save_move").prop('disabled')) {
-      $("#save_move").attr('disabled', false);
-    } else if (!$("#save_move").prop('disabled') && $('#payments_table tbody tr').length == 0) {
-      $("#save_move").attr('disabled', true);
+    if (totalInTable > 0) {
+      $('#save_move').attr('disabled', false);
+    } else {
+      $('#save_move').attr('disabled', true);
     }
   }
 
   function calculateChange() {
-    var total = parseFloat($('#reserve_sale_percent').val());
-    var received_cash = parseFloat($('#cash_registers_move_received').val());
+    var total = parseFloat($('#reserve_debt').val());
     totalInTable = 0;
-
+    var cash = 0;
+    var card = 0;
     $('#payments_table tbody tr').each(function() {
+      totalInTable += parseFloat($(this).find("td:nth-child(2) input").val());
       if ($(this).find("td:nth-child(3) input").val() == <%= @cash_id %>) {
-        totalInTable += parseFloat($(this).find("td:nth-child(2) input").val());
+        cash += parseFloat($(this).find("td:nth-child(1) input").val());
+      } else {
+        card += parseFloat($(this).find("td:nth-child(2) input").val());
       }
     });
-
-    var change = received_cash - totalInTable;
-    if (change > 0 && totalInTable > 0) {
-      // $('#display_change').html(formatter.format(change));
-      $('#display_change').html(accounting.formatMoney(change));
-
-    } else {
-      // $('#display_change').html(formatter.format(0));
+    rest = totalInTable - card;
+    if(cash + card == total || cash - rest <= 0 ){
       $('#display_change').html(accounting.formatMoney(0));
+    } else {
+      $('#display_change').html(accounting.formatMoney(cash - rest));
     }
   }
 </script>

+ 94 - 30
app/views/cash_registers_moves/_form_products_return.html.erb

@@ -58,7 +58,7 @@
           <div class="form-group">
             <div class="input-group col-md-12">
               <span class="help-block">seleccione forma de pago. </span>
-              <%= f.select :payment_method_id, PaymentMethod.vigentes.map {|c| [c.method, c.id] }, {:include_blank => "Seleccione", :selected => @cash_id}, {:class => "form-control" }   %>
+              <%= f.select :payment_method_id, PaymentMethod.vigentes.map { |c| [c.method, c.id] }, {:include_blank => "Seleccione", :selected => @cash_id}, {:class => "form-control" } %>
             </div>
           </div>
         </div>
@@ -67,30 +67,49 @@
           <button id="addrowBtn" type="button" class="btn green pull-right" onclick="addRow()">Agregar pago</button>
         </div>
         <!--  datos de la tarjeta cuando aplica -->
-        <div class="col-md-12" id="card_info" style="display: none;">
+        <div class="col-md-6" id="card_info" style="display: none;margin-top: 25px">
           <div class="form-group">
-            <%= f.label :cardnumber,  {:class=>"col-md-3 control-label "} do %> Tarjeta: <span class="required">*</span>
-            <% end %>
+            <%= f.label :cardnumber, { class: "col-md-4 control-label" } do %> Tarjeta: <span class="required">*</span><% end %>
             <div class="col-md-8">
-                <%= f.text_field :cardnumber, {:class => "form-control"}  %>
-                <span class="help-block">Ultimos 4 digitos de la tarjeta. </span>
+              <%= f.text_field :cardnumber, { class: "form-control input-xsmall", maxlength: 4 } %>
+              <span class="help-block"><small>Últimos 4 dígitos de la tarjeta.</small></span>
             </div>
           </div>
         </div>
+        <!--  datos del cheque cuando aplica -->
+        <div class="col-md-12" id="check_info" style="display: none;padding-left: 10px">
+          <div class="form-group">
+            <%= f.label :bank_name, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Nombre del banco: <span class="required">*</span><% end %>
+            <%= f.text_field :bank_name, { class: "col-md-8 form-control", style: "width: 25%" } %>
+            <%= f.label :check_number, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Folio de cheque: <span class="required">*</span><% end %>
+            <%= f.text_field :check_number, { class: "col-md-8 form-control", style: "width: 25%" } %>
+          </div>
+          <div class="form-group">
+            <%= f.label :customer_account, { class: "col-md-2 control-label", style: "padding-right: 5px" } do %> Número de cuenta: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_account, { class: "col-md-8 form-control input-medium", style: "width: 25%" } %>
+          </div>
+        </div>
+        <!--  datos de la transferencia cuando aplica -->
+        <div class="col-md-6" id="transfer_info" style="display: none;padding-left: 10px;margin-top: 25px">
+          <div class="form-group">
+            <%= f.label :customer_code, { class: "col-md-5 control-label" } do %> Referencia: <span class="required">*</span><% end %>
+            <%= f.text_field :customer_code, class: "col-md-7 form-control input-small" %>
+          </div>
+        </div>
       </div>
       <div class="col-md-12">
         <table class="table table-striped table-hover table-bordered" id="payments_table">
-            <thead>
-                <tr>
-                    <th> Recibido </th>
-                    <th> Cobro </th>
-                    <th> Forma de pago </th>
-                    <th> Info. adicional </th>
-                    <th> Acciones </th>
-                </tr>
-            </thead>
-            <tbody>
-            </tbody>
+          <thead>
+            <tr>
+              <th> Recibido </th>
+              <th> Cobro </th>
+              <th> Forma de pago </th>
+              <th> Info. adicional </th>
+              <th> Acciones </th>
+            </tr>
+          </thead>
+          <tbody>
+          </tbody>
         </table>
       </div>
       <!-- div para mostrar total -->
@@ -108,6 +127,7 @@
         <button type="button" class="btn green btn-block" id="save_move" disabled onclick="confirmPayments()">Cobrar</button>
       </div>
     </div>
+  </div>
 <% end %>
 <script type="text/javascript">
   // var received_cash = 0;
@@ -138,11 +158,54 @@
   });
 
   $('#cash_registers_move_payment_method_id').on('change', function() {
-    if ($(this).val() != <%= @cash_id %>) {
-      $("#card_info").fadeIn();
-    } else {
-      $("#card_info").fadeOut();
-      $("#cash_registers_move_cardnumber").val("");
+    var method = parseInt($(this).val());
+    $('#display_change').html(accounting.formatMoney(0));
+
+    switch(method){
+      case 1:
+        // tarjeta de debito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 2:
+        // efectivo
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 3:
+        // transferencia bancaria
+        $('#transfer_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#check_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
+      case 5:
+        // cheque
+        $('#check_info').fadeIn();
+        $('#card_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_cardnumber").val("");
+        break;
+      case 4:
+        // tarjeta de credito
+        $('#card_info').fadeIn();
+        $('#check_info').fadeOut();
+        $('#transfer_info').fadeOut();
+        $("#cash_registers_move_bank_name").val("");
+        $("#cash_registers_move_check_number").val("");
+        $("#cash_registers_move_customer_account").val("");
+        break;
     }
   });
 
@@ -217,21 +280,22 @@
 
   function calculateChange() {
     var total = parseFloat($('#products_return_total').val());
-    var received_cash  = parseFloat($('#cash_registers_move_received').val());
+    var received_cash = parseFloat($('#cash_registers_move_received').val());
     totalInTable = 0;
 
     $('#payments_table tbody tr').each(function() {
+      totalInTable += parseFloat($(this).find("td:nth-child(2) input").val());
       if ($(this).find("td:nth-child(3) input").val() == <%= @cash_id %>) {
-        totalInTable += parseFloat($(this).find("td:nth-child(2) input").val());
+        cash += parseFloat($(this).find("td:nth-child(1) input").val());
+      } else {
+        card += parseFloat($(this).find("td:nth-child(2) input").val());
       }
     });
-
-    var change = received_cash - totalInTable;
-    if (change > 0 && totalInTable > 0) {
-      $('#display_change').html(accounting.formatMoney(change));
-    } else {
+    rest = totalInTable - card;
+    if(cash + card == total || cash - rest <= 0 ){
       $('#display_change').html(accounting.formatMoney(0));
-
+    } else {
+      $('#display_change').html(accounting.formatMoney(cash - rest));
     }
   }
 </script>

+ 20 - 20
app/views/cash_registers_moves/create.js.erb

@@ -1,27 +1,27 @@
-$("#error_explanation_move").html("")
+$("#error_explanation_move").html("");
 <% if @cash_registers_move.errors.any? %>
-	$('#error_explanation_move').removeClass('hidden');
+  $('#error_explanation_move').removeClass('hidden');
     <% @cash_registers_move.errors.values.each do |message| %>
         $("#error_explanation_move").append($("<li />").html("<%= message.first.to_s %>"));
     <% end %>
 <% else %>
-	if($("#error_explanation_move").is(':visible')) {
-		$("#error_explanation_move").addClass('hidden');
-	}
+  if($("#error_explanation_move").is(':visible')) {
+    $("#error_explanation_move").addClass('hidden');
+  }
 
-	<% if @sale.present? && @sale.saletype == 'credit' %>
-		window.location = "<%= debtors_path %>";
-		var ticket_window = window.open("<%= print_credit_payment_receipt_path(:sale_id => @sale.id, :debts => @debt, format: 'pdf') %>", 'New tab', '' );
-	<% else %>
-		var newRow = $('<%= j render (@cash_registers_move) %>');
-		$('#payments_table tbody').append(newRow);
-		$('#cash_registers_move_quantity').val('');
-		$('#cash_registers_move_payment_method_id').val('');
-		$('#cash_registers_move_received').attr('disabled', false);
-		if($("#card_info").is(":visible")) {
-			$('#cash_registers_move_cardnumber').val('');
-			$("#card_info").fadeOut();
-		}
-		unlockConfirmPayment();
-	<% end %>
+  <% if @sale.present? && @sale.saletype == 'credit' %>
+    window.location = "<%= debtors_path %>";
+    var ticket_window = window.open("<%= print_credit_payment_receipt_path(:sale_id => @sale.id, :debts => @debt, format: 'pdf') %>", 'New tab', '' );
+  <% else %>
+    var newRow = $('<%= j render (@cash_registers_move) %>');
+    $('#payments_table tbody').append(newRow);
+    $('#cash_registers_move_quantity').val('');
+    $('#cash_registers_move_payment_method_id').val('');
+    $('#cash_registers_move_received').attr('disabled', false);
+    if($("#card_info").is(":visible")) {
+      $('#cash_registers_move_cardnumber').val('');
+      $("#card_info").fadeOut();
+    }
+    unlockConfirmPayment();
+  <% end %>
 <% end %>

+ 15 - 22
app/views/customers/customer_sales.html.erb

@@ -16,7 +16,7 @@
 		<!-- BEGIN PAGE CONTENT BODY -->
 		<div class="page-content">
 			<div class="container-fluid">
-				<%= link_to  debtors_path(:filter => @filter, :current_page => @current_page), {:class=>"btn blue-hoki pull-right margin-bottom-10"} do %>  <i class="fa fa-angle-left "></i> Regresar
+				<%= link_to debtors_path(filter: @filter, current_page: @current_page), { class: "btn blue-hoki pull-right margin-bottom-10" } do %> <i class="fa fa-angle-left "></i> Regresar
 				<% end %>
 				<!-- BEGIN PAGE BREADCRUMBS -->
 				<ul class="page-breadcrumb breadcrumb">
@@ -42,7 +42,7 @@
 								<div class="portlet-title">
 									<div class="caption">
 										<i class="fa fa-list "></i>
-										<span class="caption-subject bold uppercase">Ventas al cliente <%= @custom.nick_name %></span>
+										<span class="caption-subject bold uppercase">Ventas al cliente <%= @customer.nick_name %></span>
 										<span class="caption-helper"></span>
 									</div>
 								</div>
@@ -115,7 +115,7 @@
 													</thead>
 													<tbody id="customer_sales">
 														<% @sales.each_with_index do |sale, key| %>
-															<tr class=<%= (sale.cancelled? ? 'danger' : (sale.paid? ? 'success' : '')) %>>
+															<tr class=<%= sale.cancelled? ? 'danger' : '' %>>
 																<td><%= sale.id %></td>
 																<td><%= sale.sale_code %> </td>
 																<% if current_user.usertype == "A" || current_user.usertype == "SS" %>
@@ -135,20 +135,15 @@
 																<td><%= sale.products.count %></td>
 																<td><%= sale_status(sale) %></td>
 																<td><%= number_to_currency(sale.total, precision: 2) %></td>
-																<% credito = Credit.where(:sale_id => sale.id).first %>
-																<% if credito.present? %>
-																	<% abonos = CreditPayment.where(:credit_id => credito.id, :status => 0).sum(:quantity) %>
-																	<% if abonos.present? %>
-																		<td><%= number_to_currency(abonos, precision: 2) %></td>
-																	<% end %>
-																	<td><%= number_to_currency(credito.rest, precision: 2) %></td>
+																<% if sale.credit.present? %>
+																	<td><%= number_to_currency(sale.credit.credit_payments.activos.sum(:quantity), precision: 2) %></td>
+																	<td><%= number_to_currency(sale.credit.rest, precision: 2) %></td>
 																<% else %>
 																	<td></td>
 																	<td></td>
 																<% end %>
-
 																<td class="text-center">
-																	<%= link_to sale, {:class=>"btn btn-icon-only default", :title=>"Ver venta"} do %>
+																	<%= link_to sale, { class: "btn btn-icon-only default", title: "Ver venta" } do %>
 																		<i class="fa fa-search"></i>
 																	<% end %>
 																	<% if can? :destroy, Sale %>
@@ -182,17 +177,15 @@
 														</tr>
 													</thead>
 													<tbody id="abonos">
-														<% @credit.each_with_index do |credit, key| %>
-															<% abonos = CreditPayment.where(:credit_id => credit.id).order('id') %>
-																<% total = credit.total %>
+														<% @credits.each_with_index do |credit, key| %>
+															<% abonos = credit.credit_payments.activos.order(:id) %>
 																<% abonos.each_with_index do |abono, key| %>
-																	<% rest = total - abono.quantity %>
-																	<tr class=<%= (credit.cancelled? ? 'danger' : (credit.active? ? 'success' : '')) %>>
+																	<tr class=<%= credit.cancelled? ? 'danger' : '' %>>
 																		<td><%= credit.sale.sale_code %> </td>
 																		<td><%= l(abono.date_payment, :format => '%d/%m/%Y')  %></td>
-																		<td><%= number_to_currency(total, precision: 2) %></td>
+																		<td><%= number_to_currency(credit.total, precision: 2) %></td>
 																		<td><%= number_to_currency(abono.quantity, precision: 2) %></td>
-																		<td><%= number_to_currency(rest, precision: 2) %></td>
+																		<td><%= number_to_currency(credit.rest, precision: 2) %></td>
 																		<td>
 																			<% case abono.status %>
 																			<% when "cancelled"%>
@@ -202,12 +195,12 @@
 																			<% end %>
 																		</td>
 																		<td class="text-center">
-																		<% if !abono.cancelled? && abono.cash_registers_move.present? && abono.cash_registers_move.open_cash_register.open?%>
+																		<% if !abono.cancelled? && abono.cash_registers_move.present? && abono.cash_registers_move.open_cash_register.open? %>
 																			<%= link_to cash_move_delete_payment_path(:credit_payment_id => abono.id, :credit => credit.id) , method: :delete_credit_payment, :class => "btn btn-icon-only btn-danger", :title=>"Cancelar abono", data: { confirm: '¿Está seguro que desea cancelar el abono?' } do %> <i class="fa fa-ban"></i>
 																			<% end %>
 																		<% end %>
 																		</td>
-																		<% total -= abono.quantity %>
+																		<% credit.total -= abono.quantity %>
 																	</tr>
 																<% end %>
 														<% end %>
@@ -256,7 +249,7 @@
 	function salesByDate() {
 		var start = moment($("#begin_date").data("date"), "DD-MM-YYYY").format('YYYY-MM-DD HH:mm:ss');
 		var end = moment($("#end_date").data("date"), "DD-MM-YYYY").format('YYYY-MM-DD HH:mm:ss');
-		var cliente = '<%= @custom.id %>'
+		var cliente = '<%= @customer.id %>'
 		App.blockUI({
 			target: $("#sales_table"),
 			animate: true

+ 1 - 1
app/views/customers/debtors.html.erb

@@ -61,7 +61,7 @@
 												</thead>
 												<tbody>
 													<% @customers.each_with_index do |customer, key| %>
-													<% customer.verify_credit %>
+													<% # customer.verify_credit %>
 													<% payment = CreditPayment.where(:customer_id => customer.id, :status => 0).order("date_payment DESC").first %>
 													<% credito = Credit.activos.where(:customer_id => customer.id).sum(:rest) %>
 													<% sales = Sale.where("customer_id = #{customer.id} and status != 1 and status != 2 and saletype = 0").order("date_sale DESC") %>

+ 85 - 0
app/views/layouts/cfdi.html.erb.html

@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset='utf-8' />
+  <style type="text/css">
+    body {
+        width: 216mm;
+        height: auto;
+        font-family: 'OpenSansRegular';
+        font-size: 11px;
+      }
+      .left-right{
+        float: left;
+        text-align: right;
+      }
+      .left-left{
+        float: left;
+        text-align: left;
+      }
+      .logo{
+        width: 70%;
+        height: 5%;
+        text-align: left;
+      }
+      @page{
+        size: a4;
+        margin: 1.5cm 2cm;
+      }
+      table {
+        border-collapse: collapse;
+      }
+      th{
+        background-color: #D8D8D8;
+        height: 20px;
+        /*border: 1px solid;*/
+      }
+      tr{
+        padding: 0px;
+        height: 10px;
+      }
+      table td{
+        max-height: auto;
+        word-wrap: break-word;
+        vertical-align: top;
+        padding: 1px;
+        /*border-right: 1px solid;*/
+      }
+      table td, table th {
+        text-align: center;
+      }
+      td{
+        overflow: hidden;
+        text-overflow:'';
+        white-space: nowrap;
+      }
+      hr{
+        width: 100%;
+        background-color: #f2f2f2;
+      }
+      /*div.alwaysbreak { page-break-before: always; }
+      div.nobreak:before { clear:both; }*/
+      /*div.nobreak { page-break-inside: avoid; }*/
+      /*table tr:first-child th {
+        border-top: 0;
+      }
+      table tr:last-child td {
+        border-bottom: 0;
+      }
+      table tr td:first-child,
+      table tr th:first-child {
+        border-left: 0;
+      }
+      table tr td:last-child,
+      table tr th:last-child {
+        border-right: 0;
+      }*/
+
+  </style>
+  </head>
+  <body>
+  <page>
+    <%= yield %>
+  </page>
+  </body>
+</html>

+ 36 - 0
app/views/pointsales/_form.html.erb

@@ -26,12 +26,48 @@
 				</div>
 			</div>
 			<div class="form-group">
+        <%= f.label :business_name, "Razón social", {:class=>"col-md-3 control-label"} do %> Razón social
+          <span class="required">*</span>
+        <% end %>
+        <div class="col-md-9">
+          <%= f.text_field :business_name, {:class=>"form-control input-large"} %>
+          <span class="help-block">La razón social se utilizará para la generación de facturas</span>
+        </div>
+      </div>
+      <div class="form-group">
+        <%= f.label :federal_taxpayer_registration, "RFC", {:class=>"col-md-3 control-label"} do %> RFC
+          <span class="required">*</span>
+        <% end %>
+        <div class="col-md-9">
+          <%= f.text_field :federal_taxpayer_registration, {:class=>"form-control input-medium uppercase"} %>
+          <span class="help-block">El rfc que se capture se utilizará para la generación de facturas</span>
+        </div>
+      </div>
+      <div class="form-group">
+        <%= f.label :tax_regime, "", { class: "col-md-3 control-label" } do %> Régimen físcal
+          <span class="required">*</span>
+        <% end %>
+        <div class="col-md-4">
+          <%= f.select :tax_regime, (Rails.application.config.taxregime), { prompt: "Seleccione" }, { class: 'form-control select2'} %>
+          <span class="help-block">El régimen físcal es requerido para la generación de facturas</span>
+        </div>
+      </div>
+			<div class="form-group">
 				<%= f.label :address, "Dirección", { class: "col-md-3 col-sm-3 control-label" } %>
 				<div class="col-md-4 col-sm-6">
 					<%= f.text_field :address, { class: "form-control" } %>
 				</div>
 			</div>
 			<div class="form-group">
+        <%= f.label :postal_code, "Código postal", {:class=>"col-md-3 control-label"} do %> Código postal
+         <span class="required">*</span>
+        <% end %>
+        <div class="col-md-9">
+          <%= f.text_field :postal_code, {:class=>"form-control input-small"} %>
+          <span class="help-block">El código postal se utilizará para la generación de facturas</span>
+        </div>
+      </div>
+			<div class="form-group">
 				<%= f.label :haggle_percent, { class: "col-md-3 col-sm-3 control-label" } do %> Porcentaje de regateo para ventas <% end %>
 				<div class="col-md-2 col-sm-6">
 					<%= f.number_field :haggle_percent, { class: "form-control input-xsmall" } %>

+ 8 - 8
app/views/sales/receipt_credit_payment.pdf.erb

@@ -35,11 +35,11 @@
 				<tr>
 					<td width="30%">Saldo anterior</td>
 					<td width="15%" class="text-right">$</td>
-					<% if debt == 0 %>
+					<!-- < % if debt == 0 %> -->
 						<td width="40%"><%= number_to_currency(deuda, precision: 2, :unit => "") %></td>
-					<% else %>
-						<td width="40%"><%= number_to_currency(debt + new_payment, precision: 2, :unit => "") %></td>
-					<% end %>
+					<!-- < % else %>
+						<td width="40%">< %= number_to_currency(debt + new_payment, precision: 2, :unit => "") %></td>
+					< % end %> -->
 				</tr>
 				<tr>
 					<td width="30%">Abono a crédito</td>
@@ -49,7 +49,7 @@
 				<tr>
 					<td width="30%">Saldo actual</td>
 					<td width="15%" class="text-right">$</td>
-					<td width="40%"><%= number_to_currency(debt, precision: 2, :unit => "") %></td>
+					<td width="40%"><%= number_to_currency((deuda > new_payment ? (deuda - new_payment) : 0), precision: 2, :unit => "") %></td>
 				</tr>
 			</tbody>
 		</table>
@@ -68,7 +68,7 @@
 				<tr class="text-center" style="text-decoration:underline;">
 					<td><%= move.payment_method.method %> </td>
 					<td></td>
-					<td></td>
+					<td><small><%= move.payment_method.id == 1 || move.payment_method.id == 4 ? "n° #{move.cardnumber}" : "" %></small></td>
 				</tr>
 				<% if move.payment_method.isCash? %>
 					<% marginFooter += 80 %>
@@ -96,8 +96,8 @@
 					</tr>
 					<tr class="text-left">
 						<td> </td>
-						<td> tarjeta nº: </td>
-						<td> <%= move.cardnumber %></td>
+						<td> </td>
+						<td> </td>
 					</tr>
 				<% end %>
 			</tbody>

+ 64 - 0
config/application.rb

@@ -48,5 +48,69 @@ module Pos
     config.support_mails = [
       "daniel.mendoza@sml.mx"
     ]
+
+    # Datos generales para el proceso de facturas y notas de credito
+    config.issuing = {
+      "Version" => "3.3",
+      "CveIngreso" => "I",
+      "CveEgreso" => "E",
+      "CvePago" => "P",
+      "Password" =>  "mvpNUXmQfK8=", # contrasenia de integrador proporcionada por el proveedor ProFact
+      "MetodoPago" => "PUE", # Metodo de pago usado para las facturas y notas de credito Pago en una sola exhibicion
+      "SerieContado" => "B", # Serie para factura de venta de contado
+      "SerieCredito" => "A", # Serie para factura de venta a credito
+      "SerieNota" => "C", # Serie para notas de credito
+      "stamper_uri" => "https://cfdi33-pruebas.buzoncfdi.mx:1443/Timbrado.asmx?wsdl",
+      "Impuesto" => "002", # Clave del impuesto aplicado 002: IVA
+      "TipoRelacionNC" => "03" # Relaciin de facturas con nota de credito
+    }
+
+    config.taxregime = {
+      "General de Ley Personas Morales" => "601",
+      "Personas Morales con Fines no Lucrativos" => "603",
+      "Sueldos y Salarios e Ingresos Asimilados a Salarios" => "605",
+      "Arrendamiento" => "606",
+      "Demás ingresos" => "608",
+      "Consolidación" => "609",
+      "Residentes en el Extranjero sin Establecimiento Permanente en México" => "610",
+      "Ingresos por Dividendos (socios y accionistas)" => "611",
+      "Personas Físicas con Actividades Empresariales y Profesionales" => "612",
+      "Ingresos por intereses" => "614",
+      "Sin obligaciones fiscales" => "616",
+      "Sociedades Cooperativas de Producción que optan por diferir sus ingresos" => "620",
+      "Incorporación Fiscal" => "621",
+      "Actividades Agrícolas, Ganaderas, Silvícolas y Pesqueras" => "622",
+      "Opcional para Grupos de Sociedades" => "623",
+      "Coordinados" => "624",
+      "Hidrocarburos" => "628",
+      "Régimen de Enajenación o Adquisición de Bienes" => "607",
+      "De los Regímenes Fiscales Preferentes y de las Empresas Multinacionales" => "629",
+      "Enajenación de acciones en bolsa de valores" => "630",
+      "Régimen de los ingresos por obtención de premios" => "615"
+    }
+
+    config.cfdiuse = {
+      "Adquisición de mercancias" => "G01",
+      "Devoluciones, descuentos o bonificaciones" => "G02",
+      "Gastos en general" => "G03",
+      "Construcciones" => "I01",
+      "Mobilario y equipo de oficina por inversiones" => "I02",
+      "Equipo de transporte" => "I03",
+      "Equipo de computo y accesorios" => "I04",
+      "Dados, troqueles, moldes, matrices y herramental" => "I05",
+      "Comunicaciones telefónicas" => "I06",
+      "Comunicaciones satelitales" => "I07",
+      "Otra maquinaria y equipo" => "I08",
+      "Honorarios médicos, dentales y gastos hospitalarios." => "D01",
+      "Gastos médicos por incapacidad o discapacidad" => "D02",
+      "Gastos funerales." => "D03",
+      "Donativos." => "D04",
+      "Intereses reales efectivamente pagados por créditos hipotecarios (casa habitación)." => "D05",
+      "Aportaciones voluntarias al SAR." => "D06",
+      "Primas por seguros de gastos médicos." => "D07",
+      "Gastos de transportación escolar obligatoria." => "D08",
+      "Depósitos en cuentas para el ahorro, primas que tengan como base planes de pensiones." => "D09",
+      "Pagos por servicios educativos (colegiaturas)" => "D10"
+    }
   end
 end

+ 3 - 0
config/routes.rb

@@ -114,6 +114,9 @@ Rails.application.routes.draw do
   post 'update_all_variants_prices' => 'available_products#update_all_variants_prices', defaults: { format: 'json' }
 
   resources :cash_outs
+  get 'general_public_invoice/:cash_out_id' => 'cash_outs#general_public_invoice', format: :js, as: "general_public_invoice"
+  get 'generate_gpi/:cash_out_id' => 'cash_outs#generate_gpi', format: :js, as: 'generate_gpi'
+  get 'print_gpi/:cash_out_id' => 'cash_outs#print_invoice', as: 'print_gpi'
   get 'get_open_cash_registers' => 'cash_outs#get_open_cash_registers', defaults: { format: 'js' }
   post 'select_open_cash_to_close/:open_cash_register_id' => 'cash_outs#select_open_cash_to_close', defaults: { format: 'js' }
   get 'find_cash_outs_by_date/:pointsale_id/:begin_date/:end_date' => 'cash_outs#find_cash_outs_by_date', defaults: { format: 'js' }

+ 7 - 0
db/migrate/20181213183811_add_sales_invoice_column.rb

@@ -0,0 +1,7 @@
+class AddSalesInvoiceColumn < ActiveRecord::Migration
+  def change
+    add_column :cash_outs, :invoice_num, :string, null: true unless column_exists?(:cash_outs, :invoice_num)
+    add_column :sales, :invoice_num, :string, null: true unless column_exists?(:sales, :invoice_num)
+    add_column :sales, :require_invoice, :boolean, default: false unless column_exists?(:sales, :require_invoice)
+  end
+end

+ 17 - 0
db/migrate/20181213185244_create_invoice_details.rb

@@ -0,0 +1,17 @@
+class CreateInvoiceDetails < ActiveRecord::Migration
+  def change
+    drop_table :invoice_details if table_exists? :invoice_details
+    create_table :invoice_details do |t|
+      t.belongs_to :sale, index: true
+      t.string :uuid, null: false
+      t.string :cfdi_type, limit: 1, null: false
+      t.string :invoice_reason
+      t.string :rfc_receptor
+      t.datetime :generating_date
+      t.datetime :stamping_date
+      t.string :storing_url
+      t.integer :status, limit: 1, default: 1
+      t.timestamps null: false
+    end
+  end
+end

+ 8 - 0
db/migrate/20181213203152_add_invoice_columns_to_pointsale.rb

@@ -0,0 +1,8 @@
+class AddInvoiceColumnsToPointsale < ActiveRecord::Migration
+  def change
+    add_column :pointsales, :federal_taxpayer_registration, :string
+    add_column :pointsales, :business_name, :string
+    add_column :pointsales, :tax_regime, :integer
+    add_column :pointsales, :postal_code, :integer
+  end
+end

+ 5 - 0
db/migrate/20181213203326_add_column_to_billing_information.rb

@@ -0,0 +1,5 @@
+class AddColumnToBillingInformation < ActiveRecord::Migration
+  def change
+    add_column :billing_informations, :cfdi_use_key, :string, default: "G03"
+  end
+end

+ 5 - 0
db/migrate/20181217171552_add_key_column_to_payment_method.rb

@@ -0,0 +1,5 @@
+class AddKeyColumnToPaymentMethod < ActiveRecord::Migration
+  def change
+    add_column :payment_methods, :payment_method_key, :string, null:true, default: '99'
+  end
+end

+ 5 - 0
db/migrate/20181217172147_add_key_column_to_products.rb

@@ -0,0 +1,5 @@
+class AddKeyColumnToProducts < ActiveRecord::Migration
+  def change
+    add_column :products, :product_service_key, :string, null: true, default: '01010101'
+  end
+end

+ 5 - 0
db/migrate/20181217175547_add_key_column_to_unit.rb

@@ -0,0 +1,5 @@
+class AddKeyColumnToUnit < ActiveRecord::Migration
+  def change
+    add_column :units, :unit_key, :string, default: ""
+  end
+end

+ 8 - 0
db/migrate/20181220182317_add_extra_info_columns_to_cash_registers_moves.rb

@@ -0,0 +1,8 @@
+class AddExtraInfoColumnsToCashRegistersMoves < ActiveRecord::Migration
+  def change
+    add_column :cash_registers_moves, :bank_name, :string, default: ""
+    add_column :cash_registers_moves, :check_number, :string, default: ""
+    add_column :cash_registers_moves, :customer_account, :string, default: ""
+    add_column :cash_registers_moves, :customer_code, :string, default: ""
+  end
+end

+ 5 - 0
db/migrate/20181221220426_add_cash_register_move_id_to_credit_payment.rb

@@ -0,0 +1,5 @@
+class AddCashRegisterMoveIdToCreditPayment < ActiveRecord::Migration
+  def change
+    add_column :credit_payments, :cash_registers_move_id, :integer, index: true, null: true unless column_exists? :credit_payments, :cash_registers_move_id
+  end
+end

+ 82 - 50
db/schema.rb

@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20181122030513) do
+ActiveRecord::Schema.define(version: 20181221220426) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -55,21 +55,22 @@ ActiveRecord::Schema.define(version: 20181122030513) do
   add_index "available_products", ["product_id"], name: "index_available_products_on_product_id", using: :btree
 
   create_table "billing_informations", force: :cascade do |t|
-    t.integer  "customer_id",             default: 0,  null: false
-    t.string   "name",        limit: 255, default: "", null: false
-    t.string   "rfc",         limit: 13,  default: "", null: false
-    t.string   "address",     limit: 255, default: "", null: false
-    t.integer  "zipcode",                 default: 0,  null: false
-    t.string   "num_ext",                 default: "", null: false
-    t.string   "num_int",                 default: "", null: false
-    t.integer  "state_id",                default: 0,  null: false
-    t.integer  "county_id",               default: 0,  null: false
-    t.string   "city",                    default: "", null: false
-    t.string   "suburb",                  default: "", null: false
-    t.integer  "status",                  default: 1,  null: false
-    t.datetime "created_at",                           null: false
-    t.datetime "updated_at",                           null: false
-    t.integer  "supplier_id",             default: 0,  null: false
+    t.integer  "customer_id",              default: 0,     null: false
+    t.string   "name",         limit: 255, default: "",    null: false
+    t.string   "rfc",          limit: 13,  default: "",    null: false
+    t.string   "address",      limit: 255, default: "",    null: false
+    t.integer  "zipcode",                  default: 0,     null: false
+    t.string   "num_ext",                  default: "",    null: false
+    t.string   "num_int",                  default: "",    null: false
+    t.integer  "state_id",                 default: 0,     null: false
+    t.integer  "county_id",                default: 0,     null: false
+    t.string   "city",                     default: "",    null: false
+    t.string   "suburb",                   default: "",    null: false
+    t.integer  "status",                   default: 1,     null: false
+    t.datetime "created_at",                               null: false
+    t.datetime "updated_at",                               null: false
+    t.integer  "supplier_id",              default: 0,     null: false
+    t.string   "cfdi_use_key",             default: "G03"
   end
 
   add_index "billing_informations", ["county_id"], name: "index_billing_informations_on_county_id", using: :btree
@@ -103,6 +104,7 @@ ActiveRecord::Schema.define(version: 20181122030513) do
     t.decimal  "cash_fund",             precision: 10, scale: 2, default: 0.0
     t.decimal  "physical_cash",         precision: 10, scale: 2, default: 0.0, null: false
     t.string   "observations"
+    t.string   "invoice_num"
   end
 
   add_index "cash_outs", ["open_cash_register_id"], name: "index_cash_outs_on_open_cash_register_id", using: :btree
@@ -136,6 +138,10 @@ ActiveRecord::Schema.define(version: 20181122030513) do
     t.decimal  "change",                          precision: 10, scale: 2
     t.integer  "products_return_id"
     t.integer  "credit_payment_id"
+    t.string   "bank_name",                                                default: ""
+    t.string   "check_number",                                             default: ""
+    t.string   "customer_account",                                         default: ""
+    t.string   "customer_code",                                            default: ""
   end
 
   add_index "cash_registers_moves", ["open_cash_register_id"], name: "index_cash_registers_moves_on_open_cash_register_id", using: :btree
@@ -185,12 +191,13 @@ ActiveRecord::Schema.define(version: 20181122030513) do
     t.integer  "customer_id"
     t.integer  "credit_id"
     t.integer  "pointsale_id"
-    t.decimal  "quantity",     precision: 10, scale: 2, default: 0.0, null: false
-    t.integer  "status",                                default: 0,   null: false
-    t.date     "date_payment",                                        null: false
-    t.datetime "created_at",                                          null: false
-    t.datetime "updated_at",                                          null: false
+    t.decimal  "quantity",               precision: 10, scale: 2, default: 0.0, null: false
+    t.integer  "status",                                          default: 0,   null: false
+    t.date     "date_payment",                                                  null: false
+    t.datetime "created_at",                                                    null: false
+    t.datetime "updated_at",                                                    null: false
     t.integer  "user_id"
+    t.integer  "cash_registers_move_id"
   end
 
   add_index "credit_payments", ["credit_id"], name: "index_credit_payments_on_credit_id", using: :btree
@@ -288,6 +295,22 @@ ActiveRecord::Schema.define(version: 20181122030513) do
   add_index "inventories_moves", ["purchase_id"], name: "index_inventories_moves_on_purchase_id", using: :btree
   add_index "inventories_moves", ["sale_id"], name: "index_inventories_moves_on_sale_id", using: :btree
 
+  create_table "invoice_details", force: :cascade do |t|
+    t.integer  "sale_id"
+    t.string   "uuid",                                  null: false
+    t.string   "cfdi_type",       limit: 1,             null: false
+    t.string   "invoice_reason"
+    t.string   "rfc_receptor"
+    t.datetime "generating_date"
+    t.datetime "stamping_date"
+    t.string   "storing_url"
+    t.integer  "status",          limit: 2, default: 1
+    t.datetime "created_at",                            null: false
+    t.datetime "updated_at",                            null: false
+  end
+
+  add_index "invoice_details", ["sale_id"], name: "index_invoice_details_on_sale_id", using: :btree
+
   create_table "open_cash_registers", force: :cascade do |t|
     t.integer  "cash_register_id"
     t.integer  "user_id"
@@ -302,21 +325,22 @@ ActiveRecord::Schema.define(version: 20181122030513) do
   add_index "open_cash_registers", ["user_id"], name: "index_open_cash_registers_on_user_id", using: :btree
 
   create_table "payment_methods", force: :cascade do |t|
-    t.string   "method",                 null: false
-    t.integer  "status",     default: 1, null: false
-    t.datetime "created_at",             null: false
-    t.datetime "updated_at",             null: false
+    t.string   "method",                            null: false
+    t.integer  "status",             default: 1,    null: false
+    t.datetime "created_at",                        null: false
+    t.datetime "updated_at",                        null: false
     t.integer  "reference"
-    t.integer  "isCash",     default: 0, null: false
+    t.integer  "isCash",             default: 0,    null: false
+    t.string   "payment_method_key", default: "99"
   end
 
   create_table "pointsales", force: :cascade do |t|
     t.string   "name"
     t.string   "address"
     t.text     "notes"
-    t.integer  "status",                                              default: 1
-    t.datetime "created_at",                                                        null: false
-    t.datetime "updated_at",                                                        null: false
+    t.integer  "status",                                                 default: 1
+    t.datetime "created_at",                                                           null: false
+    t.datetime "updated_at",                                                           null: false
     t.text     "prefix"
     t.string   "img_pointsale_file_name"
     t.string   "img_pointsale_content_type"
@@ -324,7 +348,11 @@ ActiveRecord::Schema.define(version: 20181122030513) do
     t.datetime "img_pointsale_updated_at"
     t.string   "ticket_footer"
     t.string   "img_pointsale"
-    t.decimal  "haggle_percent",             precision: 10, scale: 2, default: 0.0
+    t.decimal  "haggle_percent",                precision: 10, scale: 2, default: 0.0
+    t.string   "federal_taxpayer_registration"
+    t.string   "business_name"
+    t.integer  "tax_regime"
+    t.integer  "postal_code"
   end
 
   create_table "pos_configs", force: :cascade do |t|
@@ -421,24 +449,24 @@ ActiveRecord::Schema.define(version: 20181122030513) do
   add_index "product_wastes", ["product_id"], name: "index_product_wastes_on_product_id", using: :btree
 
   create_table "products", force: :cascade do |t|
-    t.string   "sku",                      limit: 30,                           default: "",    null: false
-    t.string   "name",                     limit: 255,                          default: "",    null: false
-    t.text     "description",                                                   default: "",    null: false
+    t.string   "sku",                      limit: 30,                           default: "",         null: false
+    t.string   "name",                     limit: 255,                          default: "",         null: false
+    t.text     "description",                                                   default: "",         null: false
     t.decimal  "price_base",                           precision: 10, scale: 2, default: 0.0
     t.decimal  "price_sale",                           precision: 10, scale: 2, default: 0.0
     t.string   "img_product_file_name"
     t.string   "img_product_content_type"
     t.integer  "img_product_file_size"
     t.datetime "img_product_updated_at"
-    t.boolean  "presentation",                                                  default: false, null: false
-    t.boolean  "inventory",                                                     default: true,  null: false
+    t.boolean  "presentation",                                                  default: false,      null: false
+    t.boolean  "inventory",                                                     default: true,       null: false
     t.decimal  "content"
-    t.integer  "status",                                                        default: 1,     null: false
-    t.datetime "created_at",                                                                    null: false
-    t.datetime "updated_at",                                                                    null: false
+    t.integer  "status",                                                        default: 1,          null: false
+    t.datetime "created_at",                                                                         null: false
+    t.datetime "updated_at",                                                                         null: false
     t.integer  "unit_id"
-    t.integer  "include_purchase_tax",                                          default: 0,     null: false
-    t.integer  "include_sale_tax",                                              default: 0,     null: false
+    t.integer  "include_purchase_tax",                                          default: 0,          null: false
+    t.integer  "include_sale_tax",                                              default: 0,          null: false
     t.string   "barcode"
     t.integer  "parent_id"
     t.text     "attributes_json"
@@ -447,6 +475,7 @@ ActiveRecord::Schema.define(version: 20181122030513) do
     t.decimal  "price_base_dollars",                   precision: 10, scale: 2
     t.string   "img_product"
     t.integer  "category_id"
+    t.string   "product_service_key",                                           default: "01010101"
   end
 
   add_index "products", ["unit_id"], name: "index_products_on_unit_id", using: :btree
@@ -560,19 +589,21 @@ ActiveRecord::Schema.define(version: 20181122030513) do
     t.integer  "customer_id"
     t.integer  "user_id"
     t.integer  "open_cash_register_id"
-    t.decimal  "amount",                          precision: 10, scale: 2, default: 0.0, null: false
-    t.decimal  "tax",                             precision: 10, scale: 2, default: 0.0, null: false
-    t.decimal  "discount",                        precision: 10, scale: 2, default: 0.0, null: false
-    t.decimal  "total",                           precision: 10, scale: 2, default: 0.0, null: false
-    t.integer  "status",                                                   default: 1,   null: false
-    t.date     "date_sale",                                                              null: false
-    t.datetime "created_at",                                                             null: false
-    t.datetime "updated_at",                                                             null: false
+    t.decimal  "amount",                          precision: 10, scale: 2, default: 0.0,   null: false
+    t.decimal  "tax",                             precision: 10, scale: 2, default: 0.0,   null: false
+    t.decimal  "discount",                        precision: 10, scale: 2, default: 0.0,   null: false
+    t.decimal  "total",                           precision: 10, scale: 2, default: 0.0,   null: false
+    t.integer  "status",                                                   default: 1,     null: false
+    t.date     "date_sale",                                                                null: false
+    t.datetime "created_at",                                                               null: false
+    t.datetime "updated_at",                                                               null: false
     t.integer  "saletype",              limit: 2
     t.integer  "seller_id"
     t.string   "sale_code"
     t.date     "expiration_date"
     t.string   "credit_note"
+    t.string   "invoice_num"
+    t.boolean  "require_invoice",                                          default: false
   end
 
   add_index "sales", ["customer_id"], name: "index_sales_on_customer_id", using: :btree
@@ -750,8 +781,9 @@ ActiveRecord::Schema.define(version: 20181122030513) do
   create_table "units", force: :cascade do |t|
     t.string   "unit"
     t.integer  "status"
-    t.datetime "created_at", null: false
-    t.datetime "updated_at", null: false
+    t.datetime "created_at",              null: false
+    t.datetime "updated_at",              null: false
+    t.string   "unit_key",   default: ""
   end
 
   create_table "users", force: :cascade do |t|

+ 37 - 1
db/seeds.rb

@@ -21,7 +21,43 @@
 	PosConfig.create(cancel_partial_payment: 30, refund_sale: 30, days_cancel_sale: 30, days_cancel_purchase: 30, tax_percent: 16, time_zone: "Mountain Time (US & Canada)", gain_margin: 20, reserve_sale_percent: 20, days_cancel_reserved: 30, haggle_in_sale_percent: 10, commission_percent: 10)
 
 	# METODOS DE PAGO
-	PaymentMethod.create([{method: "Tarjeta", status: 1, reference: 1, isCash: 0}, {method: "Efectivo", status: 1, reference: 0, isCash: 1}])
+	PaymentMethod.create([
+    {
+      method: "Tarjeta de debito",
+      status: 1,
+      reference: 1,
+      isCash: 0,
+      payment_method_key: "28"
+    },
+    {
+      method: "Efectivo",
+      status: 1,
+      reference: 0,
+      isCash: 1,
+      payment_method_key: "01"
+    },
+    {
+      method: "Transferencia bancaria",
+      status: 1,
+      reference: 1,
+      isCash: 0,
+      payment_method_key: "03"
+    },
+    {
+      method: "Tarjeta de credito",
+      status: 1,
+      reference: 1,
+      isCash: 0,
+      payment_method_key: "04"
+    },
+    {
+      method: "Cheque",
+      status: 1,
+      reference: 1,
+      isCash: 0,
+      payment_method_key: "02"
+    }
+  ])
 
 	# CLIENTE
 	Customer.create(nick_name: "Publico general", phone: "0000000000", email: 'cliente@clientes.com', credit: false, credit_limit: 0, time_limit: 0, notes: "ninguna", status: 1, is_public: 1)

TEMPAT SAMPAH
facturacion/aaa010101aaa/aaa010101aaa__csd_01.cer


TEMPAT SAMPAH
facturacion/aaa010101aaa/aaa010101aaa__csd_01.key


File diff ditekan karena terlalu besar
+ 3 - 0
facturacion/cancelado.xml


+ 3 - 0
facturacion/generaxml.rb

@@ -0,0 +1,3 @@
+File.open('prueba.xml', 'w') do |f2|
+  f2.puts "Por que la vida \n puede ser maravillosa"
+end

File diff ditekan karena terlalu besar
+ 80 - 0
facturacion/timbrado.xml