Skip to main content
The business onboarding workflow in BeanQuick is a multi-step process that ensures only verified businesses can sell on the platform. This guide walks through each stage from initial application to active seller status.

Workflow Overview

The workflow involves three main parties: the business applicant, the admin, and the system’s automated processes.

Step 1: Business Registration Request

Businesses begin by submitting an application through the public registration form.

Application Data

SolicitudEmpresa.php:14-25
protected $fillable = [
    'nombre',
    'correo',
    'nit',
    'telefono',
    'direccion',
    'descripcion',
    'logo',
    'foto_local',
    'estado',    // 'pendiente', 'aprobado', 'rechazado'
    'token',     // Token de seguridad para la activación
];

Submission Process

1

Fill Application Form

Business provides:
  • Company name and contact email
  • NIT (tax ID), phone, and address
  • Business description
  • Logo image (max 2MB: jpeg, png, jpg, webp)
  • Storefront photo (max 4MB: jpeg, png, jpg, webp)
2

Upload Images

Images are stored temporarily in the solicitudes/ directory:
  • Logo: storage/solicitudes/logos/
  • Storefront: storage/solicitudes/locales/
3

Submit to API

POST /api/solicitud-empresa
Content-Type: multipart/form-data
4

Record Created

A SolicitudEmpresa record is created with status pendiente

API Response

{
  "status": "success",
  "message": "Tu solicitud fue enviada correctamente. Nuestro equipo la revisará pronto.",
  "solicitud_id": 1
}
At this stage, no user account is created yet. The application waits for admin review.

Step 2: Admin Review

Administrators review pending applications from their dashboard.

Viewing Pending Applications

GET /api/admin/solicitudes
Returns all applications with estado = 'pendiente':
AdminController.php:34
'solicitudes' => SolicitudEmpresa::where('estado', 'pendiente')->get(),

Admin Decision Points

Action: POST /api/admin/aprobar/{id}When approved:
  1. Generate a secure 60-character token
  2. Update application status to aprobado
  3. Store the token in the database
  4. Send activation email to the business
AdminController.php:43-54
public function aprobar($id): JsonResponse
{
    $solicitud = SolicitudEmpresa::findOrFail($id);
    $token = Str::random(60);
    
    $solicitud->update([
        'estado' => 'aprobado',
        'token'  => $token 
    ]);
    
    $link = "http://localhost:5173/empresa/activar/" . $token;
    Mail::to($solicitud->correo)->send(new ActivacionEmpresaMail($solicitud, $link));
    // ...
}
The business receives an email with a unique activation link valid for their application.

Step 3: Email Activation

Approved businesses receive an activation email with a unique link.

Email Contents

  • Subject: Account approval notification
  • Body: Welcome message and activation instructions
  • Link: http://localhost:5173/empresa/activar/{token}
The token in the URL is a 60-character random string that serves as a one-time activation key.

Token Validation

When the business clicks the link:
GET /api/empresa/validar-token/{token}
EmpresaActivacionController.php:20-35
public function validarToken($token): JsonResponse
{
    $solicitud = SolicitudEmpresa::where('token', $token)
        ->where('estado', 'aprobado')
        ->first();

    if (!$solicitud) {
        return response()->json([
            'message' => 'El enlace de activación no es válido o ya fue usado.'
        ], 404);
    }

    return response()->json([
        'status' => 'success',
        'solicitud' => $solicitud
    ]);
}
If valid, the frontend displays the activation form pre-filled with business details.

Step 4: Account Activation

The business completes activation by setting their password.

Activation Process

1

Password Setup

Business enters and confirms their password (minimum 8 characters)
2

Submit Activation

POST /api/empresa/activar/{token}
{
  "password": "securepassword123",
  "password_confirmation": "securepassword123"
}
3

Database Transaction

The system performs several operations atomically:a) Create User Account
EmpresaActivacionController.php:64-70
$user = User::create([
    'name' => $solicitud->nombre,
    'email' => $solicitud->correo,
    'password' => Hash::make($request->password),
    'rol' => 'empresa',
]);
b) Move Images to Permanent Storage
  • Logo: solicitudes/logos/empresas/logos/
  • Photo: solicitudes/locales/empresas/locales/
c) Create Empresa Record
EmpresaActivacionController.php:108-109
$empresa = Empresa::create($empresaData);
d) Update Application Status
EmpresaActivacionController.php:112-115
$solicitud->update([
    'estado' => 'completada',
    'token' => null,  // Invalidate token
]);
e) Clean Up Temporary Files
EmpresaActivacionController.php:118-119
if ($solicitud->logo) Storage::disk('public')->delete($solicitud->logo);
if ($solicitud->foto_local) Storage::disk('public')->delete($solicitud->foto_local);
4

Account Created

Business receives confirmation and can now log in

Success Response

{
  "status": "success",
  "message": "Cuenta creada exitosamente. Ya puedes iniciar sesión.",
  "user": {
    "id": 5,
    "name": "Café Delicioso",
    "email": "[email protected]",
    "rol": "empresa"
  }
}
The business is now fully registered and can log in using their email and password.

Application States

The estado field tracks the application’s progress:
Initial state after form submission
  • Application awaits admin review
  • Visible in admin dashboard
  • No user account exists yet
After admin approval
  • Activation email sent
  • Token generated and stored
  • Awaiting business activation
After admin rejection
  • Application denied
  • No further action taken
  • Record kept for audit purposes
