refactor BookingFotoController and add BookingFotoRequest for improved validation and code organization
This commit is contained in:
parent
7fb675d70f
commit
a6a893bd05
|
|
@ -3,16 +3,13 @@
|
||||||
namespace App\Http\Controllers\User;
|
namespace App\Http\Controllers\User;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Additional;
|
use App\Models\{Additional, BookingFoto, DetailAdditional, PaketFoto, Pelanggan};
|
||||||
use App\Models\BookingFoto;
|
use App\Http\Requests\User\BookingFotoRequest;
|
||||||
use App\Models\DetailAdditional;
|
use App\Services\WhatsAppService;
|
||||||
use App\Models\PaketFoto;
|
|
||||||
use App\Models\Pelanggan;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
|
|
||||||
|
|
||||||
class BookingFotoController extends Controller
|
class BookingFotoController extends Controller
|
||||||
|
|
@ -64,204 +61,87 @@ public function cekSlot(Request $request)
|
||||||
}
|
}
|
||||||
public function formulir(Request $request)
|
public function formulir(Request $request)
|
||||||
{
|
{
|
||||||
$foto = PaketFoto::findOrFail($request->id_paket);
|
$details = $this->calculateDetails($request);
|
||||||
$durasiDasar = $foto->durasi;
|
|
||||||
$addonsDetails = [];
|
|
||||||
$totalAddon = 0;
|
|
||||||
$tambahanMenit = 0;
|
|
||||||
if ($request->has('addons')) {
|
|
||||||
foreach ($request->addons as $id => $qty) {
|
|
||||||
if ($qty > 0) {
|
|
||||||
$add = Additional::find($id);
|
|
||||||
if ($add) {
|
|
||||||
$subtotal = $add->harga * $qty;
|
|
||||||
$totalAddon += $subtotal;
|
|
||||||
|
|
||||||
if ($id == 4) {
|
|
||||||
$tambahanMenit += (5 * $qty);
|
|
||||||
} elseif ($id == 6) {
|
|
||||||
$tambahanMenit += (10 * $qty);
|
|
||||||
}
|
|
||||||
|
|
||||||
$addonsDetails[] = [
|
|
||||||
'nama' => $add->nama,
|
|
||||||
'qty' => $qty,
|
|
||||||
'subtotal' => $subtotal,
|
|
||||||
'id' => $id
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$totalDurasi = $durasiDasar + $tambahanMenit;
|
|
||||||
$jamMulai = \Carbon\Carbon::createFromFormat('H:i', $request->jam_mulai);
|
|
||||||
$jamSelesaiBaru = $jamMulai->copy()->addMinutes($totalDurasi)->format('H:i');
|
|
||||||
$grandTotal = $foto->harga + $totalAddon;
|
|
||||||
if (!session()->has('payment_deadline')) {
|
if (!session()->has('payment_deadline')) {
|
||||||
$deadline = now()->addHours(2);
|
session()->put('payment_deadline', now()->addHours(2));
|
||||||
session()->put('payment_deadline', $deadline);
|
|
||||||
} else {
|
|
||||||
$deadline = session('payment_deadline');
|
|
||||||
}
|
}
|
||||||
$sisaWaktu = now()->diffInSeconds($deadline, false);
|
$sisaWaktu = now()->diffInSeconds(session('payment_deadline'), false);
|
||||||
if ($sisaWaktu <= 0) {
|
if ($sisaWaktu <= 0) {
|
||||||
session()->forget(['payment_deadline', 'addons']);
|
session()->forget(['payment_deadline', 'addons']);
|
||||||
return redirect()->route('booking.foto')->with('error', 'Waktu pembayaran telah habis.');
|
return redirect()->route('booking.foto')->with('error', 'Waktu pembayaran telah habis.');
|
||||||
}
|
}
|
||||||
return view('user.pembayaran-foto', compact(
|
return view('user.pembayaran-foto', array_merge($details, [
|
||||||
'foto',
|
'sisaWaktu' => $sisaWaktu,
|
||||||
'request',
|
'request' => $request
|
||||||
'addonsDetails',
|
]));
|
||||||
'grandTotal',
|
|
||||||
'sisaWaktu',
|
|
||||||
'jamSelesaiBaru'
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
public function cancelBooking()
|
public function cancelBooking()
|
||||||
{
|
{
|
||||||
session()->forget(['payment_deadline', 'addons']);
|
session()->forget(['payment_deadline', 'addons']);
|
||||||
return redirect()->route('booking.foto');
|
return redirect()->route('booking.foto');
|
||||||
}
|
}
|
||||||
public function store(Request $request)
|
public function store(BookingFotoRequest $request)
|
||||||
{
|
{
|
||||||
$validator = Validator::make($request->all(), [
|
$details = $this->calculateDetails($request);
|
||||||
'id_paket' => 'required|exists:paket_fotos,id_paket',
|
return DB::transaction(function () use ($request, $details) {
|
||||||
'tgl_booking' => 'required|date|after_or_equal:today',
|
if (BookingFoto::where(['tgl_booking' => $request->tgl_booking, 'jam_mulai' => $request->jam_mulai])
|
||||||
'jam_mulai' => 'required',
|
->whereIn('status_booking', ['menunggu_verifikasi', 'diterima'])->exists()
|
||||||
'nama' => 'required|string|min:3|max:100',
|
) {
|
||||||
'no_wa' => 'required|numeric|digits_between:10,15',
|
return back()->with('error', 'Slot baru saja diambil orang lain.');
|
||||||
'bukti_bayar' => 'required|image|mimes:jpeg,png,jpg|max:2048',
|
|
||||||
], [
|
|
||||||
'required' => 'Kolom :attribute wajib diisi.',
|
|
||||||
'string' => 'Input :attribute harus berupa teks valid.',
|
|
||||||
'min' => ':attribute terlalu pendek, minimal :min karakter.',
|
|
||||||
'max' => ':attribute terlalu panjang, maksimal :max karakter.',
|
|
||||||
'numeric' => ':attribute harus berupa angka.',
|
|
||||||
'digits_between' => ':attribute harus antara :min sampai :max digit.',
|
|
||||||
'date' => 'Format tanggal pada :attribute tidak valid.',
|
|
||||||
'after_or_equal' => ':attribute tidak boleh tanggal yang sudah lewat.',
|
|
||||||
'image' => ':attribute harus berupa file gambar.',
|
|
||||||
'mimes' => 'Format :attribute harus jpeg, png, atau jpg.',
|
|
||||||
'bukti_bayar.max' => 'Ukuran :attribute maksimal adalah 2MB.',
|
|
||||||
], [
|
|
||||||
'nama' => 'nama pemesan',
|
|
||||||
'no_wa' => 'nomor WhatsApp',
|
|
||||||
'bukti_bayar' => 'bukti pembayaran',
|
|
||||||
]);
|
|
||||||
|
|
||||||
DB::beginTransaction();
|
|
||||||
try {
|
|
||||||
$paket = PaketFoto::findOrFail($request->id_paket);
|
|
||||||
$durasiMenit = $paket->durasi;
|
|
||||||
$jamMulai = \Carbon\Carbon::createFromFormat('H:i', $request->jam_mulai);
|
|
||||||
$jamSelesai = $jamMulai->copy()->addMinutes($durasiMenit);
|
|
||||||
|
|
||||||
$isTaken = BookingFoto::where('tgl_booking', $request->tgl_booking)
|
|
||||||
->where('jam_mulai', $request->jam_mulai)
|
|
||||||
->whereIn('status_booking', ['menunggu_verifikasi', 'diterima', 'selesai'])
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if ($isTaken) {
|
|
||||||
return back()->with('error', 'Mohon maaf, slot waktu ini baru saja diambil orang lain.');
|
|
||||||
}
|
}
|
||||||
|
$pelanggan = Pelanggan::firstOrCreate(['no_wa' => $request->no_wa], ['nama' => $request->nama]);
|
||||||
$pelanggan = Pelanggan::firstOrCreate(
|
$pathBukti = $request->hasFile('bukti_bayar')
|
||||||
['no_wa' => $request->no_wa],
|
? $request->file('bukti_bayar')->store('img/payment/foto', 'public')
|
||||||
['nama' => $request->nama]
|
: null;
|
||||||
);
|
$booking = BookingFoto::create([
|
||||||
$grandTotal = $paket->harga;
|
'no_invoice' => 'INV-FOTO-' . strtoupper(Str::random(6)),
|
||||||
$listAdditional = [];
|
|
||||||
$totalDurasi = $durasiMenit;
|
|
||||||
if ($request->has('addons')) {
|
|
||||||
foreach ($request->addons as $idAddon => $qty) {
|
|
||||||
if ($qty > 0) {
|
|
||||||
$add = \App\Models\Additional::find($idAddon);
|
|
||||||
if ($add) {
|
|
||||||
$subtotal = $add->harga * $qty;
|
|
||||||
$grandTotal += $subtotal;
|
|
||||||
|
|
||||||
if ($idAddon == 4) $totalDurasi += (5 * $qty);
|
|
||||||
if ($idAddon == 6) $totalDurasi += (10 * $qty);
|
|
||||||
|
|
||||||
$listAdditional[] = [
|
|
||||||
'id_additional' => $idAddon,
|
|
||||||
'qty' => $qty,
|
|
||||||
'subtotal' => $subtotal,
|
|
||||||
'nama_barang' => $add->nama
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$jamMulai = \Carbon\Carbon::createFromFormat('H:i', $request->jam_mulai);
|
|
||||||
$jamSelesai = $jamMulai->copy()->addMinutes($totalDurasi);
|
|
||||||
$isTaken = \App\Models\BookingFoto::where('tgl_booking', $request->tgl_booking)
|
|
||||||
->where('jam_mulai', $request->jam_mulai)
|
|
||||||
->whereIn('status_booking', ['menunggu_verifikasi', 'diterima'])
|
|
||||||
->exists();
|
|
||||||
if ($isTaken) {
|
|
||||||
return back()->with('error', 'Mohon maaf, slot waktu ini baru saja diambil orang lain.');
|
|
||||||
}
|
|
||||||
$pelanggan = \App\Models\Pelanggan::create([
|
|
||||||
'nama' => $request->nama,
|
|
||||||
'no_wa' => $request->no_wa
|
|
||||||
]);
|
|
||||||
$pathBukti = null;
|
|
||||||
if ($request->hasFile('bukti_bayar')) {
|
|
||||||
$file = $request->file('bukti_bayar');
|
|
||||||
$namaFile = 'bukti_' . time() . '.' . $file->getClientOriginalExtension();
|
|
||||||
$pathBukti = $file->storeAs('img/payment/foto', $namaFile, 'public');
|
|
||||||
}
|
|
||||||
$booking = \App\Models\BookingFoto::create([
|
|
||||||
'no_invoice' => 'INV-FOTO-' . strtoupper(\Illuminate\Support\Str::random(6)),
|
|
||||||
'id_pelanggan' => $pelanggan->id_pelanggan,
|
'id_pelanggan' => $pelanggan->id_pelanggan,
|
||||||
'id_paket' => $paket->id_paket,
|
'id_paket' => $details['foto']->id_paket,
|
||||||
'tgl_booking' => $request->tgl_booking,
|
'tgl_booking' => $request->tgl_booking,
|
||||||
'jam_mulai' => $request->jam_mulai,
|
'jam_mulai' => $request->jam_mulai,
|
||||||
'jam_selesai' => $jamSelesai->format('H:i'),
|
'jam_selesai' => $details['jamSelesaiBaru'],
|
||||||
'total_bayar' => $grandTotal,
|
'total_bayar' => $details['grandTotal'],
|
||||||
'bukti_bayar' => $pathBukti,
|
'bukti_bayar' => $pathBukti,
|
||||||
'status_booking' => 'menunggu_verifikasi'
|
'status_booking' => 'menunggu_verifikasi'
|
||||||
]);
|
]);
|
||||||
foreach ($listAdditional as $item) {
|
foreach ($details['addonsDetails'] as $item) {
|
||||||
\App\Models\DetailAdditional::create([
|
DetailAdditional::create([
|
||||||
'id_booking' => $booking->id_booking,
|
'id_booking' => $booking->id_booking,
|
||||||
'id_additional' => $item['id_additional'],
|
'id_additional' => $item['id'],
|
||||||
'qty' => $item['qty'],
|
'qty' => $item['qty'],
|
||||||
'subtotal' => $item['subtotal']
|
'subtotal' => $item['subtotal']
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
\Illuminate\Support\Facades\DB::commit();
|
$urlWA = WhatsAppService::getBookingFotoMessage($booking, $details['foto'], $details['addonsDetails'], $details['grandTotal'], $details['jamSelesaiBaru']);
|
||||||
$txtAddons = "";
|
|
||||||
if (count($listAdditional) > 0) {
|
|
||||||
$txtAddons = "*Additional:*";
|
|
||||||
foreach ($listAdditional as $item) {
|
|
||||||
$txtAddons .= "\n- " . $item['nama_barang'] . " (" . $item['qty'] . "x)";
|
|
||||||
}
|
|
||||||
$txtAddons .= "\n";
|
|
||||||
}
|
|
||||||
$pesan = "Halo Admin Flo.do! Saya sudah melakukan pembayaran untuk invoice {$booking->no_invoice}:\n\n" .
|
|
||||||
"*Data Pemesan:*\n" .
|
|
||||||
"Nama: {$request->nama}\n" .
|
|
||||||
"WA: {$request->no_wa}\n\n" .
|
|
||||||
"*Detail Booking:*\n" .
|
|
||||||
"Nama Paket: {$paket->nama}\n" .
|
|
||||||
$txtAddons .
|
|
||||||
"Tanggal: " . \Carbon\Carbon::parse($request->tgl_booking)->translatedFormat('l, d F Y') . "\n" .
|
|
||||||
"Jam: {$request->jam_mulai} - {$jamSelesai->format('H:i')} WIB\n" .
|
|
||||||
"Total: Rp " . number_format($grandTotal, 0, ',', '.') . "\n\n" .
|
|
||||||
"Mohon segera diproses, ya! Terima kasih.";
|
|
||||||
|
|
||||||
$urlWA = "https://wa.me/6282337687878?text=" . urlencode($pesan);
|
|
||||||
session()->forget('payment_deadline');
|
session()->forget('payment_deadline');
|
||||||
|
|
||||||
return redirect()->route('booking.foto')->with([
|
return redirect()->route('booking.foto')->with(['success' => 'Pesanan Berhasil!', 'waUrl' => $urlWA]);
|
||||||
'success' => 'Pesanan Berhasil Dibuat!',
|
});
|
||||||
'waUrl' => $urlWA
|
}
|
||||||
]);
|
private function calculateDetails($request)
|
||||||
} catch (\Exception $e) {
|
{
|
||||||
\Illuminate\Support\Facades\DB::rollBack();
|
$foto = PaketFoto::findOrFail($request->id_paket);
|
||||||
return back()->with('error', 'Error: ' . $e->getMessage())->withInput();
|
$totalAddon = 0;
|
||||||
|
$tambahanMenit = 0;
|
||||||
|
$addonsDetails = [];
|
||||||
|
|
||||||
|
if ($request->has('addons')) {
|
||||||
|
foreach ($request->addons as $id => $qty) {
|
||||||
|
if ($qty > 0 && $add = Additional::find($id)) {
|
||||||
|
$subtotal = $add->harga * $qty;
|
||||||
|
$totalAddon += $subtotal;
|
||||||
|
if ($id == 4) $tambahanMenit += (5 * $qty);
|
||||||
|
if ($id == 6) $tambahanMenit += (10 * $qty);
|
||||||
|
$addonsDetails[] = ['nama' => $add->nama, 'qty' => $qty, 'subtotal' => $subtotal, 'id' => $id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return [
|
||||||
|
'foto' => $foto,
|
||||||
|
'addonsDetails' => $addonsDetails,
|
||||||
|
'grandTotal' => $foto->harga + $totalAddon,
|
||||||
|
'jamSelesaiBaru' => Carbon::createFromFormat('H:i', $request->jam_mulai)
|
||||||
|
->addMinutes($foto->durasi + $tambahanMenit)->format('H:i')
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\User;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class BookingFotoRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'id_paket' => 'required|exists:paket_fotos,id_paket',
|
||||||
|
'tgl_booking' => 'required|date|after_or_equal:today',
|
||||||
|
'jam_mulai' => 'required',
|
||||||
|
'nama' => 'required|string|min:3|max:100',
|
||||||
|
'no_wa' => 'required|numeric|digits_between:10,15',
|
||||||
|
'bukti_bayar' => 'required|image|mimes:jpeg,png,jpg|max:2048',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function messages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'required' => 'Kolom :attribute wajib diisi.',
|
||||||
|
'image' => ':attribute harus berupa file gambar.',
|
||||||
|
'max' => 'Ukuran :attribute maksimal adalah 2MB.',
|
||||||
|
'string' => 'Input :attribute harus berupa teks valid.',
|
||||||
|
'min' => ':attribute terlalu pendek, minimal :min karakter.',
|
||||||
|
'numeric' => ':attribute harus berupa angka.',
|
||||||
|
'digits_between' => ':attribute harus antara :min sampai :max digit.',
|
||||||
|
'date' => 'Format tanggal pada :attribute tidak valid.',
|
||||||
|
'after_or_equal' => ':attribute tidak boleh tanggal yang sudah lewat.',
|
||||||
|
'mimes' => 'Format :attribute harus jpeg, png, atau jpg.',
|
||||||
|
'bukti_bayar.max' => 'Ukuran :attribute maksimal adalah 2MB.',
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
public function attributes(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'nama' => 'nama pemesan',
|
||||||
|
'no_wa' => 'nomor WhatsApp',
|
||||||
|
'bukti_bayar' => 'bukti pembayaran',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue