Módulo: Vacantes
Scope
| Tipo de organización | Acceso |
|---|---|
| Empresa | ✅ |
| Agencia | ✅ |
| Reclutador independiente | ✅ |
Permisos por rol
Empresa (COMPANY)
| Acción | Disponible | Permiso |
|---|---|---|
| Ver lista de vacantes propias | ✅ | vacancies:read |
| Crear vacante borrador | ✅ | vacancies:create |
| Editar vacante borrador | ✅ | vacancies:create |
| Publicar vacante | ✅ | vacancies:publish |
| Ver detalle de vacante | ✅ | vacancies:read |
| Ver participantes de una vacante | ✅ | vacancies:read |
| Ver vacantes compatibles | ❌ | — |
| Tomar vacante | ❌ | — |
Agencia (AGENCY)
| Acción | Disponible | Permiso |
|---|---|---|
| Ver lista de vacantes propias | ❌ | — |
| Crear vacante borrador | ❌ | — |
| Editar vacante borrador | ❌ | — |
| Publicar vacante | ❌ | — |
| Ver vacantes compatibles | ✅ | vacancies:read |
| Ver detalle de vacante compatible | ✅ | vacancies:read |
| Tomar vacante (seleccionar reclutador del equipo) | ✅ | vacancies:take |
| Ver participantes de una vacante | ❌ | — |
Reclutador independiente (RECRUITER)
| Acción | Disponible | Permiso |
|---|---|---|
| Ver lista de vacantes propias | ❌ | — |
| Crear vacante borrador | ❌ | — |
| Editar vacante borrador | ❌ | — |
| Publicar vacante | ❌ | — |
| Ver vacantes compatibles | ✅ | vacancies:read |
| Ver detalle de vacante compatible | ✅ | vacancies:read |
| Tomar vacante (auto-asignado desde sesión) | ✅ | vacancies:take |
| Ver participantes de una vacante | ❌ | — |
¿Qué es?
El módulo de Vacantes es el núcleo operativo de Contratta. Las empresas publican posiciones de reclutamiento con un incentivo económico, y las agencias/reclutadores independientes las visualizan según compatibilidad de especialidad y cobertura geográfica para tomarlas y registrar candidatos.
¿Qué puede hacer el usuario?
Empresa
- Crear vacantes en borrador con título, categoría, ubicación, modalidad, tipo de contrato, horario, nivel de seniority, volumen de cobertura, sector industrial e incentivo económico
- Editar vacantes en borrador
- Publicar vacantes cuando cumple readiness operativo
- Ver lista paginada con filtros de status y categoría
- Ver participantes (reclutadores que tomaron la vacante)
- Ver detalle completo con conteos de candidatos y participantes
Agencia / Reclutador
- Ver vacantes compatibles publicadas (match por especialidad/cobertura)
- Tomar vacantes para comenzar a registrar candidatos
- Ver detalle de vacante con reclutadores compatibles del equipo
- Ver si ya tomó la vacante (idempotente)
Flujo del usuario
Empresa
1. Abre "Mis Vacantes" desde la navegación
2. Ve lista de vacantes propias con filtros por status
3. Presiona "Nueva" → formulario de creación con catálogos
4. Llena datos obligatorios (título, categoría, incentivo mínimo $1,000 MXN)
5. Guarda como borrador
6. Edita si necesita ajustar
7. Presiona "Publicar" → validación de readiness → vacante visible para reclutadores
8. Ve participantes que toman la vacante
Agencia / Reclutador
1. Abre "Vacantes Compatibles" desde la navegación
2. Ve vacantes publicadas que coinciden con su especialidad/cobertura
3. Selecciona una vacante → ve detalle con reclutadores compatibles del equipo
4. Presiona "Tomar" → selecciona reclutador (agencia) o auto-asignado (independiente)
5. Comienza a registrar candidatos para esa vacante
Reglas de negocio
- Incentivo mínimo MVP: MXN $1,000.00 (100,000 centavos)
- Solo vacantes en estado
DRAFTse pueden editar o publicar - Publicar requiere empresa APPROVED + readiness completo (políticas aceptadas, datos fiscales)
- Compatibilidad: specialties del reclutador ↔ category de la vacante, coverage ↔ location
- Tomar es no-exclusivo: múltiples reclutadores pueden tomar la misma vacante
- Tomar es idempotente: re-tomar restaura participación soft-deleted
- Agencias deben seleccionar un
recruiterIdde su equipo aprobado - Reclutador independiente se resuelve automáticamente desde la sesión
Arquitectura
lib/features/vacancies/
├── application/
│ ├── vacancies_cubit.dart # Lógica por rol + infinite scroll
│ └── vacancies_state.dart # VacancyRole enum (company/marketplace)
├── data/
│ ├── datasources/
│ │ └── vacancies_remote_datasource.dart # Abstract + Impl (typed Dio calls)
│ ├── models/
│ │ ├── vacancy_model.dart # VacancyModel extends Vacancy (fromJson/toJson)
│ │ └── participant_model.dart # ParticipantModel extends Participant (fromJson/toJson)
│ └── repositories/
│ └── vacancies_repository_impl.dart
├── domain/
│ ├── entities/
│ │ ├── vacancy.dart # Equatable entity (immutable, typed fields)
│ │ └── participant.dart # Equatable entity (immutable, typed fields)
│ └── repositories/
│ └── vacancies_repository.dart
└── presentation/
└── pages/
├── vacancies_page.dart
├── create_vacancy_page.dart
├── edit_vacancy_page.dart
├── vacancy_detail_page.dart
└── vacancy_participants_page.dart
Endpoints API (sin prefijo /api)
| Método | Endpoint | Rol | Descripción |
|---|---|---|---|
| GET | /vacancies | Empresa | Lista vacantes propias (paginado, filtros) |
| GET | /vacancies/compatible | Agencia/Reclutador | Lista vacantes compatibles |
| GET | /vacancies/:id | Todos | Detalle de vacante |
| POST | /vacancies | Empresa | Crear borrador |
| PUT | /vacancies/:id | Empresa | Actualizar borrador |
| PATCH | /vacancies/:id/publish | Empresa | Publicar borrador |
| POST | /vacancies/:id/take | Agencia/Reclutador | Tomar vacante |
| GET | /vacancies/:id/participants | Empresa | Lista participantes |
Catálogos utilizados
Los campos opcionales de una vacante se alimentan de catálogos dinámicos del backend:
| Campo | Catálogo |
|---|---|
| modality | WORK_MODALITY |
| contractType | CONTRACT_TYPE |
| workSchedule | WORK_SCHEDULE |
| seniorityLevel | SENIORITY_LEVEL |
| coverageVolume | COVERAGE_VOLUME |
| industrySector | INDUSTRY_SECTOR |
Registro DI
- Datasource:
LazySingleton - Repository:
LazySingleton - Cubit:
FactoryParam<String>(recibeorgTypepara determinar rol)
getIt<VacanciesCubit>(param1: orgType)
Localización
✅ Completada — todos los strings de la capa de presentación usan context.l10n.vacanciesXxx.
Claves con prefijo vacancies en lib/l10n/app_es.arb y lib/l10n/app_en.arb.