добавил детальный вид итема, пока недопиленый
All checks were successful
Deploy MES Core / deploy (push) Successful in 8s
All checks were successful
Deploy MES Core / deploy (push) Successful in 8s
This commit is contained in:
120
shiftflow/templates/shiftflow/item_detail copy.html
Normal file
120
shiftflow/templates/shiftflow/item_detail copy.html
Normal file
@@ -0,0 +1,120 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block title %}ShiftFlow | {{ item.drawing_name|default:"Б/ч" }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10 col-xl-8">
|
||||
|
||||
<div class="card shadow bg-dark text-light border-secondary mb-4">
|
||||
|
||||
<div class="card-header border-secondary d-flex justify-content-between align-items-center py-3">
|
||||
<h3 class="text-accent mb-0">
|
||||
<i class="bi bi-info-circle me-2"></i>
|
||||
Деталь: {{ item.drawing_name|default:"Без чертежа" }}
|
||||
</h3>
|
||||
<span class="badge bg-secondary opacity-75 fw-normal">ID: {{ item.id }}</span>
|
||||
</div>
|
||||
|
||||
<form method="post" class="card-body p-4">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row g-3 mb-4 border-bottom border-secondary pb-4">
|
||||
<div class="col-md-4 col-6">
|
||||
<label class="small text-muted">Дата задания:</label>
|
||||
<div class="fw-bold">{{ item.date|date:"d.m.Y" }}</div>
|
||||
</div>
|
||||
<div class="col-md-4 col-6">
|
||||
<label class="small text-muted">Станок:</label>
|
||||
<div class="fw-bold"><i class="bi bi-cpu me-1"></i>{{ item.machine.name }}</div>
|
||||
</div>
|
||||
<div class="col-md-4 col-12">
|
||||
<label class="small text-muted">Сделка/Заказ:</label>
|
||||
<div class="fw-bold text-accent fs-5">№ {{ item.deal.number }}</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<label class="small text-muted">Материал / Габариты:</label>
|
||||
<div class="fw-bold small">{{ item.material.name }} (s{{ item.size_value|default:"-" }})</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h5 class="text-accent mb-3"><i class="bi bi-files me-2"></i>Файлы задания</h5>
|
||||
<div class="d-flex gap-2">
|
||||
{% if item.drawing_file %}
|
||||
<a href="{{ item.drawing_file.url }}" target="_blank" class="btn btn-outline-info">
|
||||
<i class="bi bi-file-earmark-code me-2"></i>Открыть DXF/STEP
|
||||
</a>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary p-1" disabled><i class="bi bi-file-earmark-code me-1"></i>DXF: нет файла</button>
|
||||
{% endif %}
|
||||
|
||||
{% if item.extra_drawing %}
|
||||
<a href="{{ item.extra_drawing.url }}" target="_blank" class="btn btn-outline-danger">
|
||||
<i class="bi bi-file-pdf me-2"></i>Открыть Чертеж PDF
|
||||
</a>
|
||||
{% else %}
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary p-1" disabled><i class="bi bi-file-pdf me-1"></i>PDF: нет файла</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h5 class="text-accent mb-3"><i class="bi bi-vector-pen me-2"></i>Фактическое исполнение</h5>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4 col-6">
|
||||
<label class="form-label small text-muted">Заказано штук (План):</label>
|
||||
<input type="number" class="form-control form-control-lg fw-bold bg-secondary text-info" value="{{ item.quantity_plan }}" readonly disabled>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-6">
|
||||
<label for="id_quantity_fact" class="form-label small text-muted">Изготовлено штук (Факт):</label>
|
||||
<input type="number" name="quantity_fact" id="id_quantity_fact" class="form-control form-control-lg bg-dark text-light border-secondary" value="{{ item.quantity_fact }}" min="0" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 col-12 d-flex align-items-end">
|
||||
<div class="form-check form-switch bg-dark border border-secondary p-3 rounded shadow-sm w-100 h-100 d-flex align-items-center justify-content-between">
|
||||
<label class="form-check-label ms-1 text-light small" for="id_is_synced_1c">Списано в 1С?</label>
|
||||
<input class="form-check-input form-switch-lg stop-prop" type="checkbox" name="is_synced_1c" id="id_is_synced_1c" {% if item.is_synced_1c %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-5">
|
||||
<label for="id_status" class="form-label small text-muted">Текущий статус задания:</label>
|
||||
<select name="status" id="id_status" class="form-select bg-dark text-light border-secondary form-select-lg">
|
||||
{% for choice_val, choice_label in form.fields.status.choices %}
|
||||
<option value="{{ choice_val }}" {% if item.status == choice_val %}selected{% endif %}>
|
||||
{{ choice_label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="card-footer border-secondary bg-dark p-0 pt-4 d-flex justify-content-between">
|
||||
<a href="{% url 'registry' %}" class="btn btn-outline-secondary btn-lg px-4">
|
||||
<i class="bi bi-arrow-left me-2"></i>В реестр
|
||||
</a>
|
||||
<button type="submit" class="btn btn-outline-accent btn-lg px-5 fw-bold">
|
||||
<i class="bi bi-save me-2"></i>Сохранить изменения
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger mt-4 small mb-0 p-3 shadow-sm border-danger">
|
||||
<h6 class="fw-bold mb-2">Обнаружены ошибки:</h6>
|
||||
<ul class="mb-0">
|
||||
{% for field, errors in form.errors.items %}
|
||||
{% for error in errors %}
|
||||
<li>{{ field|upper }}: {{ error }}</li>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
126
shiftflow/templates/shiftflow/item_detail.html
Normal file
126
shiftflow/templates/shiftflow/item_detail.html
Normal file
@@ -0,0 +1,126 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10 col-xl-8">
|
||||
<div class="card shadow-sm border-secondary mb-4">
|
||||
|
||||
<div class="card-header border-secondary d-flex justify-content-between align-items-center py-3">
|
||||
<h3 class="text-accent mb-0"><i class="bi bi-info-circle me-2"></i>{{ item.drawing_name|default:"Без названия" }}</h3>
|
||||
<span class="badge bg-secondary">Сделка № {{ item.deal.number }}</span>
|
||||
</div>
|
||||
|
||||
<form method="post" id="mainForm" class="card-body p-4">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="row g-3 mb-4 border-bottom border-secondary pb-3 text-body">
|
||||
<div class="col-md-4">
|
||||
<small class="text-muted d-block">Станок</small>
|
||||
<strong>{{ item.machine.name }}</strong>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<small class="text-muted d-block">Материал</small>
|
||||
<strong>{{ item.material.name }}</strong>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<small class="text-muted d-block">План</small>
|
||||
<strong class="text-info fs-5">{{ item.quantity_plan }} шт.</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 d-flex gap-2">
|
||||
{% if item.drawing_file %}<a href="{{ item.drawing_file.url }}" target="_blank" class="btn btn-outline-info btn-sm">DXF</a>{% endif %}
|
||||
{% if item.extra_drawing %}<a href="{{ item.extra_drawing.url }}" target="_blank" class="btn btn-outline-danger btn-sm">PDF</a>{% endif %}
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="status" id="id_status" value="{{ item.status }}">
|
||||
|
||||
{% if user_role in 'operator,master' %}
|
||||
{% if item.status == 'work' %}
|
||||
<div class="bg-body-tertiary p-3 rounded border mb-4 text-center">
|
||||
<h5 class="mb-3">Закрыть задание:</h5>
|
||||
<div class="btn-group btn-group-lg w-100">
|
||||
<button type="button" class="btn btn-success" onclick="closeTask('done')">
|
||||
<i class="bi bi-check-all"></i> Выполнено
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-warning" onclick="showPartial()">
|
||||
Частично
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div id="partialInput" class="mt-3 d-none">
|
||||
<label class="small text-muted">Сколько сделано?</label>
|
||||
<input type="number" name="quantity_fact" id="id_quantity_fact" class="form-control form-control-lg text-center mx-auto" style="max-width: 200px;" value="{{ item.quantity_fact }}" max="{{ item.quantity_plan }}">
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-success">Статус: {{ item.get_status_display }}. Сделано: {{ item.quantity_fact }} шт.</div>
|
||||
<input type="hidden" name="quantity_fact" value="{{ item.quantity_fact }}">
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if user_role == 'admin' %}
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="small text-muted">Статус задания (Админ)</label>
|
||||
<select name="status" class="form-select border-secondary">
|
||||
{% for val, name in form.fields.status.choices %}
|
||||
<option value="{{ val }}" {% if item.status == val %}selected{% endif %}>{{ name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="small text-muted">Факт (шт)</label>
|
||||
<input type="number" name="quantity_fact" class="form-control border-secondary" value="{{ item.quantity_fact }}">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user_role in 'admin,clerk' %}
|
||||
{% if item.status == 'done' or item.quantity_fact > 0 %}
|
||||
<div class="form-check form-switch p-3 rounded border border-warning mb-4 bg-body-tertiary d-flex justify-content-between align-items-center">
|
||||
<label class="form-check-label fw-bold ms-2" for="sync1c">Списано в 1С</label>
|
||||
<input class="form-check-input ms-0" style="width: 3em; height: 1.5em;" type="checkbox" name="is_synced_1c" id="sync1c" {% if item.is_synced_1c %}checked{% endif %}>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="text-muted small mb-4"><i class="bi bi-info-circle me-1"></i>Списание будет доступно после выполнения.</div>
|
||||
{% endif %}
|
||||
{% if user_role == 'clerk' %}<input type="hidden" name="quantity_fact" value="{{ item.quantity_fact }}">{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div class="d-flex justify-content-between mt-4">
|
||||
<a href="{% url 'registry' %}" class="btn btn-outline-secondary">Назад</a>
|
||||
<button type="submit" class="btn btn-outline-accent px-5 fw-bold">
|
||||
<i class="bi bi-save me-2"></i>
|
||||
{% if user_role in 'operator,master' %}Закрыть задание{% else %}Сохранить{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function closeTask(status) {
|
||||
document.getElementById('id_status').value = status;
|
||||
// Если "Выполнено", автоматом ставим факт = плану
|
||||
if(status === 'done') {
|
||||
const factInput = document.getElementById('id_quantity_fact');
|
||||
if(factInput) factInput.value = "{{ item.quantity_plan }}";
|
||||
else {
|
||||
let hiddenFact = document.createElement('input');
|
||||
hiddenFact.type = 'hidden';
|
||||
hiddenFact.name = 'quantity_fact';
|
||||
hiddenFact.value = "{{ item.quantity_plan }}";
|
||||
document.getElementById('mainForm').appendChild(hiddenFact);
|
||||
}
|
||||
}
|
||||
document.getElementById('mainForm').submit();
|
||||
}
|
||||
|
||||
function showPartial() {
|
||||
document.getElementById('partialInput').classList.remove('d-none');
|
||||
document.getElementById('id_status').value = 'part'; // Статус Частично
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -1,65 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'shiftflow/partials/_filter.html' %}
|
||||
|
||||
{% if not selected_machines %}
|
||||
<div class="alert alert-warning text-center mt-4">
|
||||
<i class="bi bi-info-circle me-2"></i> Станки не выбраны. Выберите станки в фильтре для отображения позиций.
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
{% if in_work is not None %}
|
||||
<h6 class="text-primary mt-4 fw-bold"><i class="bi bi-play-circle me-2"></i>В РАБОТЕ</h6>
|
||||
<div class="table-responsive rounded border shadow-sm mb-4">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead class="table-custom-header small fw-bold text-uppercase">
|
||||
<tr>
|
||||
<th style="width: 80px;">Сделка</th>
|
||||
<th>Деталь / Чертеж</th>
|
||||
<th>Материал</th>
|
||||
<th class="text-center">План</th>
|
||||
<th class="text-center">Факт</th>
|
||||
{% if user_role in 'admin,technologist,master,operator' %}
|
||||
<th class="text-end">Действия</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in in_work %}
|
||||
<tr>
|
||||
<td class="small">{{ item.deal.number }}</td>
|
||||
<td><strong>{{ item.drawing_name }}</strong> <small class="text-muted">({{ item.machine.name }})</small></td>
|
||||
<td><span class="badge bg-secondary opacity-75">{{ item.material.name }}</span></td>
|
||||
<td class="text-center fw-bold">{{ item.quantity_plan }}</td>
|
||||
<td class="text-center" style="width: 100px;">
|
||||
<input type="number" class="form-control form-control-sm text-center" value="{{ item.quantity_fact|default:0 }}" {% if user_role == 'clerk' %}readonly{% endif %}>
|
||||
</td>
|
||||
{% if user_role in 'admin,technologist,master,operator' %}
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-outline-success"><i class="bi bi-check2-all"></i></button>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="6" class="text-center py-4 text-muted small">Активных заданий нет</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if backlog is not None %}
|
||||
<h6 class="text-danger fw-bold"><i class="bi bi-exclamation-triangle me-2"></i>НЕДОДЕЛЫ (ХВОСТЫ)</h6>
|
||||
<div class="table-responsive rounded border shadow-sm mb-4">
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if done_items is not None %}
|
||||
<h6 class="text-success fw-bold"><i class="bi bi-check-circle me-2"></i>ЗАВЕРШЕНО</h6>
|
||||
<div class="table-responsive rounded border shadow-sm">
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -1,38 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card shadow bg-dark text-light border-secondary">
|
||||
<div class="card-header border-secondary d-flex justify-content-between align-items-center">
|
||||
<h3 class="text-accent mb-0">Реестр деталей</h3>
|
||||
{% if user_role == 'admin' or user_role == 'technologist' %}
|
||||
<button class="btn btn-sm btn-outline-accent">+ Добавить заказ</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-dark table-hover">
|
||||
<thead>
|
||||
<tr class="table-custom-header">
|
||||
<th>ID</th>
|
||||
<th>Наименование</th>
|
||||
<th>Кол-во</th>
|
||||
<th>Статус</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>{{ item.id }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>{{ item.quantity }}</td>
|
||||
<td><span class="badge bg-secondary">{{ item.status }}</span></td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-muted">Деталей пока нет</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,12 +1,14 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="text-center">
|
||||
<h1 class="text-accent mb-4 display-3 fw-bold">
|
||||
<i class="bi bi-gear-fill me-3"></i>ShiftFlow
|
||||
</h1>
|
||||
<a href="{% url 'login' %}" class="btn btn-lg btn-outline-accent px-5 py-3 fw-bold shadow">
|
||||
ВОЙТИ В СИСТЕМУ
|
||||
</a>
|
||||
<div class="flex-center-center">
|
||||
<div class="text-center">
|
||||
<h1 class="text-accent mb-4 display-3 fw-bold">
|
||||
<i class="bi bi-gear-fill me-3"></i>ShiftFlow
|
||||
</h1>
|
||||
<a href="{% url 'login' %}" class="btn btn-lg btn-outline-accent px-5 py-3 fw-bold shadow">
|
||||
ВОЙТИ В СИСТЕМУ
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
86
shiftflow/templates/shiftflow/registry.html
Normal file
86
shiftflow/templates/shiftflow/registry.html
Normal file
@@ -0,0 +1,86 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card shadow border-secondary">
|
||||
<div class="card-header border-secondary py-3">
|
||||
<h3 class="text-accent mb-0"><i class="bi bi-list-task me-2"></i>Реестр заданий</h3>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0 align-middle">
|
||||
<thead>
|
||||
<tr class="table-custom-header">
|
||||
<th>Дата</th>
|
||||
<th>Сделка</th>
|
||||
<th>Станок</th>
|
||||
<th>Наименование</th>
|
||||
<th>Габариты</th>
|
||||
<th>План / Факт</th>
|
||||
<th>Материал</th>
|
||||
<th class="text-center">Файлы</th>
|
||||
<th class="text-center">1С</th>
|
||||
<th>Статус</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr class="clickable-row" data-href="{% url 'item_detail' item.pk %}">
|
||||
<td class="small">{{ item.date|date:"d.m.y" }}</td>
|
||||
<td><span class="text-accent fw-bold">{{ item.deal.number }}</span></td>
|
||||
<td><span class="badge bg-dark border border-secondary">{{ item.machine.name }}</span></td>
|
||||
<td class="fw-bold">{{ item.drawing_name }}</td>
|
||||
<td class="small">{{ item.size_value }}</td>
|
||||
<td>
|
||||
<span class="text-info fw-bold">{{ item.quantity_plan }}</span> /
|
||||
<span class="text-success">{{ item.quantity_fact }}</span>
|
||||
</td>
|
||||
<td class="small text-muted">{{ item.material.name }}</td>
|
||||
<td class="text-center">
|
||||
{% if item.drawing_file %}
|
||||
<a href="{{ item.drawing_file.url }}" target="_blank" class="btn btn-sm btn-outline-info p-1 stop-prop" title="DXF/STEP">
|
||||
<i class="bi bi-file-earmark-code"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if item.extra_drawing %}
|
||||
<a href="{{ item.extra_drawing.url }}" target="_blank" class="btn btn-sm btn-outline-danger p-1 stop-prop" title="Чертеж PDF">
|
||||
<i class="bi bi-file-pdf"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{% if item.is_synced_1c %}
|
||||
<i class="bi bi-check-circle-fill text-success" title="Учтено"></i>
|
||||
{% else %}
|
||||
<i class="bi bi-clock-history text-muted" title="Ожидает"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="badge {% if item.status == 'work' %}bg-primary{% elif item.status == 'done' %}bg-success{% else %}bg-secondary{% endif %}">
|
||||
{{ item.get_status_display }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="10" class="text-center p-5 text-muted">Заданий не найдено</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
const rows = document.querySelectorAll(".clickable-row");
|
||||
rows.forEach(row => {
|
||||
row.addEventListener("click", function(e) {
|
||||
// Если нажали на ссылку файла (класс stop-prop), не переходим на страницу деталей
|
||||
if (e.target.closest('.stop-prop')) return;
|
||||
// Иначе переходим по ссылке из data-href
|
||||
window.location.href = this.dataset.href;
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user