diff --git a/myproject/inventory/templates/inventory/incoming_document/incoming_document_detail.html b/myproject/inventory/templates/inventory/incoming_document/incoming_document_detail.html index c839660..495e431 100644 --- a/myproject/inventory/templates/inventory/incoming_document/incoming_document_detail.html +++ b/myproject/inventory/templates/inventory/incoming_document/incoming_document_detail.html @@ -118,7 +118,7 @@
- {% include 'products/components/product_search_picker.html' with container_id='incoming-picker' title='Найти товар для поступления' warehouse_id=document.warehouse.id filter_in_stock_only=False categories=categories tags=tags add_button_text='Выбрать товар' content_height='250px' %} + {% include 'products/components/product_search_picker.html' with container_id='incoming-picker' title='Найти товар для поступления' warehouse_id=document.warehouse.id filter_in_stock_only=False skip_stock_filter=True categories=categories tags=tags add_button_text='Выбрать товар' content_height='250px' %}
diff --git a/myproject/products/static/products/js/product-search-picker.js b/myproject/products/static/products/js/product-search-picker.js index baf4c79..ad9e70d 100644 --- a/myproject/products/static/products/js/product-search-picker.js +++ b/myproject/products/static/products/js/product-search-picker.js @@ -61,7 +61,8 @@ category: '', tag: '', inStock: false, - warehouse: '' // ID склада для фильтрации + warehouse: '', // ID склада для фильтрации + skipStockFilter: false // Не фильтровать по остаткам (для приёмки) } }; @@ -105,6 +106,11 @@ if (this.container.dataset.warehouseId) { this.state.filters.warehouse = this.container.dataset.warehouseId; } + + // Инициализация skipStockFilter из data-атрибута + if (this.container.dataset.skipStockFilter === 'true') { + this.state.filters.skipStockFilter = true; + } }; /** @@ -266,6 +272,9 @@ if (this.state.filters.warehouse) { params.append('warehouse', this.state.filters.warehouse); } + if (this.state.filters.skipStockFilter) { + params.append('skip_stock_filter', 'true'); + } fetch(this.options.apiUrl + '?' + params.toString()) .then(function(response) { diff --git a/myproject/products/templates/products/components/product_search_picker.html b/myproject/products/templates/products/components/product_search_picker.html index a1222e5..9efc507 100644 --- a/myproject/products/templates/products/components/product_search_picker.html +++ b/myproject/products/templates/products/components/product_search_picker.html @@ -12,6 +12,7 @@ - initial_view: начальный вид 'grid' или 'list' (default: 'list') - filter_in_stock_only: показывать только товары в наличии (default: False) - warehouse_id: ID склада для фильтрации товаров (default: None) +- skip_stock_filter: не фильтровать по остаткам на складе (default: False, для приёмки: True) - categories: список категорий для фильтра (queryset или list) - tags: список тегов для фильтра (queryset или list) - content_height: высота контейнера с товарами (default: '400px') @@ -43,7 +44,8 @@ ProductSearchPicker.init('#writeoff-products', { id="{{ container_id|default:'product-search-picker' }}" data-api-url="{{ api_url|default:'/products/api/search-products-variants/' }}" data-exclude-kits="true" - {% if warehouse_id %}data-warehouse-id="{{ warehouse_id }}"{% endif %}> + {% if warehouse_id %}data-warehouse-id="{{ warehouse_id }}"{% endif %} + {% if skip_stock_filter %}data-skip-stock-filter="true"{% endif %}>
diff --git a/myproject/products/views/api_views.py b/myproject/products/views/api_views.py index 80adc98..5d50fd9 100644 --- a/myproject/products/views/api_views.py +++ b/myproject/products/views/api_views.py @@ -21,16 +21,22 @@ def _get_product_photo_url(product_id): return None -def _apply_product_filters(queryset, category_id=None, tag_id=None, in_stock_only=False, warehouse_id=None): - """Применяет фильтры к queryset товаров.""" +def _apply_product_filters(queryset, category_id=None, tag_id=None, in_stock_only=False, warehouse_id=None, skip_stock_filter=False): + """Применяет фильтры к queryset товаров. + + Args: + skip_stock_filter: Если True, warehouse_id не фильтрует по остаткам. + Используется для приёмки товаров. + """ if category_id: queryset = queryset.filter(categories__id=category_id) if tag_id: queryset = queryset.filter(tags__id=tag_id) if in_stock_only: queryset = queryset.filter(in_stock=True) - if warehouse_id: + if warehouse_id and not skip_stock_filter: # Фильтруем только товары, которые есть на указанном складе с доступным количеством + # НЕ применяется при skip_stock_filter=True (приёмка товаров) from inventory.models import Stock products_with_stock = Stock.objects.filter( warehouse_id=warehouse_id, @@ -186,6 +192,7 @@ def search_products_and_variants(request): tag_id = request.GET.get('tag', '').strip() in_stock_only = request.GET.get('in_stock', '').lower() == 'true' warehouse_id = request.GET.get('warehouse', '').strip() + skip_stock_filter = request.GET.get('skip_stock_filter', '').lower() == 'true' results = [] @@ -208,7 +215,7 @@ def search_products_and_variants(request): # Показываем последние добавленные активные товары products_qs = Product.objects.filter(status='active').prefetch_related('sales_units__unit') # Применяем фильтры - products_qs = _apply_product_filters(products_qs, category_id, tag_id, in_stock_only, warehouse_id) + products_qs = _apply_product_filters(products_qs, category_id, tag_id, in_stock_only, warehouse_id, skip_stock_filter) products = products_qs.order_by('-created_at')[:page_size] for product in products: @@ -352,7 +359,7 @@ def search_products_and_variants(request): ).order_by('-relevance', 'name') # Применяем дополнительные фильтры - products_query = _apply_product_filters(products_query, category_id, tag_id, in_stock_only, warehouse_id) + products_query = _apply_product_filters(products_query, category_id, tag_id, in_stock_only, warehouse_id, skip_stock_filter) # Добавляем prefetch для единиц продажи products_query = products_query.prefetch_related('sales_units__unit')