br_nfe 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +16 -0
  5. data/Gemfile.lock +27 -3
  6. data/LICENSE +1 -1
  7. data/README.markdown +10 -12
  8. data/Rakefile +13 -0
  9. data/br_nfe.gemspec +18 -21
  10. data/lib/br_nfe/active_model_base.rb +7 -1
  11. data/lib/br_nfe/base.rb +175 -37
  12. data/lib/br_nfe/endereco.rb +7 -1
  13. data/lib/br_nfe/helper/have_rps.rb +1 -1
  14. data/lib/br_nfe/helper/values_ts/service_v1.rb +313 -0
  15. data/lib/br_nfe/response/service/build_response.rb +286 -0
  16. data/lib/br_nfe/response/service/default.rb +185 -0
  17. data/lib/br_nfe/{servico/response → response/service}/nota_fiscal.rb +11 -10
  18. data/lib/br_nfe/response/service/paths/base.rb +93 -0
  19. data/lib/br_nfe/response/service/paths/v1/servico_cancelar_nfse_resposta.rb +22 -0
  20. data/lib/br_nfe/response/service/paths/v1/servico_consultar_lote_rps_resposta.rb +25 -0
  21. data/lib/br_nfe/response/service/paths/v1/servico_consultar_nfse_resposta.rb +25 -0
  22. data/lib/br_nfe/response/service/paths/v1/servico_consultar_nfse_rps_resposta.rb +25 -0
  23. data/lib/br_nfe/response/service/paths/v1/servico_consultar_situacao_lote_rps_resposta.rb +31 -0
  24. data/lib/br_nfe/response/service/paths/v1/servico_enviar_lote_rps_resposta.rb +36 -0
  25. data/lib/br_nfe/response/service/paths/v1/tc_nfse.rb +127 -0
  26. data/lib/br_nfe/service/base.rb +59 -0
  27. data/lib/br_nfe/service/betha/base.rb +8 -0
  28. data/lib/br_nfe/service/betha/v1/cancelamento_nfs.rb +39 -0
  29. data/lib/br_nfe/service/betha/v1/consulta_lote_rps.rb +34 -0
  30. data/lib/br_nfe/service/betha/v1/consulta_nfs_por_rps.rb +32 -0
  31. data/lib/br_nfe/service/betha/v1/consulta_nfse.rb +32 -0
  32. data/lib/br_nfe/service/betha/v1/consulta_situacao_lote_rps.rb +30 -0
  33. data/lib/br_nfe/service/betha/v1/gateway.rb +21 -0
  34. data/lib/br_nfe/service/betha/v1/recepcao_lote_rps.rb +37 -0
  35. data/lib/br_nfe/service/betha/v1/response_paths/servico_consultar_lote_rps_resposta.rb +19 -0
  36. data/lib/br_nfe/service/betha/v1/response_paths/servico_consultar_nfse_resposta.rb +17 -0
  37. data/lib/br_nfe/service/betha/v1/response_paths/servico_consultar_nfse_rps_resposta.rb +17 -0
  38. data/lib/br_nfe/service/concerns/rules/cancelamento_nfs.rb +20 -0
  39. data/lib/br_nfe/service/concerns/rules/consulta_nfs_por_rps.rb +18 -0
  40. data/lib/br_nfe/service/concerns/rules/consulta_nfse.rb +29 -0
  41. data/lib/br_nfe/service/concerns/rules/recepcao_lote_rps.rb +50 -0
  42. data/lib/br_nfe/{servico → service}/intermediario.rb +1 -1
  43. data/lib/br_nfe/service/item.rb +70 -0
  44. data/lib/br_nfe/service/rps.rb +231 -0
  45. data/lib/br_nfe/service/sc/florianopolis/base.rb +25 -0
  46. data/lib/br_nfe/service/sc/florianopolis/cancellation.rb +30 -0
  47. data/lib/br_nfe/service/sc/florianopolis/emission_rps.rb +19 -0
  48. data/lib/br_nfe/service/sc/florianopolis/xml/_address.xml.slim +21 -0
  49. data/lib/br_nfe/service/sc/florianopolis/xml/_contact.xml.slim +3 -0
  50. data/lib/br_nfe/service/sc/florianopolis/xml/_service_item.xml.slim +9 -0
  51. data/lib/br_nfe/service/sc/florianopolis/xml/cancellation.xml.slim +6 -0
  52. data/lib/br_nfe/service/sc/florianopolis/xml/inf_requisicao.xml.slim +55 -0
  53. data/lib/br_nfe/service/sc/gaspar/cancela_nfse.rb +13 -0
  54. data/lib/br_nfe/service/sc/gaspar/consulta_lote_rps.rb +13 -0
  55. data/lib/br_nfe/service/sc/gaspar/consulta_nfs_por_rps.rb +13 -0
  56. data/lib/br_nfe/service/sc/gaspar/consulta_nfse.rb +17 -0
  57. data/lib/br_nfe/service/sc/gaspar/consulta_situacao_lote_rps.rb +13 -0
  58. data/lib/br_nfe/service/sc/gaspar/recepcao_lote_rps.rb +13 -0
  59. data/lib/br_nfe/service/sc/gaspar/recepcao_lote_rps_limitado.rb +13 -0
  60. data/lib/br_nfe/service/thema/v1/base.rb +55 -0
  61. data/lib/br_nfe/service/thema/v1/cancela_nfse.rb +48 -0
  62. data/lib/br_nfe/service/thema/v1/consulta_lote_rps.rb +49 -0
  63. data/lib/br_nfe/service/thema/v1/consulta_nfs_por_rps.rb +48 -0
  64. data/lib/br_nfe/service/thema/v1/consulta_nfse.rb +47 -0
  65. data/lib/br_nfe/service/thema/v1/consulta_situacao_lote_rps.rb +46 -0
  66. data/lib/br_nfe/service/thema/v1/recepcao_lote_rps.rb +51 -0
  67. data/lib/br_nfe/service/thema/v1/recepcao_lote_rps_limitado.rb +30 -0
  68. data/lib/br_nfe/service/xml/v1/_tc_contato.xml.slim +7 -0
  69. data/lib/br_nfe/service/xml/v1/_tc_cpf_cnpj.xml.slim +5 -0
  70. data/lib/br_nfe/service/xml/v1/_tc_dados_construcao_civil.xml.slim +2 -0
  71. data/lib/br_nfe/service/xml/v1/_tc_dados_prestador.xml.slim +15 -0
  72. data/lib/br_nfe/service/xml/v1/_tc_dados_servico.xml.slim +14 -0
  73. data/lib/br_nfe/service/xml/v1/_tc_dados_tomador.xml.slim +15 -0
  74. data/lib/br_nfe/service/xml/v1/_tc_endereco.xml.slim +13 -0
  75. data/lib/br_nfe/service/xml/v1/_tc_identificacao_intermediario_servico.xml.slim +7 -0
  76. data/lib/br_nfe/service/xml/v1/_tc_identificacao_nfse.xml.slim +7 -0
  77. data/lib/br_nfe/service/xml/v1/_tc_identificacao_orgao_gerador.xml.slim +8 -0
  78. data/lib/br_nfe/service/xml/v1/_tc_identificacao_prestador.xml.slim +3 -0
  79. data/lib/br_nfe/service/xml/v1/_tc_identificacao_rps.xml.slim +16 -0
  80. data/lib/br_nfe/service/xml/v1/_tc_identificacao_tomador.xml.slim +4 -0
  81. data/lib/br_nfe/service/xml/v1/_tc_inf_pedido_cancelamento.xml.slim +4 -0
  82. data/lib/br_nfe/service/xml/v1/_tc_inf_rps.xml.slim +47 -0
  83. data/lib/br_nfe/service/xml/v1/_tc_lote_rps.xml.slim +9 -0
  84. data/lib/br_nfe/service/xml/v1/_tc_pedido_cancelamento.xml.slim +4 -0
  85. data/lib/br_nfe/service/xml/v1/_tc_rps.xml.slim +8 -0
  86. data/lib/br_nfe/service/xml/v1/_tc_valores.xml.slim +48 -0
  87. data/lib/br_nfe/service/xml/v1/servico_cancelar_nfse_envio.xml.slim +9 -0
  88. data/lib/br_nfe/service/xml/v1/servico_consultar_lote_rps_envio.xml.slim +4 -0
  89. data/lib/br_nfe/service/xml/v1/servico_consultar_nfse_envio.xml.slim +19 -0
  90. data/lib/br_nfe/service/xml/v1/servico_consultar_nfse_rps_envio.xml.slim +5 -0
  91. data/lib/br_nfe/service/xml/v1/servico_consultar_situacao_lote_rps_envio.xml.slim +4 -0
  92. data/lib/br_nfe/service/xml/v1/servico_enviar_lote_rps_envio.xml.slim +9 -0
  93. data/lib/br_nfe/version.rb +2 -2
  94. data/lib/br_nfe/xml/_signed_info_sh1.xml.slim +9 -0
  95. data/lib/br_nfe/xml/signature_sh1.xml.slim +12 -0
  96. data/lib/br_nfe/xml/soap_env.xml.slim +3 -0
  97. data/lib/br_nfe.rb +72 -20
  98. data/test/br_nfe/base_test.rb +257 -108
  99. data/test/br_nfe/helper/have_intermediario_test.rb +2 -2
  100. data/test/br_nfe/helper/have_rps_test.rb +4 -4
  101. data/test/br_nfe/response/service/build_response_test.rb +377 -0
  102. data/test/br_nfe/response/service/default_test.rb +218 -0
  103. data/test/br_nfe/{servico/response → response/service}/nota_fiscal_test.rb +2 -2
  104. data/test/br_nfe/response/service/paths/base_test.rb +199 -0
  105. data/test/br_nfe/response/service/paths/v1/servico_cancelar_nfse_resposta_test.rb +25 -0
  106. data/test/br_nfe/response/service/paths/v1/servico_consultar_lote_rps_resposta_test.rb +30 -0
  107. data/test/br_nfe/response/service/paths/v1/servico_consultar_nfse_resposta_test.rb +30 -0
  108. data/test/br_nfe/response/service/paths/v1/servico_consultar_nfse_rps_resposta_test.rb +30 -0
  109. data/test/br_nfe/response/service/paths/v1/servico_consultar_situacao_lote_rps_resposta_test.rb +30 -0
  110. data/test/br_nfe/response/service/paths/v1/servico_enviar_lote_rps_resposta_test.rb +34 -0
  111. data/test/br_nfe/response/service/paths/v1/tc_nfse_test.rb +122 -0
  112. data/test/br_nfe/service/base_test.rb +138 -0
  113. data/test/br_nfe/service/betha/base_test.rb +9 -0
  114. data/test/br_nfe/service/betha/v1/cancelamento_nfs_test.rb +60 -0
  115. data/test/br_nfe/service/betha/v1/consulta_lote_rps_test.rb +55 -0
  116. data/test/br_nfe/service/betha/v1/consulta_nfs_por_rps_test.rb +55 -0
  117. data/test/br_nfe/service/betha/v1/consulta_nfse_test.rb +53 -0
  118. data/test/br_nfe/service/betha/v1/consulta_situacao_lote_rps_test.rb +49 -0
  119. data/test/br_nfe/service/betha/v1/gateway_test.rb +35 -0
  120. data/test/br_nfe/service/betha/v1/recepcao_lote_rps_test.rb +84 -0
  121. data/test/br_nfe/service/betha/v1/response_paths/servico_consultar_lote_rps_resposta_test.rb +16 -0
  122. data/test/br_nfe/service/betha/v1/response_paths/servico_consultar_nfse_resposta_test.rb +16 -0
  123. data/test/br_nfe/service/betha/v1/response_paths/servico_consultar_nfse_rps_resposta_test.rb +16 -0
  124. data/test/br_nfe/service/betha/v1/xsd/TiposNFe_v01.xsd +583 -0
  125. data/test/br_nfe/service/betha/v1/xsd/nfse_v01.xsd +652 -0
  126. data/test/br_nfe/service/betha/v1/xsd/servico_cancelar_nfse_envio_v01.xsd +17 -0
  127. data/test/br_nfe/service/betha/v1/xsd/servico_consultar_lote_rps_envio_v01.xsd +16 -0
  128. data/test/br_nfe/service/betha/v1/xsd/servico_consultar_nfse_envio_v01.xsd +28 -0
  129. data/test/br_nfe/service/betha/v1/xsd/servico_consultar_nfse_rps_envio_v01.xsd +16 -0
  130. data/test/br_nfe/service/betha/v1/xsd/servico_consultar_situacao_lote_rps_envio_v01.xsd +16 -0
  131. data/test/br_nfe/service/betha/v1/xsd/servico_enviar_lote_rps_envio_v01.xsd +17 -0
  132. data/test/br_nfe/service/betha/v1/xsd/xmldsig-core-schema.xsd +308 -0
  133. data/test/br_nfe/service/betha/v1/xsd/xmldsig-core-schema_v01.xsd +95 -0
  134. data/test/br_nfe/service/concerns/rules/cancelamento_nfs_test.rb +15 -0
  135. data/test/br_nfe/service/concerns/rules/consulta_nfs_por_rps_test.rb +36 -0
  136. data/test/br_nfe/service/concerns/rules/consulta_nfse_test.rb +42 -0
  137. data/test/br_nfe/{servico/base_test.rb → service/concerns/rules/recepcao_lote_rps_test.rb} +12 -4
  138. data/test/br_nfe/{servico → service}/intermediario_test.rb +1 -1
  139. data/test/br_nfe/service/item_test.rb +34 -0
  140. data/test/br_nfe/{servico → service}/rps_test.rb +191 -43
  141. data/test/br_nfe/service/sc/florianopolis/XSD/TiposNFSe_v2.0.xsd +863 -0
  142. data/test/br_nfe/service/sc/florianopolis/XSD/xmldsig-core-schema.xsd +309 -0
  143. data/test/br_nfe/service/sc/florianopolis/base_test.rb +20 -0
  144. data/test/br_nfe/service/sc/florianopolis/cancellation_test.rb +36 -0
  145. data/test/br_nfe/service/sc/florianopolis/emission_rps_test.rb +145 -0
  146. data/test/br_nfe/service/sc/gaspar/cancela_nfse_test.rb +21 -0
  147. data/test/br_nfe/service/sc/gaspar/consulta_nfs_por_rps_test.rb +21 -0
  148. data/test/br_nfe/service/sc/gaspar/consulta_nfse_test.rb +21 -0
  149. data/test/br_nfe/service/sc/gaspar/consulta_situacao_lote_rps_test.rb +21 -0
  150. data/test/br_nfe/service/sc/gaspar/recepcao_lote_rps_limitado_test.rb +22 -0
  151. data/test/br_nfe/service/sc/gaspar/recepcao_lote_rps_test.rb +22 -0
  152. data/test/br_nfe/service/thema/v1/base_test.rb +65 -0
  153. data/test/br_nfe/service/thema/v1/cancela_nfse_test.rb +56 -0
  154. data/test/br_nfe/service/thema/v1/consulta_lote_rps_test.rb +47 -0
  155. data/test/br_nfe/service/thema/v1/consulta_nfs_por_rps_test.rb +50 -0
  156. data/test/br_nfe/service/thema/v1/consulta_nfse_test.rb +50 -0
  157. data/test/br_nfe/service/thema/v1/consulta_situacao_lote_rps_test.rb +47 -0
  158. data/test/br_nfe/service/thema/v1/recepcao_lote_rps_test.rb +62 -0
  159. data/test/br_nfe/service/thema/v1/recepcao_lote_rps_test_limitado.rb +50 -0
  160. data/test/br_nfe/service/thema/v1/xsd/nfse.xsd +656 -0
  161. data/test/br_nfe/service/thema/v1/xsd/xmldsig-core-schema20020212.xsd +318 -0
  162. data/test/br_nfe/service/xsd/v1/nfse.xsd +779 -0
  163. data/test/br_nfe/service/xsd/v1/xmldsig-core-schema20020212.xsd +316 -0
  164. data/test/cert.pfx +0 -0
  165. data/test/factories/base.rb +2 -0
  166. data/test/factories/destinatario.rb +3 -3
  167. data/test/factories/response/service/build_response.rb +5 -0
  168. data/test/factories/response/service/default.rb +10 -0
  169. data/test/factories/{servico/response → response/service}/nota_fiscal.rb +9 -9
  170. data/test/factories/service/base.rb +6 -0
  171. data/test/factories/service/betha/base.rb +4 -0
  172. data/test/factories/service/betha/v1/cancelamento_nfs.rb +9 -0
  173. data/test/factories/{servico → service}/betha/v1/consulta_lote_rps.rb +2 -2
  174. data/test/factories/{servico → service}/betha/v1/consulta_nfs_por_rps.rb +1 -1
  175. data/test/factories/service/betha/v1/consulta_nfse.rb +8 -0
  176. data/test/factories/{servico → service}/betha/v1/consulta_situacao_lote_rps.rb +2 -2
  177. data/test/factories/{servico → service}/betha/v1/gateway.rb +1 -1
  178. data/test/factories/service/betha/v1/recepcao_lote_rps.rb +8 -0
  179. data/test/factories/{servico → service}/intermediario.rb +2 -2
  180. data/test/factories/service/item.rb +12 -0
  181. data/test/factories/service/rps.rb +50 -0
  182. data/test/factories/service/sc/florianopolis/base.rb +5 -0
  183. data/test/factories/service/sc/florianopolis/cancellation.rb +7 -0
  184. data/test/factories/service/sc/florianopolis/emission_rps.rb +7 -0
  185. data/test/factories/service/sc/gaspar/cancela_nfse.rb +9 -0
  186. data/test/factories/service/sc/gaspar/consulta_lote_rps.rb +7 -0
  187. data/test/factories/service/sc/gaspar/consulta_nfs_por_rps.rb +6 -0
  188. data/test/factories/service/sc/gaspar/consulta_nfse.rb +8 -0
  189. data/test/factories/service/sc/gaspar/consulta_situacao_lote_rps.rb +6 -0
  190. data/test/factories/service/sc/gaspar/recepcao_lote_rps.rb +9 -0
  191. data/test/factories/service/sc/gaspar/recepcao_lote_rps_limitado.rb +9 -0
  192. data/test/factories/service/thema/v1/base.rb +7 -0
  193. data/test/factories/service/thema/v1/cancela_nfse.rb +9 -0
  194. data/test/factories/service/thema/v1/consulta_lote_rps.rb +7 -0
  195. data/test/factories/service/thema/v1/consulta_nfs_por_rps.rb +6 -0
  196. data/test/factories/service/thema/v1/consulta_nfse.rb +8 -0
  197. data/test/factories/service/thema/v1/consulta_situacao_lote_rps.rb +6 -0
  198. data/test/factories/service/thema/v1/recepcao_lote_rps.rb +9 -0
  199. data/test/factories/service/thema/v1/recepcao_lote_rps_limitado.rb +8 -0
  200. data/test/test_helper.rb +42 -0
  201. metadata +338 -121
  202. data/lib/br_nfe/servico/base.rb +0 -35
  203. data/lib/br_nfe/servico/betha/base.rb +0 -85
  204. data/lib/br_nfe/servico/betha/build_response.rb +0 -141
  205. data/lib/br_nfe/servico/betha/v1/build_response.rb +0 -121
  206. data/lib/br_nfe/servico/betha/v1/cancelamento_nfs.rb +0 -52
  207. data/lib/br_nfe/servico/betha/v1/consulta_lote_rps.rb +0 -33
  208. data/lib/br_nfe/servico/betha/v1/consulta_nfs_por_rps.rb +0 -37
  209. data/lib/br_nfe/servico/betha/v1/consulta_nfse.rb +0 -51
  210. data/lib/br_nfe/servico/betha/v1/consulta_situacao_lote_rps.rb +0 -18
  211. data/lib/br_nfe/servico/betha/v1/gateway.rb +0 -125
  212. data/lib/br_nfe/servico/betha/v1/recepcao_lote_rps.rb +0 -97
  213. data/lib/br_nfe/servico/betha/v2/build_response.rb +0 -159
  214. data/lib/br_nfe/servico/betha/v2/cancelamento_nfs.rb +0 -30
  215. data/lib/br_nfe/servico/betha/v2/consulta_lote_rps.rb +0 -30
  216. data/lib/br_nfe/servico/betha/v2/consulta_nfse_por_rps.rb +0 -27
  217. data/lib/br_nfe/servico/betha/v2/envio_lote_rps_sincrono.rb +0 -30
  218. data/lib/br_nfe/servico/betha/v2/gateway.rb +0 -230
  219. data/lib/br_nfe/servico/betha/v2/gera_nfse.rb +0 -30
  220. data/lib/br_nfe/servico/betha/v2/recepcao_lote_rps.rb +0 -52
  221. data/lib/br_nfe/servico/betha/v2/substituicao_nfse.rb +0 -43
  222. data/lib/br_nfe/servico/response/default.rb +0 -34
  223. data/lib/br_nfe/servico/rps.rb +0 -108
  224. data/test/br_nfe/servico/betha/base_test.rb +0 -135
  225. data/test/br_nfe/servico/betha/v1/build_response_test.rb +0 -557
  226. data/test/br_nfe/servico/betha/v1/cancelamento_nfs_test.rb +0 -72
  227. data/test/br_nfe/servico/betha/v1/consulta_lote_rps_test.rb +0 -46
  228. data/test/br_nfe/servico/betha/v1/consulta_nfs_por_rps_test.rb +0 -68
  229. data/test/br_nfe/servico/betha/v1/consulta_nfse_test.rb +0 -74
  230. data/test/br_nfe/servico/betha/v1/consulta_situacao_lote_rps_test.rb +0 -27
  231. data/test/br_nfe/servico/betha/v1/gateway_test.rb +0 -151
  232. data/test/br_nfe/servico/betha/v1/recepcao_lote_rps_test.rb +0 -249
  233. data/test/br_nfe/servico/betha/v2/cancelamento_nfs_test.rb +0 -44
  234. data/test/br_nfe/servico/betha/v2/consulta_lote_rps_test.rb +0 -38
  235. data/test/br_nfe/servico/betha/v2/consulta_nfse_por_rps_test.rb +0 -36
  236. data/test/br_nfe/servico/betha/v2/envio_lote_rps_sincrono_test.rb +0 -51
  237. data/test/br_nfe/servico/betha/v2/gateway_test.rb +0 -372
  238. data/test/br_nfe/servico/betha/v2/gera_nfse_test.rb +0 -62
  239. data/test/br_nfe/servico/betha/v2/recepcao_lote_rps_test.rb +0 -108
  240. data/test/br_nfe/servico/betha/v2/substituicao_nfse_test.rb +0 -84
  241. data/test/br_nfe/servico/response/default_test.rb +0 -54
  242. data/test/factories/servico/base.rb +0 -5
  243. data/test/factories/servico/betha/base.rb +0 -5
  244. data/test/factories/servico/betha/v1/build_response.rb +0 -6
  245. data/test/factories/servico/betha/v1/cancelamento_nfs.rb +0 -7
  246. data/test/factories/servico/betha/v1/consulta_nfse.rb +0 -8
  247. data/test/factories/servico/betha/v1/recepcao_lote_rps.rb +0 -6
  248. data/test/factories/servico/betha/v2/cancelamento_nfs.rb +0 -7
  249. data/test/factories/servico/betha/v2/consulta_lote_rps.rb +0 -6
  250. data/test/factories/servico/betha/v2/consulta_nfse_por_rps.rb +0 -6
  251. data/test/factories/servico/betha/v2/envio_lote_rps_sincrono.rb +0 -5
  252. data/test/factories/servico/betha/v2/gateway.rb +0 -5
  253. data/test/factories/servico/betha/v2/gera_nfse.rb +0 -6
  254. data/test/factories/servico/betha/v2/recepcao_lote_rps.rb +0 -5
  255. data/test/factories/servico/betha/v2/substituicao_nfse.rb +0 -8
  256. data/test/factories/servico/response/default.rb +0 -10
  257. data/test/factories/servico/rps.rb +0 -44
