Saltar a contenido

Modelo vigente

Reemplaza al modelo archivado en _archivo/datos/modelo-datos-legacy.md. Cuando una columna cambie, sincronizar este archivo y propagar a los backlogs P0 de la APK.


Modelo de datos

Documento técnico canónico — 2026-06-08 (sustituye a la versión v1)

Este documento es la fuente única de verdad del modelo de datos de IslaBox. Es la versión consolidada y limpia (anteriormente modelo-datos-v2.md).

Esta versión:

  • Elimina campos duplicados (ej. phone repetido en users).
  • Unifica el tipo de id a bigint autoincrement para todas las entidades de negocio.
  • Alinea todos los enums con estados.md.
  • Separa explícitamente tablas MVP vs Fase 2.
  • Documenta cada tabla con su propósito, índices y reglas asociadas.

Relación: la versión anterior está archivada como ../_archivo/datos/modelo-datos-legacy.md y no debe usarse como referencia.


1. Convenciones

Símbolo Significado
PK Primary Key
FK Foreign Key
UK Unique constraint
IX Index (para queries frecuentes)
MVP Tabla/campo disponible en MVP
F2 Solo Fase 2
🔵 Soft delete (campo deleted_at)
NOT NULL

Tipos estándar

Tipo Postgres Uso
bigint IDs de negocio (autoincrement)
uuid Solo file_attachments.id (para distribución de IDs)
varchar(N) Texto corto con longitud definida
text Texto largo sin límite
boolean Flags
decimal(p,s) Montos y medidas
timestamp Fecha y hora UTC
date Solo fecha
enum Valores discretos (definidos en Postgres)
jsonb Datos semi-estructurados
array Arreglos de valores
inet Direcciones IP

Convenciones de nombres

  • Tablas en plural (users, physical_packages).
  • Columnas en snake_case.
  • Timestamps: created_at, updated_at, deleted_at.
  • Foreign keys: <recurso>_id (ej. user_id).
  • Enums: prefijo por tabla + nombre (package_status, shipment_status).

2. Núcleo de identidad

2.1 users (MVP)

Personas registradas en la plataforma (usuarios finales y personal interno).

Campo Tipo Nulo Notas
id bigint PK, autoincrement
email varchar(255) UK, validado en app
email_verified boolean Default: false
phone varchar(20) UK, formato E.164 con +1 (RN-001)
phone_verified boolean Default: false
full_name varchar(255)
country_code char(2) Default: US, no editable
password_hash varchar(255) bcrypt cost 12
role enum user / operator / admin / sysadmin
referral_code varchar(20) UK, generado al registrarse
referred_by bigint FK → users.id
level integer Default: 1 (Fase 2)
is_active boolean Default: true
created_at timestamp
updated_at timestamp
deleted_at timestamp 🔵 Soft delete

Índices: email, phone, referral_code, role, is_active, created_at.

2.2 api_tokens (MVP)

Tokens JWT emitidos para sesiones.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
token_hash varchar(255) UK, SHA-256 del token
name varchar(100) Para identificar (ej. "iPhone de María")
scopes varchar[] Ej: ["read:packages", "write:incidents"]
last_used_at timestamp
expires_at timestamp Default: now() + 30 días
created_at timestamp
revoked_at timestamp Soft revocation

Índices: user_id, token_hash, expires_at, revoked_at.

2.3 device_tokens (MVP)

Tokens FCM/APNS para push notifications.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
token varchar(500) UK, el token del push provider
platform enum ios / android / web
device_id varchar(255) Identificador del device
is_active boolean Default: true
created_at timestamp
updated_at timestamp

3. Casillero

3.1 locker_codes (MVP)

Identificadores únicos de casillero CP-XXXXXX-D.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
prefix varchar(10) Default: CP
sequential integer Secuencial dentro del prefijo
check_digit integer Dígito verificador mod-10 (RN-002)
full_code varchar(20) UK, CP-001042-8
status enum active / inactive / blocked
issued_at timestamp
created_at timestamp
updated_at timestamp

Índices: UK(prefix, sequential), UK(full_code), user_id.

Reglas: ver RN-002, RN-003 en reglas-negocio.md.


