facturama 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/lib/facturama.rb +56 -0
  3. data/lib/facturama/facturama_api_multi.rb +37 -0
  4. data/lib/facturama/facturama_api_web.rb +55 -0
  5. data/lib/facturama/models/address.rb +16 -0
  6. data/lib/facturama/models/branch_office.rb +14 -0
  7. data/lib/facturama/models/cfdi.rb +80 -0
  8. data/lib/facturama/models/cfdi_relation.rb +10 -0
  9. data/lib/facturama/models/cfdi_relations.rb +12 -0
  10. data/lib/facturama/models/client.rb +19 -0
  11. data/lib/facturama/models/complement.rb +8 -0
  12. data/lib/facturama/models/connection_info.rb +36 -0
  13. data/lib/facturama/models/csd.rb +14 -0
  14. data/lib/facturama/models/exception/facturama_exception.rb +18 -0
  15. data/lib/facturama/models/exception/model_exception.rb +11 -0
  16. data/lib/facturama/models/image.rb +11 -0
  17. data/lib/facturama/models/item.rb +25 -0
  18. data/lib/facturama/models/model.rb +75 -0
  19. data/lib/facturama/models/product.rb +27 -0
  20. data/lib/facturama/models/product_tax.rb +14 -0
  21. data/lib/facturama/models/receiver.rb +15 -0
  22. data/lib/facturama/models/serie.rb +13 -0
  23. data/lib/facturama/models/tax.rb +14 -0
  24. data/lib/facturama/models/tax_entity.rb +21 -0
  25. data/lib/facturama/models/tax_stamp.rb +12 -0
  26. data/lib/facturama/services/branch_office_service.rb +16 -0
  27. data/lib/facturama/services/catalog_service.rb +42 -0
  28. data/lib/facturama/services/cfdi_multi_service.rb +164 -0
  29. data/lib/facturama/services/cfdi_service.rb +172 -0
  30. data/lib/facturama/services/client_service.rb +19 -0
  31. data/lib/facturama/services/crud_service.rb +41 -0
  32. data/lib/facturama/services/csd_service.rb +16 -0
  33. data/lib/facturama/services/http_service.rb +152 -0
  34. data/lib/facturama/services/product_service.rb +16 -0
  35. data/lib/facturama/version.rb +4 -0
  36. data/lib/samples/sample_api.rb +17 -0
  37. data/lib/samples/sample_api_multi.rb +352 -0
  38. data/lib/samples/sample_api_web.rb +454 -0
  39. metadata +94 -0
