Make a car rental admin using laravel 9 part 5: Transaction management
Hello everyone, we will continue our car rental project with a focus this time on transaction management.
First, we will create a TransactionController controller with resources, run the following command:
php artisan make:controller TransactionController --resource
then in routes\web.php
add route
Route::middleware(['auth'])->resource('/transaction', TransactionController::class);
don’t forget in sidebar.php
we add the route transaction url
<div class="sb-sidenav-menu-heading">Transaksi</div>
<a class="nav-link" href="{{ route('transaction.index') }}">
<div class="sb-nav-link-icon"><i class="fas fa-dollar-sign"></i></div>
Transaksi
</a>
Create
To create the create feature, we will go to the TransactionController
method create and store
public function create(){
$cars = Car::all();
$users = User::all();
return view('transaction.create', compact('cars', 'users'));
}public function store(Request $request)
{
$data = $request->validate([
'user_id' => 'required',
'car_id' => 'required',
'date_start' => 'required',
'date_end' => 'required',
'note' => 'required',
]);
$data['date_due'] = $request->date_end;
$data['status'] = 'PENDING';
$price = Car::find($request->car_id);
$date_start = new DateTime($request->date_start);
$date_end = new DateTime($request->date_end);
$duration = $date_start->diff($date_end);
$data['total'] = $price->price * $duration->days;
Transaction::create($data);
return redirect()->route('transaction.index')->with('success', 'Transaksi berhasil dibuat');
}
Next we create a view transaction.create
@extends('layouts.main')
@section('content')
<h1 class="mt-4">Transaksi</h1>
<ol class="mb-4 breadcrumb">
<li class="breadcrumb-item active">Tambah Transaksi</li>
</ol>
<form action="{{ route('transaction.store') }}" method="POST" enctype="multipart/form-data">
@csrf()
<div class="mb-3">
<label for="user_id" class="form-label">Pilih Pelanggan</label>
<select class="form-select" id="user_id" name="user_id">
@foreach($users as $user)
<option {{ (old('user_id') == $user->id ? 'selected' : '') }} value="{{ $user->id }}">{{ $user->name }}</option>
@endforeach
</select>
@error('user_id')
<span class="invalid-feedback">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="name" class="form-label">Pilih Mobil</label>
<select class="form-select" id="status" name="car_id">
@foreach($cars as $car)
<option {{ (old('car_id') == $car->id ? 'selected' : '') }} value="{{ $car->id }}">{{ $car->name }}</option>
@endforeach
</select>
@error('car_id')
<span class="invalid-feedback">{{ $message }}</span>
@enderror
</div>
<div class="mb-3">
<label for="date_end" class="form-label">Tanggal Pinjam</label>
<input type="date" class="form-control @error('date_end') is-invalid @enderror" name="date_start" id="date_start" value="{{ old('date_start') }}">
@error('date_start')
<span class="invalid-feedback">
{{ $message }}
</span>
@enderror
</div>
<div class="mb-3">
<label for="date_end" class="form-label">Tanggal Kembali</label>
<input type="date" class="form-control @error('date_end') is-invalid @enderror" name="date_end" id="date_end" value="{{ old('date_end') }}">
@error('date_end')
<span class="invalid-feedback">
{{ $message }}
</span>
@enderror
</div>
<div class="mb-3">
<label for="note" class="form-label">Note</label>
<textarea name="note" id="note" class="form-control @error('note') @enderror">{{ old('note') }}</textarea>
@error('note')
<span class="invalid-feedback">
{{ $message }}
</span>
@enderror
</div>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
@endsection
Index
For the index we will use the yajra datatable (complete documentation: https://yajrabox.com/docs/laravel-datatables/master/introduction)
Run the following command to install the datatable
composer require yajra/laravel-datatables-oracle:"~9.0"
Open config\app.php
and add the following code:
'providers' => [
// ...
Yajra\DataTables\DataTablesServiceProvider::class,
],
Then run the following command:
php artisan vendor:publish --tag=datatables
In view\layouts\main.blade.php
add @stack(‘style’)
under the css and @stack(‘script’)
at the end of the javascript. Now create view\transaction\index.blade.php
with the following code:
Then in TransactionController
method index
public function index(Request $request){
if ($request->ajax()) {
$data = Transaction::latest()->get();
return DataTables::of($data)
->addIndexColumn()
->editColumn('user_id', function(Transaction $transaction) {
$transaction = Transaction::with('user')->find($transaction->id);
return $transaction->user->name;
})
->editColumn('car_id', function(Transaction $transaction) {
$transaction = Transaction::with('car')->find($transaction->id);
return $transaction->car->name;
})
->editColumn('date_start', function(Transaction $transaction) {
return Carbon::parse($transaction->date_start)->format('d F Y');
})
->editColumn('date_end', function(Transaction $transaction) {
return Carbon::parse($transaction->date_end)->format('d F Y');
})
->editColumn('total', function(Transaction $transaction) {
return number_format($transaction->total, 2);
})
->addColumn('action', function(Transaction $transaction){
$btn = '<a href='. route("transaction.edit", $transaction->id) . ' class="edit btn btn-success btn-sm"><i class="fas fa-edit"></i></a>';
$btn = $btn.'<form class="d-inline" action='. route("transaction.destroy", $transaction->id) . ' method="POST">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value=' . csrf_token() . '>
<button class="btn btn-danger btn-sm" type="submit"><i class="fas fa-trash"></i></button>
</form>';
$btn = $btn. '<a href='. route("transaction.show", $transaction->id) . ' class="btn btn-info btn-sm"><i class="fas fa-eye"></i></a>';
$btn = $btn.'<form class="d-inline" action='. route("transaction.status", $transaction->id) . ' method="POST">
<input type="hidden" name="_token" value=' . csrf_token() . '>
<input type="hidden" name="status" value="SUCCESS">
<button class="btn btn-outline-success btn-sm" type="submit"><i class="far fa-check-circle"></i></button>
</form>';
$btn = $btn.'<form class="d-inline" action='. route("transaction.status", $transaction->id) . ' method="POST">
<input type="hidden" name="_token" value=' . csrf_token() . '>
<input type="hidden" name="status" value="FAILED">
<button class="btn btn-outline-danger btn-sm" type="submit"><i class="far fa-times-circle"></i></button>
</form>';
return $btn;
})
->rawColumns(['action', 'modal'])
->make(true);
}
return view('transaction.index');
}
If the error occurs because we haven’t added route(‘transaction.status’)
then we need to add it in routes\web.php
Route::post('transaction/{transaction:id}/status', [TransactionController::class, 'status'])->name('transaction.status');
Later, we will use this route to change the transaction status to SUCCESS
or FAILED
. The advantage of using datatable, we don’t need to create our own search function because by default datatable already provides it
Edit
For the edit feature on the TransactionController
the edit and update methods
public function edit(Transaction $transaction){
$users = User::all();
$cars = Car::all();
return view('transaction.edit', compact('users', 'cars', 'transaction'));
}public function update(Request $request, Transaction $transaction){
$data = $request->validate([
'user_id' => 'required',
'car_id' => 'required',
'date_start' => 'required',
'date_end' => 'required',
'note' => 'required',
]);
$price = Car::find($request->car_id);
$date_start = new DateTime($request->date_start);
$date_end = new DateTime($request->date_end);
$duration = $date_start->diff($date_end);
$data['total'] = $price->price * $duration->days;
$transaction->update($data);
return redirect()->route('transaction.index')->with('success', 'Transaksi berhasil diupdate');
}
Next we create view\transaction\edit.blade.php
Delete
For the delete feature, we just need to add the following code to the TransactionController method destroy
public function destroy(Transaction $transaction){
Transaction::destroy($transaction->id);
return redirect()->route('transaction.index')->with('success', 'Transaksi berhasil dihapus');
}
Show
For the show feature add the following code to the TransactionController
method show
public function show(Transaction $transaction){
$transaction = Transaction::with('user', 'car')->find($transaction->id);
return view('transaction.show', compact('transaction'));
}
Change Status
For this feature we use the post method so that it cannot be accessed via url so it is more secure. Add a status method to the TransactionController
public function status(Request $request, Transaction $transaction){
$transaction->update([
'status' => $request->status
]);
return redirect()->route('transaction.index')->with('success', 'Transaksi berhasil diupdate');
}
So later the status change will be adjusted to the request received
Okay, for our transaction is complete, then we will add features to change admin profile, change password, and display dashboard. That is all and thank you :).