4. Direcciones y contactos

4.1 addresses (MVP)

Direcciones de casillero, facturación y destinatarios.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
address_type enum locker / billing / recipient
full_name varchar(255)
phone varchar(20) E.164
address_line1 varchar(500)
address_line2 varchar(500)
city varchar(100)
state varchar(100)
zip_code varchar(20)
country varchar(2) ISO 3166-1 alpha-2
province varchar(100) Solo Cuba
municipality varchar(100) Solo Cuba
delivery_references text
is_default boolean Default: false
created_at timestamp
updated_at timestamp

4.2 senders (MVP)

Remitentes en EE.UU. (opcional, default = datos del usuario).

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id (dueño del registro)
full_name varchar(255)
phone varchar(20) E.164 con +1
email varchar(255)
address_line1 varchar(500)
city varchar(100)
state varchar(100)
zip_code varchar(20)
relationship_to_shipment varchar(100)
notes text
created_at timestamp

4.3 recipients (MVP)

Destinatarios en Cuba.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id (usuario que lo gestiona)
full_name varchar(255)
identity_document varchar(50) CI cubano
phone varchar(20) E.164 con +53 o +1
alternate_phone varchar(20)
address_line1 varchar(500) Dirección en Cuba
province varchar(100) Provincia cubana
municipality varchar(100)
delivery_references text
is_default boolean Default: true (el propio usuario)
created_at timestamp
updated_at timestamp

5. KYC

5.1 kyc_records (MVP)

Un KYC por usuario.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id, UK
document_type enum passport / national_id / drivers_license
document_number varchar(50)
document_front_file_id uuid FK → file_attachments.id
document_back_file_id uuid FK → file_attachments.id
selfie_file_id uuid FK → file_attachments.id
residence_address text
province varchar(100) Estado/provincia de residencia
municipality varchar(100) Ciudad/municipio
zip_code varchar(20)
status enum Ver estados.md §KYC
submitted_at timestamp
reviewed_by bigint FK → users.id
reviewed_at timestamp
rejection_reason text
expires_at timestamp Default: now() + 2 años
created_at timestamp
updated_at timestamp

Reglas: ver RN-040 a RN-045.


6. Prealerta (reporte de compra)

6.1 purchase_reports (MVP)

Reportes de compra antes de que llegue el paquete.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
marketplace enum amazon / shein / temu / other
order_number varchar(100)
total_declared_value decimal(10,2)
total_declared_currency varchar(10) Default: USD
status enum Ver estados.md §prealerta
recipient_id bigint FK → recipients.id
sender_id bigint FK → senders.id
wants_consolidation boolean Default: false
notes text
created_at timestamp
updated_at timestamp

6.2 purchase_items (MVP)

Ítems individuales de un reporte de compra.

Campo Tipo Nulo Notas
id bigint PK
purchase_report_id bigint FK → purchase_reports.id
description text
quantity integer Default: 1
unit_value decimal(10,2)
currency varchar(10) Default: USD
category_id bigint FK → customs_categories.id
product_url varchar(1000)
seller varchar(255)
created_at timestamp

6.3 tracking_numbers (MVP)

Campo Tipo Nulo Notas
id bigint PK
purchase_report_id bigint FK → purchase_reports.id
tracking_number varchar(100)
carrier enum ups / usps / fedex / dhl / other
estimated_arrival date
last_polled_at timestamp Última consulta al carrier (F2)
created_at timestamp

7. Almacén y paquetes

7.1 warehouse_locations (MVP)

Ubicaciones físicas en el almacén de Miami.

Campo Tipo Nulo Notas
id bigint PK
warehouse_code varchar(50) Default: MIA01
zone varchar(10) AF (ver manual-almacen §2.6)
shelf varchar(10)
bin varchar(10)
location_code varchar(20) UK, A-03-B
is_occupied boolean Default: false
created_at timestamp

7.2 physical_packages (MVP)

Paquete físico recibido en almacén.

