focus_nfe 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.git-hooks/pre_push/steep.rb +18 -0
- data/.git-hooks/pre_push/yard_doc.rb +18 -0
- data/.gitattributes +1 -0
- data/.overcommit.yml +69 -0
- data/.rspec +3 -0
- data/.yardopts +11 -0
- data/CHANGELOG.md +77 -0
- data/CLAUDE.md +118 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +348 -0
- data/Rakefile +105 -0
- data/data/schemas/schema_cte.json +2793 -0
- data/data/schemas/schema_cte_os.json +1335 -0
- data/data/schemas/schema_cte_os_transporte_rodoviario.json +109 -0
- data/data/schemas/schema_cte_transporte_aereo.json +115 -0
- data/data/schemas/schema_cte_transporte_aquaviario.json +174 -0
- data/data/schemas/schema_cte_transporte_dutoviario.json +65 -0
- data/data/schemas/schema_cte_transporte_ferroviario.json +144 -0
- data/data/schemas/schema_cte_transporte_multimodal.json +45 -0
- data/data/schemas/schema_cte_transporte_rodoviario.json +78 -0
- data/data/schemas/schema_dce.json +549 -0
- data/data/schemas/schema_mdfe.json +1102 -0
- data/data/schemas/schema_mdfe_transporte_aereo.json +44 -0
- data/data/schemas/schema_mdfe_transporte_aquaviario.json +209 -0
- data/data/schemas/schema_mdfe_transporte_ferroviario.json +99 -0
- data/data/schemas/schema_mdfe_transporte_rodoviario.json +628 -0
- data/data/schemas/schema_nfcom.json +1859 -0
- data/data/schemas/schema_nfe.json +4750 -0
- data/data/schemas/schema_nfe_forma_pagamento.json +97 -0
- data/data/schemas/schema_nfe_item.json +2574 -0
- data/data/schemas/schema_nfgas.json +2316 -0
- data/data/schemas/schema_nfse_nacional.json +1847 -0
- data/data/schemas/schema_nfse_recebida.json +548 -0
- data/lib/focus_nfe/client.rb +162 -0
- data/lib/focus_nfe/configuration.rb +104 -0
- data/lib/focus_nfe/errors.rb +123 -0
- data/lib/focus_nfe/esquemas/campo.rb +171 -0
- data/lib/focus_nfe/esquemas/catalogo.rb +34 -0
- data/lib/focus_nfe/esquemas/decimal.rb +66 -0
- data/lib/focus_nfe/esquemas/esquema.rb +72 -0
- data/lib/focus_nfe/esquemas/validador.rb +87 -0
- data/lib/focus_nfe/http/adapter.rb +25 -0
- data/lib/focus_nfe/http/adapters/net_http.rb +99 -0
- data/lib/focus_nfe/http/authentication.rb +23 -0
- data/lib/focus_nfe/http/connection.rb +118 -0
- data/lib/focus_nfe/http/logging.rb +100 -0
- data/lib/focus_nfe/http/response.rb +75 -0
- data/lib/focus_nfe/modelos/documento.rb +113 -0
- data/lib/focus_nfe/modelos/inutilizacao.rb +75 -0
- data/lib/focus_nfe/modelos/pagina.rb +54 -0
- data/lib/focus_nfe/recursos/backups.rb +17 -0
- data/lib/focus_nfe/recursos/base.rb +91 -0
- data/lib/focus_nfe/recursos/ceps.rb +16 -0
- data/lib/focus_nfe/recursos/cfops.rb +16 -0
- data/lib/focus_nfe/recursos/cnaes.rb +16 -0
- data/lib/focus_nfe/recursos/cnpjs.rb +13 -0
- data/lib/focus_nfe/recursos/concerns/baixavel.rb +41 -0
- data/lib/focus_nfe/recursos/concerns/baixavel_eventos.rb +34 -0
- data/lib/focus_nfe/recursos/concerns/cancelavel.rb +25 -0
- data/lib/focus_nfe/recursos/concerns/conciliavel.rb +66 -0
- data/lib/focus_nfe/recursos/concerns/consultavel.rb +26 -0
- data/lib/focus_nfe/recursos/concerns/corrigivel.rb +45 -0
- data/lib/focus_nfe/recursos/concerns/corrigivel_cte.rb +60 -0
- data/lib/focus_nfe/recursos/concerns/emitivel.rb +51 -0
- data/lib/focus_nfe/recursos/concerns/enviavel.rb +40 -0
- data/lib/focus_nfe/recursos/concerns/eventavel.rb +46 -0
- data/lib/focus_nfe/recursos/concerns/inutilizavel.rb +96 -0
- data/lib/focus_nfe/recursos/concerns/listavel.rb +22 -0
- data/lib/focus_nfe/recursos/concerns/localizavel.rb +22 -0
- data/lib/focus_nfe/recursos/concerns/notificavel.rb +23 -0
- data/lib/focus_nfe/recursos/concerns/removivel.rb +20 -0
- data/lib/focus_nfe/recursos/concerns/visualizavel.rb +28 -0
- data/lib/focus_nfe/recursos/cte.rb +35 -0
- data/lib/focus_nfe/recursos/cte_os.rb +29 -0
- data/lib/focus_nfe/recursos/ctes_recebidas.rb +38 -0
- data/lib/focus_nfe/recursos/dce.rb +16 -0
- data/lib/focus_nfe/recursos/emails_bloqueados.rb +31 -0
- data/lib/focus_nfe/recursos/empresas.rb +35 -0
- data/lib/focus_nfe/recursos/mdfe.rb +78 -0
- data/lib/focus_nfe/recursos/municipios.rb +60 -0
- data/lib/focus_nfe/recursos/ncms.rb +16 -0
- data/lib/focus_nfe/recursos/nfce.rb +19 -0
- data/lib/focus_nfe/recursos/nfcom.rb +16 -0
- data/lib/focus_nfe/recursos/nfe.rb +106 -0
- data/lib/focus_nfe/recursos/nfes_recebidas.rb +56 -0
- data/lib/focus_nfe/recursos/nfgas.rb +16 -0
- data/lib/focus_nfe/recursos/nfse.rb +18 -0
- data/lib/focus_nfe/recursos/nfse_nacional.rb +16 -0
- data/lib/focus_nfe/recursos/nfses_nacionais_recebidas.rb +21 -0
- data/lib/focus_nfe/recursos/webhooks.rb +22 -0
- data/lib/focus_nfe/version.rb +6 -0
- data/lib/focus_nfe/webhook.rb +68 -0
- data/lib/focus_nfe.rb +124 -0
- data/sig/focus_nfe/client.rbs +38 -0
- data/sig/focus_nfe/configuration.rbs +29 -0
- data/sig/focus_nfe/errors.rbs +59 -0
- data/sig/focus_nfe/esquemas/campo.rbs +47 -0
- data/sig/focus_nfe/esquemas/catalogo.rbs +8 -0
- data/sig/focus_nfe/esquemas/decimal.rbs +25 -0
- data/sig/focus_nfe/esquemas/esquema.rbs +30 -0
- data/sig/focus_nfe/esquemas/validador.rbs +20 -0
- data/sig/focus_nfe/http/adapter.rbs +7 -0
- data/sig/focus_nfe/http/adapters/net_http.rbs +25 -0
- data/sig/focus_nfe/http/authentication.rbs +9 -0
- data/sig/focus_nfe/http/connection.rbs +32 -0
- data/sig/focus_nfe/http/logging.rbs +30 -0
- data/sig/focus_nfe/http/response.rbs +28 -0
- data/sig/focus_nfe/modelos/documento.rbs +34 -0
- data/sig/focus_nfe/modelos/inutilizacao.rbs +24 -0
- data/sig/focus_nfe/modelos/pagina.rbs +21 -0
- data/sig/focus_nfe/recursos/backups.rbs +7 -0
- data/sig/focus_nfe/recursos/base.rbs +25 -0
- data/sig/focus_nfe/recursos/ceps.rbs +10 -0
- data/sig/focus_nfe/recursos/cfops.rbs +10 -0
- data/sig/focus_nfe/recursos/cnaes.rbs +10 -0
- data/sig/focus_nfe/recursos/cnpjs.rbs +7 -0
- data/sig/focus_nfe/recursos/concerns/baixavel.rbs +12 -0
- data/sig/focus_nfe/recursos/concerns/baixavel_eventos.rbs +14 -0
- data/sig/focus_nfe/recursos/concerns/cancelavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/conciliavel.rbs +15 -0
- data/sig/focus_nfe/recursos/concerns/consultavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/corrigivel.rbs +15 -0
- data/sig/focus_nfe/recursos/concerns/corrigivel_cte.rbs +17 -0
- data/sig/focus_nfe/recursos/concerns/emitivel.rbs +14 -0
- data/sig/focus_nfe/recursos/concerns/enviavel.rbs +15 -0
- data/sig/focus_nfe/recursos/concerns/eventavel.rbs +12 -0
- data/sig/focus_nfe/recursos/concerns/inutilizavel.rbs +20 -0
- data/sig/focus_nfe/recursos/concerns/listavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/localizavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/notificavel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/removivel.rbs +9 -0
- data/sig/focus_nfe/recursos/concerns/visualizavel.rbs +9 -0
- data/sig/focus_nfe/recursos/cte.rbs +17 -0
- data/sig/focus_nfe/recursos/cte_os.rbs +17 -0
- data/sig/focus_nfe/recursos/ctes_recebidas.rbs +14 -0
- data/sig/focus_nfe/recursos/dce.rbs +10 -0
- data/sig/focus_nfe/recursos/emails_bloqueados.rbs +12 -0
- data/sig/focus_nfe/recursos/empresas.rbs +12 -0
- data/sig/focus_nfe/recursos/mdfe.rbs +21 -0
- data/sig/focus_nfe/recursos/municipios.rbs +19 -0
- data/sig/focus_nfe/recursos/ncms.rbs +10 -0
- data/sig/focus_nfe/recursos/nfce.rbs +12 -0
- data/sig/focus_nfe/recursos/nfcom.rbs +10 -0
- data/sig/focus_nfe/recursos/nfe.rbs +23 -0
- data/sig/focus_nfe/recursos/nfes_recebidas.rbs +16 -0
- data/sig/focus_nfe/recursos/nfgas.rbs +10 -0
- data/sig/focus_nfe/recursos/nfse.rbs +11 -0
- data/sig/focus_nfe/recursos/nfse_nacional.rbs +10 -0
- data/sig/focus_nfe/recursos/nfses_nacionais_recebidas.rbs +11 -0
- data/sig/focus_nfe/recursos/webhooks.rbs +11 -0
- data/sig/focus_nfe/webhook.rbs +11 -0
- data/sig/focus_nfe.rbs +10 -0
- data/spec/focus_nfe/client_spec.rb +208 -0
- data/spec/focus_nfe/configuration_spec.rb +121 -0
- data/spec/focus_nfe/errors_mapping_spec.rb +68 -0
- data/spec/focus_nfe/errors_spec.rb +107 -0
- data/spec/focus_nfe/esquemas/campo_spec.rb +291 -0
- data/spec/focus_nfe/esquemas/decimal_spec.rb +54 -0
- data/spec/focus_nfe/esquemas/esquema_spec.rb +73 -0
- data/spec/focus_nfe/esquemas/validador_spec.rb +167 -0
- data/spec/focus_nfe/esquemas_spec.rb +42 -0
- data/spec/focus_nfe/http/adapter_spec.rb +8 -0
- data/spec/focus_nfe/http/adapters/net_http_spec.rb +181 -0
- data/spec/focus_nfe/http/authentication_spec.rb +24 -0
- data/spec/focus_nfe/http/connection_spec.rb +255 -0
- data/spec/focus_nfe/http/logging_spec.rb +83 -0
- data/spec/focus_nfe/http/response_spec.rb +161 -0
- data/spec/focus_nfe/modelos/documento_spec.rb +150 -0
- data/spec/focus_nfe/modelos/inutilizacao_spec.rb +91 -0
- data/spec/focus_nfe/modelos/pagina_spec.rb +77 -0
- data/spec/focus_nfe/recursos/backups_spec.rb +29 -0
- data/spec/focus_nfe/recursos/base_spec.rb +56 -0
- data/spec/focus_nfe/recursos/ceps_spec.rb +16 -0
- data/spec/focus_nfe/recursos/cfops_spec.rb +16 -0
- data/spec/focus_nfe/recursos/cnaes_spec.rb +20 -0
- data/spec/focus_nfe/recursos/cnpjs_spec.rb +11 -0
- data/spec/focus_nfe/recursos/concerns/emitivel_validacao_spec.rb +158 -0
- data/spec/focus_nfe/recursos/cte_os_spec.rb +9 -0
- data/spec/focus_nfe/recursos/cte_spec.rb +9 -0
- data/spec/focus_nfe/recursos/ctes_recebidas_spec.rb +56 -0
- data/spec/focus_nfe/recursos/dce_spec.rb +8 -0
- data/spec/focus_nfe/recursos/emails_bloqueados_spec.rb +29 -0
- data/spec/focus_nfe/recursos/empresas_spec.rb +45 -0
- data/spec/focus_nfe/recursos/mdfe_spec.rb +100 -0
- data/spec/focus_nfe/recursos/municipios_spec.rb +58 -0
- data/spec/focus_nfe/recursos/ncms_spec.rb +16 -0
- data/spec/focus_nfe/recursos/nfce_spec.rb +10 -0
- data/spec/focus_nfe/recursos/nfcom_spec.rb +8 -0
- data/spec/focus_nfe/recursos/nfe_spec.rb +262 -0
- data/spec/focus_nfe/recursos/nfes_recebidas_spec.rb +87 -0
- data/spec/focus_nfe/recursos/nfgas_spec.rb +8 -0
- data/spec/focus_nfe/recursos/nfse_nacional_spec.rb +8 -0
- data/spec/focus_nfe/recursos/nfse_spec.rb +9 -0
- data/spec/focus_nfe/recursos/nfses_nacionais_recebidas_spec.rb +17 -0
- data/spec/focus_nfe/recursos/webhooks_spec.rb +22 -0
- data/spec/focus_nfe/webhook_spec.rb +66 -0
- data/spec/focus_nfe_global_configuration_spec.rb +70 -0
- data/spec/focus_nfe_require_spec.rb +87 -0
- data/spec/focus_nfe_spec.rb +11 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/support/shared_examples/recurso_fiscal.rb +445 -0
- data/spec/support/shared_examples/recurso_leitura.rb +217 -0
- data/tools/pull_fields.rb +62 -0
- metadata +420 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de Carta de Correção Eletrônica (CC-e) do CT-e/CT-e OS: +POST
|
|
7
|
+
# /<base>/<ref>/carta_correcao+ com a correção _por campo_ no corpo — diferente
|
|
8
|
+
# da CC-e de texto livre da NF-e ({Corrigivel}). Devolve o {Modelos::Documento}
|
|
9
|
+
# com o estado fiscal da CC-e.
|
|
10
|
+
module CorrigivelCte
|
|
11
|
+
# Emite uma Carta de Correção Eletrônica corrigindo um campo do documento.
|
|
12
|
+
#
|
|
13
|
+
# São aceitas até 20 correções por documento, cada uma em uma requisição; vale
|
|
14
|
+
# apenas a última correção enviada. Variáveis tributárias, dados de remetente/
|
|
15
|
+
# destinatário e datas de emissão/saída não podem ser corrigidos.
|
|
16
|
+
#
|
|
17
|
+
# @param ref [String] referência do documento
|
|
18
|
+
# @param campo_corrigido [String] nome do campo a corrigir
|
|
19
|
+
# @param valor_corrigido [String] novo valor do campo
|
|
20
|
+
# @param grupo_corrigido [String, nil] grupo que contém o campo (ex.: +"cargas"+)
|
|
21
|
+
# @param numero_item_grupo_corrigido [String, nil] índice do item, quando o campo está numa lista (inicia em 1)
|
|
22
|
+
# @param campo_api [Integer, String, nil] +1+ para nomes de campo da API (padrão), +0+ para tags XML
|
|
23
|
+
# @return [FocusNfe::Modelos::Documento]
|
|
24
|
+
# @raise [ArgumentError] se a +ref+, +campo_corrigido+ ou +valor_corrigido+ forem inválidos
|
|
25
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
26
|
+
def corrigir(ref, campo_corrigido:, valor_corrigido:, grupo_corrigido: nil,
|
|
27
|
+
numero_item_grupo_corrigido: nil, campo_api: nil)
|
|
28
|
+
validar_referencia!(ref)
|
|
29
|
+
validar_campos_correcao!(campo_corrigido, valor_corrigido)
|
|
30
|
+
|
|
31
|
+
body = {
|
|
32
|
+
campo_corrigido: campo_corrigido, valor_corrigido: valor_corrigido,
|
|
33
|
+
grupo_corrigido: grupo_corrigido, numero_item_grupo_corrigido: numero_item_grupo_corrigido,
|
|
34
|
+
campo_api: campo_api
|
|
35
|
+
}.compact
|
|
36
|
+
response = connection.post("#{caminho_referencia(ref)}/carta_correcao", body: body)
|
|
37
|
+
Modelos::Documento.from_response(response, ref: ref)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
# @param campo_corrigido [String] campo informado
|
|
43
|
+
# @param valor_corrigido [String] valor informado
|
|
44
|
+
# @return [void]
|
|
45
|
+
# @raise [ArgumentError] se algum deles não for uma String não-vazia
|
|
46
|
+
def validar_campos_correcao!(campo_corrigido, valor_corrigido)
|
|
47
|
+
return if string_preenchida?(campo_corrigido) && string_preenchida?(valor_corrigido)
|
|
48
|
+
|
|
49
|
+
raise ArgumentError, "correção inválida: campo_corrigido e valor_corrigido são obrigatórios"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @param valor [Object] valor a checar
|
|
53
|
+
# @return [Boolean] true se for uma String com conteúdo não em branco
|
|
54
|
+
def string_preenchida?(valor)
|
|
55
|
+
valor.is_a?(String) && !valor.strip.empty?
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de emissão (+POST /<base>?ref=+). Devolve o {Modelos::Documento}
|
|
7
|
+
# com o estado fiscal inicial (em geral assíncrono: +processando_autorizacao+).
|
|
8
|
+
module Emitivel
|
|
9
|
+
# Emite um documento fiscal.
|
|
10
|
+
#
|
|
11
|
+
# @param ref [String] referência única do documento na sua aplicação
|
|
12
|
+
# @param dados [Hash] payload de emissão (campos do schema, validados server-side)
|
|
13
|
+
# @param validar [Boolean] se +true+, valida +dados+ contra o schema empacotado
|
|
14
|
+
# antes do envio (documentos sem schema próprio são emitidos sem validar)
|
|
15
|
+
# @param opcoes [Hash] parâmetros de query adicionais (ex.: emissão síncrona)
|
|
16
|
+
# @return [FocusNfe::Modelos::Documento]
|
|
17
|
+
# @raise [ArgumentError] se a +ref+ for inválida
|
|
18
|
+
# @raise [FocusNfe::Esquemas::ErroDeValidacao] se +validar+ e +dados+ violarem o schema
|
|
19
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
20
|
+
def emitir(ref:, dados:, validar: false, **opcoes)
|
|
21
|
+
validar_referencia!(ref)
|
|
22
|
+
validar_dados!(dados) if validar
|
|
23
|
+
|
|
24
|
+
response = connection.post(caminho_base, params: { ref: ref, **opcoes }, body: dados)
|
|
25
|
+
Modelos::Documento.from_response(response, ref: ref)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
# @param dados [Hash] payload de emissão a validar contra o schema
|
|
31
|
+
# @return [void]
|
|
32
|
+
# @raise [FocusNfe::Esquemas::ErroDeValidacao] se houver campo inválido/ausente
|
|
33
|
+
def validar_dados!(dados)
|
|
34
|
+
esquema = Esquemas::Esquema.carregar(caminho_base)
|
|
35
|
+
return unless esquema
|
|
36
|
+
|
|
37
|
+
normalizados = dados.transform_keys(&:to_s)
|
|
38
|
+
aninhados = carregar_aninhados(normalizados)
|
|
39
|
+
erros = Esquemas::Validador.new(esquema, aninhados: aninhados).validar(normalizados)
|
|
40
|
+
raise Esquemas::ErroDeValidacao, erros unless erros.empty?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# @param dados [Hash] payload normalizado (chaves String)
|
|
44
|
+
# @return [Hash{String => FocusNfe::Esquemas::Esquema}] sub-esquemas por chave aninhada
|
|
45
|
+
def carregar_aninhados(dados)
|
|
46
|
+
esquemas_extras(dados).transform_values { |nome| Esquemas::Esquema.carregar(nome) }.compact
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de reenvio do documento por e-mail (+POST
|
|
7
|
+
# /<base>/<ref>/email+ com a lista de destinatários no corpo). Devolve o
|
|
8
|
+
# corpo cru da resposta.
|
|
9
|
+
module Enviavel
|
|
10
|
+
# @return [Integer] número máximo de destinatários aceito pela API
|
|
11
|
+
MAX_EMAILS = 10
|
|
12
|
+
|
|
13
|
+
# Reenvia o documento por e-mail para os destinatários informados.
|
|
14
|
+
#
|
|
15
|
+
# @param ref [String] referência do documento
|
|
16
|
+
# @param emails [Array<String>] destinatários (1 a 10)
|
|
17
|
+
# @return [Hash, Array, nil] corpo cru da resposta
|
|
18
|
+
# @raise [ArgumentError] se a +ref+ ou a lista de +emails+ forem inválidas
|
|
19
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
20
|
+
def enviar_email(ref, emails:)
|
|
21
|
+
validar_referencia!(ref)
|
|
22
|
+
validar_emails!(emails)
|
|
23
|
+
|
|
24
|
+
connection.post("#{caminho_referencia(ref)}/email", body: { emails: emails }).body
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# @param emails [Array<String>] lista informada
|
|
30
|
+
# @return [void]
|
|
31
|
+
# @raise [ArgumentError] se não for Array de 1 a 10 elementos
|
|
32
|
+
def validar_emails!(emails)
|
|
33
|
+
return if emails.is_a?(Array) && (1..MAX_EMAILS).cover?(emails.size)
|
|
34
|
+
|
|
35
|
+
raise ArgumentError, "emails inválidos: esperado Array com 1 a #{MAX_EMAILS} destinatários"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Transporte de eventos fiscais sobre um documento (+POST+/+DELETE+ num
|
|
7
|
+
# sub-caminho da referência). Cada recurso expõe seus eventos por cima
|
|
8
|
+
# destes helpers — o MDF-e com nomes próprios (+encerrar+, +incluir_condutor+,
|
|
9
|
+
# +incluir_dfe+) e as notas recebidas com +emitir_evento+/+cancelar_evento+.
|
|
10
|
+
# Devolve o {Modelos::Documento} com o estado fiscal resultante do evento.
|
|
11
|
+
module Eventavel
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
# Emite um evento sobre o documento (+POST /<base>/<ref>/<caminho>+).
|
|
15
|
+
#
|
|
16
|
+
# @param ref [String] referência do documento
|
|
17
|
+
# @param caminho [String] sub-caminho do evento (ex.: +encerrar+)
|
|
18
|
+
# @param dados [Hash] campos do corpo do evento
|
|
19
|
+
# @return [FocusNfe::Modelos::Documento]
|
|
20
|
+
# @raise [ArgumentError] se a +ref+ for inválida
|
|
21
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
22
|
+
def emitir_evento_em(ref, caminho:, **dados)
|
|
23
|
+
validar_referencia!(ref)
|
|
24
|
+
|
|
25
|
+
response = connection.post("#{caminho_referencia(ref)}/#{caminho}", body: dados)
|
|
26
|
+
Modelos::Documento.from_response(response, ref: ref)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Cancela um evento do documento (+DELETE /<base>/<ref>/<caminho>+).
|
|
30
|
+
#
|
|
31
|
+
# @param ref [String] referência do documento
|
|
32
|
+
# @param caminho [String] sub-caminho do evento (ex.: +evento+)
|
|
33
|
+
# @param dados [Hash] campos do corpo do cancelamento; omitidos não enviam corpo
|
|
34
|
+
# @return [FocusNfe::Modelos::Documento]
|
|
35
|
+
# @raise [ArgumentError] se a +ref+ for inválida
|
|
36
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
37
|
+
def cancelar_evento_em(ref, caminho:, **dados)
|
|
38
|
+
validar_referencia!(ref)
|
|
39
|
+
|
|
40
|
+
response = connection.delete("#{caminho_referencia(ref)}/#{caminho}", body: dados.empty? ? nil : dados)
|
|
41
|
+
Modelos::Documento.from_response(response, ref: ref)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de inutilização de numeração: criação (+POST
|
|
7
|
+
# /<base>/inutilizacao+, devolvendo um {Modelos::Inutilizacao}) e consulta
|
|
8
|
+
# das já criadas (+GET /<base>/inutilizacoes+, devolvendo uma lista de
|
|
9
|
+
# {Modelos::Inutilizacao}). É uma operação de coleção — sem +ref+ por
|
|
10
|
+
# documento.
|
|
11
|
+
module Inutilizavel
|
|
12
|
+
# @return [String] segmento do caminho de criação (singular)
|
|
13
|
+
CAMINHO_INUTILIZACAO = "inutilizacao"
|
|
14
|
+
|
|
15
|
+
# @return [String] segmento do caminho de consulta (plural)
|
|
16
|
+
CAMINHO_INUTILIZACOES = "inutilizacoes"
|
|
17
|
+
|
|
18
|
+
# @return [Integer] tamanho mínimo da justificativa exigido pela SEFAZ
|
|
19
|
+
JUSTIFICATIVA_MINIMA = 15
|
|
20
|
+
|
|
21
|
+
# Inutiliza uma faixa de numeração não utilizada.
|
|
22
|
+
#
|
|
23
|
+
# @param cnpj [String] CNPJ do emitente
|
|
24
|
+
# @param serie [String, Integer] série da numeração
|
|
25
|
+
# @param numero_inicial [String, Integer] número inicial da faixa
|
|
26
|
+
# @param numero_final [String, Integer] número final da faixa
|
|
27
|
+
# @param justificativa [String] motivo da inutilização (mínimo 15 caracteres)
|
|
28
|
+
# @return [FocusNfe::Modelos::Inutilizacao]
|
|
29
|
+
# @raise [ArgumentError] se a +justificativa+ for inválida
|
|
30
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
31
|
+
def inutilizar(cnpj:, serie:, numero_inicial:, numero_final:, justificativa:)
|
|
32
|
+
validar_justificativa!(justificativa)
|
|
33
|
+
validar_faixa!(numero_inicial, numero_final)
|
|
34
|
+
|
|
35
|
+
body = { cnpj: cnpj, serie: serie, numero_inicial: numero_inicial,
|
|
36
|
+
numero_final: numero_final, justificativa: justificativa }
|
|
37
|
+
response = connection.post("#{caminho_base}/#{CAMINHO_INUTILIZACAO}", body: body)
|
|
38
|
+
Modelos::Inutilizacao.from_response(response)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Consulta as inutilizações já registradas, aplicando os filtros como query string.
|
|
42
|
+
#
|
|
43
|
+
# @param filtros [Hash] filtros aceitos pela API (ex.: +cnpj:+, +cpf:+, +numero_inicial:+)
|
|
44
|
+
# @return [Array<FocusNfe::Modelos::Inutilizacao>]
|
|
45
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
46
|
+
def consultar_inutilizacoes(**filtros)
|
|
47
|
+
response = connection.get("#{caminho_base}/#{CAMINHO_INUTILIZACOES}", params: filtros)
|
|
48
|
+
itens = response.body.is_a?(Array) ? response.body : []
|
|
49
|
+
itens.map { |item| Modelos::Inutilizacao.from_item(item) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
# @param justificativa [String] justificativa informada
|
|
55
|
+
# @return [void]
|
|
56
|
+
# @raise [ArgumentError] se não for String ou tiver menos de 15 caracteres
|
|
57
|
+
def validar_justificativa!(justificativa)
|
|
58
|
+
return if justificativa.is_a?(String) && justificativa.length >= JUSTIFICATIVA_MINIMA
|
|
59
|
+
|
|
60
|
+
raise ArgumentError,
|
|
61
|
+
"justificativa inválida: esperado String com ao menos #{JUSTIFICATIVA_MINIMA} caracteres"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Valida a faixa de numeração: ambos os números presentes, inteiros, e
|
|
65
|
+
# +numero_inicial+ não maior que +numero_final+ (faixa de um único número
|
|
66
|
+
# é permitida).
|
|
67
|
+
#
|
|
68
|
+
# @param numero_inicial [String, Integer] número inicial informado
|
|
69
|
+
# @param numero_final [String, Integer] número final informado
|
|
70
|
+
# @return [void]
|
|
71
|
+
# @raise [ArgumentError] se algum número for ausente/não inteiro ou se inicial > final
|
|
72
|
+
def validar_faixa!(numero_inicial, numero_final)
|
|
73
|
+
inicial = numero_para_inteiro(numero_inicial)
|
|
74
|
+
final = numero_para_inteiro(numero_final)
|
|
75
|
+
|
|
76
|
+
if inicial.nil? || final.nil?
|
|
77
|
+
raise ArgumentError, "numeração inválida: numero_inicial e numero_final devem ser inteiros"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return if inicial <= final
|
|
81
|
+
|
|
82
|
+
raise ArgumentError, "numeração inválida: numero_inicial (#{inicial}) maior que numero_final (#{final})"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param valor [Object] valor informado
|
|
86
|
+
# @return [Integer, nil] o valor como inteiro (base 10) ou +nil+ se não for conversível
|
|
87
|
+
def numero_para_inteiro(valor)
|
|
88
|
+
case valor
|
|
89
|
+
when Integer then valor
|
|
90
|
+
when String then Integer(valor, 10, exception: false)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de listagem (+GET /<base>+). Os filtros viram query string e
|
|
7
|
+
# a resposta — corpo + cabeçalhos de paginação — é encapsulada numa
|
|
8
|
+
# {Modelos::Pagina}.
|
|
9
|
+
module Listavel
|
|
10
|
+
# Lista os registros do recurso, aplicando os filtros como query string.
|
|
11
|
+
#
|
|
12
|
+
# @param filtros [Hash] filtros e paginação aceitos pelo recurso (ex.: +cnpj:+, +versao:+, +offset:+)
|
|
13
|
+
# @return [FocusNfe::Modelos::Pagina]
|
|
14
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
15
|
+
def listar(**filtros)
|
|
16
|
+
response = connection.get(caminho_base, params: filtros)
|
|
17
|
+
Modelos::Pagina.from_response(response)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de consulta por identificador (+GET /<base>/<identificador>+),
|
|
7
|
+
# para recursos de leitura e referência. Devolve o corpo cru da resposta
|
|
8
|
+
# (Hash) — sem validação fiscal de +ref+, pois o identificador é um código,
|
|
9
|
+
# chave ou CNPJ.
|
|
10
|
+
module Localizavel
|
|
11
|
+
# Consulta um registro pelo seu identificador.
|
|
12
|
+
#
|
|
13
|
+
# @param identificador [String] código/chave/CNPJ do registro
|
|
14
|
+
# @return [Hash, Array, nil] corpo cru da resposta
|
|
15
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
16
|
+
def consultar(identificador)
|
|
17
|
+
connection.get(caminho_referencia(identificador)).body
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de reenvio de notificação (+POST /<base>/<identificador>/hook+),
|
|
7
|
+
# disparando de novo o webhook do documento.
|
|
8
|
+
module Notificavel
|
|
9
|
+
# Reenvia a notificação (webhook) do documento.
|
|
10
|
+
#
|
|
11
|
+
# @param identificador [String] chave ou referência do documento
|
|
12
|
+
# @return [Hash, Array, nil] corpo cru da resposta
|
|
13
|
+
# @raise [ArgumentError] se o +identificador+ for inválido
|
|
14
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
15
|
+
def reenviar_hook(identificador)
|
|
16
|
+
validar_referencia!(identificador)
|
|
17
|
+
|
|
18
|
+
connection.post("#{caminho_referencia(identificador)}/hook").body
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de exclusão por identificador (+DELETE /<base>/<identificador>+),
|
|
7
|
+
# para recursos de gestão (CRUD).
|
|
8
|
+
module Removivel
|
|
9
|
+
# Exclui um registro pelo seu identificador.
|
|
10
|
+
#
|
|
11
|
+
# @param identificador [String] id do registro
|
|
12
|
+
# @return [Hash, Array, nil] corpo cru da resposta
|
|
13
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
14
|
+
def excluir(identificador)
|
|
15
|
+
connection.delete(caminho_referencia(identificador)).body
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
module Concerns
|
|
6
|
+
# Comportamento de prévia/visualização (+POST /<base_previa>+ com o payload
|
|
7
|
+
# no corpo). Gera o PDF apenas para conferência visual — sem valor fiscal e
|
|
8
|
+
# sem emitir o documento. O caminho é declarado por
|
|
9
|
+
# {Base.caminho_base_previa} em cada recurso (ex.: +"nfe/danfe"+), para que
|
|
10
|
+
# outros documentos com prévia o adotem sem alterar o mixin. A validação
|
|
11
|
+
# opt-in reaproveita o schema via {Concerns::Emitivel}.
|
|
12
|
+
module Visualizavel
|
|
13
|
+
# Gera a prévia do documento a partir do payload, devolvendo os bytes do PDF.
|
|
14
|
+
#
|
|
15
|
+
# @param dados [Hash] payload do documento (mesmos campos da emissão)
|
|
16
|
+
# @param validar [Boolean] se +true+, valida +dados+ contra o schema empacotado antes do envio
|
|
17
|
+
# @return [String, nil] bytes crus do PDF da prévia
|
|
18
|
+
# @raise [FocusNfe::Esquemas::ErroDeValidacao] se +validar+ e +dados+ violarem o schema
|
|
19
|
+
# @raise [FocusNfe::Errors::HttpError] em respostas não-2xx
|
|
20
|
+
def previa(dados:, validar: false)
|
|
21
|
+
validar_dados!(dados) if validar
|
|
22
|
+
|
|
23
|
+
connection.post(caminho_base_previa, body: dados).raw_body
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
# Recurso de Conhecimento de Transporte eletrônico (CT-e). Emissão
|
|
6
|
+
# assíncrona (síncrona opcional) com consulta de estado, cancelamento e
|
|
7
|
+
# Carta de Correção Eletrônica (CC-e) por campo.
|
|
8
|
+
class Cte < Base
|
|
9
|
+
include Concerns::Emitivel
|
|
10
|
+
include Concerns::Consultavel
|
|
11
|
+
include Concerns::Cancelavel
|
|
12
|
+
include Concerns::CorrigivelCte
|
|
13
|
+
include Concerns::Notificavel
|
|
14
|
+
|
|
15
|
+
caminho_base "cte"
|
|
16
|
+
|
|
17
|
+
# @return [Hash{String=>Hash{String=>String}}] código do modal => chave do payload => nome do sub-esquema
|
|
18
|
+
MODAIS = {
|
|
19
|
+
"01" => { "modal_rodoviario" => "cte_transporte_rodoviario" },
|
|
20
|
+
"02" => { "modal_aereo" => "cte_transporte_aereo" },
|
|
21
|
+
"03" => { "modal_aquaviario" => "cte_transporte_aquaviario" },
|
|
22
|
+
"04" => { "modal_ferroviario" => "cte_transporte_ferroviario" },
|
|
23
|
+
"05" => { "modal_dutoviario" => "cte_transporte_dutoviario" },
|
|
24
|
+
"06" => { "modal_multimodal" => "cte_transporte_multimodal" }
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
# @see FocusNfe::Recursos::Base#esquemas_extras
|
|
30
|
+
def esquemas_extras(dados)
|
|
31
|
+
MODAIS.fetch(dados["modal"], {})
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
# Recurso de CT-e Outros Serviços (CT-e OS). Emissão síncrona com consulta
|
|
6
|
+
# de estado e cancelamento.
|
|
7
|
+
class CteOs < Base
|
|
8
|
+
include Concerns::Emitivel
|
|
9
|
+
include Concerns::Consultavel
|
|
10
|
+
include Concerns::Cancelavel
|
|
11
|
+
include Concerns::CorrigivelCte
|
|
12
|
+
include Concerns::Notificavel
|
|
13
|
+
|
|
14
|
+
caminho_base "cte_os"
|
|
15
|
+
|
|
16
|
+
# @return [Hash{String=>Hash{String=>String}}] código do modal => chave do payload => nome do sub-esquema
|
|
17
|
+
MODAIS = {
|
|
18
|
+
"01" => { "modal_rodoviario" => "cte_os_transporte_rodoviario" }
|
|
19
|
+
}.freeze
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
# @see FocusNfe::Recursos::Base#esquemas_extras
|
|
24
|
+
def esquemas_extras(dados)
|
|
25
|
+
MODAIS.fetch(dados["modal"], {})
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
# Conhecimentos de transporte (CT-e) recebidos contra um CNPJ. Listagem com
|
|
6
|
+
# sincronização incremental, consulta por chave, downloads e prestação de
|
|
7
|
+
# desacordo de serviço.
|
|
8
|
+
class CtesRecebidas < Base
|
|
9
|
+
include Concerns::Listavel
|
|
10
|
+
include Concerns::Baixavel
|
|
11
|
+
include Concerns::BaixavelEventos
|
|
12
|
+
include Concerns::Notificavel
|
|
13
|
+
|
|
14
|
+
caminho_base "ctes_recebidas"
|
|
15
|
+
|
|
16
|
+
# @param chave [String] chave de acesso do CT-e
|
|
17
|
+
# @return [Hash] corpo cru da resposta
|
|
18
|
+
def consultar(chave)
|
|
19
|
+
connection.get(caminho_referencia(chave)).body
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Registra a prestação de desacordo do serviço de transporte.
|
|
23
|
+
#
|
|
24
|
+
# @param chave [String] chave de acesso do CT-e
|
|
25
|
+
# @param observacoes [String] motivo do desacordo (15 a 255 caracteres)
|
|
26
|
+
# @return [Hash] corpo cru da resposta
|
|
27
|
+
def desacordo(chave, observacoes:)
|
|
28
|
+
connection.post("#{caminho_referencia(chave)}/desacordo", body: { observacoes: observacoes }).body
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @param chave [String] chave de acesso do CT-e
|
|
32
|
+
# @return [Hash] corpo cru da resposta com o desacordo registrado
|
|
33
|
+
def consultar_desacordo(chave)
|
|
34
|
+
connection.get("#{caminho_referencia(chave)}/desacordo").body
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
# Recurso de Declaração de Conteúdo eletrônica (DC-e). Emissão assíncrona
|
|
6
|
+
# com consulta de estado e cancelamento.
|
|
7
|
+
class Dce < Base
|
|
8
|
+
include Concerns::Emitivel
|
|
9
|
+
include Concerns::Consultavel
|
|
10
|
+
include Concerns::Cancelavel
|
|
11
|
+
include Concerns::Notificavel
|
|
12
|
+
|
|
13
|
+
caminho_base "dce"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
# Gestão de e-mails bloqueados (bounces/reclamações). O caminho da API é
|
|
6
|
+
# +blocked_emails+; o e-mail compõe o path e é escapado.
|
|
7
|
+
class EmailsBloqueados < Base
|
|
8
|
+
caminho_base "blocked_emails"
|
|
9
|
+
|
|
10
|
+
# @param email [String] e-mail a consultar
|
|
11
|
+
# @return [Hash] corpo cru da resposta com o motivo do bloqueio
|
|
12
|
+
def consultar(email)
|
|
13
|
+
connection.get(caminho_email(email)).body
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Solicita o desbloqueio (exclusão) de um e-mail.
|
|
17
|
+
#
|
|
18
|
+
# @param email [String] e-mail a desbloquear
|
|
19
|
+
# @return [Hash] corpo cru da resposta
|
|
20
|
+
def desbloquear(email)
|
|
21
|
+
connection.delete(caminho_email(email)).body
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def caminho_email(email)
|
|
27
|
+
"#{caminho_base}/#{URI.encode_www_form_component(email)}"
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module FocusNfe
|
|
4
|
+
module Recursos
|
|
5
|
+
# Gestão de empresas (CRUD). Disponível apenas em produção na Focus NFe; o
|
|
6
|
+
# certificado vai em base64 nos dados. A simulação (+dry_run+) valida o cadastro
|
|
7
|
+
# sem persistir.
|
|
8
|
+
class Empresas < Base
|
|
9
|
+
include Concerns::Listavel
|
|
10
|
+
include Concerns::Localizavel
|
|
11
|
+
include Concerns::Removivel
|
|
12
|
+
|
|
13
|
+
caminho_base "empresas"
|
|
14
|
+
|
|
15
|
+
# Cadastra uma empresa.
|
|
16
|
+
#
|
|
17
|
+
# @param dados [Hash] dados da empresa (certificado PFX em base64 quando aplicável)
|
|
18
|
+
# @param dry_run [Boolean] quando +true+, valida sem persistir (+dry_run=1+)
|
|
19
|
+
# @return [Hash] corpo cru da resposta
|
|
20
|
+
def criar(dados:, dry_run: false)
|
|
21
|
+
params = dry_run ? { dry_run: 1 } : {}
|
|
22
|
+
connection.post(caminho_base, params: params, body: dados).body
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Atualiza uma empresa existente.
|
|
26
|
+
#
|
|
27
|
+
# @param id [String, Integer] identificador da empresa
|
|
28
|
+
# @param dados [Hash] campos a atualizar
|
|
29
|
+
# @return [Hash] corpo cru da resposta
|
|
30
|
+
def atualizar(id, dados:)
|
|
31
|
+
connection.put(caminho_referencia(id), body: dados).body
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|