| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- @extends('layouts.app')
- @section('content')
- <div class="container-fluid">
- <div class="row">
- <div class="col-12">
- <h2>{{ $title }}</h2>
- {{-- Вкладки --}}
- <ul class="nav nav-tabs mb-3">
- <li class="nav-item">
- <a class="nav-link {{ ($tab ?? 'catalog') === 'catalog' ? 'active' : '' }}"
- href="{{ route('spare_parts.index') }}">
- Каталог
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link {{ ($tab ?? '') === 'orders' ? 'active' : '' }}"
- href="{{ route('spare_part_orders.index') }}">
- Заказы деталей
- </a>
- </li>
- <li class="nav-item">
- <a class="nav-link {{ ($tab ?? '') === 'inventory' ? 'active' : '' }}"
- href="{{ route('spare_part_inventory.index') }}">
- Контроль наличия
- </a>
- </li>
- @if(hasRole('admin'))
- <li class="nav-item">
- <a class="nav-link" href="{{ route('pricing_codes.index') }}">
- Справочник расшифровок
- </a>
- </li>
- @endif
- </ul>
- @if(($tab ?? 'catalog') === 'catalog')
- {{-- Кнопки управления --}}
- <div class="mb-3">
- @if(hasRole('admin'))
- <a href="{{ route('spare_parts.create') }}" class="btn btn-primary">Добавить запчасть</a>
- <form action="{{ route('spare_parts.export') }}" method="POST" class="d-inline">
- @csrf
- <button type="submit" class="btn btn-success">Экспорт</button>
- </form>
- <button type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#importModal">
- Импорт
- </button>
- @endif
- </div>
- {{-- Таблица каталога --}}
- @if(isset($spare_parts) && isset($strings))
- @include('partials.table', [
- 'id' => $id,
- 'header' => $header,
- 'strings' => $strings,
- 'filters' => $filters ?? [],
- 'ranges' => $ranges ?? [],
- 'dates' => $dates ?? [],
- 'searchFields' => $searchFields ?? [],
- 'sortBy' => $sortBy ?? 'article',
- 'orderBy' => $orderBy ?? 'asc',
- 'routeName' => $routeName ?? null,
- ])
- {{ $spare_parts->links() }}
- @endif
- @elseif($tab === 'orders')
- {{-- Таблица заказов --}}
- @if(isset($spare_part_orders))
- <div class="mb-3">
- @if(hasRole('admin,manager'))
- <a href="{{ route('spare_part_orders.create') }}" class="btn btn-primary">Создать заказ</a>
- @endif
- </div>
- @include('partials.table', [
- 'id' => $id,
- 'header' => $header,
- 'strings' => $strings,
- 'filters' => $filters ?? [],
- 'ranges' => $ranges ?? [],
- 'dates' => $dates ?? [],
- 'searchFields' => $searchFields ?? [],
- 'sortBy' => $sortBy ?? 'id',
- 'orderBy' => $orderBy ?? 'desc',
- 'routeName' => $routeName ?? null,
- ])
- {{ $spare_part_orders->links() }}
- @endif
- @elseif($tab === 'inventory')
- {{-- Контроль наличия --}}
- {{-- Открытые дефициты --}}
- <h4 class="text-danger"><i class="bi bi-exclamation-triangle-fill"></i> Открытые дефициты
- @if(isset($open_shortages) && $open_shortages->count() > 0)
- <span class="badge bg-danger">{{ $open_shortages->count() }}</span>
- @endif
- </h4>
- @if(isset($open_shortages) && $open_shortages->count() > 0)
- <div class="table-responsive">
- <table class="table table-danger table-striped">
- <thead>
- <tr>
- <th>Картинка</th>
- <th>Артикул</th>
- <th>Рекламация</th>
- <th class="text-center">Требуется</th>
- <th class="text-center">Зарезервировано</th>
- <th class="text-center">Не хватает</th>
- <th class="text-center">С док.</th>
- <th>Дата создания</th>
- </tr>
- </thead>
- <tbody>
- @foreach($open_shortages as $shortage)
- <tr>
- <td>
- @if($shortage->sparePart && $shortage->sparePart->image)
- <img src="{{ $shortage->sparePart->image }}" alt="{{ $shortage->sparePart->article }}" style="max-width: 50px;">
- @endif
- </td>
- <td>
- @if($shortage->sparePart)
- <a href="{{ route('spare_parts.show', $shortage->sparePart->id) }}">{{ $shortage->sparePart->article }}</a>
- @if($shortage->sparePart->used_in_maf)
- <br><small class="text-muted">{{ $shortage->sparePart->used_in_maf }}</small>
- @endif
- @else
- -
- @endif
- </td>
- <td>
- @if($shortage->reclamation)
- <a href="{{ route('reclamations.show', $shortage->reclamation->id) }}">#{{ $shortage->reclamation->id }}</a>
- @else
- -
- @endif
- </td>
- <td class="text-center">{{ $shortage->required_qty }}</td>
- <td class="text-center">{{ $shortage->reserved_qty }}</td>
- <td class="text-center fw-bold">{{ $shortage->missing_qty }}</td>
- <td class="text-center">
- @if($shortage->with_documents)
- <i class="bi bi-check-circle text-success"></i> Да
- @else
- <i class="bi bi-x-circle text-muted"></i> Нет
- @endif
- </td>
- <td>{{ $shortage->created_at->format('d.m.Y H:i') }}</td>
- </tr>
- @endforeach
- </tbody>
- </table>
- </div>
- @else
- <p class="text-muted">Нет открытых дефицитов</p>
- @endif
- {{-- Запчасти с критическим недостатком --}}
- <h4 class="text-danger mt-4">Запчасти с дефицитами</h4>
- @if(isset($critical_shortages) && $critical_shortages->count() > 0)
- <div class="table-responsive">
- <table class="table table-danger table-striped">
- <thead>
- <tr>
- <th>Картинка</th>
- <th>Артикул</th>
- <th class="text-center">Свободно без док</th>
- <th class="text-center">Свободно с док</th>
- <th>Дефициты</th>
- </tr>
- </thead>
- <tbody>
- @foreach($critical_shortages as $sp)
- <tr>
- <td>
- @if($sp->image)
- <img src="{{ $sp->image }}" alt="{{ $sp->article }}" style="max-width: 50px;">
- @endif
- </td>
- <td>
- <a href="{{ route('spare_parts.show', $sp->id) }}">{{ $sp->article }}</a>
- @if($sp->used_in_maf)
- <br><small class="text-muted">{{ $sp->used_in_maf }}</small>
- @endif
- </td>
- <td class="text-center">{{ $sp->quantity_without_docs }}</td>
- <td class="text-center">{{ $sp->quantity_with_docs }}</td>
- <td>
- @if(isset($sp->shortage_details))
- @foreach($sp->shortage_details as $detail)
- <div class="small">
- <a href="{{ route('reclamations.show', $detail['reclamation_id']) }}">Рекл. #{{ $detail['reclamation_id'] }}</a>:
- не хватает <strong>{{ $detail['missing_qty'] }}</strong> шт.
- @if($detail['with_documents'])
- (с док.)
- @else
- (без док.)
- @endif
- </div>
- @endforeach
- @endif
- </td>
- </tr>
- @endforeach
- </tbody>
- </table>
- </div>
- @else
- <p class="text-muted">Нет запчастей с дефицитами</p>
- @endif
- <h4 class="text-warning mt-4"><i class="bi bi-exclamation-circle-fill"></i> Ниже минимального остатка</h4>
- @if(isset($below_min_stock) && $below_min_stock->count() > 0)
- <div class="table-responsive">
- <table class="table table-warning table-striped">
- <thead>
- <tr>
- <th>Картинка</th>
- <th>Артикул</th>
- <th class="text-center">Текущий остаток</th>
- <th class="text-center">Минимальный остаток</th>
- <th class="text-center">Нужно заказать</th>
- </tr>
- </thead>
- <tbody>
- @foreach($below_min_stock as $sp)
- <tr>
- <td>
- @if($sp->image)
- <img src="{{ $sp->image }}" alt="{{ $sp->article }}" style="max-width: 50px;">
- @endif
- </td>
- <td>
- <a href="{{ route('spare_parts.show', $sp->id) }}">{{ $sp->article }}</a>
- @if($sp->used_in_maf)
- <br><small class="text-muted">{{ $sp->used_in_maf }}</small>
- @endif
- </td>
- <td class="text-center">{{ $sp->total_quantity }}</td>
- <td class="text-center">{{ $sp->min_stock }}</td>
- <td class="text-center fw-bold">{{ max(0, $sp->min_stock - $sp->total_quantity) }}</td>
- </tr>
- @endforeach
- </tbody>
- </table>
- </div>
- @else
- <p class="text-muted">Нет запчастей ниже минимального остатка</p>
- @endif
- @endif
- </div>
- </div>
- </div>
- {{-- Модальное окно импорта --}}
- @if(hasRole('admin'))
- <div class="modal fade" id="importModal" tabindex="-1">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h5 class="modal-title">Импорт каталога запчастей и справочника расшифровок</h5>
- <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
- </div>
- <form action="{{ route('spare_parts.import') }}" method="POST" enctype="multipart/form-data">
- @csrf
- <div class="modal-body">
- <div class="mb-3">
- <label for="import_file" class="form-label">Выберите файл Excel</label>
- <input type="file" class="form-control" id="import_file" name="file" accept=".xlsx,.xls" required>
- <div class="form-text">
- Файл должен содержать две вкладки:<br>
- 1. Каталог запчастей (колонки: ID, Артикул, Где используется, Кол-во без док, Кол-во с док, Кол-во общее, Примечание, Цена закупки, Цена для заказчика, Цена экспертизы, № по ТСН, Шифр расценки, Минимальный остаток)<br>
- 2. Справочник расшифровок (колонки: ID, Тип, Код, Расшифровка)
- </div>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
- <button type="submit" class="btn btn-primary">Импортировать</button>
- </div>
- </form>
- </div>
- </div>
- </div>
- @endif
- @push('scripts')
- <script type="module">
- function waitForJQuery(callback) {
- if (typeof window.$ !== 'undefined') {
- callback();
- } else {
- setTimeout(() => waitForJQuery(callback), 50);
- }
- }
- waitForJQuery(function() {
- $(document).on('click', '.clickable-quantity', function(e) {
- e.preventDefault();
- const sparePartId = $(this).data('spare-part-id');
- const withDocs = $(this).data('with-docs');
- let url = "{{ route('spare_part_orders.index') }}" +
- "?spare_part_id=" + sparePartId +
- "&status=in_stock&available_qty_min=1";
- if (withDocs !== 'all') {
- url += "&with_documents=" + withDocs;
- }
- window.location.href = url;
- });
- });
- </script>
- @endpush
- @endsection
|