SPARE_PARTS_MODULE.md 13 KB

Модуль управления запчастями

Обзор

Модуль управления запчастями добавляет полнофункциональную систему для:

  • Ведения каталога запчастей
  • Управления заказами деталей
  • Автоматического списания при использовании в рекламациях
  • Контроля наличия на складе

Основные возможности

1. Каталог запчастей

ВАЖНО: Каталог запчастей является общим для всех лет. Одна запчасть (по артикулу) существует во всех годах, но количества рассчитываются только для текущего выбранного года.

Доступ: Меню → Запчасти → вкладка "Каталог"

Функции:

  • Просмотр всех запчастей с вычисляемыми остатками
  • Добавление/редактирование запчастей (только admin)
  • Загрузка изображений запчастей
  • Экспорт/импорт каталога в Excel
  • Управление ценами (закупка, заказчик, экспертиза)
  • Установка минимального остатка

Вычисляемые поля:

  • Кол-во без док - количество на складе без документов (для текущего года)
  • Кол-во с док - количество на складе с документами (для текущего года)
  • Кол-во общее - сумма двух предыдущих

Кликабельные ячейки: Клик по ячейке с количеством открывает вкладку "Заказы деталей" с автоматическим фильтром по:

  • Артикулу
  • Наличию документов (если кликнули на "без док" или "с док")
  • Статусу "На складе"
  • Остатку > 0

2. Заказы деталей

ВАЖНО: Заказы разделены по годам. Каждый заказ принадлежит конкретному году.

Доступ: Меню → Запчасти → вкладка "Заказы деталей"

Функции:

  • Создание заказа детали (admin, manager)
  • Изменение статуса (Заказано → На складе → Отгружено)
  • Отгрузка детали (списание) с указанием куда/для чего
  • Просмотр истории списаний
  • Автоматическое изменение статуса на "Отгружено" при полном списании

Статусы заказа:

  • Заказано - деталь в процессе заказа
  • На складе - деталь поступила и доступна для использования
  • Отгружено - деталь полностью списана

История списаний:

  • Дата и время списания
  • Количество
  • Примечание (куда/для чего)
  • Пользователь
  • Флаг "автоматическое" (если списано через рекламацию)
  • Ссылка на рекламацию (если применимо)

3. Контроль наличия

Доступ: Меню → Запчасти → вкладка "Контроль наличия"

Две таблицы:

Критический недостаток (красные строки):

  • Запчасти с отрицательным количеством
  • Означает, что была попытка списать больше, чем есть на складе
  • Автоматически создаётся виртуальный заказ с отрицательным остатком

Ниже минимального остатка (желтые строки):

  • Запчасти, у которых общее количество < минимальный остаток
  • Предупреждение о необходимости пополнения

4. Интеграция с рекламациями

Автоматическое списание: При добавлении детали в рекламацию система:

  1. Проверяет, есть ли запчасть с таким артикулом в каталоге
  2. Если есть - автоматически списывает из подходящего заказа (FIFO)
  3. Если нет достаточного количества - создаёт виртуальный заказ с недостачей
  4. Сохраняет связь запчасть-рекламация

Чекбокс "С док.":

  • В форме деталей рекламации добавлен чекбокс "С док."
  • Определяет, нужна ли запчасть с документами или без
  • Влияет на выбор заказа для списания

5. Справочник расценок

Доступ: Меню → Запчасти → (отдельный раздел, только для admin)

Функции:

  • Ведение справочника кодов расценок
  • Добавление/редактирование/удаление кодов
  • Расшифровка кодов
  • Tooltip при наведении на код в каталоге (планируется)

Мультигодовая архитектура

КРИТИЧНО ВАЖНО:

Каталог запчастей (БЕЗ year):

  • Таблица spare_parts НЕ имеет поле year
  • Модель SparePart НЕ использует YearScope
  • Одна запчасть видна во всех годах

Заказы деталей (С year):

  • Таблица spare_part_orders имеет поле year
  • Модель SparePartOrder использует YearScope
  • Заказы разделены по годам

Логика вычисления количеств:

  • Вычисляемые поля (quantity_without_docs, quantity_with_docs) в модели SparePart
  • Учитывают только заказы текущего года из сессии year()
  • При смене года количества пересчитываются автоматически

Пример:

// Запчасть "BOLT-001" существует одна
$sparePart = SparePart::where('article', 'BOLT-001')->first();

// Год 2024: есть заказ на 100 шт
session(['year' => 2024]);
echo $sparePart->total_quantity; // 100

// Год 2025: есть заказ на 50 шт
session(['year' => 2025]);
echo $sparePart->total_quantity; // 50

// Год 2026: нет заказов
session(['year' => 2026]);
echo $sparePart->total_quantity; // 0

Структура базы данных

