Aplikasi E-Commerce Laravel 6 #11: Dashboard & Management Orders

Aplikasi E-Commerce Laravel 6 #11: Dashboard & Management Orders

Pendahuluan

Fitur untuk memantau atau melihat riwayat interaksi pelanggan adalah salah satu hal yang harus disediakan, dalam hal ini adalah informasi terkait pesanan yang sudah dilakukan. Pada artikel ini kita akan membahas bagaimana membuat dashboard untuk menampilkan ringkasan informasi bagi setiap akun terakit dan juga kita akan membuat halaman dimana user memiliki kemampuan untuk mengelola data pesanannya. Diakhir materi juga disediakan fitur untuk mengkofirmasi pesanan yang telah dilakukan agar dapat diproses lebih lanjut.

Baca Juga: Aplikasi E-Commerce Laravel 6 #10: Multiple Authentication

Ringkasan Transaksi (Dashboard)

Menampilkan informasi singkat berupa ringkasan transaksi atau ringkasan lainnya adalah bagian yang selalu saja ada pada halaman home atau dashboard, jalur pintas bagi user untuk melihat rangkuman tanpa harus berkunjung ke halaman lainnya jika sedang tidak punya banyak waktu.

Pada seri sebelumnya kita telah membuat halaman login, dimana jika user berhasil login akan diarahkan ke halaman dashboard. Akan tetapi halaman tersebut untuk saat ini masih menampilkan teks biasa saja, maka pada seri kali ini kita akan melengkapi fitur tersebut.

Buka file Ecommerce/LoginController.php dan modifikasi method dashboard() menjadi:

