refactor(purchase): mengubah nama dan penyimpanan var untuk menampung items dari cartItems ke purchaseItems dan dipindahkan ke component create bukan lagi form

- membuat trait baru untuk calculate total
- menyesuaikan perubahan di atas
This commit is contained in:
Yoga Pangestu 2025-10-30 19:29:18 +07:00
parent 4fbb18b1ce
commit 6343802fd5
8 changed files with 71 additions and 31 deletions

View File

@ -4,6 +4,7 @@
use App\Models\Purchase; use App\Models\Purchase;
use App\Rules\UnsignedInteger; use App\Rules\UnsignedInteger;
use App\Traits\Purchase\WithPurchaseItems;
use App\Traits\Purchase\WithUpdateStock; use App\Traits\Purchase\WithUpdateStock;
use App\Traits\WithMediaHandler; use App\Traits\WithMediaHandler;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -12,7 +13,7 @@
class PurchaseForm extends Form class PurchaseForm extends Form
{ {
use WithMediaHandler, WithUpdateStock; use WithMediaHandler, WithPurchaseItems, WithUpdateStock;
public ?Purchase $purchase = null; public ?Purchase $purchase = null;
@ -44,14 +45,12 @@ class PurchaseForm extends Form
public string $quantity_edit = ''; public string $quantity_edit = '';
public $cartItems;
public function rules(): array public function rules(): array
{ {
return [ return [
'invoice_number' => ['nullable', 'string', 'max:50'], 'invoice_number' => ['nullable', 'string', 'max:50'],
'note' => ['nullable', 'string', 'max:100'], 'note' => ['nullable', 'string', 'max:100'],
'purchase_date' => ['required', 'date'], 'purchase_date' => ['required', 'date', 'before_or_equal:today'],
'outlet_id' => ['required', Rule::exists('outlets', 'id')], 'outlet_id' => ['required', Rule::exists('outlets', 'id')],
'total' => ['required', new UnsignedInteger], 'total' => ['required', new UnsignedInteger],
'image' => ['nullable', 'array', 'max:1'], 'image' => ['nullable', 'array', 'max:1'],
@ -86,14 +85,16 @@ public function store()
{ {
$this->validate(); $this->validate();
DB::transaction(function () { $purchaseItems = $this->loadPurchaseItems();
DB::transaction(function () use ($purchaseItems) {
$purchase = Purchase::create($this->prepareSavedData()); $purchase = Purchase::create($this->prepareSavedData());
$purchase->load('outlet'); $purchase->load('outlet');
$this->uploadMedia($this->image, $purchase, 'image'); $this->uploadMedia($this->image, $purchase, 'image');
foreach ($this->cartItems as $item) { foreach ($purchaseItems as $item) {
$item->update(['purchase_id' => $purchase->id]); $item->update(['purchase_id' => $purchase->id]);
$this->increaseOutletStock($purchase->outlet, $item); $this->increaseOutletStock($purchase->outlet, $item);

View File

@ -7,9 +7,10 @@
use App\Models\Outlet; use App\Models\Outlet;
use App\Models\Perfume; use App\Models\Perfume;
use App\Models\Product; use App\Models\Product;
use App\Models\PurchaseItem;
use App\Traits\Purchase\WithAddItem; use App\Traits\Purchase\WithAddItem;
use App\Traits\Purchase\WithCalculateTotal;
use App\Traits\Purchase\WithDeleteItem; use App\Traits\Purchase\WithDeleteItem;
use App\Traits\Purchase\WithPurchaseItems;
use App\Traits\Purchase\WithUpdateItem; use App\Traits\Purchase\WithUpdateItem;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
use App\Traits\WithConfirmation; use App\Traits\WithConfirmation;
@ -21,7 +22,7 @@
#[Title('Tambah Belanja')] #[Title('Tambah Belanja')]
class Create extends Component class Create extends Component
{ {
use WithAddItem, WithAuthorization, WithConfirmation, WithDeleteItem, WithToast, WithUpdatedData, WithUpdateItem; use WithAddItem, WithAuthorization, WithCalculateTotal, WithConfirmation, WithDeleteItem, WithPurchaseItems, WithToast, WithUpdatedData, WithUpdateItem;
public PurchaseForm $form; public PurchaseForm $form;
@ -33,6 +34,8 @@ class Create extends Component
public array $bottles = []; public array $bottles = [];
public $purchaseItems;
public function mount() public function mount()
{ {
$this->outlets = Outlet::pluck('name', 'id')->toArray(); $this->outlets = Outlet::pluck('name', 'id')->toArray();
@ -43,14 +46,14 @@ public function mount()
$this->bottles = Bottle::pluck('name', 'id')->toArray(); $this->bottles = Bottle::pluck('name', 'id')->toArray();
$this->form->cartItems = PurchaseItem::whereNull('purchase_id')->get(); $this->purchaseItems = $this->loadPurchaseItems();
$this->form->total = currency($this->form->cartItems->sum('total_price'), ''); $this->form->total = $this->getTotal();
} }
public function save() public function save()
{ {
if ($this->form->cartItems->isEmpty()) { if ($this->purchaseItems->isEmpty()) {
$this->toast('Keranjang tidak boleh kosong.', 'Gagal', 'danger'); $this->toast('Keranjang tidak boleh kosong.', 'Gagal', 'danger');
return; return;

View File

@ -59,7 +59,7 @@ public function addItem(string $type)
return; return;
} }
$existingItem = $this->form->cartItems $existingItem = $this->purchaseItems
->where('purchasable_type', $model) ->where('purchasable_type', $model)
->where('purchasable_id', $itemModel->id) ->where('purchasable_id', $itemModel->id)
->first(); ->first();
@ -71,11 +71,12 @@ public function addItem(string $type)
$existingItem->refresh(); $existingItem->refresh();
$this->form->cartItems = $this->form->cartItems->map(fn ($i) => $i->id === $existingItem->id ? $existingItem : $i); $this->purchaseItems = $this->purchaseItems->map(fn ($i) => $i->id === $existingItem->id ? $existingItem : $i);
$this->toast('Jumlah '.$type.' diperbarui di keranjang.', 'Berhasil'); $this->toast('Jumlah '.$type.' diperbarui di keranjang.', 'Berhasil');
} else { } else {
$item = PurchaseItem::create([ $item = PurchaseItem::create([
'user_id' => auth()->id(),
'purchasable_id' => $itemModel->id, 'purchasable_id' => $itemModel->id,
'purchasable_type' => $model, 'purchasable_type' => $model,
'quantity' => $quantity, 'quantity' => $quantity,
@ -83,18 +84,25 @@ public function addItem(string $type)
'total_price' => $costPrice * $quantity, 'total_price' => $costPrice * $quantity,
]); ]);
$this->form->cartItems->push($item); $this->purchaseItems->push($item);
$this->toast(Str::ucfirst($type).' ditambahkan ke keranjang.', 'Berhasil'); $this->toast(Str::ucfirst($type).' ditambahkan ke keranjang.', 'Berhasil');
} }
$this->form->total = currency($this->form->cartItems->sum('total_price'), ''); $this->form->total = currency($this->getTotal());
$this->reset('form.perfume_id'); switch ($type) {
$this->reset('form.product_id'); case 'parfum':
$this->reset('form.bottle_id'); $this->reset(['form.perfume_id', 'form.quantity_perfume']);
$this->reset('form.quantity_perfume'); break;
$this->reset('form.quantity_product');
$this->reset('form.quantity_bottle'); case 'produk':
$this->reset(['form.product_id', 'form.quantity_product']);
break;
case 'botol':
$this->reset(['form.bottle_id', 'form.quantity_bottle']);
break;
}
} }
} }

View File

@ -0,0 +1,11 @@
<?php
namespace App\Traits\Purchase;
trait WithCalculateTotal
{
public function getTotal()
{
return $this->purchaseItems->sum(fn ($item) => $item->unit_price * $item->quantity);
}
}

View File

@ -8,11 +8,11 @@ trait WithDeleteItem
{ {
public function deleteItem(PurchaseItem $item) public function deleteItem(PurchaseItem $item)
{ {
$this->form->cartItems = $this->form->cartItems->reject(fn ($i) => $i->id === $item->id); $this->purchaseItems = $this->purchaseItems->reject(fn ($i) => $i->id === $item->id);
$item->delete(); $item->delete();
$this->form->total = currency($this->form->cartItems->sum('total_price'), ''); $this->form->total = currency($this->purchaseItems->sum('total_price'), '');
$this->toast('Item berhasil dihapus.'); $this->toast('Item berhasil dihapus.');
} }

View File

@ -0,0 +1,18 @@
<?php
namespace App\Traits\Purchase;
use App\Models\PurchaseItem;
trait WithPurchaseItems
{
public function loadPurchaseItems()
{
return $this->purchaseItems = PurchaseItem::query()
->currentUser()
->where('user_id', auth()->id())
->whereNull('purchase_id')
->latest()
->get();
}
}

View File

@ -17,7 +17,7 @@ public function openModal(PurchaseItem $item)
$this->form->item_id = $item->id; $this->form->item_id = $item->id;
$this->form->quantity_edit = currency($item->quantity, ''); $this->form->quantity_edit = currency($item->quantity);
} }
public function closeModal() public function closeModal()
@ -36,9 +36,9 @@ public function updateItem()
$item->refresh(); $item->refresh();
$this->form->cartItems = $this->form->cartItems->map(fn ($i) => $i->id === $item->id ? $item : $i); $this->purchaseItems = $this->purchaseItems->map(fn ($i) => $i->id === $item->id ? $item : $i);
$this->form->total = currency($this->form->cartItems->sum('total_price'), ''); $this->form->total = currency($this->purchaseItems->sum('total_price'));
$this->toast('Item berhasil diperbarui.'); $this->toast('Item berhasil diperbarui.');

View File

@ -15,7 +15,7 @@
<div class="w-full lg:w-3/4 space-y-4"> <div class="w-full lg:w-3/4 space-y-4">
<flux:card class="space-y-6 p-6"> <flux:card class="space-y-6 p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<flux:input label="Nomor Invoice" placeholder="INV-2025-0001" <flux:input label="Nomor Faktur" placeholder="INV-2025-0001"
wire:model.live.debounce.500ms="form.invoice_number" autofocus autocomplete="off" /> wire:model.live.debounce.500ms="form.invoice_number" autofocus autocomplete="off" />
<flux:input label="Catatan" placeholder="Belanja pas hujan" <flux:input label="Catatan" placeholder="Belanja pas hujan"
@ -96,9 +96,8 @@
<flux:select.option value="{{ $key }}">{{ $bottle }}</flux:select.option> <flux:select.option value="{{ $key }}">{{ $bottle }}</flux:select.option>
@endforeach @endforeach
</flux:select> </flux:select>
<flux:input label="Kuantitas" placeholder="50" <flux:input label="Kuantitas" placeholder="50" wire:model.live="form.quantity_bottle"
wire:model.live="form.quantity_bottle" autocomplete="off" autocomplete="off" x-mask:dynamic="$money($input, ',')" />
x-mask:dynamic="$money($input, ',')" />
<div class="flex justify-end"> <div class="flex justify-end">
<flux:button variant="primary" color="zinc" wire:click="addItem('botol')"> <flux:button variant="primary" color="zinc" wire:click="addItem('botol')">
@ -136,7 +135,7 @@
</flux:table.columns> </flux:table.columns>
<flux:table.rows> <flux:table.rows>
@forelse($form->cartItems as $item) @forelse($purchaseItems as $item)
<flux:table.row> <flux:table.row>
<flux:table.cell> <flux:table.cell>
<flux:heading> <flux:heading>