fac
# == Schema Information
#
# Table name: facturas
#
# id :integer not null, primary key
# account_statement_id :integer
# diverza_client_id :integer
# created_at :datetime(23)
# updated_at :datetime(23)
# file_file_name :string(255)
# file_content_type :string(255)
# file_file_size :integer
# file_updated_at :datetime(23)
#
class Factura < ActiveRecord::Base
include ActionView::Helpers::NumberHelper
belongs_to :account_statement
belongs_to :diverza_client
validates :file, presence: true
default_scope ->{order(created_at: :desc)}
validates :account_statement_id, :diverza_client_id, presence: true
validate :validate_emisor, :validate_receptor, :validate_sub_total, :validate_total, :validate_cfdi_client_with_sat_service
has_attached_file :file,
path: "#{Rails.root}/public/facturas/:id/:basename.:extension",
url: "/facturas/:id/:basename.:extension"
validates_attachment_content_type :file, content_type: %w(text/xml)
before_validation :parse_file
private
def parse_file
tempfile = file.queued_for_write[:original]
doc = Nokogiri::XML(tempfile)
parse_xml(doc)
end
def parse_xml(doc)
@emisor = doc.xpath("//cfdi:Emisor/@rfc").first.text.to_s
@receptor = doc.xpath("//cfdi:Receptor/@rfc").first.text.to_s
@imp_retenidos = doc.xpath("cfdi:Impuestos/@totalImpuestosRetenidos").first
@sub_total = doc.xpath("//cfdi:Comprobante/@subTotal").first.text.to_f
@total = doc.xpath("//cfdi:Comprobante/@total").first.text.to_f
@uuid = doc.xpath("//cfdi:Complemento/@UUID").first.text.to_s
end
def validate_receptor
errors.add(:validate_receiver, "Diferente Receptor") if @receptor != self.account_statement.issuer
end
def validate_emisor
errors.add(:validate_emisor, "Diferente Emissor") if @emisor != self.account_statement.receiver
end
def validate_total
errors.add(:validate_total, "Diferente Total, factura: #{number_to_currency(@total)}, en estado de cuenta: #{number_to_currency(self.account_statement.net_amount)}") if @total != self.account_statement.net_amount
end
def validate_sub_total
errors.add(:validate_sub_total, "Diferente Sub Total, factura: #{number_to_currency(@sub_total)}, en estado de cuenta: #{number_to_currency(self.account_statement.gross_amount)}") if @sub_total != self.account_statement.gross_amount
end
def validate_cfdi_client_with_sat_service
validacion = CfdiClientSatService.new(@emisor, @receptor, @total.to_s, @uuid)
errors.add(:validate_cfdi_client_with_sat_service, validacion.resultado_codigo_estatus) if !validacion.is_a_valid_factura?
end
end