public function dashboard()
{
    $orders = Order::selectRaw('COALESCE(sum(CASE WHEN status = 0 THEN subtotal END), 0) as pending, 
        COALESCE(count(CASE WHEN status = 3 THEN subtotal END), 0) as shipping,
        COALESCE(count(CASE WHEN status = 4 THEN subtotal END), 0) as completeOrder')
        ->where('customer_id', auth()->guard('customer')->user()->id)->get();

    return view('ecommerce.dashboard', compact('orders'));
}

Penjelasan: Dari code di atas, kita belajar hal baru, yakni bagaimana membuat custom query dengan Eloquent. Jadi jika kita terjemahkan, pada fungsi select(), terdapat kondisi dengan menggunakan CASE, dimana jika kondisinya terpenuhi dalam hal ini status maka subtotal akan di-sum.

Apa perbedaan select dan selectRaw? Pada dasarnya keduanya sama saja yakni untuk memilih column apa saja yang ingin diambil dari query tersebut, akan tetapi yang membedakan adalah selectRaw memungkinkan kita untuk meng-inject query ke dalamnya.

Jangan lupa untuk menambahkan use statement di dalam file yang sama:

use App\Order;

Kemudian buka file dashboard.blade.php yang berada di dalam folder resources/views/ecommerce, lalu modifikasi menjadi

@extends('layouts.ecommerce')

@section('title')
    <title>Dashboard - DW Ecommerce</title>
@endsection

@section('content')
    <!--================Home Banner Area =================-->
	<section class="banner_area">
		<div class="banner_inner d-flex align-items-center">
			<div class="container">
				<div class="banner_content text-center">
					<h2>Dashboard</h2>
					<div class="page_link">
                        <a href="{{ url('/') }}">Home</a>
                        <a href="{{ route('customer.dashboard') }}">Dashboard</a>
					</div>
				</div>
			</div>
		</div>
	</section>
	<!--================End Home Banner Area =================-->

	<!--================Login Box Area =================-->
	<section class="login_box_area p_120">
		<div class="container">
			<div class="row">
				<div class="col-md-3">
					@include('layouts.ecommerce.module.sidebar')
				</div>
				<div class="col-md-9">
                    <div class="row">
						<div class="col-md-4">
							<div class="card text-center">
								<div class="card-body">
									<h3>Belum Dibayar</h3>
									<hr>
									<p>Rp {{ number_format($orders[0]->pending) }}</p>
								</div>
							</div>
						</div>
						<div class="col-md-4">
							<div class="card text-center">
								<div class="card-body">
									<h3>Dikirim</h3>
									<hr>
									<p>{{ $orders[0]->shipping }} Pesanan</p>
								</div>
							</div>
						</div>
						<div class="col-md-4">
							<div class="card text-center">
								<div class="card-body">
									<h3>Selesai</h3>
									<hr>
									<p>{{ $orders[0]->completeOrder }} Pesanan</p>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</section>
@endsection

Note: Code di atas hanya berisi layout HTML untuk menampilkan ringkasan pesanan.

Jika kita perhatikan pada code di atas, terdapat fungsi untuk memanggil file lainnya, yakni: @include('layouts.ecommerce.module.sidebar'). Buat file baru tersebut dengan nama sidebar.blade.php dan tempatkan di dalam folder resources/views/layouts/ecommerce/module (Note: jika folder module belum ada, silahkan buat foldernya). Masukkan tag berikut di dalam file baru tersebut

<div class="card" style="background-color: #bdc3c7">
    <div class="card-body">
        <h3>Main Menu</h3>
        <ul class="menu-sidebar-area">
            <li class="icon-dashboard"><a href="{{ route('customer.dashboard') }}">Dashboard</a></li>
            <li class="icon-customers"><a href="">Pesanan</a></li>
            <li class="icon-users"><a href="">Pengaturan</a></li>
        </ul>
    </div>
</div>

Halaman dashboard dengan layout yang telah disesuaikan sudah selesai, dimana di dalamnya terdapat informasi seputar tagihan yang belum dibayar, total pesanan yang dikirim dan total pesanan yang lampau.

Kelola Data Transaksi

Menampilkan data pesanan pelanggan berdasarkan riwayat transaksi yang telah dilakukannya akan menjadi tugas kita selanjutnya, generate controller baru dengan command

php artisan make:controller Ecommerce/OrderController

Buka file Ecommerce/OrderController.php dan tambahkan method berikut

public function index()
{
    $orders = Order::where('customer_id', auth()->guard('customer')->user()->id)->orderBy('created_at', 'DESC')->paginate(10);
    return view('ecommerce.orders.index', compact('orders'));
}

Penjelasan: Line pertama kita membuat query untuk mengambil data order berdasarkan customer yang sedang login dengan load 10 data per-page. Line selanjutnya adalah me-load view index.blade.php dan passing data orders ke view tersebut.

Jangan lupa untuk menambahkan use statement

use App\Order;

Kemudian buat file index.blade.php di dalam folder resources/views/ecommerce/orders dan tambahkan code di bawah ini

@extends('layouts.ecommerce')

@section('title')
    <title>List Pesanan - DW Ecommerce</title>
@endsection

@section('content')
    <!--================Home Banner Area =================-->
	<section class="banner_area">
		<div class="banner_inner d-flex align-items-center">
			<div class="container">
				<div class="banner_content text-center">
					<h2>List Pesanan</h2>
					<div class="page_link">
            <a href="{{ url('/') }}">Home</a>
            <a href="{{ route('customer.orders') }}">List Pesanan</a>
					</div>
				</div>
			</div>
		</div>
	</section>
	<!--================End Home Banner Area =================-->

	<!--================Login Box Area =================-->
	<section class="login_box_area p_120">
		<div class="container">
			<div class="row">
				<div class="col-md-3">
					@include('layouts.ecommerce.module.sidebar')
				</div>
				<div class="col-md-9">
                    <div class="row">
						<div class="col-md-12">
							<div class="card">
                <div class="card-header">
                    <h4 class="card-title">List Pesanan</h4>
                </div>
								<div class="card-body">
									<div class="table-responsive">
                      <table class="table table-hover table-bordered">
                          <thead>
                              <tr>
                                  <th>Invoice</th>
                                  <th>Penerima</th>
                                  <th>No Telp</th>
                                  <th>Total</th>
                                  <th>Status</th>
                                  <th>Tanggal</th>
                                  <th>Aksi</th>
                              </tr>
                          </thead>
                          <tbody>
                              @forelse ($orders as $row) 
                              <tr>
                                  <td><strong>{{ $row->invoice }}</strong></td>
                                  <td>{{ $row->customer_name }}</td>
                                  <td>{{ $row->customer_phone }}</td>
                                  <td>{{ number_format($row->subtotal) }}</td>
                                  <td>{!! $row->status_label !!}</td>
                                  <td>{{ $row->created_at }}</td>
                                  <td>
                                      <a href="{{ route('customer.view_order', $row->invoice) }}" class="btn btn-primary btn-sm">Detail</a>
                                  </td>
                              </tr>
                              @empty
                              <tr>
                                  <td colspan="7" class="text-center">Tidak ada pesanan</td>
                              </tr>
                              @endforelse
                          </tbody>
                      </table>
                  </div>
                  <div class="float-right">
                      {!! $orders->links() !!}
                  </div>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</section>
@endsection

Note: Hanya looping biasa dari data yang telah diterima dari controller, dalam hal ini adalah data orders.

Definisikan routing-nya dengan menambahkan line berikut di dalam route group yang menggunakan middleware customer. Buka file routes/web.php dan masukkan code:

Route::get('orders', 'OrderController@index')->name('customer.orders');

Code $row->status_label dapat dari mana? Ini adalah Accessor, tapi sebelumnya kita belum memiliki column status pada table orders. Dari terminal, generate migration baru dengan command

php artisan make:migration add_field_status_to_orders_table

Buka migration baru tersebut dan modifikasi menjadi:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class AddFieldStatusToOrdersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('orders', function (Blueprint $table) {
            $table->char('status', 1)->default(0)->comment('0: new, 1: confirm, 2: process, 3: shipping, 4: done')->after('subtotal');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('orders', function (Blueprint $table) {
            $table->dropColumn('status');
        });
    }
}

Penjelasan: Pada method up(), kita menambahkan field status dengan type char dan dilimit 1, nilai default-nya adalah 0 dan dilengkapi dengan command column untuk menjelaskan masing-masing code status-nya, kemudian column tersebut diletakkan setelah column subtotal.

Jangan lupa menjalankan command berikut untuk mengeksekusi migration di atas.

php artisan migrate

Kemudian buka file Order.php dan tambahkan accessor berikut

protected $appends = ['status_label'];

public function getStatusLabelAttribute()
{
    if ($this->status == 0) {
        return '<span class="badge badge-secondary">Baru</span>';
    } elseif ($this->status == 1) {
        return '<span class="badge badge-primary">Dikonfirmasi</span>';
    } elseif ($this->status == 2) {
        return '<span class="badge badge-info">Proses</span>';
    } elseif ($this->status == 3) {
        return '<span class="badge badge-warning">Dikirim</span>';
    }
    return '<span class="badge badge-success">Selesai</span>';
}

Note: Ingat, Accessor dimulai dengan key get dan diakhiri dengan key attribute.

Lanjut dengan membuat halaman untuk menampilkan detail pesanan, buka file Ecommerce/OrderController.php dan tambahkan method

public function view($invoice)
{
    $order = Order::with(['district.city.province', 'details', 'details.product', 'payment'])
        ->where('invoice', $invoice)->first();
    return view('ecommerce.orders.view', compact('order'));
}

Penjelasan: Line pertama adalah query untuk mengambil data order berdasarkan invoice, kemudian me-load data yang berelasi dengan menggunakan eager loading. Line kedua me-load file view.blade.php dan passing data order sebelumnya ke halaman tersebut.

Buat file baru dengan nama view.blade.php dan letakkan di dalam folder yang sama dengan index.blade.php sebelumnya, kemudian masukkan code berikut

@extends('layouts.ecommerce')

@section('title')
    <title>Order {{ $order->invoice }} - DW Ecommerce</title>
@endsection

@section('content')
    <!--================Home Banner Area =================-->
	<section class="banner_area">
		<div class="banner_inner d-flex align-items-center">
			<div class="container">
				<div class="banner_content text-center">
					<h2>Order {{ $order->invoice }}</h2>
					<div class="page_link">
            <a href="{{ url('/') }}">Home</a>
            <a href="{{ route('customer.orders') }}">Order {{ $order->invoice }}</a>
					</div>
				</div>
			</div>
		</div>
	</section>
	<!--================End Home Banner Area =================-->

	<!--================Login Box Area =================-->
	<section class="login_box_area p_120">
		<div class="container">
			<div class="row">
				<div class="col-md-3">
					@include('layouts.ecommerce.module.sidebar')
				</div>
				<div class="col-md-9">
          <div class="row">
						<div class="col-md-6">
							<div class="card">
                <div class="card-header">
                    <h4 class="card-title">Data Pelanggan</h4>
                </div>
								<div class="card-body">
									<table>
                      <tr>
                          <td width="30%">Nama Lengkap</td>
                          <td width="5%">:</td>
                          <th>{{ $order->customer_name }}</th>
                      </tr>
                      <tr>
                          <td>No Telp</td>
                          <td>:</td>
                          <th>{{ $order->customer_phone }}</th>
                      </tr>
                      <tr>
                          <td>Alamat</td>
                          <td>:</td>
                          <th>{{ $order->customer_address }}, {{ $order->district->name }} {{ $order->district->city->name }}, {{ $order->district->city->province->name }}</th>
                      </tr>
                  </table>
								</div>
							</div>
						</div>
						<div class="col-md-6">
							<div class="card">
                <div class="card-header">
                    <h4 class="card-title">
                        Pembayaran

                        @if ($order->status == 0)
                        <a href="{{ url('member/payment?invoice=' . $order->invoice) }}" class="btn btn-primary btn-sm float-right">Konfirmasi</a>
                        @endif
                    </h4>
                </div>
								<div class="card-body">
                  @if ($order->payment)
									<table>
                      <tr>
                          <td width="30%">Nama Pengirim</td>
                          <td width="5%"></td>
                          <td>{{ $order->payment->name }}</td>
                      </tr>
                      <tr>
                          <td>Tanggal Transfer</td>
                          <td></td>
                          <td>{{ $order->payment->transfer_date }}</td>
                      </tr>
                      <tr>
                          <td>Jumlah Transfer</td>
                          <td></td>
                          <td>Rp {{ number_format($order->payment->amount) }}</td>
                      </tr>
                      <tr>
                          <td>Tujuan Transfer</td>
                          <td></td>
                          <td>{{ $order->payment->transfer_to }}</td>
                      </tr>
                      <tr>
                          <td>Bukti Transfer</td>
                          <td></td>
                          <td>
                              <img src="{{ asset('storage/payment/' . $order->payment->proof) }}" width="50px" height="50px" alt="">
                              <a href="{{ asset('storage/payment/' . $order->payment->proof) }}" target="_blank">Lihat Detail</a>
                          </td>
                      </tr>
                  </table>
                  @else
                  <h4 class="text-center">Belum ada data pembayaran</h4>
                  @endif
								</div>
							</div>
              </div>
              <div class="col-md-12 mt-4">
                  <div class="card">
                      <div class="card-header">
                          <h4 class="card-title">Detail</h4>
                      </div>
                      <div class="card-body">
                          <div class="table-responsive">
                              <table class="table table-bordered table-hover">
                                  <thead>
                                      <tr>
                                          <th>Nama Produk</th>
                                          <th>Harga</th>
                                          <th>Quantity</th>
                                          <th>Berat</th>
                                      </tr>
                                  </thead>
                                  <tbody>
                                      @forelse ($order->details as $row)
                                      <tr>
                                          <td>{{ $row->product->name }}</td>
                                          <td>{{ number_format($row->price) }}</td>
                                          <td>{{ $row->qty }} Item</td>
                                          <td>{{ $row->weight }} gr</td>
                                      </tr>
                                      @empty
                                      <tr>
                                          <td colspan="4" class="text-center">Tidak ada data</td>
                                      </tr>
                                      @endforelse
                                  </tbody>
                              </table>
                          </div>
                      </div>
                  </div>
              </div>
					</div>
				</div>
			</div>
		</div>
	</section>
@endsection

Buka kembali file Order.php dan definisikan relationships berikut

//MEMBUAT RELASI KE TABLE ORDER_DETAILS DENGAN JENIS RELASI ONE TO MANY
public function details()
{
    return $this->hasMany(OrderDetail::class);
}

Karena pada detail data pelanggan diatas kita me-load data hingga ke table provinces melalui eager loading, maka buka file City.php dan modifikasi menjadi

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class City extends Model
{
    public function province()
    {
        return $this->belongsTo(Province::class);
    }
}

Relasi ke table products juga tidak boleh dilupakan, buka file OrderDetail.php dan modifikasi menjadi

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class OrderDetail extends Model
{
    protected $guarded = [];

    public function product()
    {
        return $this->belongsTo(Product::class);
    }
}

Terakhir adalah mendefinisikan routing-nya, buka file routes/web.php dan masukkan route berikut di dalam group yang menggunakan middleware customer

Route::get('orders/{invoice}', 'OrderController@view')->name('customer.view_order');

Agar bisa diakses melakui sidebar menu, buka file sidebar.blade.php, kemudian modifikasi tag untuk halaman pesanan menjadi:

<li class="icon-customers"><a href="{{ route('customer.orders') }}">Pesanan</a></li>

Sebelum berpindah ke module payment, buka file /layouts/ecommerce.blade.php dan tambahkan code berikut sebelum tag </head>

<style>
  .menu-sidebar-area {
    list-style-type:none; padding-left: 0; font-size: 15pt;
  }
  .menu-sidebar-area > li {
    margin:0 0 10px 0;
    list-style-position:inside;
    border-bottom: 1px solid black;
  }
  .menu-sidebar-area > li > a {
    color: black
  }
</style>
@yield('css')

Payment Confirmation

Pelanggan diharuskan untuk melakukan konfirmasi pembayaran untuk setiap pesanan yang telah mereka buat. Maka tugas kita selanjutnya adalah membuat fitur tersebut. Buka file Ecommerce/OrderController.php dan tambahkan method

public function paymentForm()
{
    return view('ecommerce.payment');
}

Kemudian buat file payment.blade.php di dalam folder resources/views/ecommerce/ dan tambahkan code

@extends('layouts.ecommerce')

@section('title')
    <title>Konfirmasi Pembayaran - DW Ecommerce</title>
@endsection

@section('css')
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css">
@endsection

@section('content')
    <!--================Home Banner Area =================-->
	<section class="banner_area">
		<div class="banner_inner d-flex align-items-center">
			<div class="container">
				<div class="banner_content text-center">
					<h2>Konfirmasi Pembayaran</h2>
					<div class="page_link">
            <a href="{{ url('/') }}">Home</a>
            <a href="{{ route('customer.orders') }}">Konfirmasi Pembayaran</a>
					</div>
				</div>
			</div>
		</div>
	</section>
	<!--================End Home Banner Area =================-->

	<!--================Login Box Area =================-->
	<section class="login_box_area p_120">
		<div class="container">
			<div class="row">
				<div class="col-md-3">
					@include('layouts.ecommerce.module.sidebar')
				</div>
				<div class="col-md-9">
                    <div class="row">
						<div class="col-md-12">
							<div class="card">
                <div class="card-header">
                    <h4 class="card-title">Konfirmasi Pembayaran</h4>
                </div>
<div class="card-body">
                    <form action="{{ route('customer.savePayment') }}" enctype="multipart/form-data" method="post">
                        @csrf

                        @if (session('success')) 
                            <div class="alert alert-success">{{ session('success') }}</div>
                        @endif
                        @if (session('error')) 
                            <div class="alert alert-danger">{{ session('error') }}</div>
                        @endif

                        <div class="form-group">
                            <label for="">Invoice ID</label>
                            <input type="text" name="invoice" class="form-control" value="{{ request()->invoice }}" required>
                            <p class="text-danger">{{ $errors->first('invoice') }}</p>
                        </div>
                        <div class="form-group">
                            <label for="">Nama Pengirim</label>
                            <input type="text" name="name" class="form-control" required>
                            <p class="text-danger">{{ $errors->first('name') }}</p>
                        </div>
                        <div class="form-group">
                            <label for="">Transfer Ke</label>
                            <select name="transfer_to" class="form-control" required>
                                <option value="">Pilih</option>
                                <option value="BCA - 1234567">BCA: 1234567 a.n Anugrah Sandi</option>
                                <option value="Mandiri - 2345678">Mandiri: 2345678 a.n Anugrah Sandi</option>
                                <option value="BRI - 9876543">BCA: 9876543 a.n Anugrah Sandi</option>
                                <option value="BNI - 6789456">BCA: 6789456 a.n Anugrah Sandi</option>
                            </select>
                            <p class="text-danger">{{ $errors->first('transfer_to') }}</p>
                        </div>
                        <div class="form-group">
                            <label for="">Jumlah Transfer</label>
                            <input type="number" name="amount" class="form-control" required>
                            <p class="text-danger">{{ $errors->first('amount') }}</p>
                        </div>
                        <div class="form-group">
                            <label for="">Tanggal Transfer</label>
                            <input type="text" name="transfer_date" id="transfer_date" class="form-control" required>
                            <p class="text-danger">{{ $errors->first('transfer_date') }}</p>
                        </div>
                        <div class="form-group">
                            <label for="">Bukti Transfer</label>
                            <input type="file" name="proof" class="form-control" required>
                            <p class="text-danger">{{ $errors->first('proof') }}</p>
                        </div>
                        <div class="form-group">
                            <button class="btn btn-primary btn-sm">Konfirmasi</button>
                        </div>
                    </form>
								</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</section>
@endsection

@section('js')
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>
    <script>
        $('#transfer_date').datepicker({
            "todayHighlight": true,
            "setDate": new Date(),
            "autoclose": true
        })
    </script>
@endsection

Note: Tujuan transfernya kita buat statis, jika ada yang ingin membuatnya dinamis silahkan buat fitur untuk menambahkan data bank pada halaman administrator, dan looping data bank tersebut pada select box di atas.

Buka kembali file Ecommerce/OrderController.php dan tambahkan method berikut untuk meng-handle proses konfirmasi pembayaran

public function storePayment(Request $request)
{
  //VALIDASI DATANYA
    $this->validate($request, [
        'invoice' => 'required|exists:orders,invoice',
        'name' => 'required|string',
        'transfer_to' => 'required|string',
        'transfer_date' => 'required',
        'amount' => 'required|integer',
        'proof' => 'required|image|mimes:jpg,png,jpeg'
    ]);

    //DEFINE DATABASE TRANSACTION UNTUK MENGHINDARI KESALAHAN SINKRONISASI DATA JIKA TERJADI ERROR DITENGAH PROSES QUERY
    DB::beginTransaction();
    try {
        //AMBIL DATA ORDER BERDASARKAN INVOICE ID
        $order = Order::where('invoice', $request->invoice)->first();
        //JIKA STATUSNYA MASIH 0 DAN ADA FILE BUKTI TRANSFER YANG DI KIRIM
        if ($order->status == 0 && $request->hasFile('proof')) {
            //MAKA UPLOAD FILE GAMBAR TERSEBUT
            $file = $request->file('proof');
            $filename = time() . '.' . $file->getClientOriginalExtension();
            $file->storeAs('public/payment', $filename);

            //KEMUDIAN SIMPAN INFORMASI PEMBAYARANNYA
            Payment::create([
                'order_id' => $order->id,
                'name' => $request->name,
                'transfer_to' => $request->transfer_to,
                'transfer_date' => Carbon::parse($request->transfer_date)->format('Y-m-d'),
                'amount' => $request->amount,
                'proof' => $filename,
                'status' => false
            ]);
            //DAN GANTI STATUS ORDER MENJADI 1
            $order->update(['status' => 1]);
            //JIKA TIDAK ADA ERROR, MAKA COMMIT UNTUK MENANDAKAN BAHWA TRANSAKSI BERHASIL
            DB::commit();
            //REDIRECT DAN KIRIMKAN PESAN
            return redirect()->back()->with(['success' => 'Pesanan Dikonfirmasi']);
        }
        //REDIRECT DENGAN ERROR MESSAGE
        return redirect()->back()->with(['error' => 'Error, Upload Bukti Transfer']);
    } catch(\Exception $e) {
        //JIKA TERJADI ERROR, MAKA ROLLBACK SELURUH PROSES QUERY
        DB::rollback();
        //DAN KIRIMKAN PESAN ERROR
        return redirect()->back()->with(['error' => $e->getMessage()]);
    }
}

Jangan lupa menambahkan use statement.

use App\Payment;
use Carbon\Carbon;
use DB;

Definisikan routing-nya untuk kedua method di atas, buka file routes/web.php dan tambahkan code berikut yang lagi lagi berada di dalam group middleware customer.

Route::get('payment', 'OrderController@paymentForm')->name('customer.paymentForm');
Route::post('payment', 'OrderController@storePayment')->name('customer.savePayment');

Eits sudah panjang lebar membuat module-nya, ternyata belum ada table payments. Pada command line, jalankan command berikut

php artisan make:model Payment -m

Buka file migration yang baru saja di-generate dan modifikasi menjadi

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePaymentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('payments', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('order_id');
            $table->string('name');
            $table->string('transfer_to');
            $table->date('transfer_date');
            $table->integer('amount');
            $table->string('proof')->nullable();
            $table->boolean('status')->false(false);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('payments');
    }
}

Eksekusi migration-nya dengan command

php artisan migrate

Buka file Payment.php dan modifikasi menjadi

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Payment extends Model
{
    protected $guarded = []; //UNTUK MENGIZINKAN MENYIMPAN DATA
}

Bagian terakhir adalah membuat relasi dari orders ke payments, buka file Order.php dan tambahkan method:

public function payment()
{
    return $this->hasOne(Payment::class);
}

Baca Juga: [Tips] Membuat Routing Maintenable di Laravel 6

Kesimpulan

Sepanjang artikel ini kita telah belajar beberapa hal, yakni: membuat custom query dengan menggunakan selectRaw, melafalkan kembali cara menggunakan database transaction di Laravel, membuat relasi antar table menggunakan Eloquent, meng-handle file yang di-upload oleh user, dan lain sebagainya.

Bagi kamu yang ingin melihat dokumentasi code, bisa ditemukan di Github.

Category:
Share:

Comments