Modelos de Base de Datos
Este documento describe los modelos de Django que componen la base de datos de
NoxPanel. Todos los modelos utilizan PostgreSQL 15 como motor y
BigAutoField como campo de clave primaria por defecto (excepto donde se
usa UUIDField).
App: accounts
User
Modelo de usuario personalizado que extiende AbstractUser de Django.
Implementa control de acceso basado en roles y permisos por módulo.
Campo |
Tipo |
Descripción |
|---|---|---|
|
EmailField (unique) |
Dirección de email principal del usuario. |
|
CharField |
Rol del usuario: |
|
BooleanField |
Indica si el email ha sido verificado. |
|
CharField |
Usuario asociado en Proxmox VE (opcional). |
|
BooleanField |
Permiso para gestionar máquinas virtuales. |
|
IntegerField |
Número máximo de VMs que puede crear (default: 5). |
|
BooleanField |
Acceso al módulo de VPS & VMs. |
|
BooleanField |
Acceso al módulo de Hosting. |
|
BooleanField |
Acceso al módulo de Facturación. |
|
BooleanField |
Acceso al módulo de Tickets. |
|
CharField |
Teléfono de contacto (opcional). |
|
CharField |
Nombre de la empresa (opcional). |
|
DateTimeField |
Fecha de creación (automática). |
|
DateTimeField |
Última modificación (automática). |
Tabla: users
Índices: email, role
Métodos principales:
is_admin/is_client: Propiedades para verificar el rol.has_admin_access(): Verifica acceso admin (superuser o rol admin).has_module_access(module_name): Verificación genérica de acceso a módulo.can_create_vm(): Verifica si la cuota de VMs permite crear más.
App: hosting
HostingPackage
Paquetes predefinidos de hosting (S, M, XL, XXL) que definen cuotas estándar.
Campo |
Tipo |
Descripción |
|---|---|---|
|
CharField (unique) |
Nombre del paquete. |
|
SlugField (unique) |
Identificador URL-friendly. |
|
IntegerField |
Máximo de sitios web (default: 5). |
|
IntegerField |
Máximo de bases de datos (default: 3). |
|
IntegerField |
Máximo de dominios (default: 5). |
|
IntegerField |
Almacenamiento máximo en GB (default: 5). |
|
IntegerField |
Máximo de cuentas FTP (default: 3). |
|
IntegerField |
Máximo de buzones de email (default: 5). |
|
IntegerField |
Máximo de alias de email (default: 10). |
|
IntegerField |
Máximo de usuarios shell (default: 1). |
|
DecimalField |
Precio mensual (opcional). |
|
DecimalField |
Precio anual (opcional). |
|
BooleanField |
Paquete activo para nuevas asignaciones. |
|
BooleanField |
Paquete destacado en la interfaz. |
Tabla: hosting_packages
HostingTenant
Modelo central del sistema multi-tenant. Representa una organización que utiliza el panel de hosting con recursos y cuotas independientes.
Campo |
Tipo |
Descripción |
|---|---|---|
|
CharField (unique) |
Nombre de la organización. |
|
SlugField (unique) |
Slug único para URLs y referencias internas. |
|
EmailField |
Email de contacto principal. |
|
BooleanField |
Tenant activo o suspendido. |
|
FK → HostingPackage |
Paquete de hosting asignado (opcional). |
|
IntegerField |
Cuota de sitios web (default: 10). |
|
IntegerField |
Cuota de bases de datos (default: 5). |
|
IntegerField |
Cuota de dominios (default: 5). |
|
IntegerField |
Cuota de almacenamiento en GB (default: 10). |
|
IntegerField |
Cuota de cuentas FTP (default: 5). |
|
IntegerField |
Cuota de buzones (default: 10). |
|
IntegerField |
Cuota de alias de email (default: 20). |
|
IntegerField |
Cuota de usuarios shell (default: 1). |
|
FK → User |
Usuario que creó el tenant. |
Tabla: hosting_tenants
Índices: slug, is_active
Métodos principales:
can_create_site()/can_create_database()/can_create_domain(): Verifican si la cuota permite crear más recursos.apply_package_quotas(): Copia las cuotas del paquete asignado al tenant.get_sites_count()/get_databases_count(): Conteo de recursos activos.
TenantUser
Relación muchos-a-muchos entre usuarios y tenants con roles diferenciados.
Campo |
Tipo |
Descripción |
|---|---|---|
|
FK → HostingTenant |
Tenant al que pertenece. |
|
FK → User |
Usuario Django. |
|
CharField |
Rol: |
|
BooleanField |
Membresía activa. |
Tabla: tenant_users | Restricción: unique_together = [tenant, user]
HostingClient
Mapeo entre un usuario Django/tenant y un cliente en el motor de hosting.
Campo |
Tipo |
Descripción |
|---|---|---|
|
FK → HostingTenant |
Tenant asociado. |
|
OneToOne → User |
Usuario Django asociado. |
|
IntegerField (unique) |
ID del cliente en el motor de hosting. |
|
CharField |
Nombre de usuario en el motor de hosting. |
|
CharField |
Contraseña (encriptada) del cliente en el motor de hosting. |
|
DateTimeField |
Última sincronización con el motor de hosting. |
Tabla: hosting_clients
HostingSite, HostingDatabase, HostingDomain
Modelos que representan los recursos de hosting gestionados vía el motor de hosting. Todos comparten una estructura similar con los campos:
tenant(FK → HostingTenant): Tenant propietario.hosting_client(FK → HostingClient): Cliente del motor de hosting asociado.hosting_*_id(IntegerField): ID del recurso en el motor de hosting.is_active(BooleanField): Estado del recurso (soft-delete).created_at/updated_at: Timestamps automáticos.
Campos específicos:
HostingSite (
hosting_sites):domain,ip_address,document_root,ssl_enabled.HostingDatabase (
hosting_databases):name,db_user,db_password(encriptada).HostingDomain (
hosting_domains):domain(unique),dns_enabled.
HostingFTPAccount, HostingMailbox, HostingMailAlias
Recursos adicionales de hosting, todos vinculados a un tenant:
HostingFTPAccount (
hosting_ftp_accounts):username,password,directory,quota_mb. FK → HostingSite.HostingMailbox (
hosting_mailboxes):email(unique),local_part,quota_mb,imap_enabled,pop3_enabled,smtp_enabled. FK → HostingMailDomain.HostingMailAlias (
hosting_mail_aliases):source,destination. FK → HostingMailDomain.
HostingDNSZone y HostingDNSRecord
Gestión de DNS:
HostingDNSZone (
hosting_dns_zones):origin(unique),ns_primary,admin_email,ttl. FK → HostingTenant.HostingDNSRecord (
hosting_dns_records):record_type(A, AAAA, CNAME, MX, TXT, NS, SRV, CAA, PTR),name,data,priority,ttl. FK → HostingDNSZone.
HostingShellUser y HostingSSLCertificate
HostingShellUser (
hosting_shell_users):username,shell(default:/bin/bash),home_directory. FK → HostingSite.HostingSSLCertificate (
hosting_ssl_certificates):cert_type(letsencrypt, custom, self_signed),domain,expires_at,certificate,private_key,ca_bundle,auto_renew. FK → HostingSite.
App: billing
BillingProfile
Datos fiscales de un tenant para facturación.
Campo |
Tipo |
Descripción |
|---|---|---|
|
OneToOne → HostingTenant |
Tenant asociado. |
|
CharField |
Razón social. |
|
CharField |
NIF/CIF/VAT. |
|
CharField |
Dirección fiscal. |
|
CharField |
Ubicación (country: ISO 3166-1 alpha-2). |
|
EmailField |
Email para envío de facturas. |
|
CharField |
ID del cliente en Stripe. |
|
CharField |
ID del pagador en PayPal. |
|
CharField |
Moneda preferida (default: EUR). |
|
BooleanField |
Cobro automático activado. |
Tabla: billing_profiles
PricingPlan
Planes de precios configurables por el administrador.
resource_type:hosting,vps,addon.billing_period:hourly,daily,monthly,yearly.price: Precio por periodo (DecimalField 10,4).setup_fee: Cuota de alta.tax_rate: Porcentaje de IVA (default: 21%).hosting_package: FK opcional → HostingPackage.
Tabla: billing_pricing_plans
Subscription
Suscripción activa que enlaza un tenant con un plan de precios.
id: UUIDField (clave primaria).status:active,paused,cancelled,past_due,trial.custom_price: Override de precio por cliente.resource_type/resource_id/resource_name: Recurso vinculado.stripe_subscription_id/paypal_subscription_id: IDs externos.started_at/current_period_start/current_period_end: Fechas.
Tabla: billing_subscriptions
Invoice e InvoiceItem
Facturación:
Invoice (
billing_invoices):number(INV-2026-0001),status(draft, pending, paid, overdue, cancelled, refunded),subtotal,tax_rate,tax_amount,total,currency. Snapshot inmutable de datos fiscales (billing_name,billing_tax_id,billing_address).InvoiceItem (
billing_invoice_items): Líneas de factura condescription,quantity,unit_price,total.
Payment y PaymentMethod
Payment (
billing_payments):gateway(stripe, paypal, bank_transfer, manual),status,amount,gateway_payment_id,gateway_response(JSONField).PaymentMethod (
billing_payment_methods):method_type(card, sepa, paypal, bank_transfer),is_default,stripe_payment_method_id.
UsageRecord
Registros de consumo para facturación por horas o por uso.
subscription: FK → Subscription.resource_type/resource_id: Recurso consumido.quantity/unit/unit_price/total: Datos de consumo.invoiced: Boolean para marcar si ya fue incluido en una factura.
Tabla: billing_usage_records
WebhookEvent
Log de webhooks recibidos de Stripe y PayPal para auditoría y
reprocesamiento: gateway, event_id (unique), event_type,
payload (JSONField), processed.
Tabla: billing_webhook_events
App: ticketing
MailAccount
Cuenta de email configurada para recibir y enviar tickets.
Campo |
Tipo |
Descripción |
|---|---|---|
|
EmailField (unique) |
Dirección de email. |
|
CharField |
Protocolo: |
|
CharField / IntegerField |
Servidor y puerto de entrada (default: 993). |
|
CharField / IntegerField |
Servidor SMTP y puerto (default: 587). |
|
TextField |
Contraseña cifrada con Fernet. |
|
CharField / TextField |
Credenciales OAuth2 (cifradas). |
|
CharField |
Azure AD Tenant ID (para Microsoft 365). |
|
TextField |
Tokens OAuth2 cifrados. |
|
FK → Department |
Departamento por defecto para tickets nuevos. |
Tabla: ticketing_mail_accounts
Department
Departamentos organizacionales: name, slug, email, manager
(FK → User).
Tabla: ticketing_departments
SLAPolicy
Políticas de nivel de servicio por prioridad:
priority:low,medium,high,urgent,critical(unique).first_response_hours: Horas máximas para primera respuesta.resolution_hours: Horas máximas para resolución completa.
Tabla: ticketing_sla_policies
Ticket
Modelo principal del sistema de tickets.
id: UUIDField (clave primaria).number: FormatoTK-000123(auto-generado, unique).subject: Asunto del ticket.tenant: FK → HostingTenant (opcional).requester/requester_email/requester_name: Solicitante.assigned_to: FK → User (agente asignado).department: FK → Department.status:new,open,pending,on_hold,resolved,closed.priority:low,medium,high,urgent,critical.source:web,email,api,phone.tags: M2M → TicketTag.sla_policy/sla_first_response_due/sla_resolution_due: SLA.email_message_id: Message-ID del email original (para threading).
Tabla: ticketing_tickets
Índices: [status, priority], [assigned_to, status], [tenant, status]
TicketMessage, TicketAttachment, CannedResponse
TicketMessage (
ticketing_messages):ticket(FK),author,message_type(reply, note, system),body/body_html,is_from_agent.TicketAttachment (
ticketing_attachments):file(FileField),filename,content_type,size_bytes.CannedResponse (
ticketing_canned_responses): Respuestas predefinidas contitle,body,department(FK opcional).
Diagrama de Relaciones
User ─────────────┬──── TenantUser ──── HostingTenant
│ │
│ ┌────────────────┼────────────────┐
│ │ │ │
HostingClient │ HostingPackage BillingProfile
│ │ │
┌──────┼─────┐ │ Subscription
│ │ │ │ │
HostingSite │ HostingDB HostingDomain Invoice ── InvoiceItem
│ │ │
┌────────┤ │ Payment
│ │ │
FTPAccount │ HostingMailDomain ── HostingMailbox
ShellUser │ HostingMailAlias
SSLCert │
│
HostingDNSZone ── HostingDNSRecord
Ticket ──── TicketMessage ──── TicketAttachment
│
Department, SLAPolicy, TicketTag