Доработал закрытие, техоперации автоматом переключаются, добавил выгрузку сменных заданий
All checks were successful
Deploy MES Core / deploy (push) Successful in 14s

This commit is contained in:
2026-04-25 11:58:11 +03:00
parent 6fd01c9a6e
commit 909ba05b5d
14 changed files with 998 additions and 74 deletions

View File

@@ -8,7 +8,15 @@
<h3 class="text-accent mb-0">
<i class="bi bi-check2-square me-2"></i>Закрытие сборки
</h3>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'workitem_detail' workitem.id %}">Назад к заданию</a>
<div class="d-flex gap-2">
<a class="btn btn-outline-accent btn-sm" href="{% url 'workitem_kitting' workitem.id %}?next={{ request.get_full_path|urlencode }}">
<i class="bi bi-box-seam me-1"></i>Комплектация
</a>
<button type="button" class="btn btn-outline-secondary btn-sm" disabled title="В разработке">
<i class="bi bi-basket3 me-1"></i>Доп. расходы
</button>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'workitem_detail' workitem.id %}">Назад к заданию</a>
</div>
</div>
<div class="card-body p-4">

View File

@@ -6,10 +6,15 @@
<div class="card shadow border-secondary">
<div class="card-header border-secondary py-3 d-flex justify-content-between align-items-center">
<h3 class="text-accent mb-0"><i class="bi bi-list-task me-2"></i>Реестр заданий</h3>
{% if user_role in 'admin,technologist,master' %}
<a class="btn btn-outline-secondary btn-sm" target="_blank" href="{% url 'registry_workitems_print' %}?{{ request.GET.urlencode }}">
<i class="bi bi-printer me-1"></i>Печать
</a>
{% if user_role in 'admin,technologist,master,operator' %}
<div class="d-flex gap-2">
<a class="btn btn-outline-secondary btn-sm" target="_blank" href="{% url 'registry_workitems_print' %}?{{ request.GET.urlencode }}">
<i class="bi bi-printer me-1"></i>Печать
</a>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'registry_workitems_download' %}?{{ request.GET.urlencode }}">
<i class="bi bi-download me-1"></i>Скачать
</a>
</div>
{% endif %}
</div>

View File

@@ -0,0 +1,35 @@
{% extends 'base.html' %}
{% block content %}
<div class="card shadow border-secondary">
<div class="card-header border-secondary py-3 d-flex justify-content-between align-items-center">
<h3 class="text-accent mb-0"><i class="bi bi-download me-2"></i>Скачать сменное задание</h3>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'registry' %}?{{ request.GET.urlencode }}">
<i class="bi bi-arrow-left me-1"></i>В реестр
</a>
</div>
<div class="card-body">
<div class="alert alert-info">
В выгрузку попадают <strong>задания из текущего фильтра реестра</strong> (как на экране).
Дополнительно: только <strong>задания «В работе»</strong> и только <strong>сделки «В работе»</strong>.
HTML формируется тем же шаблоном, что и кнопка <strong>«Печать»</strong>.
</div>
<form method="post" action="?{{ request.GET.urlencode }}">
{% csrf_token %}
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" value="1" id="translit" name="translit">
<label class="form-check-label" for="translit">
Транслитерировать имена файлов и папок (для совместимости)
</label>
</div>
<button type="submit" class="btn btn-primary">
<i class="bi bi-archive me-1"></i>Подготовить и скачать архив
</button>
</form>
</div>
</div>
{% endblock %}

View File

@@ -31,6 +31,14 @@
</div>
</div>
{% if export_bar_text %}
<div class="container-fluid my-3">
<div class="alert alert-info py-2 mb-0">
{{ export_bar_text }}
</div>
</div>
{% endif %}
{% for g in groups %}
<div class="container-fluid page my-3">
<div class="print-header">
@@ -64,7 +72,12 @@
<td class="center">{{ wi.date|date:"d.m.y" }}</td>
<td class="center">{{ wi.deal.number|default:"-" }}</td>
<td>{{ wi.operation.name|default:wi.stage|default:"—" }}</td>
<td>{{ wi.entity.drawing_number|default:"—" }} {{ wi.entity.name }}</td>
<td>
{{ wi.entity.drawing_number|default:"—" }} {{ wi.entity.name }}
{% if wi.entity.blank_length_mm and not wi.entity.dxf_file and not wi.entity.pdf_main %}
<div class="small text-muted">Длина: {{ wi.entity.blank_length_mm|floatformat:0 }} мм</div>
{% endif %}
</td>
<td>
{% if wi.entity.planned_material %}
{{ wi.entity.planned_material.full_name|default:wi.entity.planned_material.name }}

