Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function () { | |
| const productForm = document.getElementById('productForm'); | |
| const productTable = document.getElementById('productTable').getElementsByTagName('tbody')[0]; | |
| const searchInput = document.getElementById('searchInput'); | |
| const cartTable = document.getElementById('cartTable').getElementsByTagName('tbody')[0]; | |
| const totalSoldElement = document.getElementById('totalSold'); | |
| const totalRevenueElement = document.getElementById('totalRevenue'); | |
| const totalProfitElement = document.getElementById('totalProfit'); | |
| let totalSold = 0; // Общее количество проданных товаров | |
| let totalRevenue = 0; // Общая выручка | |
| let totalProfit = 0; // Общая прибыль | |
| let cart = []; // Корзина | |
| // Массив для хранения чеков | |
| let receipts = JSON.parse(localStorage.getItem('receipts')) || []; | |
| // Загрузка данных из localStorage при загрузке страницы | |
| loadProducts(); | |
| loadStats(); | |
| loadCart(); | |
| updateReceiptsList(); | |
| // Обработка добавления товара | |
| productForm.addEventListener('submit', function (e) { | |
| e.preventDefault(); | |
| const productName = document.getElementById('productName').value.trim(); | |
| const purchasePrice = parseFloat(document.getElementById('purchasePrice').value); | |
| const wholesalePrice = parseFloat(document.getElementById('wholesalePrice').value) || null; | |
| const retailPrice = parseFloat(document.getElementById('retailPrice').value) || null; | |
| const quantity = parseInt(document.getElementById('quantity').value); | |
| const itemsPerPack = parseInt(document.getElementById('itemsPerPack').value); | |
| // Проверка обязательных полей | |
| if (!productName || isNaN(purchasePrice) || isNaN(quantity) || isNaN(itemsPerPack)) { | |
| alert('Пожалуйста, заполните все обязательные поля корректно.'); | |
| return; | |
| } | |
| // Добавляем товар | |
| addProduct(productName, purchasePrice, wholesalePrice, retailPrice, quantity, itemsPerPack); | |
| productForm.reset(); // Очистка формы после добавления | |
| }); | |
| // Поиск по товарам | |
| searchInput.addEventListener('input', function () { | |
| const searchTerm = searchInput.value.toLowerCase(); | |
| const rows = productTable.getElementsByTagName('tr'); | |
| for (let row of rows) { | |
| const name = row.getElementsByTagName('td')[0]?.textContent.toLowerCase(); | |
| if (name) { | |
| row.style.display = name.includes(searchTerm) ? '' : 'none'; | |
| } | |
| } | |
| }); | |
| // Делегирование событий для кнопок в таблице товаров | |
| productTable.addEventListener('click', function (e) { | |
| const target = e.target; | |
| const row = target.closest('tr'); | |
| const productId = parseInt(row.getAttribute('data-id')); | |
| if (target.classList.contains('add-to-cart-btn')) { | |
| const quantityInput = row.querySelector('.quantity-input'); | |
| const quantity = parseInt(quantityInput.value); | |
| const isWholesale = row.querySelector('.wholesale-checkbox').checked; // Проверяем галочку | |
| if (quantity && quantity > 0) { | |
| addToCart(productId, quantity, isWholesale); | |
| } else { | |
| alert('Пожалуйста, введите корректное количество.'); | |
| } | |
| } else if (target.classList.contains('add-stock-btn')) { | |
| addStock(productId); | |
| } else if (target.classList.contains('delete-btn')) { | |
| deleteProduct(productId); | |
| } | |
| }); | |
| // Делегирование событий для кнопок в корзине | |
| cartTable.addEventListener('click', function (e) { | |
| const target = e.target; | |
| if (target.classList.contains('delete-btn')) { | |
| const row = target.closest('tr'); | |
| const productId = parseInt(row.getAttribute('data-id')); | |
| removeFromCart(productId); | |
| } | |
| }); | |
| // Функция добавления товара | |
| function addProduct(name, purchasePrice, wholesalePrice, retailPrice, quantity, itemsPerPack) { | |
| const product = { | |
| id: Date.now(), // Уникальный ID на основе времени | |
| name, | |
| purchasePrice, | |
| wholesalePrice, | |
| retailPrice, | |
| quantity, | |
| itemsPerPack | |
| }; | |
| // Получаем текущие товары из localStorage | |
| let products = JSON.parse(localStorage.getItem('products')) || []; | |
| products.push(product); // Добавляем новый товар | |
| localStorage.setItem('products', JSON.stringify(products)); // Сохраняем в localStorage | |
| // Добавляем товар в таблицу | |
| addProductToTable(product); | |
| } | |
| // Функция добавления товара в таблицу | |
| function addProductToTable(product) { | |
| const row = productTable.insertRow(); | |
| row.setAttribute('data-id', product.id); | |
| row.innerHTML = ` | |
| <td>${product.name}</td> | |
| <td>${product.purchasePrice}</td> | |
| <td>${product.wholesalePrice || '—'}</td> | |
| <td>${product.retailPrice || '—'}</td> | |
| <td>${product.quantity}</td> | |
| <td>${product.itemsPerPack}</td> | |
| <td class="actions"> | |
| <input type="number" min="1" max="${product.quantity}" class="quantity-input" placeholder="Количество"> | |
| <label> | |
| <input type="checkbox" class="wholesale-checkbox"> Опт | |
| </label> | |
| <button class="add-to-cart-btn">Добавить в корзину</button> | |
| <button class="add-stock-btn">Приход</button> | |
| <button class="delete-btn">Удалить</button> | |
| </td> | |
| `; | |
| } | |
| // Функция загрузки товаров из localStorage | |
| function loadProducts() { | |
| const products = JSON.parse(localStorage.getItem('products')) || []; | |
| productTable.innerHTML = ''; // Очищаем таблицу перед загрузкой | |
| products.forEach(product => addProductToTable(product)); | |
| } | |
| // Функция загрузки статистики из localStorage | |
| function loadStats() { | |
| const stats = JSON.parse(localStorage.getItem('stats')) || { totalSold: 0, totalRevenue: 0, totalProfit: 0 }; | |
| totalSold = stats.totalSold; | |
| totalRevenue = stats.totalRevenue; | |
| totalProfit = stats.totalProfit; | |
| updateStatsDisplay(); | |
| } | |
| // Функция загрузки корзины из localStorage | |
| function loadCart() { | |
| cart = JSON.parse(localStorage.getItem('cart')) || []; | |
| updateCartDisplay(); | |
| } | |
| // Функция обновления отображения статистики | |
| function updateStatsDisplay() { | |
| totalSoldElement.textContent = totalSold; | |
| totalRevenueElement.textContent = totalRevenue.toFixed(2); | |
| totalProfitElement.textContent = totalProfit.toFixed(2); | |
| } | |
| // Функция обновления отображения корзины | |
| function updateCartDisplay() { | |
| cartTable.innerHTML = ''; // Очищаем корзину перед обновлением | |
| cart.forEach(item => { | |
| const row = cartTable.insertRow(); | |
| row.setAttribute('data-id', item.id); | |
| row.innerHTML = ` | |
| <td>${item.name}</td> | |
| <td>${item.quantity}</td> | |
| <td>${item.salePrice}</td> | |
| <td>${item.saleType}</td> | |
| <td>${item.quantity * item.salePrice}</td> | |
| <td><button class="delete-btn">Удалить</button></td> | |
| `; | |
| }); | |
| } | |
| // Функция добавления товара в корзину | |
| function addToCart(productId, quantity, isWholesale) { | |
| const products = JSON.parse(localStorage.getItem('products')) || []; | |
| const product = products.find(p => p.id === productId); | |
| if (product && product.quantity >= quantity) { | |
| const saleType = isWholesale ? 'опт' : 'розница'; | |
| const price = isWholesale ? product.wholesalePrice : product.retailPrice; | |
| if (!price) { | |
| alert(`Цена для типа продажи "${saleType}" не указана.`); | |
| return; | |
| } | |
| const cartItem = cart.find(item => item.id === productId && item.saleType === saleType); | |
| if (cartItem) { | |
| cartItem.quantity += quantity; | |
| } else { | |
| cart.push({ | |
| id: productId, | |
| name: product.name, | |
| salePrice: price, | |
| purchasePrice: product.purchasePrice, | |
| quantity: quantity, | |
| itemsPerPack: product.itemsPerPack, // Добавляем количество штук в пачке | |
| saleType: saleType | |
| }); | |
| } | |
| localStorage.setItem('cart', JSON.stringify(cart)); | |
| updateCartDisplay(); | |
| } else { | |
| alert('Недостаточно товара на складе.'); | |
| } | |
| } | |
| // Функция удаления товара из корзины | |
| function removeFromCart(productId) { | |
| cart = cart.filter(item => item.id !== productId); | |
| localStorage.setItem('cart', JSON.stringify(cart)); | |
| updateCartDisplay(); | |
| } | |
| // Функция продажи товаров из корзины | |
| window.sellCart = function () { | |
| if (cart.length === 0) { | |
| alert('Корзина пуста.'); | |
| return; | |
| } | |
| // Получаем сумму скидки | |
| const discountInput = document.getElementById('discountInput'); | |
| const discount = parseFloat(discountInput.value) || 0; // Если скидка не указана, считаем её равной 0 | |
| // Получаем текущую дату и время по бишкекскому времени | |
| const now = new Date(); | |
| const options = { timeZone: 'Asia/Bishkek', year: 'numeric', month: 'long', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit' }; | |
| const receiptDateTime = now.toLocaleString('ru-RU', options); | |
| // Создаем чек | |
| const receipt = { | |
| dateTime: receiptDateTime, | |
| items: cart.map(item => ({ | |
| name: item.name, | |
| quantity: item.quantity, | |
| salePrice: item.salePrice, | |
| purchasePrice: item.purchasePrice, | |
| itemsPerPack: item.itemsPerPack, // Добавляем количество штук в пачке | |
| saleType: item.saleType | |
| })), | |
| discount: discount | |
| }; | |
| // Отображаем чек в модальном окне | |
| openReceiptForConfirmation(receipt); | |
| }; | |
| // Функция для открытия модального окна с подтверждением продажи | |
| function openReceiptForConfirmation(receipt) { | |
| const modal = document.getElementById('receiptModal'); | |
| const receiptTable = document.getElementById('receiptTable').getElementsByTagName('tbody')[0]; | |
| // Заполняем дату и время | |
| document.getElementById('receiptDateTime').textContent = receipt.dateTime; | |
| // Заполняем таблицу товаров | |
| receiptTable.innerHTML = ''; | |
| let totalAmount = 0; | |
| receipt.items.forEach(item => { | |
| const row = receiptTable.insertRow(); | |
| row.innerHTML = ` | |
| <td>${item.name}</td> | |
| <td>${item.quantity} (${item.itemsPerPack} шт/уп)</td> | |
| <td>${item.salePrice} (${item.saleType})</td> | |
| <td>${item.quantity * item.salePrice}</td> | |
| `; | |
| totalAmount += item.quantity * item.salePrice; | |
| }); | |
| // Отображаем общую сумму, скидку и итоговую сумму | |
| document.getElementById('receiptTotal').textContent = totalAmount.toFixed(2); | |
| document.getElementById('receiptDiscount').textContent = receipt.discount.toFixed(2); | |
| document.getElementById('receiptFinalTotal').textContent = (totalAmount - receipt.discount).toFixed(2); | |
| // Показываем кнопку "Подтвердить" для завершения продажи | |
| document.getElementById('confirmSaleBtn').style.display = 'inline-block'; | |
| // Показываем модальное окно | |
| modal.style.display = 'flex'; | |
| // Обработчик для кнопки "Подтвердить" | |
| document.getElementById('confirmSaleBtn').onclick = function () { | |
| // Обновляем остатки на складе | |
| updateStockAfterSale(receipt); | |
| // Обновляем статистику | |
| updateStatistics(receipt); | |
| // Сохраняем чек | |
| saveReceipt(receipt); | |
| // Очищаем корзину | |
| cart = []; | |
| localStorage.setItem('cart', JSON.stringify(cart)); | |
| updateCartDisplay(); | |
| // Скрываем модальное окно | |
| modal.style.display = 'none'; | |
| alert('Продажа успешно завершена!'); | |
| }; | |
| // Обработчик для кнопки "Отмена" | |
| document.getElementById('cancelSaleBtn').onclick = function () { | |
| modal.style.display = 'none'; // Скрываем модальное окно | |
| }; | |
| // Обработчик для закрытия модального окна (крестик) | |
| document.querySelector('.modal .close').onclick = function () { | |
| modal.style.display = 'none'; // Скрываем модальное окно | |
| }; | |
| } | |
| // Функция для уменьшения остатков на складе после продажи | |
| function updateStockAfterSale(receipt) { | |
| let products = JSON.parse(localStorage.getItem('products')) || []; | |
| receipt.items.forEach(item => { | |
| const product = products.find(p => p.name === item.name); | |
| if (product) { | |
| product.quantity -= item.quantity; // Уменьшаем количество товара на складе | |
| // Если остаток стал меньше 0, устанавливаем его в 0 | |
| if (product.quantity < 0) { | |
| product.quantity = 0; | |
| } | |
| } | |
| }); | |
| // Сохраняем обновленные товары | |
| localStorage.setItem('products', JSON.stringify(products)); | |
| // Обновляем таблицу товаров | |
| productTable.innerHTML = ''; | |
| loadProducts(); | |
| } | |
| // Функция для сохранения чека | |
| function saveReceipt(receipt) { | |
| receipts.push(receipt); | |
| localStorage.setItem('receipts', JSON.stringify(receipts)); | |
| updateReceiptsList(); | |
| } | |
| // Функция для обновления списка чеков | |
| function updateReceiptsList(receiptsToShow = receipts) { | |
| const receiptsList = document.getElementById('receiptsList'); | |
| receiptsList.innerHTML = ''; // Очищаем список перед обновлением | |
| receiptsToShow.forEach((receipt, index) => { | |
| const receiptItem = document.createElement('div'); | |
| receiptItem.className = 'receipt-item'; | |
| receiptItem.textContent = `Чек от ${receipt.dateTime}`; | |
| receiptItem.onclick = () => openReceipt(index); | |
| receiptsList.appendChild(receiptItem); | |
| }); | |
| } | |
| // Функция для открытия чека (из отчетов) | |
| function openReceipt(index) { | |
| const receipt = receipts[index]; | |
| const modal = document.getElementById('receiptModal'); | |
| const receiptTable = document.getElementById('receiptTable').getElementsByTagName('tbody')[0]; | |
| // Заполняем дату и время | |
| document.getElementById('receiptDateTime').textContent = receipt.dateTime; | |
| // Заполняем таблицу товаров | |
| receiptTable.innerHTML = ''; | |
| let totalAmount = 0; | |
| receipt.items.forEach(item => { | |
| const row = receiptTable.insertRow(); | |
| row.innerHTML = ` | |
| <td>${item.name}</td> | |
| <td>${item.quantity} (${item.itemsPerPack} шт/уп)</td> | |
| <td>${item.salePrice} (${item.saleType})</td> | |
| <td>${item.quantity * item.salePrice}</td> | |
| `; | |
| totalAmount += item.quantity * item.salePrice; | |
| }); | |
| // Отображаем общую сумму, скидку и итоговую сумму | |
| document.getElementById('receiptTotal').textContent = totalAmount.toFixed(2); | |
| document.getElementById('receiptDiscount').textContent = receipt.discount.toFixed(2); | |
| document.getElementById('receiptFinalTotal').textContent = (totalAmount - receipt.discount).toFixed(2); | |
| // Убираем кнопку "Подтвердить" при просмотре чека (для отчетов) | |
| document.getElementById('confirmSaleBtn').style.display = 'none'; | |
| // Показываем модальное окно | |
| modal.style.display = 'flex'; | |
| } | |
| // Функция для обновления статистики | |
| function updateStatistics(receipt) { | |
| receipt.items.forEach(item => { | |
| totalSold += item.quantity; | |
| totalRevenue += item.quantity * item.salePrice; | |
| // Прибыль = (отпускная цена - приходная цена) * количество | |
| const purchasePrice = item.purchasePrice || 0; // Если purchasePrice отсутствует, считаем его равным 0 | |
| totalProfit += item.quantity * (item.salePrice - purchasePrice); | |
| }); | |
| // Вычитаем скидку из прибыли | |
| totalProfit -= receipt.discount; | |
| // Сохраняем обновленные данные | |
| localStorage.setItem('stats', JSON.stringify({ totalSold, totalRevenue, totalProfit })); | |
| updateStatsDisplay(); | |
| } | |
| // Функция добавления остатков | |
| function addStock(productId) { | |
| const quantityToAdd = prompt('Введите количество для прихода:'); | |
| if (quantityToAdd && !isNaN(quantityToAdd) && quantityToAdd > 0) { | |
| let products = JSON.parse(localStorage.getItem('products')) || []; | |
| const productIndex = products.findIndex(p => p.id === productId); | |
| if (productIndex !== -1) { | |
| products[productIndex].quantity += parseInt(quantityToAdd); | |
| localStorage.setItem('products', JSON.stringify(products)); | |
| // Обновляем таблицу | |
| productTable.innerHTML = ''; | |
| loadProducts(); | |
| } | |
| } else { | |
| alert('Пожалуйста, введите корректное количество.'); | |
| } | |
| } | |
| // Функция удаления товара | |
| function deleteProduct(productId) { | |
| if (confirm('Вы уверены, что хотите удалить этот товар?')) { | |
| let products = JSON.parse(localStorage.getItem('products')) || []; | |
| products = products.filter(p => p.id !== productId); | |
| localStorage.setItem('products', JSON.stringify(products)); | |
| // Обновляем таблицу | |
| productTable.innerHTML = ''; | |
| loadProducts(); | |
| } | |
| } | |
| // Функция для переключения бургер-меню | |
| window.toggleMenu = function () { | |
| const menuItems = document.querySelector('.menu-items'); | |
| menuItems.style.display = menuItems.style.display === 'block' ? 'none' : 'block'; | |
| }; | |
| // Функция для отображения выбранного раздела | |
| window.showSection = function (sectionId) { | |
| // Скрываем все колонки | |
| document.querySelectorAll('.column').forEach(column => { | |
| column.classList.remove('active'); | |
| }); | |
| // Показываем выбранную колонку | |
| document.getElementById(sectionId).classList.add('active'); | |
| // Скрываем меню после выбора | |
| document.querySelector('.menu-items').style.display = 'none'; | |
| }; | |
| // Функция для фильтрации чеков по дате | |
| window.filterReceiptsByDate = function () { | |
| const filterDateInput = document.getElementById('filterDateInput'); | |
| const filterDate = filterDateInput.value; // Получаем выбранную дату | |
| if (!filterDate) { | |
| alert('Пожалуйста, выберите дату для фильтрации.'); | |
| return; | |
| } | |
| // Фильтруем чеки по выбранной дате | |
| const filteredReceipts = receipts.filter(receipt => { | |
| const receiptDate = new Date(receipt.dateTime).toISOString().split('T')[0]; // Получаем дату чека | |
| return receiptDate === filterDate; // Сравниваем с выбранной датой | |
| }); | |
| // Обновляем список чеков | |
| updateReceiptsList(filteredReceipts); | |
| }; | |
| // Функция для сброса фильтрации | |
| window.clearDateFilter = function () { | |
| document.getElementById('filterDateInput').value = ''; // Очищаем поле ввода даты | |
| updateReceiptsList(receipts); // Показываем все чеки | |
| }; | |
| // Показываем Инвентарь по умолчанию | |
| showSection('inventory'); | |
| }); |