Class: Nfe::Resources::ServiceInvoices
- Inherits:
-
AbstractResource
- Object
- AbstractResource
- Nfe::Resources::ServiceInvoices
- Defined in:
- lib/nfe/resources/service_invoices.rb,
sig/nfe/resources/service_invoices.rbs
Overview
Service invoices (NFS-e) resource for the :main host family
(+https://api.nfe.io/v1/...+). This is the canonical emission resource of
the platform.
Emission is typically asynchronous: #create returns either a ServiceInvoicePending (HTTP 202, queued) or a ServiceInvoiceIssued (HTTP 201, materialized). There is no +create_and_wait+/+create_batch+ in v1.0 — poll manually:
result = client.service_invoices.create(company_id: id, data: payload)
if result.pending?
loop do
status = client.service_invoices.get_status(company_id: id, invoice_id: result.invoice_id)
break if status.complete?
sleep 2
end
end
Defined Under Namespace
Classes: StatusResult
Constant Summary collapse
- FAILED_STATUSES =
%w[IssueFailed CancelFailed].freeze
Instance Attribute Summary
Attributes inherited from AbstractResource
Instance Method Summary collapse
- #api_family ⇒ Symbol
-
#build_pending(response) ⇒ Nfe::Resources::ServiceInvoicePending
Build a ServiceInvoicePending from a 202 response, or raise when the Location header is missing/unparsable.
-
#cancel(company_id:, invoice_id:) ⇒ Nfe::ServiceInvoice
Cancel a service invoice (synchronous); returns the updated model.
-
#create(company_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ServiceInvoicePending, ServiceInvoiceIssued
Create (emit) a service invoice.
-
#discriminate(response) ⇒ Nfe::Resources::ServiceInvoicePending, Nfe::Resources::ServiceInvoiceIssued
Interpret the emission response into the discriminated value object.
-
#download_document(company_id:, invoice_id:, ext:, accept:) ⇒ String
GET the single-invoice or bulk document path and return binary bytes.
-
#download_pdf(company_id:, invoice_id: nil) ⇒ String
Download the invoice PDF (or the company ZIP when
invoice_idis nil). -
#download_xml(company_id:, invoice_id: nil) ⇒ String
Download the invoice XML (or the company ZIP when
invoice_idis nil). -
#extract_invoice_id(location) ⇒ String?
Extract the trailing id from a
Locationpath. -
#get_status(company_id:, invoice_id:) ⇒ StatusResult
Status snapshot derived from #retrieve (Node parity — no extra HTTP).
- #json_body(data) ⇒ String
- #json_headers ⇒ Hash[String, String]
-
#list(company_id:, **options) ⇒ Nfe::ListResponse
List service invoices (page-style pagination plus date filters).
-
#list_query(options) ⇒ Hash[Symbol, untyped]
Map snake_case list options onto the API's camelCase query parameters, dropping nil values.
-
#retrieve(company_id:, invoice_id:) ⇒ Nfe::ServiceInvoice
Retrieve a service invoice by id.
-
#send_email(company_id:, invoice_id:) ⇒ Hash
E-mail the invoice to the borrower.
Methods inherited from AbstractResource
#api_version, #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
50 51 52 |
# File 'lib/nfe/resources/service_invoices.rb', line 50 def api_family :main end |
#build_pending(response) ⇒ Nfe::Resources::ServiceInvoicePending
Build a Nfe::Resources::ServiceInvoicePending from a 202 response, or raise when the Location header is missing/unparsable.
205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/nfe/resources/service_invoices.rb', line 205 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 NFS-e em processamento.", status_code: response.status, response_headers: response.headers ) end ServiceInvoicePending.new(invoice_id: invoice_id, location: location) end |
#cancel(company_id:, invoice_id:) ⇒ Nfe::ServiceInvoice
Cancel a service invoice (synchronous); returns the updated model.
108 109 110 111 112 113 |
# File 'lib/nfe/resources/service_invoices.rb', line 108 def cancel(company_id:, invoice_id:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = delete("/companies/#{cid}/serviceinvoices/#{iid}") hydrate(Nfe::ServiceInvoice, parse_json(response.body)) end |
#create(company_id:, data:, idempotency_key: nil, request_options: nil) ⇒ ServiceInvoicePending, ServiceInvoiceIssued
Create (emit) a service invoice. Returns a discriminated result: a
Nfe::Resources::ServiceInvoicePending on HTTP 202 (queued, invoice_id parsed from the
Location header) or a Nfe::Resources::ServiceInvoiceIssued on HTTP 201 (materialized).
66 67 68 69 70 71 72 73 |
# File 'lib/nfe/resources/service_invoices.rb', line 66 def create(company_id:, data:, idempotency_key: nil, request_options: nil) cid = Nfe::IdValidator.company_id(company_id) response = post("/companies/#{cid}/serviceinvoices", body: json_body(data), headers: json_headers, idempotency_key: idempotency_key, request_options: ) discriminate(response) end |
#discriminate(response) ⇒ Nfe::Resources::ServiceInvoicePending, Nfe::Resources::ServiceInvoiceIssued
Interpret the emission response into the discriminated value object.
197 198 199 200 201 |
# File 'lib/nfe/resources/service_invoices.rb', line 197 def discriminate(response) return build_pending(response) if response.status == 202 ServiceInvoiceIssued.new(resource: hydrate(Nfe::ServiceInvoice, parse_json(response.body))) end |
#download_document(company_id:, invoice_id:, ext:, accept:) ⇒ String
GET the single-invoice or bulk document path and return binary bytes.
185 186 187 188 189 190 191 192 193 194 |
# File 'lib/nfe/resources/service_invoices.rb', line 185 def download_document(company_id:, invoice_id:, ext:, accept:) cid = Nfe::IdValidator.company_id(company_id) path = if invoice_id.nil? "/companies/#{cid}/serviceinvoices/#{ext}" else iid = Nfe::IdValidator.invoice_id(invoice_id) "/companies/#{cid}/serviceinvoices/#{iid}/#{ext}" end download(path, headers: { "Accept" => accept }) end |
#download_pdf(company_id:, invoice_id: nil) ⇒ String
Download the invoice PDF (or the company ZIP when invoice_id is nil).
133 134 135 136 |
# File 'lib/nfe/resources/service_invoices.rb', line 133 def download_pdf(company_id:, invoice_id: nil) download_document(company_id: company_id, invoice_id: invoice_id, ext: "pdf", accept: "application/pdf") end |
#download_xml(company_id:, invoice_id: nil) ⇒ String
Download the invoice XML (or the company ZIP when invoice_id is nil).
143 144 145 146 |
# File 'lib/nfe/resources/service_invoices.rb', line 143 def download_xml(company_id:, invoice_id: nil) download_document(company_id: company_id, invoice_id: invoice_id, ext: "xml", accept: "application/xml") end |
#extract_invoice_id(location) ⇒ String?
Extract the trailing id from a Location path.
218 219 220 221 222 223 |
# File 'lib/nfe/resources/service_invoices.rb', line 218 def extract_invoice_id(location) return nil if location.nil? match = location.match(%r{serviceinvoices/([a-z0-9-]+)}i) match ? match[1] : nil end |
#get_status(company_id:, invoice_id:) ⇒ StatusResult
Status snapshot derived from #retrieve (Node parity — no extra HTTP).
153 154 155 156 157 158 159 160 161 |
# File 'lib/nfe/resources/service_invoices.rb', line 153 def get_status(company_id:, invoice_id:) invoice = retrieve(company_id: company_id, invoice_id: invoice_id) status = invoice&.flow_status || "WaitingSend" StatusResult.new( status: status, invoice: invoice, complete: Nfe::FlowStatus.terminal?(status), failed: FAILED_STATUSES.include?(status) ) end |
#json_body(data) ⇒ String
169 170 171 |
# File 'lib/nfe/resources/service_invoices.rb', line 169 def json_body(data) JSON.generate(data) end |
#json_headers ⇒ Hash[String, String]
165 166 167 |
# File 'lib/nfe/resources/service_invoices.rb', line 165 def json_headers { "Content-Type" => "application/json" } end |
#list(company_id:, **options) ⇒ Nfe::ListResponse
List service invoices (page-style pagination plus date filters).
81 82 83 84 85 |
# File 'lib/nfe/resources/service_invoices.rb', line 81 def list(company_id:, **) cid = Nfe::IdValidator.company_id(company_id) response = get("/companies/#{cid}/serviceinvoices", query: list_query()) hydrate_list(Nfe::ServiceInvoice, parse_json(response.body), wrapper_key: "serviceInvoices") end |
#list_query(options) ⇒ Hash[Symbol, untyped]
Map snake_case list options onto the API's camelCase query parameters, dropping nil values.
175 176 177 178 179 180 181 182 |
# File 'lib/nfe/resources/service_invoices.rb', line 175 def list_query() { pageIndex: [:page_index], pageCount: [:page_count], issuedBegin: [:issued_begin], issuedEnd: [:issued_end], createdBegin: [:created_begin], createdEnd: [:created_end], hasTotals: [:has_totals] }.compact end |
#retrieve(company_id:, invoice_id:) ⇒ Nfe::ServiceInvoice
Retrieve a service invoice by id.
93 94 95 96 97 98 99 100 101 |
# File 'lib/nfe/resources/service_invoices.rb', line 93 def retrieve(company_id:, invoice_id:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = get("/companies/#{cid}/serviceinvoices/#{iid}") payload = parse_json(response.body) raise Nfe::NotFoundError, "nota de serviço #{iid} não encontrada" if payload.nil? hydrate(Nfe::ServiceInvoice, payload) end |
#send_email(company_id:, invoice_id:) ⇒ Hash
E-mail the invoice to the borrower. No e-mail list argument (Node parity).
120 121 122 123 124 125 126 |
# File 'lib/nfe/resources/service_invoices.rb', line 120 def send_email(company_id:, invoice_id:) cid = Nfe::IdValidator.company_id(company_id) iid = Nfe::IdValidator.invoice_id(invoice_id) response = put("/companies/#{cid}/serviceinvoices/#{iid}/sendemail") payload = parse_json(response.body) || {} { sent: payload.fetch("sent", response.success?), message: payload["message"] } end |