facturama 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/facturama.rb +56 -0
- data/lib/facturama/facturama_api_multi.rb +37 -0
- data/lib/facturama/facturama_api_web.rb +55 -0
- data/lib/facturama/models/address.rb +16 -0
- data/lib/facturama/models/branch_office.rb +14 -0
- data/lib/facturama/models/cfdi.rb +80 -0
- data/lib/facturama/models/cfdi_relation.rb +10 -0
- data/lib/facturama/models/cfdi_relations.rb +12 -0
- data/lib/facturama/models/client.rb +19 -0
- data/lib/facturama/models/complement.rb +8 -0
- data/lib/facturama/models/connection_info.rb +36 -0
- data/lib/facturama/models/csd.rb +14 -0
- data/lib/facturama/models/exception/facturama_exception.rb +18 -0
- data/lib/facturama/models/exception/model_exception.rb +11 -0
- data/lib/facturama/models/image.rb +11 -0
- data/lib/facturama/models/item.rb +25 -0
- data/lib/facturama/models/model.rb +75 -0
- data/lib/facturama/models/product.rb +27 -0
- data/lib/facturama/models/product_tax.rb +14 -0
- data/lib/facturama/models/receiver.rb +15 -0
- data/lib/facturama/models/serie.rb +13 -0
- data/lib/facturama/models/tax.rb +14 -0
- data/lib/facturama/models/tax_entity.rb +21 -0
- data/lib/facturama/models/tax_stamp.rb +12 -0
- data/lib/facturama/services/branch_office_service.rb +16 -0
- data/lib/facturama/services/catalog_service.rb +42 -0
- data/lib/facturama/services/cfdi_multi_service.rb +164 -0
- data/lib/facturama/services/cfdi_service.rb +172 -0
- data/lib/facturama/services/client_service.rb +19 -0
- data/lib/facturama/services/crud_service.rb +41 -0
- data/lib/facturama/services/csd_service.rb +16 -0
- data/lib/facturama/services/http_service.rb +152 -0
- data/lib/facturama/services/product_service.rb +16 -0
- data/lib/facturama/version.rb +4 -0
- data/lib/samples/sample_api.rb +17 -0
- data/lib/samples/sample_api_multi.rb +352 -0
- data/lib/samples/sample_api_web.rb +454 -0
- metadata +94 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "crud_service"
|
2
|
+
|
3
|
+
module Facturama
|
4
|
+
|
5
|
+
module Services
|
6
|
+
class ClientService < CrudService
|
7
|
+
|
8
|
+
def initialize(connection_info )
|
9
|
+
super(connection_info, "client")
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
end # class ClientService
|
16
|
+
|
17
|
+
end # module Services
|
18
|
+
|
19
|
+
end # module Facturama
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative "http_service"
|
2
|
+
|
3
|
+
module Facturama
|
4
|
+
|
5
|
+
module Services
|
6
|
+
class CrudService < HttpService
|
7
|
+
|
8
|
+
def initialize( connection_info, uri_resource )
|
9
|
+
super( connection_info, uri_resource)
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
def retrieve(message)
|
14
|
+
HttpService.instance_method(:get).bind(self).call(message)
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def list
|
19
|
+
HttpService.instance_method(:get).bind(self).call('')
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def create (message, url = "")
|
24
|
+
HttpService.instance_method(:post).bind(self).call(message, url)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def remove(message)
|
29
|
+
HttpService.instance_method(:delete).bind(self).call(message)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def update(message, url = "" )
|
34
|
+
HttpService.instance_method(:put).bind(self).call(message, url)
|
35
|
+
end
|
36
|
+
|
37
|
+
end # class CrudService
|
38
|
+
|
39
|
+
end # module Services
|
40
|
+
|
41
|
+
end # module Facturama
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative "crud_service"
|
2
|
+
|
3
|
+
module Facturama
|
4
|
+
|
5
|
+
module Services
|
6
|
+
class CsdService < CrudService
|
7
|
+
|
8
|
+
def initialize( connection_info )
|
9
|
+
super(connection_info, "api-lite/csds")
|
10
|
+
end
|
11
|
+
|
12
|
+
end # class CsdService
|
13
|
+
|
14
|
+
end # module Services
|
15
|
+
|
16
|
+
end # module Facturama
|
@@ -0,0 +1,152 @@
|
|
1
|
+
|
2
|
+
require_relative "../models/exception/facturama_exception"
|
3
|
+
require_relative "../models/connection_info.rb"
|
4
|
+
|
5
|
+
module Facturama
|
6
|
+
|
7
|
+
module Services
|
8
|
+
|
9
|
+
class HttpService
|
10
|
+
|
11
|
+
def initialize(connection_info, uri_resource )
|
12
|
+
@connection_info = connection_info
|
13
|
+
@uri_resource = uri_resource
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
def get(args='')
|
19
|
+
res=RestClient::Request.new(
|
20
|
+
:method => :get,
|
21
|
+
:url => url(args),
|
22
|
+
:user => @connection_info.facturama_user,
|
23
|
+
:password => @connection_info.facturama_password ,
|
24
|
+
:headers => {:accept => :json,
|
25
|
+
:content_type => :json,
|
26
|
+
:user_agent => '',
|
27
|
+
}
|
28
|
+
)
|
29
|
+
|
30
|
+
executor(res)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
def post(message, args = "")
|
37
|
+
json =message.to_json
|
38
|
+
|
39
|
+
res= RestClient::Request.new(
|
40
|
+
:method => :post,
|
41
|
+
:url => url(args),
|
42
|
+
:user => @connection_info.facturama_user,
|
43
|
+
:password => @connection_info.facturama_password,
|
44
|
+
:payload => json,
|
45
|
+
:headers => { :content_type => :json }
|
46
|
+
)
|
47
|
+
|
48
|
+
executor(res)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
def put(message, args = "")
|
56
|
+
json =message.to_json
|
57
|
+
|
58
|
+
res= RestClient::Request.new(
|
59
|
+
:method => :put,
|
60
|
+
:url => url(args),
|
61
|
+
:user => @connection_info.facturama_user,
|
62
|
+
:password => @connection_info.facturama_password ,
|
63
|
+
:payload => json,
|
64
|
+
:headers => {:accept => :json,
|
65
|
+
:content_type => :json}
|
66
|
+
)
|
67
|
+
|
68
|
+
executor(res)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
def delete(args = "")
|
75
|
+
res=RestClient::Request.new(
|
76
|
+
:method => :delete,
|
77
|
+
:url => url(args),
|
78
|
+
:user => @connection_info.facturama_user,
|
79
|
+
:password => @connection_info.facturama_password ,
|
80
|
+
:headers => {:accept => :json,
|
81
|
+
:content_type => :json
|
82
|
+
}
|
83
|
+
)
|
84
|
+
|
85
|
+
executor(res)
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def url(args = '')
|
94
|
+
slash = ""
|
95
|
+
args = args.to_s
|
96
|
+
|
97
|
+
if args.length > 0
|
98
|
+
slash = (args =~ /^\?/)? "" : "/"
|
99
|
+
end
|
100
|
+
|
101
|
+
if(@uri_resource.length > 0)
|
102
|
+
@uri_resource = "/" + @uri_resource;
|
103
|
+
end
|
104
|
+
|
105
|
+
@connection_info.uri_base + @uri_resource + slash + args
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# Executa la peticion y procesa la respuesta decodificando el JSON a un Hash y
|
110
|
+
# Conviriendo los errores de la API en FacturamaExceptions
|
111
|
+
def executor(request)
|
112
|
+
|
113
|
+
begin
|
114
|
+
response = request.execute
|
115
|
+
|
116
|
+
if response.code != 204 && response.body != "" # 204 = sin contenido
|
117
|
+
JSON[ response]
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
#exceptions
|
122
|
+
rescue Exception => e
|
123
|
+
case e.class.name
|
124
|
+
when "RestClient::NotFound"
|
125
|
+
raise( FacturamaException.new( "404 NotFound: Elemento no encontrado" ) )
|
126
|
+
when "RestClient::BadRequest"
|
127
|
+
json_response = JSON[e.response]
|
128
|
+
model_state = json_response['ModelState']
|
129
|
+
if model_state != nil
|
130
|
+
model_state = json_response['ModelState'].map{|k,v| [k.to_s, v]}
|
131
|
+
fact_exception = FacturamaException.new( json_response['Message'] )
|
132
|
+
end
|
133
|
+
|
134
|
+
fact_exception = FacturamaException.new( json_response['Message'], model_state )
|
135
|
+
raise( fact_exception )
|
136
|
+
else
|
137
|
+
raise( Exception.new( e.response ) )
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
end # class HttpService
|
149
|
+
|
150
|
+
end # module Services
|
151
|
+
|
152
|
+
end # module Facturama
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative "crud_service"
|
2
|
+
|
3
|
+
module Facturama
|
4
|
+
|
5
|
+
module Services
|
6
|
+
class ProductService < CrudService
|
7
|
+
|
8
|
+
def initialize( connection_info )
|
9
|
+
super(connection_info, "product")
|
10
|
+
end
|
11
|
+
|
12
|
+
end # class ProductService
|
13
|
+
|
14
|
+
end # module Services
|
15
|
+
|
16
|
+
end # module Facturama
|
@@ -0,0 +1,352 @@
|
|
1
|
+
|
2
|
+
require_relative "../facturama"
|
3
|
+
require_relative "sample_api.rb"
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
|
7
|
+
module Facturama
|
8
|
+
|
9
|
+
|
10
|
+
module Samples
|
11
|
+
|
12
|
+
class SampleApiMulti < SampleApi
|
13
|
+
|
14
|
+
|
15
|
+
def run
|
16
|
+
puts "====================================================================="
|
17
|
+
puts " FACTURAMA MULTIEMISOR SDK #{Facturama::VERSION}"
|
18
|
+
puts "====================================================================="
|
19
|
+
|
20
|
+
|
21
|
+
# Creación de una instacia de la API Multiemisor de Facturama, configurado con los datos del usuario de pruebas
|
22
|
+
facturama = create_api_instance
|
23
|
+
|
24
|
+
|
25
|
+
# Invocaciones a los ejemplos de uso de los servicios de Facturama API
|
26
|
+
begin
|
27
|
+
|
28
|
+
#sample_csds(facturama) # Servicio de CSD (certificados)
|
29
|
+
|
30
|
+
sample_cfdis(facturama) # Servicio de CFDI
|
31
|
+
|
32
|
+
|
33
|
+
rescue FacturamaException => ex
|
34
|
+
puts "----------- EXCEPCIONES -----------"
|
35
|
+
puts " * " + ex.message
|
36
|
+
|
37
|
+
if ex.details
|
38
|
+
ex.details.each do |item|
|
39
|
+
puts "#{item[0]}: " + item[1].join(",")
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
rescue Exception => ex
|
45
|
+
puts "----------- EXCEPCIONES -----------"
|
46
|
+
puts " * " + ex.to_s
|
47
|
+
end
|
48
|
+
end # run
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
55
|
+
# CONFIGURACION DEL ENTORNO DE LA API
|
56
|
+
def create_api_instance
|
57
|
+
facturama_user='pruebas'
|
58
|
+
facturama_password='pruebas2011'
|
59
|
+
is_development = true # true = Modo de pruebas / sandbox, false = Modo de Producción (Timbrado real)
|
60
|
+
|
61
|
+
|
62
|
+
#Creacion de una instancia de FacturamaApiMultiemisor
|
63
|
+
Facturama::FacturamaApiMulti.new(facturama_user,facturama_password,is_development)
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
69
|
+
# EJEMPLO DEL SERVICIO DE CSDS
|
70
|
+
def sample_csds(facturama)
|
71
|
+
puts "===== Ejemplo de CSD - Inicio ====="
|
72
|
+
|
73
|
+
sample_csds_list(facturama) # Listar todos los csd de la cuenta
|
74
|
+
|
75
|
+
sample_csds_load(facturama) # Cargar un nuevo CSD
|
76
|
+
|
77
|
+
sample_csds_update(facturama) # Obtiene un CSD mediante el RFC y lo actualiza
|
78
|
+
|
79
|
+
#sample_csds_remove(facturama) # Elmina el CSD asociado con el RFC
|
80
|
+
|
81
|
+
puts "===== Ejemplo de CSD - Fin ====="
|
82
|
+
end
|
83
|
+
|
84
|
+
# Ejemplo de obtener el listado de todos los certifiados cargados
|
85
|
+
def sample_csds_list(facturama)
|
86
|
+
puts "===== Obtener los CSD cargados - Inicio ====="
|
87
|
+
|
88
|
+
lst_csds = facturama.csds.list # Se obtiene una lista con todos los csds
|
89
|
+
lst_csds_count = lst_csds.count # Cantidad de csds
|
90
|
+
|
91
|
+
puts "Cantidad de CSDs: " + lst_csds_count.to_s
|
92
|
+
|
93
|
+
puts "===== Obtener los CSD cargados - Fin ====="
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# Carga de un nuevo certificado, para un RFC
|
98
|
+
# * La API espera que el certificado y la llave sean enviados en base64. Por lo que las cadenas aqui expuestas,
|
99
|
+
# representan el contenido de los archivos corresponidientes, en dicho formato
|
100
|
+
def sample_csds_load(facturama)
|
101
|
+
puts "===== Cargar nuevo CSD - Inicio ====="
|
102
|
+
|
103
|
+
csd_model = Facturama::Models::Csd.new({
|
104
|
+
Rfc: "AAA010101AAA",
|
105
|
+
Certificate: "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",
|
106
|
+
PrivateKey: "MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIAgEAAoIBAQACAggAMBQGCCqGSIb3DQMHBAgwggS9AgEAMASCBMh4EHl7aNSCaMDA1VlRoXCZ5UUmqErAbucRBAKNQXH8tz2zJ7hdZaOZx7PEfMiWh5Nh6e8G8kxY+GW4YCSbLxslkhBtfTR6v5JYv3vhgH7XzMCwJPOfX6gxeeCYZ4HTdDNAyBVCjTbJpqbo778ri33o+I4yx7zgMqA3mzVE61re6MPrGXh1YT/K9zZeEdmwvXQfPs9VnioKUhiswoMcJ3kc3FxGLrEAsjQqv/ZVOHPY3NrbcfpQUyprsCKv3rRdxkIRdMPY4eiA720mffzvDqyzeQ8xfwHTE8Xjunja4KXvW/mV7ItTH0vRXHc3HJQ0dNnyawXmbC1FiYbCVdswoYuVQmslvq3QEXUGwP3KYfxQzKatnU7nprkmsipPqPBqDrzqc6NSN/8rxIc5zTAL4bFul+CEKz9VybwdavgewEy7u3fPnKPN+y4HilNgmlbtS7seWpbIgVPA+woG2Ph5hsgREXZCjGKSRuI77/FLcI5CMrZR+FvbnaqG+gXDBTz2lWhK9pmWlVawT2pvfiHOLzYRf2YyuVbJ79D2EgbUKyp3kCQ6fddMzspPhD/pvLQizExeyIxImb/kQXs2mmtDnyFIsj4Hcn5wCcs+SDIj+FJnwRiKB6YfdzjIig/ZMfpgMpl0u69LX649uL318o+Hy3d5t3wxgSkTaJ5McKhWyh9x9vlHZhYyM6HArBNfP9cGF86M3GwAMHAiJQl9UevyKe6rlvAIDlop6l3M02m5hHUXUpPjz4j7inFXZzvSv0tFoSbEqGgno0Pa+0gWHqRwBEGLGEwHVfyEy+Of8g4+0jzo0jNPIcurA5xRh9HSRSAd3kdEhx75eeVL7lBdLjRUkbtRtg7nelSjqAX7tQZK6Awp5C/17W96+f/vtjB+Y+ZgrSUjnQDADnZCnapIrzHgE3ZanhGAtnMMl+o4aLd1+74inG4jht/GJB60raSQfYrDrM3kBs0oyfpbEk5TI8ISzRlRmejv+mqpTogJaAqhnLP7rAli3d4pRhUjbACn/xQSFKxl2OURdmnMlvlbb6pleXviJHRxzPPQ25NVdWvmCYWrDfAZYn8X1sABOdyrth38BfmAVsyyPATYFB+5cXuNIZkPz1swz3859iZWTn5JRfPEAGICu5G6w6nrgOLYM9UqOPmxofzEdiEPafLQ5orMxdSWF6+3mD2Yw/VP+B43B/oYehgfrYjBUJt2D04VU/v8XK1ZUVgX/Co0odcdcszAP+ljQ7UVhW+uxVMd2sEprwepPPjYT3HvdI6RBB94yYBWfkoCSo/jsrrRpw2DVEyvoDp/hOXKyt8Y/8UGLCxJUhhv5fEiezYnlUAmwAGjgZfzfAErx0gkQFBgNKglEA7jz0Dqc2Z92pGVGTyPtXqRsqX3IYX5WsZVUoJim0wI7+LNmKpu147ePC0G4Sf4AGoZyPWVXq2SZSPpN261pIKSoLEDeA8WIKj2U5JG2DMMYokV0bZ1TsabrwHvwsp3muLnaP8L+n2fBplbhAEE2buBXvsATixMGu57ZI5WKFLnHn4KIBrZzALCtGehfFbCsdf1nBR6aAt+BpWhhZki54fZTurgMr6zuC5hAaP4rExW+LCc3upHMW7R9DcHWaZuZIfwnVDImnAQ9UOsz+A=",
|
107
|
+
PrivateKeyPassword:"12345678a"
|
108
|
+
})
|
109
|
+
|
110
|
+
facturama.csds.create(csd_model)
|
111
|
+
puts "Se ha cargado un nuevo CSD para el Rfc: #{csd_model.Rfc}"
|
112
|
+
|
113
|
+
puts "===== Cargar nuevo CSD - Fin ====="
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
# Ejemplo de eliminacion del un CSD asociado como RFC
|
120
|
+
def sample_csds_remove(facturama)
|
121
|
+
puts "===== Eliminar CSD asociado con un RFC- Inicio ====="
|
122
|
+
|
123
|
+
facturama.csds.remove("AAA010101AAA")
|
124
|
+
puts "Se ha eliminado el CSD asociado al Rfc"
|
125
|
+
|
126
|
+
puts "===== Eliminar CSD asociado con un RFC- Inicio ====="
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
# Ejemplo de actualización de CSD asociado con un RFC
|
131
|
+
def sample_csds_update(facturama)
|
132
|
+
puts "===== Actualiza el CSD asociado con un RFC- Inicio ====="
|
133
|
+
|
134
|
+
csd = facturama.csds.retrieve("AAA010101AAA")
|
135
|
+
|
136
|
+
csd['Certificate'] = "MIIF+TCCA+GgAwIBAgIUMzAwMDEwMDAwMDAzMDAwMjM3MDEwDQYJKoZIhvcNAQELBQAwggFmMSAwHgYDVQQDDBdBLkMuIDIgZGUgcHJ1ZWJhcyg0MDk2KTEvMC0GA1UECgwmU2VydmljaW8gZGUgQWRtaW5pc3RyYWNpw7NuIFRyaWJ1dGFyaWExODA2BgNVBAsML0FkbWluaXN0cmFjacOzbiBkZSBTZWd1cmlkYWQgZGUgbGEgSW5mb3JtYWNpw7NuMSkwJwYJKoZIhvcNAQkBFhphc2lzbmV0QHBydWViYXMuc2F0LmdvYi5teDEmMCQGA1UECQwdQXYuIEhpZGFsZ28gNzcsIENvbC4gR3VlcnJlcm8xDjAMBgNVBBEMBTA2MzAwMQswCQYDVQQGEwJNWDEZMBcGA1UECAwQRGlzdHJpdG8gRmVkZXJhbDESMBAGA1UEBwwJQ295b2Fjw6FuMRUwEwYDVQQtEwxTQVQ5NzA3MDFOTjMxITAfBgkqhkiG9w0BCQIMElJlc3BvbnNhYmxlOiBBQ0RNQTAeFw0xNzA1MTgwMzU0NTFaFw0yMTA1MTgwMzU0NTFaMIHlMSkwJwYDVQQDEyBBQ0NFTSBTRVJWSUNJT1MgRU1QUkVTQVJJQUxFUyBTQzEpMCcGA1UEKRMgQUNDRU0gU0VSVklDSU9TIEVNUFJFU0FSSUFMRVMgU0MxKTAnBgNVBAoTIEFDQ0VNIFNFUlZJQ0lPUyBFTVBSRVNBUklBTEVTIFNDMSUwIwYDVQQtExxBQUEwMTAxMDFBQUEgLyBIRUdUNzYxMDAzNFMyMR4wHAYDVQQFExUgLyBIRUdUNzYxMDAzTURGUk5OMDkxGzAZBgNVBAsUEkNTRDEwX0FBQTAxMDEwMUFBQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAIiV+76Q7p9i5Bj4G1YuYuPtf/cO/dyNX19o6y57CiKcgGYEqPqb88cJ/IPPyFPIFtBdxYJmqikxMwxDHTIsolI0GMvqEO1BsokcDOL4UfMZt7NmYaH1P8Nj/fO5xn0b1qSnSfQHGdPLMgXsLPhaR69HREsVEIowEMM5ucoNArSNzel4XJU8X/dnoumZvaOyCdvEC076NzB3UJA53ZD1xvvPEedUfAfj2eaUCQJYPnToyf7TAOGzzGkX5EGcjxC3YfcXGwG2eNdbSbxSiADPx6QACgslCu1vzmCzwQAmfeHWQvirpZccJyD/8shd7z7fv5A/G0g3aDloM5AXwA3nDVsCAwEAAaMdMBswDAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCBsAwDQYJKoZIhvcNAQELBQADggIBAJepSmoMRmasH1IyLe68oM6+Qpm/kXjwQw8ALMkhHTI3XmxjUVqpJ6k9zZQfwyTLc2UZIo8jdO4WH3bcRBDcYOkciW3KxhKAbLgJPHAieVOyObXViET0ktLL6xeDHnf5Au4LOi0m01E8IPFbxYKb+RU1xpOKqJuRHH5dfRBg4HV8y+OTa5lVZil+sAhwdyXFsPf9FqN1SNn9EuKjYc9+lkRiGcHPNb1ZAtDsaQdGzoAbR+Z6m9FdZB/XU+Huls+ePdkw1t2/37AJZkYqr3wVNKrrpQkax9DrnFT8E+7xKXLcbpw3YOYBoENj2+NuMn29sn3U97wKlpyn/GeMwbkCmOGBAMtK9O6+wRrcEmu9Js68asHd5JQSzA39BRAUjb/9aefmWTb6DNm22IUUSSOT9MK5yWGncdWxKrNtMvx7OyYlYV2/qG4p/rMlj6nZcIpwONhyLUwxr74kO0Jo3zus81t9S/J91jumiwyNVqJZ77vmAy6lQnr8Og9/YaIzDH5L/byJQJquDKEmLvuya4sQ2iJj+p282RNpBscO/iyma8T+bZjG2CFYUTwGtOEZ2aLqApJ4cCBW7Ip569B+g7mgG8fdij6E1OlJ8Y3+ovBMak8LtnFVxsfthdWOK+AU2hWGU88rfZkLJ0RJn8oAq/6ri0iJNCKym/mc9g0JpNw+asMM"
|
137
|
+
csd['PrivateKey'] = "MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIAgEAAoIBAQACAggAMBQGCCqGSIb3DQMHBAgwggS9AgEAMASCBMh4EHl7aNSCaMDA1VlRoXCZ5UUmqErAbucRBAKNQXH8tz2zJ7hdZaOZx7PEfMiWh5Nh6e8G8kxY+GW4YCSbLxslkhBtfTR6v5JYv3vhgH7XzMCwJPOfX6gxeeCYZ4HTdDNAyBVCjTbJpqbo778ri33o+I4yx7zgMqA3mzVE61re6MPrGXh1YT/K9zZeEdmwvXQfPs9VnioKUhiswoMcJ3kc3FxGLrEAsjQqv/ZVOHPY3NrbcfpQUyprsCKv3rRdxkIRdMPY4eiA720mffzvDqyzeQ8xfwHTE8Xjunja4KXvW/mV7ItTH0vRXHc3HJQ0dNnyawXmbC1FiYbCVdswoYuVQmslvq3QEXUGwP3KYfxQzKatnU7nprkmsipPqPBqDrzqc6NSN/8rxIc5zTAL4bFul+CEKz9VybwdavgewEy7u3fPnKPN+y4HilNgmlbtS7seWpbIgVPA+woG2Ph5hsgREXZCjGKSRuI77/FLcI5CMrZR+FvbnaqG+gXDBTz2lWhK9pmWlVawT2pvfiHOLzYRf2YyuVbJ79D2EgbUKyp3kCQ6fddMzspPhD/pvLQizExeyIxImb/kQXs2mmtDnyFIsj4Hcn5wCcs+SDIj+FJnwRiKB6YfdzjIig/ZMfpgMpl0u69LX649uL318o+Hy3d5t3wxgSkTaJ5McKhWyh9x9vlHZhYyM6HArBNfP9cGF86M3GwAMHAiJQl9UevyKe6rlvAIDlop6l3M02m5hHUXUpPjz4j7inFXZzvSv0tFoSbEqGgno0Pa+0gWHqRwBEGLGEwHVfyEy+Of8g4+0jzo0jNPIcurA5xRh9HSRSAd3kdEhx75eeVL7lBdLjRUkbtRtg7nelSjqAX7tQZK6Awp5C/17W96+f/vtjB+Y+ZgrSUjnQDADnZCnapIrzHgE3ZanhGAtnMMl+o4aLd1+74inG4jht/GJB60raSQfYrDrM3kBs0oyfpbEk5TI8ISzRlRmejv+mqpTogJaAqhnLP7rAli3d4pRhUjbACn/xQSFKxl2OURdmnMlvlbb6pleXviJHRxzPPQ25NVdWvmCYWrDfAZYn8X1sABOdyrth38BfmAVsyyPATYFB+5cXuNIZkPz1swz3859iZWTn5JRfPEAGICu5G6w6nrgOLYM9UqOPmxofzEdiEPafLQ5orMxdSWF6+3mD2Yw/VP+B43B/oYehgfrYjBUJt2D04VU/v8XK1ZUVgX/Co0odcdcszAP+ljQ7UVhW+uxVMd2sEprwepPPjYT3HvdI6RBB94yYBWfkoCSo/jsrrRpw2DVEyvoDp/hOXKyt8Y/8UGLCxJUhhv5fEiezYnlUAmwAGjgZfzfAErx0gkQFBgNKglEA7jz0Dqc2Z92pGVGTyPtXqRsqX3IYX5WsZVUoJim0wI7+LNmKpu147ePC0G4Sf4AGoZyPWVXq2SZSPpN261pIKSoLEDeA8WIKj2U5JG2DMMYokV0bZ1TsabrwHvwsp3muLnaP8L+n2fBplbhAEE2buBXvsATixMGu57ZI5WKFLnHn4KIBrZzALCtGehfFbCsdf1nBR6aAt+BpWhhZki54fZTurgMr6zuC5hAaP4rExW+LCc3upHMW7R9DcHWaZuZIfwnVDImnAQ9UOsz+A="
|
138
|
+
csd['PrivateKeyPassword'] = "12345678a"
|
139
|
+
|
140
|
+
facturama.csds.update(csd, "AAA010101AAA")
|
141
|
+
|
142
|
+
puts "===== Actualiza CSD asociado con un RFC - Inicio ====="
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
148
|
+
# EJEMPLO DEL SERVICIO DE CFDI
|
149
|
+
def sample_cfdis( facturama )
|
150
|
+
puts "===== Ejemplo de CFDI - Inicio ====="
|
151
|
+
|
152
|
+
# Creacion del cfdi en su forma general (sin items / productos) asociados
|
153
|
+
cfdi = sample_cfdis_create(facturama)
|
154
|
+
|
155
|
+
cfdi_uuid = cfdi['Complement']['TaxStamp']['Uuid']
|
156
|
+
puts "Se creó exitosamente el cfdi con el folio fiscal: " + cfdi_uuid
|
157
|
+
|
158
|
+
# Descarga de los arvhivos PDF y XML del cfdi recien creado
|
159
|
+
file_path = "factura" + cfdi_uuid
|
160
|
+
facturama.cfdis.save_pdf( file_path + ".pdf", cfdi['Id'])
|
161
|
+
facturama.cfdis.save_xml( file_path + ".xml", cfdi['Id'])
|
162
|
+
|
163
|
+
# Envio del cfdi por correo
|
164
|
+
if facturama.cfdis.send_by_mail(cfdi['Id'], "chucho@facturama.mx", "Factura del servicio" )
|
165
|
+
puts "Se envió por correo exitosamente el cfdi con el folio fiscal: " + cfdi_uuid
|
166
|
+
end
|
167
|
+
|
168
|
+
# Se elmina el cfdi recien creado
|
169
|
+
facturama.cfdis.remove(cfdi['Id'])
|
170
|
+
puts "Se elminó exitosamente el cfdi con el folio fiscal: " + cfdi_uuid
|
171
|
+
|
172
|
+
|
173
|
+
# Consulta de cfdi por palabra clave o Rfc
|
174
|
+
lst_by_rfc = facturama.cfdis.list_by_rfc("ESO1202108R2")
|
175
|
+
lst_by_keyword = facturama.cfdis.list_by_keyword("Software")
|
176
|
+
|
177
|
+
puts "Se obtiene la lista de facturas por RFC: #{lst_by_rfc.length}"
|
178
|
+
puts "Se obtiene la lista de facturas por KEYWORD: #{lst_by_keyword.length}"
|
179
|
+
|
180
|
+
|
181
|
+
puts "===== Ejemplo de CFDI - Fin ====="
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
# Ejemplo de creación de un CFDI
|
187
|
+
# En la API MULTIMEMISOR Se puede cambiar el campo de "Issuer" y emitir una factura,
|
188
|
+
# siempre y cuando previamente cargáramos los Certificados CSD
|
189
|
+
# * Nota:
|
190
|
+
# La creación de una factura muy similar a la forma de crearla en API WEB.
|
191
|
+
# Y se diferencía en que aquí se tiene la sección de:
|
192
|
+
# "Issuer": {
|
193
|
+
# "FiscalRegime": "601",
|
194
|
+
# "Rfc": "AAA010101AAA",
|
195
|
+
# "Name": "EXPRESION EN SOFTWARE"
|
196
|
+
# },
|
197
|
+
def sample_cfdis_create(facturama)
|
198
|
+
|
199
|
+
cfdi = {
|
200
|
+
"Serie": "R",
|
201
|
+
"Currency": "MXN",
|
202
|
+
"ExpeditionPlace": "78116",
|
203
|
+
"PaymentConditions": "CREDITO A SIETE DIAS",
|
204
|
+
"Folio": "100",
|
205
|
+
"CfdiType": "I",
|
206
|
+
"PaymentForm": "03",
|
207
|
+
"PaymentMethod": "PUE",
|
208
|
+
|
209
|
+
|
210
|
+
"Issuer": {
|
211
|
+
"FiscalRegime": "601",
|
212
|
+
"Rfc": "AAA010101AAA",
|
213
|
+
"Name": "EXPRESION EN SOFTWARE"
|
214
|
+
},
|
215
|
+
|
216
|
+
|
217
|
+
"Receiver": {
|
218
|
+
"Rfc": "XAXX010101000",
|
219
|
+
"Name": "RADIAL SOFTWARE SOLUTIONS",
|
220
|
+
"CfdiUse": "P01"
|
221
|
+
},
|
222
|
+
"Items": [
|
223
|
+
{
|
224
|
+
"ProductCode": "10101504",
|
225
|
+
"IdentificationNumber": "EDL",
|
226
|
+
"Description": "Estudios de viabilidad",
|
227
|
+
"Unit": "NO APLICA",
|
228
|
+
"UnitCode": "MTS",
|
229
|
+
"UnitPrice": 50.0,
|
230
|
+
"Quantity": 2.0,
|
231
|
+
"Subtotal": 100.0,
|
232
|
+
"Taxes": [{
|
233
|
+
"Total": 16.0,
|
234
|
+
"Name": "IVA",
|
235
|
+
"Base": 100.0,
|
236
|
+
"Rate": 0.16,
|
237
|
+
"IsRetention": false
|
238
|
+
}],
|
239
|
+
"Total": 116.0
|
240
|
+
},
|
241
|
+
{
|
242
|
+
"ProductCode": "10101504",
|
243
|
+
"IdentificationNumber": "001",
|
244
|
+
"Description": "SERVICIO DE COLOCACION",
|
245
|
+
"Unit": "NO APLICA",
|
246
|
+
"UnitCode": "E49",
|
247
|
+
"UnitPrice": 100.0,
|
248
|
+
"Quantity": 15.0,
|
249
|
+
"Subtotal": 1500.0,
|
250
|
+
"Discount": 0.0,
|
251
|
+
"Taxes": [{
|
252
|
+
"Total": 240.0,
|
253
|
+
"Name": "IVA",
|
254
|
+
"Base": 1500.0,
|
255
|
+
"Rate": 0.16,
|
256
|
+
"IsRetention": false
|
257
|
+
}],
|
258
|
+
"Total": 1740.0
|
259
|
+
}
|
260
|
+
]
|
261
|
+
}
|
262
|
+
|
263
|
+
|
264
|
+
# Creación del CFDI mediante la API, para su creación
|
265
|
+
facturama.cfdis.create(cfdi)
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
def add_items_to_cfdi(facturama, currency, cfdi)
|
270
|
+
|
271
|
+
lst_products = facturama.products.list
|
272
|
+
lst_products_size = lst_products.length
|
273
|
+
|
274
|
+
n_items = (rand( lst_products.length ) % 10) + 1
|
275
|
+
|
276
|
+
decimals = currency['Decimals'].to_i
|
277
|
+
|
278
|
+
# Lista de conceptos para el CFDI
|
279
|
+
lst_items = Array.new
|
280
|
+
|
281
|
+
|
282
|
+
n_begin = lst_products_size - 1 - n_items
|
283
|
+
|
284
|
+
for index in n_begin..lst_products_size
|
285
|
+
|
286
|
+
product = lst_products[index] # Un producto cualquiera
|
287
|
+
|
288
|
+
if( product.nil? )
|
289
|
+
break
|
290
|
+
|
291
|
+
end
|
292
|
+
|
293
|
+
quantity = rand(5) + 1 # una cantidad aleatoria de elementos de este producto
|
294
|
+
|
295
|
+
discount = product['Price'] % ( product['Price']) == 0 ? 1 : rand( (product['Price'].to_i ) )
|
296
|
+
subtotal = ( product['Price'] * quantity).round(decimals) # Redondeo de acuerdo a la moneda
|
297
|
+
|
298
|
+
|
299
|
+
|
300
|
+
item = Facturama::Models::Item.new({
|
301
|
+
ProductCode: product['CodeProdServ'],
|
302
|
+
UnitCode: product['UnitCode'],
|
303
|
+
Unit: product['Unit'],
|
304
|
+
Description: product['Description'],
|
305
|
+
IdentificationNumber: product['IdentificationNumber'],
|
306
|
+
Quantity: quantity,
|
307
|
+
Discount: discount.round(decimals),
|
308
|
+
UnitPrice: product['Price'].round(decimals),
|
309
|
+
Subtotal: subtotal,
|
310
|
+
Taxes: nil
|
311
|
+
|
312
|
+
})
|
313
|
+
|
314
|
+
|
315
|
+
base_amount = (subtotal - discount).round(decimals)
|
316
|
+
taxes = product['Taxes'].map { |t|
|
317
|
+
Facturama::Models::Tax.new(
|
318
|
+
Name: t['Name'],
|
319
|
+
IsQuota: t['IsQuota'],
|
320
|
+
IsRetention: t['IsRetention'],
|
321
|
+
Rate: t['Rate'].to_f.round(decimals),
|
322
|
+
Base: base_amount,
|
323
|
+
Total: (base_amount * t['Rate'].to_f).round(decimals)
|
324
|
+
)
|
325
|
+
}
|
326
|
+
|
327
|
+
retentions_amount = 0
|
328
|
+
transfers_amount = 0
|
329
|
+
if taxes.length > 0
|
330
|
+
item.Taxes = taxes
|
331
|
+
# Calculo del monto total del concepto, tomando en cuenta los impuestos
|
332
|
+
retentions_amount = item.Taxes.select { |tax| tax.IsRetention }.sum(&:Total)
|
333
|
+
transfers_amount = item.Taxes.select { |tax| ! tax.IsRetention }.sum(&:Total)
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
item.Total = (item.Subtotal - item.Discount + transfers_amount - retentions_amount).round(decimals)
|
338
|
+
|
339
|
+
lst_items.push(item)
|
340
|
+
|
341
|
+
end
|
342
|
+
|
343
|
+
cfdi.Items = lst_items
|
344
|
+
|
345
|
+
end
|
346
|
+
|
347
|
+
|
348
|
+
|
349
|
+
end # class SampleApiWeb
|
350
|
+
end
|
351
|
+
|
352
|
+
end
|