Skip to content

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 23:21
· 20 commits to main since this release
0064ceb

Minor Changes

  • #25 8fab024 Thanks @Chelu97! - Add series.update(series, body?, config?) (PUT /v1/series/{series}, scope series:write) and re-pin spec/openapi.json from the current public contract (571 operations: 1 added, none removed). src/generated/ and src/resources/ are regenerated.

    New in the client:

    • series.update edits a series with a partial body: name, code, counter_reset (never, annual or monthly), number_format, initial_number, invoice_kind and the deprecated year_reset. document_type is not editable. It answers the updated Series. The new type UpdateSeriesRequest is exported from @factuarea/sdk.
    • Each fiscal guard of the numbering arrives as ValidationError with code business_rule_violation and a subcode: series_code_immutable_with_documents, series_format_immutable_with_documents, series_locked_by_verifactu, series_initial_number_creates_gap, series_invoice_kind_locked and series_default_kind_change. Invalid values answer parameter_invalid_value.
    • Changing only counter_reset also emits the webhook series.updated. PATCH and DELETE on a series keep answering 405 series_immutable, now with Allow: GET, PUT; archive a series instead of deleting it.
    • invoices.activities publishes more event_type values with an exact metadata contract: the result of each AEAT submission (verifactu.record_accepted, verifactu.record_rejected, verifactu.transmission_failed, verifactu.transmission_blocked), invoice.email_failed, invoice.public_link_viewed and the payment events payment.payment_created, payment.payment_reversed and payment.payment_updated, whose provider is the gateway (stripe, gocardless, monei, woocommerce or shopify) or null for a manual payment.
    • VeriFactuRecord gains the required aeat_warning_requires_subsanation (boolean | null). Code that builds VeriFactuRecord objects by hand, such as test fixtures typed as VeriFactuRecord, must add it.
  • #25 dab5844 Thanks @Chelu97! - Add unattended checkout (self-service kiosks and vending machines) and the VERI*FACTU remission controls, and re-pin spec/openapi.json from the current public contract (570 operations: 6 added, none removed). src/generated/ and src/resources/ are regenerated.

    New in the client:

    • invoices.create issues a paid simplified invoice in one idempotent call. The request accepts type (F1 or F2), prices_include_tax, payment (method, paid_at, reference), operation_on and the options register_verifactu and wait_for_pdf; client_id is optional, so an F2 without it is an anonymous ticket. The response is the new InvoiceWithCheckoutBlocks type: the invoice plus verifactu (status registered or failed, error_code, aeat_status, huella, qr_url, qr_png_base64, legend, csv), pdf (status, signed url, expires_at) and public_url.
    • A late retry with the same external_id answers 200 with Idempotent-Replayed: true and the invoice already issued. invoices.create returns the same body for 201 and 200; call factuarea.http.request when you need the status or the header. A different type or total answers 409 idempotency_key_reused with subcode unattended_replay_mismatch, and a request still in flight answers 409 resource_locked; both arrive as ConflictError with code, subcode and param.
    • invoices.pdf and invoices.pdfLink accept format: a4 (default), ticket_80 or ticket_58. invoices.pdfLink(invoice, params?, config?) keeps the previous invoices.pdfLink(invoice, config?) call working: a second argument made only of request-option keys (headers, timeout, maxRetries, idempotencyKey) is still read as the options, and any other object is the query.
    • invoices.annul accepts revert_collections, which reverts every live payment (reason issued_in_error) and annuls the invoice atomically. invoices.canAnnul also returns requires_collection_reversal and active_collections_amount.
    • invoices.corrective lines accept unit, regime_key, exemption_reason and exemption_reason_text; an omitted value is inherited from the original line. The conversion of a quote, a proforma or a delivery note can return warnings and warning_codes (zero_rate_line_without_exemption).
    • Invoice gains operation_on.
    • Series carry a purpose: Series.invoice_kind is complete, simplified, corrective or simplified_corrective, and null for a series that is not of invoices. series.create accepts invoice_kind. series.list, series.default and series.active accept an invoice_kind filter, and series.active also takes document_type; series.active(params?, config?) keeps the series.active(config?) call working with the same rule as invoices.pdfLink.
    • series_id is optional and nullable in invoices.create. invoices.update accepts type (F1 or F2). invoices.corrective accepts correction_nature (I or S) and series_id. invoices.duplicate and series.active document a 422 response.
    • contacts.imports.show retrieves a contact import (BusinessContactImport), and contacts.imports.errors downloads its errors as CSV and returns a BinaryResponse. BusinessContactImportPreview gains import_uuid, added_count, skipped_count, failed_count, unprocessed_count, status and failure_reason, so code that builds that type by hand must add them; its rows gain an optional result.
    • The types BusinessContactImport, CreateCorrectiveInvoiceRequest, CreateSeriesRequest and UpdateInvoiceRequest are exported from @factuarea/sdk.
    • verifactu.records.retryBlocked reactivates every blocked record at once. VeriFactuRecord gains aeat_error_code, is_blocked, block_reason and can_subsanar, and verifactu.records.subsanar now returns the id of the new record. VeriFactuStats gains pending_incident_count, blocked_incident_count and oldest_pending_at.
    • verifactu.representation (show, register, revoke) manages the representation that enables remission by a third party. VeriFactuConfig gains remission_mode and the active_representation_* fields, and verifactu.settings accepts remission_mode.
    • FactuareaError.lineIndex carries error.line_index, the zero-based position of the document line a domain rule rejected, the N of lines.N.tax_rate. It is null for any other error.
    • The types CreateInvoiceRequest, InvoiceWithCheckoutBlocks, AnnulInvoiceV1Request, CanAnnulInvoice, CompanyRepresentation, RegisterCompanyRepresentationV1Request, RemissionMode, RepresentationKind, VeriFactuConfig, VeriFactuRecord and VeriFactuStats are exported from @factuarea/sdk.

    Breaking changes (the SDK is in 0.x, so they land in a minor):

    • A sale line with no tax_rate, no referenced tax and no product with a tax no longer receives an implicit 21 %. It takes the company's default VAT for the document, or the request is rejected with 422 missing_required_param, param lines.N.tax_rate and line_index N.
    • Operations that issue an invoice (invoices.create when it issues, issue, corrective, substituteSimplified, and send and markSent when they issue) can answer 422 verifactu_not_eligible when a field does not fit the AEAT billing record: a customer name over 120 characters, a Spanish tax ID that is not 9 characters, an invoice number with characters the AEAT does not accept, or more than 12 tax breakdowns. error.param says which (client_id, series_id, original_invoice_id, simplified_invoice_uuids, company_name, lines, total or type). No number is consumed and the invoice stays as it was, so correct the data and repeat. In bulkCreate and bulkStatus the rejection appears per element in failures.
    • Issuing and annulling (annul, void) answer 422 verifactu_not_eligible with subcode signing_certificate_unavailable for a company that has enabled VeriFactu in NO VERIFACTU mode and has no usable certificate, until one is uploaded. error.param is certificate, representation or system_certificate. Companies with VeriFactu disabled and companies in VERIFACTU mode are not affected.
    • verifactu.records.retry no longer answers max_retries_exceeded: a record is retried without a cap while the incident lasts.
    • Invoice gains the required operation_on (string | null). Code that builds Invoice objects by hand, such as test fixtures typed as Invoice, must add it.
    • The payment reversal reason gains issued_in_error in InvoicePaymentDetail.reversal_reason and in the payment.reversed event, so an exhaustive switch over it needs a new case. It cannot be requested for a single payment with paymentsRevert.