Add files via upload

v1.3.0
This commit is contained in:
cyrteL
2025-07-28 18:24:57 +03:00
committed by GitHub
parent bd7afd54b5
commit e572c34e99
13 changed files with 632 additions and 248 deletions

View File

@ -175,24 +175,108 @@ class AuthSystem {
}
}
// Обновление прав доступа для кнопок
// Обновление прав доступа для кнопок и элементов интерфейса
updateButtonPermissions() {
// Кнопки, доступные только администраторам
const adminButtons = [
// Элементы, доступные только администраторам
const adminElements = [
'#addItemBtn',
'#editItemBtn',
'#editItemBtn',
'#deleteItemBtn',
'#manageUsersBtn'
'#manageUsersBtn',
'.admin-only',
'[data-role="admin"]'
];
adminButtons.forEach(buttonId => {
// Элементы, доступные администраторам и менеджерам
const managerElements = [
'.manager-or-admin',
'[data-role="manager"]',
'#addCategoryBtn',
'#editCategoryBtn'
];
// Элементы, доступные всем авторизованным пользователям
const authenticatedElements = [
'.authenticated-only',
'[data-role="authenticated"]',
'#exportBtn',
'#searchBtn'
];
// Скрываем/показываем элементы для администраторов
adminElements.forEach(selector => {
const elements = $(selector);
elements.each((index, element) => {
const $element = $(element);
if (this.hasRole('admin')) {
$element.show();
$element.prop('disabled', false);
} else {
$element.hide();
$element.prop('disabled', true);
}
});
});
// Скрываем/показываем элементы для менеджеров и администраторов
managerElements.forEach(selector => {
const elements = $(selector);
elements.each((index, element) => {
const $element = $(element);
if (this.hasRole('admin') || this.hasRole('manager')) {
$element.show();
$element.prop('disabled', false);
} else {
$element.hide();
$element.prop('disabled', true);
}
});
});
// Скрываем/показываем элементы для авторизованных пользователей
authenticatedElements.forEach(selector => {
const elements = $(selector);
elements.each((index, element) => {
const $element = $(element);
if (this.isUserAuthenticated()) {
$element.show();
$element.prop('disabled', false);
} else {
$element.hide();
$element.prop('disabled', true);
}
});
});
// Специальная обработка для кнопок с подсказками
this.updateButtonTooltips();
}
// Обновление подсказок для кнопок
updateButtonTooltips() {
// Кнопки с подсказками о правах доступа
const buttonPermissions = {
'#addItemBtn': { roles: ['admin', 'manager'], message: 'Требуются права администратора или менеджера' },
'#editItemBtn': { roles: ['admin', 'manager'], message: 'Требуются права администратора или менеджера' },
'#deleteItemBtn': { roles: ['admin'], message: 'Требуются права администратора' },
'#addCategoryBtn': { roles: ['admin', 'manager'], message: 'Требуются права администратора или менеджера' },
'#editCategoryBtn': { roles: ['admin', 'manager'], message: 'Требуются права администратора или менеджера' },
'#deleteCategoryBtn': { roles: ['admin'], message: 'Требуются права администратора' },
'#exportBtn': { roles: ['admin', 'manager', 'operator', 'viewer'], message: 'Требуется авторизация' }
};
Object.keys(buttonPermissions).forEach(buttonId => {
const button = $(buttonId);
if (button.length) {
if (this.hasRole('admin')) {
const permission = buttonPermissions[buttonId];
const hasAccess = permission.roles.some(role => this.hasRole(role));
if (hasAccess) {
button.prop('disabled', false);
button.removeAttr('title');
} else {
button.prop('disabled', true);
button.attr('title', 'Требуются права администратора');
button.attr('title', permission.message);
}
}
});

View File

@ -130,11 +130,6 @@ class CatalogManager {
// Заполнение фильтра категорий
populateCategoryFilters(categories) {
if (!categories || categories.length === 0) {
console.warn('Нет категорий для отображения');
return;
}
const categoryFilter = $('#categoryFilter');
const addItemCategory = $('#itemCategory');
const editItemCategory = $('#editItemCategory');
@ -144,15 +139,23 @@ class CatalogManager {
addItemCategory.find('option:not(:first)').remove();
editItemCategory.find('option:not(:first)').remove();
// Добавляем опцию "Без категории"
const uncategorizedOption = `<option value="uncategorized">Без категории</option>`;
categoryFilter.append(uncategorizedOption);
addItemCategory.append(uncategorizedOption);
editItemCategory.append(uncategorizedOption);
// Добавляем категории
categories.forEach(category => {
if (category && category.id && category.name) {
const option = `<option value="${category.id}">${category.name}</option>`;
categoryFilter.append(option);
addItemCategory.append(option);
editItemCategory.append(option);
}
});
if (categories && categories.length > 0) {
categories.forEach(category => {
if (category && category.id && category.name) {
const option = `<option value="${category.id}">${category.name}</option>`;
categoryFilter.append(option);
addItemCategory.append(option);
editItemCategory.append(option);
}
});
}
}
// Обработка поиска
@ -441,8 +444,8 @@ class CatalogManager {
// Получение информации о категории
getCategoryInfo(categoryId) {
if (!categoryId) {
return { id: 'unknown', name: 'Без категории', icon: 'fas fa-box' };
if (!categoryId || categoryId === 'uncategorized') {
return { id: 'uncategorized', name: 'Без категории', icon: 'fas fa-box' };
}
// Используем категории из warehouse
@ -723,6 +726,9 @@ class CatalogManager {
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
// Обновляем права доступа для элементов интерфейса
auth.updateButtonPermissions();
}
// Загрузка категорий в навигацию
@ -755,18 +761,8 @@ class CatalogManager {
// Обновление прав доступа
updatePermissions() {
const user = auth.getCurrentUser();
if (!user) return;
// Показываем кнопку добавления для администраторов и менеджеров
if (auth.hasRole('admin') || auth.hasRole('manager')) {
$('#addItemBtn').show();
} else {
$('#addItemBtn').hide();
}
// Показываем кнопку экспорта для всех авторизованных пользователей
$('#exportBtn').show();
// Используем централизованную систему управления правами из auth.js
auth.updateButtonPermissions();
}
// Загрузка категорий в выпадающее меню
@ -781,21 +777,60 @@ class CatalogManager {
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const isEmpty = category.itemCount === 0;
const categoryLink = `
<li>
<a class="dropdown-item" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
<a class="dropdown-item ${isEmpty ? 'empty-category' : ''}" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<div class="category-info">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
<span>${category.name}</span>
</div>
<span class="category-count">${category.itemCount || 0}</span>
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
// Инициализируем hover-функциональность
this.initHoverDropdown();
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
// Инициализация hover-функциональности для выпадающего меню
initHoverDropdown() {
const $dropdown = $('.nav-item.dropdown');
const $dropdownMenu = $dropdown.find('.dropdown-menu');
let hoverTimeout;
// Показываем меню при наведении
$dropdown.on('mouseenter', function() {
clearTimeout(hoverTimeout);
$(this).find('.dropdown-menu').addClass('show');
});
// Скрываем меню при уходе мыши
$dropdown.on('mouseleave', function() {
const $menu = $(this).find('.dropdown-menu');
hoverTimeout = setTimeout(() => {
$menu.removeClass('show');
}, 150); // Небольшая задержка для плавности
});
// Предотвращаем скрытие при наведении на само меню
$dropdownMenu.on('mouseenter', function() {
clearTimeout(hoverTimeout);
});
$dropdownMenu.on('mouseleave', function() {
hoverTimeout = setTimeout(() => {
$(this).removeClass('show');
}, 150);
});
}
// Обработка параметра категории из URL
handleCategoryFromUrl() {

View File

@ -350,13 +350,22 @@ class CategoryManager {
$('#currentUserInfo').text(user.name);
$('#loginLink').hide();
$('#profileDropdown').show();
$('#adminDropdown').show();
// Показываем админ панель только для администраторов
if (auth.hasRole('admin')) {
$('#adminDropdown').show();
} else {
$('#adminDropdown').hide();
}
} else {
$('#currentUserInfo').text('Гость');
$('#loginLink').show();
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
// Обновляем права доступа для элементов интерфейса
auth.updateButtonPermissions();
}
// Загрузка категорий в выпадающее меню
@ -371,21 +380,60 @@ class CategoryManager {
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const isEmpty = category.itemCount === 0;
const categoryLink = `
<li>
<a class="dropdown-item" href="../catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
<a class="dropdown-item ${isEmpty ? 'empty-category' : ''}" href="../catalog.html?category=${category.id}" title="${category.description || ''}">
<div class="category-info">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
<span>${category.name}</span>
</div>
<span class="category-count">${category.itemCount || 0}</span>
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
// Инициализируем hover-функциональность
this.initHoverDropdown();
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
// Инициализация hover-функциональности для выпадающего меню
initHoverDropdown() {
const $dropdown = $('.nav-item.dropdown');
const $dropdownMenu = $dropdown.find('.dropdown-menu');
let hoverTimeout;
// Показываем меню при наведении
$dropdown.on('mouseenter', function() {
clearTimeout(hoverTimeout);
$(this).find('.dropdown-menu').addClass('show');
});
// Скрываем меню при уходе мыши
$dropdown.on('mouseleave', function() {
const $menu = $(this).find('.dropdown-menu');
hoverTimeout = setTimeout(() => {
$menu.removeClass('show');
}, 150); // Небольшая задержка для плавности
});
// Предотвращаем скрытие при наведении на само меню
$dropdownMenu.on('mouseenter', function() {
clearTimeout(hoverTimeout);
});
$dropdownMenu.on('mouseleave', function() {
hoverTimeout = setTimeout(() => {
$(this).removeClass('show');
}, 150);
});
}
}
// Инициализация при загрузке страницы

View File

@ -658,13 +658,22 @@ class HistoryManager {
$('#currentUserInfo').text(user.name);
$('#loginLink').hide();
$('#profileDropdown').show();
$('#adminDropdown').show();
// Показываем админ панель только для администраторов
if (auth.hasRole('admin')) {
$('#adminDropdown').show();
} else {
$('#adminDropdown').hide();
}
} else {
$('#currentUserInfo').text('Гость');
$('#loginLink').show();
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
// Обновляем права доступа для элементов интерфейса
auth.updateButtonPermissions();
}
// Загрузка категорий в навигацию
@ -707,21 +716,60 @@ class HistoryManager {
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const isEmpty = category.itemCount === 0;
const categoryLink = `
<li>
<a class="dropdown-item" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
<a class="dropdown-item ${isEmpty ? 'empty-category' : ''}" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<div class="category-info">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
<span>${category.name}</span>
</div>
<span class="category-count">${category.itemCount || 0}</span>
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
// Инициализируем hover-функциональность
this.initHoverDropdown();
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
// Инициализация hover-функциональности для выпадающего меню
initHoverDropdown() {
const $dropdown = $('.nav-item.dropdown');
const $dropdownMenu = $dropdown.find('.dropdown-menu');
let hoverTimeout;
// Показываем меню при наведении
$dropdown.on('mouseenter', function() {
clearTimeout(hoverTimeout);
$(this).find('.dropdown-menu').addClass('show');
});
// Скрываем меню при уходе мыши
$dropdown.on('mouseleave', function() {
const $menu = $(this).find('.dropdown-menu');
hoverTimeout = setTimeout(() => {
$menu.removeClass('show');
}, 150); // Небольшая задержка для плавности
});
// Предотвращаем скрытие при наведении на само меню
$dropdownMenu.on('mouseenter', function() {
clearTimeout(hoverTimeout);
});
$dropdownMenu.on('mouseleave', function() {
hoverTimeout = setTimeout(() => {
$(this).removeClass('show');
}, 150);
});
}
}
// Инициализация менеджера истории

View File

@ -494,6 +494,9 @@ class MainApp {
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
// Обновляем права доступа для элементов интерфейса
auth.updateButtonPermissions();
}
// Загрузка категорий в навигацию
@ -536,21 +539,60 @@ class MainApp {
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const isEmpty = category.itemCount === 0;
const categoryLink = `
<li>
<a class="dropdown-item" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
<a class="dropdown-item ${isEmpty ? 'empty-category' : ''}" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<div class="category-info">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
<span>${category.name}</span>
</div>
<span class="category-count">${category.itemCount || 0}</span>
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
// Инициализируем hover-функциональность
this.initHoverDropdown();
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
// Инициализация hover-функциональности для выпадающего меню
initHoverDropdown() {
const $dropdown = $('.nav-item.dropdown');
const $dropdownMenu = $dropdown.find('.dropdown-menu');
let hoverTimeout;
// Показываем меню при наведении
$dropdown.on('mouseenter', function() {
clearTimeout(hoverTimeout);
$(this).find('.dropdown-menu').addClass('show');
});
// Скрываем меню при уходе мыши
$dropdown.on('mouseleave', function() {
const $menu = $(this).find('.dropdown-menu');
hoverTimeout = setTimeout(() => {
$menu.removeClass('show');
}, 150); // Небольшая задержка для плавности
});
// Предотвращаем скрытие при наведении на само меню
$dropdownMenu.on('mouseenter', function() {
clearTimeout(hoverTimeout);
});
$dropdownMenu.on('mouseleave', function() {
hoverTimeout = setTimeout(() => {
$(this).removeClass('show');
}, 150);
});
}
}
// Инициализация приложения

View File

@ -469,13 +469,22 @@ class ProfileManager {
$('#currentUserInfo').text(user.name);
$('#loginLink').hide();
$('#profileDropdown').show();
$('#adminDropdown').show();
// Показываем админ панель только для администраторов
if (auth.hasRole('admin')) {
$('#adminDropdown').show();
} else {
$('#adminDropdown').hide();
}
} else {
$('#currentUserInfo').text('Гость');
$('#loginLink').show();
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
// Обновляем права доступа для элементов интерфейса
auth.updateButtonPermissions();
}
// Загрузка категорий в навигацию
@ -518,21 +527,60 @@ class ProfileManager {
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const isEmpty = category.itemCount === 0;
const categoryLink = `
<li>
<a class="dropdown-item" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
<a class="dropdown-item ${isEmpty ? 'empty-category' : ''}" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<div class="category-info">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
<span>${category.name}</span>
</div>
<span class="category-count">${category.itemCount || 0}</span>
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
// Инициализируем hover-функциональность
this.initHoverDropdown();
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
// Инициализация hover-функциональности для выпадающего меню
initHoverDropdown() {
const $dropdown = $('.nav-item.dropdown');
const $dropdownMenu = $dropdown.find('.dropdown-menu');
let hoverTimeout;
// Показываем меню при наведении
$dropdown.on('mouseenter', function() {
clearTimeout(hoverTimeout);
$(this).find('.dropdown-menu').addClass('show');
});
// Скрываем меню при уходе мыши
$dropdown.on('mouseleave', function() {
const $menu = $(this).find('.dropdown-menu');
hoverTimeout = setTimeout(() => {
$menu.removeClass('show');
}, 150); // Небольшая задержка для плавности
});
// Предотвращаем скрытие при наведении на само меню
$dropdownMenu.on('mouseenter', function() {
clearTimeout(hoverTimeout);
});
$dropdownMenu.on('mouseleave', function() {
hoverTimeout = setTimeout(() => {
$(this).removeClass('show');
}, 150);
});
}
}
// Инициализация менеджера профиля

View File

@ -705,13 +705,22 @@ class SearchManager {
$('#currentUserInfo').text(user.name);
$('#loginLink').hide();
$('#profileDropdown').show();
$('#adminDropdown').show();
// Показываем админ панель только для администраторов
if (auth.hasRole('admin')) {
$('#adminDropdown').show();
} else {
$('#adminDropdown').hide();
}
} else {
$('#currentUserInfo').text('Гость');
$('#loginLink').show();
$('#profileDropdown').hide();
$('#adminDropdown').hide();
}
// Обновляем права доступа для элементов интерфейса
auth.updateButtonPermissions();
}
// Загрузка категорий в навигацию
@ -754,21 +763,60 @@ class SearchManager {
// Добавляем активные категории
categories.forEach(category => {
if (category.active) {
const isEmpty = category.itemCount === 0;
const categoryLink = `
<li>
<a class="dropdown-item" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
${category.name}
<a class="dropdown-item ${isEmpty ? 'empty-category' : ''}" href="catalog.html?category=${category.id}" title="${category.description || ''}">
<div class="category-info">
<i class="${category.icon}" style="color: ${category.color || '#2c5aa0'}"></i>
<span>${category.name}</span>
</div>
<span class="category-count">${category.itemCount || 0}</span>
</a>
</li>
`;
dropdown.append(categoryLink);
}
});
// Инициализируем hover-функциональность
this.initHoverDropdown();
} catch (error) {
console.error('Ошибка загрузки категорий в выпадающее меню:', error);
}
}
// Инициализация hover-функциональности для выпадающего меню
initHoverDropdown() {
const $dropdown = $('.nav-item.dropdown');
const $dropdownMenu = $dropdown.find('.dropdown-menu');
let hoverTimeout;
// Показываем меню при наведении
$dropdown.on('mouseenter', function() {
clearTimeout(hoverTimeout);
$(this).find('.dropdown-menu').addClass('show');
});
// Скрываем меню при уходе мыши
$dropdown.on('mouseleave', function() {
const $menu = $(this).find('.dropdown-menu');
hoverTimeout = setTimeout(() => {
$menu.removeClass('show');
}, 150); // Небольшая задержка для плавности
});
// Предотвращаем скрытие при наведении на само меню
$dropdownMenu.on('mouseenter', function() {
clearTimeout(hoverTimeout);
});
$dropdownMenu.on('mouseleave', function() {
hoverTimeout = setTimeout(() => {
$(this).removeClass('show');
}, 150);
});
}
}
// Инициализация менеджера поиска

View File

@ -36,58 +36,7 @@ class WarehouseManager {
// Получение категорий по умолчанию
getDefaultCategories() {
return [
{
id: 'electronics',
name: 'Электроника',
description: 'Электронные компоненты и устройства',
icon: 'fas fa-microchip',
color: '#2c5aa0',
active: true,
itemCount: 0,
createdAt: new Date().toISOString()
},
{
id: 'components',
name: 'Компоненты',
description: 'Радиодетали и электронные компоненты',
icon: 'fas fa-cogs',
color: '#28a745',
active: true,
itemCount: 0,
createdAt: new Date().toISOString()
},
{
id: 'tools',
name: 'Инструменты',
description: 'Ручной и электроинструмент',
icon: 'fas fa-tools',
color: '#ffc107',
active: true,
itemCount: 0,
createdAt: new Date().toISOString()
},
{
id: 'office',
name: 'Офисные принадлежности',
description: 'Канцелярские товары и офисное оборудование',
icon: 'fas fa-briefcase',
color: '#6c757d',
active: true,
itemCount: 0,
createdAt: new Date().toISOString()
},
{
id: 'furniture',
name: 'Мебель',
description: 'Офисная мебель и оборудование',
icon: 'fas fa-chair',
color: '#8b4513',
active: true,
itemCount: 0,
createdAt: new Date().toISOString()
}
];
return [];
}
// Сохранение категорий
@ -98,7 +47,9 @@ class WarehouseManager {
// Обновление количества позиций в категориях
updateCategoryItemCounts() {
this.categories.forEach(category => {
category.itemCount = this.items.filter(item => item.category === category.id).length;
const itemsInCategory = this.items.filter(item => item.category === category.id);
category.itemCount = itemsInCategory.length;
category.totalQuantity = itemsInCategory.reduce((sum, item) => sum + (item.quantity || 0), 0);
});
this.saveCategories();
}
@ -114,78 +65,7 @@ class WarehouseManager {
// Получение позиций по умолчанию
getDefaultItems() {
return [
{
id: 1,
name: 'Ноутбук Dell Inspiron',
category: 'electronics',
price: 45000,
quantity: 15,
description: '15.6" Full HD, Intel Core i5, 8GB RAM, 256GB SSD',
barcode: '1234567890123',
minQuantity: 5,
location: 'Стеллаж A-1',
supplier: 'Dell Inc.',
createdAt: '2025-01-15T10:00:00Z',
updatedAt: '2025-01-15T10:00:00Z'
},
{
id: 2,
name: 'Принтер HP LaserJet',
category: 'electronics',
price: 12000,
quantity: 8,
description: 'Лазерный принтер, монохромный, 20 стр/мин',
barcode: '1234567890124',
minQuantity: 3,
location: 'Стеллаж A-2',
supplier: 'HP Inc.',
createdAt: '2025-01-10T14:30:00Z',
updatedAt: '2025-01-10T14:30:00Z'
},
{
id: 3,
name: 'Офисный стул',
category: 'office',
price: 3500,
quantity: 25,
description: 'Офисный стул с подлокотниками, черный',
barcode: '1234567890125',
minQuantity: 10,
location: 'Стеллаж B-1',
supplier: 'МебельСтрой',
createdAt: '2025-01-05T09:15:00Z',
updatedAt: '2025-01-05T09:15:00Z'
},
{
id: 4,
name: 'Бумага А4',
category: 'office',
price: 250,
quantity: 100,
description: 'Бумага А4, 80 г/м², 500 листов',
barcode: '1234567890126',
minQuantity: 20,
location: 'Стеллаж C-1',
supplier: 'ОфисМаркет',
createdAt: '2025-01-12T11:45:00Z',
updatedAt: '2025-01-12T11:45:00Z'
},
{
id: 5,
name: 'Отвертка крестовая',
category: 'tools',
price: 150,
quantity: 50,
description: 'Отвертка крестовая PH2, 150мм',
barcode: '1234567890127',
minQuantity: 15,
location: 'Стеллаж D-1',
supplier: 'ИнструментСтрой',
createdAt: '2025-01-08T16:20:00Z',
updatedAt: '2025-01-08T16:20:00Z'
}
];
return [];
}
// Получение статистики
@ -229,14 +109,14 @@ class WarehouseManager {
const newItem = {
id: this.getNextItemId(),
name: itemData.itemName,
category: itemData.itemCategory,
category: itemData.itemCategory || 'uncategorized',
price: parseFloat(itemData.itemPrice),
quantity: parseInt(itemData.itemQuantity),
description: itemData.itemDescription || '',
barcode: itemData.itemBarcode || '',
minQuantity: parseInt(itemData.itemQuantity) * 0.2, // 20% от начального количества
location: 'Новый стеллаж',
supplier: '',
location: itemData.itemLocation || 'Новый стеллаж',
supplier: itemData.itemSupplier || '',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
};
@ -244,6 +124,9 @@ class WarehouseManager {
this.items.push(newItem);
this.saveItems();
// Обновляем количество товаров в категории
this.updateCategoryItemCounts();
// Создаем операцию прихода для новой позиции
await this.createOperation({
type: 'incoming',
@ -269,6 +152,10 @@ class WarehouseManager {
};
this.saveItems();
// Обновляем количество товаров в категории
this.updateCategoryItemCounts();
return this.items[itemIndex];
}
@ -281,6 +168,10 @@ class WarehouseManager {
this.items.splice(itemIndex, 1);
this.saveItems();
// Обновляем количество товаров в категории
this.updateCategoryItemCounts();
return true;
}
@ -298,6 +189,9 @@ class WarehouseManager {
item.quantity += quantity;
item.updatedAt = new Date().toISOString();
this.saveItems();
// Обновляем количество товаров в категории
this.updateCategoryItemCounts();
// Создаем операцию
const operation = await this.createOperation({
@ -330,6 +224,9 @@ class WarehouseManager {
item.quantity -= quantity;
item.updatedAt = new Date().toISOString();
this.saveItems();
// Обновляем количество товаров в категории
this.updateCategoryItemCounts();
// Создаем операцию
const operation = await this.createOperation({