facturama 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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'] = "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"
|
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
|