Saltar al contenido principal
Versión: 1.0

Módulo: Vacantes

Scope​

Tipo de organizaciónAcceso
Empresa✅
Agencia✅
Reclutador independiente✅

Permisos por rol​

Empresa (COMPANY)​

AcciónDisponiblePermiso
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ónDisponiblePermiso
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ónDisponiblePermiso
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 DRAFT se 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 recruiterId de 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étodoEndpointRolDescripción
GET/vacanciesEmpresaLista vacantes propias (paginado, filtros)
GET/vacancies/compatibleAgencia/ReclutadorLista vacantes compatibles
GET/vacancies/:idTodosDetalle de vacante
POST/vacanciesEmpresaCrear borrador
PUT/vacancies/:idEmpresaActualizar borrador
PATCH/vacancies/:id/publishEmpresaPublicar borrador
POST/vacancies/:id/takeAgencia/ReclutadorTomar vacante
GET/vacancies/:id/participantsEmpresaLista participantes

Catálogos utilizados​

Los campos opcionales de una vacante se alimentan de catálogos dinámicos del backend:

CampoCatálogo
modalityWORK_MODALITY
contractTypeCONTRACT_TYPE
workScheduleWORK_SCHEDULE
seniorityLevelSENIORITY_LEVEL
coverageVolumeCOVERAGE_VOLUME
industrySectorINDUSTRY_SECTOR

Registro DI​

  • Datasource: LazySingleton
  • Repository: LazySingleton
  • Cubit: FactoryParam<String> (recibe orgType para 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.