Campo Tipo Nulo Notas
id bigint PK
locker_code_id bigint FK → locker_codes.id
purchase_report_id bigint FK → purchase_reports.id
tracking_number_id bigint FK → tracking_numbers.id
warehouse_location_id bigint FK → warehouse_locations.id
status enum Ver estados.md §paquete
received_at timestamp
received_by bigint FK → users.id (operador)
weight_kg decimal(8,3)
length_cm decimal(8,2)
width_cm decimal(8,2)
height_cm decimal(8,2)
volumetric_weight_kg decimal(8,3) Calculado
billable_weight_kg decimal(8,3) max(real, volumétrico)
storage_days integer Default: 0, calculado
storage_charge_total decimal(10,2) Default: 0
customs_category_id bigint FK → customs_categories.id
customs_declared_value decimal(10,2)
notes_internal text
created_at timestamp
updated_at timestamp

7.3 package_events (MVP)

Historial de eventos de un paquete (timeline).

Campo Tipo Nulo Notas
id bigint PK
physical_package_id bigint FK → physical_packages.id
status enum Estado resultante
description text
operator_id bigint FK → users.id
visible_to_user boolean Default: true
source enum operator / user / agency / system
metadata jsonb Datos extra del evento
created_at timestamp

7.4 package_photos (MVP)

Campo Tipo Nulo Notas
id bigint PK
physical_package_id bigint FK → physical_packages.id
file_attachment_id uuid FK → file_attachments.id, UK
photo_type enum reception / inspection / return / damage / consolidation
caption varchar(255)
created_at timestamp

8. Aduana y categorías

8.1 customs_categories (MVP)

Catálogo de categorías aduaneras. Tabla canónica (antes había duplicado con categories).

Campo Tipo Nulo Notas
id bigint PK
code varchar(50) UK, ej. ropa, electronicos
name varchar(100) Nombre visible
description text
accepted enum yes / conditional / no
requires_invoice boolean Default: false
requires_review boolean Default: false
risk_level enum low / medium / high / prohibited
allows_air boolean Default: true
allows_sea boolean Default: true
duty_percentage decimal(5,2) Porcentaje de arancel
user_message text Mensaje al usuario
operator_message text Nota interna
is_active boolean Default: true
created_at timestamp
updated_at timestamp

Tabla categories (legacy)

La tabla categories del modelo v1 queda deprecated y debe eliminarse en migración. La entidad canónica es customs_categories.


9. Consolidación y cotización

