Certainly! Here’s a step-by-step solution for your requirements using Laravel, Livewire, and the bumbummen99/shoppingcart package.
1. Livewire Component Setup
Assume you have a Livewire component called InvoiceCart.
Properties
public $cartContents = [];
public $vatPercentage = 0;
public $advancePayment = 0;
public $subtotal = 0;
public $vatAmount = 0;
public $totalAmount = 0;
public $balance = 0;
public $errors = [];
Mount Method
public function mount()
{
$this->cartContents = \Cart::content()->toArray();
$this->calculateTotals();
}
2. Update Cart Item (Qty & Price) and Check Product Stock
public function updateCartItem($rowId, $qty, $price)
{
$cartItem = \Cart::get($rowId);
$product = \App\Models\Product::find($cartItem->id);
// Check stock
if ($qty > $product->qty) {
$this->errors[$rowId] = "Requested quantity exceeds available stock ({$product->qty}).";
return;
} else {
unset($this->errors[$rowId]);
}
// Update cart
\Cart::update($rowId, [
'qty' => $qty,
'price' => $price,
]);
$this->cartContents = \Cart::content()->toArray();
$this->calculateTotals();
}
3. Calculate Subtotal, VAT, Total, and Balance
public function calculateTotals()
{
$this->subtotal = \Cart::subtotal(2, '.', '');
$this->vatAmount = ($this->vatPercentage / 100) * $this->subtotal;
$this->totalAmount = $this->subtotal + $this->vatAmount;
$this->balance = $this->totalAmount - $this->advancePayment;
}
4. Update VAT or Advance Payment
public function updatedVatPercentage()
{
$this->calculateTotals();
}
public function updatedAdvancePayment()
{
$this->calculateTotals();
}
5. Blade Example
@foreach($cartContents as $rowId => $item)
<div>
<input type="number" wire:model.lazy="cartContents.{{ $rowId }}.qty"
wire:change="updateCartItem('{{ $rowId }}', {{ $item['qty'] }}, {{ $item['price'] }})">
<input type="number" wire:model.lazy="cartContents.{{ $rowId }}.price"
wire:change="updateCartItem('{{ $rowId }}', {{ $item['qty'] }}, {{ $item['price'] }})">
@if(isset($errors[$rowId]))
<span class="text-danger">{{ $errors[$rowId] }}</span>
@endif
</div>
@endforeach
<div>
Subtotal: {{ $subtotal }}
<input type="number" wire:model="vatPercentage"> VAT (%)
<br>
VAT Amount: {{ $vatAmount }}
<br>
Total: {{ $totalAmount }}
<br>
Advance Payment: <input type="number" wire:model="advancePayment">
<br>
Balance: {{ $balance }}
</div>
6. Notes
- Make sure to call
calculateTotals()after any cart update. - The error message is shown only for the product that exceeds stock.
- You can further improve UX by debouncing input or adding validation rules.
Let me know if you need more details or a full component code!