Invoicing
Issue invoices from sales, mark them as paid, and issue rectifying invoices.
Modules are installed from your Hub's marketplace. Sign up for a Hub to access this module.
Módulo invoice — facturación
Convierte ventas completadas en documentos fiscales numerados por serie (F1/F2/F3, R1–R5) e impone la inmutabilidad fiscal (RD 1007/2023): una factura emitida no se modifica ni se borra — se corrige con una rectificativa (R1, importes negados; una devolución parcial emite la suya por diferencias, prorrateando el desglose congelado) o se completa con una sustitutiva (F3, «el cliente pide factura de un tiquet»). Numeración monotónica por serie+año. La cuota del desglose se cierra una vez por clave fiscal (ADR-0123 §4), nunca sumando líneas.
Module id:
invoice. Depende de:taxes,sales(instalar invoice los auto-instala). Módulo híbrido: SQL + handler WASM (create_invoice,create_from_sale,substitute_from_invoice).
Documentación de usuario — docs/
Viaja dentro del módulo y se versiona con él: el asistente del hub (ADR-0282) la indexa por versión instalada y cita la de TU versión, no la de la última publicada. En inglés (idioma fuente).
| Fichero | Para qué |
|---|---|
docs/overview.md |
Qué hace y qué NO hace; los tipos F1/F2/F3/R1–R5 |
docs/screens.md |
Invoices y Settings (series): emitir, marcar pagada, rectificar, sustituir |
docs/concepts.md |
Rectificar vs sustituir, inmutabilidad, numeración por serie+año, 1 factura por origen, desglose con DOS ejes |
docs/limits.md |
Huecos conocidos (F3 sin botón, todo sale F2), permisos por acción y diagnóstico |
Qué expone hoy
| Tipo | Nombre | Permiso |
|---|---|---|
| query | invoice.list / .get / .lines / .by_source / .series.list |
invoice.view_invoice |
| command | invoice.create (WASM) |
invoice.add_invoice |
| command | invoice.create_from_sale (WASM, listener) |
invoice.add_invoice |
| command | invoice.substitute (WASM, ADR-0140) |
invoice.add_invoice |
| command | invoice.mark_paid |
invoice.add_invoice |
| command | invoice.rectify |
invoice.rectify_invoice |
| command | invoice.series.create / .update |
invoice.manage_series |
| escucha | sale.completed → invoice.create_from_sale |
— |
| emite | invoice.created, invoice.rectified |
— |
Navegación: erp-invoice-list («Invoices») y erp-invoice-settings («Settings» = gestor de series).
🧩 ADR-0223: la resolución de la regla fiscal vive UNA vez en
erplora_guest_sdk::tax, no aquí.
Layout
module.json # manifest (contrato técnico)
migrations/postgres/ # esquema §2.5 (hub_id + soft-delete + auditoría)
queries/*.sql # lecturas declarativas (:hub_id inyectado)
commands/*.sql # escrituras declarativas (las `_` son intenciones del WASM)
schemas/*.json # JSON Schemas de input (draft 2020-12)
handler/ # WASM Tier 2 → dist/handler.wasm
ui/ # Web Components (Lit/Ionic/OutfitKit)
docs/ # documentación de usuario + corpus del asistente
Estado y trabajo abierto
El estado vive en las Issues de este repo, no aquí. Huecos conocidos y documentados en
docs/limits.md: la UI no invoca invoice.substitute todavía, y document_type no viaja en
sale.completed, así que toda venta se factura como F2 (ADR-0140).
Doc de arquitectura: architecture/modules/invoice.md (cargarlo antes de tocar el módulo).
This module requires the following modules to be installed:
Sign in to leave a review
Share your experience with this module
User Reviews
No reviews yet
Be the first to review this module
chore(release): v1.2.32
chore(release): v1.2.31
chore(release): v1.2.30
chore(release): v1.2.29
chore(release): v1.2.28
chore(release): v1.2.27
chore(release): v1.2.26
chore(release): v1.2.25
chore(release): v1.2.24
fix(rectify): rectificar una factura nacida de una venta (invoice#5 D1/D2) (#60) Ningun tique de TPV se podia rectificar, o sea el camino normal de una devolucion. `rectify_insert.sql` copiaba `source_type, source_id` verbatim de la original, y `uq_invoice_source (hub_id, source_type, source_id) WHERE source_id IS NOT NULL` ya tenia esa tupla ocupada por la propia factura que se rectifica: violacion de unicidad y, con `transaction: true`, la cadena entera abortada. Solo funcionaba la factura MANUAL (`source_id` NULL, el indice parcial no aplica), que es justo la unica que probaba el e2e del hub. - La rectificativa deja de heredar el origen: `source_type='rectification'` y `source_id` NULL. No nace de una venta, nace de esta orden, asi que no tiene clave externa de la que ser idempotente. - El "una rectificativa por factura" pasa al esquema, sobre el enlace fiscal: `ux_invoice_rectifies`, indice unico parcial espejo de `ux_invoice_substitutes` (invoice#34). NO se reutiliza `uq_invoice_source`: ese significa "una factura por venta", no excluye filas soft-borradas, y colgar de el una regla fiscal la hace moverse cuando se mueva la de ventas. De paso evita que `by_source.sql` (ORDER BY created_at DESC LIMIT 1) resuelva venta -> factura -> QR devolviendo la RECTIFICATIVA. - `tax_breakdown` deja de ser `'{}'`. `'{}'` no falla de forma ruidosa: `aeat.rs::desglose()` cae a un unico detalle con el tipo EFECTIVO, que en una factura mixta (21 % + 10 %) da ~19,1 % -- no es un tipo legal de IVA y la tumba el guard local `xsd.rs`. Ahora se COPIA del snapshot congelado en la original negando solo `base`, `quota` y `surcharge_quota`; el tipo no se niega. Nunca se re-deriva (ADR-0210) y se cierra una vez por TIPO, no por linea (ADR-0123 §4). Cubre el formato array actual y el objeto legacy. Tests: `tests/rectify_sale_born.postgres.test.py` contra Postgres 18 real -- reproduce el fallo original, y pina que la idempotencia de la VENTA sigue intacta, que el segundo intento lo rechaza la BASE DE DATOS, que el indice es por hub y parcial, y que el desglose negado suma al centimo con su cabecera. De paso, el binder en miniatura compartido por los tests de Postgres (`substitution_unique.postgres.test.py::bind`) ignoraba que `::` es el cast de Postgres y lo trataba como un `:name`, asi que convertia `(x)::numeric` en `(x):NULL`. El runtime SI lo trata bien (`hub/crates/db/src/lib.rs::translate`, es su primera regla), o sea que la miniatura estaba equivocada donde el runtime acierta. Corregido en la copia compartida, que es la que usan los cinco. Fuera de alcance, con su sitio: las LINEAS de la rectificativa (#59, necesita pasar el command a WASM: N lineas = N ids y un command declarativo recibe uno) y `TipoRectificativa`/`FacturasRectificadas` en el XML (hub#1023, el core). Closes #5 Co-authored-by: ioanbeilic <erplora.cloud@gmail.com>
chore(release): v1.2.22
chore(release): v1.2.21
chore(release): v1.2.20
chore(release): v1.2.19
chore(release): v1.2.18
chore(release): v1.2.17
chore(release): v1.2.16
chore(release): v1.2.15
chore(release): v1.2.14
chore(release): v1.2.13