From fa00ee377ad7689dbb10b6ca8438262f0df1b8f4 Mon Sep 17 00:00:00 2001 From: Bayu Lukman Yusuf Date: Thu, 29 Jan 2026 08:26:00 +0700 Subject: [PATCH] checkout & create payment --- app/Http/Controllers/CheckoutController.php | 73 +++- app/Models/ItemReference.php | 7 +- app/Repositories/Auth/RoleRepository.php | 66 +++ .../Member/Transaction/CheckoutController.php | 26 -- .../Member/Voucher/VoucherRepository.php | 149 +++++++ app/ThirdParty/Xendit/Xendit.php | 24 ++ .../checkout/v1-delivery-1-shipping.blade.php | 395 ++++-------------- .../views/checkout/v1-delivery-1.blade.php | 7 + 8 files changed, 396 insertions(+), 351 deletions(-) create mode 100644 app/Repositories/Auth/RoleRepository.php delete mode 100644 app/Repositories/Member/Transaction/CheckoutController.php create mode 100644 app/Repositories/Member/Voucher/VoucherRepository.php create mode 100644 app/ThirdParty/Xendit/Xendit.php diff --git a/app/Http/Controllers/CheckoutController.php b/app/Http/Controllers/CheckoutController.php index 6b45eeb..bb955f9 100644 --- a/app/Http/Controllers/CheckoutController.php +++ b/app/Http/Controllers/CheckoutController.php @@ -6,6 +6,7 @@ use App\Models\Address; use App\Models\Location; use App\Repositories\Member\Cart\MemberCartRepository; use App\Repositories\Member\ShippingRepository; +use App\Repositories\Member\Transaction\TransactionRepository; use Illuminate\Http\Request; class CheckoutController extends Controller @@ -77,6 +78,12 @@ class CheckoutController extends Controller $location_id = session('location_id', 22); + + if ($delivery_method == null || $address_id == null || $location_id == null) { + + return redirect()->route('checkout.delivery'); + } + $subtotal = $memberCartRepository->getSubtotal($location_id); $total = $subtotal; @@ -97,11 +104,6 @@ class CheckoutController extends Controller 'cost' => $row['shipping_fee'], ]; }); - - - - - return view('checkout.v1-delivery-1-shipping', [ 'carts' => $request->user()->carts, @@ -113,8 +115,6 @@ class CheckoutController extends Controller 'shipping_list' => $shipping_list, ]); } catch (\Exception $e) { - dd($e); - return redirect()->route('checkout.delivery')->with('error', 'Invalid checkout data'); } } @@ -131,22 +131,73 @@ class CheckoutController extends Controller session(['checkout_courier' => $courier]); session(['checkout_service' => $service]); - session(['checkout_shipping_cost' => $cost]); + // session(['checkout_shipping_cost' => $cost]); return redirect()->route('checkout.payment'); } - public function choosePayment(Request $request) + public function choosePayment(Request $request, TransactionRepository $repository, MemberCartRepository $memberCartRepository) { try { - - // proses checkout + $address_id = session('checkout_address_id'); + + $courier = session('checkout_courier'); + $service = session('checkout_service'); + + $location_id = session('location_id', 22); + + $items = []; + + $request->merge(['location_id' => $location_id]); + $carts = $memberCartRepository->getList($request); + + if (count($carts) == 0) { + return redirect()->route('checkout.delivery')->with('error', 'No items in cart'); + } + + foreach ($carts as $cart) { + $items[] = [ + "item_reference_id" => $cart->item_reference_id, + "qty" => $cart->qty + ]; + } + + $data = [ + "address_id" => $address_id, + "note" => "", + "courier_company" => $courier, + "courier_type" => $service, + "location_id" => $location_id, + "items" => $items, + "vouchers" => [], + "use_customer_points" => 0, + ]; + + $item = $repository->create($data); + + $notification = new \App\Notifications\Member\Transaction\OrderWaitPayment($item); + $user = auth()->user(); + $user->notify($notification->delay(now()->addMinutes(1))); + + // return new CheckoutResource($item); // proses payment + $payment = $item->payments()->where("method_type",'App\Models\XenditLink') + ->where("status",'PENDING') + ->first(); + $invoice_url = $payment ? @$payment->method->invoice_url: ""; + + return redirect()->to($invoice_url); + + + } catch (\Exception $e) { + + dd($e); + return redirect()->route('checkout.delivery')->with('error', 'Invalid checkout data'); } } diff --git a/app/Models/ItemReference.php b/app/Models/ItemReference.php index c70e3d2..4853b09 100644 --- a/app/Models/ItemReference.php +++ b/app/Models/ItemReference.php @@ -6,8 +6,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Awobaz\Compoships\Compoships; use Carbon\Carbon; +use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; -use Cache; + class ItemReference extends Model { @@ -126,9 +127,7 @@ class ItemReference extends Model }); -// Log::info([$location_id, $is_consignment]); - - return $this->hasOne(Discount::class,DB::raw("discount_items.item_reference_id")) + return $this->hasOne(Discount::class, 'id', 'item_reference_id') ->leftJoin("discount_items","discounts.id","=","discount_id") ->where("discounts.type","discount") ->orderBy("discounts.created_at","desc") diff --git a/app/Repositories/Auth/RoleRepository.php b/app/Repositories/Auth/RoleRepository.php new file mode 100644 index 0000000..d3186e6 --- /dev/null +++ b/app/Repositories/Auth/RoleRepository.php @@ -0,0 +1,66 @@ +where('name', 'iLIKE', '%' . $params['search'] . '%'); + }) + ->orderBy($sortColumn, $sortDir) + ->paginate($limit); + } + + public function getPermission(array $params = []) + { + return Permission::orderBy("code")->paginate(1000); + } + + public function create(array $data) + { + $item = Role::create($data); + $item->permissions()->sync($data["permissions"]); + $item->save(); + return $item; + } + + public function update(Role $item, array $data) + { + $item->update($data); + $item->permissions()->sync($data["permissions"]); + $item->save(); + return $item; + } + + public function delete(Role $item) + { + $item->delete(); + } + + public function findBy($column, $value) + { + $item = Role::where($column, $value)->firstOrFail(); + return $item; + } + + public function findUserByPermission($code) + { + $roles = Role::whereHas("permissions", function($query) use ($code){ + $query->where("code", $code); + })->get(); + return $roles->flatMap(function($role){ + return $role->users; + }); + } +} diff --git a/app/Repositories/Member/Transaction/CheckoutController.php b/app/Repositories/Member/Transaction/CheckoutController.php deleted file mode 100644 index 5cb9a3e..0000000 --- a/app/Repositories/Member/Transaction/CheckoutController.php +++ /dev/null @@ -1,26 +0,0 @@ -validated(); - $item = $repository->create($data); - - $notification = new OrderWaitPayment($item); - $user = auth()->user(); - $user->notify($notification->delay(now()->addMinutes(1))); - - return new CheckoutResource($item); - } - -} diff --git a/app/Repositories/Member/Voucher/VoucherRepository.php b/app/Repositories/Member/Voucher/VoucherRepository.php new file mode 100644 index 0000000..bc21a62 --- /dev/null +++ b/app/Repositories/Member/Voucher/VoucherRepository.php @@ -0,0 +1,149 @@ +user()->id; + $customer = Customer::where("user_id", $user_id)->first(); + $model = Voucher::where('customer_id', (int) @$customer->id) + ->where('used_at', null) + ->where('expired_at','>=',Carbon::now()) + ->orderBy('created_at','desc')->paginate($request->limit); + + return $model; + } + + + public function getValidByItems($carts, $customer_id) + { + $item_reference_ids = $carts->pluck("item_reference_id")->toArray(); + // collect voucher ids valids + if (count($item_reference_ids) == 0){ + $item_reference_ids[] = 0; + } + + $item_ids = implode(',', $item_reference_ids); + $ids = DB::select("SELECT distinct vouchers.id from vouchers + left join voucher_events on vouchers.voucher_event_id = voucher_events.id + left join voucher_items on voucher_items.voucher_event_id = voucher_events.id + where used_at is null and + (expired_at > now() or expired_at is null) and + customer_id = ? and ( + redeem_point > 0 or + ( vouchers.voucher_event_id is null and vouchers.item_reference_id is null) or + ( vouchers.voucher_event_id is not null and voucher_items.item_reference_id is null) or + ( vouchers.item_reference_id is not null and vouchers.item_reference_id in ($item_ids)) or + ( vouchers.voucher_event_id is not null and voucher_items.item_reference_id in ($item_ids)) + )",[$customer_id]); + $ids = collect($ids)->pluck("id")->toArray(); + return $ids; + } + + public function getSum($params) + { + $user_id = auth()->user()->id; + $customer = Customer::where("user_id", $user_id)->firstOrFail(); + $voucher_ids = $params["voucher_ids"]; + // collect item_reference_ids + $cart_ids = @$params["cart_ids"] ?? []; + $carts = Cart::where("user_id", $user_id) + ->where(function($query) use ($cart_ids){ + if (count($cart_ids)){ + $query->whereIn("id", $cart_ids); + } + }) + ->get(); + $ids = $this->getValidByItems($carts, $customer->id); + + return Voucher::where('customer_id', (int) @$customer->id) + ->where('used_at', null) + ->whereIn('id', $ids) + ->whereIn('id', $ids) + ->orderBy('created_at','desc') + ->get(); + } + + public function getValid($params) + { + $user_id = auth()->user()->id; + $customer = Customer::where("user_id", $user_id)->first(); + $limit = $params["limit"] ?? 10; + + // collect item_reference_ids + $cart_ids = @$params["cart_ids"] ?? []; + $carts = Cart::where("user_id", $user_id) + ->where(function($query) use ($cart_ids){ + if (count($cart_ids)){ + $query->whereIn("id", $cart_ids); + } + }) + ->get(); + + $ids = $this->getValidByItems($carts, $customer->id); + + return Voucher::where('customer_id', (int) @$customer->id) + ->where('used_at', null) + ->orderBy('created_at','desc')->paginate($limit) + ->transform(function ($voucher, $key) use ($ids) { + $voucher->is_valid = in_array($voucher->id, $ids); + return $voucher; + }); + } + + public function detail($id) + { + $model = Voucher::findOrFail($id); + return $model; + } + + public function send($id, $data) + { + $model = DB::transaction(function () use ($id, $data) { + + $customer = Customer::where("user_id", $data['customer_id'])->firstOrFail(); + $model = Voucher::findOrFail($id); + + \Log::info("VOUCHER SEND FROM ".$model->customer_id." TO ".$customer->id); + + $model->customer_id = $customer->id; + $model->save(); + + return $model; + }); + + return $model; + } + + public function phoneCheck($data) + { + $model = DB::transaction(function () use ($data) { + + $model = Customer::where('phone', $data['phone'])->first(); + + if ($model->user_id == null) { + + throw ValidationException::withMessages([ + "phone" => "User dari phone number belum terdaftar" + ]); + } + + $model = User::findOrfail($model->user_id); + + return $model; + }); + + return $model; + } + +} diff --git a/app/ThirdParty/Xendit/Xendit.php b/app/ThirdParty/Xendit/Xendit.php new file mode 100644 index 0000000..5de8a7a --- /dev/null +++ b/app/ThirdParty/Xendit/Xendit.php @@ -0,0 +1,24 @@ +withBody(json_encode($payload), 'application/json') + ->post($url); + + if ($res->status() == 200) + return $res->json(); + + return null; + } +} diff --git a/resources/views/checkout/v1-delivery-1-shipping.blade.php b/resources/views/checkout/v1-delivery-1-shipping.blade.php index c794650..80c07b5 100644 --- a/resources/views/checkout/v1-delivery-1-shipping.blade.php +++ b/resources/views/checkout/v1-delivery-1-shipping.blade.php @@ -37,9 +37,7 @@
@csrf - - - + @if ($delivery_method == 'shipping') @foreach ($shipping_list as $shipping)
@@ -100,360 +98,137 @@ @section('scripts') @endsection diff --git a/resources/views/checkout/v1-delivery-1.blade.php b/resources/views/checkout/v1-delivery-1.blade.php index 5142acc..104b646 100644 --- a/resources/views/checkout/v1-delivery-1.blade.php +++ b/resources/views/checkout/v1-delivery-1.blade.php @@ -8,6 +8,13 @@
+ {{-- show error message --}} + @if(session('error')) +
+ {{ session('error') }} +
+ @endif +