Ver.07
This commit is contained in:
parent
d58a583044
commit
6ed717407d
BIN
assets/pasted-20260127-202812-8ab5fa36.png
Normal file
BIN
assets/pasted-20260127-202812-8ab5fa36.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 363 KiB |
Binary file not shown.
Binary file not shown.
@ -43,10 +43,18 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-end px-4">
|
||||
<a href="{{ b.fleet_unit.get_absolute_url }}" class="btn btn-sm btn-outline-primary rounded-pill px-3">К технике</a>
|
||||
{% if b.status == 'need_part' %}
|
||||
<a href="{% url 'part_request_add' %}?breakdown={{ b.pk }}" class="btn btn-sm btn-outline-warning rounded-pill px-3">Заказать запчасть</a>
|
||||
{% endif %}
|
||||
<div class="btn-group">
|
||||
<a href="{{ b.fleet_unit.get_absolute_url }}" class="btn btn-sm btn-outline-primary rounded-pill px-3 me-2">К технике</a>
|
||||
{% if b.status == 'need_part' %}
|
||||
<a href="{% url 'part_request_add' %}?breakdown={{ b.pk }}" class="btn btn-sm btn-outline-warning rounded-pill px-3 me-2">Заказать запчасть</a>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'breakdown_delete' b.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить запись о поломке?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger rounded-pill px-2" title="Удалить"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
@ -59,4 +67,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -51,6 +51,12 @@
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<a href="{% url 'fleet_edit' unit.pk %}" class="btn btn-outline-primary rounded-pill">Редактировать</a>
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'fleet_delete' unit.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Вы уверены, что хотите удалить эту единицу техники? Все связанные данные будут удалены.')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-outline-danger rounded-pill w-100 mb-2">Удалить технику</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
<a href="{% url 'breakdown_add' %}?fleet_unit={{ unit.pk }}" class="btn btn-danger rounded-pill">Заявить о поломке</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -114,7 +120,15 @@
|
||||
<td><span class="badge bg-{{ m.status|yesno:'success,warning,secondary' }} rounded-pill small">{{ m.get_status_display }}</span></td>
|
||||
<td>{{ m.mechanic|default:"-" }}</td>
|
||||
<td class="text-end">
|
||||
<a href="{% url 'maintenance_detail' m.pk %}" class="btn btn-sm btn-link text-primary">Открыть</a>
|
||||
<div class="btn-group">
|
||||
<a href="{% url 'maintenance_detail' m.pk %}" class="btn btn-sm btn-link text-primary p-0 me-2">Открыть</a>
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'maintenance_delete' m.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить запись ТО?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
@ -136,7 +150,15 @@
|
||||
<div class="list-group-item px-0 py-3">
|
||||
<div class="d-flex justify-content-between mb-1">
|
||||
<h6 class="mb-0 fw-bold text-danger">{{ b.system_node }}</h6>
|
||||
<span class="badge bg-light text-dark border small">{{ b.get_status_display }}</span>
|
||||
<div>
|
||||
<span class="badge bg-light text-dark border small me-2">{{ b.get_status_display }}</span>
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'breakdown_delete' b.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить запись о поломке?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="small mb-1 text-muted">{{ b.date|date:"d.m.Y" }} — {{ b.description }}</p>
|
||||
<div class="d-flex align-items-center mt-2">
|
||||
@ -164,6 +186,7 @@
|
||||
<th>Кол-во</th>
|
||||
<th>Статус</th>
|
||||
<th>Дата</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -173,9 +196,17 @@
|
||||
<td>{{ r.quantity }}</td>
|
||||
<td><span class="badge bg-light text-dark border rounded-pill small">{{ r.get_status_display }}</span></td>
|
||||
<td class="small">{{ r.created_at|date:"d.m.Y" }}</td>
|
||||
<td class="text-end">
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'part_request_delete' r.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить заявку?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="4" class="text-center py-4 text-muted">Нет заявок</td></tr>
|
||||
<tr><td colspan="5" class="text-center py-4 text-muted">Нет заявок</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
@ -223,6 +254,7 @@
|
||||
<th>Деталь</th>
|
||||
<th>Статус</th>
|
||||
<th>Дата</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -231,9 +263,17 @@
|
||||
<td>{{ r.part_name }}</td>
|
||||
<td><span class="badge bg-light text-dark border rounded-pill small">{{ r.get_status_display }}</span></td>
|
||||
<td class="small">{{ r.created_at|date:"d.m.Y" }}</td>
|
||||
<td class="text-end">
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'part_request_delete' r.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить заявку?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-link text-danger p-0"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="3" class="text-center py-4 text-muted">Нет заявок</td></tr>
|
||||
<tr><td colspan="4" class="text-center py-4 text-muted">Нет заявок</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
@ -252,4 +292,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -41,7 +41,15 @@
|
||||
</td>
|
||||
<td>{{ m.mechanic|default:"-" }}</td>
|
||||
<td class="text-end px-4">
|
||||
<a href="{% url 'maintenance_detail' m.pk %}" class="btn btn-sm btn-outline-primary rounded-pill px-3">Открыть</a>
|
||||
<div class="btn-group">
|
||||
<a href="{% url 'maintenance_detail' m.pk %}" class="btn btn-sm btn-outline-primary rounded-pill px-3 me-2">Открыть</a>
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'maintenance_delete' m.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить запись ТО?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger rounded-pill px-2" title="Удалить"><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
@ -54,4 +62,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@ -43,7 +43,17 @@
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<a href="#" class="btn btn-sm btn-outline-primary">Управление</a>
|
||||
<div class="btn-group">
|
||||
<a href="#" class="btn btn-sm btn-outline-primary">Управление</a>
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'part_request_delete' req.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить заявку?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger ms-1" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
@ -63,7 +73,7 @@
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
|
||||
<h5 class="card-title mb-0">Поставщики</h5>
|
||||
<a href="{% url 'supplier_add' %}" class="btn btn-sm btn-primary">
|
||||
<a href="{% url 'supplier_create' %}" class="btn btn-sm btn-primary">
|
||||
<i class="bi bi-plus-lg"></i> Добавить
|
||||
</a>
|
||||
</div>
|
||||
@ -73,9 +83,19 @@
|
||||
<div class="list-group-item px-0 py-3">
|
||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||
<h6 class="mb-1">{{ supplier.name }}</h6>
|
||||
<a href="{% url 'supplier_edit' supplier.pk %}" class="btn btn-sm btn-link p-0 text-muted">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</a>
|
||||
<div class="btn-group">
|
||||
<a href="{% url 'supplier_edit' supplier.pk %}" class="btn btn-sm btn-link p-0 text-muted me-2" title="Редактировать">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</a>
|
||||
{% if user.is_staff %}
|
||||
<form action="{% url 'supplier_delete' supplier.pk %}" method="POST" class="d-inline" onsubmit="return confirm('Удалить поставщика?')">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-sm btn-link p-0 text-danger" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p class="mb-1 small text-muted">
|
||||
<strong>Менеджер:</strong> {{ supplier.representative_name|default:"-" }}<br>
|
||||
|
||||
@ -9,12 +9,14 @@ urlpatterns = [
|
||||
path('fleet/<int:pk>/', views.FleetDetailView.as_view(), name='fleet_detail'),
|
||||
path('fleet/add/', views.FleetCreateView.as_view(), name='fleet_add'),
|
||||
path('fleet/<int:pk>/edit/', views.FleetUpdateView.as_view(), name='fleet_edit'),
|
||||
path('fleet/<int:pk>/delete/', views.FleetUnitDeleteView.as_view(), name='fleet_delete'),
|
||||
|
||||
# Maintenance
|
||||
path('maintenance/', views.MaintenanceListView.as_view(), name='maintenance_list'),
|
||||
path('maintenance/<int:pk>/', views.MaintenanceDetailView.as_view(), name='maintenance_detail'),
|
||||
path('maintenance/add/', views.MaintenanceCreateView.as_view(), name='maintenance_add'),
|
||||
path('maintenance/<int:pk>/edit/', views.MaintenanceUpdateView.as_view(), name='maintenance_edit'),
|
||||
path('maintenance/<int:pk>/delete/', views.MaintenanceDeleteView.as_view(), name='maintenance_delete'),
|
||||
path('maintenance/<int:pk>/process/', views.MaintenanceProcessView.as_view(), name='maintenance_process'),
|
||||
path('maintenance/<int:pk>/complete/', views.MaintenanceCompleteView.as_view(), name='maintenance_complete'),
|
||||
path('maintenance/<int:pk>/pdf/', views.MaintenancePDFView.as_view(), name='maintenance_pdf'),
|
||||
@ -22,13 +24,16 @@ urlpatterns = [
|
||||
# Breakdown
|
||||
path('breakdown/', views.BreakdownListView.as_view(), name='breakdown_list'),
|
||||
path('breakdown/add/', views.BreakdownCreateView.as_view(), name='breakdown_add'),
|
||||
path('breakdown/<int:pk>/delete/', views.BreakdownDeleteView.as_view(), name='breakdown_delete'),
|
||||
|
||||
# Part Request
|
||||
path('part-request/', views.PartRequestListView.as_view(), name='part_request_list'),
|
||||
path('part-request/add/', views.PartRequestCreateView.as_view(), name='part_request_add'),
|
||||
path('part-request/<int:pk>/delete/', views.PartRequestDeleteView.as_view(), name='part_request_delete'),
|
||||
|
||||
# Supply
|
||||
path('supply/', views.SupplyListView.as_view(), name='supply_list'),
|
||||
path('supplier/add/', views.SupplierCreateView.as_view(), name='supplier_add'),
|
||||
path('supplier/add/', views.SupplierCreateView.as_view(), name='supplier_create'),
|
||||
path('supplier/<int:pk>/edit/', views.SupplierUpdateView.as_view(), name='supplier_edit'),
|
||||
path('supplier/<int:pk>/delete/', views.SupplierDeleteView.as_view(), name='supplier_delete'),
|
||||
]
|
||||
@ -1,11 +1,11 @@
|
||||
import json
|
||||
from io import BytesIO
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.views.generic import ListView, DetailView, CreateView, UpdateView, TemplateView, View
|
||||
from django.views.generic import ListView, DetailView, CreateView, UpdateView, TemplateView, View, DeleteView
|
||||
from django.urls import reverse_lazy, reverse
|
||||
from django import forms
|
||||
from django.db.models import Count, Q
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
||||
from django.http import HttpResponse
|
||||
from reportlab.pdfgen import canvas
|
||||
from reportlab.lib.pagesizes import A4
|
||||
@ -13,6 +13,11 @@ from reportlab.pdfbase import pdfmetrics
|
||||
from reportlab.pdfbase.ttfonts import TTFont
|
||||
from .models import FleetUnit, Maintenance, Breakdown, PartRequest, Category, Document, Supplier
|
||||
|
||||
# Mixins
|
||||
class StaffRequiredMixin(UserPassesTestMixin):
|
||||
def test_func(self):
|
||||
return self.request.user.is_staff
|
||||
|
||||
# Forms
|
||||
class FleetUnitForm(forms.ModelForm):
|
||||
class Meta:
|
||||
@ -159,6 +164,10 @@ class FleetUpdateView(UpdateView):
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('fleet_detail', kwargs={'pk': self.object.pk})
|
||||
|
||||
class FleetUnitDeleteView(LoginRequiredMixin, StaffRequiredMixin, DeleteView):
|
||||
model = FleetUnit
|
||||
success_url = reverse_lazy('fleet_list')
|
||||
|
||||
# Maintenance Views
|
||||
class MaintenanceListView(ListView):
|
||||
model = Maintenance
|
||||
@ -205,6 +214,10 @@ class MaintenanceUpdateView(UpdateView):
|
||||
def get_success_url(self):
|
||||
return reverse('maintenance_detail', kwargs={'pk': self.object.pk})
|
||||
|
||||
class MaintenanceDeleteView(LoginRequiredMixin, StaffRequiredMixin, DeleteView):
|
||||
model = Maintenance
|
||||
success_url = reverse_lazy('maintenance_list')
|
||||
|
||||
class MaintenanceProcessView(View):
|
||||
def post(self, request, pk):
|
||||
maintenance = get_object_or_404(Maintenance, pk=pk)
|
||||
@ -299,6 +312,11 @@ class BreakdownCreateView(CreateView):
|
||||
def get_success_url(self):
|
||||
return reverse('fleet_detail', kwargs={'pk': self.object.fleet_unit.pk})
|
||||
|
||||
class BreakdownDeleteView(LoginRequiredMixin, StaffRequiredMixin, DeleteView):
|
||||
model = Breakdown
|
||||
def get_success_url(self):
|
||||
return reverse('fleet_detail', kwargs={'pk': self.object.fleet_unit.pk})
|
||||
|
||||
# Part Request Views
|
||||
class PartRequestListView(ListView):
|
||||
model = PartRequest
|
||||
@ -325,6 +343,11 @@ class PartRequestCreateView(CreateView):
|
||||
def get_success_url(self):
|
||||
return reverse('fleet_detail', kwargs={'pk': self.object.fleet_unit.pk})
|
||||
|
||||
class PartRequestDeleteView(LoginRequiredMixin, StaffRequiredMixin, DeleteView):
|
||||
model = PartRequest
|
||||
def get_success_url(self):
|
||||
return reverse('supply_list')
|
||||
|
||||
class SupplyListView(ListView):
|
||||
model = PartRequest
|
||||
template_name = 'core/supply_list.html'
|
||||
@ -345,4 +368,8 @@ class SupplierUpdateView(UpdateView):
|
||||
model = Supplier
|
||||
form_class = SupplierForm
|
||||
template_name = 'core/supplier_form.html'
|
||||
success_url = reverse_lazy('supply_list')
|
||||
success_url = reverse_lazy('supply_list')
|
||||
|
||||
class SupplierDeleteView(LoginRequiredMixin, StaffRequiredMixin, DeleteView):
|
||||
model = Supplier
|
||||
success_url = reverse_lazy('supply_list')
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user