@@ -0,0 +1,454 @@
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 SampleApiWeb < SampleApi
13
+
14
+ def initialize
15
+
16
+ end
17
+
18
+ def run
19
+
20
+
21
+
22
+
23
+ puts "============================================================"
24
+ puts " FACTURAMA WEB SDK #{Facturama::VERSION}"
25
+ puts "============================================================"
26
+
27
+
28
+ # Creación de una instacia de la API Facturama, configurado con los datos del usuario de pruebas
29
+ facturama = create_api_instance
30
+
31
+
32
+ # Invocaciones a los ejemplos de uso de los servicios de Facturama API
33
+ begin
34
+ #sample_clients(facturama) # Servicio de cliente
35
+
36
+ sample_products(facturama) # Servicio de productos
37
+
38
+ #sample_cfdis(facturama) # Servicio de CFDI
39
+
40
+
41
+
42
+
43
+
44
+ rescue FacturamaException => ex
45
+ puts "----------- EXCEPCIONES -----------"
46
+ puts " * " + ex.message
47
+
48
+ if ex.details
49
+ ex.details.each do |item|
50
+ puts "#{item[0]}: " + item[1].join(",")
51
+ end
52
+ end
53
+
54
+
55
+
56
+
57
+
58
+ rescue Exception => ex
59
+ puts "----------- EXCEPCIONES -----------"
60
+ puts " * " + ex.to_s
61
+ end
62
+ end
63
+
64
+
65
+
66
+
67
+
68
+ # ---------------------------------------------------------------------------------------------------------------------
69
+ # CONFIGURACION DEL ENTORNO DE LA API
70
+ def create_api_instance
71
+ facturama_user='pruebas'
72
+ facturama_password='pruebas2011'
73
+ is_development = true # true = Modo de pruebas / sandbox, false = Modo de Producción (Timbrado real)
74
+
75
+
76
+ #Creacion de una instancia de FacturamaApi
77
+ Facturama::FacturamaApiWeb.new(facturama_user,facturama_password,is_development)
78
+ end
79
+
80
+
81
+
82
+
83
+ # ---------------------------------------------------------------------------------------------------------------------
84
+ # EJEMPLO DEL SERVICIO DE CLIENTES
85
+ # - Listado de clientes
86
+ # - Agregar cliente
87
+ # - Obtener cliente específico y editarlo
88
+ def sample_clients(facturama)
89
+
90
+ sample_clients_list(facturama) # Listar todos los clientes
91
+
92
+ new_client = sample_clients_create(facturama) # Agregar cliente
93
+ client_id = new_client['Id'] # Id del cliente recientemente agregado
94
+
95
+ sample_clients_retrieve_and_update(facturama, client_id)
96
+
97
+ sample_clients_remove(facturama, client_id)
98
+
99
+ end
100
+
101
+
102
+
103
+ # Obtiene el listado de clientes y muestra la cantidad de los mismos
104
+ def sample_clients_list(facturama)
105
+ puts "===== Obtener los clientes - Inicio ====="
106
+
107
+ lst_clients = facturama.clients.list # Se obtiene una lista con todos los clientes
108
+ lst_clients_count = lst_clients.count # Cantidad inicial de clientes
109
+
110
+
111
+
112
+ puts "Cantidad inicial de clientes: " + lst_clients_count.to_s
113
+
114
+ puts "===== Obtener los clientes - Fin ====="
115
+ end
116
+
117
+
118
+
119
+ # Agrega un cliente
120
+ def sample_clients_create(facturama)
121
+ puts "===== Agregar cliente - Inicio ====="
122
+
123
+ facturama.clients.create(Facturama::Models::Client.new(
124
+ { Email: "info@pedroperez.net",
125
+ Rfc: "RODJ899315654",
126
+ CfdiUse: "P01",
127
+ Name: "Pedro Perez Development Environment",
128
+
129
+ Address: {Country: "MEXICO",
130
+ ExteriorNumber: "1230",
131
+ InteriorNumber: "B",
132
+ Locality: "San Luis",
133
+ Municipality: "San Luis Potosí",
134
+ Neighborhood: "Lomas 4ta",
135
+ State: "San Luis Potosí",
136
+ Street: "Cañada de Gomez",
137
+ ZipCode: "78220"
138
+ }
139
+ }))
140
+
141
+ puts "===== Agregar cliente - Fin ====="
142
+ end
143
+
144
+
145
+
146
+ # Obtiene un cliente específico, lo edita y lo guarda
147
+ def sample_clients_retrieve_and_update(facturama, client_id)
148
+
149
+ puts "===== Obtener cliente y editarlo - Inicio ====="
150
+
151
+ # Se obtiene el cliente con el Id especificado
152
+ specific_client = facturama.clients.retrieve(client_id)
153
+
154
+
155
+ # Se ha encontrado un cliente con ese Id
156
+ if specific_client != nil then
157
+
158
+ puts "Specific Client: "
159
+ puts JSON[specific_client]
160
+
161
+ # Edición del campo RFC
162
+ specific_client['Rfc'] = "XAXX010101000"
163
+ specific_client['Email'] = "wm@joseromero.net"
164
+ facturama.clients.update(specific_client, client_id)
165
+
166
+
167
+ # Se obtiene nuevamente el cliente para confirmar que ha cambiado
168
+ specific_client = facturama.clients.retrieve(client_id)
169
+
170
+ if specific_client['Rfc'] == "XAXX010101000" then
171
+ puts "Cliente editado, ahora su RFC es XAXX010101000"
172
+ else
173
+ puts "Error al editar cliente"
174
+ end
175
+ end
176
+
177
+
178
+ puts "===== Obtener cliente y editarlo - Fin ====="
179
+ end
180
+
181
+
182
+
183
+ # Elimina un cliente
184
+ def sample_clients_remove(facturama, client_id)
185
+
186
+ puts "===== Eliminar cliente - Inicio ====="
187
+
188
+ specific_client = facturama.clients.remove(client_id)
189
+
190
+ puts "Cliente eliminado: "
191
+ puts JSON[specific_client]
192
+
193
+ puts "===== Eliminar cliente - Fin ====="
194
+
195
+ end
196
+
197
+
198
+
199
+
200
+
201
+ # ---------------------------------------------------------------------------------------------------------------------
202
+ # EJEMPLO DEL SERVICIO DE PRODUCTOS
203
+ def sample_products( facturama )
204
+ sample_products_list(facturama) # Listar todos los productos
205
+
206
+ sample_products_create(facturama) # Agregar producto y eliminarlo
207
+ end
208
+
209
+
210
+
211
+ # Obtiene el listado de productos y muestra la cantidad de los mismos
212
+ def sample_products_list(facturama)
213
+ puts "===== Obtener los productos - Inicio ====="
214
+
215
+ lst_products = facturama.products.list # Se obtiene una lista con todos los productos
216
+ lst_products_count = lst_products.count # Cantidad inicial de productos
217
+
218
+ puts "Cantidad inicial de productos: " + lst_products_count.to_s
219
+
220
+ puts "===== Obtener los productos - Fin ====="
221
+ end
222
+
223
+
224
+
225
+ # Agrega un cliente
226
+ def sample_products_create(facturama)
227
+ puts "===== Agregar producto - Inicio ====="
228
+
229
+ unit = facturama.catalog.units("servicio").first # La primera unidad que tenga que ver con servicio
230
+ prod = facturama.catalog.products_or_services("desarrollo").first # Se toma el primer producto o servicio
231
+
232
+
233
+
234
+ product_model = Facturama::Models::Product.new(
235
+ {
236
+ Unit: "Servicio",
237
+ UnitCode: unit['Value'],
238
+ IdentificationNumber: "WEB003",
239
+ Name: "Sitio Web CMS",
240
+ Description: "Desarrollo e implementación de sitio web empleando un CMS",
241
+ Price: 6500.0,
242
+ CodeProdServ: prod['Value'],
243
+ CuentaPredial: "123",
244
+
245
+ Taxes: [
246
+ {
247
+ Name: "IVA",
248
+ Rate: 0.16,
249
+ IsRetention: false
250
+ }
251
+ ]
252
+ }
253
+ )
254
+
255
+ product = facturama.products.create(product_model)
256
+
257
+ puts "Se creo exitosamente un producto con el id: " + product['Id']
258
+
259
+
260
+ facturama.products.delete( product['Id'] )
261
+ puts "Se eliminó exitosamente un producto con el id: " + product['Id']
262
+
263
+
264
+ puts "===== Agregar producto - Fin ====="
265
+ end
266
+
267
+
268
+
269
+
270
+
271
+
272
+
273
+
274
+ # ---------------------------------------------------------------------------------------------------------------------
275
+ # EJEMPLO DEL SERVICIO DE CFDI
276
+ # En la API WEB el emisor es Siempre la entidad fiscal configurada en la cuenta
277
+ def sample_cfdis( facturama )
278
+ puts "===== Ejemplo de CFDI - Inicio ====="
279
+
280
+ # Se obtiene la moneda con el valor "MXN"
281
+ lst_currencies = facturama::catalog.currencies
282
+ currency = lst_currencies.select {|currency| currency["Value"] == "MXN" }.first
283
+
284
+
285
+ # Creacion del cfdi en su forma general (sin items / productos) asociados
286
+ cfdi_model = sample_cfdis_create(facturama, currency)
287
+
288
+ # Agregar los items que lleva el cfdi ( para este ejemplo, se agregan con datos aleatorios)
289
+ add_items_to_cfdi(facturama, currency, cfdi_model)
290
+
291
+ # Creación del CFDI mediante la API, para su creación
292
+ cfdi = facturama.cfdis.create(cfdi_model)
293
+ cfdi_uuid = cfdi['Complement']['TaxStamp']['Uuid']
294
+ puts "Se creó exitosamente el cfdi con el folio fiscal: " + cfdi_uuid
295
+
296
+ # Descarga de los arvhivos PDF y XML del cfdi recien creado
297
+ file_path = "factura" + cfdi_uuid
298
+ facturama.cfdis.save_pdf( file_path + ".pdf", cfdi['Id'])
299
+ facturama.cfdis.save_xml( file_path + ".xml", cfdi['Id'])
300
+
301
+ # Envio del cfdi por correo
302
+ if facturama.cfdis.send_by_mail(cfdi['Id'], "chucho@facturama.mx", "Factura del servicio" )
303
+ puts "Se envió por correo exitosamente el cfdi con el folio fiscal: " + cfdi_uuid
304
+ end
305
+
306
+ # Se elmina el cfdi recien creado
307
+ facturama.cfdis.remove(cfdi['Id'])
308
+ puts "Se elminó exitosamente el cfdi con el folio fiscal: " + cfdi_uuid
309
+
310
+
311
+ # Consulta de cfdi por palabra clave o Rfc
312
+ lst_by_rfc = facturama.cfdis.list_by_rfc("ESO1202108R2")
313
+ lst_by_keyword = facturama.cfdis.list_by_keyword("Software")
314
+
315
+ puts "Se obtiene la lista de facturas por RFC: #{lst_by_rfc.length}"
316
+ puts "Se obtiene la lista de facturas por KEYWORD: #{lst_by_keyword.length}"
317
+
318
+
319
+
320
+ puts "===== Ejemplo de CFDI - Fin ====="
321
+ end
322
+
323
+
324
+
325
+ def sample_cfdis_create(facturama, currency)
326
+
327
+ # Nombre para el CFDI, para el ejemplo, tomado el primero de la lista del catálogo de nombres en el PDF
328
+ name_for_pdf = facturama.catalog.name_ids.first; # Nombre en el pdf: "Factura"
329
+
330
+ # Método de pago
331
+ payment_method = facturama.catalog.payment_methods.select {|method| method["Name"] == "Pago en una sola exhibición" }.first
332
+
333
+
334
+ # Forma de pago
335
+ payment_form = facturama.catalog.payment_forms.select {|method| method["Name"] == "Efectivo" }.first
336
+
337
+
338
+ # Cliente (se toma como cliente el "cliente generico", aquel que tiene el RFC genérico),
339
+ #(como los clientes son exclusivos para cada usuario, se debe previamente dar de alta este cliente)
340
+ client = facturama.clients.list.select {|client| client["Rfc"] == "XAXX010101000" }.first
341
+
342
+
343
+ # Lugar de expedición
344
+ branch_office = facturama.branch_office.list.first
345
+
346
+ # Fecha de emision (ahora mismo)
347
+ date = Time.now.strftime("%Y-%m-%d %H:%M:%S")
348
+
349
+ cfdi = Facturama::Models::Cfdi.new(
350
+ {
351
+ NameId: name_for_pdf['Value'],
352
+ CfdiType: Facturama::CfdiType::INGRESO,
353
+ PaymentForm: payment_form['Value'],
354
+ PaymentMethod: payment_method['Value'],
355
+ Currency: currency['Value'],
356
+ Date: date,
357
+ ExpeditionPlace: branch_office['Address']['ZipCode'],
358
+ Receiver: {
359
+ CfdiUse: client['CfdiUse'],
360
+ Name: client['Name'],
361
+ Rfc: client['Rfc']
362
+ },
363
+ Items: []
364
+ }
365
+ )
366
+
367
+
368
+ end
369
+
370
+
371
+ def add_items_to_cfdi(facturama, currency, cfdi)
372
+
373
+ lst_products = facturama.products.list
374
+ lst_products_size = lst_products.length
375
+
376
+ n_items = (rand( lst_products.length ) % 10) + 1
377
+
378
+ decimals = currency['Decimals'].to_i
379
+
380
+ # Lista de conceptos para el CFDI
381
+ lst_items = Array.new
382
+
383
+
384
+ n_begin = lst_products_size - 1 - n_items
385
+
386
+ for index in n_begin..lst_products_size
387
+
388
+ product = lst_products[index] # Un producto cualquiera
389
+
390
+ if( product.nil? )
391
+ break
392
+
393
+ end
394
+
395
+ quantity = rand(5) + 1 # una cantidad aleatoria de elementos de este producto
396
+
397
+ discount = product['Price'] % ( product['Price']) == 0 ? 1 : rand( (product['Price'].to_i ) )
398
+ subtotal = ( product['Price'] * quantity).round(decimals) # Redondeo de acuerdo a la moneda
399
+
400
+
401
+
402
+ item = Facturama::Models::Item.new({
403
+ ProductCode: product['CodeProdServ'],
404
+ UnitCode: product['UnitCode'],
405
+ Unit: product['Unit'],
406
+ Description: product['Description'],
407
+ IdentificationNumber: product['IdentificationNumber'],
408
+ Quantity: quantity,
409
+ Discount: discount.round(decimals),
410
+ UnitPrice: product['Price'].round(decimals),
411
+ Subtotal: subtotal,
412
+ Taxes: nil
413
+
414
+ })
415
+
416
+
417
+ base_amount = (subtotal - discount).round(decimals)
418
+ taxes = product['Taxes'].map { |t|
419
+ Facturama::Models::Tax.new(
420
+ Name: t['Name'],
421
+ IsQuota: t['IsQuota'],
422
+ IsRetention: t['IsRetention'],
423
+ Rate: t['Rate'].to_f.round(decimals),
424
+ Base: base_amount,
425
+ Total: (base_amount * t['Rate'].to_f).round(decimals)
426
+ )
427
+ }
428
+
429
+ retentions_amount = 0
430
+ transfers_amount = 0
431
+ if taxes.length > 0
432
+ item.Taxes = taxes
433
+ # Calculo del monto total del concepto, tomando en cuenta los impuestos
434
+ retentions_amount = item.Taxes.select { |tax| tax.IsRetention }.sum(&:Total)
435
+ transfers_amount = item.Taxes.select { |tax| ! tax.IsRetention }.sum(&:Total)
436
+
437
+ end
438
+
439
+ item.Total = (item.Subtotal - item.Discount + transfers_amount - retentions_amount).round(decimals)
440
+
441
+ lst_items.push(item)
442
+
443
+ end
444
+
445
+ cfdi.Items = lst_items
446
+
447
+ end
448
+
449
+
450
+
451
+ end
452
+ end
453
+
454
+ end