There should be a better way to do this (Refer to the mount method)
foreach ($bill->billItems as $billItem) {
$this->billTotal += $billItem->qty * $billItem->rate;
}
foreach ($bill->billAccounts as $billAccount) {
$this->billTotal += $billAccount->amount;
}
The entire livewire class looks like this
<?php
namespace App\Http\Livewire;
use Carbon\Carbon;
use App\Models\Bill;
use App\Models\Comp;
use App\Models\Item;
use App\Models\Account;
use App\Models\Company;
use Livewire\Component;
use App\Models\BillItem;
use App\Models\Category;
use App\Models\BillAccount;
use Illuminate\Http\Request;
use Livewire\WithFileUploads;
class BillForm extends Component
{
use WithFileUploads;
public Bill $bill;
public BillItem $billItem;
public BillAccount $billAccount;
public $users;
public $companies;
public $comps;
public $categories;
public $items;
public $accounts;
public $billItems;
public $billAccounts;
public $billTotal;
public $billItemAmount;
public $confirmingBillItemDeletion = false;
public $confirmingBillAccountDeletion = false;
public $selectedCompany = null;
//public $selectedUser = null;
public $selectedComp = 1;
public $selectedCategory = null;
public $selectedItem = null;
public $selectedAccount = null;
protected function rules()
{
return [
'bill.company_id' => 'required',
'bill.comp_id' => 'required',
'bill.reference' => 'nullable',
'bill.description' => 'nullable',
'bill.date' => 'nullable',
'billItem.bill_id' => 'nullable',
'billItem.item_id' => 'nullable',
'billItem.job_id' => 'nullable',
'billItem.account_id' => 'nullable',
'billItem.description' => 'nullable',
'billItem.qty' => 'nullable',
'billItem.rate' => 'nullable',
'billItemAmount' => 'nullable',
'billAccount.account_id' => 'nullable',
'billAccount.description' => 'nullable',
'billAccount.amount' => 'nullable',
];
}
//Customize validation
protected $validationAttributes = [
'selectedCompany' => 'provider',
'selectedCategory' => 'category',
'selectedItem' => 'item',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function updatedSelectedCategory()
{
$category_id = $this->selectedCategory;
$category = Category::findOrFail($category_id);
$this->items = $category->items;
$this->selectedItem = $category->items->first()->id;
}
public function updatedBillItemQty()
{
$this->billItem->rate = $this->billItemAmount / $this->billItem->qty;
}
public function updatedBillItemRate()
{
$this->billItemAmount = $this->billItem->qty * $this->billItem->rate;
}
public function updatedBillItemAmount()
{
$this->billItem->rate = $this->billItemAmount / $this->billItem->qty;
}
// Delete BillItem Show Modal
public function confirmBillItemDeletion($id)
{
$this->confirmingBillItemDeletion = $id;
}
// Delete BillItem
public function deleteBillItem(BillItem $billItem)
{
$billItem->delete();
$this->confirmingBillItemDeletion = false;
return redirect(request()->header('Referer')); //To refresh the page
}
// Delete BillItem Show Modal
public function confirmBillAccountDeletion($id)
{
$this->confirmingBillAccountDeletion = $id;
}
// Delete BillAccount
public function deleteBillAccount(BillAccount $billAccount)
{
$billAccount->delete();
$this->confirmingBillAccountDeletion = false;
return redirect(request()->header('Referer')); //To refresh the page
}
public function mount(Bill $bill, BillItem $billItem, BillAccount $billAccount)
{
$this->bill = $bill ?? new Bill();
$this->billItem = $billItem ?? new BillItem();
$this->billAccount = $billAccount ?? new BillAccount();
$this->bill->date = Carbon::now()->format('Y-m-d');
$this->bill->comp_id = 1;
$this->companies = Company::all()->sortBy('name');
$this->comps = Comp::all();
$this->categories = Category::all();
$this->items = Item::all();
$this->accounts = Account::all();
if($bill->billItems->count() > 0 )
{
$this->billItems = $bill->billItems; //To display existing billItems
}
if($bill->billAccounts->count() > 0 )
{
$this->billAccounts = $bill->billAccounts;
}
foreach ($bill->billItems as $billItem) {
$this->billTotal += $billItem->qty * $billItem->rate;
}
foreach ($bill->billAccounts as $billAccount) {
$this->billTotal += $billAccount->amount;
}
}
public function save($action)
{
//$this->validate();
// Bill is in create mode
if($this->bill->id == null)
{
$this->validate([
'bill.company_id' => 'required',
'bill.comp_id' => 'required',
'bill.reference' => 'nullable',
'bill.date' => 'nullable',
'bill.description' => 'nullable',
]);
Bill::create([
'company_id' => $this->bill->company_id,
'comp_id' => $this->bill->comp_id,
'date' => $this->bill->date,
'reference' => $this->bill->reference,
'description' => $this->bill->description,
'entered_by' => null,
'verified_by' => null,
'paid_by' => null,
]);
$lastBillId = Bill::latest()->first()->id;
return redirect()->route('employees.pays.bills.edit', $lastBillId);
}
// Bill is in edit mode
else
{
if($action == "addBillItem")
{
//Bill::latest()->first()->id;
$this->billItem->fill([
'bill_id' => $this->bill->id,
'item_id' => $this->selectedItem,
'job_id' => $this->billItem->job_id,
'account_id' => $this->billItem->account_id,
'description' => $this->billItem->description,
'qty' => $this->billItem->qty,
'rate' => $this->billItem->rate,
'paid' => null,
'verified' => null,
]);
$this->billItem->save();
}
elseif($action == "addBillAccount")
{
$this->billAccount->fill([
'bill_id' => $this->bill->id,
'account_id' => $this->billAccount->account_id,
'description' => $this->billAccount->description,
'paid' => 1,
'verify' => 1,
'amount' => $this->billAccount->amount,
]);
$this->billAccount->save();
}
elseif($action == "addBill")
{
$this->bill->fill([
'company_id' => $this->bill->company_id,
'comp_id' => $this->bill->comp_id,
'date' => $this->bill->date,
'reference' => $this->bill->reference,
'description' => $this->bill->description,
'entered_by' => null,
'verified_by' => null,
'paid_by' => null,
]);
$this->bill->save();
}
return redirect()->route('employees.pays.bills.edit', $this->bill->id);
}
}
public function render()
{
return view('livewire.bill-form');
}
}
My Preference is to insert each and every record (BillItem and BillAccount) to the database
(E.g. - 20 BillItems required 20 Submits per Bill)
However, i prefer to calculate $this->billTotal in a much optimized way
class Bill extends Model
{
..
..
public function billItems()
{
return $this->hasMany(BillItem::class);
}
public function billAccounts()
{
return $this->hasMany(BillAccount::class);
}
}