Fix: Auto-cleanup temp files after photo processing

- Added temp file deletion in Celery task after successful processing
- Added temp file cleanup in sync fallback method
- Added temp file removal in delete() if processing never completed
- Prevents accumulation of orphaned files in media/<entity>/temp/ folders
This commit is contained in:
2025-11-15 22:28:41 +03:00
parent 53fbb6d3c1
commit 9363527e50
9 changed files with 275 additions and 18 deletions

View File

@@ -72,10 +72,14 @@
{% endif %}
</td>
<td>
{% if product.is_active %}
<span class="badge bg-info">Активен</span>
{% if product.status == 'active' %}
<span class="badge bg-success">Активный</span>
{% elif product.status == 'archived' %}
<span class="badge bg-warning text-dark">Архивный</span>
{% elif product.status == 'discontinued' %}
<span class="badge bg-danger">Снят</span>
{% else %}
<span class="badge bg-secondary">Неактивен</span>
<span class="badge bg-secondary">{{ product.status }}</span>
{% endif %}
</td>
<td>

View File

@@ -69,10 +69,14 @@
{% endif %}
</td>
<td>
{% if kit.is_active %}
<span class="badge bg-info">Активен</span>
{% if kit.status == 'active' %}
<span class="badge bg-success">Активный</span>
{% elif kit.status == 'archived' %}
<span class="badge bg-warning text-dark">Архивный</span>
{% elif kit.status == 'discontinued' %}
<span class="badge bg-danger">Снят</span>
{% else %}
<span class="badge bg-secondary">Неактивен</span>
<span class="badge bg-secondary">{{ kit.status }}</span>
{% endif %}
</td>
<td>

View File

