Saltar a contenido

Documento histórico

Este documento se conserva solo para trazabilidad. Consulte el índice maestro para la fuente vigente.

Documento histórico — no usar como fuente de decisiones actuales

Reemplazado por la versión canónica del 2026-07-11. Conservar solo como trazabilidad histórica.


Diagrama de clases

Vista UML de las entidades principales del sistema IslaBox, sus atributos, métodos y relaciones. Complementa al modelo de datos relacional agregando relaciones visuales, cardinalidad y métodos de comportamiento.


Diagrama general (Mermaid)

classDiagram
    class User {
        +Long id
        +String email
        +Boolean emailVerified
        +String phone
        +Boolean phoneVerified
        +String fullName
        +String countryCode = "US"
        +String passwordHash
        +Role role
        +String referralCode
        +User referredBy
        +Integer level = 1
        +Boolean isActive
        +LocalDateTime createdAt
        +String initials
        +String fullNameFormatted
    }

    class LockerCode {
        +Long id
        +User user
        +String prefix = "CP"
        +Integer sequential
        +Integer checkDigit
        +String fullCode
        +LockerCodeStatus status
        +LocalDateTime createdAt
        +String formatted()
        +Boolean validate()
    }

    class KycRecord {
        +Long id
        +User user
        +DocumentType documentType
        +String documentNumber
        +File documentFront
        +File documentBack
        +File selfie
        +String residenceAddress
        +String province
        +String municipality
        +KycStatus status
        +LocalDateTime submittedAt
        +User reviewedBy
        +LocalDateTime reviewedAt
        +String rejectionReason
        +LocalDateTime expiresAt
        +Boolean isApproved()
        +Boolean isExpired()
    }

    class Address {
        +Long id
        +User user
        +AddressType addressType
        +String fullName
        +String phone
        +String alternatePhone
        +String addressLine1
        +String addressLine2
        +String city
        +String state
        +String zipCode
        +String country
        +String province
        +String municipality
        +String deliveryReferences
        +Boolean isDefault
    }

    class Recipient {
        +Long id
        +User user
        +String fullName
        +String identityDocument
        +String phone
        +String alternatePhone
        +String addressLine1
        +String province
        +String municipality
        +String deliveryReferences
        +Boolean isSameAsUser
    }

    class Sender {
        +Long id
        +PurchaseReport purchaseReport
        +String fullName
        +String phone
        +String email
        +String addressLine1
        +String city
        +String state
        +String zipCode
        +String relationship
    }

    class PurchaseReport {
        +Long id
        +User user
        +String marketplace
        +String orderNumber
        +LocalDate purchaseDate
        +PurchaseReportStatus purchaseStatus
        +String instructions
        +Boolean consolidationPreference
        +LocalDateTime createdAt
        +String trackingSummary()
        +Boolean isEditable()
    }

    class TrackingNumber {
        +Long id
        +PurchaseReport purchaseReport
        +String number
        +LocalDateTime addedAt
    }

    class PurchaseItem {
        +Long id
        +PurchaseReport purchaseReport
        +CustomsCategory category
        +String description
        +Integer quantity
        +BigDecimal valuePaid
        +String productUrl
        +String captureFileId
    }

    class PhysicalPackage {
        +Long id
        +User user
        +PurchaseReport purchaseReport
        +String trackingNumber
        +String store
        +BigDecimal weight
        +String dimensions
        +PackageStatus status
        +String packagingCondition
        +LocalDateTime arrivedAt
        +WarehouseLocation location
        +Integer daysInWarehouse
        +BigDecimal totalStorageCharges
        +Boolean isInFreePeriod()
        +Integer daysToExpiration()
    }

    class PackageItem {
        +Long id
        +PhysicalPackage physicalPackage
        +String description
        +Integer quantity
    }

    class PackageEvent {
        +Long id
        +PhysicalPackage physicalPackage
        +PackageStatus status
        +String description
        +User operator
        +LocalDateTime createdAt
    }

    class PackagePhoto {
        +Long id
        +PhysicalPackage physicalPackage
        +File file
        +LocalDateTime createdAt
    }

    class Consolidation {
        +Long id
        +User user
        +ConsolidationStatus status
        +BigDecimal totalWeight
        +BigDecimal totalValue
        +Integer packageCount
        +String trackingNumber
        +String shippingAddressId
        +LocalDateTime createdAt
    }

    class ConsolidationPackage {
        +Long id
        +Consolidation consolidation
        +PhysicalPackage physicalPackage
        +LocalDateTime addedAt
        +String notes
    }

    class Shipment {
        +Long id
        +Consolidation consolidation
        +User user
        +Recipient recipient
        +ShipmentStatus status
        +BigDecimal weight
        +String shippingType
        +LocalDateTime estimatedDelivery
        +String masterGuide
        +String carrier
        +LocalDateTime shippedAt
        +LocalDateTime deliveredAt
    }

    class Quote {
        +Long id
        +Shipment shipment
        +BigDecimal totalAmount
        +String currency = "USD"
        +LocalDateTime expiresAt
        +QuoteStatus status
    }

    class QuoteItem {
        +Long id
        +Quote quote
        +String description
        +Integer quantity
        +BigDecimal unitPrice
        +BigDecimal total
    }

    class Payment {
        +Long id
        +Shipment shipment
        +BigDecimal amount
        +String currency
        +PaymentStatus status
        +PaymentMethodMix paymentMethodMix
        +String transactionId
        +Invoice invoice
        +LocalDateTime createdAt
    }

    class PaymentAttempt {
        +Long id
        +Payment payment
        +String provider
        +String providerReference
        +PaymentStatus status
        +String errorCode
        +LocalDateTime attemptedAt
    }

    class PaymentMethodMix {
        +BigDecimal realMoney
        +BigDecimal credit
        +BigDecimal card
        +String cardLastFour
        +BigDecimal total
    }

    class Charge {
        +Long id
        +Payment payment
        +String description
        +BigDecimal amount
        +ChargeCategory category
        +String referenceId
        +LocalDateTime createdAt
    }

    class Invoice {
        +Long id
        +String number
        +List~Charge~ charges
        +BigDecimal subtotal
        +BigDecimal taxes
        +BigDecimal total
        +InvoiceStatus status
        +LocalDateTime createdAt
        +LocalDateTime dueDate
        +LocalDateTime paidAt
    }

    class ServiceRequest {
        +Long id
        +PhysicalPackage physicalPackage
        +ServiceType type
        +ServiceStatus status
        +BigDecimal cost
        +LocalDateTime requestedAt
        +LocalDateTime completedAt
        +List~File~ evidenceFileIds
        +String userNotes
        +String operatorNotes
    }

    class Incident {
        +Long id
        +PhysicalPackage physicalPackage
        +Shipment shipment
        +IncidentType type
        +IncidentStatus status
        +String description
        +User openedBy
        +User assignedTo
        +LocalDateTime createdAt
        +LocalDateTime resolvedAt
    }

    class Notification {
        +Long id
        +User user
        +String title
        +String body
        +NotificationChannel channel
        +Boolean visibleToUser
        +Boolean read
        +LocalDateTime createdAt
    }

    class AuditLog {
        +Long id
        +String entityType
        +Long entityId
        +String action
        +User user
        +String ipAddress
        +String beforeState
        +String afterState
        +LocalDateTime createdAt
    }

    class Referral {
        +Long id
        +User referrer
        +User referred
        +LocalDateTime registeredAt
        +LocalDateTime windowExpiresAt
        +Integer level
    }

    class CreditBalance {
        +Long id
        +User user
        +BigDecimal available
        +BigDecimal pending
        +LocalDateTime expiresAt
    }

    class CreditMovement {
        +Long id
        +CreditBalance creditBalance
        +BigDecimal amount
        +String description
        +MovementType type
        +LocalDateTime createdAt
    }

    class PromoCard {
        +Long id
        +User user
        +BigDecimal amount
        +LocalDateTime issuedAt
        +LocalDateTime expiresAt
        +Boolean used
        +LocalDateTime usedAt
    }

    class CustomsCategory {
        +String code
        +String name
        +String description
        +Acceptance accepted
        +Boolean requiresInvoice
        +Boolean requiresReview
        +RiskLevel riskLevel
        +Boolean allowsAir
        +Boolean allowsSea
        +BigDecimal dutyPercentage
        +String userMessage
        +String operatorMessage
    }

    class FileAttachment {
        +UUID id
        +String ownerType
        +Long ownerId
        +String bucket
        +String objectKey
        +String originalFilename
        +String mimeType
        +Long sizeBytes
        +String checksum
        +Visibility visibility
        +Long uploadedBy
        +LocalDateTime createdAt
        +String presignedUploadUrl()
        +String presignedReadUrl(userId)
    }

    class WarehouseLocation {
        +Long id
        +String zone
        +String shelf
        +String position
        +Integer capacity
    }

    %% Relaciones
    User "1" --> "1" LockerCode : tiene
    User "1" --> "0..1" KycRecord : tiene
    User "1" --> "*" Address : tiene
    User "1" --> "*" Recipient : gestiona
    User "1" --> "*" PurchaseReport : crea
    User "1" --> "*" PhysicalPackage : recibe
    User "1" --> "*" Consolidation : agrupa
    User "1" --> "*" Shipment : envía
    User "1" --> "*" Notification : recibe
    User "1" --> "*" Referral : referidor
    User "1" --> "*" Referral : referido
    User "1" --> "0..1" CreditBalance : tiene
    User "1" --> "*" PromoCard : tiene
    User "1" --> "*" AuditLog : origina

    PurchaseReport "1" --> "*" PurchaseItem : tiene
    PurchaseReport "1" --> "*" TrackingNumber : tiene
    PurchaseReport "1" --> "1" Sender : tiene
    PurchaseReport "*" --> "1" CustomsCategory : clasifica

    PhysicalPackage "1" --> "*" PackageItem : tiene
    PhysicalPackage "1" --> "*" PackageEvent : tiene
    PhysicalPackage "1" --> "*" PackagePhoto : tiene
    PhysicalPackage "1" --> "1" WarehouseLocation : ubicado en
    PhysicalPackage "1" --> "*" ServiceRequest : tiene
    PhysicalPackage "*" --> "0..1" PurchaseReport : originado de

    Consolidation "1" --> "*" ConsolidationPackage : agrupa
    ConsolidationPackage "*" --> "1" PhysicalPackage : referencia

    Shipment "1" --> "1" Consolidation : incluye
    Shipment "1" --> "1" Recipient : entrega a
    Shipment "1" --> "*" Payment : tiene
    Shipment "1" --> "0..1" Quote : tiene

    Quote "1" --> "*" QuoteItem : tiene

    Payment "1" --> "*" PaymentAttempt : intentos
    Payment "1" --> "1" PaymentMethodMix : métodos
    Payment "1" --> "*" Charge : incluye
    Payment "1" --> "0..1" Invoice : genera

    CreditBalance "1" --> "*" CreditMovement : tiene

    FileAttachment "1" --> "*" FileAccessLog : registra accesos

