update
This commit is contained in:
@@ -30,7 +30,7 @@ class BiorepositoryController extends Controller
|
||||
|
||||
$data['cabinets'] = BioCabinet::with([
|
||||
'racks' => function ($query) {
|
||||
$query->orderBy('level', 'ASC')->orderBy('rack_number', 'ASC');
|
||||
$query->orderBy('rack_number', 'ASC')->orderBy('code', 'ASC');
|
||||
},
|
||||
'racks.specimens' => function ($query) {
|
||||
$query->orderBy('stored_at', 'ASC');
|
||||
@@ -79,10 +79,8 @@ class BiorepositoryController extends Controller
|
||||
'cabinet_id' => 'required|exists:bio_cabinets,id',
|
||||
'code' => 'required|max:50',
|
||||
'name' => 'required|max:150',
|
||||
'level' => 'required|integer|min:1',
|
||||
'rack_number' => 'required|integer|min:1',
|
||||
'box_number' => 'required|integer|min:1',
|
||||
'capacity' => 'required|integer|min:1',
|
||||
'level' => 'required|integer|min:4|max:6',
|
||||
'capacity' => 'required|integer|min:16|max:20',
|
||||
'notes' => 'nullable',
|
||||
]);
|
||||
|
||||
@@ -98,13 +96,15 @@ class BiorepositoryController extends Controller
|
||||
return back()->withErrors(['code' => 'Kode rack sudah dipakai pada lemari ini.'])->withInput();
|
||||
}
|
||||
|
||||
$nextRackNumber = ((int) BioRack::where('cabinet_id', $request->input('cabinet_id'))->max('rack_number')) + 1;
|
||||
|
||||
BioRack::create([
|
||||
'cabinet_id' => $request->input('cabinet_id'),
|
||||
'code' => $request->input('code'),
|
||||
'name' => $request->input('name'),
|
||||
'level' => $request->input('level'),
|
||||
'rack_number' => $request->input('rack_number'),
|
||||
'box_number' => $request->input('box_number'),
|
||||
'rack_number' => $nextRackNumber,
|
||||
'box_number' => 1,
|
||||
'capacity' => $request->input('capacity'),
|
||||
'notes' => $request->input('notes'),
|
||||
]);
|
||||
@@ -135,22 +135,26 @@ class BiorepositoryController extends Controller
|
||||
$expectedRackNo = $rack->rack_number ?: $rack->id;
|
||||
$expectedBoxNo = $rack->box_number ?: 1;
|
||||
|
||||
if ((int) $request->input('shelfnomor') !== (int) $rack->level ||
|
||||
(int) $request->input('raknomor') !== (int) $expectedRackNo ||
|
||||
if ((int) $request->input('raknomor') !== (int) $expectedRackNo ||
|
||||
(int) $request->input('boxnomor') !== (int) $expectedBoxNo) {
|
||||
return back()->withErrors(['slotnomor' => 'Posisi slot tidak sesuai dengan konfigurasi rack.'])->withInput();
|
||||
}
|
||||
|
||||
if ((int) $request->input('slotnomor') > (int) $rack->capacity) {
|
||||
return back()->withErrors(['slotnomor' => 'Slot melebihi kapasitas rack.'])->withInput();
|
||||
if ((int) $request->input('shelfnomor') < 1 || (int) $request->input('shelfnomor') > (int) $rack->level) {
|
||||
return back()->withErrors(['shelfnomor' => 'Shelf melebihi konfigurasi rack.'])->withInput();
|
||||
}
|
||||
|
||||
if ((int) $request->input('tubenomor') < 1 || (int) $request->input('tubenomor') > (int) $rack->capacity) {
|
||||
return back()->withErrors(['tubenomor' => 'Nomor tube melebihi kapasitas box pada shelf ini.'])->withInput();
|
||||
}
|
||||
|
||||
$slotTaken = BioSpecimen::where('rack_id', $rack->id)
|
||||
->where('slot_number', $request->input('slotnomor'))
|
||||
->where('shelf_number', $request->input('shelfnomor'))
|
||||
->where('tube_number', $request->input('tubenomor'))
|
||||
->exists();
|
||||
|
||||
if ($slotTaken) {
|
||||
return back()->withErrors(['slotnomor' => 'Slot ini sudah terisi spesimen.'])->withInput();
|
||||
return back()->withErrors(['tubenomor' => 'Posisi tube pada shelf ini sudah terisi spesimen.'])->withInput();
|
||||
}
|
||||
|
||||
$atccByUser = strtoupper(preg_replace('/[^A-Za-z0-9]/', '', Session::get('nama', 'UNKNOWN')));
|
||||
@@ -182,7 +186,7 @@ class BiorepositoryController extends Controller
|
||||
'category_storage' => $request->input('kategorisimpan'),
|
||||
'shelf_number' => $request->input('shelfnomor'),
|
||||
'rack_number' => $request->input('raknomor'),
|
||||
'slot_number' => $request->input('slotnomor'),
|
||||
'slot_number' => $request->input('shelfnomor'),
|
||||
'box_number' => $request->input('boxnomor'),
|
||||
'tube_number' => $request->input('tubenomor'),
|
||||
'bacteria_name' => $request->input('nmbakteri'),
|
||||
|
||||
@@ -34,6 +34,19 @@
|
||||
gap: 6px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.shelf-section {
|
||||
border: 1px dashed #bfd3e8;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
margin-top: 8px;
|
||||
background: #fbfdff;
|
||||
}
|
||||
.tube-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(10, minmax(24px, 1fr));
|
||||
gap: 5px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.slot-btn {
|
||||
border: 1px solid #bfd3e8;
|
||||
background: #f4f9ff;
|
||||
@@ -150,8 +163,8 @@
|
||||
<div class="alert alert-warning m-b-20">Belum ada data spesimen.</div>
|
||||
@endif
|
||||
|
||||
<h4 class="m-b-20">Visualisasi Lemari, Rack, dan Slot</h4>
|
||||
<p class="text-muted">Klik slot berwarna biru untuk mengisi spesimen. Slot merah artinya sudah terisi.</p>
|
||||
<h4 class="m-b-20">Visualisasi Lemari, Rack, Shelf, Box, dan Tube</h4>
|
||||
<p class="text-muted">Klik nomor tube berwarna biru untuk mengisi spesimen. Tube merah artinya sudah terisi.</p>
|
||||
|
||||
@forelse($cabinets as $cabinet)
|
||||
<div class="cabinet-visual">
|
||||
@@ -159,39 +172,47 @@
|
||||
<div class="rack-grid">
|
||||
@forelse($cabinet->racks as $rack)
|
||||
@php
|
||||
$slotMap = [];
|
||||
$tubeMap = [];
|
||||
foreach ($rack->specimens as $item) {
|
||||
if ($item->slot_number) {
|
||||
$slotMap[$item->slot_number] = $item;
|
||||
if ($item->shelf_number && $item->tube_number) {
|
||||
$tubeMap[$item->shelf_number.'-'.$item->tube_number] = $item;
|
||||
}
|
||||
}
|
||||
$capacity = (int) $rack->capacity;
|
||||
$shelfCount = (int) $rack->level;
|
||||
$tubeCapacity = (int) $rack->capacity;
|
||||
@endphp
|
||||
<div class="rack-box">
|
||||
<div class="rack-header">{{ $rack->code }} - {{ $rack->name }}</div>
|
||||
<div style="font-size:12px;">Shelf {{ $rack->level }} | Rack {{ $rack->rack_number ?? $rack->id }} | Box {{ $rack->box_number ?? 1 }}</div>
|
||||
<div style="font-size:12px;">Slot: {{ $capacity }} | Terisi: {{ $rack->specimens->count() }}</div>
|
||||
<div style="font-size:12px;">Rack No {{ $rack->rack_number ?? $rack->id }} | Total Shelf {{ $shelfCount }} | 1 Box per Shelf | Tube per Box {{ $tubeCapacity }}</div>
|
||||
<div style="font-size:12px;">Terisi: {{ $rack->specimens->count() }}</div>
|
||||
|
||||
@if($capacity > 0)
|
||||
<div class="slot-grid">
|
||||
@for($i = 1; $i <= $capacity; $i++)
|
||||
@if(isset($slotMap[$i]))
|
||||
<div class="slot-btn slot-filled" title="{{ $slotMap[$i]->specimen_code }} - {{ $slotMap[$i]->bacteria_name ?? $slotMap[$i]->specimen_name }}">{{ $i }}</div>
|
||||
@else
|
||||
<button type="button"
|
||||
class="slot-btn js-slot"
|
||||
data-rack-id="{{ $rack->id }}"
|
||||
data-shelf="{{ $rack->level }}"
|
||||
data-rackno="{{ $rack->rack_number ?? $rack->id }}"
|
||||
data-slot="{{ $i }}"
|
||||
data-box="{{ $rack->box_number ?? 1 }}">
|
||||
{{ $i }}
|
||||
</button>
|
||||
@endif
|
||||
@endfor
|
||||
</div>
|
||||
@if($shelfCount > 0 && $tubeCapacity > 0)
|
||||
@for($shelf = 1; $shelf <= $shelfCount; $shelf++)
|
||||
<div class="shelf-section">
|
||||
<div style="font-size:12px;"><b>Shelf {{ $shelf }}</b> - Box 1 (Tube 1-{{ $tubeCapacity }})</div>
|
||||
<div class="tube-grid">
|
||||
@for($tube = 1; $tube <= $tubeCapacity; $tube++)
|
||||
@php $tubeKey = $shelf.'-'.$tube; @endphp
|
||||
@if(isset($tubeMap[$tubeKey]))
|
||||
<div class="slot-btn slot-filled" title="{{ $tubeMap[$tubeKey]->specimen_code }} - {{ $tubeMap[$tubeKey]->bacteria_name ?? $tubeMap[$tubeKey]->specimen_name }}">{{ $tube }}</div>
|
||||
@else
|
||||
<button type="button"
|
||||
class="slot-btn js-slot"
|
||||
data-rack-id="{{ $rack->id }}"
|
||||
data-shelf="{{ $shelf }}"
|
||||
data-rackno="{{ $rack->rack_number ?? $rack->id }}"
|
||||
data-slot="{{ $shelf }}"
|
||||
data-box="1"
|
||||
data-tube="{{ $tube }}">
|
||||
{{ $tube }}
|
||||
</button>
|
||||
@endif
|
||||
@endfor
|
||||
</div>
|
||||
</div>
|
||||
@endfor
|
||||
@else
|
||||
<div class="alert alert-light m-b-0 m-t-10">Kapasitas slot belum diatur.</div>
|
||||
<div class="alert alert-light m-b-0 m-t-10">Konfigurasi rack belum lengkap.</div>
|
||||
@endif
|
||||
</div>
|
||||
@empty
|
||||
@@ -343,23 +364,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-3">
|
||||
<label>Shelf</label>
|
||||
<input type="number" name="level" class="form-control" min="1" value="1" required>
|
||||
<div class="form-group col-md-6">
|
||||
<label>Jumlah Shelf per Rack (4-6)</label>
|
||||
<input type="number" name="level" class="form-control" min="4" max="6" value="4" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>Rack No</label>
|
||||
<input type="number" name="rack_number" class="form-control" min="1" value="1" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>Box No</label>
|
||||
<input type="number" name="box_number" class="form-control" min="1" value="1" required>
|
||||
</div>
|
||||
<div class="form-group col-md-3">
|
||||
<label>Jumlah Slot</label>
|
||||
<input type="number" name="capacity" class="form-control" min="1" value="24" required>
|
||||
<div class="form-group col-md-6">
|
||||
<label>Tube per Box (16-20)</label>
|
||||
<input type="number" name="capacity" class="form-control" min="16" max="20" value="16" required>
|
||||
</div>
|
||||
</div>
|
||||
<small class="text-muted">Rack number dibuat otomatis oleh sistem. Struktur: 1 rack memiliki 4-6 shelf, setiap shelf memiliki 1 box, setiap box 16-20 tube.</small>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Batal</button>
|
||||
@@ -404,16 +418,16 @@
|
||||
<input type="number" class="form-control" id="raknomor" name="raknomor" readonly>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<label>Slot Number</label>
|
||||
<label>Slot Number (Sama dengan Shelf)</label>
|
||||
<input type="number" class="form-control" id="slotnomor" name="slotnomor" readonly>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<label>Box Number</label>
|
||||
<label>Box Number (1 per Shelf)</label>
|
||||
<input type="number" class="form-control" id="boxnomor" name="boxnomor" readonly>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<label>Tube Number</label>
|
||||
<input type="number" class="form-control" id="tubenomor" name="tubenomor" required>
|
||||
<input type="number" class="form-control" id="tubenomor" name="tubenomor" readonly required>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<label>Tanggal Simpan</label>
|
||||
@@ -474,7 +488,7 @@
|
||||
$('#raknomor').val($(this).data('rackno'));
|
||||
$('#slotnomor').val($(this).data('slot'));
|
||||
$('#boxnomor').val($(this).data('box'));
|
||||
$('#tubenomor').val('');
|
||||
$('#tubenomor').val($(this).data('tube'));
|
||||
buildSampleCodePreview();
|
||||
$('#modalIsiSlot').modal('show');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user