Saltar al contenido principal
Versión: 2.0

Módulo: Vacantes

Scope

Tipo de organizaciónAcceso
Empresa
Agencia
Reclutador independiente

Permisos por rol

Empresa (COMPANY)

AcciónDisponiblePermiso
Ver lista de vacantes propiasvacancies:read
Crear vacante borradorvacancies:create
Editar vacante borradorvacancies:create
Publicar vacantevacancies:publish
Ver detalle de vacantevacancies:read
Ver participantes de una vacantevacancies: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 compatiblesvacancies:read
Ver detalle de vacante compatiblevacancies: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 compatiblesvacancies:read
Ver detalle de vacante compatiblevacancies: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.