Таблицы:

  1. spare_parts - каталог запчастей (БЕЗ year)
  2. spare_part_orders - заказы деталей (С year)
  3. spare_part_order_shipments - история списаний (БЕЗ year, привязана к заказу)
  4. pricing_codes - справочник расценок
  5. reclamation_spare_part - pivot таблица запчасти-рекламации

View:

  • spare_part_orders_view - представление для заказов с join'ами

Экспорт/Импорт

Экспорт каталога:

  • Кнопка "Экспорт" (только admin)
  • Выполняется через очередь (ExportSparePartsJob)
  • Шаблон: /templates/SpareParts.xlsx
  • ВАЖНО: Вычисляемые поля (количества) экспортируются для текущего года!

Формат Excel (13 колонок, БЕЗ года):

| ID | Артикул | Где используется | Кол-во без док | Кол-во с док | Кол-во общее | Примечание | Цена закупки | Цена для заказчика | Цена экспертизы | № по ТСН | Шифр расценки | Минимальный остаток |

Изображения

Расположение: /public/images/spare_parts/

Формат имени: {article}.jpg

Пример: TEST-001.jpg

Загрузка:

  • Форма редактирования запчасти → кнопка "Загрузить изображение" (только admin)
  • Автоматическое отображение в каталоге и формах

Роли и права доступа

Admin:

  • Полный доступ ко всем функциям
  • Создание/редактирование/удаление запчастей
  • Экспорт/импорт
  • Управление заказами и списание
  • Доступ к ценам закупки

Manager:

  • Просмотр каталога
  • Создание/редактирование заказов деталей
  • Списание деталей
  • Просмотр контроля наличия
  • НЕТ доступа к ценам закупки

Другие роли:

  • Только просмотр

Технические детали

Сервисы:

  • SparePartInventoryService - логика автосписания и контроля
  • Export/ExportSparePartsService - экспорт в Excel

Jobs:

  • Export/ExportSparePartsJob - фоновая задача экспорта

Form Requests:

  • StoreSparePartRequest - валидация запчасти
  • StoreSparePartOrderRequest - валидация заказа
  • ShipSparePartOrderRequest - валидация отгрузки
  • StoreReclamationDetailsRequest - обновлён для поддержки with_documents

Контроллеры:

  • SparePartController - каталог
  • SparePartOrderController - заказы
  • SparePartInventoryController - контроль наличия
  • PricingCodeController - справочник расценок
  • ReclamationController - обновлён для интеграции

Маршруты

// Каталог
GET    /spare-parts
POST   /spare-parts (admin)
GET    /spare-parts/create (admin)
GET    /spare-parts/{id}
PUT    /spare-parts/{id} (admin)
DELETE /spare-parts/{id} (admin)
POST   /spare-parts/export (admin)
POST   /spare-parts/{id}/upload-image (admin)

// Заказы
GET    /spare-part-orders
POST   /spare-part-orders (admin, manager)
GET    /spare-part-orders/create (admin, manager)
GET    /spare-part-orders/{id}
PUT    /spare-part-orders/{id} (admin, manager)
DELETE /spare-part-orders/{id} (admin)
POST   /spare-part-orders/{id}/ship (admin, manager)
POST   /spare-part-orders/{id}/set-in-stock (admin, manager)

// Контроль
GET    /spare-part-inventory

// Справочник
GET    /pricing-codes (admin)
POST   /pricing-codes (admin)
PUT    /pricing-codes/{id} (admin)
DELETE /pricing-codes/{id} (admin)

// API
GET    /api/pricing-codes/{code}

Тестирование

Создание тестовых данных:

docker exec dkr-app-1 php artisan tinker
// Создать запчасть
$sp = SparePart::create([
    'article' => 'TEST-001',
    'used_in_maf' => 'Качели',
    'customer_price' => 150.00,
    'min_stock' => 10
]);

// Создать заказ
$order = SparePartOrder::create([
    'spare_part_id' => $sp->id,
    'source_text' => 'Поставщик А',
    'status' => 'in_stock',
    'ordered_quantity' => 100,
    'with_documents' => true,
    'user_id' => 1
]);

// Проверить количество
echo $sp->quantity_with_docs; // 100

Тест автосписания:

$service = new SparePartInventoryService();
$service->deductForReclamation('TEST-001', 10, true, $reclamationId);

// Проверить
$sp->refresh();
echo $sp->quantity_with_docs; // 90

Известные особенности

  1. Отрицательные остатки - разрешены и означают недостачу
  2. Виртуальные заказы - автоматически создаются при недостаче со статусом "На складе" и отрицательным остатком
  3. FIFO - при списании выбирается самый ранний заказ с подходящими параметрами
  4. Пересчёт количеств - происходит динамически при каждом обращении к атрибутам модели