After successful activation
  • User and Empresa records created
  • Token invalidated (set to null)
  • Images moved to permanent storage
  • Business can now log in

Post-Activation: Business Setup

Once activated, businesses gain access to their dashboard and can:

Update Profile

Modify business information, logo, and photos via:
POST /api/empresa/update

Add Products

Create their product catalog:
POST /api/empresa/productos

Set Availability

Toggle open/closed status:
POST /api/empresa/toggle-estado

Receive Orders

View and fulfill customer orders:
GET /api/empresa/pedidos

Key Relationships

User ↔ Empresa

Each business has one user account and one empresa profile:
User.php:29-32
public function empresa()
{
    return $this->hasOne(Empresa::class, 'user_id');
}
Empresa.php:47-50
public function usuario()
{
    return $this->belongsTo(User::class, 'user_id');
}

Database Schema

users
  ├── id (PK)
  ├── name
  ├── email
  ├── password
  └── rol = 'empresa'

empresas
  ├── id (PK)
  ├── user_id (FK → users.id)
  ├── nombre
  ├── nit
  ├── direccion
  ├── telefono
  ├── descripcion
  ├── logo
  ├── foto_local
  └── is_open

solicitudes_empresas
  ├── id (PK)
  ├── nombre
  ├── correo
  ├── nit
  ├── estado ('pendiente', 'aprobado', 'rechazado', 'completada')
  └── token (nullable)

Error Handling

Common issues and their solutions:

Invalid Token

Problem: Token doesn’t exist or was already used
{
  "message": "El enlace de activación no es válido o ya fue usado."
}
Solution: Business must request a new approval from admin

Duplicate Email

Problem: Email already registered in users table
{
  "message": "Ya existe una cuenta con este correo."
}
Solution: Use different email or contact admin to resolve

Email Delivery Failure

Problem: Mail server error during approval
AdminController.php:67-73
catch (\Exception $e) {
    return response()->json([
        'message' => 'Solicitud aprobada pero hubo un error al enviar el correo.',
        'error'   => $e->getMessage()
    ], 500);
}
Solution: Application is still approved; admin can manually send activation link

Security Considerations

Security Features

  • One-time tokens: 60-character random strings, invalidated after use
  • Email verification: Ensures applicant owns the email address
  • Admin approval: Prevents automated spam registrations
  • Password hashing: Passwords stored using bcrypt
  • Transaction safety: Database rollback on any activation failure

Workflow Diagram with Code References

┌─────────────────────────────────────────────────────────────┐
│ 1. REGISTRATION                                             │
│    POST /api/solicitud-empresa                              │
│    → SolicitudEmpresaController::store()                    │
│    → Creates record with estado='pendiente'                 │
└─────────────────────────────────────────────────────────────┘
                           |
                           v
┌─────────────────────────────────────────────────────────────┐
│ 2. ADMIN REVIEW                                             │
│    GET /api/admin/solicitudes                               │
│    → AdminController::dashboard()                           │
│                                                             │
│    APPROVE: POST /api/admin/aprobar/{id}                    │
│    → Generate token, send email, estado='aprobado'          │
│                                                             │
│    REJECT: POST /api/admin/rechazar/{id}                    │
│    → Set estado='rechazado', end process                    │
└─────────────────────────────────────────────────────────────┘
                           |
                           v
┌─────────────────────────────────────────────────────────────┐
│ 3. EMAIL & VALIDATION                                       │
│    GET /api/empresa/validar-token/{token}                   │
│    → EmpresaActivacionController::validarToken()            │
│    → Verifies token exists and estado='aprobado'            │
└─────────────────────────────────────────────────────────────┘
                           |
                           v
┌─────────────────────────────────────────────────────────────┐
│ 4. ACTIVATION                                               │
│    POST /api/empresa/activar/{token}                        │
│    → EmpresaActivacionController::store()                   │
│    → Creates User (rol='empresa')                           │
│    → Creates Empresa                                        │
│    → Moves images to permanent storage                      │
│    → Updates estado='completada', nullifies token           │
└─────────────────────────────────────────────────────────────┘
                           |
                           v
┌─────────────────────────────────────────────────────────────┐
│ 5. ACTIVE BUSINESS                                          │
│    POST /api/login                                          │
│    → Business can now authenticate and access dashboard     │
└─────────────────────────────────────────────────────────────┘

Testing the Workflow

1

Submit Application

curl -X POST http://localhost:8000/api/solicitud-empresa \
  -F "nombre=Mi Cafetería" \
  -F "[email protected]" \
  -F "nit=123456789" \
  -F "[email protected]" \
  -F "[email protected]"
2

Admin Approves

curl -X POST http://localhost:8000/api/admin/aprobar/1 \
  -H "Authorization: Bearer {admin_token}"
3

Validate Token

curl http://localhost:8000/api/empresa/validar-token/{token}
4

Activate Account

curl -X POST http://localhost:8000/api/empresa/activar/{token} \
  -H "Content-Type: application/json" \
  -d '{
    "password": "SecurePass123",
    "password_confirmation": "SecurePass123"
  }'
5

Login as Business

curl -X POST http://localhost:8000/api/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "SecurePass123"
  }'

Next Steps

User Roles

Learn about business permissions and capabilities

Order Lifecycle

Understand how businesses fulfill customer orders

Build docs developers (and LLMs) love