Detalle por módulos

Módulo 1: Identidad y autenticación

classDiagram
    class User
    class LockerCode
    class KycRecord
    class Address
    class AuditLog

    User "1" --> "1" LockerCode
    User "1" --> "0..1" KycRecord
    User "1" --> "*" Address
    User "1" --> "*" AuditLog

Características: - User es la raíz de identidad. - LockerCode 1:1 (todo usuario tiene exactamente un identificador activo). - KycRecord 1:0..1 (puede no tener KYC, o tener uno activo/vencido). - Address 1:* (puede tener varias: casillero, residencia, etc.).

Módulo 2: Prealerta y paquete

classDiagram
    class PurchaseReport
    class PurchaseItem
    class TrackingNumber
    class PhysicalPackage
    class PackageEvent
    class CustomsCategory
    class Sender

    PurchaseReport "1" --> "*" PurchaseItem
    PurchaseReport "1" --> "*" TrackingNumber
    PurchaseReport "1" --> "1" Sender
    PurchaseItem "*" --> "1" CustomsCategory
    PhysicalPackage "0..1" --> "1" PurchaseReport
    PhysicalPackage "1" --> "*" PackageEvent

Características: - PurchaseReport (prealerta) puede existir sin PhysicalPackage (el paquete aún no llegó). - Cuando el operador identifica el paquete, vincula la prealerta con el PhysicalPackage. - Cada cambio de estado del paquete genera un PackageEvent (auditoría inmutable).

