diff --git a/myproject/pos/static/pos/js/products.js b/myproject/pos/static/pos/js/products.js
index 3622ce6..ed127a7 100644
--- a/myproject/pos/static/pos/js/products.js
+++ b/myproject/pos/static/pos/js/products.js
@@ -517,6 +517,47 @@ export class ProductManager {
* @private
*/
_renderShowcaseKitBadges(card, item, cart) {
+ // Кнопка редактирования (только если не заблокирован другим)
+ if (!item.is_locked || item.locked_by_me) {
+ const editBtn = document.createElement('button');
+ editBtn.className = 'btn btn-sm btn-outline-primary';
+ editBtn.style.position = 'absolute';
+ editBtn.style.top = '5px';
+ editBtn.style.right = '5px';
+ editBtn.style.zIndex = '10';
+ editBtn.innerHTML = '';
+ editBtn.title = 'Редактировать комплект';
+ editBtn.onclick = (e) => {
+ e.stopPropagation();
+ if (window.showcaseManager) {
+ window.showcaseManager.openEditModal(item.id);
+ }
+ };
+ card.appendChild(editBtn);
+
+ // Индикатор неактуальной цены (красный кружок)
+ if (item.price_outdated) {
+ const outdatedBadge = document.createElement('div');
+ outdatedBadge.className = 'badge bg-danger';
+ outdatedBadge.style.position = 'absolute';
+ outdatedBadge.style.top = '5px';
+ outdatedBadge.style.right = '45px';
+ outdatedBadge.style.zIndex = '10';
+ outdatedBadge.style.width = '18px';
+ outdatedBadge.style.height = '18px';
+ outdatedBadge.style.padding = '0';
+ outdatedBadge.style.borderRadius = '50%';
+ outdatedBadge.style.display = 'flex';
+ outdatedBadge.style.alignItems = 'center';
+ outdatedBadge.style.justifyContent = 'center';
+ outdatedBadge.style.fontSize = '10px';
+ outdatedBadge.style.minWidth = '18px';
+ outdatedBadge.title = 'Цена неактуальна';
+ outdatedBadge.innerHTML = '!';
+ card.appendChild(outdatedBadge);
+ }
+ }
+
// Индикация блокировки
if (item.is_locked) {
const lockBadge = document.createElement('div');
diff --git a/myproject/pos/static/pos/js/showcase.js b/myproject/pos/static/pos/js/showcase.js
index 62152a2..8284ed1 100644
--- a/myproject/pos/static/pos/js/showcase.js
+++ b/myproject/pos/static/pos/js/showcase.js
@@ -162,9 +162,9 @@ export class ShowcaseManager {
const key = `product-${item.product_id}-${item.sales_unit_id || 'base'}`;
this.tempCart.set(key, {
id: item.product_id,
- name: item.product_name,
- price: item.price,
- qty: item.quantity,
+ name: item.name || item.product_name, // Сервер отдаёт name
+ price: parseFloat(item.price) || 0,
+ qty: parseFloat(item.qty || item.quantity) || 1, // Сервер отдаёт qty
type: 'product',
sales_unit_id: item.sales_unit_id,
unit_name: item.unit_name
@@ -254,11 +254,26 @@ export class ShowcaseManager {
if (!select) return;
let html = '';
+ let defaultShowcaseId = null;
+
this.showcases.forEach(showcase => {
- html += ``;
+ const displayName = showcase.warehouse_name
+ ? `${showcase.name} (${showcase.warehouse_name})`
+ : showcase.name;
+ html += ``;
+
+ // Запоминаем витрину по умолчанию
+ if (showcase.is_default) {
+ defaultShowcaseId = showcase.id;
+ }
});
select.innerHTML = html;
+
+ // Автовыбор витрины по умолчанию (только в режиме создания)
+ if (!this.isEditMode && defaultShowcaseId) {
+ select.value = defaultShowcaseId;
+ }
}
/**
@@ -268,33 +283,83 @@ export class ShowcaseManager {
const container = document.getElementById('tempKitItemsList');
if (!container) return;
+ container.innerHTML = '';
+
if (this.tempCart.size === 0) {
container.innerHTML = '
-
-
${escapeHtml(item.name)}
-
- ${formatMoney(item.price)} × ${roundQuantity(item.qty)}
- ${item.unit_name ? ' ' + item.unit_name : ''}
-
-
-
${formatMoney(itemTotal)}
-
- `;
- });
+ const itemDiv = document.createElement('div');
+ itemDiv.className = 'd-flex justify-content-between align-items-center py-1 border-bottom';
- container.innerHTML = html;
+ // Левая часть: название и цена
+ const leftDiv = document.createElement('div');
+ leftDiv.className = 'flex-grow-1';
+
+ // Название товара
+ const nameDiv = document.createElement('div');
+ nameDiv.className = 'small';
+ nameDiv.textContent = item.name;
+ leftDiv.appendChild(nameDiv);
+
+ // Контейнер цены с полем ввода
+ const priceContainer = document.createElement('div');
+ priceContainer.className = 'text-muted d-flex align-items-center';
+ priceContainer.style.fontSize = '0.75rem';
+ priceContainer.style.gap = '4px';
+
+ // Поле ввода цены (всегда видимое, без стрелочек)
+ const priceInput = document.createElement('input');
+ priceInput.type = 'text';
+ priceInput.inputMode = 'decimal';
+ priceInput.className = 'form-control form-control-sm';
+ priceInput.style.width = '70px';
+ priceInput.style.padding = '2px 4px';
+ priceInput.style.textAlign = 'right';
+ priceInput.value = formatMoney(item.price);
+
+ // Сохранение цены при изменении
+ const savePrice = () => {
+ const newPrice = parseFloat(priceInput.value.replace(',', '.')) || 0;
+ if (item.price !== newPrice) {
+ item.price = newPrice;
+ this.renderTempKitItems();
+ this.updatePriceCalculation();
+ }
+ };
+
+ priceInput.onblur = savePrice;
+ priceInput.onkeydown = (e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ priceInput.blur();
+ }
+ };
+ priceInput.onfocus = () => priceInput.select();
+
+ priceContainer.appendChild(priceInput);
+ priceContainer.appendChild(document.createTextNode(`× ${roundQuantity(item.qty)}`));
+ if (item.unit_name) {
+ priceContainer.appendChild(document.createTextNode(` ${item.unit_name}`));
+ }
+ leftDiv.appendChild(priceContainer);
+
+ // Правая часть: итоговая сумма
+ const rightDiv = document.createElement('div');
+ rightDiv.className = 'fw-semibold small';
+ rightDiv.textContent = formatMoney(itemTotal);
+
+ itemDiv.appendChild(leftDiv);
+ itemDiv.appendChild(rightDiv);
+ container.appendChild(itemDiv);
+ });
// Обновляем базовую цену
document.getElementById('tempKitBasePrice').textContent = formatMoney(totalBasePrice) + ' руб.';
@@ -384,8 +449,11 @@ export class ShowcaseManager {
* Сбрасывает форму
*/
resetForm() {
- document.getElementById('tempKitName').value = '';
- document.getElementById('showcaseSelect').value = '';
+ // Генерируем название по умолчанию
+ const randomSuffix = Math.floor(Math.random() * 900) + 100;
+ const defaultName = `Витринный букет ${randomSuffix}`;
+ document.getElementById('tempKitName').value = defaultName;
+ // Не сбрасываем showcaseSelect - витрина по умолчанию выбирается в renderShowcaseSelect()
document.getElementById('showcaseKitQuantity').value = '1';
document.getElementById('tempKitDescription').value = '';
document.getElementById('showcaseCreatedAt').value = '';
@@ -463,7 +531,7 @@ export class ShowcaseManager {
// Формируем данные для отправки
const formData = new FormData();
- formData.append('name', data.name);
+ formData.append('kit_name', data.name); // Сервер ожидает kit_name
formData.append('showcase_id', data.showcaseId);
formData.append('description', data.description || '');
formData.append('showcase_created_at', data.createdAt || '');
diff --git a/myproject/pos/static/pos/js/terminal.js b/myproject/pos/static/pos/js/terminal.js
index 62e185a..1702c0e 100644
--- a/myproject/pos/static/pos/js/terminal.js
+++ b/myproject/pos/static/pos/js/terminal.js
@@ -157,6 +157,7 @@ document.addEventListener('DOMContentLoaded', () => {
// Глобальные ссылки для обратной совместимости с cart-item-editor.js
window.cart = cart;
window.renderCart = renderCart;
+ window.showcaseManager = showcaseManager;
});
// ===== РЕНДЕРИНГ КАТЕГОРИЙ =====