@extends('layouts.teknisi') @section('title', 'Detail Produksi - Teknisi') @section('content')

Detail Produksi #{{ $production->id }}

{{ $production->product->product_title ?? 'N/A' }} · {{ $production->order->customer_name ?? 'N/A' }}

@if (session('success'))
{{ session('success') }}
@endif @if (session('info'))
{{ session('info') }}
@endif @if ($errors->any())
@endif
@if ($errors->any())
@endif @include('teknisi.productions.partials.timeline', ['production' => $production])

Info Produksi

Qty: {{ $production->quantity ?? 1 }} unit
Customer: {{ $production->order->customer_name ?? 'N/A' }}
Ditugaskan: {{ $production->assigned_at?->format('d/m/Y') ?? 'N/A' }}

Info Pesanan

Order ID: #{{ $production->order->id ?? 'N/A' }}
Produk: {{ Str::limit($production->product->product_title ?? 'N/A', 15) }}
Harga: Rp {{ number_format($production->order->total_price ?? 0, 0, ',', '.') }}

Ringkasan

@php $materialTotal = $production->total_material_cost ?? 0; $sparepartTotal = $production->total_sparepart_cost ?? 0; $directTotal = $materialTotal + $sparepartTotal; @endphp
Bahan: {{ $production->productionMaterials->count() }} item
Sparepart: {{ $production->productionSpareparts->count() }} item
Total: Rp {{ number_format($directTotal, 0, ',', '.') }}

Status

Planning: @php $statusColors = [ 'planning' => [ 'bg' => 'bg-blue-100 dark:bg-blue-900/40', 'text' => 'text-blue-700 dark:text-blue-300', 'label' => 'Planning', ], 'pending_approval' => [ 'bg' => 'bg-amber-100 dark:bg-amber-900/40', 'text' => 'text-amber-700 dark:text-amber-300', 'label' => 'Pending', ], 'approved' => [ 'bg' => 'bg-green-100 dark:bg-green-900/40', 'text' => 'text-green-700 dark:text-green-300', 'label' => 'Approved', ], 'rejected' => [ 'bg' => 'bg-red-100 dark:bg-red-900/40', 'text' => 'text-red-700 dark:text-red-300', 'label' => 'Rejected', ], ]; $planningStatus = $statusColors[$production->planning_status] ?? $statusColors['planning']; @endphp {{ $planningStatus['label'] }}
Produksi: @php $prodStatusColors = [ 'menunggu' => [ 'bg' => 'bg-gray-100 dark:bg-gray-700/50', 'text' => 'text-gray-700 dark:text-gray-300', 'label' => 'Menunggu', ], 'dalam_proses' => [ 'bg' => 'bg-yellow-100 dark:bg-yellow-900/40', 'text' => 'text-yellow-700 dark:text-yellow-300', 'label' => 'Dalam Proses', ], 'selesai' => [ 'bg' => 'bg-green-100 dark:bg-green-900/40', 'text' => 'text-green-700 dark:text-green-300', 'label' => 'Selesai', ], ]; $prodStatus = $prodStatusColors[$production->status] ?? $prodStatusColors['menunggu']; @endphp {{ $prodStatus['label'] }}
Bayar: {{ strtoupper($production->order->payment_method ?? 'N/A') }}
@if ($production->supervisor_feedback && in_array($production->planning_status, ['rejected', 'planning']))

Feedback Supervisor @if ($production->planning_status === 'planning') Revisi @endif

{{ $production->supervisor_feedback }}

@endif {{-- ============================================== --}} {{-- TABEL GABUNGAN BAHAN & SPAREPART --}} {{-- ============================================== --}} @php $canEdit = $production->planning_status === 'planning'; $canCheckReceived = $production->planning_status === 'approved' && in_array($production->status, ['menunggu', 'dalam_proses']); @endphp

Daftar Bahan & Sparepart

{{ $production->productionMaterials->count() + $production->productionSpareparts->count() }} item · {{ $production->quantity ?? 1 }} unit produk

