Documento histórico
Este documento se conserva solo para trazabilidad. Consulte el índice maestro para la fuente vigente.
Modelo de datos (LEGACY — archivado)
Documento histórico — no vigente
Este archivo es la versión 1 del modelo de datos de IslaBox, archivada el 2026-06-08 cuando se consolidó la versión limpia como ../../datos/modelo-datos.md.
No usar como referencia. Contiene problemas conocidos:
users.phone aparecía duplicado (en users y en users.address).
locker_codes.status usaba valores legacy (active/inactive/blocked) no alineados con ../../datos/estados.md.
- Decisiones de diseño obsoletas (separación
addresses vs locker_addresses, etc.).
- Formato menos consistente.
Para el modelo vigente, consultar ../../datos/modelo-datos.md.
Modelo de datos (v1 — histórico)
Documento de referencia técnica. Cada entidad incluye todos sus campos con tipo de dato, restricciones y propósito.
Convenciones del documento
| Símbolo |
Significado |
| PK |
Primary Key |
| FK |
Foreign Key |
| UK |
Unique constraint |
| IX |
Index (para queries frecuentes) |
varchar |
Texto corto |
text |
Texto largo |
boolean |
Booleano |
integer |
Entero |
bigint |
Entero grande |
decimal |
Número con decimales |
timestamp |
Fecha y hora |
date |
Solo fecha |
uuid |
Identificador único universal |
jsonb |
JSON binario (PostgreSQL) |
array |
Arreglo |
enum |
Valor discreto |
Entidades
users
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
Yes |
Autoincrement |
| email |
varchar(255) |
No |
|
|
UK |
Yes |
|
| email_verified |
boolean |
No |
|
|
|
|
Default: false |
| phone |
varchar(20) |
No |
|
|
UK |
Yes |
|
| phone_verified |
boolean |
No |
|
|
|
|
Default: false |
| full_name |
varchar(255) |
No |
|
|
|
|
|
| phone |
varchar(20) |
No |
|
|
UK |
Yes |
+1 (EE.UU.), 10 dígitos nacionales, formato E.164 (+1XXXXXXXXXX). Ver Regla de origen del usuario. |
| country_code |
char(2) |
No |
|
|
|
Yes |
Default US, no editable. Refuerza que el usuario vive en EE.UU. |
| password_hash |
varchar(255) |
No |
|
|
|
|
|
| role |
enum |
No |
|
|
|
|
|
| referral_code |
varchar(20) |
No |
|
|
UK |
Yes |
Código propio para referir |
| referred_by |
bigint |
Sí |
|
FK→users |
|
Yes |
FK al usuario que lo refiere |
| level |
integer |
No |
|
|
|
|
1/2/3, default 1 |
| last_level_recalculated_at |
timestamp |
Sí |
|
|
|
|
|
| is_active |
boolean |
No |
|
|
|
|
Default: true |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
| deleted_at |
timestamp |
Sí |
|
|
|
|
|
locker_codes
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| prefix |
varchar(10) |
No |
|
|
|
|
Default: CP |
| sequential |
integer |
No |
|
|
|
Yes |
Secuencial dentro del prefijo |
| check_digit |
integer |
No |
|
|
|
|
|
| full_code |
varchar(20) |
No |
|
|
UK |
Yes |
CP-001042-8 |
| status |
enum |
No |
|
|
|
Yes |
active/inactive/blocked |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
kyc_records
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
UK |
Yes |
Un KYC por usuario |
| document_type |
enum |
No |
|
|
|
|
passport/national_id/drivers_license |
| document_number |
varchar(50) |
No |
|
|
|
Yes |
|
| document_front_file_id |
bigint |
Sí |
|
FK→file_attachments |
|
|
|
| document_back_file_id |
bigint |
Sí |
|
FK→file_attachments |
|
|
|
| selfie_file_id |
bigint |
Sí |
|
FK→file_attachments |
|
|
|
| residence_address |
text |
No |
|
|
|
|
|
| province |
varchar(100) |
No |
|
|
|
|
|
| municipality |
varchar(100) |
No |
|
|
|
|
|
| status |
enum |
No |
|
|
|
Yes |
sin_iniciar/borrador/enviado/en_revision/aprobado/rechazado/requiere_mas_informacion/vencido/bloqueado_manual |
| submitted_at |
timestamp |
Sí |
|
|
|
|
|
| reviewed_by |
bigint |
Sí |
|
FK→users |
|
|
Operador que revisó |
| reviewed_at |
timestamp |
Sí |
|
|
|
|
|
| rejection_reason |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
addresses
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| address_type |
enum |
No |
|
|
|
|
shipping/billing/recipient |
| full_name |
varchar(255) |
No |
|
|
|
|
|
| phone |
varchar(20) |
No |
|
|
|
|
|
| alternate_phone |
varchar(20) |
Sí |
|
|
|
|
|
| address_line1 |
varchar(500) |
No |
|
|
|
|
|
| address_line2 |
varchar(500) |
Sí |
|
|
|
|
|
| city |
varchar(100) |
No |
|
|
|
|
|
| state |
varchar(100) |
No |
|
|
|
|
|
| zip_code |
varchar(20) |
No |
|
|
|
|
|
| country |
varchar(100) |
No |
|
|
|
|
Default según address_type: shipping → US (casillero en EE.UU.), recipient → Cuba. El casillero físico está en Miami, FL; los destinatarios siempre están en Cuba. |
| province |
varchar(100) |
Sí |
|
|
|
|
|
| municipality |
varchar(100) |
Sí |
|
|
|
|
|
| delivery_references |
text |
Sí |
|
|
|
|
|
| is_default |
boolean |
No |
|
|
|
|
Default: false |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
senders
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| purchase_report_id |
bigint |
No |
|
FK→purchase_reports |
|
Yes |
|
| full_name |
varchar(255) |
No |
|
|
|
|
|
| phone |
varchar(20) |
No |
|
|
|
|
+1 (EE.UU., 10 dígitos), formato E.164. El remitente siempre está en EE.UU. |
| email |
varchar(255) |
Sí |
|
|
|
|
|
| address_line1 |
varchar(500) |
No |
|
|
|
|
|
| city |
varchar(100) |
No |
|
|
|
|
|
| state |
varchar(100) |
No |
|
|
|
|
|
| zip_code |
varchar(20) |
No |
|
|
|
|
|
| relationship_to_shipment |
varchar(100) |
Sí |
|
|
|
|
|
| notes |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
recipients
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
El usuario registrado (en EE.UU.) que gestiona este destinatario |
| full_name |
varchar(255) |
No |
|
|
|
|
|
| identity_document |
varchar(50) |
Sí |
|
|
|
|
Carné de identidad cubano |
| phone |
varchar(20) |
No |
|
|
|
|
+53 (Cuba, 8 dígitos) o +1 (EE.UU., 10 dígitos), formato E.164 |
| alternate_phone |
varchar(20) |
Sí |
|
|
|
|
Misma regla que phone |
| address_line1 |
varchar(500) |
No |
|
|
|
|
Dirección en Cuba |
| province |
varchar(100) |
No |
|
|
|
|
Provincia cubana (ver catálogo en datos/../../datos/aduana.md) |
| municipality |
varchar(100) |
No |
|
|
|
|
|
| delivery_references |
text |
Sí |
|
|
|
|
|
| is_same_as_user |
boolean |
No |
|
|
|
|
Default: true (el destinatario es el propio usuario registrado) |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
purchase_reports
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| marketplace |
enum |
No |
|
|
|
Yes |
amazon/shein/temu/other |
| order_number |
varchar(100) |
No |
|
|
|
Yes |
|
| total_declared_value |
decimal(10,2) |
No |
|
|
|
|
|
| total_declared_currency |
varchar(10) |
No |
|
|
|
|
Default: USD |
| status |
enum |
No |
|
|
|
Yes |
borrador/reportada/reportada_sin_tracking/tracking_actualizado/vinculada_a_paquete/cancelada_por_usuario/cancelada_por_operador/requiere_correccion |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
purchase_items
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| purchase_report_id |
bigint |
No |
|
FK→purchase_reports |
|
Yes |
|
| description |
text |
No |
|
|
|
|
|
| quantity |
integer |
No |
|
|
|
|
|
| unit_value |
decimal(10,2) |
No |
|
|
|
|
|
| currency |
varchar(10) |
No |
|
|
|
|
Default: USD |
| category_id |
bigint |
Sí |
|
FK→categories |
|
Yes |
|
| product_url |
varchar(1000) |
Sí |
|
|
|
|
|
| seller |
varchar(255) |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
tracking_numbers
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| purchase_report_id |
bigint |
No |
|
FK→purchase_reports |
|
Yes |
|
| tracking_number |
varchar(100) |
No |
|
|
|
Yes |
|
| carrier |
enum |
No |
|
|
|
Yes |
ups/usps/fedex/dhl/other |
| estimated_arrival |
date |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
customs_categories
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| code |
varchar(50) |
No |
|
|
UK |
Yes |
Código único (ej. ropa, electronicos) |
| name |
varchar(100) |
No |
|
|
|
|
Nombre visible |
| description |
text |
Sí |
|
|
|
|
|
| accepted |
enum |
No |
|
|
|
|
yes/conditional/no |
| requires_invoice |
boolean |
No |
|
|
|
|
Default: false |
| requires_review |
boolean |
No |
|
|
|
|
Default: false |
| risk_level |
enum |
No |
|
|
|
|
low/medium/high/prohibited |
| allows_air |
boolean |
No |
|
|
|
|
Default: true |
| allows_sea |
boolean |
No |
|
|
|
|
Default: true |
| duty_percentage |
decimal(5,2) |
Sí |
|
|
|
|
Porcentaje de arancel aplicable |
| user_message |
text |
Sí |
|
|
|
|
Mensaje al usuario |
| operator_message |
text |
Sí |
|
|
|
|
Nota interna para el operador |
| is_active |
boolean |
No |
|
|
|
|
Default: true |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
physical_packages
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| locker_code_id |
bigint |
No |
|
FK→locker_codes |
|
Yes |
|
| purchase_report_id |
bigint |
Sí |
|
FK→purchase_reports |
|
Yes |
|
| tracking_number_id |
bigint |
Sí |
|
FK→tracking_numbers |
|
Yes |
|
| warehouse_location_id |
bigint |
Sí |
|
FK→warehouse_locations |
|
Yes |
|
| status |
enum |
No |
|
|
|
Yes |
prealertado/en_camino_al_almacen/recibido_sin_identificar/recibido_identificado/pendiente_conciliacion/en_almacen/esperando_instrucciones/en_servicio_adicional/listo_para_consolidar/reservado_para_consolidacion/consolidado/en_transito/entregado/retenido_por_incidencia/devuelto_a_tienda/descartado_o_cerrado |
| received_at |
timestamp |
No |
|
|
|
|
|
| received_by |
bigint |
No |
|
FK→users |
|
Yes |
Operador que recibió |
| weight_kg |
decimal(8,3) |
Sí |
|
|
|
|
|
| length_cm |
decimal(8,2) |
Sí |
|
|
|
|
|
| width_cm |
decimal(8,2) |
Sí |
|
|
|
|
|
| height_cm |
decimal(8,2) |
Sí |
|
|
|
|
|
| storage_days |
integer |
No |
|
|
|
|
Calculado |
| storage_charge |
decimal(10,2) |
Sí |
|
|
|
|
|
| storage_charge_status |
enum |
No |
|
|
|
|
pendiente/aplicado/exonerado |
| inspection_requested |
boolean |
No |
|
|
|
|
Default: false |
| inspection_result |
text |
Sí |
|
|
|
|
|
| repack_requested |
boolean |
No |
|
|
|
|
Default: false |
| return_requested |
boolean |
No |
|
|
|
|
Default: false |
| return_reason |
text |
Sí |
|
|
|
|
|
| return_status |
enum |
Sí |
|
|
|
|
pendiente/en_transito/completado |
| customs_category_id |
bigint |
Sí |
|
FK→customs_categories |
|
Yes |
|
| customs_value |
decimal(10,2) |
Sí |
|
|
|
|
|
| customs_amount |
decimal(10,2) |
Sí |
|
|
|
|
Monto pagado en aduana |
| notes_internal |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
package_events
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| physical_package_id |
bigint |
No |
|
FK→physical_packages |
|
Yes |
|
| status |
varchar(50) |
No |
|
|
|
Yes |
|
| description |
text |
Sí |
|
|
|
|
|
| operator_id |
bigint |
Sí |
|
FK→users |
|
Yes |
|
| visible_to_user |
boolean |
No |
|
|
|
|
Default: false |
| created_at |
timestamp |
No |
|
|
Yes |
|
|
package_photos
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| physical_package_id |
bigint |
No |
|
FK→physical_packages |
|
Yes |
|
| file_attachment_id |
bigint |
No |
|
FK→file_attachments |
UK |
|
|
| photo_type |
enum |
No |
|
|
|
|
reception/inspection/return/customs |
| created_at |
timestamp |
No |
|
|
|
|
|
warehouse_locations
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| warehouse_code |
varchar(50) |
No |
|
|
|
|
|
| zone |
varchar(50) |
No |
|
|
|
|
|
| shelf |
varchar(50) |
No |
|
|
|
|
|
| bin |
varchar(50) |
No |
|
|
|
|
|
| location_description |
varchar(255) |
No |
|
|
|
|
|
| is_occupied |
boolean |
No |
|
|
|
|
Default: false |
| created_at |
timestamp |
No |
|
|
|
|
|
consolidations
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| status |
enum |
No |
|
|
|
Yes |
borrador/completa/cotizada/pendiente_pago/pagada/en_preparacion/despachada/cancelada |
| total_value |
decimal(10,2) |
No |
|
|
|
|
|
| total_weight_kg |
decimal(8,3) |
No |
|
|
|
|
|
| quote_id |
bigint |
Sí |
|
FK→quotes |
|
Yes |
|
| shipment_id |
bigint |
Sí |
|
FK→shipments |
|
Yes |
|
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
consolidation_packages
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| consolidation_id |
bigint |
No |
|
FK→consolidations |
|
Yes |
|
| physical_package_id |
bigint |
No |
|
FK→physical_packages |
|
Yes |
|
| added_at |
timestamp |
No |
|
|
|
|
|
shipments
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| consolidation_id |
bigint |
No |
|
FK→consolidations |
UK |
Yes |
|
| status |
enum |
No |
|
|
|
Yes |
borrador/pendiente_kyc/pendiente_destinatario/pendiente_cotizacion/cotizado/pendiente_pago/pagado/en_preparacion/despachado_desde_almacen/en_transito_a_cuba/en_aduana/liberado_de_aduana/en_reparto/entregado/incidencia/cancelado |
| carrier |
varchar(100) |
No |
|
|
|
|
|
| master_guide |
varchar(100) |
Sí |
|
|
|
Yes |
|
| departure_date |
date |
Sí |
|
|
|
|
|
| estimated_arrival |
date |
Sí |
|
|
|
|
|
| actual_arrival |
date |
Sí |
|
|
|
|
|
| customs_amount_total |
decimal(10,2) |
Sí |
|
|
|
|
Monto total de aduana pagado por el envío |
| customs_paid_at |
timestamp |
Sí |
|
|
|
|
|
| notes_internal |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
shipment_events
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| shipment_id |
bigint |
No |
|
FK→shipments |
|
Yes |
|
| status |
varchar(50) |
No |
|
|
|
Yes |
|
| description |
text |
Sí |
|
|
|
|
|
| location |
varchar(255) |
Sí |
|
|
|
|
|
| operator_id |
bigint |
Sí |
|
FK→users |
|
Yes |
|
| created_at |
timestamp |
No |
|
|
Yes |
|
|
quotes
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| consolidation_id |
bigint |
Sí |
|
FK→consolidations |
|
Yes |
|
| total_freight |
decimal(10,2) |
No |
|
|
|
|
|
| total_customs |
decimal(10,2) |
No |
|
|
|
|
|
| total_charges |
decimal(10,2) |
No |
|
|
|
|
|
| total_payable |
decimal(10,2) |
No |
|
|
|
|
|
| valid_until |
timestamp |
No |
|
|
Yes |
|
|
| status |
enum |
No |
|
|
|
Yes |
pending/accepted/expired/superseded |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
payments
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| quote_id |
bigint |
No |
|
FK→quotes |
|
Yes |
|
| consolidation_id |
bigint |
Sí |
|
FK→consolidations |
|
Yes |
|
| amount |
decimal(10,2) |
No |
|
|
|
|
|
| currency |
varchar(10) |
No |
|
|
|
|
Default: USD |
| payment_method |
enum |
No |
|
|
|
|
card/bank_transfer/cash/credit |
| payment_provider |
varchar(50) |
Sí |
|
|
|
|
|
| provider_reference |
varchar(255) |
Sí |
|
|
|
Yes |
|
| status |
enum |
No |
|
|
|
Yes |
pendiente/completado/fallido/reembolsado/parcial |
| processed_at |
timestamp |
Sí |
|
|
|
|
|
| failure_reason |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
payment_attempts
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| payment_id |
bigint |
No |
|
FK→payments |
|
Yes |
|
| amount |
decimal(10,2) |
No |
|
|
|
|
|
| status |
varchar(50) |
No |
|
|
|
|
|
| provider_response |
jsonb |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
charges
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| consolidation_id |
bigint |
Sí |
|
FK→consolidations |
|
Yes |
|
| charge_type |
enum |
No |
|
|
|
Yes |
storage/inspection/repack/customs/delivery/other |
| amount |
decimal(10,2) |
No |
|
|
|
|
|
| description |
text |
No |
|
|
|
|
|
| status |
enum |
No |
|
|
|
|
|
| applied_at |
timestamp |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
invoices
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| payment_id |
bigint |
No |
|
FK→payments |
UK |
Yes |
|
| invoice_number |
varchar(50) |
No |
|
|
UK |
|
|
| amount |
decimal(10,2) |
No |
|
|
|
|
|
| currency |
varchar(10) |
No |
|
|
|
|
Default: USD |
| issued_at |
timestamp |
No |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
additional_services
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| physical_package_id |
bigint |
No |
|
FK→physical_packages |
|
Yes |
|
| service_type |
enum |
No |
|
|
|
|
inspection/functional_test/repack/other |
| requested |
boolean |
No |
|
|
|
|
Default: false |
| result |
text |
Sí |
|
|
|
|
|
| evidence_file_ids |
array(bigint) |
Sí |
|
|
|
|
|
| cost |
decimal(10,2) |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
incidents
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| physical_package_id |
bigint |
Sí |
|
FK→physical_packages |
|
Yes |
|
| shipment_id |
bigint |
Sí |
|
FK→shipments |
|
Yes |
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| incident_type |
enum |
No |
|
|
|
Yes |
damaged_package/wrong_package/missing_item/customs_hold/carrier_loss/other |
| status |
enum |
No |
|
|
|
Yes |
reportado/en_revision/resuelto/escalado/cerrado |
| description |
text |
No |
|
|
|
|
|
| operator_notes |
text |
Sí |
|
|
|
|
|
| resolution |
text |
Sí |
|
|
|
|
|
| reported_by |
bigint |
No |
|
FK→users |
|
Yes |
|
| assigned_to |
bigint |
Sí |
|
FK→users |
|
Yes |
|
| created_at |
timestamp |
No |
|
|
|
Yes |
|
| resolved_at |
timestamp |
Sí |
|
|
|
|
|
notifications
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| notification_type |
varchar(50) |
No |
|
|
|
Yes |
|
| title |
varchar(255) |
No |
|
|
|
|
|
| body |
text |
No |
|
|
|
|
|
| data_payload |
jsonb |
Sí |
|
|
|
|
|
| read_at |
timestamp |
Sí |
|
|
|
|
|
| sent_at |
timestamp |
No |
|
|
|
|
|
| channel |
enum |
No |
|
|
|
|
push/email/sms/whatsapp |
| status |
enum |
No |
|
|
|
|
queued/sent/delivered/failed |
audit_logs
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
Sí |
|
FK→users |
|
Yes |
|
| action |
varchar(100) |
No |
|
|
|
Yes |
|
| entity_type |
varchar(100) |
No |
|
|
|
|
|
| entity_id |
bigint |
Sí |
|
|
|
|
|
| changes |
jsonb |
Sí |
|
|
|
|
|
| ip_address |
generic_ip_address |
Sí |
|
|
|
|
|
| user_agent |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
Yes |
|
referrals
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| referrer_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| referred_user_id |
bigint |
No |
|
FK→users |
UK |
Yes |
|
| referral_code_used |
varchar(20) |
No |
|
|
|
|
Código que usó al registrarse |
| status |
enum |
No |
|
|
|
Yes |
active/expired/cancelled |
| registered_at |
timestamp |
No |
|
|
|
|
|
| window_expires_at |
timestamp |
No |
|
|
Yes |
180 días desde registro |
|
| level |
integer |
No |
|
|
|
|
1, 2 o 3 |
| created_at |
timestamp |
No |
|
|
|
|
|
credit_balances
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
UK |
Yes |
Un balance por usuario |
| available_balance |
decimal(12,2) |
No |
|
|
|
|
Default: 0 |
| total_earned |
decimal(12,2) |
No |
|
|
|
|
Histórico |
| total_used |
decimal(12,2) |
No |
|
|
|
|
Histórico |
| total_expired |
decimal(12,2) |
No |
|
|
|
|
Histórico |
| status |
enum |
No |
|
|
|
|
active/expired/suspended |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
credit_movements
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| credit_balance_id |
bigint |
No |
|
FK→credit_balances |
|
Yes |
|
| movement_type |
enum |
No |
|
|
|
Yes |
accreditation/usage/expiry/conversion_to_card/adjustment |
| amount |
decimal(12,2) |
No |
|
|
|
|
|
| resulting_balance |
decimal(12,2) |
No |
|
|
|
|
|
| origin |
enum |
No |
|
|
|
|
referral_level_1/2/3/loyalty_pool/adjustment |
| reference_type |
varchar(50) |
Sí |
|
|
|
|
|
| reference_id |
bigint |
Sí |
|
|
|
|
|
| description |
text |
No |
|
|
|
|
|
| expires_at |
timestamp |
Sí |
|
|
|
|
|
| expired_at |
timestamp |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
Yes |
|
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| denomination |
decimal(10,2) |
No |
|
|
|
|
$50/$100/$150 |
| issuer_user_id |
bigint |
No |
|
FK→users |
|
Yes |
Quién la emite |
| receiver_user_id |
bigint |
No |
|
FK→users |
|
Yes |
A quién se le asigna |
| origin |
enum |
No |
|
|
|
|
from_credit/loyalty_benefit |
| credit_movement_id |
bigint |
Sí |
|
FK→credit_movements |
|
Yes |
Si viene de crédito |
| status |
enum |
No |
|
|
|
Yes |
available/applied/expired/cancelled |
| issued_at |
timestamp |
No |
|
|
|
|
|
| expires_at |
timestamp |
No |
|
|
|
Yes |
|
| applied_to_shipment_id |
bigint |
Sí |
|
FK→shipments |
|
Yes |
|
| applied_at |
timestamp |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
file_attachments
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
uuid |
No |
PK |
|
|
|
|
| owner_type |
enum |
No |
|
|
|
|
user/operator/system |
| owner_id |
bigint |
No |
|
|
|
Yes |
|
| bucket |
varchar(100) |
No |
|
|
|
Yes |
|
| object_key |
varchar(500) |
No |
|
|
|
|
Path en MinIO |
| original_filename |
varchar(255) |
No |
|
|
|
|
|
| mime_type |
varchar(100) |
No |
|
|
|
|
|
| size_bytes |
bigint |
No |
|
|
|
|
|
| checksum |
varchar(64) |
No |
|
|
|
|
SHA-256 |
| visibility |
enum |
No |
|
|
|
|
private/public |
| uploaded_by |
bigint |
No |
|
FK→users |
|
Yes |
|
| created_at |
timestamp |
No |
|
|
|
|
|
| deleted_at |
timestamp |
Sí |
|
|
|
|
Soft delete |
file_access_logs
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| file_attachment_id |
bigint |
No |
|
FK→file_attachments |
|
Yes |
|
| accessed_by |
bigint |
No |
|
FK→users |
|
Yes |
|
| access_type |
enum |
No |
|
|
|
|
read/download/upload |
| ip_address |
generic_ip_address |
Sí |
|
|
|
|
|
| user_agent |
text |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
categories
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| name |
varchar(100) |
No |
|
|
UK |
|
|
| description |
text |
Sí |
|
|
|
|
|
| is_active |
boolean |
No |
|
|
|
|
Default: true |
| created_at |
timestamp |
No |
|
|
|
|
|
customs_categories (alias en narrativa)
Entidad canónica arriba
La definición canónica de customs_categories está en este mismo documento, en la primera ocurrencia (justo antes de physical_packages). Esta segunda mención se mantiene por trazabilidad narrativa, pero no debe usarse como referencia.
api_tokens
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
Autoincrement |
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| token_hash |
varchar(255) |
No |
|
|
UK |
Yes |
|
| name |
varchar(100) |
No |
|
|
|
|
Para identificarlo |
| scopes |
array(varchar) |
No |
|
|
|
|
|
| last_used_at |
timestamp |
Sí |
|
|
|
|
|
| expires_at |
timestamp |
Sí |
|
|
|
|
|
| created_at |
timestamp |
No |
|
|
|
|
|
device_tokens
| Campo |
Tipo |
Nulo |
PK |
FK |
UK |
IX |
Notas |
| id |
bigint |
No |
PK |
|
|
|
|
| user_id |
bigint |
No |
|
FK→users |
|
Yes |
|
| token |
varchar(500) |
No |
|
|
UK |
|
Token push |
| platform |
enum |
No |
|
|
|
|
ios/android/web |
| device_id |
varchar(255) |
Sí |
|
|
|
|
|
| is_active |
boolean |
No |
|
|
|
|
Default: true |
| created_at |
timestamp |
No |
|
|
|
|
|
| updated_at |
timestamp |
No |
|
|
|
|
|
Vistas materializadas
v_package_summary
Agrega información de paquetes, prealerta y consolidado para dashboards y listados.
CREATE MATERIALIZED VIEW v_package_summary AS
SELECT
pp.id,
pp.status,
lc.full_code AS locker_code,
pr.marketplace,
pr.order_number,
tn.tracking_number,
wl.location_description,
pp.storage_days,
pp.storage_charge,
pp.storage_charge_status,
c.id AS consolidation_id,
c.status AS consolidation_status,
s.id AS shipment_id,
s.status AS shipment_status,
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,
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 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
LEFT JOIN kyc_records kr ON kr.user_id = u.id;
Reglas de negocio 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 |
| 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 |
Check constraint en consolidation_packages |
| El crédito no puede ser negativo |
Check constraint available_balance >= 0 |
| El dígito verificador se calcula en aplicación |
No en DB — calculado en locker_service.py |
| OTP expira en 5 minutos |
TTL en Redis, no en DB |