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>
This commit is contained in:
objecttothis committed 2026-08-19 17:36:03 +04:00
1 parent 2115fda4e5
commit 39124e8132
2 files changed
+23 -10

No files matched your search

+17 -5
View File
@@ -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-<n>' 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));
+6 -5
View File
@@ -31,6 +31,7 @@
// Validation and submit handling
$(document).ready(function() {
let location_count = <?= sizeof($stock_locations) ?>;
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("<?= lang('Config.stock_location') ?> " + ++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(','));
};