@@ -0,0 +1,189 @@
{% extends 'base.html' %}
{% load quality_tags %}
{% block title %}Список товаров и комплектов{% endblock %}
{% block content %}
<div class="container-fluid mt-4">
<h2 class="mb-4">Товары и Комплекты</h2>
<!-- Панель фильтрации и действий -->
<div class="card shadow-sm mb-4">
<div class="card-body">
<div class="d-flex justify-content-between align-items-center mb-3 flex-wrap">
<h5 class="card-title mb-0 me-3">
<i class="bi bi-funnel-fill"></i> Фильтры
</h5>
<div class="btn-toolbar" role="toolbar">
{% if perms.products.add_product %}
<a href="{% url 'products:product-create' %}" class="btn btn-primary btn-sm me-2 mb-2 mb-md-0">
<i class="bi bi-plus-circle"></i> Создать товар
</a>
{% endif %}
{% if perms.products.add_productkit %}
<a href="{% url 'products:productkit-create' %}" class="btn btn-outline-primary btn-sm mb-2 mb-md-0">
<i class="bi bi-box-seam"></i> Создать комплект
</a>
{% endif %}
</div>
</div>
<hr class="my-3">
<form method="get" id="filterForm">
<div class="row g-3">
<!-- Поиск -->
<div class="col-12 col-md-4">
<label for="search" class="form-label"><i class="bi bi-search"></i> Поиск</label>
<input type="text" class="form-control" id="search" name="search" placeholder="Название, артикул, описание..." value="{{ filters.current.search|default:'' }}">
</div>
<!-- Тип -->
<div class="col-12 col-md-2">
<label for="type" class="form-label"><i class="bi bi-box-seam"></i> Тип</label>
<select class="form-select" id="type" name="type">
<option value="all" {% if filters.current.type == 'all' %}selected{% endif %}>Все</option>
<option value="products" {% if filters.current.type == 'products' %}selected{% endif %}>Только товары</option>
<option value="kits" {% if filters.current.type == 'kits' %}selected{% endif %}>Только комплекты</option>
</select>
</div>
<!-- Категория -->
<div class="col-12 col-md-3">
<label for="category" class="form-label"><i class="bi bi-bookmark"></i> Категория</label>
<select class="form-select" id="category" name="category">
<option value="">Все категории</option>
{% for category in filters.categories %}
<option value="{{ category.id }}" {% if filters.current.category == category.id|stringformat:"s" %}selected{% endif %}>{{ category.name }}</option>
{% endfor %}
</select>
</div>
<!-- Статус -->
<div class="col-12 col-md-3">
<label for="status" class="form-label"><i class="bi bi-toggle-on"></i> Статус</label>
<select class="form-select" id="status" name="status">
<option value="">Все статусы</option>
{% for status_value, status_name in item_statuses %}
<option value="{{ status_value }}" {% if filters.current.status == status_value %}selected{% endif %}>{{ status_name }}</option>
{% endfor %}
</select>
</div>
</div>
<div class="row g-3 mt-2">
<div class="col-12">
<button type="submit" class="btn btn-primary"><i class="bi bi-check-circle"></i> Применить</button>
<a href="{% url 'products:product-list' %}" class="btn btn-outline-secondary"><i class="bi bi-x-circle"></i> Сброс</a>
</div>
</div>
</form>
</div>
</div>
{% if items %}
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th>Фото</th>
<th>Название</th>
<th>Артикул</th>
<th>Тип</th>
<th>Категория</th>
<th>Цена</th>
<th>В наличии</th>
<th>Компоненты</th>
<th>Статус</th>
<th>Действия</th>
</tr>
</thead>
<tbody>
{% for item in items %}
<tr>
<td>
{% with photo=item.photos.first %}
<div class="photo-list-item">
<img src="{{ photo.get_thumbnail_url }}" alt="{{ item.name }}" class="img-thumbnail rounded">
{% if item.item_type == 'product' and photo %}
<span class="quality-icon" title="{{ photo.get_quality_level_display }}">{{ photo|quality_icon_only }}</span>
{% endif %}
</div>
{% endwith %}
</td>
<td>
<a href="{{ item.get_absolute_url }}">{{ item.name }}</a>
</td>
<td>{{ item.sku }}</td>
<td>
{% if item.item_type == 'product' %}
<span class="badge bg-success" title="Товар"><i class="bi bi-box"></i> Товар</span>
{% else %}
<span class="badge bg-info" title="Комплект"><i class="bi bi-box-seam"></i> Комплект</span>
{% endif %}
</td>
<td>
{% for category in item.categories.all %}
<span class="badge bg-secondary">{{ category.name }}</span>
{% empty %}
-
{% endfor %}
</td>
<td>
{% if item.sale_price %}
<span class="text-decoration-line-through text-muted small">{{ item.price|floatformat:2 }} руб.</span><br>
<strong class="text-danger">{{ item.sale_price|floatformat:2 }} руб.</strong>
{% else %}
<strong>{{ item.price|floatformat:2 }} руб.</strong>
{% endif %}
</td>
<td>
{% if item.item_type == 'product' %}
{% if item.in_stock %}
<span class="badge bg-success"><i class="bi bi-check-circle"></i> Да</span>
{% else %}
<span class="badge bg-danger"><i class="bi bi-x-circle"></i> Нет</span>
{% endif %}
{% else %}
-
{% endif %}
</td>
<td>
{% if item.item_type == 'kit' %}
<span class="badge bg-secondary">{{ item.get_total_components_count }} шт</span>
{% else %}
-
{% endif %}
</td>
<td>
<span class="badge" style="background-color: {{ item.get_status_color }}">{{ item.get_status_display }}</span>
</td>
<td>
<div class="btn-group btn-group-sm">
<a href="{{ item.get_absolute_url }}" class="btn btn-outline-info" title="Просмотр"><i class="bi bi-eye"></i></a>
{% if item.item_type == 'product' and perms.products.change_product %}
<a href="{% url 'products:product-update' item.pk %}" class="btn btn-outline-primary" title="Изменить"><i class="bi bi-pencil"></i></a>
{% elif item.item_type == 'kit' and perms.products.change_productkit %}
<a href="{% url 'products:productkit-update' item.pk %}" class="btn btn-outline-primary" title="Изменить"><i class="bi bi-pencil"></i></a>
{% endif %}
{% if item.item_type == 'product' and perms.products.delete_product %}
<a href="{% url 'products:product-delete' item.pk %}" class="btn btn-outline-danger" title="Удалить"><i class="bi bi-trash"></i></a>
{% elif item.item_type == 'kit' and perms.products.delete_productkit %}
<a href="{% url 'products:productkit-delete' item.pk %}" class="btn btn-outline-danger" title="Удалить"><i class="bi bi-trash"></i></a>
{% endif %}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include 'components/pagination.html' %}
{% else %}
<div class="alert alert-info">
<p>Товары или комплекты не найдены.</p>
</div>
{% endif %}
</div>
{% endblock %}