Доработали фильт в реестре заданий
All checks were successful
Deploy MES Core / deploy (push) Successful in 10s
All checks were successful
Deploy MES Core / deploy (push) Successful in 10s
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import os
|
||||
from django.contrib import admin
|
||||
from .models import Company, EmployeeProfile, Machine, Deal, Material, ProductionTask, Item
|
||||
from .models import Company, EmployeeProfile, Machine, Deal, ProductionTask, Item
|
||||
|
||||
# --- Настройка отображения Компаний ---
|
||||
@admin.register(Company)
|
||||
@@ -15,11 +15,6 @@ class DealAdmin(admin.ModelAdmin):
|
||||
search_fields = ('number', 'company__name')
|
||||
list_filter = ('company',)
|
||||
|
||||
# --- Настройка отображения Материалов ---
|
||||
@admin.register(Material)
|
||||
class MaterialAdmin(admin.ModelAdmin):
|
||||
search_fields = ('name',)
|
||||
|
||||
# --- Задания на производство (База) ---
|
||||
@admin.register(ProductionTask)
|
||||
class ProductionTaskAdmin(admin.ModelAdmin):
|
||||
@@ -50,10 +45,12 @@ class ItemAdmin(admin.ModelAdmin):
|
||||
}),
|
||||
)
|
||||
|
||||
def get_deal(self, obj): return obj.task.deal
|
||||
def get_deal(self, obj):
|
||||
return obj.task.deal if obj.task else "-"
|
||||
get_deal.short_description = 'Сделка'
|
||||
|
||||
def get_drawing(self, obj): return obj.task.drawing_name
|
||||
def get_drawing(self, obj):
|
||||
return obj.task.drawing_name if obj.task else "-"
|
||||
get_drawing.short_description = 'Деталь'
|
||||
|
||||
# Регистрация станков просто списком
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 6.0.3 on 2026-03-29 14:16
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('shiftflow', '0004_alter_item_options_remove_item_deal_and_more'),
|
||||
('warehouse', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='productiontask',
|
||||
name='material',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='warehouse.material', verbose_name='Материал'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Material',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# Generated by Django 6.0.3 on 2026-03-29 16:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('shiftflow', '0005_alter_productiontask_material_delete_material'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='item',
|
||||
options={'ordering': ['-date', 'task__deal'], 'verbose_name': 'Пункт сменки', 'verbose_name_plural': 'Реестр сменных заданий'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='item',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('work', 'В работе'), ('done', 'Выполнено'), ('partial', 'Частично'), ('leftover', 'Недодел'), ('imported', 'Импортировано')], default='work', max_length=10, verbose_name='Статус'),
|
||||
),
|
||||
]
|
||||
@@ -1,6 +1,7 @@
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.models import User
|
||||
from warehouse.models import Material as WarehouseMaterial
|
||||
|
||||
class Company(models.Model):
|
||||
"""
|
||||
@@ -38,17 +39,6 @@ class Deal(models.Model):
|
||||
class Meta:
|
||||
verbose_name = "Сделка"; verbose_name_plural = "Сделки"
|
||||
|
||||
class Material(models.Model):
|
||||
"""
|
||||
Справочник ТМЦ (Трубы, листы, профили).
|
||||
Необходим для точного списания остатков и синхронизации с 1С.
|
||||
"""
|
||||
name = models.CharField("Наименование", max_length=255, unique=True)
|
||||
|
||||
def __str__(self): return self.name
|
||||
class Meta:
|
||||
verbose_name = "Материал"; verbose_name_plural = "Материалы"
|
||||
|
||||
class ProductionTask(models.Model):
|
||||
"""
|
||||
Основание для производства. Определяет ЧТО делать.
|
||||
@@ -62,7 +52,7 @@ class ProductionTask(models.Model):
|
||||
drawing_file = models.FileField("Исходник (DXF/IGES)", upload_to="drawings/%Y/%m/", blank=True, null=True)
|
||||
extra_drawing = models.FileField("Доп. чертеж (PDF)", upload_to="extra_drawings/%Y/%m/", blank=True, null=True)
|
||||
|
||||
material = models.ForeignKey(Material, on_delete=models.PROTECT, verbose_name="Материал")
|
||||
material = models.ForeignKey(WarehouseMaterial, on_delete=models.PROTECT, verbose_name="Материал")
|
||||
quantity_ordered = models.PositiveIntegerField("Заказано всего, шт")
|
||||
is_bend = models.BooleanField("Гибка", default=False)
|
||||
|
||||
@@ -84,6 +74,7 @@ class Item(models.Model):
|
||||
('done', 'Выполнено'),
|
||||
('partial', 'Частично'),
|
||||
('leftover', 'Недодел'),
|
||||
('imported', 'Импортировано'),
|
||||
]
|
||||
|
||||
# --- Ссылка на основу (временно null=True для миграции старых данных) ---
|
||||
@@ -106,11 +97,13 @@ class Item(models.Model):
|
||||
is_synced_1c = models.BooleanField("Учтено в 1С", default=False)
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Позиция сменки"; verbose_name_plural = "Реестр сменных заданий"
|
||||
verbose_name = "Пункт сменки"; verbose_name_plural = "Реестр сменных заданий"
|
||||
ordering = ['-date', 'task__deal']
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.task.drawing_name} - {self.date}"
|
||||
if self.task:
|
||||
return f"{self.task.drawing_name} - {self.date}"
|
||||
return f"Без задания - {self.date}"
|
||||
|
||||
|
||||
class EmployeeProfile(models.Model):
|
||||
|
||||
@@ -52,6 +52,21 @@
|
||||
<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 class="row g-3 mt-3 text-start">
|
||||
<div class="col-md-4">
|
||||
<label class="small text-muted">Взятый материал</label>
|
||||
<input type="text" name="material_taken" class="form-control border-secondary" value="{{ item.material_taken }}" placeholder="Напр: 3 трубы по 12м">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="small text-muted">Деловой отход</label>
|
||||
<input type="text" name="usable_waste" class="form-control border-secondary" value="{{ item.usable_waste }}" placeholder="Напр: кусок 1500мм">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="small text-muted">Лом (кг)</label>
|
||||
<input type="number" step="0.01" name="scrap_weight" class="form-control border-secondary" value="{{ item.scrap_weight }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-success">Статус: {{ item.get_status_display }}. Сделано: {{ item.quantity_fact }} шт.</div>
|
||||
@@ -120,7 +135,7 @@ function closeTask(status) {
|
||||
|
||||
function showPartial() {
|
||||
document.getElementById('partialInput').classList.remove('d-none');
|
||||
document.getElementById('id_status').value = 'part'; // Статус Частично
|
||||
document.getElementById('id_status').value = 'partial';
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -1,45 +1,81 @@
|
||||
<div class="card border-secondary mb-3 shadow-sm">
|
||||
<div class="card-body py-2">
|
||||
<form method="get" id="filter-form" class="row g-2 align-items-center">
|
||||
<input type="hidden" name="filtered" value="1"> <div class="col-md-4">
|
||||
<input type="hidden" name="filtered" value="1">
|
||||
|
||||
{% if user_role != 'operator' %}
|
||||
<div class="col-md-4">
|
||||
<div class="small text-muted mb-1 fw-bold">Станки:</div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
{% for m in machines %}
|
||||
<div>
|
||||
<input type="checkbox" class="btn-check" name="m_ids" id="m_{{ m.id }}" value="{{ m.id }}"
|
||||
{% if m.id in selected_machines %}checked{% endif %} onchange="this.form.submit()">
|
||||
{% if all_selected_machines or m.id in selected_machines %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-accent btn-sm" for="m_{{ m.id }}">{{ m.name }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="small text-muted mb-1 fw-bold">Статус:</div>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_work" value="work" {% if 'work' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-primary btn-sm" for="s_work">В работе</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_partial" value="partial" {% if 'partial' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-danger btn-sm" for="s_partial">Недодел</label>
|
||||
{% if user_role == 'operator' %}
|
||||
<input type="hidden" name="statuses" value="work">
|
||||
<span class="badge bg-primary">В работе</span>
|
||||
{% else %}
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_work" value="work" {% if 'work' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-primary btn-sm" for="s_work">В работе</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_leftover" value="leftover" {% if 'leftover' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-danger btn-sm" for="s_leftover">Недодел</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_done" value="done" {% if 'done' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-success btn-sm" for="s_done">Завершено</label>
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_closed" value="closed" {% if 'closed' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-success btn-sm" for="s_closed">Завершено</label>
|
||||
|
||||
{% if user_role in 'admin,technologist' %}
|
||||
<input type="checkbox" class="btn-check" name="statuses" id="s_imported" value="imported" {% if 'imported' in selected_statuses %}checked{% endif %} onchange="this.form.submit()">
|
||||
<label class="btn btn-outline-accent btn-sm" for="s_imported">Импорт</label>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if user_role in 'admin,technologist,clerk' %}
|
||||
<div class="col-md-2">
|
||||
<label class="small text-muted mb-1 fw-bold">Учёт 1С:</label>
|
||||
<select name="is_synced" class="form-select form-select-sm bg-body text-body border-secondary" onchange="this.form.submit()">
|
||||
<option value="" {% if not is_synced %}selected{% endif %}>Все</option>
|
||||
<option value="1" {% if is_synced == '1' %}selected{% endif %}>Учтено</option>
|
||||
<option value="0" {% if is_synced == '0' %}selected{% endif %}>Ожидает</option>
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="col-md-2">
|
||||
<label class="small text-muted mb-1 fw-bold">С:</label>
|
||||
<input type="date" name="start_date" class="form-control form-control-sm" value="{{ start_date }}" onchange="this.form.submit()">
|
||||
<input type="date" name="start_date" class="form-control form-control-sm bg-body text-body border-secondary" value="{{ start_date }}" onchange="this.form.submit()">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="small text-muted mb-1 fw-bold">По:</label>
|
||||
<input type="date" name="end_date" class="form-control form-control-sm" value="{{ end_date }}" onchange="this.form.submit()">
|
||||
<input type="date" name="end_date" class="form-control form-control-sm bg-body text-body border-secondary" value="{{ end_date }}" onchange="this.form.submit()">
|
||||
</div>
|
||||
|
||||
<div class="col-md-1 text-end mt-auto">
|
||||
<a href="{% url 'registry' %}" class="btn btn-outline-secondary btn-sm w-100" title="Сбросить по умолчанию"><i class="bi bi-x-circle"></i></a>
|
||||
<a href="{% url 'registry' %}" class="btn btn-outline-secondary btn-sm w-100" title="Сброс">
|
||||
<i class="bi bi-arrow-counterclockwise me-1"></i>Сброс
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function(){
|
||||
const s = document.querySelector('input[name="start_date"]');
|
||||
const e = document.querySelector('input[name="end_date"]');
|
||||
const today = new Date().toISOString().slice(0,10);
|
||||
if (s && !s.value) s.value = today;
|
||||
if (e && !e.value) e.value = today;
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +1,8 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'shiftflow/partials/_filter.html' %}
|
||||
|
||||
<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>
|
||||
@@ -27,23 +29,23 @@
|
||||
{% 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="text-accent fw-bold">{{ item.task.deal.number|default:"-" }}</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 class="fw-bold">{{ item.task.drawing_name|default:"Б/ч" }}</td>
|
||||
<td class="small">{{ item.task.size_value|default:"-" }}</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="small text-muted">{{ item.task.material.full_name|default:item.task.material.name|default:"-" }}</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">
|
||||
{% if item.task.drawing_file %}
|
||||
<a href="{{ item.task.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">
|
||||
{% if item.task.extra_drawing %}
|
||||
<a href="{{ item.task.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 %}
|
||||
|
||||
@@ -2,7 +2,8 @@ from django.shortcuts import redirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import TemplateView, ListView, UpdateView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from .models import Item # Проверь, как точно называется твоя модель деталей/заказов
|
||||
from django.utils import timezone
|
||||
from .models import Item, Machine
|
||||
|
||||
# Класс главной страницы (роутер)
|
||||
class IndexView(TemplateView):
|
||||
@@ -22,22 +23,84 @@ class RegistryView(LoginRequiredMixin, ListView):
|
||||
context_object_name = 'items'
|
||||
|
||||
def get_queryset(self):
|
||||
# Оптимизируем запросы, подгружая связанные данные сразу
|
||||
queryset = Item.objects.select_related('task', 'task__deal', 'task__material', 'machine').all()
|
||||
|
||||
# Если это оператор, показываем только задания для его станков
|
||||
if hasattr(self.request.user, 'profile') and self.request.user.profile.role == 'operator':
|
||||
user_machines = self.request.user.profile.machines.all()
|
||||
if user_machines.exists():
|
||||
queryset = queryset.filter(machine__in=user_machines)
|
||||
|
||||
queryset = Item.objects.select_related('task', 'task__deal', 'task__material', 'machine')
|
||||
user = self.request.user
|
||||
profile = getattr(user, 'profile', None)
|
||||
role = profile.role if profile else 'operator'
|
||||
filtered = self.request.GET.get('filtered')
|
||||
|
||||
# Станки
|
||||
m_ids = self.request.GET.getlist('m_ids')
|
||||
if filtered and role != 'operator' and not m_ids:
|
||||
return queryset.none()
|
||||
if m_ids:
|
||||
queryset = queryset.filter(machine_id__in=m_ids)
|
||||
|
||||
# Статусы (+ агрегат "closed" = done+partial)
|
||||
statuses = self.request.GET.getlist('statuses')
|
||||
if filtered and not statuses:
|
||||
return queryset.none()
|
||||
if statuses:
|
||||
expanded = []
|
||||
for s in statuses:
|
||||
if s == 'closed':
|
||||
expanded += ['done', 'partial']
|
||||
else:
|
||||
expanded.append(s)
|
||||
queryset = queryset.filter(status__in=expanded)
|
||||
|
||||
# Даты
|
||||
start_date = self.request.GET.get('start_date')
|
||||
end_date = self.request.GET.get('end_date')
|
||||
if not filtered:
|
||||
today = timezone.now().date()
|
||||
queryset = queryset.filter(date=today, status__in=['work', 'leftover'])
|
||||
else:
|
||||
if start_date:
|
||||
queryset = queryset.filter(date__gte=start_date)
|
||||
if end_date:
|
||||
queryset = queryset.filter(date__lte=end_date)
|
||||
|
||||
# Списание (1С)
|
||||
is_synced = self.request.GET.get('is_synced')
|
||||
if is_synced in ['0', '1']:
|
||||
queryset = queryset.filter(is_synced_1c=bool(int(is_synced)))
|
||||
|
||||
# Ограничения по ролям
|
||||
if role == 'operator':
|
||||
user_machines = profile.machines.all() if profile else Machine.objects.none()
|
||||
queryset = queryset.filter(machine__in=user_machines, status='work')
|
||||
elif role == 'master' and not filtered:
|
||||
queryset = queryset.filter(status='work')
|
||||
|
||||
return queryset.order_by('status', '-date', 'machine__name', 'task__deal__number')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
# Передаем роль в шаблон, чтобы скрывать/показывать кнопки
|
||||
if hasattr(self.request.user, 'profile'):
|
||||
context['user_role'] = self.request.user.profile.role
|
||||
user = self.request.user
|
||||
profile = getattr(user, 'profile', None)
|
||||
role = profile.role if profile else 'operator'
|
||||
context['user_role'] = role
|
||||
|
||||
machines = Machine.objects.all()
|
||||
context['machines'] = machines
|
||||
filtered = self.request.GET.get('filtered')
|
||||
|
||||
if not filtered:
|
||||
today_str = timezone.now().date().strftime('%Y-%m-%d')
|
||||
context['start_date'] = today_str
|
||||
context['end_date'] = today_str
|
||||
context['selected_statuses'] = ['work', 'leftover']
|
||||
context['selected_machines'] = [m.id for m in machines]
|
||||
context['all_selected_machines'] = True
|
||||
else:
|
||||
context['selected_machines'] = [int(i) for i in self.request.GET.getlist('m_ids') if i.isdigit()]
|
||||
context['selected_statuses'] = self.request.GET.getlist('statuses')
|
||||
context['start_date'] = self.request.GET.get('start_date', '')
|
||||
context['end_date'] = self.request.GET.get('end_date', '')
|
||||
context['is_synced'] = self.request.GET.get('is_synced', '')
|
||||
context['all_selected_machines'] = False
|
||||
|
||||
return context
|
||||
|
||||
# Вьюха детального вида и редактирования
|
||||
@@ -59,6 +122,54 @@ class ItemUpdateView(LoginRequiredMixin, UpdateView):
|
||||
context['user_role'] = self.request.user.profile.role
|
||||
return context
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
profile = getattr(request.user, 'profile', None)
|
||||
role = profile.role if profile else 'operator'
|
||||
|
||||
# Общие поля
|
||||
self.object.material_taken = request.POST.get('material_taken', self.object.material_taken)
|
||||
self.object.usable_waste = request.POST.get('usable_waste', self.object.usable_waste)
|
||||
self.object.scrap_weight = request.POST.get('scrap_weight', self.object.scrap_weight or 0)
|
||||
|
||||
status = request.POST.get('status', self.object.status)
|
||||
|
||||
if role in ['operator', 'master']:
|
||||
if status == 'done':
|
||||
self.object.quantity_fact = self.object.quantity_plan
|
||||
self.object.status = 'done'
|
||||
self.object.save()
|
||||
elif status == 'partial':
|
||||
try:
|
||||
fact = int(request.POST.get('quantity_fact', '0'))
|
||||
except ValueError:
|
||||
fact = 0
|
||||
fact = max(0, min(fact, self.object.quantity_plan))
|
||||
residual = self.object.quantity_plan - fact
|
||||
self.object.quantity_fact = fact
|
||||
self.object.status = 'partial'
|
||||
self.object.save()
|
||||
if residual > 0:
|
||||
Item.objects.create(
|
||||
task=self.object.task,
|
||||
date=self.object.date,
|
||||
machine=self.object.machine,
|
||||
quantity_plan=residual,
|
||||
quantity_fact=0,
|
||||
status='leftover',
|
||||
is_synced_1c=False,
|
||||
)
|
||||
else:
|
||||
# Просто сохранить без спец-логики
|
||||
return super().post(request, *args, **kwargs)
|
||||
elif role == 'clerk':
|
||||
# Учетчик может отмечать списание 1С
|
||||
self.object.is_synced_1c = bool(request.POST.get('is_synced_1c'))
|
||||
self.object.save()
|
||||
else:
|
||||
return super().post(request, *args, **kwargs)
|
||||
|
||||
return redirect('registry')
|
||||
|
||||
def get_success_url(self):
|
||||
# После сохранения возвращаемся в реестр
|
||||
return reverse_lazy('registry')
|
||||
Reference in New Issue
Block a user