Make a car rental admin using laravel 9 part 5: Transaction management

AlfaRiza
5 min readApr 1, 2022

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 :).

--

--