9.1 consolidations (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
status enum Ver estados.md §consolidación
total_value decimal(10,2)
total_weight_kg decimal(8,3)
recipient_id bigint FK → recipients.id
shipping_method enum air / sea
notes text
created_at timestamp
updated_at timestamp

9.2 consolidation_packages (MVP)

Relación N:M entre consolidación y paquetes.

Campo Tipo Nulo Notas
id bigint PK
consolidation_id bigint FK → consolidations.id
physical_package_id bigint FK → physical_packages.id, UK con consolidation_id
added_at timestamp

Constraint check: un physical_package no puede estar en 2 consolidaciones activas (no canceladas) al mismo tiempo.

9.3 quotes (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
consolidation_id bigint FK → consolidations.id, UK
total_freight decimal(10,2)
total_customs decimal(10,2)
total_charges decimal(10,2)
total_payable decimal(10,2)
currency varchar(10) Default: USD
valid_until timestamp Vigencia 7 días
status enum pending / accepted / expired / superseded
accepted_at timestamp
created_at timestamp
updated_at timestamp

9.4 quote_items (MVP)

Desglose de los conceptos de la cotización.

Campo Tipo Nulo Notas
id bigint PK
quote_id bigint FK → quotes.id
concept enum freight / customs_duty / storage / consolidation_fee / service_inspection / service_repack / service_return / insurance / other
description varchar(255)
amount decimal(10,2)
quantity decimal(8,3) Default: 1
unit_price decimal(10,2)

10. Pagos y facturación

10.1 payments (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
quote_id bigint FK → quotes.id
consolidation_id bigint FK → consolidations.id
amount decimal(10,2)
currency varchar(10) Default: USD
payment_method enum card / bank_transfer / cash / credit
payment_provider varchar(50) stripe, manual, etc.
provider_reference varchar(255) UK
status enum Ver estados.md §pago
payment_method_mix jsonb Desglose de métodos
processed_at timestamp
failure_reason text
created_at timestamp
updated_at timestamp

10.2 payment_attempts (MVP)

Campo Tipo Nulo Notas
id bigint PK
payment_id bigint FK → payments.id
amount decimal(10,2)
status varchar(50)
provider_response jsonb
created_at timestamp

10.3 invoices (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
payment_id bigint FK → payments.id, UK
invoice_number varchar(50) UK, formato ISB-2026-00001
amount decimal(10,2)
currency varchar(10) Default: USD
pdf_file_id uuid FK → file_attachments.id
issued_at timestamp
created_at timestamp

10.4 charges (MVP)

Cargos individuales (almacenaje, servicios, etc.) que se incluyen en una cotización.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
consolidation_id bigint FK → consolidations.id
physical_package_id bigint FK → physical_packages.id
charge_type enum storage / inspection / repack / customs / delivery / other
amount decimal(10,2)
description text
status enum pending / applied / waived
applied_at timestamp
created_at timestamp

11. Envíos y despacho

11.1 shipments (MVP)

Campo Tipo Nulo Notas
id bigint PK
consolidation_id bigint FK → consolidations.id, UK
status enum Ver estados.md §envío
carrier varchar(100) agencia_aliada en MVP
master_guide varchar(100) UK
departure_date date
estimated_arrival date
actual_arrival date
customs_amount_total decimal(10,2)
customs_paid_at timestamp
recipient_id bigint FK → recipients.id (desnormalizado para histórico)
notes_internal text
created_at timestamp
updated_at timestamp

11.2 shipment_events (MVP)

Timeline del envío, alimentado por webhooks de la agencia y operadores.

Campo Tipo Nulo Notas
id bigint PK
shipment_id bigint FK → shipments.id
status enum Estado resultante
description text
location varchar(255)
operator_id bigint FK → users.id (si fue manual)
source enum operator / agency / system
metadata jsonb
created_at timestamp

12. Servicios adicionales

12.1 service_requests (MVP)

Solicitudes de servicios adicionales (inspección, reempaque, devolución).

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
physical_package_id bigint FK → physical_packages.id
service_type enum inspection / functional_test / repack / return
status enum Ver estados.md §servicios
description text
cost decimal(10,2)
cost_approved_at timestamp
started_at timestamp
completed_at timestamp
result text
evidence_file_ids uuid[] Array de FK → file_attachments.id
created_at timestamp
updated_at timestamp

Constraint: solo puede haber 1 service_request activo por physical_package (ver RN-050).

12.2 additional_services (MVP, lectura)

Vista materializada para queries rápidas (alternativa a service_requests agregados por paquete). Se calcula al final del sprint.


13. Incidencias

13.1 incidents (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id (si fue el usuario)
opened_by_operator_id bigint FK → users.id (si fue operador)
resource_type enum physical_package / consolidation / shipment / payment / user / other
resource_id bigint ID polimórfico
incident_type enum Ver incidencias-reclamos §2
status enum Ver incidencias-reclamos §3
description text
assigned_operator_id bigint FK → users.id
resolution text
refund_payment_id bigint FK → payments.id (si hubo reembolso)
created_at timestamp
updated_at timestamp
closed_at timestamp

13.2 incident_messages (MVP)

Campo Tipo Nulo Notas
id bigint PK
incident_id bigint FK → incidents.id
author_id bigint FK → users.id
author_type enum user / operator / admin / system
body text
is_internal boolean Default: false (visible al usuario)
created_at timestamp

13.3 incident_evidence (MVP)

Campo Tipo Nulo Notas
id bigint PK
incident_id bigint FK → incidents.id
file_attachment_id uuid FK → file_attachments.id
uploaded_by bigint FK → users.id
caption varchar(255)
created_at timestamp

14. Notificaciones

14.1 notifications (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id
notification_type varchar(50)
title varchar(255)
body text
data_payload jsonb
channel enum push / email / sms / in_app
status enum queued / sent / delivered / failed
sent_at timestamp
delivered_at timestamp
read_at timestamp
created_at timestamp

14.2 notification_delivery_log (MVP)

Log inmutable de cada intento de entrega.

Campo Tipo Nulo Notas
id bigint PK
notification_id bigint FK → notifications.id
channel enum
provider varchar(50) fcm / sendgrid / twilio
provider_response jsonb
status enum pending / success / failed
attempt_number integer
error_message text
created_at timestamp

14.3 notification_preferences (MVP)

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id, UK
preferences jsonb {type: {push: bool, email: bool, sms: bool}}
updated_at timestamp

15. Archivos

15.1 file_attachments (MVP)

Registro de todos los archivos subidos a MinIO/S3.

Campo Tipo Nulo Notas
id uuid PK (UUID para distribución)
owner_type enum user / operator / admin / system
owner_id bigint ID del dueño
bucket varchar(100)
object_key varchar(500) Path en MinIO
original_filename varchar(255)
mime_type varchar(100)
size_bytes bigint
checksum_sha256 varchar(64)
visibility enum private / public / signed_only
uploaded_by bigint FK → users.id
expires_at timestamp Para archivos temporales
created_at timestamp
deleted_at timestamp 🔵

15.2 file_access_logs (MVP)

Auditoría de accesos a archivos sensibles.

Campo Tipo Nulo Notas
id bigint PK
file_attachment_id uuid FK → file_attachments.id
accessed_by bigint FK → users.id
access_type enum read / download / upload / delete
ip_address inet
user_agent text
created_at timestamp

16. Webhooks externos

16.1 webhook_events (MVP)

Idempotencia de webhooks de Stripe y agencia aliada.

Campo Tipo Nulo Notas
id bigint PK
provider enum stripe / agency / whatsapp
event_id varchar(255) UK con provider
event_type varchar(100)
payload jsonb Crudo
signature varchar(500)
processed boolean Default: false
processed_at timestamp
error_message text
retry_count integer Default: 0
received_at timestamp
created_at timestamp

17. Auditoría y logs

17.1 audit_logs (MVP)

Log inmutable de todas las acciones críticas.

Campo Tipo Nulo Notas
id bigint PK
user_id bigint FK → users.id (puede ser null para acciones del sistema)
action varchar(100) package.received, payment.completed, etc.
entity_type varchar(100)
entity_id bigint
changes jsonb {before: {...}, after: {...}}
ip_address inet
user_agent text
request_id varchar(100) UUID del request HTTP
result enum success / failure / forbidden
created_at timestamp

Inmutabilidad

Esta tabla no debe permitir UPDATE ni DELETE. Se replica a S3 WORM mensualmente.


18. Configuración dinámica (admin)

18.1 shipping_rates (MVP)

Tarifas configurables de envío.

Campo Tipo Nulo Notas
id bigint PK
method enum air / sea
rate_per_lb decimal(8,4)
currency varchar(10) Default: USD
min_charge decimal(10,2) Cargo mínimo
effective_from timestamp
effective_until timestamp Null = vigente
created_by bigint FK → users.id
created_at timestamp

18.2 storage_policies (MVP)

Política dinámica de almacenamiento (ver politica-almacenamiento.md).

Campo Tipo Nulo Notas
id bigint PK
name varchar(100) UK, ej. standard, no_prealert
free_days integer
daily_rate decimal(8,2)
abandonment_days integer
abandonment_amount decimal(10,2)
effective_from timestamp
effective_until timestamp
created_by bigint FK → users.id
created_at timestamp

19. Fase 2 (no MVP)

Las siguientes tablas se reservan para Fase 2 y no se crean en MVP:

Tabla Propósito Trigger para crearla
referrals Tracking de referidos Activación del programa
credit_balances Saldo de crédito Idem
credit_movements Movimientos de crédito Idem
promo_cards Tarjetas promocionales Idem
user_levels Niveles de fidelidad Idem
loyalty_pool Pool promocional Idem
feedback Feedback de usuarios Lanzamiento
support_tickets Tickets de soporte Lanzamiento Fase 2

20. Vistas materializadas

20.1 v_package_summary (MVP)

Vista desnormalizada que une paquete + casillero + prealerta + consolidación + envío + KYC. Usada por listados y dashboards.

CREATE MATERIALIZED VIEW v_package_summary AS
SELECT
    pp.id AS package_id,
    pp.status,
    pp.received_at,
    pp.weight_kg,
    pp.billable_weight_kg,
    pp.storage_days,
    pp.storage_charge_total,
    lc.full_code AS locker_code,
    u.id AS user_id,
    u.full_name AS user_name,
    u.email AS user_email,
    u.phone AS user_phone,
    kr.status AS kyc_status,
    pr.marketplace,
    pr.order_number,
    tn.tracking_number,
    tn.carrier,
    wl.location_code AS warehouse_location,
    c.id AS consolidation_id,
    c.status AS consolidation_status,
    s.id AS shipment_id,
    s.status AS shipment_status,
    s.master_guide,
    pp.created_at,
    pp.updated_at
FROM physical_packages pp
JOIN locker_codes lc ON lc.id = pp.locker_code_id
JOIN users u ON u.id = lc.user_id
LEFT JOIN kyc_records kr ON kr.user_id = u.id
LEFT JOIN purchase_reports pr ON pr.id = pp.purchase_report_id
LEFT JOIN tracking_numbers tn ON tn.id = pp.tracking_number_id
LEFT JOIN warehouse_locations wl ON wl.id = pp.warehouse_location_id
LEFT JOIN consolidation_packages cp ON cp.physical_package_id = pp.id
LEFT JOIN consolidations c ON c.id = cp.consolidation_id
LEFT JOIN shipments s ON s.consolidation_id = c.id;

CREATE UNIQUE INDEX idx_vps_pk ON v_package_summary(package_id);
CREATE INDEX idx_vps_user ON v_package_summary(user_id);
CREATE INDEX idx_vps_status ON v_package_summary(status);

Refrescar con REFRESH MATERIALIZED VIEW CONCURRENTLY v_package_summary cada 5 minutos.


21. Reglas enforced por la base de datos

Regla Implementación
Un usuario tiene un solo KYC UNIQUE(user_id) en kyc_records
Un usuario tiene un solo balance de crédito UNIQUE(user_id) en credit_balances (Fase 2)
Un código de casillero es único UNIQUE(full_code) en locker_codes
El secuencial es único por prefijo UNIQUE(prefix, sequential) en locker_codes
Un paquete no puede estar en dos consolidaciones activas EXCLUDE constraint en consolidation_packages
El crédito no puede ser negativo CHECK (available_balance >= 0) en credit_balances
El dígito verificador se calcula en aplicación No en DB (en locker_service.py)
Un pago solo tiene una factura UNIQUE(payment_id) en invoices
Un consolidation solo tiene un envío UNIQUE(consolidation_id) en shipments
audit_logs es inmutable Trigger que bloquea UPDATE/DELETE

22. Diferencias vs modelo v1

# Cambio Razón
1 Eliminado campo duplicado phone en users Error de merge
2 Unificado id a bigint en todas las tablas de negocio (excepto file_attachments que usa uuid) Consistencia de joins
3 Renombrado customs_valuecustoms_declared_value Claridad
4 Renombrado status de customs_amount → eliminado (duplicaba info) Limpieza
5 Renombrado return_status → integrado en service_requests con service_type=return Evitar redundancia
6 Renombrado additional_servicesservice_requests (más semántico) Claridad
7 Consolidado categories y customs_categories en una sola tabla Eliminar duplicación
8 Nuevos campos: volumetric_weight_kg, billable_weight_kg en physical_packages Necesario para cotización
9 Nuevos campos: payment_method_mix en payments (jsonb) Soporte para pago mixto
10 Nuevas tablas: webhook_events, notification_delivery_log, notification_preferences, charges, quote_items, shipment_events, incident_messages, incident_evidence Cubrir nuevos flujos
11 Tablas de Fase 2 marcadas y movidas a §19 No se crean en MVP

23. Próximos pasos

  1. Validar este modelo v2 con el equipo backend antes de implementar.
  2. Generar las migraciones Alembic a partir de este modelo.
  3. Eliminar la tabla categories (legacy).
  4. Eliminar la tabla additional_services (legacy) tras migrar a service_requests.
  5. Actualizar api-contract.md y matriz-trazabilidad.md con los nuevos nombres de campos y tablas.