Skip to main content

Overview

Inventario implements a role-based access control (RBAC) system with two primary roles: Admin and Vendedor (Salesperson). Each role has distinct permissions and access levels throughout the system.

User Model

Roles are defined directly in the Usuario model:
class Usuario(AbstractUser):
    ROLES = (
        ('admin', 'Administrador'),
        ('vendedor', 'Vendedor'),
    )

    rol = models.CharField(max_length=20, choices=ROLES, default='admin')
    
    # Hierarchical relationship
    creado_por = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='vendedores_creados'
    )

    def __str__(self):
        return f"{self.username} ({self.get_rol_display()})"
The creado_por field creates a hierarchical relationship where admins can create and manage their vendedor accounts.

Admin Role

Capabilities

Administrators have full access to the system:

User Management

Create, edit, and delete vendedor accounts

Dashboard Access

View comprehensive analytics and insights

Inventory Control

Manage products, suppliers, and stock levels

Financial Reports

Access sales reports, expenses, and profit analysis

Configuration

Configure invoice settings and system preferences

Purchase Management

Record purchases and manage expenses

Client Management

Manage client database and relationships

AI Features

Access AI-powered insights and recommendations

Admin-Only Views

Certain views are restricted to admins using the @admin_required decorator:
applications/cuentas/decorators.py
def admin_required(view_func):
    """🔒 Permite acceso solo a administradores"""
    def wrapper(request, *args, **kwargs):
        if not request.user.is_authenticated:
            messages.error(request, 'Debes iniciar sesión para continuar.')
            return redirect('login')

        if request.user.rol == 'admin':
            return view_func(request, *args, **kwargs)
        else:
            messages.warning(request, 'Acceso restringido a administradores.')
            return redirect('ventas:lista_ventas')
    return wrapper
applications/cuentas/views.py
@admin_required
@login_required
@no_cache
def dashboard(request):
    # Dashboard logic with hierarchical data filtering
    usuarios_ids = get_subordinate_ids(request.user)
    # ... analytics and reporting logic
The dashboard uses get_subordinate_ids() to show data only for the admin and their vendedores.

Vendedor Role

Capabilities

Vendedores (Salespeople) have focused access to sales operations:

Sales Management

Create and view their own sales transactions

Product Catalog

View available products and inventory

Client Information

Access client information for sales

Invoice Generation

Generate invoices for their sales

Vendedor Restrictions

Vendedores cannot:
  • Access the admin dashboard
  • Create or manage other users
  • Modify product inventory or prices
  • View financial reports or analytics
  • Access purchase management
  • Change system configuration
  • View sales from other vendedores

Vendedor-Only Decorator

applications/cuentas/decorators.py
def vendedor_required(view_func):
    """🛒 Permite acceso solo a vendedores"""
    def wrapper(request, *args, **kwargs):
        if not request.user.is_authenticated:
            messages.error(request, 'Debes iniciar sesión para continuar.')
            return redirect('login')

        if request.user.rol == 'vendedor':
            return view_func(request, *args, **kwargs)
        else:
            messages.warning(request, 'Acceso restringido a vendedores.')
            return redirect('dashboard')
    return wrapper

Role Assignment

Creating Vendedor Accounts

Only admins can create vendedor accounts through the user management interface:
1

Admin Accesses User List

Navigate to the user management section (restricted to admins).
2

Create New User

Fill out the user creation form:
class UsuarioForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Limit role choices to 'Vendedor' only
        self.fields['rol'].choices = [('vendedor', 'Vendedor')]
3

Automatic Assignment

The system automatically assigns the creating admin as the vendedor’s supervisor:
nuevo_usuario = form.save(commit=False)
nuevo_usuario.creado_por = request.user
nuevo_usuario.save()
4

Password Setup

New vendedores receive a temporary password and are required to change it on first login:
nuevo_usuario.debe_cambiar_password = True
Security Note: The user creation form only allows admins to create vendedor accounts. Admins cannot create other admin accounts through the UI.

User Form Configuration

