feat: Improve stock opname input handling by using number input, allowing null physical quantities, adding a 'fill with zero' option, and refining progress percentage calculation.

This commit is contained in:
Yoga Pangestu 2026-02-23 22:10:25 +07:00
parent d2b764d3f4
commit 6af61d9dd3
5 changed files with 37 additions and 18 deletions

View File

@ -54,7 +54,11 @@ public function update(): void
continue; continue;
} }
$item->qty_physical = (int) str_replace('.', '', (string) ($qtyPhysical ?? 0)); // Bersihkan nilai: hapus separator ribuan (titik), trim whitespace
$normalizedQty = trim(str_replace('.', '', (string) ($qtyPhysical ?? '')));
// Simpan null jika input kosong/tidak diisi, integer jika ada nilai
$item->qty_physical = $normalizedQty !== '' ? (int) $normalizedQty : null;
$item->save(); $item->save();
} }

View File

@ -110,7 +110,7 @@ public function render(): View
->whereNotNull('qty_physical') ->whereNotNull('qty_physical')
->count(); ->count();
$percent = $total > 0 ? round(($filled / $total) * 100) : 0; $percent = $total > 0 ? floor(($filled / $total) * 100) : 0;
$stockOpname->total_item = $total; $stockOpname->total_item = $total;
$stockOpname->progress_filled = $filled; $stockOpname->progress_filled = $filled;

View File

@ -53,6 +53,14 @@ public function save(): void
], navigate: true); ], navigate: true);
} }
public function fillAllWithZero(): void
{
$this->form->outlet_stock = array_map(
fn ($qty) => $qty === null || $qty === '' ? 0 : $qty,
$this->form->outlet_stock
);
}
public function render(): View public function render(): View
{ {
$items = StockOpnameItem::with('itemable') $items = StockOpnameItem::with('itemable')

View File

@ -69,16 +69,13 @@
</flux:tooltip> </flux:tooltip>
@if ($item->progress_percent == 100) @if ($item->progress_percent == 100)
<flux:modal.trigger name="delete-confirmation"> <flux:modal.trigger name="request-confirmation">
<flux:tooltip content="Ajukan Persetujuan"> <flux:tooltip content="Ajukan Persetujuan">
<flux:button variant="primary" color="emerald" icon="document-check" <flux:button variant="primary" color="emerald" icon="document-check"
size="sm" size="sm"
wire:click="$dispatch('fn:confirmAction', { wire:click="$dispatch('fn:confirmAction', {
id : '{{ $item->hash }}', id : '{{ $item->hash }}',
message: 'Pastikan proses stock opname sudah tepat dan sesuai.', target: 'requestApproval'
confirmButtonText: 'Ajukan',
target: 'requestApproval',
confirmButtonColor : 'emerald'
})"> })">
</flux:button> </flux:button>
</flux:tooltip> </flux:tooltip>
@ -87,15 +84,12 @@
@endif @endif
@if ($item->status === \App\Enums\StockOpnameStatus::PENDING_APPROVAL && auth()->user()->can('approve stock opname')) @if ($item->status === \App\Enums\StockOpnameStatus::PENDING_APPROVAL && auth()->user()->can('approve stock opname'))
<flux:modal.trigger name="delete-confirmation"> <flux:modal.trigger name="approve-confirmation">
<flux:tooltip content="Setujui"> <flux:tooltip content="Setujui">
<flux:button variant="primary" color="emerald" icon="check-circle" size="sm" <flux:button variant="primary" color="emerald" icon="check-circle" size="sm"
wire:click="$dispatch('fn:confirmAction', { wire:click="$dispatch('fn:confirmAction', {
id : '{{ $item->hash }}', id : '{{ $item->hash }}',
message: 'Proses ini akan menyesuaikan kembali stok barang dengan hasil inputan dan proes tidak dapat dibatalkan, silakan periksa kembali dengan benar.', target: 'approveApproval'
confirmButtonText: 'Ajukan',
target: 'approveApproval',
confirmButtonColor : 'emerald'
})"> })">
</flux:button> </flux:button>
</flux:tooltip> </flux:tooltip>
@ -110,11 +104,21 @@
</div> </div>
@include('components.modals.confirmation', [ @include('components.modals.confirmation', [
'modalName' => 'delete-confirmation', 'modalName' => 'request-confirmation',
'modalTitle' => 'Apakah Anda yakin?', 'modalTitle' => 'Apakah Anda yakin?',
'modalMessage' => 'Data yang berelasi dengan data ini juga akan ikut terhapus.', 'modalMessage' => 'Pastikan proses stock opname sudah tepat dan sesuai.',
'buttonVariant' => 'primary', 'buttonVariant' => 'primary',
'buttonColor' => 'danger', 'buttonColor' => 'danger',
'buttonText' => 'Ya, Hapus', 'buttonText' => 'Ya, Ajukan',
])
@include('components.modals.confirmation', [
'modalName' => 'approve-confirmation',
'modalTitle' => 'Apakah Anda yakin?',
'modalMessage' =>
'Proses ini akan menyesuaikan kembali stok barang dengan hasil inputan dan proes tidak dapat dibatalkan, silakan periksa kembali dengan benar.',
'buttonVariant' => 'primary',
'buttonColor' => 'danger',
'buttonText' => 'Ya, Setujui',
]) ])
</flux:main> </flux:main>

View File

@ -33,8 +33,8 @@
</flux:table.cell> </flux:table.cell>
<flux:table.cell>{{ $item->qty_system }}</flux:table.cell> <flux:table.cell>{{ $item->qty_system }}</flux:table.cell>
<flux:table.cell> <flux:table.cell>
<flux:input wire:model="form.outlet_stock.{{ $item->id }}" <flux:input type="number" min="0" step="1"
x-mask:dynamic="$money($input, ',')" autocomplete="off" /> wire:model="form.outlet_stock.{{ $item->id }}" autocomplete="off" />
</flux:table.cell> </flux:table.cell>
<flux:table.cell variant="strong"> <flux:table.cell variant="strong">
{{ $item->difference }} {{ $item->difference }}
@ -50,7 +50,10 @@
autocomplete="off" rows="2" /> autocomplete="off" rows="2" />
</flux:card> </flux:card>
<div class="flex justify-start"> <div class="flex justify-start gap-2">
<flux:button wire:click="fillAllWithZero">
Isi Kosong dengan 0
</flux:button>
<flux:button variant="primary" class="sm:w-auto cursor-pointer" wire:click="save"> <flux:button variant="primary" class="sm:w-auto cursor-pointer" wire:click="save">
Simpan Simpan
</flux:button> </flux:button>