Implemented complete web interface for managing showcases (display areas for ready-made bouquets) with: **Backend:** - ShowcaseForm with validation (unique name per warehouse) - ShowcaseListView with filtering by warehouse and status - ShowcaseCreateView, ShowcaseUpdateView with success messages - ShowcaseDeleteView with active reservation validation - URL routes: list, create, edit, delete **Frontend:** - List page with warehouse grouping, active reservations count - Responsive table with filters (warehouse, status) - Create/edit form with Bootstrap styling - Delete confirmation with active reservations check - Breadcrumb navigation **Features:** ✅ One warehouse can have multiple showcases (ForeignKey relationship) ✅ Unique showcase names within each warehouse ✅ Display active reservation counts for each showcase ✅ Prevent deletion if showcase has active reservations ✅ Auto-select default warehouse when creating showcase ✅ Navigation link added to main navbar between "Касса" and "Склад" ✅ Active state highlighting in navigation **Files created:** - inventory/forms_showcase.py (ShowcaseForm) - inventory/views/showcase.py (4 CBV views) - inventory/templates/inventory/showcase/ (list, form, delete templates) **Files modified:** - inventory/urls.py (added showcase routes) - inventory/forms.py (added Showcase import) - templates/navbar.html (added "Витрины" link) URL structure: /inventory/showcases/ - list /inventory/showcases/create/ - create /inventory/showcases/<id>/edit/ - edit /inventory/showcases/<id>/delete/ - delete 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
136 lines
5.4 KiB
HTML
136 lines
5.4 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}{{ title }}{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="container-fluid">
|
||
<!-- Header -->
|
||
<div class="row mb-4">
|
||
<div class="col-12">
|
||
<h1 class="mb-2 text-danger">
|
||
<i class="bi bi-exclamation-triangle me-2"></i>Удаление витрины
|
||
</h1>
|
||
<nav aria-label="breadcrumb">
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="{% url 'inventory:inventory-home' %}">Склад</a></li>
|
||
<li class="breadcrumb-item"><a href="{% url 'inventory:showcase-list' %}">Витрины</a></li>
|
||
<li class="breadcrumb-item active">Удаление</li>
|
||
</ol>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Delete Confirmation -->
|
||
<div class="row">
|
||
<div class="col-lg-8">
|
||
<div class="card border-danger">
|
||
<div class="card-header bg-danger text-white">
|
||
<h5 class="mb-0">
|
||
<i class="bi bi-exclamation-triangle me-2"></i>Подтверждение удаления
|
||
</h5>
|
||
</div>
|
||
<div class="card-body">
|
||
<p class="lead">
|
||
Вы действительно хотите удалить витрину <strong>"{{ object.name }}"</strong>
|
||
на складе <strong>"{{ object.warehouse.name }}"</strong>?
|
||
</p>
|
||
|
||
{% if has_active_reservations %}
|
||
<div class="alert alert-danger">
|
||
<h6 class="alert-heading">
|
||
<i class="bi bi-x-circle me-2"></i>Невозможно удалить витрину
|
||
</h6>
|
||
<p class="mb-2">
|
||
На этой витрине есть <strong>{{ active_reservations.count }}</strong> активных резервов.
|
||
Сначала необходимо освободить или продать зарезервированные товары.
|
||
</p>
|
||
|
||
{% if active_reservations %}
|
||
<hr>
|
||
<p class="mb-2"><strong>Активные резервы:</strong></p>
|
||
<ul class="mb-0">
|
||
{% for reservation in active_reservations|slice:":5" %}
|
||
<li>{{ reservation.product.name }} — {{ reservation.quantity }} шт.</li>
|
||
{% endfor %}
|
||
{% if active_reservations.count > 5 %}
|
||
<li class="text-muted">...и еще {{ active_reservations.count|add:"-5" }} резервов</li>
|
||
{% endif %}
|
||
</ul>
|
||
{% endif %}
|
||
</div>
|
||
|
||
<div class="d-flex gap-2">
|
||
<a href="{% url 'inventory:showcase-list' %}" class="btn btn-secondary">
|
||
<i class="bi bi-arrow-left me-1"></i>Вернуться к списку
|
||
</a>
|
||
<a href="{% url 'inventory:reservation-list' %}?showcase={{ object.id }}" class="btn btn-info">
|
||
<i class="bi bi-eye me-1"></i>Просмотреть резервы
|
||
</a>
|
||
</div>
|
||
{% else %}
|
||
<div class="alert alert-warning">
|
||
<i class="bi bi-info-circle me-2"></i>
|
||
<strong>Внимание:</strong> Это действие нельзя отменить. Все данные о витрине будут удалены безвозвратно.
|
||
</div>
|
||
|
||
<form method="post">
|
||
{% csrf_token %}
|
||
<div class="d-flex gap-2">
|
||
<button type="submit" class="btn btn-danger">
|
||
<i class="bi bi-trash me-1"></i>Да, удалить витрину
|
||
</button>
|
||
<a href="{% url 'inventory:showcase-list' %}" class="btn btn-secondary">
|
||
<i class="bi bi-x-circle me-1"></i>Отмена
|
||
</a>
|
||
</div>
|
||
</form>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Info Card -->
|
||
<div class="col-lg-4">
|
||
<div class="card">
|
||
<div class="card-header bg-light">
|
||
<h6 class="mb-0">Информация о витрине</h6>
|
||
</div>
|
||
<div class="card-body">
|
||
<dl class="row mb-0">
|
||
<dt class="col-sm-6">Название:</dt>
|
||
<dd class="col-sm-6 text-end">{{ object.name }}</dd>
|
||
|
||
<dt class="col-sm-6">Склад:</dt>
|
||
<dd class="col-sm-6 text-end">{{ object.warehouse.name }}</dd>
|
||
|
||
<dt class="col-sm-6">Статус:</dt>
|
||
<dd class="col-sm-6 text-end">
|
||
{% if object.is_active %}
|
||
<span class="badge bg-success">Активна</span>
|
||
{% else %}
|
||
<span class="badge bg-secondary">Неактивна</span>
|
||
{% endif %}
|
||
</dd>
|
||
|
||
<dt class="col-sm-6">Создана:</dt>
|
||
<dd class="col-sm-6 text-end">{{ object.created_at|date:"d.m.Y H:i" }}</dd>
|
||
|
||
<dt class="col-sm-6">Обновлена:</dt>
|
||
<dd class="col-sm-6 text-end">{{ object.updated_at|date:"d.m.Y H:i" }}</dd>
|
||
|
||
<dt class="col-sm-6">Активные резервы:</dt>
|
||
<dd class="col-sm-6 text-end">
|
||
{% if has_active_reservations %}
|
||
<span class="badge bg-danger">{{ active_reservations.count }}</span>
|
||
{% else %}
|
||
<span class="text-muted">—</span>
|
||
{% endif %}
|
||
</dd>
|
||
</dl>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|