@@ -13,7 +13,7 @@ module BrNfe
13
13
  attr_accessor :complemento
14
14
  attr_accessor :bairro
15
15
  attr_accessor :nome_municipio
16
- attr_accessor :codigo_municipio
16
+ attr_accessor :codigo_municipio # IBGE
17
17
  attr_accessor :uf
18
18
  attr_accessor :cep
19
19
  attr_accessor :codigo_pais # defaul: 1058 (Brasil)
@@ -21,6 +21,12 @@ module BrNfe
21
21
 
22
22
  validates :logradouro, :numero, :bairro, :codigo_municipio, :uf, :cep, presence: true
23
23
 
24
+ def is_present?
25
+ logradouro.present? || numero.present? || complemento.present? ||
26
+ bairro.present? || nome_municipio.present? || codigo_municipio.present? ||
27
+ cep.present?
28
+ end
29
+
24
30
  def logradouro
25
31
  "#{@logradouro}".to_valid_format_nf
26
32
  end
@@ -16,7 +16,7 @@ module BrNfe
16
16
 
17
17
  protected
18
18
 
19
- def validar_rps
19
+ def validate_rps
20
20
  if rps.invalid?
21
21
  rps.errors.full_messages.map{|msg| errors.add(:rps, msg) }
22
22
  end
