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.
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