diff --git a/streetup/mobile/views.py b/streetup/mobile/views.py index 2051bdf..c52cbc5 100644 --- a/streetup/mobile/views.py +++ b/streetup/mobile/views.py @@ -414,15 +414,27 @@ def stock_serialized_item_detail_mobile(request, pk): @stock_access_required def stock_preparation_orders_mobile(request): from stock.models import PreparationOrder + from django.db import models selected_status = request.GET.get('status', '').strip() selected_priority = request.GET.get('priority', '').strip() + search_q = request.GET.get('q', '').strip() - preparation_orders = PreparationOrder.objects.all() + preparation_orders = PreparationOrder.objects.select_related('intervention').all() if selected_status: preparation_orders = preparation_orders.filter(status=selected_status) if selected_priority: preparation_orders = preparation_orders.filter(priority=selected_priority) + if search_q: + q_filter = ( + models.Q(order_number__icontains=search_q) | + models.Q(intervention__code__icontains=search_q) | + models.Q(intervention__title__icontains=search_q) | + models.Q(requester__icontains=search_q) + ) + if search_q.isdigit(): + q_filter |= models.Q(intervention__id=int(search_q)) + preparation_orders = preparation_orders.filter(q_filter) preparation_orders = preparation_orders.prefetch_related( 'preparationorderitem_set__product' @@ -431,6 +443,7 @@ def stock_preparation_orders_mobile(request): 'preparation_orders': preparation_orders, 'selected_status': selected_status, 'selected_priority': selected_priority, + 'search_q': search_q, 'preparation_order_status_choices': [ ('to_process', _("A traiter")), ('pending', _("En attente")), @@ -1028,10 +1041,17 @@ def stock_preparation_order_detail_mobile(request, pk): can_manage = user_config.has_role('stock_manager') or user_config.has_role('admin') or user_config.can_manage_preparation_orders_any() can_cancel = user_config.can_manage_preparation_orders_any() can_manage_purchase = user_config.can_manage_purchase_orders_any() + can_manage_stock = ( + request.user.is_superuser + or user_config.has_role('admin') + or user_config.has_role('stock_manager') + or user_config.get_accessible_warehouses(can_manage=True).exists() + ) except UserConfig.DoesNotExist: can_manage = False can_cancel = False can_manage_purchase = False + can_manage_stock = False other_items_with_info = [] for oi in preparation_order.other_items.all(): @@ -1050,6 +1070,7 @@ def stock_preparation_order_detail_mobile(request, pk): 'can_manage': can_manage, 'can_cancel': can_cancel, 'can_manage_purchase': can_manage_purchase, + 'can_manage_stock': can_manage_stock, 'exit_batches': exit_batches, 'return_batches': return_batches, 'has_executed_outputs': has_executed_outputs, diff --git a/streetup/stock/models.py b/streetup/stock/models.py index 57c3454..c5766d2 100644 --- a/streetup/stock/models.py +++ b/streetup/stock/models.py @@ -1454,6 +1454,29 @@ class PreparationOrder(models.Model): summary[p_id]['net'] -= move.quantity return summary + def get_default_return_location_id(self): + """ + Si tous les produits sortis pour ce bon proviennent du même emplacement unique, + retourne l'ID de cet emplacement (pour préremplir l'emplacement de destination lors d'un retour). + """ + executed_by_loc = self.get_executed_outputs_by_product_and_location() + loc_set = set() + for p_id, loc_dict in executed_by_loc.items(): + for loc_id, qty in loc_dict.items(): + if qty > 0: + loc_set.add(loc_id) + if len(loc_set) == 1: + return list(loc_set)[0] + + gross_locs = set() + for batch in self.stock_batches.filter(movement_type='out'): + for move in batch.movements.all(): + if move.source_location_id: + gross_locs.add(move.source_location_id) + if len(gross_locs) == 1: + return list(gross_locs)[0] + return None + class PreparationOrderItem(models.Model): diff --git a/streetup/stock/templates/stock/mobile/new_stock_batch_mobile.html b/streetup/stock/templates/stock/mobile/new_stock_batch_mobile.html index c600c3e..8b8639f 100644 --- a/streetup/stock/templates/stock/mobile/new_stock_batch_mobile.html +++ b/streetup/stock/templates/stock/mobile/new_stock_batch_mobile.html @@ -167,7 +167,7 @@ {% if movement_type == 'in' %} - + {% elif movement_type == 'out' %} @@ -721,6 +721,15 @@ const bpResults = document.getElementById('bp-results'); const bpLoadBtn = document.getElementById('bp-load-btn'); const bpInfo = document.getElementById('bp-info'); +{% if preselected_po %} +if (bpSearchInput && bpHiddenId && bpLoadBtn) { + bpHiddenId.value = '{{ preselected_po.pk }}'; + bpSearchInput.value = '{{ preselected_po.order_number }}{% if preselected_po.intervention %} (Int. {{ preselected_po.intervention.code|default:preselected_po.intervention.id }}){% endif %}'; + bpLoadBtn.disabled = false; + setTimeout(() => { bpLoadBtn.click(); }, 150); +} +{% endif %} + let bpTimeout = null; if (bpSearchInput) { @@ -779,6 +788,14 @@ if (bpLoadBtn) { bpInfo.innerHTML = `{% translate "Chargement de" %} ${data.items.length} {% translate "produit(s) depuis le bon" %} ${escHtml(data.order_number)}`; bpInfo.className = 'alert alert-info mt-2 mb-0 py-2 small'; bpInfo.style.display = ''; + // Pré-remplir l'emplacement de destination si unique + if (data.default_location_id) { + const globalDestSelect = document.getElementById('global_dest_location_id'); + if (globalDestSelect) { + globalDestSelect.value = data.default_location_id; + globalDestSelect.dispatchEvent(new Event('change')); + } + } // Effacer les lignes existantes document.getElementById('lines-container').innerHTML = ''; updateNoLinesPlaceholder(); diff --git a/streetup/stock/templates/stock/mobile/stock_preparation_order_detail_mobile.html b/streetup/stock/templates/stock/mobile/stock_preparation_order_detail_mobile.html index a115e1d..408582d 100644 --- a/streetup/stock/templates/stock/mobile/stock_preparation_order_detail_mobile.html +++ b/streetup/stock/templates/stock/mobile/stock_preparation_order_detail_mobile.html @@ -456,6 +456,19 @@ {% translate "Annuler le bon" %} {% endif %} + {% elif preparation_order.status == 'processed' %} + {% if can_manage_stock %} + + {% translate "Créer un retour de stock" %} + + {% endif %} +
{% endif %} {% endif %} diff --git a/streetup/stock/templates/stock/mobile/stock_preparation_orders_mobile.html b/streetup/stock/templates/stock/mobile/stock_preparation_orders_mobile.html index d41e00b..4ed6225 100644 --- a/streetup/stock/templates/stock/mobile/stock_preparation_orders_mobile.html +++ b/streetup/stock/templates/stock/mobile/stock_preparation_orders_mobile.html @@ -40,6 +40,13 @@{% translate "Enregistrer la réintégration de matériel en stock préremplie depuis ce bon" %}
+ + {% translate "Créer un retour" %} + +