@@ -0,0 +1,313 @@
1
+ module BrNfe
2
+ module Helper
3
+ module ValuesTs
4
+ module ServiceV1
5
+
6
+ # Número da Nota Fiscal de Serviço Eletrônica,
7
+ # formado pelo ano com 04 (quatro) dígitos e um
8
+ # número seqüencial com 11 posições – Formato
9
+ # AAAANNNNNNNNNNN.
10
+ #
11
+ def ts_numero_nfse value
12
+ BrNfe::Helper.only_number(value).max_size(15)
13
+ end
14
+
15
+ # Código de verificação do número da nota
16
+ #
17
+ def ts_codigo_verificacao value
18
+ "#{value}".max_size(9)
19
+ end
20
+
21
+ # Código de status do RPS
22
+ # 1 – Normal
23
+ # 2 – Cancelado
24
+ #
25
+ def ts_status_rps value
26
+ BrNfe::Helper.only_number(value).max_size(1)
27
+ end
28
+
29
+ # Código de status do NFS-e
30
+ # 1 – Normal
31
+ # 2 – Cancelado
32
+ #
33
+ def ts_status_nfse value
34
+ BrNfe::Helper.only_number(value).max_size(1)
35
+ end
36
+
37
+ # Código de natureza da operação
38
+ # 1 – Tributação no município
39
+ # 2 - Tributação fora do município
40
+ # 3 - Isenção
41
+ # 4 - Imune
42
+ # 5 –Exigibilidade suspensa por decisão judicial
43
+ # 6 – Exigibilidade suspensa por procedimento administrativo
44
+ #
45
+ def ts_natureza_operacao value
46
+ BrNfe::Helper.only_number(value).max_size(2)
47
+ end
48
+
49
+ # Código de identificação do regime especial de tributação
50
+ # 1 – Microempresa municipal
51
+ # 2 - Estimativa
52
+ # 3 – Sociedade de profissionais
53
+ # 4 – Cooperativa
54
+ #
55
+ def ts_regime_especial_tributacao value
56
+ BrNfe::Helper.only_number(value).max_size(2)
57
+ end
58
+
59
+ # Identificação de Sim/Não
60
+ # 1 - Sim
61
+ # 2 - Não
62
+ #
63
+ def ts_sim_nao value
64
+ value_true_false(value)
65
+ end
66
+
67
+ # Quantidade de RPS do Lote
68
+ #
69
+ def ts_quantidade_rps value
70
+ BrNfe::Helper.only_number(value).max_size(4)
71
+ end
72
+
73
+ # Número do RPS
74
+ #
75
+ def ts_numero_rps value
76
+ BrNfe::Helper.only_number(value).max_size(15)
77
+ end
78
+
79
+ # Número de série do RPS
80
+ #
81
+ def ts_serie_rps value
82
+ "#{value}".max_size(5)
83
+ end
84
+
85
+ # Código de tipo de RPS
86
+ # 1 - RPS
87
+ # 2 – Nota Fiscal Conjugada (Mista)
88
+ # 3 – Cupom
89
+ #
90
+ def ts_tipo_rps value
91
+ BrNfe::Helper.only_number(value).max_size(1)
92
+ end
93
+
94
+ # Informações adicionais ao documento.
95
+ #
96
+ def ts_outras_informacoes value
97
+ "#{value}".max_size(255)
98
+ end
99
+
100
+ # Valor monetário.
101
+ # Formato: 0.00 (ponto separando casa decimal)
102
+ # Ex: 1.234,56 = 1234.56
103
+ # 1.000,00 = 1000.00
104
+ # 1.000,00 = 1000
105
+ #
106
+ def ts_valor value
107
+ "#{value_monetary(value, 2)}".max_size(17)
108
+ end
109
+
110
+ # Código de item da lista de serviço
111
+ #
112
+ def ts_item_lista_servico value
113
+ BrNfe::Helper.only_number(value).max_size(5).rjust(4, '0')
114
+ end
115
+
116
+ # Código CNAE
117
+ #
118
+ def ts_codigo_cnae value
119
+ BrNfe::Helper.only_number(value).max_size(7)
120
+ end
121
+
122
+ # Código de Tributação
123
+ #
124
+ def ts_codigo_tributacao value
125
+ "#{value}".max_size(20)
126
+ end
127
+
128
+ # Alíquota. Valor percentual.
129
+ # Formato: 0.0000
130
+ # Ex: 1% = 0.01
131
+ # 25,5% = 0.255
132
+ # 100% = 1.0000 ou 1
133
+ #
134
+ def ts_aliquota value
135
+ "#{value_monetary(value, 4)}".max_size(9)
136
+ end
137
+
138
+ # Discriminação do conteúdo da NFS-e
139
+ #
140
+ def ts_discriminacao value
141
+ "#{value}".max_size(2_000).remove_accents
142
+ end
143
+
144
+ # Código de identificação do município conforme tabela do IBGE
145
+ #
146
+ def ts_codigo_municipio_ibge value
147
+ BrNfe::Helper.only_number(value).max_size(7)
148
+ end
149
+
150
+ # Número de inscrição municipal
151
+ #
152
+ def ts_inscricao_municipal value
153
+ "#{value}".max_size(15)
154
+ end
155
+
156
+ # Razão Social do contribuinte
157
+ #
158
+ def ts_razao_social value
159
+ "#{value}".max_size(115)
160
+ end
161
+
162
+ # Nome fantasia
163
+ #
164
+ def ts_nome_fantasia value
165
+ "#{value}".max_size(60)
166
+ end
167
+
168
+ # Número CNPJ
169
+ #
170
+ def ts_cnpj value
171
+ "#{BrNfe::Helper::CpfCnpj.new(value).sem_formatacao}".max_size(14)
172
+ end
173
+
174
+ # Endereço / rua
175
+ #
176
+ def ts_endereco value
177
+ "#{value}".max_size(125)
178
+ end
179
+
180
+ # Número do endereço
181
+ #
182
+ def ts_numero_endereco value
183
+ "#{value}".max_size(10)
184
+ end
185
+
186
+ # Complemento de endereço
187
+ #
188
+ def ts_complemento_endereco value
189
+ "#{value}".max_size(60)
190
+ end
191
+
192
+ # Bairro
193
+ #
194
+ def ts_bairro value
195
+ "#{value}".max_size(60)
196
+ end
197
+
198
+ # Sigla da unidade federativa
199
+ #
200
+ def ts_uf value
201
+ "#{value}".max_size(2)
202
+ end
203
+
204
+ # Número do CEP
205
+ #
206
+ def ts_cep value
207
+ BrNfe::Helper.only_number(value).max_size(8)
208
+ end
209
+
210
+ # E-mail
211
+ #
212
+ def ts_email value
213
+ "#{value}".max_size(80)
214
+ end
215
+
216
+ # Telefone
217
+ #
218
+ def ts_telefone value
219
+ "#{value}".max_size(11)
220
+ end
221
+
222
+ # Número CPF
223
+ #
224
+ def ts_cpf value
225
+ "#{BrNfe::Helper::CpfCnpj.new(value).sem_formatacao}".max_size(11)
226
+ end
227
+
228
+ # Indicador de uso de CPF ou CNPJ
229
+ # 1 – CPF
230
+ # 2 – CNPJ
231
+ # 3 – Não Informado
232
+ #
233
+ def ts_indicacao_cpf_cnpj
234
+ BrNfe::Helper.only_number(value).max_size(1)
235
+ end
236
+
237
+ # Código de Obra
238
+ #
239
+ def ts_codigo_obra value
240
+ "#{value}".max_size(15)
241
+ end
242
+
243
+ # Código ART
244
+ #
245
+ def ts_art value
246
+ "#{value}".max_size(15)
247
+ end
248
+
249
+ # Número do Lote de RPS
250
+ #
251
+ def ts_numero_lote value
252
+ BrNfe::Helper.only_number(value).max_size(15)
253
+ end
254
+
255
+ # Número do protocolo de recebimento do RPS
256
+ #
257
+ def ts_numero_protocolo value
258
+ "#{value}".max_size(50)
259
+ end
260
+
261
+ # Código de situação de lote de RPS
262
+ # 1 – Não Recebido
263
+ # 2 – Não Processado
264
+ # 3 – Processado com Erro
265
+ # 4 – Processado com Sucesso
266
+ #
267
+ def ts_situacao_lote_rps value
268
+ BrNfe::Helper.only_number(value).max_size(1)
269
+ end
270
+
271
+ # Código de mensagem de retorno de serviço.
272
+ #
273
+ def ts_codigo_mensagem_alerta value
274
+ "#{value}".max_size(4)
275
+ end
276
+
277
+ # Descrição da mensagem de retorno de serviço.
278
+ #
279
+ def ts_descricao_mensagem_alerta value
280
+ "#{value}".max_size(200)
281
+ end
282
+
283
+ # Código de cancelamento com base na tabela de Erros e alertas.
284
+ #
285
+ def ts_codigo_cancelamento_nfse value
286
+ "#{value}".max_size(4)
287
+ end
288
+
289
+ # Atributo de identificação da tag a ser assinada no documento XML
290
+ #
291
+ def ts_id_tag value
292
+ "#{value}".max_size(255)
293
+ end
294
+
295
+ # Atributo do formato Datetime
296
+ # Não está identificado na documentação porém é utilizado
297
+ # para identificar valores Datetime
298
+ #
299
+ def ts_datetime value
300
+ value_date_time(value)
301
+ end
302
+
303
+ # Atributo do formato Date
304
+ # Não está identificado na documentação porém é utilizado
305
+ # para identificar valores Date
306
+ #
307
+ def ts_date value
308
+ value_date(value)
309
+ end
310
+ end
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,286 @@
1
+ #encoding UTF-8
2
+ module BrNfe
3
+ module Response
4
+ module Service
5
+ class BuildResponse < BrNfe::ActiveModelBase
6
+ # 1: A resposta da requisição soap
7
+ attr_accessor :savon_response
8
+
9
+ # 2: O module que será incluido contendo os métodos com os
10
+ # caminhos das chaves para encontrar cada valor
11
+ attr_accessor :module_methods
12
+
13
+ # 3: Um array com o caminho inicial padrão da requisição de retorno
14
+ attr_accessor :keys_root_path
15
+
16
+ # 4: Caminho para encontrar o XML da NF-e
17
+ attr_accessor :nfe_xml_path
18
+
19
+ # 5: Alguns Webservices trazem dentro do body da resposta SOAp
20
+ # outro XML com as informações necessárias.
21
+ # Quando isso aocntece é preciso converter esse XML para um HASH
22
+ # para que possamos encontrar os valores necessários.
23
+ attr_accessor :body_xml_path
24
+
25
+ def initialize(attributes = {})
26
+ super(attributes)
27
+ include_module!
28
+ end
29
+
30
+ # Método utilizado para incluir módules dinâmicos
31
+ #
32
+ def include_module!
33
+ self.class.send(:include, module_methods) if module_methods
34
+ end
35
+
36
+ def response
37
+ @response ||= BrNfe::Response::Service::Default.new({
38
+ error_messages: get_message_for_path(message_errors_path),
39
+ notas_fiscais: get_invoices,
40
+ protocolo: get_protocol,
41
+ data_recebimento: get_received_date,
42
+ numero_lote: get_lot_number,
43
+ situation: get_situation,
44
+ original_xml: savon_response.xml.force_encoding('UTF-8'),
45
+ cancelation_date_time: get_cancelation_date_time
46
+ })
47
+ end
48
+
49
+ # Retorna o valor encontrado no body da resposta Savon
50
+ # em formato de hash
51
+ #
52
+ # <b>Tipo de retorno: </b> _Hash_
53
+ #
54
+ def savon_body
55
+ return @savon_body if @savon_body.present?
56
+ if body_xml_path.present?
57
+ @savon_body = Nori.new.parse(
58
+ find_value_for_keys(savon_response.try(:body), body_xml_path)
59
+ ).deep_transform_keys!{|k| k.to_s.underscore.to_sym}
60
+ else
61
+ @savon_body = savon_response.try(:body) || {}
62
+ end
63
+ end
64
+
65
+ # Método utilizado para encontrar valores em um Hash
66
+ # passando o caminho do valor em um array onde contém as chaves
67
+ # ordenadas.
68
+ # Recebe 2 parêmntros:
69
+ # 1º um o hash onde contém o valor a ser encontrado
70
+ # 2º um array com as chaves em sequencia formando o caminho para encontrar o valor.
71
+ #
72
+ # A funcionalidade desse método funciona parecido com o `.dig` da classe Hash do
73
+ # Ruby 2.3.0.
74
+ # A diferença é que no caso de exmeplo a seguir não apresenta uma excessão par ao usuário
75
+ # hash = {v1: {v2: 'valor string'}}
76
+ # hash.dig(:v1, :v2, :v3) <- Dá erro
77
+ # find_value_for_keys(hash, [:v1, :v2, :v3] <- Retorna nil e não da erro
78
+ #
79
+ # <b>Tipo de retorno: </b> _Anything_
80
+ #
81
+ def find_value_for_keys(hash, keys)
82
+ return if keys.blank?
83
+ keys = [keys] unless keys.is_a?(Array)
84
+
85
+ result = hash
86
+ keys.each do |key|
87
+ if result.is_a?(Hash)
88
+ result = result[key]
89
+ else
90
+ result = nil
91
+ break
92
+ end
93
+ end
94
+ result
95
+ end
96
+
97
+ # Quando para encontrar o valor de uma determinada chave
98
+ # é necessaŕio percorer o hash de retorno dês do inicio do mesmo.
99
+ # Como a mensagem tem uma chave 'root' padrão e pode ser diferente
100
+ # para cada orgaao emissor, é setado uma valor na variavel keys_root_path
101
+ # para que não seja necessário ficar setando a mesma chave em todos os
102
+ # métodos utilizados para encontrar determinado valor
103
+ #
104
+ # <b>Tipo de retorno: </b> _Array_
105
+ #
106
+ def path_with_root(path)
107
+ return if path.blank?
108
+ keys_root_path + [path].flatten
109
+ end
110
+
111
+ # Método que retorna as mensagens de retorno da requisição
112
+ # Quando procurar a mensagem a mesma pode retornar em 3 formatos:
113
+ # Hash: Onde encontrou apenas 1 mensagem com Codigo, Mensagem e Solução
114
+ # Array: Onde encontrou mais de uma mensagem com Codigo, Mensagem e Solução
115
+ # String: Onde encontrou uma unica mensagem de texto
116
+ #
117
+ # <b>Tipo de retorno: </b> _Array_
118
+ #
119
+ def get_message_for_path(msg_path)
120
+ messages = []
121
+ _messages = find_value_for_keys(savon_body, path_with_root(msg_path) )
122
+ if _messages.is_a?(Hash)
123
+ messages << get_message_for_hash(_messages)
124
+ elsif _messages.is_a?(Array)
125
+ _messages.map{|msg| messages << get_message_for_hash(msg) }
126
+ elsif _messages.present?
127
+ messages << _messages
128
+ end
129
+ messages
130
+ end
131
+
132
+ # Método utilizado para quando encontrar uam mensagem que seja um HAsh,
133
+ # onde nesse caso a mensagem terá um codigo de erro, uma mensagem, e uma
134
+ # mensagem de solução
135
+ #
136
+ # <b>Tipo de retorno: </b> _hash_
137
+ #
138
+ def get_message_for_hash(msg_hash)
139
+ {
140
+ code: find_value_for_keys(msg_hash, message_code_key),
141
+ message: find_value_for_keys(msg_hash, message_msg_key),
142
+ solution: find_value_for_keys(msg_hash, message_solution_key)
143
+ }
144
+ end
145
+
146
+ # Método que retorna as notas fiscais emitidas.
147
+ # Como pode ser que retorne mais de uma NF, a busca pela NF
148
+ # pode retornar um Array ou um Hash.
149
+ # Se retornar um array é porque existe mais de uma NFE, então é necessario
150
+ # percorer com um loop e instanciar cada nota com seus valores.
151
+ # Se retornar um Hash é porque tem apenas uma NFe, e nesse caso
152
+ # irá instanciar apenas a nfe encontrada.
153
+ #
154
+ # <b>Tipo de retorno: </b> _Array_
155
+ #
156
+ def get_invoices
157
+ invoices = []
158
+ _inoices = find_value_for_keys(savon_body, path_with_root(invoices_path))
159
+ if _inoices.is_a?(Hash)
160
+ invoices << instance_invoice(_inoices)
161
+ elsif _inoices.is_a?(Array)
162
+ _inoices.map{|inv| invoices << instance_invoice(inv) }
163
+ end
164
+ invoices
165
+ end
166
+
167
+ # Método utilizado para pegar protocolo de solicitação de
168
+ # processamento do RPS.
169
+ # Esse protocolo é utilizado posteriormente para consultar se
170
+ # o RPS já foi processado
171
+ #
172
+ # <b>Tipo de retorno: </b> _String_
173
+ #
174
+ def get_protocol
175
+ find_value_for_keys(savon_body, path_with_root(protocol_path))
176
+ end
177
+
178
+ # Método utilizado para pegar a situação do RPS
179
+ #
180
+ # <b>Tipo de retorno: </b> _Symbol_
181
+ #
182
+ def get_situation
183
+ situation_value = find_value_for_keys(savon_body, path_with_root(situation_path))
184
+ situation_value = situation_key_values[situation_value.to_s.strip] if situation_value.present?
185
+ situation_value
186
+ end
187
+
188
+ # Método utilizado para pegar a data de recebimento do lote
189
+ #
190
+ # <b>Tipo de retorno: </b> _String_
191
+ #
192
+ def get_received_date
193
+ find_value_for_keys(savon_body, path_with_root(received_date_path))
194
+ end
195
+
196
+ # Método utilizado para pegar o número do lote RPS
197
+ #
198
+ # <b>Tipo de retorno: </b> _String_
199
+ #
200
+ def get_lot_number
201
+ find_value_for_keys(savon_body, path_with_root(lot_number_path))
202
+ end
203
+
204
+ # Método utilizado para pegar o XML da NF
205
+ # É necessário canonicalizar o document para que seja colocado os
206
+ # namespaces nas tags corretas. Caso contrário o XML não irá abrir.
207
+ #
208
+ # <b>Tipo de retorno: </b> _String_
209
+ #
210
+ def get_xml_nf
211
+ canonicalize(Nokogiri::XML.parse(canonicalize(savon_response.doc.to_s), nil, 'UTF-8').xpath(nfe_xml_path).to_xml)
212
+ rescue
213
+ savon_response.xml
214
+ end
215
+
216
+ # Método utilizado para pegar o valor da data e hora de cancelmaento
217
+ # Só é utilizado para cancelar a NF-e
218
+ #
219
+ # <b>Tipo de retorno: </b> _DateTime_ OU _Nil_ OU _String_
220
+ #
221
+ def get_cancelation_date_time
222
+ find_value_for_keys(savon_body, path_with_root(cancelation_date_time_path)) if cancelation_date_time_path.present?
223
+ end
224
+
225
+ # Método responsável por instanciar a nota fiscal de acordo com o hash
226
+ # passado por parêmetro
227
+ # O parâmetro recebido deve ser o Hash representado pelo tipo de dados tcCompNfse(do manual NFS-e v1)
228
+ #
229
+ def instance_invoice(invoice_hash)
230
+ BrNfe::Response::Service::NotaFiscal.new({
231
+ xml_nf: get_xml_nf.force_encoding('UTF-8'),
232
+ numero_nf: find_value_for_keys(invoice_hash, invoice_numero_nf_path ),
233
+ codigo_verificacao: find_value_for_keys(invoice_hash, invoice_codigo_verificacao_path ),
234
+ data_emissao: find_value_for_keys(invoice_hash, invoice_data_emissao_path ),
235
+ url_nf: find_value_for_keys(invoice_hash, invoice_url_nf_path ),
236
+ rps_numero: find_value_for_keys(invoice_hash, invoice_rps_numero_path ),
237
+ rps_serie: find_value_for_keys(invoice_hash, invoice_rps_serie_path ),
238
+ rps_tipo: find_value_for_keys(invoice_hash, invoice_rps_tipo_path ),
239
+ rps_situacao: find_value_for_keys(invoice_hash, invoice_rps_situacao_path ),
240
+ rps_substituido_numero: find_value_for_keys(invoice_hash, invoice_rps_substituido_numero_path ),
241
+ rps_substituido_serie: find_value_for_keys(invoice_hash, invoice_rps_substituido_serie_path ),
242
+ rps_substituido_tipo: find_value_for_keys(invoice_hash, invoice_rps_substituido_tipo_path ),
243
+ data_emissao_rps: find_value_for_keys(invoice_hash, invoice_data_emissao_rps_path ),
244
+ competencia: find_value_for_keys(invoice_hash, invoice_competencia_path ),
245
+ outras_informacoes: find_value_for_keys(invoice_hash, invoice_outras_informacoes_path ),
246
+ item_lista_servico: find_value_for_keys(invoice_hash, invoice_item_lista_servico_path ),
247
+ cnae_code: find_value_for_keys(invoice_hash, invoice_cnae_code_path ),
248
+ description: find_value_for_keys(invoice_hash, invoice_description_path ),
249
+ codigo_municipio: find_value_for_keys(invoice_hash, invoice_codigo_municipio_path ),
250
+ total_services: find_value_for_keys(invoice_hash, invoice_total_services_path ),
251
+ deductions: find_value_for_keys(invoice_hash, invoice_deductions_path ),
252
+ valor_pis: find_value_for_keys(invoice_hash, invoice_valor_pis_path ),
253
+ valor_cofins: find_value_for_keys(invoice_hash, invoice_valor_cofins_path ),
254
+ valor_inss: find_value_for_keys(invoice_hash, invoice_valor_inss_path ),
255
+ valor_ir: find_value_for_keys(invoice_hash, invoice_valor_ir_path ),
256
+ valor_csll: find_value_for_keys(invoice_hash, invoice_valor_csll_path ),
257
+ iss_retained: find_value_for_keys(invoice_hash, invoice_iss_retained_path ),
258
+ outras_retencoes: find_value_for_keys(invoice_hash, invoice_outras_retencoes_path ),
259
+ total_iss: find_value_for_keys(invoice_hash, invoice_total_iss_path ),
260
+ base_calculation: find_value_for_keys(invoice_hash, invoice_base_calculation_path ),
261
+ iss_tax_rate: find_value_for_keys(invoice_hash, invoice_iss_tax_rate_path ),
262
+ valor_liquido: find_value_for_keys(invoice_hash, invoice_valor_liquido_path ),
263
+ desconto_condicionado: find_value_for_keys(invoice_hash, invoice_desconto_condicionado_path ),
264
+ desconto_incondicionado: find_value_for_keys(invoice_hash, invoice_desconto_incondicionado_path ),
265
+ responsavel_retencao: find_value_for_keys(invoice_hash, invoice_responsavel_retencao_path ),
266
+ numero_processo: find_value_for_keys(invoice_hash, invoice_numero_processo_path ),
267
+ municipio_incidencia: find_value_for_keys(invoice_hash, invoice_municipio_incidencia_path ),
268
+ orgao_gerador_municipio: find_value_for_keys(invoice_hash, invoice_orgao_gerador_municipio_path ),
269
+ orgao_gerador_uf: find_value_for_keys(invoice_hash, invoice_orgao_gerador_uf_path ),
270
+ cancelamento_codigo: find_value_for_keys(invoice_hash, invoice_cancelamento_codigo_path ),
271
+ cancelamento_numero_nf: find_value_for_keys(invoice_hash, invoice_cancelamento_numero_nf_path ),
272
+ cancelamento_cnpj: find_value_for_keys(invoice_hash, invoice_cancelamento_cnpj_path ),
273
+ cancelamento_inscricao_municipal: find_value_for_keys(invoice_hash, invoice_cancelamento_inscricao_municipal_path),
274
+ cancelamento_municipio: find_value_for_keys(invoice_hash, invoice_cancelamento_municipio_path ),
275
+ cancelamento_sucesso: find_value_for_keys(invoice_hash, invoice_cancelamento_sucesso_path ),
276
+ cancelamento_data_hora: find_value_for_keys(invoice_hash, invoice_cancelamento_data_hora_path ),
277
+ nfe_substituidora: find_value_for_keys(invoice_hash, invoice_nfe_substituidora_path ),
278
+ codigo_obra: find_value_for_keys(invoice_hash, invoice_codigo_obra_path ),
279
+ codigo_art: find_value_for_keys(invoice_hash, invoice_codigo_art_path )
280
+ })
281
+ end
282
+
283
+ end
284
+ end
285
+ end
286
+ end