- Order product CRUD in admin panel (add, delete, edit quantity/prices) - AJAX product search endpoint for order edit form - Automatic stock adjustment when editing order products - Transport cost recalculation based on free delivery threshold - Fix: promo price = 0 when equal to base price (no real promotion) - Clean up stale temp/ build artifacts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
245 lines
9.9 KiB
PHP
245 lines
9.9 KiB
PHP
<script type="text/javascript">
|
|
$(function() {
|
|
|
|
// =========================================================================
|
|
// InPost paczkomat
|
|
// =========================================================================
|
|
|
|
function toggleInpostField() {
|
|
if ($('#transport_id').val() != '2') {
|
|
$('#inpost_paczkomat').closest('.row').hide();
|
|
} else {
|
|
$('#inpost_paczkomat').closest('.row').show();
|
|
}
|
|
}
|
|
|
|
toggleInpostField();
|
|
|
|
$('body').on('change', '#transport_id', function() {
|
|
toggleInpostField();
|
|
recalculateTotals();
|
|
});
|
|
|
|
$('body').on('click', '.btn-paczkomat', function() {
|
|
window.easyPackAsyncInit = function () {
|
|
easyPack.init({
|
|
mapType: 'osm',
|
|
searchType: 'osm',
|
|
});
|
|
|
|
easyPack.mapWidget('inpost-map', function(point) {
|
|
$('#inpost_paczkomat').val(point.name + ' | ' + point.address.line1 + ', ' + point.address.line2);
|
|
$('.inpost-map-container').hide();
|
|
});
|
|
};
|
|
|
|
$('.inpost-map-container').show();
|
|
});
|
|
|
|
// =========================================================================
|
|
// Order save
|
|
// =========================================================================
|
|
|
|
$('body').on('click', '#order-save', function(e) {
|
|
e.preventDefault();
|
|
$('#fg-order-details').attr('method', 'POST').attr('action', '/admin/shop_order/order_save/').submit();
|
|
});
|
|
|
|
// =========================================================================
|
|
// Product row index counter
|
|
// =========================================================================
|
|
|
|
var productIndex = $('#order-products-body .order-product-row').length;
|
|
|
|
// =========================================================================
|
|
// Remove product
|
|
// =========================================================================
|
|
|
|
$('body').on('click', '.btn-remove-product', function() {
|
|
var $row = $(this).closest('.order-product-row');
|
|
var orderProductId = $row.find('input[name$="[order_product_id]"]').val();
|
|
|
|
if (orderProductId && orderProductId !== '0') {
|
|
// Istniejący produkt — ukryj i oznacz do usunięcia
|
|
$row.hide();
|
|
$row.append('<input type="hidden" name="products[' + $row.data('index') + '][delete]" value="1">');
|
|
} else {
|
|
// Nowy produkt — po prostu usuń z DOM
|
|
$row.remove();
|
|
}
|
|
|
|
recalculateTotals();
|
|
});
|
|
|
|
// =========================================================================
|
|
// Quantity and price change — recalculate
|
|
// =========================================================================
|
|
|
|
$('body').on('change input', '.product-qty, .product-price, .product-price-promo', function() {
|
|
recalculateTotals();
|
|
});
|
|
|
|
// =========================================================================
|
|
// Product search (AJAX)
|
|
// =========================================================================
|
|
|
|
var searchTimer = null;
|
|
var $searchInput = $('#product-search-input');
|
|
var $searchResults = $('#product-search-results');
|
|
|
|
$searchInput.on('keyup', function() {
|
|
var query = $(this).val().trim();
|
|
|
|
clearTimeout(searchTimer);
|
|
|
|
if (query.length < 2) {
|
|
$searchResults.hide().empty();
|
|
return;
|
|
}
|
|
|
|
searchTimer = setTimeout(function() {
|
|
$.ajax({
|
|
url: '/admin/shop_order/search_products_ajax/',
|
|
type: 'GET',
|
|
data: { query: query },
|
|
dataType: 'json',
|
|
success: function(data) {
|
|
$searchResults.empty();
|
|
|
|
if (!data || !data.products || data.products.length === 0) {
|
|
$searchResults.append('<div style="padding:10px;color:#999">Brak wyników</div>');
|
|
$searchResults.show();
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < data.products.length; i++) {
|
|
var p = data.products[i];
|
|
var priceDisplay = p.price_brutto_promo > 0
|
|
? '<span style="text-decoration:line-through;color:#999">' + parseFloat(p.price_brutto).toFixed(2) + ' zł</span> <strong>' + parseFloat(p.price_brutto_promo).toFixed(2) + ' zł</strong>'
|
|
: '<strong>' + parseFloat(p.price_brutto).toFixed(2) + ' zł</strong>';
|
|
|
|
var stockWarning = p.quantity <= 0
|
|
? ' <span style="color:#d9534f;font-size:11px">(brak na stanie)</span>'
|
|
: ' <span style="color:#5cb85c;font-size:11px">(stan: ' + p.quantity + ')</span>';
|
|
|
|
var imgHtml = p.image
|
|
? '<img src="' + p.image + '" style="width:35px;height:35px;object-fit:cover;margin-right:8px;border-radius:3px">'
|
|
: '<span style="display:inline-block;width:35px;height:35px;margin-right:8px;background:#eee;border-radius:3px"></span>';
|
|
|
|
var $item = $('<div class="product-search-item" style="padding:8px 10px;cursor:pointer;display:flex;align-items:center;border-bottom:1px solid #f0f0f0"></div>');
|
|
$item.html(imgHtml + '<div><div>' + $('<span>').text(p.name).html() + (p.sku ? ' <span style="color:#999;font-size:11px">(' + $('<span>').text(p.sku).html() + ')</span>' : '') + stockWarning + '</div><div>' + priceDisplay + '</div></div>');
|
|
$item.data('product', p);
|
|
$searchResults.append($item);
|
|
}
|
|
|
|
$searchResults.show();
|
|
}
|
|
});
|
|
}, 300);
|
|
});
|
|
|
|
// Kliknięcie w wynik wyszukiwania — dodaj produkt
|
|
$('body').on('click', '.product-search-item', function() {
|
|
var p = $(this).data('product');
|
|
|
|
if (p.quantity <= 0) {
|
|
if (!confirm('Produkt "' + p.name + '" nie jest dostępny na stanie. Czy na pewno chcesz go dodać?')) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
addProductRow(p);
|
|
$searchInput.val('');
|
|
$searchResults.hide().empty();
|
|
});
|
|
|
|
// Ukryj wyniki przy kliknięciu poza
|
|
$(document).on('click', function(e) {
|
|
if (!$(e.target).closest('#add-product-section').length) {
|
|
$searchResults.hide();
|
|
}
|
|
});
|
|
|
|
// =========================================================================
|
|
// Add product row
|
|
// =========================================================================
|
|
|
|
function addProductRow(product) {
|
|
var idx = productIndex++;
|
|
var imgHtml = product.image
|
|
? '<img src="' + product.image + '" style="max-width:50px;max-height:50px">'
|
|
: '';
|
|
|
|
var effectivePrice = product.price_brutto_promo > 0 ? product.price_brutto_promo : product.price_brutto;
|
|
|
|
var $row = $('<tr class="order-product-row" data-index="' + idx + '"></tr>');
|
|
$row.html(
|
|
'<input type="hidden" name="products[' + idx + '][order_product_id]" value="0">' +
|
|
'<input type="hidden" name="products[' + idx + '][product_id]" value="' + product.product_id + '">' +
|
|
'<input type="hidden" name="products[' + idx + '][parent_product_id]" value="' + (product.parent_product_id || product.product_id) + '">' +
|
|
'<input type="hidden" name="products[' + idx + '][name]" value="' + $('<span>').text(product.name).html() + '">' +
|
|
'<input type="hidden" name="products[' + idx + '][vat]" value="' + product.vat + '">' +
|
|
'<td class="product-image">' + imgHtml + '</td>' +
|
|
'<td>' + $('<span>').text(product.name).html() +
|
|
(product.sku ? ' <span class="small text-muted">(' + $('<span>').text(product.sku).html() + ')</span>' : '') +
|
|
'</td>' +
|
|
'<td class="tab-center"><input type="number" name="products[' + idx + '][quantity]" value="1" min="1" class="form-control form-control-sm text-center product-qty" style="width:70px"></td>' +
|
|
'<td class="tab-right"><input type="number" name="products[' + idx + '][price_brutto]" value="' + parseFloat(product.price_brutto).toFixed(2) + '" step="0.01" min="0" class="form-control form-control-sm text-right product-price" style="width:110px"></td>' +
|
|
'<td class="tab-right"><input type="number" name="products[' + idx + '][price_brutto_promo]" value="' + parseFloat(product.price_brutto_promo).toFixed(2) + '" step="0.01" min="0" class="form-control form-control-sm text-right product-price-promo" style="width:110px"></td>' +
|
|
'<td class="tab-right product-row-total">' + parseFloat(effectivePrice).toFixed(2).replace('.', ',') + ' zł</td>' +
|
|
'<td class="text-center"><button type="button" class="btn btn-xs btn-danger btn-remove-product" title="Usuń produkt"><i class="fa fa-times"></i></button></td>'
|
|
);
|
|
|
|
$('#order-products-body').append($row);
|
|
recalculateTotals();
|
|
}
|
|
|
|
// =========================================================================
|
|
// Recalculate totals
|
|
// =========================================================================
|
|
|
|
function recalculateTotals() {
|
|
var productsTotal = 0;
|
|
|
|
$('#order-products-body .order-product-row:visible').each(function() {
|
|
var qty = parseFloat($(this).find('.product-qty').val()) || 0;
|
|
var price = parseFloat($(this).find('.product-price').val()) || 0;
|
|
var pricePromo = parseFloat($(this).find('.product-price-promo').val()) || 0;
|
|
|
|
var effectivePrice = pricePromo > 0 ? pricePromo : price;
|
|
var rowTotal = effectivePrice * qty;
|
|
|
|
$(this).find('.product-row-total').text(rowTotal.toFixed(2).replace('.', ',') + ' zł');
|
|
productsTotal += rowTotal;
|
|
});
|
|
|
|
// Transport cost (z uwzględnieniem progu darmowej dostawy)
|
|
var transportId = parseInt($('#transport_id').val()) || 0;
|
|
var transportCost = 0;
|
|
var transports = orderEditConfig.transports || [];
|
|
|
|
for (var i = 0; i < transports.length; i++) {
|
|
if (transports[i].id === transportId) {
|
|
var t = transports[i];
|
|
if (t.delivery_free === 1 && orderEditConfig.freeDelivery > 0 && productsTotal >= orderEditConfig.freeDelivery) {
|
|
transportCost = 0;
|
|
} else {
|
|
transportCost = t.cost;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
var orderTotal = productsTotal + transportCost;
|
|
|
|
$('#products-total-display').text(productsTotal.toFixed(2).replace('.', ','));
|
|
$('#transport-cost-display').text(transportCost.toFixed(2).replace('.', ','));
|
|
$('#order-summary-display').text(orderTotal.toFixed(2).replace('.', ',') + ' zł');
|
|
}
|
|
|
|
// Inicjalizacja sum przy załadowaniu strony
|
|
recalculateTotals();
|
|
|
|
});
|
|
</script>
|