Открыл админу изделия, доработал списание
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:
@@ -755,6 +755,26 @@ class MaintenanceStatusView(LoginRequiredMixin, View):
|
||||
class MaintenanceView(LoginRequiredMixin, TemplateView):
|
||||
template_name = 'shiftflow/maintenance.html'
|
||||
|
||||
def _server_log_path(self):
|
||||
p = (django_settings.BASE_DIR / 'logs' / 'mes.log')
|
||||
return p
|
||||
|
||||
def _read_tail(self, path, max_bytes: int = 20000) -> str:
|
||||
try:
|
||||
if not path.exists():
|
||||
return ''
|
||||
size = path.stat().st_size
|
||||
start = max(0, size - max_bytes)
|
||||
with path.open('rb') as f:
|
||||
f.seek(start)
|
||||
data = f.read()
|
||||
try:
|
||||
return data.decode('utf-8', errors='replace')
|
||||
except Exception:
|
||||
return str(data)
|
||||
except Exception:
|
||||
return ''
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
profile = getattr(request.user, 'profile', None)
|
||||
role = profile.role if profile else ('admin' if request.user.is_superuser else 'operator')
|
||||
@@ -767,6 +787,10 @@ class MaintenanceView(LoginRequiredMixin, TemplateView):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['user_role'] = 'admin'
|
||||
|
||||
log_path = self._server_log_path()
|
||||
context['log_path'] = str(log_path)
|
||||
context['log_tail'] = self._read_tail(log_path)
|
||||
|
||||
# Подтягиваем текущие настройки генерации превью, чтобы отрисовать форму.
|
||||
s = _get_dxf_preview_settings()
|
||||
context['dxf_settings'] = s
|
||||
@@ -817,9 +841,18 @@ class MaintenanceView(LoginRequiredMixin, TemplateView):
|
||||
messages.success(request, 'Остановка запрошена.')
|
||||
return redirect('maintenance')
|
||||
|
||||
if action == 'refresh_log':
|
||||
return redirect('maintenance')
|
||||
|
||||
if action == 'clear_log':
|
||||
# Очистка лог-файла последней задачи. Во время выполнения не трогаем,
|
||||
# потому что процесс может держать открытый дескриптор файла.
|
||||
try:
|
||||
self._server_log_path().open('wb').close()
|
||||
messages.success(request, 'Лог очищен.')
|
||||
except Exception:
|
||||
messages.error(request, 'Не удалось очистить лог.')
|
||||
return redirect('maintenance')
|
||||
|
||||
if action == 'clear_dxf_job_log':
|
||||
job = DxfPreviewJob.objects.order_by('-id').first()
|
||||
if not job:
|
||||
messages.info(request, 'Логов нет.')
|
||||
@@ -831,9 +864,9 @@ class MaintenanceView(LoginRequiredMixin, TemplateView):
|
||||
|
||||
try:
|
||||
_dxf_job_log_path(job.id).open('wb').close()
|
||||
messages.success(request, 'Лог очищен.')
|
||||
messages.success(request, 'Лог DXF-генерации очищен.')
|
||||
except Exception:
|
||||
messages.error(request, 'Не удалось очистить лог.')
|
||||
messages.error(request, 'Не удалось очистить лог DXF-генерации.')
|
||||
return redirect('maintenance')
|
||||
|
||||
if action != 'update_previews':
|
||||
@@ -1177,6 +1210,7 @@ class MaterialCategoryUpsertView(LoginRequiredMixin, View):
|
||||
category_id = request.POST.get('id')
|
||||
name = (request.POST.get('name') or '').strip()
|
||||
gost_standard = (request.POST.get('gost_standard') or '').strip()
|
||||
form_factor = (request.POST.get('form_factor') or '').strip() or 'other'
|
||||
|
||||
if not name:
|
||||
return JsonResponse({'error': 'name_required'}, status=400)
|
||||
@@ -1188,6 +1222,8 @@ class MaterialCategoryUpsertView(LoginRequiredMixin, View):
|
||||
category, _ = MaterialCategory.objects.get_or_create(name=name)
|
||||
|
||||
category.gost_standard = gost_standard
|
||||
if form_factor in ['sheet', 'bar', 'other']:
|
||||
category.form_factor = form_factor
|
||||
category.save()
|
||||
return JsonResponse({'id': category.id, 'label': category.name})
|
||||
|
||||
@@ -1809,6 +1845,25 @@ class ClosingView(LoginRequiredMixin, TemplateView):
|
||||
messages.error(request, 'Выбери хотя бы один пункт сменки и режим закрытия (полностью/частично).')
|
||||
return redirect(f"{reverse_lazy('closing')}?machine_id={machine_id}&material_id={material_id}")
|
||||
|
||||
if not consumptions:
|
||||
messages.error(request, 'Заполни списание: укажи, какие единицы на складе использованы и в каком количестве.')
|
||||
return redirect(f"{reverse_lazy('closing')}?machine_id={machine_id}&material_id={material_id}")
|
||||
|
||||
try:
|
||||
apply_closing(
|
||||
user_id=request.user.id,
|
||||
machine_id=int(machine_id),
|
||||
material_id=int(material_id),
|
||||
item_actions=item_actions,
|
||||
consumptions=consumptions,
|
||||
remnants=remnants,
|
||||
)
|
||||
messages.success(request, 'Закрытие выполнено.')
|
||||
except Exception as e:
|
||||
messages.error(request, f'Ошибка закрытия: {e}')
|
||||
|
||||
return redirect(f"{reverse_lazy('closing')}?machine_id={machine_id}&material_id={material_id}")
|
||||
|
||||
|
||||
class ProductsView(LoginRequiredMixin, TemplateView):
|
||||
template_name = 'shiftflow/products.html'
|
||||
|
||||
Reference in New Issue
Block a user