feat(expense): add outlet selection for expenses and update form handling

This commit is contained in:
Yoga Pangestu 2025-10-16 21:50:32 +07:00
parent e9e5975e57
commit 2b101764a8
4 changed files with 40 additions and 5 deletions

View File

@ -25,6 +25,9 @@ public function columns(): array
->format(fn ($value) => currency($value, 'Rp')) ->format(fn ($value) => currency($value, 'Rp'))
->searchable(), ->searchable(),
Column::make('Outlet', 'outlet.name')
->searchable(),
Column::make('Aksi') Column::make('Aksi')
->label(function ($row) { ->label(function ($row) {
$actions = ''; $actions = '';
@ -52,6 +55,6 @@ public function columns(): array
public function builder(): Builder public function builder(): Builder
{ {
return Expense::select('id', 'description', 'amount'); return Expense::select('expenses.id', 'description', 'amount')->with('outlet');
} }
} }

View File

@ -7,6 +7,7 @@
use App\Rules\UnsignedInteger; use App\Rules\UnsignedInteger;
use App\Traits\WithMediaHandler; use App\Traits\WithMediaHandler;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Livewire\Form; use Livewire\Form;
class ExpenseForm extends Form class ExpenseForm extends Form
@ -19,6 +20,8 @@ class ExpenseForm extends Form
public string $amount = ''; public string $amount = '';
public string $outlet_id = '';
public array $image = []; public array $image = [];
public function rules(): array public function rules(): array
@ -26,6 +29,7 @@ public function rules(): array
return [ return [
'description' => ['required', 'string', 'max:100'], 'description' => ['required', 'string', 'max:100'],
'amount' => ['required', new UnsignedInteger], 'amount' => ['required', new UnsignedInteger],
'outlet_id' => [Rule::requiredIf(auth()->user()->outlets()->count() > 1), Rule::exists('outlets', 'id')],
'image' => ['nullable', 'array'], 'image' => ['nullable', 'array'],
]; ];
} }
@ -45,6 +49,7 @@ public function setExpense(Expense $expense)
$this->description = $expense->description; $this->description = $expense->description;
$this->amount = $expense->amount; $this->amount = $expense->amount;
$this->outlet_id = $expense->outlet_id;
$this->image = $this->mapMediaCollection($expense->getMedia('image')); $this->image = $this->mapMediaCollection($expense->getMedia('image'));
} }
@ -57,7 +62,8 @@ public function store()
$expense = Expense::create([ $expense = Expense::create([
'type' => ExpenseType::OPERATIONAL, 'type' => ExpenseType::OPERATIONAL,
'description' => $this->description, 'description' => $this->description,
'amount' => $this->amount, 'amount' => replaceCurrency($this->amount),
'outlet_id' => auth()->user()->outlets()->count() > 1 ? $this->outlet_id : auth()->user()->outlets()->first()->id,
]); ]);
$this->uploadMedia($this->image, $expense, 'image'); $this->uploadMedia($this->image, $expense, 'image');
@ -71,7 +77,7 @@ public function update()
DB::transaction(function () { DB::transaction(function () {
$this->expense->update([ $this->expense->update([
'description' => $this->description, 'description' => $this->description,
'amount' => $this->amount, 'amount' => replaceCurrency($this->amount),
]); ]);
$this->syncMedia($this->image, $this->expense, 'image'); $this->syncMedia($this->image, $this->expense, 'image');

View File

@ -4,6 +4,7 @@
use App\Livewire\Forms\Studio\Finance\ExpenseForm; use App\Livewire\Forms\Studio\Finance\ExpenseForm;
use App\Models\Expense as ExpenseModel; use App\Models\Expense as ExpenseModel;
use App\Models\Outlet;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
use App\Traits\WithCloseModal; use App\Traits\WithCloseModal;
use App\Traits\WithConfirmation; use App\Traits\WithConfirmation;
@ -21,10 +22,21 @@ class Expense extends Component
public ExpenseForm $form; public ExpenseForm $form;
public array $outlets = [];
public bool $userHasMultipleOutlets = false;
public string $method = 'create'; public string $method = 'create';
public string $modalTitle = ''; public string $modalTitle = '';
public function mount()
{
$this->outlets = Outlet::pluck('name', 'id')->toArray();
$this->userHasMultipleOutlets = auth()->user()->outlets()->count() > 1;
}
#[On('modal:open')] #[On('modal:open')]
public function openModal(string $method, string $modalTitle, ?string $id = null) public function openModal(string $method, string $modalTitle, ?string $id = null)
{ {

View File

@ -26,8 +26,8 @@
<flux:field> <flux:field>
<flux:label>Keterangan <span class="text-red-500 ms-1">*</span></flux:label> <flux:label>Keterangan <span class="text-red-500 ms-1">*</span></flux:label>
<flux:input placeholder="Masukkan keterangan" wire:model.live.debounce.500ms="form.description" <flux:input placeholder="Beli kuota" wire:model.live.debounce.500ms="form.description" autofocus
autofocus autocomplete="off" /> autocomplete="off" />
<flux:error name="form.description" /> <flux:error name="form.description" />
</flux:field> </flux:field>
@ -42,6 +42,20 @@
<flux:error name="form.amount" /> <flux:error name="form.amount" />
</flux:field> </flux:field>
@if ($userHasMultipleOutlets)
<flux:field>
<flux:label>Outlet <span class="text-red-500 ms-1">*</span></flux:label>
<flux:select variant="listbox" searchable placeholder="Pilih Outlet"
wire:model.live.debounce.500ms="form.outlet_id">
@foreach ($outlets as $key => $value)
<flux:select.option value="{{ $key }}">{{ $value }}
</flux:select.option>
@endforeach
</flux:select>
<flux:error name="form.outlet_id" />
</flux:field>
@endif
<div class="space-y-3"> <div class="space-y-3">
<h3 class="text-sm font-medium">Gambar</h3> <h3 class="text-sm font-medium">Gambar</h3>
<div class="dropzone-wrapper"> <div class="dropzone-wrapper">