feat(shipments): add ShipmentProviderInterface and ShipmentProviderRegistry

- Introduced ShipmentProviderInterface to define the contract for shipment providers.
- Implemented ShipmentProviderRegistry to manage and retrieve shipment providers.
- Added a new tool for probing Apaczka order_send payload variants, enhancing debugging capabilities.
This commit is contained in:
2026-03-08 23:45:10 +01:00
parent af052e1ff5
commit 2b12fde248
34 changed files with 3285 additions and 233 deletions

View File

@@ -292,6 +292,7 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
$dmMappings = is_array($deliveryMappings ?? null) ? $deliveryMappings : [];
$dmOrderMethods = is_array($orderDeliveryMethods ?? null) ? $orderDeliveryMethods : [];
$dmAllegroServices = is_array($allegroDeliveryServices ?? null) ? $allegroDeliveryServices : [];
$dmApaczkaServices = is_array($apaczkaDeliveryServices ?? null) ? $apaczkaDeliveryServices : [];
$dmInpostServices = is_array($inpostDeliveryServices ?? null) ? $inpostDeliveryServices : [];
$dmServicesError = (string) ($allegroDeliveryServicesError ?? '');
$dmMappingsByMethod = [];
@@ -326,9 +327,18 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
<?php foreach ($dmOrderMethods as $rowIdx => $orderMethod): ?>
<?php
$currentMapping = $dmMappingsByMethod[$orderMethod] ?? null;
$currentCarrier = $currentMapping !== null ? trim((string) ($currentMapping['carrier'] ?? 'allegro')) : '';
$currentAllegroId = $currentMapping !== null ? trim((string) ($currentMapping['allegro_delivery_method_id'] ?? '')) : '';
$currentServiceName = $currentMapping !== null ? trim((string) ($currentMapping['allegro_service_name'] ?? '')) : '';
$currentProvider = $currentMapping !== null ? trim((string) ($currentMapping['provider'] ?? 'allegro_wza')) : '';
$currentMethodId = $currentMapping !== null ? trim((string) ($currentMapping['provider_service_id'] ?? '')) : '';
$currentServiceName = $currentMapping !== null ? trim((string) ($currentMapping['provider_service_name'] ?? '')) : '';
$currentProviderCarrierId = $currentMapping !== null ? trim((string) ($currentMapping['provider_carrier_id'] ?? '')) : '';
$currentCarrier = '';
if ($currentProvider === 'apaczka') {
$currentCarrier = 'apaczka';
} elseif (stripos($currentProviderCarrierId, 'inpost') !== false) {
$currentCarrier = 'inpost';
} elseif ($currentMethodId !== '') {
$currentCarrier = 'allegro';
}
?>
<tr data-dm-row="<?= $rowIdx ?>">
<td>
@@ -338,20 +348,22 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
<td>
<select class="form-control dm-carrier-select" name="carrier[]" data-row="<?= $rowIdx ?>">
<option value="">-- <?= $e($t('settings.allegro.delivery.fields.no_mapping')) ?> --</option>
<option value="allegro"<?= $currentCarrier === 'allegro' && $currentAllegroId !== '' ? ' selected' : '' ?>>Allegro</option>
<option value="allegro"<?= $currentCarrier === 'allegro' && $currentMethodId !== '' ? ' selected' : '' ?>>Allegro</option>
<option value="inpost"<?= $currentCarrier === 'inpost' ? ' selected' : '' ?>>InPost</option>
<option value="apaczka"<?= $currentCarrier === 'apaczka' ? ' selected' : '' ?>>Apaczka</option>
</select>
</td>
<td>
<div class="dm-service-wrap" data-row="<?= $rowIdx ?>">
<input type="hidden" name="allegro_delivery_method_id[]" class="dm-hidden-method-id" value="<?= $e($currentAllegroId) ?>">
<input type="hidden" name="allegro_credentials_id[]" class="dm-hidden-credentials-id" value="<?= $e(trim((string) ($currentMapping['allegro_credentials_id'] ?? ''))) ?>">
<input type="hidden" name="allegro_carrier_id[]" class="dm-hidden-carrier-id" value="<?= $e(trim((string) ($currentMapping['allegro_carrier_id'] ?? ''))) ?>">
<input type="hidden" name="allegro_delivery_method_id[]" class="dm-hidden-method-id" value="<?= $e($currentProvider !== 'apaczka' ? $currentMethodId : '') ?>">
<input type="hidden" name="apaczka_delivery_method_id[]" class="dm-hidden-apaczka-method-id" value="<?= $e($currentProvider === 'apaczka' ? $currentMethodId : '') ?>">
<input type="hidden" name="allegro_credentials_id[]" class="dm-hidden-credentials-id" value="<?= $e(trim((string) ($currentMapping['provider_account_id'] ?? ''))) ?>">
<input type="hidden" name="allegro_carrier_id[]" class="dm-hidden-carrier-id" value="<?= $e($currentProviderCarrierId) ?>">
<input type="hidden" name="allegro_service_name[]" class="dm-hidden-service-name" value="<?= $e($currentServiceName) ?>">
<?php // Allegro searchable select ?>
<div class="dm-allegro-panel dm-searchable-select" data-current-id="<?= $e($currentCarrier === 'allegro' ? $currentAllegroId : '') ?>" data-current-name="<?= $e($currentCarrier === 'allegro' ? $currentServiceName : '') ?>" style="<?= $currentCarrier !== 'allegro' || $currentAllegroId === '' && $currentCarrier === '' ? 'display:none' : '' ?>">
<input type="text" class="form-control dm-search-input" placeholder="<?= $e($t('settings.allegro.delivery.fields.search_placeholder')) ?>" value="<?= $e($currentCarrier === 'allegro' ? $currentServiceName : '') ?>" autocomplete="off">
<div class="dm-allegro-panel dm-searchable-select" data-current-id="<?= $e(($currentCarrier === 'allegro' || $currentCarrier === 'inpost') ? $currentMethodId : '') ?>" data-current-name="<?= $e(($currentCarrier === 'allegro' || $currentCarrier === 'inpost') ? $currentServiceName : '') ?>" style="<?= ($currentCarrier !== 'allegro' && $currentCarrier !== 'inpost') ? 'display:none' : '' ?>">
<input type="text" class="form-control dm-search-input" placeholder="<?= $e($t('settings.allegro.delivery.fields.search_placeholder')) ?>" value="<?= $e(($currentCarrier === 'allegro' || $currentCarrier === 'inpost') ? $currentServiceName : '') ?>" autocomplete="off">
<div class="searchable-select__dropdown dm-dropdown">
<div class="searchable-select__option dm-option-clear" data-value="" data-label="" data-credentials-id="" data-carrier-id="">
<em class="muted">-- <?= $e($t('settings.allegro.delivery.fields.no_mapping')) ?> --</em>
@@ -376,6 +388,29 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
</div>
</div>
<div class="dm-apaczka-panel" style="<?= $currentCarrier !== 'apaczka' ? 'display:none' : '' ?>">
<?php if ($dmApaczkaServices === []): ?>
<div class="muted">Brak uslug Apaczka (sprawdz konfiguracje App ID/App Secret).</div>
<?php else: ?>
<select class="form-control dm-apaczka-select">
<option value="">-- <?= $e($t('settings.allegro.delivery.fields.no_mapping')) ?> --</option>
<?php foreach ($dmApaczkaServices as $aSvc): ?>
<?php
$aSvcId = trim((string) ($aSvc['id'] ?? ''));
$aSvcName = trim((string) ($aSvc['name'] ?? ''));
$aSvcCarrier = trim((string) ($aSvc['carrier_code'] ?? ''));
?>
<option
value="<?= $e($aSvcId) ?>"
data-carrier-id="<?= $e($aSvcCarrier) ?>"
<?= $currentCarrier === 'apaczka' && $currentMethodId === $aSvcId ? 'selected' : '' ?>>
<?= $e($aSvcName !== '' ? $aSvcName : ('ID ' . $aSvcId)) ?>
</option>
<?php endforeach; ?>
</select>
<?php endif; ?>
</div>
<?php // InPost simple select ?>
<div class="dm-inpost-panel" style="<?= $currentCarrier !== 'inpost' ? 'display:none' : '' ?>">
<?php if ($dmInpostServices === []): ?>
@@ -395,7 +430,7 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
value="<?= $e($inSvcMethodId) ?>"
data-credentials-id="<?= $e($inSvcCredentialsId) ?>"
data-carrier-id="<?= $e($inSvcCarrierId) ?>"
<?= $currentCarrier === 'inpost' && $currentAllegroId === $inSvcMethodId ? 'selected' : '' ?>>
<?= $currentCarrier === 'inpost' && $currentMethodId === $inSvcMethodId ? 'selected' : '' ?>>
<?= $e($inSvcName) ?>
</option>
<?php endforeach; ?>
@@ -404,7 +439,7 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
</div>
<?php // Empty state ?>
<div class="dm-empty-panel muted" style="<?= $currentCarrier !== '' ? 'display:none' : ($currentAllegroId !== '' ? 'display:none' : '') ?>">
<div class="dm-empty-panel muted" style="<?= $currentCarrier !== '' ? 'display:none' : ($currentMethodId !== '' ? 'display:none' : '') ?>">
<?= $e($t('settings.allegro.delivery.fields.select_carrier_first')) ?>
</div>
</div>
@@ -474,6 +509,60 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
})();
(function () {
function attachSelectFilter(selectEl) {
if (!selectEl || selectEl.dataset.enhanced === '1') {
return;
}
selectEl.dataset.enhanced = '1';
var parent = selectEl.parentNode;
if (!parent) {
return;
}
var filterInput = document.createElement('input');
filterInput.type = 'text';
filterInput.className = 'form-control';
filterInput.placeholder = 'Szukaj...';
filterInput.autocomplete = 'off';
filterInput.style.marginBottom = '8px';
parent.insertBefore(filterInput, selectEl);
function focusFirstMatch(term) {
var query = term.toLowerCase().trim();
if (query === '') {
return;
}
var matchedIndex = -1;
Array.prototype.forEach.call(selectEl.options, function (opt, idx) {
if (matchedIndex >= 0) {
return;
}
if (opt.textContent.toLowerCase().indexOf(query) !== -1) {
matchedIndex = idx;
}
});
if (matchedIndex >= 0 && selectEl.selectedIndex !== matchedIndex) {
selectEl.selectedIndex = matchedIndex;
selectEl.dispatchEvent(new Event('change', { bubbles: true }));
}
}
filterInput.addEventListener('input', function () {
focusFirstMatch(filterInput.value);
});
selectEl._syncTrigger = function () {
// Keep select untouched; filter only suggests matching option.
};
}
document.querySelectorAll('.dm-inpost-select, .dm-apaczka-select').forEach(function (selectEl) {
attachSelectFilter(selectEl);
});
// Carrier switching logic
document.querySelectorAll('.dm-carrier-select').forEach(function (carrierSelect) {
var rowIdx = carrierSelect.getAttribute('data-row');
@@ -482,8 +571,10 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
var allegroPanel = serviceWrap.querySelector('.dm-allegro-panel');
var inpostPanel = serviceWrap.querySelector('.dm-inpost-panel');
var apaczkaPanel = serviceWrap.querySelector('.dm-apaczka-panel');
var emptyPanel = serviceWrap.querySelector('.dm-empty-panel');
var hiddenMethodId = serviceWrap.querySelector('.dm-hidden-method-id');
var hiddenApaczkaMethodId = serviceWrap.querySelector('.dm-hidden-apaczka-method-id');
var hiddenCredentialsId = serviceWrap.querySelector('.dm-hidden-credentials-id');
var hiddenCarrierId = serviceWrap.querySelector('.dm-hidden-carrier-id');
var hiddenServiceName = serviceWrap.querySelector('.dm-hidden-service-name');
@@ -491,23 +582,42 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
function showPanel(carrier) {
if (allegroPanel) allegroPanel.style.display = carrier === 'allegro' ? '' : 'none';
if (inpostPanel) inpostPanel.style.display = carrier === 'inpost' ? '' : 'none';
if (apaczkaPanel) apaczkaPanel.style.display = carrier === 'apaczka' ? '' : 'none';
if (emptyPanel) emptyPanel.style.display = carrier === '' ? '' : 'none';
}
showPanel(carrierSelect.value);
carrierSelect.addEventListener('change', function () {
var carrier = carrierSelect.value;
showPanel(carrier);
// Clear hidden values when switching carrier
if (hiddenMethodId) hiddenMethodId.value = '';
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = '';
if (hiddenCredentialsId) hiddenCredentialsId.value = '';
if (hiddenCarrierId) hiddenCarrierId.value = '';
if (hiddenServiceName) hiddenServiceName.value = '';
// Reset Allegro search input
var allegroInput = allegroPanel ? allegroPanel.querySelector('.dm-search-input') : null;
if (allegroInput) allegroInput.value = '';
if (allegroInput) {
allegroInput.value = '';
allegroInput.blur();
}
var allegroDropdown = allegroPanel ? allegroPanel.querySelector('.dm-dropdown') : null;
if (allegroDropdown) {
allegroDropdown.classList.remove('is-open');
}
// Reset InPost select
var inpostSelect = inpostPanel ? inpostPanel.querySelector('.dm-inpost-select') : null;
if (inpostSelect) inpostSelect.value = '';
if (inpostSelect) {
inpostSelect.value = '';
if (inpostSelect._syncTrigger) inpostSelect._syncTrigger();
}
var apaczkaSelect = apaczkaPanel ? apaczkaPanel.querySelector('.dm-apaczka-select') : null;
if (apaczkaSelect) {
apaczkaSelect.value = '';
if (apaczkaSelect._syncTrigger) apaczkaSelect._syncTrigger();
}
});
// InPost select change -> update hidden fields
@@ -516,10 +626,29 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
inpostSelect.addEventListener('change', function () {
var opt = inpostSelect.options[inpostSelect.selectedIndex];
if (hiddenMethodId) hiddenMethodId.value = inpostSelect.value;
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = '';
if (hiddenCredentialsId) hiddenCredentialsId.value = opt ? (opt.getAttribute('data-credentials-id') || '') : '';
if (hiddenCarrierId) hiddenCarrierId.value = opt ? (opt.getAttribute('data-carrier-id') || '') : '';
if (hiddenServiceName) hiddenServiceName.value = opt ? opt.textContent.trim() : '';
});
if (inpostSelect.value !== '') {
inpostSelect.dispatchEvent(new Event('change', { bubbles: true }));
}
}
var apaczkaSelect = apaczkaPanel ? apaczkaPanel.querySelector('.dm-apaczka-select') : null;
if (apaczkaSelect) {
apaczkaSelect.addEventListener('change', function () {
var opt = apaczkaSelect.options[apaczkaSelect.selectedIndex];
if (hiddenMethodId) hiddenMethodId.value = '';
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = apaczkaSelect.value;
if (hiddenCredentialsId) hiddenCredentialsId.value = '';
if (hiddenCarrierId) hiddenCarrierId.value = opt ? (opt.getAttribute('data-carrier-id') || '') : '';
if (hiddenServiceName) hiddenServiceName.value = opt ? opt.textContent.trim() : '';
});
if (apaczkaSelect.value !== '') {
apaczkaSelect.dispatchEvent(new Event('change', { bubbles: true }));
}
}
});
@@ -531,6 +660,7 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
if (!searchInput || !dropdown || !serviceWrap) return;
var hiddenMethodId = serviceWrap.querySelector('.dm-hidden-method-id');
var hiddenApaczkaMethodId = serviceWrap.querySelector('.dm-hidden-apaczka-method-id');
var hiddenCredentialsId = serviceWrap.querySelector('.dm-hidden-credentials-id');
var hiddenCarrierId = serviceWrap.querySelector('.dm-hidden-carrier-id');
var hiddenServiceName = serviceWrap.querySelector('.dm-hidden-service-name');
@@ -540,6 +670,7 @@ $orderproStatuses = is_array($orderproStatuses ?? null) ? $orderproStatuses : []
function selectOption(opt) {
hiddenMethodId.value = opt.getAttribute('data-value') || '';
if (hiddenApaczkaMethodId) hiddenApaczkaMethodId.value = '';
hiddenCredentialsId.value = opt.getAttribute('data-credentials-id') || '';
hiddenCarrierId.value = opt.getAttribute('data-carrier-id') || '';
hiddenServiceName.value = opt.getAttribute('data-label') || '';