Módulo 3: Consolidación y envío

classDiagram
    class Consolidation
    class ConsolidationPackage
    class PhysicalPackage
    class Shipment
    class Recipient

    Consolidation "1" --> "*" ConsolidationPackage
    ConsolidationPackage "*" --> "1" PhysicalPackage
    Consolidation "1" --> "1" Shipment
    Shipment "1" --> "1" Recipient

Características: - Una Consolidation agrupa varios PhysicalPackage mediante la entidad débil ConsolidationPackage. - Una Consolidation se traduce en un Shipment cuando se confirma. - El Shipment tiene un único Recipient.

Módulo 4: Dinero y facturación

classDiagram
    class Quote
    class QuoteItem
    class Payment
    class PaymentMethodMix
    class PaymentAttempt
    class Charge
    class Invoice

    Quote "1" --> "*" QuoteItem
    Shipment "1" --> "0..1" Quote
    Shipment "1" --> "*" Payment
    Payment "1" --> "1" PaymentMethodMix
    Payment "1" --> "*" PaymentAttempt
    Payment "1" --> "*" Charge
    Payment "1" --> "0..1" Invoice

Características: - Quote se genera al consolidar y tiene vigencia. - Payment puede combinar realMoney + credit + card mediante PaymentMethodMix. - Invoice se genera tras un pago confirmado. - Charge desglosa cada concepto (servicio, envío, almacenaje, aduana, etc.).

