Files
ACORE/apps/it_manager/models/providers.py
T
lokses 38747a93fc IT-менеджер: каталог моделей оборудования + перевод choices на справочники
- EquipmentModel (каталог: тип+бренд+модель заводятся раз) отделён от
  Equipment (экземпляр: серийник+локация); миграция сворачивает данные.
  Массовый ввод серийников, массовая выдача на локации/сотрудников
- Enum-choices (тип/статус/приоритет заявок, вид работ, каналы, расходники,
  договоры) переведены на core.Directory с quick-add из формы
- Фронт-страница /it-manager/: вкладки оборудование/заявки/работы/
  расходники/провайдеры/обращения; searchable-select локаций
- Тесты (10)

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

103 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from django.db import models
from django.utils import timezone
from core.models.directories import directory_default
class InternetProvider(models.Model):
name = models.CharField('Название', max_length=200, unique=True)
phone = models.CharField('Телефон', max_length=50, blank=True)
email = models.EmailField('Email', blank=True)
website = models.URLField('Сайт', blank=True)
support_phone = models.CharField('Телефон техподдержки', max_length=50, blank=True)
support_email = models.EmailField('Email техподдержки', blank=True)
notes = models.TextField('Примечания', blank=True)
is_active = models.BooleanField('Активен', default=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Провайдер'
verbose_name_plural = 'Провайдеры'
ordering = ['name']
def __str__(self):
return self.name
@property
def active_contracts_count(self):
return self.contracts.filter(status__code='active').count()
class InternetContract(models.Model):
provider = models.ForeignKey(
InternetProvider, on_delete=models.PROTECT,
related_name='contracts', verbose_name='Провайдер',
)
location = models.ForeignKey(
'locations.Location', on_delete=models.PROTECT,
related_name='internet_contracts', verbose_name='Локация',
)
contract_number = models.CharField('Номер договора', max_length=100)
service_type = models.ForeignKey(
'core.Directory', on_delete=models.PROTECT,
limit_choices_to={'directory_type__code': 'contract_service_type', 'is_active': True},
related_name='contracts_by_service_type', verbose_name='Тип услуги',
default=directory_default('contract_service_type', 'internet'),
)
connection_type = models.ForeignKey(
'core.Directory', on_delete=models.SET_NULL,
limit_choices_to={'directory_type__code': 'contract_connection_type', 'is_active': True},
related_name='contracts_by_connection_type', verbose_name='Технология подключения',
null=True, blank=True,
)
status = models.ForeignKey(
'core.Directory', on_delete=models.PROTECT,
limit_choices_to={'directory_type__code': 'contract_status', 'is_active': True},
related_name='contracts_by_status', verbose_name='Статус',
default=directory_default('contract_status', 'active'),
)
start_date = models.DateField('Дата начала')
end_date = models.DateField('Дата окончания', null=True, blank=True)
monthly_cost = models.DecimalField('Стоимость в месяц', max_digits=10, decimal_places=2,
null=True, blank=True)
bandwidth_down = models.PositiveIntegerField('Скорость вниз (Мбит/с)', null=True, blank=True)
bandwidth_up = models.PositiveIntegerField('Скорость вверх (Мбит/с)', null=True, blank=True)
static_ips = models.TextField('Статические IP', blank=True,
help_text='По одному на строку')
account_number = models.CharField('Лицевой счёт', max_length=100, blank=True)
notes = models.TextField('Примечания', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Договор с провайдером'
verbose_name_plural = 'Договоры с провайдерами'
ordering = ['location', 'provider']
unique_together = [('provider', 'contract_number')]
def __str__(self):
return f'{self.provider} — {self.location} (№{self.contract_number})'
@property
def is_expiring_soon(self):
if not self.end_date or self.status.code != 'active':
return False
return (self.end_date - timezone.now().date()).days <= 30
@property
def bandwidth_display(self):
if self.bandwidth_down and self.bandwidth_up:
return f'{self.bandwidth_down}↓ / {self.bandwidth_up}↑ Мбит/с'
if self.bandwidth_down:
return f'{self.bandwidth_down} Мбит/с'
return '—'
@property
def static_ip_list(self):
return [ip.strip() for ip in self.static_ips.splitlines() if ip.strip()]