Class: Nfe::Resources::ConsumerInvoices
- Inherits:
-
AbstractResource
- Object
- AbstractResource
- Nfe::Resources::ConsumerInvoices
- Defined in:
- lib/nfe/resources/consumer_invoices.rb,
sig/nfe/resources/consumer_invoices.rbs
Overview
Consumer invoices (NFC-e — Nota Fiscal de Consumidor Eletrônica).
Hosted at https://api.nfse.io under /v2 (the :cte family), backed by
the paths exposed in nf-consumidor-v2.yaml.
Parity-plus
This resource is a parity-plus addition: the Node.js SDK deliberately
does NOT expose NFC-e emission (it covers only the read-only
consumerInvoiceQuery). The NFE.io API has supported the full NFC-e
lifecycle since v2, so this Ruby SDK extends beyond Node parity — useful
for PoS and e-commerce integrations.
Intentional omissions (grounded in Brazilian fiscal law)
Unlike ProductInvoices (NF-e), this resource does NOT define:
send_correction_letter— the Carta de Correção Eletrônica (CC-e) instrument applies only to NF-e/CT-e, never to NFC-e.download_epec_xml— there is no EPEC (Evento Prévio de Emissão em Contingência) for NFC-e.- a per-invoice
disable— NFC-e supports only collective inutilization of a number range via #disable_range, not per-document disablement. Calling any of these raisesNoMethodError.
Emission contract
#create and #create_with_state_tax return a discriminated result:
ConsumerInvoicePending on HTTP 202 (async) or
ConsumerInvoiceIssued on HTTP 201/200 (sync). Both accept
an optional idempotency_key: (sent as the Idempotency-Key header; the
SDK never auto-retries, so re-invoking with the SAME key after a timeout
lets the server deduplicate) and request_options: (per-call
multi-tenant overrides). +create_and_wait+/+create_batch+ are deferred:
poll manually with result.pending? + FlowStatus.terminal?.
Constant Summary collapse
- ENVELOPE =
Wrapper key for the list envelope.
"consumerInvoices"
Instance Attribute Summary
Attributes inherited from AbstractResource
Instance Method Summary collapse
- #api_family ⇒ Symbol
-
#api_version ⇒ String
The
:ctehost (+api.nfse.io+) does not bake in a version, so this resource supplies the/v2segment itself. -
#cancel(company_id:, invoice_id:) ⇒ Nfe::ConsumerInvoice
Cancel an NFC-e (synchronous); returns the updated model.
-
#create(company_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ConsumerInvoicePending, ConsumerInvoiceIssued
Emit an NFC-e.
-
#create_with_state_tax(company_id:, state_tax_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ConsumerInvoicePending, ConsumerInvoiceIssued
Emit an NFC-e scoped to a specific state-tax registration.
-
#disable_range(company_id:, data:) ⇒ Hash
Collectively inutilize a range of NFC-e numbers.
-
#discriminate(response) ⇒ Nfe::Resources::ConsumerInvoicePending, Nfe::Resources::ConsumerInvoiceIssued
Interpret an emission response into the discriminated NFC-e result.
-
#download_pdf(company_id:, invoice_id:) ⇒ String
Download the DANFE NFC-e PDF as binary bytes (unlike ProductInvoices, which returns a URI).
-
#download_rejection_xml(company_id:, invoice_id:) ⇒ String
Download the rejection XML (sefaz refusal) as binary bytes.
-
#download_xml(company_id:, invoice_id:) ⇒ String
Download the authorized NFC-e XML as binary bytes.
-
#extract_invoice_id(location) ⇒ String?
Extract the trailing id from a
Locationpath. - #issued_result(response) ⇒ Nfe::Resources::ConsumerInvoiceIssued
- #json_body(data) ⇒ String
- #json_headers ⇒ Hash[String, String]
-
#list(company_id:, environment:, **options) ⇒ Nfe::ListResponse
List NFC-e for a company (cursor pagination; wrapper
consumerInvoices). -
#list_events(company_id:, invoice_id:) ⇒ Array<Hash>
List the events of an NFC-e.
-
#list_items(company_id:, invoice_id:) ⇒ Array<Hash>
List the line items of an NFC-e.
-
#require_environment(environment) ⇒ void
The API rejects a NFC-e listing without an
environment; require it client-side (mirrors product_invoices#list). -
#retrieve(company_id:, invoice_id:) ⇒ Nfe::ConsumerInvoice
Retrieve a single NFC-e by id.
-
#unwrap_collection(payload, key) ⇒ Array[untyped]
Unwrap a collection envelope, tolerating a bare array or a wrapped one.
-
#validate_pair(company_id, invoice_id) ⇒ Array[String]
Validate a (company_id, invoice_id) pair, returning both normalized.
Methods inherited from AbstractResource
#build_list_page, #build_multipart_body, #cursor_list_page, #delete, #dig_key, #download, #full_path, #get, #handle_async_response, #hydrate, #hydrate_list, #initialize, #multipart_part, #page_list_page, #parse_json, #post, #put, #unwrap, #upload_multipart
Constructor Details
This class inherits a constructor from Nfe::Resources::AbstractResource
Instance Method Details
#api_family ⇒ Symbol
56 57 58 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 56 def api_family :cte end |
#api_version ⇒ String
The :cte host (+api.nfse.io+) does not bake in a version, so this
resource supplies the /v2 segment itself.
62 63 64 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 62 def api_version "v2" end |
#cancel(company_id:, invoice_id:) ⇒ Nfe::ConsumerInvoice
Cancel an NFC-e (synchronous); returns the updated model.
127 128 129 130 131 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 127 def cancel(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) response = delete("/companies/#{cid}/consumerinvoices/#{iid}") hydrate(Nfe::ConsumerInvoice, parse_json(response.body)) end |
#create(company_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ConsumerInvoicePending, ConsumerInvoiceIssued
Emit an NFC-e. Returns Nfe::Resources::ConsumerInvoicePending (HTTP 202) or Nfe::Resources::ConsumerInvoiceIssued (HTTP 201/200).
76 77 78 79 80 81 82 83 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 76 def create(company_id:, data:, idempotency_key: nil, request_options: nil) id = Nfe::IdValidator.company_id(company_id) response = post("/companies/#{id}/consumerinvoices", body: json_body(data), headers: json_headers, idempotency_key: idempotency_key, request_options: ) discriminate(response) end |
#create_with_state_tax(company_id:, state_tax_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ConsumerInvoicePending, ConsumerInvoiceIssued
Emit an NFC-e scoped to a specific state-tax registration.
93 94 95 96 97 98 99 100 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 93 def create_with_state_tax(company_id:, state_tax_id:, data:, idempotency_key: nil, request_options: nil) cid = Nfe::IdValidator.company_id(company_id) sid = Nfe::IdValidator.state_tax_id(state_tax_id) response = post("/companies/#{cid}/statetaxes/#{sid}/consumerinvoices", body: json_body(data), headers: json_headers, idempotency_key: idempotency_key, request_options: ) discriminate(response) end |
#disable_range(company_id:, data:) ⇒ Hash
Collectively inutilize a range of NFC-e numbers. NFC-e supports only collective inutilization (no per-invoice disablement).
185 186 187 188 189 190 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 185 def disable_range(company_id:, data:) id = Nfe::IdValidator.company_id(company_id) response = post("/companies/#{id}/consumerinvoices/disablement", body: json_body(data), headers: json_headers) parse_json(response.body) || {} end |
#discriminate(response) ⇒ Nfe::Resources::ConsumerInvoicePending, Nfe::Resources::ConsumerInvoiceIssued
Interpret an emission response into the discriminated NFC-e result.
208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 208 def discriminate(response) return issued_result(response) unless response.status == 202 location = response.location if location.nil? || location.empty? raise Nfe::InvoiceProcessingError.new( "Resposta 202 sem cabeçalho Location: não é possível identificar a NFC-e em processamento.", status_code: response.status, response_headers: response.headers ) end ConsumerInvoicePending.new(invoice_id: extract_invoice_id(location), location: location) end |
#download_pdf(company_id:, invoice_id:) ⇒ String
Download the DANFE NFC-e PDF as binary bytes (unlike ProductInvoices, which returns a URI).
155 156 157 158 159 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 155 def download_pdf(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) download("/companies/#{cid}/consumerinvoices/#{iid}/pdf", headers: { "Accept" => "application/pdf" }) end |
#download_rejection_xml(company_id:, invoice_id:) ⇒ String
Download the rejection XML (sefaz refusal) as binary bytes.
173 174 175 176 177 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 173 def download_rejection_xml(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) download("/companies/#{cid}/consumerinvoices/#{iid}/xml/rejection", headers: { "Accept" => "application/xml" }) end |
#download_xml(company_id:, invoice_id:) ⇒ String
Download the authorized NFC-e XML as binary bytes.
164 165 166 167 168 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 164 def download_xml(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) download("/companies/#{cid}/consumerinvoices/#{iid}/xml", headers: { "Accept" => "application/xml" }) end |
#extract_invoice_id(location) ⇒ String?
Extract the trailing id from a Location path.
227 228 229 230 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 227 def extract_invoice_id(location) match = location.match(%r{/([a-z0-9-]+)\z}i) match ? match[1] : nil end |
#issued_result(response) ⇒ Nfe::Resources::ConsumerInvoiceIssued
221 222 223 224 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 221 def issued_result(response) invoice = hydrate(Nfe::ConsumerInvoice, parse_json(response.body)) ConsumerInvoiceIssued.new(resource: invoice) end |
#json_body(data) ⇒ String
245 246 247 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 245 def json_body(data) JSON.generate(data) end |
#json_headers ⇒ Hash[String, String]
241 242 243 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 241 def json_headers { "Content-Type" => "application/json" } end |
#list(company_id:, environment:, **options) ⇒ Nfe::ListResponse
List NFC-e for a company (cursor pagination; wrapper consumerInvoices).
107 108 109 110 111 112 113 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 107 def list(company_id:, environment:, **) id = Nfe::IdValidator.company_id(company_id) require_environment(environment) response = get("/companies/#{id}/consumerinvoices", query: .merge(environment: environment)) hydrate_list(Nfe::ConsumerInvoice, parse_json(response.body), wrapper_key: ENVELOPE) end |
#list_events(company_id:, invoice_id:) ⇒ Array<Hash>
List the events of an NFC-e.
145 146 147 148 149 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 145 def list_events(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) response = get("/companies/#{cid}/consumerinvoices/#{iid}/events") unwrap_collection(parse_json(response.body), "events") end |
#list_items(company_id:, invoice_id:) ⇒ Array<Hash>
List the line items of an NFC-e.
136 137 138 139 140 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 136 def list_items(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) response = get("/companies/#{cid}/consumerinvoices/#{iid}/items") unwrap_collection(parse_json(response.body), "items") end |
#require_environment(environment) ⇒ void
This method returns an undefined value.
The API rejects a NFC-e listing without an environment; require it
client-side (mirrors product_invoices#list).
196 197 198 199 200 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 196 def require_environment(environment) return unless environment.nil? || environment.to_s.strip.empty? raise Nfe::InvalidRequestError, "environment é obrigatório (Production ou Test)" end |
#retrieve(company_id:, invoice_id:) ⇒ Nfe::ConsumerInvoice
Retrieve a single NFC-e by id.
118 119 120 121 122 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 118 def retrieve(company_id:, invoice_id:) cid, iid = validate_pair(company_id, invoice_id) response = get("/companies/#{cid}/consumerinvoices/#{iid}") hydrate(Nfe::ConsumerInvoice, parse_json(response.body)) end |
#unwrap_collection(payload, key) ⇒ Array[untyped]
Unwrap a collection envelope, tolerating a bare array or a wrapped one.
233 234 235 236 237 238 239 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 233 def unwrap_collection(payload, key) return payload if payload.is_a?(Array) return [] unless payload.is_a?(Hash) wrapped = payload[key] || payload[key.to_sym] wrapped.is_a?(Array) ? wrapped : [] end |
#validate_pair(company_id, invoice_id) ⇒ Array[String]
Validate a (company_id, invoice_id) pair, returning both normalized.
203 204 205 |
# File 'lib/nfe/resources/consumer_invoices.rb', line 203 def validate_pair(company_id, invoice_id) [Nfe::IdValidator.company_id(company_id), Nfe::IdValidator.invoice_id(invoice_id)] end |