@if ($canCheckReceived) @php // Hitung dari production relations langsung $materialCount = $production->productionMaterials->count(); $sparepartCount = $production->productionSpareparts->count(); $totalItemsHeader = $materialCount + $sparepartCount; $receivedMaterials = $production->productionMaterials ->where('is_received', true) ->count(); $receivedSpareparts = $production->productionSpareparts ->where('is_received', true) ->count(); $receivedItemsHeader = $receivedMaterials + $receivedSpareparts; // Semua item dianggap available kecuali ada pengecekan stok khusus $availableItemsHeader = $totalItemsHeader; @endphp
{{ $receivedItemsHeader }}/{{ $availableItemsHeader }} diterima
@csrf @php $allReceivedHeader = $receivedItemsHeader == $availableItemsHeader && $availableItemsHeader > 0; $canConfirm = in_array($production->materials_status, ['preparing', 'pending']) || in_array($production->spareparts_status, ['preparing', 'pending']); @endphp @if ($canConfirm || !$allReceivedHeader) @else Semua Diterima @endif
@endif @if ($canEdit) @else Planning sudah disubmit @endif
@php $allItems = collect(); $orderQty = $production->quantity ?? 1; foreach ($production->productionMaterials as $pm) { $totalNeeded = $pm->quantity * $orderQty; $currentStock = $pm->material->stock ?? 0; $stockStatus = 'available'; // available, insufficient, pending_purchase $stockStatusLabel = 'Tersedia'; $stockStatusClass = 'bg-green-100 text-green-700'; // Untuk item request yang sudah diterima (is_additional = true dan is_received = true) // Stok di master barang sudah dikurangi saat admin kirim, jadi stok yang ditampilkan // adalah stok yang "tersedia untuk produksi" (quantity yang sudah diterima) if ($pm->is_additional && $pm->is_received) { // Item request yang sudah diterima: stok yang tersedia = quantity yang sudah diterima $currentStock = $pm->quantity * $orderQty; $stockStatus = 'available'; $stockStatusLabel = 'Tersedia (Diterima)'; $stockStatusClass = 'bg-green-100 text-green-700'; } elseif ($currentStock < $totalNeeded) { if ($currentStock == 0) { $stockStatus = 'pending_purchase'; $stockStatusLabel = 'Perlu Pembelian'; $stockStatusClass = 'bg-red-100 text-red-700'; } else { $stockStatus = 'insufficient'; $stockStatusLabel = 'Kurang'; $stockStatusClass = 'bg-amber-100 text-amber-700'; } } $allItems->push([ 'id' => $pm->id, 'item_id' => $pm->material_id, 'type' => 'material', 'name' => $pm->material->name ?? 'N/A', 'quantity' => $pm->quantity, 'unit' => $pm->unit, 'unit_cost' => $pm->unit_cost, 'total_cost' => $pm->total_cost, 'stock' => $currentStock, 'total_needed' => $totalNeeded, 'stock_ok' => $currentStock >= $totalNeeded, 'stock_status' => $stockStatus, 'stock_status_label' => $stockStatusLabel, 'stock_status_class' => $stockStatusClass, 'is_received' => $pm->is_received ?? false, 'is_admin_suggested' => $pm->is_admin_suggested ?? false, 'revised_at' => $pm->revised_by_teknisi_at, 'is_additional' => $pm->is_additional ?? false, ]); } foreach ($production->productionSpareparts as $ps) { $totalNeeded = $ps->quantity * $orderQty; $currentStock = $ps->sparepart->stock ?? 0; $stockStatus = 'available'; $stockStatusLabel = 'Tersedia'; $stockStatusClass = 'bg-green-100 text-green-700'; // Untuk item request yang sudah diterima (is_additional = true dan is_received = true) // Stok di master barang sudah dikurangi saat admin kirim, jadi stok yang ditampilkan // adalah stok yang "tersedia untuk produksi" (quantity yang sudah diterima) if ($ps->is_additional && $ps->is_received) { // Item request yang sudah diterima: stok yang tersedia = quantity yang sudah diterima $currentStock = $ps->quantity * $orderQty; $stockStatus = 'available'; $stockStatusLabel = 'Tersedia (Diterima)'; $stockStatusClass = 'bg-green-100 text-green-700'; } elseif ($currentStock < $totalNeeded) { if ($currentStock == 0) { $stockStatus = 'pending_purchase'; $stockStatusLabel = 'Perlu Pembelian'; $stockStatusClass = 'bg-red-100 text-red-700'; } else { $stockStatus = 'insufficient'; $stockStatusLabel = 'Kurang'; $stockStatusClass = 'bg-amber-100 text-amber-700'; } } $allItems->push([ 'id' => $ps->id, 'item_id' => $ps->sparepart_id, 'type' => 'sparepart', 'name' => $ps->sparepart->name ?? 'N/A', 'quantity' => $ps->quantity, 'unit' => $ps->unit, 'unit_cost' => $ps->unit_cost, 'total_cost' => $ps->total_cost, 'stock' => $currentStock, 'total_needed' => $totalNeeded, 'stock_ok' => $currentStock >= $totalNeeded, 'stock_status' => $stockStatus, 'stock_status_label' => $stockStatusLabel, 'stock_status_class' => $stockStatusClass, 'is_received' => $ps->is_received ?? false, 'is_admin_suggested' => $ps->is_admin_suggested ?? false, 'revised_at' => $ps->revised_by_teknisi_at, 'is_additional' => $ps->is_additional ?? false, ]); } $totalCost = $allItems->sum('total_cost'); @endphp @if ($allItems->count() > 0)
@if ($canEdit) @elseif($canCheckReceived) @endif @foreach ($allItems as $item) @if ($canEdit) @elseif($canCheckReceived) @endif @endforeach
Nama Item Tipe Jumlah Satuan Harga/Unit Total Stok Status Ketersediaan Aksi Diterima
{{ $item['name'] }}
@if ($item['is_admin_suggested']) Admin @endif @if ($item['revised_at']) Direvisi @endif
@if ($item['type'] === 'material') Bahan @else Sparepart @endif {{ $item['quantity'] }} {{ $item['unit'] }} Rp {{ number_format($item['unit_cost'], 0, ',', '.') }} Rp {{ number_format($item['total_cost'], 0, ',', '.') }}
{{ $item['stock'] }} Butuh: {{ $item['total_needed'] }}
@if ($item['stock_status'] === 'available') @elseif($item['stock_status'] === 'insufficient') @else @endif {{ $item['stock_status_label'] }} @if ($item['stock_status'] !== 'available')
@if ($item['stock_status'] === 'insufficient') Kurang: {{ $item['total_needed'] - $item['stock'] }} {{ $item['unit'] }} @else Stok: 0 @endif
@endif
@if ($item['is_admin_suggested']) @endif
@if ($item['stock_ok']) @else @endif
@php $unavailableItems = $allItems->where('stock_ok', false); @endphp @if ($unavailableItems->count() > 0 && $canCheckReceived)

{{ $unavailableItems->count() }} item stok tidak mencukupi

Item dengan stok kurang tidak dapat di-checklist. Hubungi Admin untuk melakukan pembelian.

@foreach ($unavailableItems->take(5) as $item) {{ $item['name'] }} (stok: {{ $item['stock'] }}) @endforeach @if ($unavailableItems->count() > 5) +{{ $unavailableItems->count() - 5 }} lainnya @endif
@endif
Bahan: Rp {{ number_format($production->total_material_cost ?? 0, 0, ',', '.') }} Sparepart: Rp {{ number_format($production->total_sparepart_cost ?? 0, 0, ',', '.') }}
Total: Rp {{ number_format($totalCost, 0, ',', '.') }}
@else

Belum ada bahan atau sparepart ditambahkan

Klik "Tambah Item" untuk menambahkan

@endif
@if ( $production->planning_status === 'planning' || ($production->planning_status === 'approved' && in_array($production->status, ['menunggu', 'dalam_proses'])))

Request Item Baru

Butuh bahan/sparepart yang tidak ada di sistem? Request ke Admin

@if ($production->itemRequests && $production->itemRequests->count() > 0)

Request Anda:

@foreach ($production->itemRequests as $request)

{{ $request->item_name_display }}

{{ (int)$request->quantity }} {{ $request->unit }} • {{ Str::limit($request->reason, 40) }}

@if ($request->status === 'pending') {{ $request->status_label }} @elseif($request->status === 'approved') {{ $request->status_label }} @elseif($request->status === 'rejected') {{ $request->status_label }} @elseif($request->status === 'purchased') {{ $request->status_label }} @elseif($request->status === 'sent') {{ $request->status_label }} @elseif($request->status === 'received') {{ $request->status_label }} @endif @if (in_array($request->status, ['sent', 'purchased']) && in_array($production->status, ['menunggu', 'dalam_proses']))
@csrf
@endif
@endforeach
@endif
@endif {{-- ============================================== --}} {{-- TABEL USULAN PERTAMA, KEDUA, KETIGA --}} {{-- ============================================== --}} @php $proposalGroups = $production->itemRequests->groupBy('proposal_number')->sortKeys(); @endphp @if ($proposalGroups->count() > 0)

Usulan Bahan & Sparepart

Dikelompokkan berdasarkan usulan pertama, kedua, ketiga

@foreach ($proposalGroups as $proposalNumber => $requests)

{{ $proposalNumber ?? '1' }} Usulan {{ $proposalNumber == 1 ? 'Pertama' : ($proposalNumber == 2 ? 'Kedua' : ($proposalNumber == 3 ? 'Ketiga' : 'Ke-' . $proposalNumber)) }} {{ $requests->count() }} item

@foreach ($requests as $request) @php $quantity = (int)$request->quantity; // Ambil harga: prioritas dari relasi material/sparepart, jika tidak ada cari di master berdasarkan nama, terakhir pakai estimated_price $estimatedPrice = 0; if ($request->item_type === 'material' && $request->material) { $estimatedPrice = $request->material->price ?? $request->estimated_price ?? 0; } elseif ($request->item_type === 'sparepart' && $request->sparepart) { $estimatedPrice = $request->sparepart->price ?? $request->estimated_price ?? 0; } else { // Item baru: coba cari di master barang berdasarkan nama if ($request->item_name) { if ($request->item_type === 'material') { // Coba exact match dulu $foundMaterial = \App\Models\Material::where('name', $request->item_name)->first(); // Jika tidak ada, coba partial match if (!$foundMaterial) { $foundMaterial = \App\Models\Material::where('name', 'LIKE', '%' . trim($request->item_name) . '%')->first(); } if ($foundMaterial) { $estimatedPrice = $foundMaterial->price ?? $request->estimated_price ?? 0; } else { $estimatedPrice = $request->estimated_price ?? 0; } } else { // Coba exact match dulu $foundSparepart = \App\Models\Sparepart::where('name', $request->item_name)->first(); // Jika tidak ada, coba partial match if (!$foundSparepart) { $foundSparepart = \App\Models\Sparepart::where('name', 'LIKE', '%' . trim($request->item_name) . '%')->first(); } if ($foundSparepart) { $estimatedPrice = $foundSparepart->price ?? $request->estimated_price ?? 0; } else { $estimatedPrice = $request->estimated_price ?? 0; } } } else { $estimatedPrice = $request->estimated_price ?? 0; } } $totalPrice = $quantity * $estimatedPrice; // Ambil stok terbaru dari database (fresh) $currentStock = 0; if ($request->item_type === 'material' && $request->material_id) { $material = \App\Models\Material::find($request->material_id); $currentStock = $material ? $material->stock : 0; } elseif ($request->item_type === 'sparepart' && $request->sparepart_id) { $sparepart = \App\Models\Sparepart::find($request->sparepart_id); $currentStock = $sparepart ? $sparepart->stock : 0; } $totalNeeded = $quantity * ($production->quantity ?? 1); $stockStatus = 'available'; $stockStatusLabel = 'Tersedia'; $stockStatusClass = 'bg-green-100 dark:bg-green-900/40 text-green-700 dark:text-green-300'; $stockStatusIcon = 'check-circle'; if ($currentStock < $totalNeeded) { if ($currentStock == 0) { $stockStatus = 'pending_purchase'; $stockStatusLabel = 'Perlu Pembelian'; $stockStatusClass = 'bg-red-100 dark:bg-red-900/40 text-red-700 dark:text-red-300'; $stockStatusIcon = 'times-circle'; } else { $stockStatus = 'insufficient'; $stockStatusLabel = 'Perlu Pembelian (Kurang)'; $stockStatusClass = 'bg-amber-100 dark:bg-amber-900/40 text-amber-700 dark:text-amber-300'; $stockStatusIcon = 'exclamation-triangle'; } } @endphp @endforeach
Item Tipe Jumlah Satuan Harga/Unit Total Stok Status Ketersediaan Alasan Status Tanggal Aksi
{{ $request->item_name_display }}
@if ($request->is_new_item) Item Baru @endif
@if ($request->item_type === 'material') Bahan @else Sparepart @endif {{ $quantity }} {{ $request->unit }} @if($estimatedPrice > 0) Rp {{ number_format($estimatedPrice, 0, ',', '.') }} @else - @endif @if($totalPrice > 0) Rp {{ number_format($totalPrice, 0, ',', '.') }} @else - @endif
{{ $currentStock }} Butuh: {{ $totalNeeded }}
{{ $stockStatusLabel }} @if($stockStatus !== 'available')
@if($stockStatus === 'insufficient') Kurang: {{ $totalNeeded - $currentStock }} {{ $request->unit }} @else Stok: 0 @endif
@endif
{{ Str::limit($request->reason, 50) }} @if ($request->status === 'pending') @elseif($request->status === 'approved') @elseif($request->status === 'rejected') @elseif($request->status === 'purchased') @elseif($request->status === 'sent') @elseif($request->status === 'received') @endif {{ $request->status_label }} @if (in_array($request->status, ['sent', 'purchased']) && in_array($production->status, ['menunggu', 'dalam_proses']))
@csrf
@endif
{{ $request->requested_at->format('d/m/Y H:i') }} @if (in_array($request->status, ['sent', 'purchased']) && in_array($production->status, ['menunggu', 'dalam_proses']))
@csrf
@elseif($request->status === 'received') Sudah Dikonfirmasi @else - @endif
@endforeach
@endif @if ($production->planning_status === 'planning' || in_array($production->status, ['dalam_proses', 'selesai']))

Upah Jasa

@csrf

Pilih paket service untuk mengisi upah jasa otomatis, atau kosongkan untuk input manual

@if ($production->product->service_fee)

Default: Rp {{ number_format($production->product->service_fee, 0, ',', '.') }}

@endif

Default: {{ $production->quantity ?? $production->order->quantity ?? 1 }} paket (sesuai quantity order)

@php // Extract labor cost notes from production notes $laborCostNotes = ''; if ($production->notes) { // Cari bagian "Penjelasan Perhitungan Upah:" di notes if (strpos($production->notes, 'Penjelasan Perhitungan Upah:') !== false) { $parts = explode('Penjelasan Perhitungan Upah:', $production->notes, 2); if (isset($parts[1])) { // Ambil hanya bagian setelah "Penjelasan Perhitungan Upah:" // Hapus newline di awal jika ada $laborCostNotes = trim($parts[1]); } } } @endphp
@endif @php $laborTotal = $production->labor_cost ?? 0; $actualTotal = $directTotal + $laborTotal; @endphp
@if ($laborTotal > 0)

Biaya Tenaga Kerja

Upah untuk {{ $production->quantity ?? 1 }} unit

Rp {{ number_format($laborTotal, 0, ',', '.') }}

Per unit: Rp {{ number_format($laborTotal / max($production->quantity ?? 1, 1), 0, ',', '.') }}

@endif

Total Biaya Produksi

Langsung: Rp {{ number_format($directTotal, 0, ',', '.') }} @if ($laborTotal > 0) · Labor: Rp {{ number_format($laborTotal, 0, ',', '.') }} @endif

Rp {{ number_format($actualTotal, 0, ',', '.') }}

Per unit: Rp {{ number_format($actualTotal / max($production->quantity ?? 1, 1), 0, ',', '.') }}

@if ($production->planning_status === 'planning') @elseif($production->planning_status === 'pending_approval') Menunggu Approval @elseif($production->planning_status === 'approved' && $production->status === 'menunggu') @php $materialsReady = $production->productionMaterials->count() == 0 || $production->materials_status === 'received'; $sparepartsReady = $production->productionSpareparts->count() == 0 || $production->spareparts_status === 'received'; $allReady = $materialsReady && $sparepartsReady; @endphp @if ($allReady)
@csrf
@else Tunggu konfirmasi bahan diterima @endif @elseif($production->status === 'dalam_proses' && $production->completion_status !== 'pending_approval') @elseif($production->completion_status === 'pending_approval') Menunggu Approval Completion @endif Kembali
@endsection @php $materialsJson = $materials ->map(function ($m) { return ['id' => $m->id, 'name' => $m->name, 'unit' => $m->unit, 'price' => $m->price, 'stock' => $m->stock]; }) ->values(); $sparepartsJson = $spareparts ->map(function ($s) { return ['id' => $s->id, 'name' => $s->name, 'unit' => $s->unit, 'price' => $s->price, 'stock' => $s->stock]; }) ->values(); $usedMaterialIds = $production->productionMaterials->pluck('material_id')->values(); $usedSparepartIds = $production->productionSpareparts->pluck('sparepart_id')->values(); @endphp @push('scripts') @endpush