Документация ЛК
Модули

Места производства

Модуль "Места производства"

Версия: 1.0
Дата: 2025-11-26
Статус: Реализован


Содержание

  1. Общее описание
  2. Текущая реализация
  3. Права доступа
  4. Описание полей
  5. UI/UX
  6. Бизнес-логика
  7. Выявленные проблемы
  8. Рекомендации

1. Общее описание

1.1 Предназначение модуля

Модуль "Места производства" предназначен для управления производственными площадками компании. Каждое место производства имеет свою производительность (мощность) по дням недели, что используется для:

  • Планирования загрузки производства
  • Расчёта доступных дат для заказов
  • Отображения в календаре производства

Основные функции:

  • Ведение реестра мест производства
  • Настройка производительности по дням недели
  • Привязка заказов к конкретному производству

1.2 Связь с другими модулями

МодульСвязь
ЗаказыЗаказ привязан к месту производства (order.manufacture_id)
Дилеры (компании)Компания может иметь привязку к производству (company.manufacture_id)
Каталог (Товары)Товар может быть привязан к производству (many-to-many)
КалендарьОтображает заказы по местам производства
РезервацииУчитывает бронирования времени производства

1.3 Статистика

МетрикаЗначение
Всего мест производства2
Активных2
Компаний с производством3
Заказов с производством37

2. Текущая реализация

2.1 Архитектура

┌─────────────────────────────────────────────────────────────────────────────┐
│                      МОДУЛЬ "МЕСТА ПРОИЗВОДСТВА"                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  РОУТЫ (routes/web.php)                                                      │
│  └── GET /manufactures → ManufactureController@index → Список                │
│                                                                              │
│  КОНТРОЛЛЕР (ManufactureController.php)                                      │
│  └── Проверка: group_id == 1 (только администраторы)                         │
│                                                                              │
│  LIVEWIRE КОМПОНЕНТЫ                                                         │
│  ├── Manufactures/Listing.php — Таблица (inline-редактирование)             │
│  └── Manufactures/Add.php     — Модальное создание                          │
│                                                                              │
│  МОДЕЛЬ                                                                      │
│  └── Manufacture — место производства с JSON productivity                    │
│                                                                              │
│  СЕРВИС                                                                      │
│  └── Services/Septik.php — расчёт свободного времени                        │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

2.2 Структура БД

Таблица manufactures

ПолеТипОписание
idbigintPK
namestringНазвание
citystringГород
addressstringАдрес (nullable)
phonestring(20)Телефон
descriptiontextОписание (HTML)
productivityjsonПроизводительность по дням
activebooleanАктивен
created_attimestamp
updated_attimestamp

Таблица manufacture_product (связь с товарами)

ПолеТипОписание
manufacture_idFKМесто производства
product_idFKТовар

2.3 Формат поля productivity

[
  {
    "days": [1, 2, 3, 4, 5],  // пн-пт
    "time": 600               // мощность в минутах
  },
  {
    "days": [6, 7],           // сб-вс
    "time": 400
  }
]

Дни недели (ISO):

  • 1 = понедельник
  • 7 = воскресенье

2.4 Файлы модуля

app/
├── Http/Controllers/
│   └── ManufactureController.php
├── Livewire/Manufactures/
│   ├── Add.php
│   └── Listing.php
├── Models/
│   └── Manufacture.php
└── Services/
    └── Septik.php  ← расчёт загрузки

database/migrations/
├── 2024_03_21_213739_create_manufactures_table.php
├── 2024_04_16_132618_change_productivity_column_to_json_in_manufactures_table.php
└── 2024_04_22_220112_create_manufacture_product_table.php

resources/views/components/
└── productivity.blade.php  ← отображение productivity в таблице

3. Права доступа

3.1 Политики

ПолитикаОписание
manufacture_can_editРедактирование места производства

3.2 Жёсткое ограничение в контроллере

// ManufactureController.php
public function index(Request $request)
{
    $user = $request->user();
    if (!$user or $user->group_id != 1)  // Только администраторы!
        abort(403);
    return view('templates.manufactures.table');
}

⚠️ Важно: Модуль доступен только администраторам (group_id = 1). Это проверяется напрямую в контроллере, а не через систему политик.

3.3 Матрица доступа по ролям

РольПросмотрСозданиеРедактир.Удаление
Администратор
Менеджер
Производство
Дилер

4. Описание полей

4.1 Форма создания/редактирования

ПолеТипОбязательноеОписание
nameTextInputНазвание производства
cityTextInputГород
addressTextInputАдрес
productivityRepeaterМощность по дням (см. ниже)
phoneTextInputТелефон (маска +7)
descriptionRichEditorОписание (HTML)

4.2 Поле Productivity (Repeater)

Repeater::make('productivity')->label('Продуктивность')
    ->schema([
        CheckboxList::make('days')
            ->options([
                1 => 'пн', 2 => 'вт', 3 => 'ср',
                4 => 'чт', 5 => 'пт', 6 => 'сб', 7 => 'вс',
            ])
            ->columns(7),
        TextInput::make('time')
            ->numeric()
            ->default(0),
    ])

