Class: Nfe::Resources::ProductInvoicesRtc
- Inherits:
-
AbstractResource
- Object
- AbstractResource
- Nfe::Resources::ProductInvoicesRtc
- Defined in:
- lib/nfe/resources/product_invoices_rtc.rb,
sig/nfe/resources/product_invoices_rtc.rbs
Overview
RTC (Reforma Tributária do Consumo) product invoices (NF-e mod 55 / NFC-e
mod 65) resource for the :cte host family (+https://api.nfse.io/v2/...+).
Full lifecycle: issue, list, retrieve, cancel, correction letters (CC-e),
disablement (inutilização) and file downloads, hydrating the RTC generated
DTOs in Generated::ProductInvoiceRtcV1.
This resource shares the SAME endpoints as the classic
ProductInvoices. There is NO discriminator header or
query param: the RTC tax layout is selected by the API from the SHAPE of
the payload — specifically the presence of the item-level IBSCBS group
(+items.tax.IBSCBS+). NF-e (mod 55) vs NFC-e (mod 65) is likewise
inferred from the payload shape. Use this resource (vs the classic one)
when you want the RTC response DTOs hydrated.
Emission is asynchronous (HTTP 202, queued; completion via webhook): #create/#create_with_state_tax return either a ProductInvoiceRtcPending or a ProductInvoiceRtcIssued. There is no +create_and_wait+/+create_batch+ — poll manually with #retrieve + FlowStatus.terminal?.
NOTE: as with the classic resource, the download methods return a
NfeFileResource (a URI to the file), NOT raw bytes — the API
responds with a JSON { uri } envelope.
Instance Attribute Summary
Attributes inherited from AbstractResource
Instance Method Summary collapse
- #api_family ⇒ Symbol
-
#api_version ⇒ String
The
:ctehost serves the v2 API; paths embed/v2explicitly, so no version segment is auto-prefixed. - #base_path(company_id) ⇒ String
-
#build_pending(response) ⇒ Nfe::Resources::ProductInvoiceRtcPending
Build a ProductInvoiceRtcPending from a 202 response, or raise when the Location header is missing/unparsable.
-
#cancel(company_id:, invoice_id:, reason: nil) ⇒ Nfe::Generated::ProductInvoiceRtcV1::RequestCancellationResource?
Cancel an RTC product invoice (async);
reasonforwarded as a query param. -
#create(company_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ProductInvoiceRtcPending, ProductInvoiceRtcIssued
Issue an RTC product invoice (NF-e/NFC-e).
-
#create_with_state_tax(company_id:, state_tax_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ProductInvoiceRtcPending, ProductInvoiceRtcIssued
Issue an RTC product invoice scoped to a state tax registration.
-
#disable(company_id:, invoice_id:, reason: nil) ⇒ Nfe::Generated::ProductInvoiceRtcV1::DisablementResource?
Disable (inutilizar) a single invoice (async).
-
#disable_range(company_id:, data:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::DisablementResource?
Disable a range of invoice numbers (single number = same begin/last).
-
#discriminate(response) ⇒ Nfe::Resources::ProductInvoiceRtcPending, Nfe::Resources::ProductInvoiceRtcIssued
Interpret the emission response into the discriminated value object.
-
#download_correction_letter_pdf(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
CC-e DANFE PDF file resource (URI, not bytes).
-
#download_correction_letter_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
CC-e XML file resource (URI, not bytes).
-
#download_epec_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
Contingency authorization (EPEC) XML file resource (URI, not bytes).
-
#download_pdf(company_id:, invoice_id:, force: false) ⇒ Nfe::NfeFileResource
DANFE PDF file resource (URI, not bytes).
-
#download_rejection_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
Rejection XML file resource (URI, not bytes).
-
#download_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
Authorized NF-e XML file resource (URI, not bytes).
- #extract_invoice_id(location) ⇒ String?
- #file_resource(company_id:, invoice_id:, segment:, query: {}) ⇒ Nfe::NfeFileResource?
- #json_body(data) ⇒ String
- #json_headers ⇒ Hash[String, String]
-
#list(company_id:, environment:, starting_after: nil, ending_before: nil, limit: nil, q: nil) ⇒ Nfe::ListResponse
List RTC product invoices (cursor-style).
-
#list_events(company_id:, invoice_id:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::InvoiceEventsResource?
List fiscal events of an invoice.
-
#list_items(company_id:, invoice_id:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::InvoiceItemsResource?
List items of an invoice.
- #list_query(starting_after:, ending_before:, limit:, q:) ⇒ Hash[Symbol, untyped]
- #require_environment(environment) ⇒ void
-
#retrieve(company_id:, invoice_id:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::InvoiceResource?
Retrieve an RTC product invoice by id.
-
#send_correction_letter(company_id:, invoice_id:, reason:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::RequestCancellationResource?
Send a correction letter (CC-e).
- #validate_correction_reason(reason) ⇒ void
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
39 40 41 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 39 def api_family :cte end |
#api_version ⇒ String
The :cte host serves the v2 API; paths embed /v2 explicitly, so no
version segment is auto-prefixed.
45 46 47 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 45 def api_version "" end |
#base_path(company_id) ⇒ String
261 262 263 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 261 def base_path(company_id) "/v2/companies/#{company_id}/productinvoices" end |
#build_pending(response) ⇒ Nfe::Resources::ProductInvoiceRtcPending
Build a Nfe::Resources::ProductInvoiceRtcPending from a 202 response, or raise when the Location header is missing/unparsable.
312 313 314 315 316 317 318 319 320 321 322 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 312 def build_pending(response) location = response.location invoice_id = extract_invoice_id(location) if location.nil? || location.empty? || invoice_id.nil? raise Nfe::InvoiceProcessingError.new( "Resposta 202 sem Location utilizável: não é possível identificar a NF-e em processamento.", status_code: response.status, response_headers: response.headers ) end ProductInvoiceRtcPending.new(invoice_id: invoice_id, location: location) end |
#cancel(company_id:, invoice_id:, reason: nil) ⇒ Nfe::Generated::ProductInvoiceRtcV1::RequestCancellationResource?
Cancel an RTC product invoice (async); reason forwarded as a query
param. Hydrates
Generated::ProductInvoiceRtcV1::RequestCancellationResource.
139 140 141 142 143 144 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 139 def cancel(company_id:, invoice_id:, reason: nil) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = delete("#{base_path(cid)}/#{iid}", query: { reason: reason }.compact) hydrate(Nfe::Generated::ProductInvoiceRtcV1::RequestCancellationResource, parse_json(response.body)) end |
#create(company_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ProductInvoiceRtcPending, ProductInvoiceRtcIssued
Issue an RTC product invoice (NF-e/NFC-e). Returns a discriminated result: a Nfe::Resources::ProductInvoiceRtcPending on HTTP 202 or a Nfe::Resources::ProductInvoiceRtcIssued (hydrating Generated::ProductInvoiceRtcV1::InvoiceResource) on 201.
data is a Hash with camelCase keys. The generated request DTO
Generated::ProductInvoiceRtcV1::ProductInvoiceRequest documents
the expected payload SHAPE; it is NOT accepted as input (the generated
DTOs deserialize only and have no camelCase serialization path). The RTC
layout is selected by the presence of the item-level IBSCBS group
(+items.tax.IBSCBS+); NF-e (mod 55) vs NFC-e (mod 65) follows the
payload shape. Same endpoint as the classic resource.
69 70 71 72 73 74 75 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 69 def create(company_id:, data:, idempotency_key: nil, request_options: nil) cid = Nfe::IdValidator.company_id(company_id) response = post(base_path(cid), 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) ⇒ ProductInvoiceRtcPending, ProductInvoiceRtcIssued
Issue an RTC product invoice scoped to a state tax registration.
data is a Hash with camelCase keys (see #create for the payload
shape and RTC-layout selection notes).
88 89 90 91 92 93 94 95 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 88 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("/v2/companies/#{cid}/statetaxes/#{sid}/productinvoices", body: json_body(data), headers: json_headers, idempotency_key: idempotency_key, request_options: ) discriminate(response) end |
#disable(company_id:, invoice_id:, reason: nil) ⇒ Nfe::Generated::ProductInvoiceRtcV1::DisablementResource?
Disable (inutilizar) a single invoice (async). reason optional;
forwarded as a query param. Hydrates
Generated::ProductInvoiceRtcV1::DisablementResource.
240 241 242 243 244 245 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 240 def disable(company_id:, invoice_id:, reason: nil) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = post("#{base_path(cid)}/#{iid}/disablement", query: { reason: reason }.compact) hydrate(Nfe::Generated::ProductInvoiceRtcV1::DisablementResource, parse_json(response.body)) end |
#disable_range(company_id:, data:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::DisablementResource?
Disable a range of invoice numbers (single number = same begin/last).
data is a Hash with camelCase keys.
253 254 255 256 257 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 253 def disable_range(company_id:, data:) cid = Nfe::IdValidator.company_id(company_id) response = post("#{base_path(cid)}/disablement", body: json_body(data), headers: json_headers) hydrate(Nfe::Generated::ProductInvoiceRtcV1::DisablementResource, parse_json(response.body)) end |
#discriminate(response) ⇒ Nfe::Resources::ProductInvoiceRtcPending, Nfe::Resources::ProductInvoiceRtcIssued
Interpret the emission response into the discriminated value object.
302 303 304 305 306 307 308 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 302 def discriminate(response) return build_pending(response) if response.status == 202 ProductInvoiceRtcIssued.new( resource: hydrate(Nfe::Generated::ProductInvoiceRtcV1::InvoiceResource, parse_json(response.body)) ) end |
#download_correction_letter_pdf(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
CC-e DANFE PDF file resource (URI, not bytes).
221 222 223 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 221 def download_correction_letter_pdf(company_id:, invoice_id:) file_resource(company_id: company_id, invoice_id: invoice_id, segment: "correctionletter/pdf") end |
#download_correction_letter_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
CC-e XML file resource (URI, not bytes).
228 229 230 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 228 def download_correction_letter_xml(company_id:, invoice_id:) file_resource(company_id: company_id, invoice_id: invoice_id, segment: "correctionletter/xml") end |
#download_epec_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
Contingency authorization (EPEC) XML file resource (URI, not bytes).
197 198 199 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 197 def download_epec_xml(company_id:, invoice_id:) file_resource(company_id: company_id, invoice_id: invoice_id, segment: "xml-epec") end |
#download_pdf(company_id:, invoice_id:, force: false) ⇒ Nfe::NfeFileResource
DANFE PDF file resource (URI, not bytes). force regenerates the PDF.
175 176 177 178 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 175 def download_pdf(company_id:, invoice_id:, force: false) file_resource(company_id: company_id, invoice_id: invoice_id, segment: "pdf", query: { force: force }.compact) end |
#download_rejection_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
Rejection XML file resource (URI, not bytes).
190 191 192 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 190 def download_rejection_xml(company_id:, invoice_id:) file_resource(company_id: company_id, invoice_id: invoice_id, segment: "xml-rejection") end |
#download_xml(company_id:, invoice_id:) ⇒ Nfe::NfeFileResource
Authorized NF-e XML file resource (URI, not bytes).
183 184 185 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 183 def download_xml(company_id:, invoice_id:) file_resource(company_id: company_id, invoice_id: invoice_id, segment: "xml") end |
#extract_invoice_id(location) ⇒ String?
324 325 326 327 328 329 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 324 def extract_invoice_id(location) return nil if location.nil? match = location.match(%r{productinvoices/([a-z0-9-]+)}i) match ? match[1] : nil end |
#file_resource(company_id:, invoice_id:, segment:, query: {}) ⇒ Nfe::NfeFileResource?
294 295 296 297 298 299 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 294 def file_resource(company_id:, invoice_id:, segment:, query: {}) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = get("#{base_path(cid)}/#{iid}/#{segment}", query: query) hydrate(Nfe::NfeFileResource, parse_json(response.body)) end |
#json_body(data) ⇒ String
269 270 271 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 269 def json_body(data) JSON.generate(data) end |
#json_headers ⇒ Hash[String, String]
265 266 267 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 265 def json_headers { "Content-Type" => "application/json" } end |
#list(company_id:, environment:, starting_after: nil, ending_before: nil, limit: nil, q: nil) ⇒ Nfe::ListResponse
List RTC product invoices (cursor-style). environment is REQUIRED.
108 109 110 111 112 113 114 115 116 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 108 def list(company_id:, environment:, starting_after: nil, ending_before: nil, limit: nil, q: nil) cid = Nfe::IdValidator.company_id(company_id) require_environment(environment) query = list_query(starting_after: starting_after, ending_before: ending_before, limit: limit, q: q).merge(environment: environment) response = get(base_path(cid), query: query) hydrate_list(Nfe::Generated::ProductInvoiceRtcV1::InvoiceResource, parse_json(response.body), wrapper_key: "productInvoices") end |
#list_events(company_id:, invoice_id:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::InvoiceEventsResource?
List fiscal events of an invoice. Hydrates Generated::ProductInvoiceRtcV1::InvoiceEventsResource.
165 166 167 168 169 170 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 165 def list_events(company_id:, invoice_id:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = get("#{base_path(cid)}/#{iid}/events") hydrate(Nfe::Generated::ProductInvoiceRtcV1::InvoiceEventsResource, parse_json(response.body)) end |
#list_items(company_id:, invoice_id:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::InvoiceItemsResource?
List items of an invoice. Hydrates Generated::ProductInvoiceRtcV1::InvoiceItemsResource.
152 153 154 155 156 157 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 152 def list_items(company_id:, invoice_id:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = get("#{base_path(cid)}/#{iid}/items") hydrate(Nfe::Generated::ProductInvoiceRtcV1::InvoiceItemsResource, parse_json(response.body)) end |
#list_query(starting_after:, ending_before:, limit:, q:) ⇒ Hash[Symbol, untyped]
279 280 281 282 283 284 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 279 def list_query(starting_after:, ending_before:, limit:, q:) { startingAfter: starting_after, endingBefore: ending_before, limit: limit, q: q }.compact end |
#require_environment(environment) ⇒ void
This method returns an undefined value.
273 274 275 276 277 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 273 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::Generated::ProductInvoiceRtcV1::InvoiceResource?
Retrieve an RTC product invoice by id.
124 125 126 127 128 129 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 124 def retrieve(company_id:, invoice_id:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = get("#{base_path(cid)}/#{iid}") hydrate(Nfe::Generated::ProductInvoiceRtcV1::InvoiceResource, parse_json(response.body)) end |
#send_correction_letter(company_id:, invoice_id:, reason:) ⇒ Nfe::Generated::ProductInvoiceRtcV1::RequestCancellationResource?
Send a correction letter (CC-e). reason must be 15..1000 chars; the
length is validated client-side before any HTTP request.
209 210 211 212 213 214 215 216 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 209 def send_correction_letter(company_id:, invoice_id:, reason:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) validate_correction_reason(reason) response = put("#{base_path(cid)}/#{iid}/correctionletter", body: json_body({ reason: reason }), headers: json_headers) hydrate(Nfe::Generated::ProductInvoiceRtcV1::RequestCancellationResource, parse_json(response.body)) end |
#validate_correction_reason(reason) ⇒ void
This method returns an undefined value.
286 287 288 289 290 291 292 |
# File 'lib/nfe/resources/product_invoices_rtc.rb', line 286 def validate_correction_reason(reason) length = reason.to_s.length return if length.between?(15, 1000) raise Nfe::InvalidRequestError, "motivo da carta de correção deve conter entre 15 e 1000 caracteres" end |