There are 3 Models
One Bil will have many BillItems (One to Many Relationship)
One Bill will have many BillAccounts (One to Many Relationship)
This is my livewire BillForm Component. This works well , but i feel that this can be improved alot(Especially the validation section)
I need your thoughts on this because i am going to code the rest of my project based on this component (there will be similar livewire componenets like this and my mistakes will be repeated over and over)
BillForm.php
<?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 Livewire\WithFileUploads;
use Illuminate\Support\Facades\Auth;
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 $confirmingBillItemDeletion = false;
public $confirmingBillAccountDeletion = false;
public $selectedCompany = null;
public $selectedCategory = null;
public $selectedItem = null;
public $selectedAccount = null;
public $verifiedButton = false;
protected function rules()
{
return [
'bill.company_id' => 'required',
'bill.comp_id' => 'required',
'bill.reference' => 'nullable',
'bill.description' => 'nullable',
'bill.date' => 'nullable',
'bill.total' => 'nullable', //Bill Section Ends
'selectedCategory' => 'nullable',
'selectedItem' => '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',
'billItem.amount' => 'nullable', //BillItem Section Ends
'billAccount.account_id' => 'nullable',
'billAccount.description' => 'nullable',
'billAccount.amount' => 'nullable', //BillAccount Section Ends
];
}
//Customize validation
protected $validationAttributes = [
'selectedCompany' => 'provider',
'selectedCategory' => 'category',
'selectedItem' => 'item',
];
//Realtime validation
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->validate([
'billItem.qty' => 'required|numeric'
]);//For realtime validation
$this->billItem->rate = $this->billItem->amount / $this->billItem->qty;
}
public function updatedBillItemRate()
{
$this->validate([
'billItem.rate' => 'required|numeric'
]);//For realtime validation
$this->billItem->amount = $this->billItem->qty * $this->billItem->rate;
}
public function updatedBillItemAmount()
{
$this->validate([
'billItem.amount' => 'required|numeric'
]);//For realtime validation
$this->billItem->rate = $this->billItem->amount / $this->billItem->qty;
}
public function updatedBillAccountAmount()
{
//dd("test");
$this->validate([
'billAccount.amount' => 'required|numeric'
]);//For realtime validation
}
// 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 changeStatus($value)
{
$this->validate();
$this->bill->fill([
'status' => $value,
]);
$this->bill->save();
}
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->companies = Company::all()->sortBy('name');
$this->comps = Comp::all();
$this->categories = Category::all();
$this->items = Item::all();
$this->accounts = Account::orderby('number', 'asc')
->where('id', 15)->orWhere('type_id', 2)->get();
if($bill->billItems->count() > 0 )
{
$this->billItems = $bill->billItems; //To display existing billItems
}
if($bill->billAccounts->count() > 0 )
{
$this->billAccounts = $bill->billAccounts; //To display existing billAccounts
}
$this->bill->total += $bill->billItems->sum(fn($billItem) => $billItem->qty * $billItem->rate)
+ $bill->billAccounts->sum('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.total' => '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,
'total' => $this->bill->total,
'status' => $this->bill->status,
'entered_by' => Auth::user()->id,
'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")
{
$this->validate([
'selectedCategory' => 'required',
'selectedItem' => 'required',
'billItem.bill_id' => 'nullable',
'billItem.item_id' => 'nullable',
'billItem.job_id' => 'nullable',
'billItem.account_id' => 'nullable',
'billItem.description' => 'nullable',
'billItem.qty' => 'required',
'billItem.rate' => 'required',
'billItem.amount' => 'required',
]);
//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->validate([
'billAccount.account_id' => 'required',
'billAccount.description' => 'nullable',
'billAccount.amount' => 'required',
]);
$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")
{
//dd($this->bill);
$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,
'status' => $this->bill->status,
'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');
}
}
bill-form-blade.php
<div>
<form method="post" wire:submit.prevent="save" action="" class="xl:h-screen">
@csrf
{{-- Row 1 --}}
<div class="grid grid-cols-1 p-4 xl:grid-cols-12 gap-x-4 gap-y-4">
{{-- Provider (Mainly includes the company list and Self Companies like Mehran)--}}
<div class="xl:col-span-3">
<b class="uppercase">Provider</b>
<select wire:model="bill.company_id"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>Choose a Provider</option>
@foreach($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</select>
<x-jet-input-error for="bill.company_id" class="mt-2" />
</div>
{{-- Comp --}}
<div class="xl:col-span-1">
<b class="uppercase">Comp</b>
<select wire:model="bill.comp_id"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="">Select</option>
@foreach($comps as $comp)
<option value="{{ $comp->id }}">{{ $comp->short_name }}</option>
@endforeach
</select>
<x-jet-input-error for="bill.comp_id" class="mt-2" />
</div>
{{-- reference --}}
<div class="xl:col-span-2">
<b class="uppercase">reference</b>
<x-jet-input wire:model.lazy="bill.reference" id="reference" type="text" class="block w-full mt-1" />
<x-jet-input-error for="bill.reference" class="mt-2" />
</div>
{{-- date --}}
<div class="xl:col-span-2">
<b class="uppercase">date</b>
<x-jet-input wire:model.lazy="bill.date" id="date" type="date" class="block w-full mt-1" />
<x-jet-input-error for="bill.date" class="mt-2" />
</div>
{{-- description --}}
<div class="xl:col-span-4">
<b class="uppercase">description</b>
<x-jet-input wire:model.lazy="bill.description" id="description" type="text" class="block w-full mt-1" />
<x-jet-input-error for="bill.description" class="mt-2" />
</div>
</div>
{{-- BillItems and BillAccounts will be visible only when there is an existing bill --}}
{{-- Row 1.1 --}}
<div class="grid grid-cols-1 p-4 xl:grid-cols-12 gap-x-4 gap-y-4">
<div class="xl:col-span-2">
<x-success-button class="w-full h-full" wire:click="save('addBill')">
{{ $bill->id ? 'Update' : 'Save' }}
</x-success-button>
</div>
<div class="xl:col-span-2">
@if($bill->id != NULL && $bill->status == "Pending")
<x-success-button class="w-full h-full" wire:click="changeStatus('Entered')">
{{ 'Enter' }}
</x-success-button>
@endif
@if($bill->status == "Entered")
<x-success-button class="w-full h-full" wire:click="changeStatus('Verified')">
{{ 'Verify' }}
</x-success-button>
@endif
</div>
<div class="xl:col-span-2">
{{-- <x-jet-label for="status" value="{{ __('STATUS') }}" class="font-bold text-left" />
<select wire:model="bill.status"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="Pending">Pending</option>
<option value="Entered">Entered</option>
<option value="Verified">Verified</option>
<option value="Error">Error</option>
</select> --}}
</div>
<div class="xl:col-span-2">
<x-jet-danger-button class="w-full h-full" wire:click="changeStatus('Error')">
{{ 'Error' }}
</x-jet-danger-button>
</div>
<div class="xl:col-span-4">
<b class="uppercase">bill total</b>
<x-jet-input wire:model.lazy="bill.total" id="billTotal" type="text" class="block w-full mt-1" readonly />
</div>
</div>
@if($bill->id != null)
{{-- Row 2 --}}
<div class="grid grid-cols-1 px-4 mt-4 xl:grid-cols-12">
{{-- bill items --}}
<div class="xl:col-span-12">
<b class="w-full underline uppercase">bill items</b>
</div>
</div>
{{-- Row 3 --}}
<div class="grid grid-cols-1 p-4 overflow-auto xl:grid-cols-12 gap-x-4 gap-y-4">
{{-- <table class="min-w-full text-center divide-y divide-gray-200"> --}}
<table class="col-span-12 overflow-x-visible table-auto">
<thead class="w-full font-bold text-gray-700 bg-gray-300">
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-2">
<b class="uppercase">category</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-2">
<b class="uppercase">item</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-1">
<b class="uppercase">job no</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-2">
<b class="uppercase">description</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-1">
<b class="uppercase">qty</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-1">
<b class="uppercase">rate</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-2">
<b class="uppercase">amount</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-1">
</div>
</th>
</thead>
<tbody class="text-left bg-white divide-y divide-gray-200">
@if($billItems)
@foreach ($billItems as $billItem)
<tr>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->item->category->name }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->item->name }}</b>
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->job_no }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->description }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->qty }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->rate }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billItem->qty * $billItem->rate }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
<a href="{{ route('employees.pays.billitems.edit', $billItem) }}"><x-warning-button>Edit</x-warning-button></a>
{{-- <a href="{{ route('employees.pay.bills.edit', $user) }}"><x-warning-button>Edit</x-warning-button></a> --}}
<x-jet-danger-button wire:click="confirmBillItemDeletion({{ $billItem->id }})">Delete</x-jet-danger-button>
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
{{-- Row 3.1 --}}
<div class="grid grid-cols-1 p-4 xl:grid-cols-12 gap-x-4 gap-y-4">
<div class="xl:col-span-2">
<label for="category" class="font-bold uppercase">category</label>
<select wire:model="selectedCategory"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>Choose a Category</option>
@foreach($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
@endforeach
</select>
<x-jet-input-error for="selectedCategory" class="mt-2" />
</div>
<div class="xl:col-span-2">
<label for="item" class="font-bold uppercase">item</label>
@if($selectedItem == null)
<div class="col-span-12 xl:col-span-6">
<select wire:model="selectedItem" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>Choose an Item</option>
</select>
<x-jet-input-error for="selectedItem" class="mt-2" />
</div>
@else
<div class="col-span-12 xl:col-span-6">
<select wire:model="selectedItem" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
@foreach($items as $item)
<option value="{{ $item->id }}">{{ $item->name }}</option>
@endforeach
</select>
<x-jet-input-error for="selectedItem" class="mt-2" />
</div>
@endif
</div>
<div class="xl:col-span-1">
<label for="job no" class="font-bold uppercase">job no</label>
<select wire:model.lazy="billItem.job_id"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
</select>
<x-jet-input-error for="billItem.job_id" class="mt-2" />
</div>
<div class="xl:col-span-2">
<label for="description" class="font-bold uppercase">description</label>
<x-jet-input wire:model.lazy="billItem.description" id="description" type="text" class="block w-full mt-1" />
<x-jet-input-error for="billItem.description" class="mt-2" />
</div>
<div class="xl:col-span-1">
<label for="qty" class="font-bold uppercase">qty</label>
<x-jet-input wire:model.lazy="billItem.qty" id="qty" type="text" class="block w-full mt-1" />
<x-jet-input-error for="billItem.qty" class="mt-2" />
</div>
<div class="xl:col-span-1">
<label for="rate" class="font-bold uppercase">rate</label>
<x-jet-input wire:model.lazy="billItem.rate" id="rate" type="text" class="block w-full mt-1" />
<x-jet-input-error for="billItem.rate" class="mt-2" />
</div>
<div class="xl:col-span-2">
<label for="billItemAmount" class="font-bold uppercase">amount</label>
<x-jet-input wire:model.lazy="billItem.amount" id="billItem.amount" type="text" class="block w-full mt-1" />
<x-jet-input-error for="billItem.amount" class="mt-2" />
</div>
<div class="xl:col-span-1">
<x-success-button class="w-full h-full" wire:click="save('addBillItem')">
{{ 'add bill item' }}
</x-success-button>
</div>
</div>
{{-- Row 4 --}}
<div class="grid grid-cols-1 px-4 mt-4 xl:grid-cols-12">
{{-- bill accounts --}}
<div class="col-span-12">
<b class="underline uppercase">bill accounts</b>
</div>
</div>
{{-- Row 5 --}}
<div class="grid grid-cols-1 px-4 mt-4 xl:grid-cols-12">
<table class="col-span-12 overflow-x-visible table-auto">
<thead class="w-full font-bold text-gray-700 bg-gray-300">
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-2">
<b class="uppercase">account</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-7">
<b class="uppercase">description</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-2">
<b class="uppercase">amount</b>
</div>
</th>
<th scope="col" class="px-6 py-3 text-xs tracking-wider uppercase">
<div class="xl:col-span-1">
</div>
</th>
</thead>
<tbody class="text-left bg-white divide-y divide-gray-200">
@if($billAccounts)
@foreach ($billAccounts as $billAccount)
<tr>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billAccount->account->name }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billAccount->description }}</b>
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
{{ $billAccount->amount }}
</td>
<td class="px-6 py-2 text-sm text-center text-gray-500 border-2 border-gray-200 whitespace-nowrap">
<a href="{{ route('employees.pays.billaccounts.edit', $billAccount) }}"><x-warning-button>Edit</x-warning-button></a>
<x-jet-danger-button wire:click="confirmBillAccountDeletion({{ $billAccount->id }})">Delete</x-jet-danger-button>
</td>
</tr>
@endforeach
@endif
</tbody>
</table>
</div>
{{-- Row 5.1 --}}
<div class="grid grid-cols-1 p-4 xl:grid-cols-12 gap-x-4 gap-y-4">
<div class="xl:col-span-2">
<label for="account" class="font-bold uppercase">account</label>
<select wire:model="billAccount.account_id"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>Choose an Account</option>
@foreach($accounts as $account)
<option value="{{ $account->id }}">{{ $account->name }}</option>
@endforeach
</select>
<x-jet-input-error for="billAccount.account_id" class="mt-2" />
</div>
<div class="xl:col-span-7">
<b class="uppercase">description</b>
<x-jet-input wire:model.lazy="billAccount.description" id="accountDescription" type="text" class="block w-full mt-1" />
<x-jet-input-error for="billAccount.description" class="mt-2" />
</div>
<div class="xl:col-span-2">
<b class="uppercase">amount</b>
<x-jet-input wire:model.lazy="billAccount.amount" id="accountAmount" type="text" class="block w-full mt-1" />
<x-jet-input-error for="billAccount.amount" class="mt-2" />
</div>
<div class="xl:col-span-1">
<x-success-button class="w-full h-full" wire:click="save('addBillAccount')">
{{ 'add bill account' }}
</x-success-button>
</div>
</div>
@endif
</form>
<div>
<div class="grid grid-cols-1 p-4 bg-green-200 border-2 border-black xl:grid-cols-12 gap-x-4 gap-y-4 mt-20">
<div class="xl:col-span-12">
<b class="underline uppercase">Insructions</b>
</div>
<div class="xl:col-span-3">
<b>Bill Section</b>
<ul class="px-4 list-disc">
<li>PK bills and PKL bills should be taken separately. E.g.- PK Vmas Bill, PKL Vmas Bill</li>
<!-- ... -->
</ul>
</div>
<div class="xl:col-span-3">
<b>Another Section</b>
</div>
</div>
<!-- Delete BillItem Confirmation Modal -->
<x-jet-dialog-modal wire:model="confirmingBillItemDeletion">
<x-slot name="title">
{{ __('Delete BillItem') }}
</x-slot>
<x-slot name="content">
{{ __('Are you sure you want to delete this BillItem?') }}
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button wire:click="$set('confirmingBillItemDeletion', false)" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jet-secondary-button>
<x-jet-danger-button class="ml-2" wire:click="deleteBillItem({{ $confirmingBillItemDeletion }})" wire:loading.attr="disabled">
{{ __('Delete') }}
</x-jet-danger-button>
</x-slot>
</x-jet-dialog-modal>
<!-- Delete BillAccount Confirmation Modal -->
<x-jet-dialog-modal wire:model="confirmingBillAccountDeletion">
<x-slot name="title">
{{ __('Delete BillAccount') }}
</x-slot>
<x-slot name="content">
{{ __('Are you sure you want to delete this BillAccount?') }}
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button wire:click="$set('confirmingBillAccountDeletion', false)" wire:loading.attr="disabled">
{{ __('Cancel') }}
</x-jet-secondary-button>
<x-jet-danger-button class="ml-2" wire:click="deleteBillAccount({{ $confirmingBillAccountDeletion }})" wire:loading.attr="disabled">
{{ __('Delete') }}
</x-jet-danger-button>
</x-slot>
</x-jet-dialog-modal>
</div>
</div>
Bill.php
<?php
namespace App\Models;
use App\Models\Comp;
use App\Models\Company;
use App\Models\BillItem;
use App\Models\BillAccount;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Bill extends Model
{
use SoftDeletes;
use HasFactory;
protected $guarded = [];
public function getStatusAttribute($value)
{
if ($value == 0) { return "Pending"; }
if ($value == 1) { return "Entered"; }
if ($value == 2) { return "Verified"; }
if ($value == 3) { return "Paid"; }
if ($value == 4) { return "Error"; }
}
public function setStatusAttribute($value)
{
//dd($value);
if($value == "Pending") { $this->attributes['status'] = 0; }
if($value == "Entered") { $this->attributes['status'] = 1; }
if($value == "Verified") { $this->attributes['status'] = 2; }
if($value == "Paid") { $this->attributes['status'] = 3; }
if($value == "Error") { $this->attributes['status'] = 4; }
}
public function company()
{
return $this->belongsTo(Company::class);
}
public function comp()
{
return $this->belongsTo(Comp::class);
}
public function billItems()
{
return $this->hasMany(BillItem::class);
}
public function billAccounts()
{
return $this->hasMany(BillAccount::class);
}
public function payBills()
{
return $this->belongsToMany('App\Models\Employee\PayBill', 'bill_paybill')->withPivot('id', 'bill_id', 'paybill_id')->withTimestamps();
}
}
BillItem.php
<?php
namespace App\Models;
use App\Models\Item;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class BillItem extends Model
{
use HasFactory;
use SoftDeletes;
protected $guarded = [];
// protected $appends = ['qty'];
public function bill()
{
return $this->belongsTo(Bill::class);
}
public function item()
{
return $this->belongsTo(Item::class);
}
public function getBillItemRateAttribute($rate)
{
return $rate / 10000;
}
public function setBillItemRateAttribute($value)
{
$this->attributes['rate'] = $value * 10000;
}
}
BillAccount.php
<?php
namespace App\Models;
use App\Models\Account;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class BillAccount extends Model
{
use HasFactory;
use SoftDeletes;
protected $guarded = [];
public function bill()
{
return $this->belongsTo(Bill::class);
}
public function account()
{
return $this->belongsTo(Account::class);
}
public function getBillAmountAttribute($amount)
{
return $amount / 10000;
}
public function setBillAmountAttribute($value)
{
$this->attributes['amount'] = $value * 10000;
}
}