Логика:

  • Можно создать несколько записей (строк)
  • Для каждой записи выбираются дни недели
  • Указывается мощность (время в минутах)

4.3 Колонки таблицы

КолонкаОписаниеОсобенности
nameНазваниеПоиск
cityГородПоиск
phoneТелефонПоиск
productivityМощностьViewColumn с кастомным отображением
activeАктивенToggleColumn

5. UI/UX

5.1 Список мест производства

┌─────────────────────────────────────────────────────────────────────────────┐
│ Места производства                                          [+ Создать]     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                    [Поиск...] [Столбцы ▾]   │
├──────┬───────────────────────┬───────────┬──────────┬─────────────┬─────────┤
│ ☐    │ Имя                   │ City      │ Телефон  │ Productivity│ Активен │
├──────┼───────────────────────┼───────────┼──────────┼─────────────┼─────────┤
│ ☐    │ Производство Верховье │ Верховье  │          │ пн-пт: 600  │ [●]     │
│      │                       │           │          │ сб-вс: 400  │         │
├──────┼───────────────────────┼───────────┼──────────┼─────────────┼─────────┤
│ ☐    │ Производство Елкино   │ Елкино    │          │ пн-пт: 300  │ [●]     │
│      │                       │           │          │ сб-вс: 200  │         │
└──────┴───────────────────────┴───────────┴──────────┴─────────────┴─────────┘

Действия:
✅ [Изменить] — модальное редактирование
✅ [Удалить] — с подтверждением

Особенности:
- Нет отдельной страницы редактирования
- Всё через модальные окна
- Productivity отображается кастомным Blade-компонентом

5.2 Отображение Productivity

{{-- components/productivity.blade.php --}}
@foreach ($getState() as $item)
    <div class="mb-1">
        {{ App\Services\Septik::getDays($item['days']) }} - {{ $item['time'] }}
    </div>
@endforeach

Пример вывода:

пн,вт,ср,чт,пт - 600
сб,вс - 400

5.3 Модальное редактирование

┌─────────────────────────────────────────────────────────────────┐
│ Редактировать склад                                       [×]   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Имя              [Производство Верховье                   ]    │
│                                                                  │
│  City             [Верховье                                ]    │
│                                                                  │
│  Address          [                                        ]    │
│                                                                  │
│  Продуктивность                                                 │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ [×] пн  [×] вт  [×] ср  [×] чт  [×] пт  [ ] сб  [ ] вс  │   │
│  │ Time: [600                                           ]  │   │
│  └─────────────────────────────────────────────────────────┘   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ [ ] пн  [ ] вт  [ ] ср  [ ] чт  [ ] пт  [×] сб  [×] вс  │   │
│  │ Time: [400                                           ]  │   │
│  └─────────────────────────────────────────────────────────┘   │
│  [+ Добавить строку]                                            │
│                                                                  │
│  Телефон          [+7(999) 123-45-67                       ]    │
│                                                                  │
│  Description      [                                        ]    │
│                                                                  │
├─────────────────────────────────────────────────────────────────┤
│                                           [Отмена] [Сохранить]  │
└─────────────────────────────────────────────────────────────────┘

6. Бизнес-логика

6.1 Расчёт свободного времени (Services/Septik.php)

Ключевой сервис системы — расчёт доступной мощности производства на дату.

class Septik
{
    /**
     * Возвращает свободное время (минуты) на производстве за дату
     */
    public static function getFreeTime($manufacture, $date, $orders = null, $reservations = null): int
    {
        // 1. Получаем мощность производства на эту дату
        $manufactureTime = static::getProductivityTime($m->productivity, $date);
        
        // 2. Считаем занятое время заказами
        $orders = Order::where('manufacture_id', $manufacture)
            ->whereDate('date_make', $date)->get();
        foreach ($orders as $order) {
            $ordersTime += $order->product->time;
        }
        
        // 3. Считаем время резерваций
        $reservations = Reservation::where('manufacture_id', $manufacture)
            ->whereDate('date', $date)->get();
        foreach ($reservations as $reservation) {
            $reservationsTime += $reservation->time;
        }
        
        // 4. Свободное время = мощность - заказы - резервации
        return $manufactureTime - $reservationsTime - $ordersTime;
    }
}

6.2 Формула загрузки

Свободное время = Мощность(дата) - Σ(время_заказов) - Σ(время_резерваций)

Где:

  • Мощность(дата) — значение time из productivity для дня недели этой даты
  • время_заказов — сумма product.time всех заказов на эту дату
  • время_резерваций — сумма time всех резерваций на эту дату

6.3 Получение мощности по дате

public static function getProductivityTime($items, $date): int
{
    foreach ($items as $item) {
        $dayOfWeek = Carbon::parse($date)->dayOfWeekIso;  // 1=пн, 7=вс
        if (in_array($dayOfWeek, $item['days'])) {
            return $item['time'] ?? 0;
        }
    }
    return 0;  // Если день не найден — мощность 0
}

6.4 Поиск свободных дат для заказа

