Files
MES_Core/shiftflow/templates/shiftflow/procurement_dashboard.html
2026-04-13 07:36:57 +03:00

218 lines
12 KiB
HTML
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.

{% 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">
<div class="w-100">
<div class="d-flex flex-wrap align-items-center gap-3 justify-content-between">
<h3 class="text-accent mb-0"><i class="bi bi-truck me-2"></i>Снабжение</h3>
<form method="get" class="d-flex flex-wrap align-items-center gap-2">
<input type="hidden" name="filtered" value="1">
<div class="d-flex w-100 mb-2 gap-2">
<input type="text" class="form-control form-control-sm border-secondary" name="q" placeholder="Сделка / компонент" value="{{ q }}" style="max-width: 300px;">
<button type="submit" class="btn btn-outline-accent btn-sm">
<i class="bi bi-search me-1"></i>Применить
</button>
<a class="btn btn-outline-secondary btn-sm" href="{% url 'procurement' %}">Сброс</a>
<div class="ms-auto">
<button type="submit" name="print" value="1" class="btn btn-outline-secondary btn-sm" formtarget="_blank">
<i class="bi bi-printer me-1"></i>Печать
</button>
</div>
</div>
<div class="d-flex align-items-center gap-1">
<input type="checkbox" class="btn-check" name="grouped" id="grouped" value="1" {% if grouped %}checked{% endif %} onchange="this.form.submit()">
<label class="btn btn-outline-accent btn-sm" for="grouped"><i class="bi bi-layers me-1"></i>Группировать</label>
</div>
<div class="d-flex flex-wrap align-items-center gap-1">
<span class="small text-muted me-1">Тип:</span>
{% for code, label in type_choices %}
<input type="checkbox" class="btn-check" name="types" id="type_{{ code }}" value="{{ code }}" {% if code in selected_types %}checked{% endif %} onchange="this.form.submit()">
<label class="btn btn-sm {% if code == 'raw' %}btn-outline-info{% elif code == 'purchased' %}btn-outline-primary{% elif code == 'casting' %}btn-outline-secondary{% elif code == 'outsourced' %}btn-outline-warning{% else %}btn-outline-secondary{% endif %}" for="type_{{ code }}">{{ label }}</label>
{% endfor %}
</div>
<div class="d-flex flex-wrap align-items-center gap-1">
<span class="small text-muted me-1">Статус:</span>
{% for code, label in status_choices %}
<input type="checkbox" class="btn-check" name="statuses" id="st_{{ code }}" value="{{ code }}" {% if code in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
<label class="btn btn-sm {% if code == 'to_order' %}btn-outline-danger{% elif code == 'ordered' %}btn-outline-warning{% else %}btn-outline-success{% endif %}" for="st_{{ code }}">{{ label }}</label>
{% endfor %}
</div>
</form>
</div>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0 align-middle" data-sortable="1">
<thead>
<tr class="table-custom-header">
<th>Компонент</th>
<th style="width: 140px;">Тип</th>
<th style="width: 140px;">К заказу</th>
<th style="width: 220px;">Сделки</th>
<th style="width: 140px;">Статус</th>
<th style="width: 70px;" data-sort="false"></th>
</tr>
</thead>
<tbody>
{% for r in requirements %}
<tr>
<td>
<div class="fw-semibold">{{ r.component_label }}</div>
</td>
<td class="small">
{% if r.type == 'raw' %}Сырьё{% elif r.type == 'purchased' %}Покупное{% elif r.type == 'casting' %}Литьё{% elif r.type == 'outsourced' %}Аутсорс{% else %}—{% endif %}
</td>
<td class="fw-semibold">
{{ r.required_qty }}{% if r.kind == 'raw' %} {{ r.unit }}{% endif %}
</td>
<td>
{% if r.deals and r.deals|length > 0 %}
{% for dn in r.deals|slice:":3" %}
<span class="badge bg-secondary">{{ dn }}</span>
{% endfor %}
{% if r.deals|length > 3 %}
<span class="badge bg-secondary" title="{{ r.deals|join:", " }}"></span>
{% endif %}
{% else %}
<span class="text-muted"></span>
{% endif %}
</td>
<td>
{% if r.status == 'to_order' %}
<span class="badge bg-danger">К заказу</span>
{% elif r.status == 'ordered' %}
<span class="badge bg-warning text-dark">Заказано</span>
{% else %}
<span class="badge bg-success">Закрыто</span>
{% endif %}
</td>
<td class="text-end">
{% if can_edit and not grouped and r.kind == 'component' %}
{% if r.status == 'to_order' %}
<form method="post" class="d-inline">
{% csrf_token %}
<input type="hidden" name="action" value="mark_ordered">
<input type="hidden" name="pr_id" value="{{ r.obj_id }}">
<input type="hidden" name="next" value="{{ request.get_full_path }}">
<button type="submit" class="btn btn-outline-accent btn-sm" title="Отметить как заказано">+</button>
</form>
{% elif r.status == 'ordered' %}
<button
type="button"
class="btn btn-outline-accent btn-sm"
title="Оформить приход"
data-bs-toggle="modal"
data-bs-target="#receiveModal"
data-pr-id="{{ r.obj_id }}"
data-label="{{ r.component_label }}"
data-deal-id="{{ r.deal_id }}"
data-deal-number="{{ r.deals.0 }}"
data-max="{{ r.required_qty }}"
>+</button>
{% else %}
<span class="text-muted"></span>
{% endif %}
{% else %}
<span class="text-muted"></span>
{% endif %}
</td>
</tr>
{% empty %}
<tr><td colspan="6" class="text-center p-5 text-muted">Потребностей не найдено</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<div class="modal fade" id="receiveModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<form method="post" class="modal-content border-secondary">
{% csrf_token %}
<input type="hidden" name="action" value="receive_component">
<input type="hidden" name="next" value="{{ request.get_full_path }}">
<input type="hidden" name="pr_id" id="receivePrId">
<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 small text-muted" id="receiveLabel"></div>
<div class="mb-3">
<label class="form-label">Склад</label>
<select class="form-select border-secondary" name="location_id" required>
{% for loc in locations %}
<option value="{{ loc.id }}">{{ loc.name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Сделка (опционально)</label>
<select class="form-select border-secondary" name="deal_id" id="receiveDealId">
<option value="">Свободно</option>
{% for d in deals %}
<option value="{{ d.id }}">{{ d.number }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Количество (шт)</label>
<input class="form-control border-secondary" name="quantity" id="receiveQty" placeholder="Напр. 100" required>
<div class="form-text">Количество уменьшит потребность выбранной строки. При достижении 0 статус станет «Закрыто».</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>
<script>
(function () {
const modal = document.getElementById('receiveModal');
if (!modal) return;
const prId = document.getElementById('receivePrId');
const label = document.getElementById('receiveLabel');
const dealId = document.getElementById('receiveDealId');
const qty = document.getElementById('receiveQty');
modal.addEventListener('show.bs.modal', function (event) {
const btn = event.relatedTarget;
if (!btn) return;
const id = btn.getAttribute('data-pr-id') || '';
const text = btn.getAttribute('data-label') || '';
const max = btn.getAttribute('data-max') || '';
const dId = btn.getAttribute('data-deal-id') || '';
const dNum = btn.getAttribute('data-deal-number') || '';
if (prId) prId.value = id;
if (label) label.textContent = (text ? ('Компонент: ' + text) : '') + (dNum ? (' · Сделка: ' + dNum) : '');
if (dealId) dealId.value = dId;
if (qty) {
qty.value = max || '';
qty.focus();
qty.select();
}
});
})();
</script>
{% endblock %}