Files
ACORE/apps/hiring/models.py
T
lokses 6ff01c4119 Доменные модули: сотрудники, локации, найм, счётчики, посещения
- employees: last_seen, internal_number, default_page_size; управление-команды
- locations: категория/куратор/ответственный аптеки, seed должностей;
  Location.__str__ показывает номер аптеки (не только адрес)
- hiring: HiringRequest (заявки на найм) + тесты (7)
- utilities: UtilityReading (показания счётчиков по аптекам)
- visit_manager: правки

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 17:33:16 +03:00

115 lines
4.7 KiB
Python

from datetime import timedelta
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from core.models import BaseModel
from core.utils.validators import validate_ukrainian_phone
class HiringRequest(BaseModel):
"""Заявка HR на найм кандидата: створення тимчасового (стажерського)
облікового запису та подальше затвердження/відхилення."""
STATUS_CHOICES = [
('trial', _('На випробуванні')),
('approved', _('Затверджено')),
('rejected', _('Відхилено')),
]
TRIAL_DAYS_CHOICES = [(i, _('%(n)d дн.') % {'n': i}) for i in range(1, 6)]
last_name = models.CharField(_('Прізвище'), max_length=150)
first_name = models.CharField(_('Ім\'я'), max_length=150)
middle_name = models.CharField(_('По батькові'), max_length=150, blank=True)
candidate_email = models.EmailField(_('Особистий email кандидата'), blank=True)
candidate_phone = models.CharField(
_('Телефон кандидата'), max_length=20, blank=True,
validators=[validate_ukrainian_phone],
)
LOCATION_TYPES = [
('pharmacy', _('Аптека')),
('warehouse', _('Склад')),
('office', _('Офіс')),
]
user_location_type = models.CharField(
_('Тип локації'), max_length=20, choices=LOCATION_TYPES,
)
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='hiring_requests_department', verbose_name=_('Відділ'),
)
user_pharmacy = models.ForeignKey(
'locations.Pharmacy', on_delete=models.SET_NULL,
null=True, blank=True,
related_name='hiring_requests', verbose_name=_('Аптека'),
)
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='hiring_requests_post', verbose_name=_('Посада'),
)
hire_date = models.DateField(_('Дата виходу'), default=timezone.localdate)
trial_days = models.PositiveSmallIntegerField(
_('Термін випробування, днів'), choices=TRIAL_DAYS_CHOICES, default=3,
validators=[MinValueValidator(1), MaxValueValidator(5)],
)
requested_access = models.ManyToManyField(
'core.Directory', blank=True,
limit_choices_to={'directory_type__code': 'access_system', 'is_active': True},
related_name='hiring_requests_access', verbose_name=_('Потрібні доступи'),
)
access_note = models.TextField(_('Примітка щодо доступів'), blank=True)
status = models.CharField(_('Статус'), max_length=10, choices=STATUS_CHOICES, default='trial')
requested_by = models.ForeignKey(
'employees.Employee', on_delete=models.PROTECT,
related_name='hiring_requests_submitted', verbose_name=_('Подав HR'),
)
employee = models.OneToOneField(
'employees.Employee', on_delete=models.SET_NULL,
null=True, blank=True,
related_name='hiring_request', verbose_name=_('Обліковий запис'),
)
decision_by = models.ForeignKey(
'employees.Employee', on_delete=models.SET_NULL,
null=True, blank=True,
related_name='hiring_requests_decided', verbose_name=_('Рішення прийняв'),
)
decision_at = models.DateTimeField(_('Дата рішення'), null=True, blank=True)
decision_note = models.TextField(_('Коментар до рішення'), blank=True)
granted_ticket = models.ForeignKey(
'it_manager.Ticket', on_delete=models.SET_NULL,
null=True, blank=True,
related_name='hiring_requests', verbose_name=_('Заявка в IT'),
)
class Meta:
verbose_name = _('Заявка на найм')
verbose_name_plural = _('Заявки на найм')
ordering = ['-created_at']
indexes = [
models.Index(fields=['status']),
]
def __str__(self):
return f'{self.last_name} {self.first_name} ({self.get_status_display()})'
@property
def trial_end_date(self):
return self.hire_date + timedelta(days=self.trial_days)
@property
def is_overdue(self):
return self.status == 'trial' and self.trial_end_date < timezone.localdate()