/**
 * Находит 10 ближайших дат, когда товар можно произвести
 */
public static function getFreeDates($manufacture, $product): array
{
    $freeDates = [];
    $startDay = Carbon::today()->addDay();  // Начинаем с завтра
    
    while (count($freeDates) < 10 && $datesChecked < 50) {
        $day = $startDay->addDays($datesChecked);
        
        // Если время товара < свободного времени — дата подходит
        if ($product->time < static::getFreeTime($manufacture, $day)) {
            $freeDates[] = $day->format('Y-m-d');
        }
        $datesChecked++;
    }
    
    return $freeDates;
}

6.5 Связь с Календарём

В календаре заказы фильтруются по manufacture_id:

// Calendar/Day.php
$this->manufacture = session('calendar_selector');  // Выбранное производство
$query = Order::query();
if ($this->manufacture) {
    $query = $query->where('manufacture_id', $this->manufacture);
}

6.6 Связь с заказами и компаниями

Order.manufacture_id ──────────┐

Company.manufacture_id ──────► Manufacture

Product ◄─────────────────────┴── manufacture_product (M:N)

7. Выявленные проблемы

7.1 Критические

#ПроблемаФайлВлияние
Критических проблем не обнаружено

7.2 Средние

#ПроблемаОписаниеРешение
1Опечатка в modalHeading'Редактировать склад' вместо 'Редактировать производство'Исправить текст
2Жёсткая проверка group_idНет гибкости через систему политикИспользовать check_access()
3Нет валидации productivityМожно сохранить пустой массив или без времениДобавить валидацию
4Время в минутах неочевидноНет подсказки о единицах измеренияДобавить hint/suffix

7.3 Низкие

#ПроблемаОписание
5Нелокализованные названия колонокCity, Productivity на английском
6Нет истории измененийНе отслеживается кто менял мощность
7Нет отчёта по загрузкеНельзя посмотреть статистику загрузки

8. Рекомендации

8.1 Приоритет: Высокий

Исправить опечатку

// Listing.php:83 — было:
->modalHeading('Редактировать склад')

// Стало:
->modalHeading('Редактировать место производства')

8.2 Приоритет: Средний

Добавить подсказку к полю time

TextInput::make('time')
    ->label('Мощность')
    ->numeric()
    ->suffix('минут')
    ->hint('Максимальное время производства за день')
    ->default(0),

Локализовать колонки

Tables\Columns\TextColumn::make('city')
    ->label('Город')
    ->searchable(),

8.3 Приоритет: Низкий

Добавить валидацию productivity

Repeater::make('productivity')
    ->minItems(1)
    ->schema([
        CheckboxList::make('days')
            ->required()
            ->minItems(1),
        TextInput::make('time')
            ->required()
            ->numeric()
            ->minValue(1),
    ])

Приложение: SQL для аналитики

Загрузка производств

SELECT 
    m.name,
    m.city,
    COUNT(o.id) as orders_count,
    DATE(o.date_make) as date
FROM manufactures m
LEFT JOIN orders o ON m.id = o.manufacture_id
WHERE o.date_make >= CURDATE()
GROUP BY m.id, m.name, m.city, DATE(o.date_make)
ORDER BY m.name, date;

Компании без привязки к производству

SELECT id, org, city
FROM companies
WHERE manufacture_id IS NULL;

Заказы по производствам за месяц

SELECT 
    m.name as manufacture,
    COUNT(o.id) as total_orders,
    SUM(o.cost) as total_cost
FROM manufactures m
LEFT JOIN orders o ON m.id = o.manufacture_id
WHERE o.created_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY m.id, m.name
ORDER BY total_orders DESC;

Документ подготовлен на основе анализа исходного кода проекта

On this page

Модуль "Места производства"Содержание1. Общее описание1.1 Предназначение модуля1.2 Связь с другими модулями1.3 Статистика2. Текущая реализация2.1 Архитектура2.2 Структура БДТаблица manufacturesТаблица manufacture_product (связь с товарами)2.3 Формат поля productivity2.4 Файлы модуля3. Права доступа3.1 Политики3.2 Жёсткое ограничение в контроллере3.3 Матрица доступа по ролям4. Описание полей4.1 Форма создания/редактирования4.2 Поле Productivity (Repeater)4.3 Колонки таблицы5. UI/UX5.1 Список мест производства5.2 Отображение Productivity5.3 Модальное редактирование6. Бизнес-логика6.1 Расчёт свободного времени (Services/Septik.php)6.2 Формула загрузки6.3 Получение мощности по дате6.4 Поиск свободных дат для заказа6.5 Связь с Календарём6.6 Связь с заказами и компаниями7. Выявленные проблемы7.1 Критические7.2 Средние7.3 Низкие8. Рекомендации8.1 Приоритет: ВысокийИсправить опечатку8.2 Приоритет: СреднийДобавить подсказку к полю timeЛокализовать колонки8.3 Приоритет: НизкийДобавить валидацию productivityПриложение: SQL для аналитикиЗагрузка производствКомпании без привязки к производствуЗаказы по производствам за месяц