Files
octopus/myproject/pos/static/pos/js/cart-item-editor.js
Andrey Smakotin 2bc70968c3 fix(pos): restrict quantity editing for showcase kits in cart edit modal
For showcase kits (showcase_kit type), the quantity field is now disabled
in the cart item edit modal since these are pre-assembled physical items
with reservations. Price editing remains available.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 14:49:02 +03:00

214 lines
6.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Модуль редактирования товара в корзине POS-терминала
* Отвечает за открытие модалки и сохранение изменений
*/
(function() {
'use strict';
let editingCartKey = null;
let basePrice = 0;
/**
* Округление цены до 2 знаков
*/
function roundPrice(value) {
if (value === null || value === undefined || isNaN(value)) return '0.00';
return (Number(value)).toFixed(2);
}
/**
* Открытие модалки редактирования
* @param {string} cartKey - ключ товара в корзине
*/
function openModal(cartKey) {
const item = window.cart?.get(cartKey);
if (!item) {
console.error('CartItemEditor: Item not found for key:', cartKey);
return;
}
// Проверяем наличие модалки
const modalEl = document.getElementById('editCartItemModal');
if (!modalEl) {
console.error('CartItemEditor: Modal element not found!');
return;
}
editingCartKey = cartKey;
basePrice = parseFloat(item.price) || 0;
// Проверяем, является ли товар витринным комплектом
const isShowcaseKit = item.type === 'showcase_kit';
// Заполнение полей
document.getElementById('editModalProductName').textContent = item.name || '—';
// Используем formatMoney из terminal.js
const fmtMoney = typeof formatMoney === 'function' ? formatMoney : (v) => Number(v).toFixed(2);
document.getElementById('editModalBasePrice').textContent = fmtMoney(basePrice) + ' руб.';
document.getElementById('editModalPrice').value = roundPrice(basePrice);
document.getElementById('editModalQuantity').value = item.qty || 1;
// Для витринных комплектов блокируем изменение количества
const qtyInput = document.getElementById('editModalQuantity');
const qtyHint = document.getElementById('editModalQtyHint');
if (isShowcaseKit) {
qtyInput.disabled = true;
qtyHint.style.display = 'block';
} else {
qtyInput.disabled = false;
qtyHint.style.display = 'none';
}
// Бейдж единицы измерения
const unitBadge = document.getElementById('editModalUnitBadge');
if (item.unit_name) {
unitBadge.textContent = item.unit_name;
unitBadge.style.display = 'inline-block';
} else {
unitBadge.style.display = 'none';
}
updateTotal();
// Показ модалки
const modal = new bootstrap.Modal(modalEl);
modal.show();
console.log('CartItemEditor: Modal opened for', item.name);
}
/**
* Обновление суммы в модалке
*/
function updateTotal() {
const price = parseFloat(document.getElementById('editModalPrice').value) || 0;
const qty = parseFloat(document.getElementById('editModalQuantity').value) || 0;
const fmtMoney = typeof formatMoney === 'function' ? formatMoney : (v) => Number(v).toFixed(2);
document.getElementById('editModalTotal').textContent = fmtMoney(price * qty) + ' руб.';
// Индикатор изменения цены
const warning = document.getElementById('editModalPriceWarning');
if (Math.abs(price - basePrice) > 0.01) {
warning.style.display = 'block';
} else {
warning.style.display = 'none';
}
}
/**
* Сохранение изменений
*/
function saveChanges() {
if (!editingCartKey) return;
const newPrice = parseFloat(document.getElementById('editModalPrice').value) || 0;
const newQty = parseFloat(document.getElementById('editModalQuantity').value) || 1;
const item = window.cart?.get(editingCartKey);
if (item) {
// Используем roundQuantity из terminal.js
const rndQty = typeof roundQuantity === 'function' ? roundQuantity : (v, d) => Math.round(v * Math.pow(10, d)) / Math.pow(10, d);
const isShowcaseKit = item.type === 'showcase_kit';
item.price = newPrice;
// Для витринных комплектов не меняем количество
if (!isShowcaseKit) {
item.qty = rndQty(newQty, 3);
}
item.price_overridden = Math.abs(newPrice - basePrice) > 0.01;
window.cart.set(editingCartKey, item);
// Перерисовка корзины
if (typeof renderCart === 'function') {
renderCart();
}
// Сохранение на сервере
if (typeof saveCartToServer === 'function') {
saveCartToServer();
}
console.log('CartItemEditor: Changes saved for', item.name);
}
// Закрытие модалки
const modalEl = document.getElementById('editCartItemModal');
const modal = bootstrap.Modal.getInstance(modalEl);
if (modal) modal.hide();
}
/**
* Сброс состояния модалки
*/
function reset() {
editingCartKey = null;
basePrice = 0;
}
/**
* Инициализация модуля
*/
function init() {
const priceInput = document.getElementById('editModalPrice');
const qtyInput = document.getElementById('editModalQuantity');
const confirmBtn = document.getElementById('confirmEditCartItem');
if (!priceInput || !confirmBtn) {
console.warn('CartItemEditor: Required elements not found, deferring init...');
// Повторная попытка через короткое время
setTimeout(init, 100);
return;
}
console.log('CartItemEditor: Initialized successfully');
// Обновление суммы при изменении полей
priceInput.addEventListener('input', updateTotal);
qtyInput.addEventListener('input', updateTotal);
// Авто-выделение всего текста при фокусе
priceInput.addEventListener('focus', function() {
this.select();
});
qtyInput.addEventListener('focus', function() {
this.select();
});
// Кнопка сохранения
confirmBtn.addEventListener('click', saveChanges);
// Сброс при закрытии модалки
const modalEl = document.getElementById('editCartItemModal');
modalEl.addEventListener('hidden.bs.modal', reset);
// Enter для сохранения
priceInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') saveChanges();
});
qtyInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') saveChanges();
});
}
// Экспорт функций для использования из terminal.js
window.CartItemEditor = {
openModal: openModal,
init: init
};
console.log('CartItemEditor: Module loaded');
// Автоинициализация при загрузке
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();