class UsuarioForm(forms.ModelForm):
    password = forms.CharField(
        widget=forms.PasswordInput(attrs={
            'class': 'form-control password-input',
            'placeholder': 'Dejar vacío para no cambiar'
        }),
        label="Contraseña",
        required=False
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if not self.instance.pk:
            self.fields['password'].required = True
        
        # 🔹 Limit role options to 'Vendedor' only
        self.fields['rol'].choices = [('vendedor', 'Vendedor')]

    class Meta:
        model = Usuario
        fields = ['username', 'nombre', 'apellido', 'email', 'telefono', 'rol', 'password']

Hierarchical Data Access

Subordinate Filtering

Admins only see data for themselves and their vendedores:
applications/cuentas/utils.py
def get_subordinate_ids(user):
    """
    Returns list of user IDs including the user and all vendedores created by them.
    """
    if user.rol == 'admin':
        subordinates = Usuario.objects.filter(creado_por=user).values_list('id', flat=True)
        return [user.id] + list(subordinates)
    return [user.id]

Application in Views

@admin_required
@login_required
def dashboard(request):
    # Filter data hierarchically
    usuarios_ids = get_subordinate_ids(request.user)
    
    # Query only relevant data
    detalles = DetalleVenta.objects.filter(
        venta__fecha_venta__gte=inicio,
        venta__vendedor__id__in=usuarios_ids
    )
This hierarchical model ensures data isolation between different admin accounts and their vendedor teams.

Multi-User Workflows

Sales Attribution

Each sale is automatically attributed to the logged-in user:
venta.vendedor = request.user
venta.save()

Reporting & Analytics

Admins can:
  • View aggregated sales across their team
  • Compare performance between vendedores
  • Filter reports by vendedor
  • Track individual contributions
The dashboard automatically aggregates data from all subordinate vendedores, providing a complete view of team performance.

Login Redirects

Users are automatically redirected based on their role after login:
applications/cuentas/views.py
if usuario:
    login(request, usuario)
    messages.success(request, f'Bienvenido {usuario.username}')

    # Role-based redirect
    if usuario.is_superuser:
        return redirect('/admin/')
    elif usuario.rol == 'admin':
        return redirect('dashboard')
    elif usuario.rol == 'vendedor':
        return redirect('ventas:lista_ventas')
    return redirect('home')

Superuser

/admin/ (Django admin panel)

Admin

/dashboard/ (Analytics dashboard)

Vendedor

→ Sales list (Operational view)

Permission Management

User List Access Control

applications/usuarios/views.py
@login_required
@admin_required
def lista_usuarios(request):
    # Show only users created by the current admin
    usuarios_list = Usuario.objects.filter(creado_por=request.user)
    
    paginator = Paginator(usuarios_list, 7)
    # ... pagination logic

Edit/Delete Restrictions

Admins can only edit/delete vendedores they created:
applications/usuarios/views.py
@login_required
@admin_required
def editar_usuario(request, id):
    # Ensures admin can only edit their own vendedores
    usuario = get_object_or_404(Usuario, id=id, creado_por=request.user)
    # ... edit logic

@login_required
@admin_required
def eliminar_usuario(request, id):
    # Ensures admin can only delete their own vendedores
    usuario = get_object_or_404(Usuario, id=id, creado_por=request.user)
    # ... delete logic
Cascade Deletion: When an admin account is deleted, all vendedor accounts created by that admin are also deleted due to the on_delete=models.CASCADE relationship.

Best Practices

  • Always assign vendedores to the correct admin supervisor
  • Require password changes for new vendedor accounts
  • Use strong password validation rules
  • Regularly audit user accounts and permissions
  • Always filter queries using get_subordinate_ids()
  • Verify ownership before allowing edits/deletes
  • Use get_object_or_404 with ownership filters
  • Test multi-admin scenarios thoroughly
  • Apply @admin_required to sensitive views
  • Use @vendedor_required for role-specific features
  • Combine with @login_required for authentication
  • Implement proper error messages for unauthorized access

Authentication

Learn about login methods and security

Profile Management

Manage user profiles and settings

Security Configuration

Advanced security and access control

Authentication API

Programmatic authentication and user management

Build docs developers (and LLMs) love