045171275e
Co-authored-by: Cursor <cursoragent@cursor.com>
491 lines
39 KiB
HTML
491 lines
39 KiB
HTML
{% load common_tags %}
|
||
{% load i18n %}
|
||
<div class="page-content">
|
||
|
||
<!-- Назад + дії -->
|
||
<div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:1rem; gap:1rem; flex-wrap:wrap;">
|
||
<a href="/dislocation/" hx-get="/dislocation/" hx-target="#main-content" hx-push-url="/dislocation/" hx-indicator="#loader"
|
||
style="display:inline-flex; align-items:center; gap:0.375rem; font-size:0.8125rem; color:var(--color-muted-foreground); text-decoration:none;">
|
||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||
<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>
|
||
</svg>
|
||
До дислокації
|
||
</a>
|
||
{% if can_edit %}
|
||
<div style="display:flex; gap:0.5rem; flex-wrap:wrap;">
|
||
{% if pharmacy_edit_mode %}
|
||
<a href="/pharmacies/{{ pharmacy.pk }}/" hx-get="/pharmacies/{{ pharmacy.pk }}/" hx-target="#main-content" hx-push-url="true" hx-indicator="#loader"
|
||
class="btn btn-secondary" style="font-size:0.8125rem; padding:0.3rem 0.75rem; text-decoration:none;">{% trans "Отмена" %}</a>
|
||
{% else %}
|
||
<a href="/pharmacies/{{ pharmacy.pk }}/?edit=1" hx-get="/pharmacies/{{ pharmacy.pk }}/?edit=1" hx-target="#main-content" hx-push-url="true" hx-indicator="#loader"
|
||
class="btn btn-primary" style="font-size:0.8125rem; padding:0.3rem 0.75rem; text-decoration:none;">{% trans "Редактировать" %}</a>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
{% if pharmacy_form_message %}
|
||
<div style="margin-bottom:1rem; padding:0.75rem 1rem; border-radius:0.5rem; border:1px solid hsl(152 40% 70%); background:color-mix(in srgb, var(--color-success) 12%, var(--color-card)); color:var(--color-foreground); font-size:0.875rem;">
|
||
{{ pharmacy_form_message }}
|
||
</div>
|
||
{% endif %}
|
||
{% if pharmacy_form_error %}
|
||
<div style="margin-bottom:1rem; padding:0.75rem 1rem; border-radius:0.5rem; background:hsl(0 70% 96%); border:1px solid hsl(0 70% 85%); color:hsl(0 55% 35%); font-size:0.8125rem;">
|
||
{{ pharmacy_form_error }}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- Заголовок -->
|
||
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); padding:1.5rem; margin-bottom:1.25rem;">
|
||
<div style="display:flex; align-items:flex-start; justify-content:space-between; gap:1rem; flex-wrap:wrap;">
|
||
<div style="display:flex; align-items:center; gap:0.875rem;">
|
||
<div style="width:3rem; height:3rem; border-radius:0.625rem; background:color-mix(in srgb, var(--color-primary) 12%, transparent); color:var(--color-primary); display:flex; align-items:center; justify-content:center; font-size:1rem; font-weight:700; flex-shrink:0;">№{{ pharmacy.pharmacy_number }}</div>
|
||
<div>
|
||
<h1 style="font-size:1.25rem; font-weight:600; color:var(--color-foreground);">{{ pharmacy.organization.name|default:"Аптека" }} №{{ pharmacy.pharmacy_number }}</h1>
|
||
<div style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{{ pharmacy.address|default:"Адреса не вказана" }}{% if pharmacy.location_region %} · {{ pharmacy.location_region.name }}{% endif %}</div>
|
||
</div>
|
||
</div>
|
||
<div style="display:flex; align-items:center; gap:0.5rem; flex-wrap:wrap;">
|
||
{% if pharmacy.category %}<span class="badge badge-muted">Категорія {{ pharmacy.category }}</span>{% endif %}
|
||
{% if pharmacy.status == 'open' %}<span class="badge badge-success">{{ pharmacy.get_status_display }}</span>
|
||
{% elif pharmacy.status == 'closed' %}<span class="badge badge-danger">{{ pharmacy.get_status_display }}</span>
|
||
{% elif pharmacy.status == 'suspended' %}<span class="badge badge-warning">{{ pharmacy.get_status_display }}</span>
|
||
{% else %}<span class="badge badge-info">{{ pharmacy.get_status_display }}</span>{% endif %}
|
||
{% if not pharmacy.is_active %}<span class="badge badge-danger">{% trans "Неактивна" %}</span>{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Метрики -->
|
||
<div style="display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:0.75rem; margin-bottom:1.25rem;">
|
||
<div class="stat-card" style="padding:1rem 1.25rem;">
|
||
<div style="font-size:0.6875rem; color:var(--color-muted-foreground); text-transform:uppercase; letter-spacing:0.05em; margin-bottom:0.375rem;">{% trans "Персонал" %}</div>
|
||
{% if can_view_staff %}
|
||
<div style="font-size:1.5rem; font-weight:500; color:var(--color-foreground);">{{ staff_count }}</div>
|
||
<div style="font-size:0.75rem; color:{% if staff_count == 0 %}var(--color-destructive){% else %}var(--color-success){% endif %}; margin-top:0.25rem;">{% if staff_count == 0 %}немає співробітників{% else %}активних{% endif %}</div>
|
||
{% else %}
|
||
<div style="font-size:1.5rem; font-weight:500; color:var(--color-muted-foreground);">—</div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "недоступно" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
<div class="stat-card" style="padding:1rem 1.25rem;">
|
||
<div style="font-size:0.6875rem; color:var(--color-muted-foreground); text-transform:uppercase; letter-spacing:0.05em; margin-bottom:0.375rem;">{% trans "Заведующий" %}</div>
|
||
<div style="font-size:1rem; font-weight:600; color:var(--color-foreground); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">{% if pharmacy.head_pharmacist %}{{ pharmacy.head_pharmacist.last_name }} {{ pharmacy.head_pharmacist.first_name }}{% else %}—{% endif %}</div>
|
||
{% if not pharmacy.head_pharmacist %}<div style="font-size:0.75rem; color:var(--color-warning); margin-top:0.25rem;">не призначений</div>{% endif %}
|
||
</div>
|
||
<div class="stat-card" style="padding:1rem 1.25rem;">
|
||
<div style="font-size:0.6875rem; color:var(--color-muted-foreground); text-transform:uppercase; letter-spacing:0.05em; margin-bottom:0.375rem;">{% trans "Лицензия" %}</div>
|
||
<div style="font-size:1rem; font-weight:600; color:var(--color-foreground);">{{ pharmacy.license_status }}</div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{{ pharmacy.license_number|default:"без номера" }}</div>
|
||
</div>
|
||
<div class="stat-card" style="padding:1rem 1.25rem;">
|
||
<div style="font-size:0.6875rem; color:var(--color-muted-foreground); text-transform:uppercase; letter-spacing:0.05em; margin-bottom:0.375rem;">{% trans "Режим работы" %}</div>
|
||
<div style="font-size:1rem; font-weight:600; color:var(--color-foreground);">{{ pharmacy.working_hours|default:"—" }}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Вкладки -->
|
||
<div style="display:flex; gap:0.25rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem; width:fit-content; margin-bottom:1.25rem; flex-wrap:wrap;">
|
||
<button type="button" class="ph-tab-btn ph-tab-active" data-tab="main" onclick="phTabSwitch('main')"
|
||
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);">{% trans "Основная информация" %}</button>
|
||
{% if can_view_equipment %}
|
||
<button type="button" class="ph-tab-btn" data-tab="equipment" onclick="phTabSwitch('equipment')"
|
||
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Сетевое и компьютерное оборудование" %}</button>
|
||
{% endif %}
|
||
{% if can_view_internet %}
|
||
<button type="button" class="ph-tab-btn" data-tab="internet" onclick="phTabSwitch('internet')"
|
||
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Интернет-провайдер" %}</button>
|
||
{% endif %}
|
||
{% if can_view_rro %}
|
||
<button type="button" class="ph-tab-btn" data-tab="rro" onclick="phTabSwitch('rro')"
|
||
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "РРО / ПРРО" %}</button>
|
||
{% endif %}
|
||
{% if can_view_utilities %}
|
||
<button type="button" class="ph-tab-btn" data-tab="utilities" onclick="phTabSwitch('utilities')"
|
||
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Коммунальный отдел" %}</button>
|
||
{% endif %}
|
||
{% if can_view_documents %}
|
||
<button type="button" class="ph-tab-btn" data-tab="documents" onclick="phTabSwitch('documents')"
|
||
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Документы" %}</button>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- ══ ВКЛАДКА: ОСНОВНА ІНФОРМАЦІЯ ══ -->
|
||
<div id="ph-panel-main" class="ph-panel">
|
||
<div style="display:grid; grid-template-columns:2fr 1fr; gap:1.25rem;">
|
||
<div style="display:flex; flex-direction:column; gap:1.25rem;">
|
||
|
||
<!-- Основна інформація -->
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; padding:1.25rem;">
|
||
<h2 style="font-size:1rem; font-weight:600; color:var(--color-foreground); margin-bottom:0.875rem;">{% trans "Основная информация" %}</h2>
|
||
{% if pharmacy_edit_mode and pharmacy_edit_form %}
|
||
{% with f=pharmacy_edit_form %}
|
||
<form method="post" action="/pharmacies/{{ pharmacy.pk }}/edit/"
|
||
hx-post="/pharmacies/{{ pharmacy.pk }}/edit/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]"
|
||
style="display:flex; flex-direction:column; gap:0.875rem;">
|
||
{% csrf_token %}
|
||
{% include "partials/pharmacy-edit-fields.html" %}
|
||
<div style="display:flex; gap:0.5rem; justify-content:flex-end; padding-top:0.25rem;">
|
||
<a href="/pharmacies/{{ pharmacy.pk }}/" hx-get="/pharmacies/{{ pharmacy.pk }}/" hx-target="#main-content" hx-push-url="true" hx-indicator="#loader"
|
||
class="btn btn-secondary" style="font-size:0.8125rem; text-decoration:none;">{% trans "Отмена" %}</a>
|
||
<button type="submit" class="btn btn-primary" style="font-size:0.8125rem;">
|
||
{% trans "Сохранить" %}
|
||
<span class="btn-label-loading htmx-indicator">…</span>
|
||
</button>
|
||
</div>
|
||
</form>
|
||
{% endwith %}
|
||
{% else %}
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem 1.5rem; font-size:0.8125rem;">
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Организация" %}</span><br>{{ pharmacy.organization.name|default:"—" }}</div>
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Регион" %}</span><br>{{ pharmacy.location_region.name|default:"—" }}</div>
|
||
<div style="grid-column:1 / -1;"><span style="color:var(--color-muted-foreground);">{% trans "Адрес" %}</span><br>{{ pharmacy.address|default:"не вказана" }}</div>
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Категория" %}</span><br>{{ pharmacy.get_category_display|default:"не вказана" }}</div>
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Категория НДС" %}</span><br>{{ pharmacy.get_vat_category_display|default:"не вказана" }}</div>
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Ответственный менеджер" %}</span><br>{% if pharmacy.responsible_manager %}{{ pharmacy.responsible_manager.last_name }} {{ pharmacy.responsible_manager.first_name }}{% else %}—{% endif %}</div>
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Куратор" %}</span><br>{% if pharmacy.curator %}{{ pharmacy.curator.last_name }} {{ pharmacy.curator.first_name }}{% else %}—{% endif %}</div>
|
||
<div><span style="color:var(--color-muted-foreground);">{% trans "Количество фармацевтов (штат)" %}</span><br>{{ pharmacy.pharmacists_count }}</div>
|
||
</div>
|
||
{% if pharmacy.comments %}
|
||
<div style="margin-top:0.875rem; padding-top:0.875rem; border-top:1px solid var(--color-border); font-size:0.8125rem;">
|
||
<span style="color:var(--color-muted-foreground);">{% trans "Примечания" %}</span>
|
||
<div style="margin-top:0.25rem; white-space:pre-line;">{{ pharmacy.comments }}</div>
|
||
</div>
|
||
{% endif %}
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Контакти -->
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; padding:1.25rem;">
|
||
<h2 style="font-size:1rem; font-weight:600; color:var(--color-foreground); margin-bottom:0.875rem;">{% trans "Контакты" %}</h2>
|
||
{% if phones %}
|
||
<div style="display:flex; flex-direction:column; gap:0.5rem;">
|
||
{% for p in phones %}
|
||
<div style="display:flex; align-items:center; gap:0.5rem; font-size:0.8125rem;">
|
||
<span>☎️ {{ p.phone }}</span>
|
||
<span class="badge badge-muted">{{ p.get_phone_type_display }}</span>
|
||
{% if p.is_primary %}<span class="badge badge-success">{% trans "Основной" %}</span>{% endif %}
|
||
{% if p.notes %}<span style="color:var(--color-muted-foreground);">— {{ p.notes }}</span>{% endif %}
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
{% elif pharmacy.phone %}
|
||
<div style="font-size:0.8125rem;">☎️ {{ pharmacy.phone }}</div>
|
||
{% else %}
|
||
<div style="font-size:0.8125rem; color:var(--color-muted-foreground);">{% trans "Телефоны не указаны" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Персонал -->
|
||
{% if can_view_staff %}
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; padding:1.25rem;">
|
||
<h2 style="font-size:1rem; font-weight:600; color:var(--color-foreground); margin-bottom:0.875rem;">Персонал · {{ staff_count }}</h2>
|
||
{% if staff %}
|
||
<div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(15rem, 1fr)); gap:0.5rem;">
|
||
{% for employee in staff %}
|
||
<div class="li-hover" style="display:flex; align-items:center; gap:0.5rem; padding:0.5rem 0.625rem; background:var(--color-muted); border-radius:0.5rem; cursor:pointer;"
|
||
hx-get="/employees/{{ employee.pk }}/" hx-target="#main-content" hx-push-url="/employees/{{ employee.pk }}/" hx-indicator="#loader">
|
||
{% if employee.photo %}
|
||
<img src="{{ employee.photo.url }}" alt="" style="width:1.75rem; height:1.75rem; border-radius:50%; object-fit:cover; flex-shrink:0;">
|
||
{% else %}
|
||
<span style="width:1.75rem; height:1.75rem; border-radius:50%; background:color-mix(in srgb, var(--color-primary) 10%, transparent); color:var(--color-primary); display:flex; align-items:center; justify-content:center; font-size:0.6875rem; font-weight:500; flex-shrink:0;">{{ employee|initials }}</span>
|
||
{% endif %}
|
||
<div style="min-width:0;">
|
||
<div style="font-size:0.8125rem; font-weight:500; color:var(--color-card-foreground); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">
|
||
{{ employee.last_name }} {{ employee.first_name }}
|
||
{% if employee.pk == pharmacy.head_pharmacist_id %}<span class="badge badge-success" style="margin-left:0.25rem;">{% trans "Заведующий" %}</span>{% endif %}
|
||
</div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">{{ employee.post.name|default:"Посада не вказана" }}</div>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
{% else %}
|
||
<div style="font-size:0.8125rem; color:var(--color-muted-foreground);">{% trans "В этой аптеке пока нет активных сотрудников" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div style="display:flex; flex-direction:column; gap:1.25rem;">
|
||
<!-- Карта -->
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; padding:1.25rem;">
|
||
<h2 style="font-size:1rem; font-weight:600; color:var(--color-foreground); margin-bottom:0.875rem;">{% trans "Координаты" %}</h2>
|
||
{% if pharmacy.has_coordinates %}
|
||
<div id="pharmacy-map" style="height:220px; width:100%; border-radius:0.5rem; overflow:hidden;"></div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.5rem;">{{ pharmacy.latitude|floatformat:5 }}, {{ pharmacy.longitude|floatformat:5 }}</div>
|
||
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.js"></script>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.css">
|
||
<script>
|
||
(function () {
|
||
var lat = {{ pharmacy.latitude|floatformat:'6' }}, lng = {{ pharmacy.longitude|floatformat:'6' }};
|
||
var map = L.map('pharmacy-map', { zoomControl: false, dragging: false, scrollWheelZoom: false }).setView([lat, lng], 15);
|
||
if (typeof acoreAddMapBaseLayer === 'function') {
|
||
acoreAddMapBaseLayer(map);
|
||
} else {
|
||
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||
attribution: '© OpenStreetMap contributors', maxZoom: 19
|
||
}).addTo(map);
|
||
}
|
||
L.marker([lat, lng]).addTo(map);
|
||
})();
|
||
</script>
|
||
{% else %}
|
||
<div style="font-size:0.8125rem; color:var(--color-warning);">⚠ Координати не вказані</div>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<!-- Службова інформація -->
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; padding:1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">
|
||
<div style="margin-bottom:0.5rem;"><span style="color:var(--color-foreground);">{% trans "Создано:" %}</span> {{ pharmacy.created_at|date:"d.m.Y H:i" }}</div>
|
||
<div><span style="color:var(--color-foreground);">{% trans "Обновлено:" %}</span> {{ pharmacy.updated_at|date:"d.m.Y H:i" }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- ══ /ВКЛАДКА: ОСНОВНА ІНФОРМАЦІЯ ══ -->
|
||
|
||
<!-- ══ ВКЛАДКА: МЕРЕЖЕВЕ ТА КОМП'ЮТЕРНЕ ОБЛАДНАННЯ ══ -->
|
||
{% if can_view_equipment %}
|
||
<div id="ph-panel-equipment" class="ph-panel" style="display:none;">
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; overflow:hidden;">
|
||
{% if equipment %}
|
||
<table style="width:100%; border-collapse:collapse; font-size:0.8125rem;">
|
||
<thead>
|
||
<tr style="border-bottom:1px solid var(--color-border); text-align:left;">
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Оборудование" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Серийный / инв. №" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Статус" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Выдано" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Гарантия" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for eq in equipment %}
|
||
<tr style="border-bottom:1px solid var(--color-border);">
|
||
<td style="padding:0.75rem 1rem;">
|
||
<strong>{{ eq.equipment_type.name }}</strong>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ eq.brand.name|default:"" }} {{ eq.model }}</div>
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-size:0.75rem;">
|
||
{{ eq.serial_number }}{% if eq.inventory_number %} · {{ eq.inventory_number }}{% endif %}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem;">
|
||
{% if eq.status.code == 'stock' %}<span class="badge badge-muted">{% trans "На складе" %}</span>
|
||
{% elif eq.status.code == 'assigned' %}<span class="badge badge-success">{% trans "Выдано" %}</span>
|
||
{% elif eq.status.code == 'repair' %}<span class="badge badge-warning">{% trans "В ремонте" %}</span>
|
||
{% else %}<span class="badge badge-danger">{{ eq.status.name }}</span>{% endif %}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ eq.assigned_to.get_full_name|default:"—" }}</td>
|
||
<td style="padding:0.75rem 1rem; color:{% if eq.is_under_warranty %}var(--color-muted-foreground){% else %}var(--color-destructive){% endif %};">{{ eq.warranty_status }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<div style="padding:1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">{% trans "За этой аптекой не закреплено оборудование" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
{% if can_edit %}
|
||
<div style="margin-top:0.75rem;">
|
||
<a href="/it-manager/" hx-get="/it-manager/" hx-target="#main-content" hx-push-url="/it-manager/" hx-indicator="#loader"
|
||
style="font-size:0.8125rem; color:var(--color-primary); text-decoration:none;">{% trans "Управлять оборудованием в IT-отделе" %} →</a>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- ══ ВКЛАДКА: ІНТЕРНЕТ-ПРОВАЙДЕР ══ -->
|
||
{% if can_view_internet %}
|
||
<div id="ph-panel-internet" class="ph-panel" style="display:none;">
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; overflow:hidden;">
|
||
{% if internet_contracts %}
|
||
<table style="width:100%; border-collapse:collapse; font-size:0.8125rem;">
|
||
<thead>
|
||
<tr style="border-bottom:1px solid var(--color-border); text-align:left;">
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Провайдер / договор" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Тип услуги" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Технология" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Скорость" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Статус" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Действует до" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for c in internet_contracts %}
|
||
<tr style="border-bottom:1px solid var(--color-border);">
|
||
<td style="padding:0.75rem 1rem;">
|
||
<strong>{{ c.provider.name }}</strong>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">№{{ c.contract_number }}{% if c.account_number %} · л/р {{ c.account_number }}{% endif %}</div>
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ c.service_type.name }}</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ c.connection_type.name|default:"—" }}</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ c.bandwidth_display }}</td>
|
||
<td style="padding:0.75rem 1rem;">
|
||
{% if c.status.code == 'active' %}<span class="badge badge-success">{{ c.status.name }}</span>
|
||
{% elif c.status.code == 'suspended' %}<span class="badge badge-warning">{{ c.status.name }}</span>
|
||
{% else %}<span class="badge badge-danger">{{ c.status.name }}</span>{% endif %}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; color:{% if c.is_expiring_soon %}var(--color-destructive){% else %}var(--color-muted-foreground){% endif %};">{{ c.end_date|date:"d.m.Y"|default:"—" }}</td>
|
||
</tr>
|
||
{% if c.static_ip_list or c.notes %}
|
||
<tr style="border-bottom:1px solid var(--color-border);">
|
||
<td colspan="6" style="padding:0 1rem 0.75rem 1rem; font-size:0.75rem; color:var(--color-muted-foreground);">
|
||
{% if c.static_ip_list %}Статичні IP: {{ c.static_ip_list|join:", " }}{% endif %}
|
||
{% if c.notes %}{% if c.static_ip_list %} · {% endif %}{{ c.notes }}{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endif %}
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<div style="padding:1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">{% trans "Договоров с провайдерами для этой аптеки не найдено" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
{% if can_edit %}
|
||
<div style="margin-top:0.75rem;">
|
||
<a href="/it-manager/" hx-get="/it-manager/" hx-target="#main-content" hx-push-url="/it-manager/" hx-indicator="#loader"
|
||
style="font-size:0.8125rem; color:var(--color-primary); text-decoration:none;">{% trans "Управлять договорами в IT-отделе" %} →</a>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- ══ ВКЛАДКА: РРО / ПРРО ══ -->
|
||
{% if can_view_rro %}
|
||
<div id="ph-panel-rro" class="ph-panel" style="display:none;">
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; overflow:hidden;">
|
||
{% if cash_registers %}
|
||
<table style="width:100%; border-collapse:collapse; font-size:0.8125rem;">
|
||
<thead>
|
||
<tr style="border-bottom:1px solid var(--color-border); text-align:left;">
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Тип" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Фискальный номер" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Модель" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Статус" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Сертификат до" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for reg in cash_registers %}
|
||
<tr style="border-bottom:1px solid var(--color-border);">
|
||
<td style="padding:0.75rem 1rem;">
|
||
{{ reg.get_kind_display }}
|
||
{% if reg.is_primary %}<span class="badge badge-info" style="margin-left:0.35rem;">{% trans "осн." %}</span>{% endif %}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; font-family:ui-monospace,monospace;">{{ reg.fiscal_number }}</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">
|
||
{% if reg.vendor %}{{ reg.vendor.name }} {% endif %}{{ reg.model_name|default:"—" }}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem;">
|
||
{% if reg.status.code == 'active' %}<span class="badge badge-success">{{ reg.status.name }}</span>
|
||
{% elif reg.status.code == 'repair' %}<span class="badge badge-warning">{{ reg.status.name }}</span>
|
||
{% elif reg.status.code == 'decommissioned' %}<span class="badge badge-danger">{{ reg.status.name }}</span>
|
||
{% else %}<span class="badge badge-muted">{{ reg.status.name }}</span>{% endif %}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">
|
||
{% if reg.cert_expires_at %}{{ reg.cert_expires_at|date:"d.m.Y" }}{% else %}—{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<div style="padding:1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">{% trans "Для этой аптеки кассовые аппараты ещё не заведены" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
<div style="margin-top:0.75rem; display:flex; align-items:center; gap:1rem; flex-wrap:wrap;">
|
||
<a href="/accounting/?tab=rro&pharmacy={{ pharmacy.pk }}" hx-get="/accounting/?tab=rro&pharmacy={{ pharmacy.pk }}" hx-target="#main-content" hx-push-url="/accounting/?tab=rro&pharmacy={{ pharmacy.pk }}" hx-indicator="#loader"
|
||
style="font-size:0.8125rem; color:var(--color-primary); text-decoration:none;">{% trans "Весь реестр РРО / ПРРО" %} →</a>
|
||
{% if can_edit %}
|
||
<a href="/accounting/?tab=rro&pharmacy={{ pharmacy.pk }}&new=1" hx-get="/accounting/?tab=rro&pharmacy={{ pharmacy.pk }}&new=1" hx-target="#main-content" hx-push-url="/accounting/?tab=rro&pharmacy={{ pharmacy.pk }}&new=1" hx-indicator="#loader"
|
||
class="btn btn-primary" style="font-size:0.75rem; padding:0.3rem 0.75rem; text-decoration:none;">{% trans "Добавить" %}</a>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- ══ ВКЛАДКА: КОМУНАЛЬНИЙ ВІДДІЛ ══ -->
|
||
{% if can_view_utilities %}
|
||
<div id="ph-panel-utilities" class="ph-panel" style="display:none;">
|
||
<div style="background:var(--color-card); border:1px solid var(--color-border); border-radius:0.75rem; overflow:hidden;">
|
||
{% if utility_readings %}
|
||
<table style="width:100%; border-collapse:collapse; font-size:0.8125rem;">
|
||
<thead>
|
||
<tr style="border-bottom:1px solid var(--color-border); text-align:left;">
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Тип счётчика" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Дата" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Показания" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Расход" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Подал" %}</th>
|
||
<th style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-weight:500;">{% trans "Комментарий" %}</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for r in utility_readings %}
|
||
<tr style="border-bottom:1px solid var(--color-border);">
|
||
<td style="padding:0.75rem 1rem;">{{ r.utility_type.name }}{% if r.reading_mode == 'day_night' %} <span class="badge badge-info" style="font-size:0.6875rem;">день/ніч</span>{% endif %}</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ r.reading_date|date:"d.m.Y" }}</td>
|
||
<td style="padding:0.75rem 1rem; font-weight:500;">{{ r.value_display }}</td>
|
||
<td style="padding:0.75rem 1rem;">
|
||
{% if r.reading_mode == 'day_night' %}
|
||
{% if r.consumption_total is not None %}
|
||
<span style="color:var(--color-muted-foreground); font-size:0.8125rem;">Σ {{ r.consumption_total }}</span>
|
||
{% else %}<span style="color:var(--color-muted-foreground);">—</span>{% endif %}
|
||
{% elif r.consumption is None %}<span style="color:var(--color-muted-foreground);">—</span>
|
||
{% elif r.consumption < 0 %}<span style="color:var(--color-destructive);" title="{% trans 'Показания меньше предыдущего — проверьте' %}">⚠ {{ r.consumption }}</span>
|
||
{% else %}<span style="color:var(--color-muted-foreground);">{{ r.consumption }}</span>{% endif %}
|
||
</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-size:0.75rem;">{{ r.submitted_by.get_full_name|default:"—" }}</td>
|
||
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-size:0.75rem;">{{ r.comment|default:"—" }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% else %}
|
||
<div style="padding:1.25rem; font-size:0.8125rem; color:var(--color-muted-foreground);">{% trans "Показаний счётчиков для этой аптеки ещё не подавали" %}</div>
|
||
{% endif %}
|
||
</div>
|
||
<div style="margin-top:0.75rem;">
|
||
<a href="/accounting/?tab=utilities" hx-get="/accounting/?tab=utilities" hx-target="#main-content" hx-push-url="/accounting/?tab=utilities" hx-indicator="#loader"
|
||
style="font-size:0.8125rem; color:var(--color-primary); text-decoration:none;">{% trans "Подать показания / все показания" %} →</a>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- ══ ВКЛАДКА: ДОКУМЕНТИ (ленива загрузка через WebDAV) ══ -->
|
||
{% if can_view_documents %}
|
||
<div id="ph-panel-documents" class="ph-panel" style="display:none;">
|
||
<div id="ph-documents-slot" data-url="/pharmacies/{{ pharmacy.pk }}/documents/"
|
||
style="font-size:0.8125rem; color:var(--color-muted-foreground); padding:0.875rem;">
|
||
{% trans "Загрузка…" %}
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
|
||
</div>
|
||
|
||
<script>
|
||
function phTabSwitch(tab) {
|
||
document.querySelectorAll('.ph-panel').forEach(function (panel) {
|
||
panel.style.display = panel.id === 'ph-panel-' + tab ? '' : 'none';
|
||
});
|
||
document.querySelectorAll('.ph-tab-btn').forEach(function (btn) {
|
||
var active = btn.getAttribute('data-tab') === tab;
|
||
btn.classList.toggle('ph-tab-active', active);
|
||
btn.style.background = active ? 'var(--color-card)' : 'transparent';
|
||
btn.style.color = active ? 'var(--color-card-foreground)' : 'var(--color-muted-foreground)';
|
||
btn.style.boxShadow = active ? '0 1px 2px rgb(0 0 0/0.08)' : '';
|
||
});
|
||
// Документы грузим лениво — только при первом открытии вкладки.
|
||
if (tab === 'documents') {
|
||
var slot = document.getElementById('ph-documents-slot');
|
||
if (slot && !slot.dataset.loaded) {
|
||
slot.dataset.loaded = '1';
|
||
htmx.ajax('GET', slot.getAttribute('data-url'), { target: '#ph-documents-slot', swap: 'innerHTML' });
|
||
}
|
||
}
|
||
}
|
||
</script>
|