From 39124e81329b0cec29239d77c866fc95ef70010c Mon Sep 17 00:00:00 2001 From: objecttothis <17935339+objecttothis@users.noreply.github.com> Date: Wed, 19 Aug 2026 17:36:03 +0400 Subject: [PATCH] fix(controllers, views): handle new stock locations in sort order and default selection - Updated controller to resolve 'new-*' placeholders in sort order to actual IDs. - Adjusted view logic to assign 'new-*' IDs to new stock location rows. - Improved default selection logic to exclude new rows with unresolved IDs. Signed-off-by: objecttothis <17935339+objecttothis@users.noreply.github.com> --- app/Controllers/Config.php | 22 +++++++++++++++++----- app/Views/configs/stock_config.php | 11 ++++++----- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/app/Controllers/Config.php b/app/Controllers/Config.php index bb1a8d2fb..8b8eb6cdf 100644 --- a/app/Controllers/Config.php +++ b/app/Controllers/Config.php @@ -761,23 +761,35 @@ class Config extends Secure_Controller } $notToDelete = []; + $newlyInsertedIds = []; foreach ($submittedLocations as $locationId => $locationName) { + $wasExisting = in_array($locationId, $submittedLocationIds); $locationData = ['location_name' => $locationName]; if ($this->stock_location->saveValue($locationData, $locationId)) { // saveValue() sets location_id on $locationData for new inserts (it stays // as-is for updates); reading it back here avoids re-resolving by name, // which is ambiguous when a deleted row still shares that name. - $notToDelete[] = $locationData['location_id'] ?? $locationId; + $savedLocationId = $locationData['location_id'] ?? $locationId; + $notToDelete[] = $savedLocationId; + if (!$wasExisting) { + $newlyInsertedIds[] = $savedLocationId; + } $this->_clear_session_state(); } } $sortOrder = $this->request->getPost('stock_location_order'); - $submittedOrderIds = $sortOrder ? array_map('intval', explode(',', $sortOrder)) : []; + $submittedOrderTokens = $sortOrder ? explode(',', $sortOrder) : []; + + // 'new-' tokens are placeholders for rows with no location_id yet; resolve + // each to its real inserted id in submission order. + $submittedOrderIds = array_map( + function ($token) use (&$newlyInsertedIds) { + return str_starts_with($token, 'new-') ? array_shift($newlyInsertedIds) : (int) $token; + }, + $submittedOrderTokens + ); - // The submitted order can be missing ids for locations added in this same submit - // (they have no location_id yet client-side), so reconcile it against the - // authoritative post-save id list before persisting, appending any missing ids. $orderedLocationIds = array_values(array_unique(array_intersect($submittedOrderIds, $notToDelete))); $orderedLocationIds = array_merge($orderedLocationIds, array_diff($notToDelete, $orderedLocationIds)); diff --git a/app/Views/configs/stock_config.php b/app/Views/configs/stock_config.php index 2cd077a9d..e5fe17ce6 100644 --- a/app/Views/configs/stock_config.php +++ b/app/Views/configs/stock_config.php @@ -31,6 +31,7 @@ // Validation and submit handling $(document).ready(function() { let location_count = ; + let new_location_counter = 0; const hide_show_remove = function() { if ($('#stock_locations .stock_location_row').length > 1) { @@ -42,7 +43,9 @@ const ensure_default_selected = function() { if ($('#stock_locations input.stock_location_default:checked').length === 0) { - $('#stock_locations .stock_location_row[data-location-id]').first().find('input.stock_location_default').prop('checked', true); + $('#stock_locations .stock_location_row').filter(function() { + return String($(this).data('location-id')).indexOf('new-') !== 0; + }).first().find('input.stock_location_default').prop('checked', true); } }; @@ -50,7 +53,7 @@ const block = $(this).parent().clone(true); const new_block = block.insertAfter($(this).parent()); const new_block_id = 'stock_location[]'; - $(new_block).removeAttr('data-location-id').find('input.stock_location_default').prop('checked', false).prop('disabled', true).val(''); + $(new_block).attr('data-location-id', 'new-' + ++new_location_counter).find('input.stock_location_default').prop('checked', false).prop('disabled', true).val(''); $(new_block).find('label').html(" " + ++location_count).attr('for', new_block_id).attr('class', 'control-label col-xs-2'); $(new_block).find('input.stock_location').attr('id', new_block_id).removeAttr('disabled').attr('name', new_block_id).attr('class', 'stock_location valid_chars form-control input-sm required').val(''); hide_show_remove(); @@ -75,9 +78,7 @@ const update_sort_order_field = function() { const orderedIds = $('#stock_locations .stock_location_row').map(function() { return $(this).data('location-id'); - }).get().filter(function(locationId) { - return locationId !== undefined && locationId !== ''; - }); + }).get(); $("input[name='stock_location_order']").val(orderedIds.join(',')); };