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>
107 lines
5.9 KiB
Python
107 lines
5.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
from django.urls import path
|
|
from .views import (
|
|
# Warehouse
|
|
WarehouseListView, WarehouseCreateView, WarehouseUpdateView, WarehouseDeleteView, SetDefaultWarehouseView,
|
|
# Incoming
|
|
IncomingListView, IncomingCreateView, IncomingUpdateView, IncomingDeleteView,
|
|
# IncomingBatch
|
|
IncomingBatchListView, IncomingBatchDetailView,
|
|
# Sale
|
|
SaleListView, SaleCreateView, SaleUpdateView, SaleDeleteView, SaleDetailView,
|
|
# Inventory
|
|
InventoryListView, InventoryCreateView, InventoryDetailView, InventoryLineCreateBulkView,
|
|
# WriteOff
|
|
WriteOffListView, WriteOffCreateView, WriteOffUpdateView, WriteOffDeleteView,
|
|
# Transfer
|
|
TransferListView, TransferBulkCreateView, TransferDetailView, TransferDeleteView, GetProductStockView,
|
|
# Reservation
|
|
ReservationListView, ReservationCreateView, ReservationUpdateView,
|
|
# Stock
|
|
StockListView, StockDetailView,
|
|
# StockBatch
|
|
StockBatchListView, StockBatchDetailView,
|
|
# SaleBatchAllocation
|
|
SaleBatchAllocationListView,
|
|
# StockMovement
|
|
StockMovementListView,
|
|
)
|
|
# Showcase views
|
|
from .views.showcase import ShowcaseListView, ShowcaseCreateView, ShowcaseUpdateView, ShowcaseDeleteView
|
|
from . import views
|
|
|
|
app_name = 'inventory'
|
|
|
|
urlpatterns = [
|
|
# Главная страница складского модуля
|
|
path('', views.inventory_home, name='inventory-home'),
|
|
|
|
# ==================== WAREHOUSE ====================
|
|
path('warehouses/', WarehouseListView.as_view(), name='warehouse-list'),
|
|
path('warehouses/create/', WarehouseCreateView.as_view(), name='warehouse-create'),
|
|
path('warehouses/<int:pk>/edit/', WarehouseUpdateView.as_view(), name='warehouse-update'),
|
|
path('warehouses/<int:pk>/delete/', WarehouseDeleteView.as_view(), name='warehouse-delete'),
|
|
path('warehouses/<int:pk>/set-default/', SetDefaultWarehouseView.as_view(), name='warehouse-set-default'),
|
|
|
|
# ==================== INCOMING ====================
|
|
path('incoming/', IncomingListView.as_view(), name='incoming-list'),
|
|
path('incoming/create/', IncomingCreateView.as_view(), name='incoming-create'),
|
|
path('incoming/<int:pk>/edit/', IncomingUpdateView.as_view(), name='incoming-update'),
|
|
path('incoming/<int:pk>/delete/', IncomingDeleteView.as_view(), name='incoming-delete'),
|
|
|
|
# ==================== INCOMING BATCH ====================
|
|
path('incoming-batches/', IncomingBatchListView.as_view(), name='incoming-batch-list'),
|
|
path('incoming-batches/<int:pk>/', IncomingBatchDetailView.as_view(), name='incoming-batch-detail'),
|
|
|
|
# ==================== SALE ====================
|
|
path('sales/', SaleListView.as_view(), name='sale-list'),
|
|
path('sales/create/', SaleCreateView.as_view(), name='sale-create'),
|
|
path('sales/<int:pk>/', SaleDetailView.as_view(), name='sale-detail'),
|
|
path('sales/<int:pk>/edit/', SaleUpdateView.as_view(), name='sale-update'),
|
|
path('sales/<int:pk>/delete/', SaleDeleteView.as_view(), name='sale-delete'),
|
|
|
|
# ==================== INVENTORY ====================
|
|
path('inventory-ops/', InventoryListView.as_view(), name='inventory-list'),
|
|
path('inventory-ops/create/', InventoryCreateView.as_view(), name='inventory-create'),
|
|
path('inventory-ops/<int:pk>/', InventoryDetailView.as_view(), name='inventory-detail'),
|
|
path('inventory-ops/<int:pk>/lines/add/', InventoryLineCreateBulkView.as_view(), name='inventory-lines-add'),
|
|
|
|
# ==================== WRITEOFF ====================
|
|
path('writeoffs/', WriteOffListView.as_view(), name='writeoff-list'),
|
|
path('writeoffs/create/', WriteOffCreateView.as_view(), name='writeoff-create'),
|
|
path('writeoffs/<int:pk>/edit/', WriteOffUpdateView.as_view(), name='writeoff-update'),
|
|
path('writeoffs/<int:pk>/delete/', WriteOffDeleteView.as_view(), name='writeoff-delete'),
|
|
|
|
# ==================== TRANSFER ====================
|
|
path('transfers/', TransferListView.as_view(), name='transfer-list'),
|
|
path('transfers/create/', TransferBulkCreateView.as_view(), name='transfer-create'), # Новая форма массового перемещения
|
|
path('transfers/<int:pk>/', TransferDetailView.as_view(), name='transfer-detail'), # Деталь документа
|
|
path('transfers/<int:pk>/delete/', TransferDeleteView.as_view(), name='transfer-delete'),
|
|
path('api/product-stock/', GetProductStockView.as_view(), name='api-product-stock'), # API для получения количества товара
|
|
|
|
# ==================== RESERVATION ====================
|
|
path('reservations/', ReservationListView.as_view(), name='reservation-list'),
|
|
path('reservations/create/', ReservationCreateView.as_view(), name='reservation-create'),
|
|
path('reservations/<int:pk>/update-status/', ReservationUpdateView.as_view(), name='reservation-update'),
|
|
|
|
# ==================== STOCK (READ ONLY) ====================
|
|
path('stock/', StockListView.as_view(), name='stock-list'),
|
|
path('stock/<int:pk>/', StockDetailView.as_view(), name='stock-detail'),
|
|
|
|
# ==================== BATCH (READ ONLY) ====================
|
|
path('batches/', StockBatchListView.as_view(), name='batch-list'),
|
|
path('batches/<int:pk>/', StockBatchDetailView.as_view(), name='batch-detail'),
|
|
|
|
# ==================== ALLOCATION (READ ONLY) ====================
|
|
path('allocations/', SaleBatchAllocationListView.as_view(), name='allocation-list'),
|
|
|
|
# ==================== MOVEMENT (READ ONLY) ====================
|
|
path('movements/', StockMovementListView.as_view(), name='movement-list'),
|
|
|
|
# ==================== SHOWCASE ====================
|
|
path('showcases/', ShowcaseListView.as_view(), name='showcase-list'),
|
|
path('showcases/create/', ShowcaseCreateView.as_view(), name='showcase-create'),
|
|
path('showcases/<int:pk>/edit/', ShowcaseUpdateView.as_view(), name='showcase-update'),
|
|
path('showcases/<int:pk>/delete/', ShowcaseDeleteView.as_view(), name='showcase-delete'),
|
|
]
|