hiring: вакансии и найм, HR-портал
Модель вакансий, флоу рекрутинга и панели HR-портала (заявки/вакансии). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -186,3 +186,85 @@ class HiringRequest(BaseModel):
|
||||
except Exception:
|
||||
return
|
||||
account.release()
|
||||
|
||||
|
||||
class Vacancy(BaseModel):
|
||||
"""Открытая вакансия (рекрутинг в HR-портале)."""
|
||||
|
||||
STATUS_CHOICES = [
|
||||
('open', _('Открыта')),
|
||||
('closed', _('Закрыта')),
|
||||
('filled', _('Закрыта наймом')),
|
||||
]
|
||||
PRIORITY_CHOICES = [
|
||||
('urgent', _('Срочно')),
|
||||
('medium', _('Средний')),
|
||||
('normal', _('Обычный')),
|
||||
]
|
||||
LOCATION_TYPES = [
|
||||
('pharmacy', _('Аптека')),
|
||||
('warehouse', _('Склад')),
|
||||
('office', _('Офис')),
|
||||
]
|
||||
|
||||
title = models.CharField(_('Название'), max_length=200)
|
||||
post = models.ForeignKey(
|
||||
'core.Directory', on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
limit_choices_to={'directory_type__code': 'post', 'is_active': True},
|
||||
related_name='vacancies', verbose_name=_('Должность'),
|
||||
)
|
||||
user_location_type = models.CharField(
|
||||
_('Тип локации'), max_length=20, choices=LOCATION_TYPES, default='pharmacy',
|
||||
)
|
||||
department = models.ForeignKey(
|
||||
'core.Directory', on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
limit_choices_to={'directory_type__code': 'department', 'is_active': True},
|
||||
related_name='vacancies_department', verbose_name=_('Отдел'),
|
||||
)
|
||||
pharmacy = models.ForeignKey(
|
||||
'locations.Pharmacy', on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
related_name='pharmacy_vacancies', verbose_name=_('Аптека'),
|
||||
)
|
||||
location = models.ForeignKey(
|
||||
'locations.Location', on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
related_name='location_vacancies', verbose_name=_('Локация'),
|
||||
)
|
||||
priority = models.CharField(
|
||||
_('Приоритет'), max_length=16, choices=PRIORITY_CHOICES, default='normal',
|
||||
)
|
||||
status = models.CharField(
|
||||
_('Статус'), max_length=16, choices=STATUS_CHOICES, default='open',
|
||||
)
|
||||
opened_at = models.DateField(_('Открыта с'), default=timezone.localdate)
|
||||
description = models.TextField(_('Описание'), blank=True)
|
||||
candidates_count = models.PositiveIntegerField(_('Кандидатов'), default=0)
|
||||
created_by = models.ForeignKey(
|
||||
'employees.Employee', on_delete=models.SET_NULL,
|
||||
null=True, blank=True,
|
||||
related_name='vacancies_created', verbose_name=_('Создал'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('Вакансия')
|
||||
verbose_name_plural = _('Вакансии')
|
||||
ordering = ['-opened_at', '-created_at']
|
||||
indexes = [
|
||||
models.Index(fields=['status', 'priority']),
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
@property
|
||||
def place_label(self) -> str:
|
||||
if self.user_location_type == 'pharmacy' and self.pharmacy_id:
|
||||
return str(self.pharmacy)
|
||||
if self.department_id:
|
||||
return self.department.name
|
||||
if self.location_id:
|
||||
return str(self.location)
|
||||
return '—'
|
||||
|
||||
Reference in New Issue
Block a user