View File

@@ -28,12 +28,18 @@
{% endif %}
{% if user_role in 'admin,technologist,master,clerk' %}
{% if workitem.entity.entity_type == 'product' or workitem.entity.entity_type == 'assembly' %}
{% if is_first_operation and workitem.entity.entity_type == 'product' or is_first_operation and workitem.entity.entity_type == 'assembly' %}
<a class="btn btn-outline-accent btn-sm" href="{% url 'workitem_kitting' workitem.id %}?next={{ request.get_full_path|urlencode }}">
<i class="bi bi-box-seam me-1"></i>Комплектация
</a>
{% endif %}
{% endif %}
{% if user_role in 'admin,technologist,master,operator,prod_head' %}
<button type="button" class="btn btn-outline-secondary btn-sm" disabled title="В разработке">
<i class="bi bi-basket3 me-1"></i>Доп. расходы
</button>
{% endif %}
</div>
</div>

View File

@@ -8,7 +8,12 @@
<h3 class="text-accent mb-0">
<i class="bi bi-check2-square me-2"></i>Закрытие операции
</h3>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'workitem_detail' workitem.id %}">Назад к заданию</a>
<div class="d-flex gap-2">
<button type="button" class="btn btn-outline-secondary btn-sm" disabled title="В разработке">
<i class="bi bi-basket3 me-1"></i>Доп. расходы
</button>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'workitem_detail' workitem.id %}">Назад к заданию</a>
</div>
</div>
<div class="card-body p-4">
@@ -25,6 +30,65 @@
Эта операция не списывает сырьё/комплектующие. Здесь фиксируется только факт выполнения.
</div>
{% if move_hint and work_location %}
<div class="alert alert-warning border-warning">
На складе участка <strong>{{ work_location.name }}</strong> не хватает изделий для закрытия операции.
Нужно: <strong>{{ move_hint.needed }}</strong> · доступно: <strong>{{ move_hint.available }}</strong> · не хватает: <strong>{{ move_hint.missing }}</strong>.
</div>
<div class="d-flex gap-2 mb-3">
<button type="button" class="btn btn-outline-accent" data-bs-toggle="modal" data-bs-target="#moveToWorkLocationModal" {% if not move_candidates %}disabled{% endif %}>
<i class="bi bi-arrow-left-right me-1"></i>Переместить на участок
</button>
{% if not move_candidates %}
<div class="small text-muted align-self-center">Нет доступных позиций для перемещения</div>
{% endif %}
</div>
<div class="modal fade" id="moveToWorkLocationModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<form method="post" action="{% url 'warehouse_transfer' %}" class="modal-content border-secondary">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.get_full_path }}">
<input type="hidden" name="to_location_id" value="{{ work_location.id }}">
<div class="modal-header border-secondary">
<h5 class="modal-title">Перемещение на участок</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
</div>
<div class="modal-body">
<div class="mb-2">
<div class="fw-bold">{{ workitem.entity.drawing_number|default:"—" }} {{ workitem.entity.name }}</div>
<div class="small text-muted">Склад участка: {{ work_location.name }}</div>
</div>
<div class="row g-2">
<div class="col-md-8">
<label class="form-label">Откуда (позиция склада)</label>
<select class="form-select" name="stock_item_id" required>
{% for c in move_candidates %}
<option value="{{ c.id }}">{{ c.location.name }} · доступно {{ c.quantity|floatformat:"-g" }}</option>
{% endfor %}
</select>
</div>
<div class="col-md-4">
<label class="form-label">Количество</label>
<input class="form-control" name="quantity" inputmode="decimal" value="{{ move_hint.missing }}" required>
</div>
</div>
</div>
<div class="modal-footer border-secondary">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Отмена</button>
<button type="submit" class="btn btn-outline-accent">Переместить</button>
</div>
</form>
</div>
</div>
{% endif %}
<form method="post">
{% csrf_token %}
<div class="row align-items-end g-2">