Módulo 5: Crecimiento (Fase 2)

classDiagram
    class User
    class Referral
    class CreditBalance
    class CreditMovement
    class PromoCard

    User "1" --> "*" Referral : referidor
    User "1" --> "*" Referral : referido
    User "1" --> "0..1" CreditBalance
    CreditBalance "1" --> "*" CreditMovement
    User "1" --> "*" PromoCard

Características: - Referral es una relación N:N con atributos (fecha, ventana de 180 días, nivel). - CreditBalance 1:0..1 (puede no tener crédito aún). - PromoCard se emite al convertir crédito.

Módulo 6: Archivos

classDiagram
    class FileAttachment
    class FileAccessLog
    class KycRecord
    class PhysicalPackage
    class ServiceRequest

    KycRecord "1" --> "0..1" FileAttachment : documentFront
    KycRecord "1" --> "0..1" FileAttachment : documentBack
    KycRecord "1" --> "0..1" FileAttachment : selfie
    PhysicalPackage "1" --> "*" FileAttachment : photos
    ServiceRequest "1" --> "*" FileAttachment : evidence
    FileAttachment "1" --> "*" FileAccessLog

Características: - FileAttachment es un patrón polimórfico: owner_type + owner_id. - Cada acceso a un archivo privado se registra en FileAccessLog. - Los buckets son privados y el acceso es solo con URL firmada.


Cardinalidad resumen

Relación Cardinalidad Significado
User → LockerCode 1:1 Cada usuario tiene un identificador activo
User → KycRecord 1:0..1 Puede tener KYC o no
User → Address 1:N Múltiples direcciones (casillero, residencia)
User → PurchaseReport 1:N Múltiples prealertas
User → PhysicalPackage 1:N Múltiples paquetes
PurchaseReport → TrackingNumber 1:N Múltiples trackings por prealerta
PurchaseReport → PurchaseItem 1:N Múltiples productos por reporte
PhysicalPackage → PackageEvent 1:N Historial completo de cambios
Consolidation → PhysicalPackage N:N vía ConsolidationPackage
Shipment → Payment 1:N Múltiples pagos posibles (parcialidades)
Payment → PaymentAttempt 1:N Historial de intentos

Notas de diseño

  • Patrón polimórfico: FileAttachment usa owner_type + owner_id para asociarse a cualquier entidad sin FK rígida.
  • Soft delete: entidades como User, Recipient, PurchaseReport usan deleted_at en lugar de DELETE físico.
  • Inmutabilidad: PackageEvent, AuditLog, CreditMovement son append-only.
  • Enums como strings: para serialización y compatibilidad con múltiples lenguajes.
  • Timestamps universales: todas las fechas en UTC en BD, conversión a zona local en frontend.

Cómo se traduce a tablas SQL

Ver modelo de datos para el detalle relacional.