Some improvements, and some not so much...
This commit is contained in:
parent
72f3decd3f
commit
8f7ad95506
|
@ -11,6 +11,7 @@ use App\Models\Payment;
|
||||||
use App\Models\ShopProduct;
|
use App\Models\ShopProduct;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Models\Coupon;
|
use App\Models\Coupon;
|
||||||
|
use App\Traits\Coupon as CouponTrait;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Redirect;
|
use Illuminate\Support\Facades\Redirect;
|
||||||
|
@ -28,6 +29,8 @@ use PayPalHttp\HttpException;
|
||||||
*/
|
*/
|
||||||
class PayPalExtension extends AbstractExtension
|
class PayPalExtension extends AbstractExtension
|
||||||
{
|
{
|
||||||
|
use CouponTrait;
|
||||||
|
|
||||||
public static function getConfig(): array
|
public static function getConfig(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -36,23 +39,27 @@ class PayPalExtension extends AbstractExtension
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static function PaypalPay(Request $request): void
|
public function PaypalPay(Request $request): void
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
|
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
|
||||||
$discount = PartnerDiscount::getDiscount();
|
$discount = PartnerDiscount::getDiscount();
|
||||||
$discountPrice = $request->get('discountPrice');
|
$couponCode = $request->input('couponCode');
|
||||||
|
$isValidCoupon = $this->validateCoupon($request->user(), $couponCode, $request->shopProduct);
|
||||||
|
|
||||||
dd($discountPrice);
|
if (is_string($shopProduct->price)) {
|
||||||
|
$shopProduct->price = floatval($shopProduct->price);
|
||||||
|
}
|
||||||
|
|
||||||
|
$price = $shopProduct->price;
|
||||||
|
|
||||||
|
if ($isValidCoupon->getStatusCode() == 200) {
|
||||||
|
$price = $this->calcDiscount($price, $isValidCoupon->getData());
|
||||||
|
}
|
||||||
|
|
||||||
// Partner Discount.
|
// Partner Discount.
|
||||||
$price = $shopProduct->price - ($shopProduct->price * $discount / 100);
|
$price = $price - ($price * $discount / 100);
|
||||||
|
|
||||||
// Coupon Discount.
|
|
||||||
// if ($discountPrice) {
|
|
||||||
// $price = $price - ($price * floatval($coupon_percentage) / 100);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// create a new payment
|
// create a new payment
|
||||||
$payment = Payment::create([
|
$payment = Payment::create([
|
||||||
|
@ -82,13 +89,11 @@ class PayPalExtension extends AbstractExtension
|
||||||
"value" => $shopProduct->getTotalPrice(),
|
"value" => $shopProduct->getTotalPrice(),
|
||||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||||
'breakdown' => [
|
'breakdown' => [
|
||||||
'item_total' =>
|
'item_total' => [
|
||||||
[
|
|
||||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||||
'value' => number_format($price, 2),
|
'value' => number_format($price, 2),
|
||||||
],
|
],
|
||||||
'tax_total' =>
|
'tax_total' => [
|
||||||
[
|
|
||||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||||
'value' => $shopProduct->getTaxValue(),
|
'value' => $shopProduct->getTaxValue(),
|
||||||
]
|
]
|
||||||
|
@ -98,7 +103,7 @@ class PayPalExtension extends AbstractExtension
|
||||||
],
|
],
|
||||||
"application_context" => [
|
"application_context" => [
|
||||||
"cancel_url" => route('payment.Cancel'),
|
"cancel_url" => route('payment.Cancel'),
|
||||||
"return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id, 'couponCode' => $coupon_code]),
|
"return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id, 'couponCode' => $couponCode]),
|
||||||
'brand_name' => config('app.name', 'CtrlPanel.GG'),
|
'brand_name' => config('app.name', 'CtrlPanel.GG'),
|
||||||
'shipping_preference' => 'NO_SHIPPING'
|
'shipping_preference' => 'NO_SHIPPING'
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,8 +4,8 @@ use Illuminate\Support\Facades\Route;
|
||||||
use App\Extensions\PaymentGateways\PayPal\PayPalExtension;
|
use App\Extensions\PaymentGateways\PayPal\PayPalExtension;
|
||||||
|
|
||||||
Route::middleware(['web', 'auth'])->group(function () {
|
Route::middleware(['web', 'auth'])->group(function () {
|
||||||
Route::get('payment/PayPalPay/{shopProduct}', function () {
|
Route::get('payment/PayPalPay/{shopProduct}', function (PayPalExtension $payPalExtension) {
|
||||||
PayPalExtension::PaypalPay(request());
|
$payPalExtension->PaypalPay(request());
|
||||||
})->name('payment.PayPalPay');
|
})->name('payment.PayPalPay');
|
||||||
|
|
||||||
Route::get(
|
Route::get(
|
||||||
|
|
|
@ -154,6 +154,6 @@ class CouponController extends Controller
|
||||||
|
|
||||||
public function redeem(Request $request)
|
public function redeem(Request $request)
|
||||||
{
|
{
|
||||||
return $this->validateCoupon($request);
|
return $this->validateCoupon($request->user(), $request->input('couponCode'), $request->input('productId'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,7 +130,6 @@ class PaymentController extends Controller
|
||||||
{
|
{
|
||||||
$product = ShopProduct::find($request->product_id);
|
$product = ShopProduct::find($request->product_id);
|
||||||
$paymentGateway = $request->payment_method;
|
$paymentGateway = $request->payment_method;
|
||||||
$coupon_data = null;
|
|
||||||
$coupon_code = $request->coupon_code;
|
$coupon_code = $request->coupon_code;
|
||||||
|
|
||||||
// on free products, we don't need to use a payment gateway
|
// on free products, we don't need to use a payment gateway
|
||||||
|
@ -140,18 +139,9 @@ class PaymentController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($coupon_code) {
|
if ($coupon_code) {
|
||||||
$isValidCoupon = $this->validateCoupon($request);
|
|
||||||
|
|
||||||
if ($isValidCoupon->getStatusCode() == 200) {
|
|
||||||
$coupon_data = $isValidCoupon;
|
|
||||||
$discountPrice = $this->calcDiscount($product, $isValidCoupon->getData());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($coupon_data) {
|
|
||||||
return redirect()->route('payment.' . $paymentGateway . 'Pay', [
|
return redirect()->route('payment.' . $paymentGateway . 'Pay', [
|
||||||
'shopProduct' => $product->id,
|
'shopProduct' => $product->id,
|
||||||
'discountPrice' => $discountPrice
|
'couponCode' => $coupon_code
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,11 +156,6 @@ class PaymentController extends Controller
|
||||||
return redirect()->route('store.index')->with('info', 'Payment was Canceled');
|
return redirect()->route('store.index')->with('info', 'Payment was Canceled');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getCouponDiscount(float $productPrice, string $discount)
|
|
||||||
{
|
|
||||||
return $productPrice - ($productPrice * $discount / 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return JsonResponse|mixed
|
* @return JsonResponse|mixed
|
||||||
*
|
*
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Coupon extends Model
|
||||||
return 'USES_LIMIT_REACHED';
|
return 'USES_LIMIT_REACHED';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! is_null($this->expires_at)) {
|
if (!is_null($this->expires_at)) {
|
||||||
$expires_at = Carbon::createFromTimeString($this->expires_at)->timestamp;
|
$expires_at = Carbon::createFromTimeString($this->expires_at)->timestamp;
|
||||||
|
|
||||||
if ($expires_at <= Carbon::now()->timestamp) {
|
if ($expires_at <= Carbon::now()->timestamp) {
|
||||||
|
@ -59,9 +59,9 @@ class Coupon extends Model
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function isLimitsUsesReached($request, $coupon_settings): bool
|
public function isLimitsUsesReached($requestUser, $coupon_settings): bool
|
||||||
{
|
{
|
||||||
$coupon_uses = $request->user()->coupons()->where('id', $this->id)->count();
|
$coupon_uses = $requestUser->coupons()->where('id', $this->id)->count();
|
||||||
|
|
||||||
return $coupon_uses >= $coupon_settings->max_uses_per_user ? true : false;
|
return $coupon_uses >= $coupon_settings->max_uses_per_user ? true : false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@ use stdClass;
|
||||||
|
|
||||||
trait Coupon
|
trait Coupon
|
||||||
{
|
{
|
||||||
public function validateCoupon(Request $request): JsonResponse
|
public function validateCoupon($requestUser, $couponCode, $productId): JsonResponse
|
||||||
{
|
{
|
||||||
$coupon = CouponModel::where('code', $request->input('coupon_code'))->first();
|
$coupon = CouponModel::where('code', $couponCode)->first();
|
||||||
|
$shopProduct = ShopProduct::findOrFail($productId);
|
||||||
$coupon_settings = new CouponSettings;
|
$coupon_settings = new CouponSettings;
|
||||||
$response = response()->json([
|
$response = response()->json([
|
||||||
'isValid' => false,
|
'isValid' => false,
|
||||||
|
@ -21,6 +22,14 @@ trait Coupon
|
||||||
], 404);
|
], 404);
|
||||||
|
|
||||||
if (!is_null($coupon)) {
|
if (!is_null($coupon)) {
|
||||||
|
if (is_string($coupon->value)) {
|
||||||
|
$coupon->value = floatval($coupon->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_string($shopProduct->price)) {
|
||||||
|
$shopProduct->price = floatval($shopProduct->price);
|
||||||
|
}
|
||||||
|
|
||||||
if ($coupon->getStatus() == 'USES_LIMIT_REACHED') {
|
if ($coupon->getStatus() == 'USES_LIMIT_REACHED') {
|
||||||
$response = response()->json([
|
$response = response()->json([
|
||||||
'isValid' => false,
|
'isValid' => false,
|
||||||
|
@ -39,7 +48,7 @@ trait Coupon
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($coupon->isLimitsUsesReached($request, $coupon_settings)) {
|
if ($coupon->isLimitsUsesReached($requestUser, $coupon_settings)) {
|
||||||
$response = response()->json([
|
$response = response()->json([
|
||||||
'isValid' => false,
|
'isValid' => false,
|
||||||
'error' => __('You have reached the maximum uses of this coupon.')
|
'error' => __('You have reached the maximum uses of this coupon.')
|
||||||
|
@ -48,6 +57,15 @@ trait Coupon
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($coupon->type === 'amount' && $coupon->value >= $shopProduct->price) {
|
||||||
|
$response = response()->json([
|
||||||
|
'isValid' => false,
|
||||||
|
'error' => __('The coupon you are trying to use would give you 100% off, so it cannot be used for this product, sorry.')
|
||||||
|
], 422);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
$response = response()->json([
|
$response = response()->json([
|
||||||
'isValid' => true,
|
'isValid' => true,
|
||||||
'couponCode' => $coupon->code,
|
'couponCode' => $coupon->code,
|
||||||
|
@ -59,14 +77,12 @@ trait Coupon
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function calcDiscount(ShopProduct $product, stdClass $data)
|
public function calcDiscount($productPrice, stdClass $data)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ($data->isValid) {
|
if ($data->isValid) {
|
||||||
$productPrice = $product->price;
|
|
||||||
|
|
||||||
if (is_string($productPrice)) {
|
if (is_string($productPrice)) {
|
||||||
$productPrice = floatval($product->price);
|
$productPrice = floatval($productPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($data->couponType === 'percentage') {
|
if ($data->couponType === 'percentage') {
|
||||||
|
@ -82,5 +98,7 @@ trait Coupon
|
||||||
|
|
||||||
return $productPrice - $data->couponValue;
|
return $productPrice - $data->couponValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $productPrice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ return new class extends Migration
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('code')->unique();
|
$table->string('code')->unique();
|
||||||
$table->enum('type', ['percentage', 'amount']);
|
$table->enum('type', ['percentage', 'amount']);
|
||||||
$table->integer('value');
|
$table->decimal('value', 10);
|
||||||
$table->integer('uses')->default(0);
|
$table->integer('uses')->default(0);
|
||||||
$table->integer('max_uses');
|
$table->integer('max_uses');
|
||||||
$table->timestamp('expires_at');
|
$table->timestamp('expires_at')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,6 +185,8 @@
|
||||||
<div id="coupon_discount_details" class="d-flex justify-content-between" style="display: none !important;">
|
<div id="coupon_discount_details" class="d-flex justify-content-between" style="display: none !important;">
|
||||||
<span class="text-muted d-inline-block">
|
<span class="text-muted d-inline-block">
|
||||||
{{ __('Coupon Discount') }}
|
{{ __('Coupon Discount') }}
|
||||||
|
</span>
|
||||||
|
<span id="coupon_discount_value" class="text-muted d-inline-block">
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -199,8 +201,13 @@
|
||||||
<hr class="text-white border-secondary">
|
<hr class="text-white border-secondary">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<span class="text-muted d-inline-block">{{ __('Total') }}</span>
|
<span class="text-muted d-inline-block">{{ __('Total') }}</span>
|
||||||
|
<input id="total_price_input" type="hidden" value="{{ $product->getTotalPrice() }}">
|
||||||
<span
|
<span
|
||||||
class="text-muted d-inline-block">{{ $product->formatToCurrency($total) }}</span>
|
id="total_price"
|
||||||
|
class="text-muted d-inline-block"
|
||||||
|
>
|
||||||
|
{{ $product->formatToCurrency($total) }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<template x-if="payment_method">
|
<template x-if="payment_method">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
|
@ -240,27 +247,46 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
const productId = $("[name='product_id']").val()
|
||||||
let hasCouponCodeValue = $('#coupon_code').val().trim() !== ''
|
let hasCouponCodeValue = $('#coupon_code').val().trim() !== ''
|
||||||
|
|
||||||
$('#coupon_code').on('change', function(e) {
|
$('#coupon_code').on('change', function(e) {
|
||||||
hasCouponCodeValue = e.target.value !== ''
|
hasCouponCodeValue = e.target.value !== ''
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function calcPriceWithCouponDiscount(couponValue, couponType) {
|
||||||
|
let totalPrice = $('#total_price_input').val()
|
||||||
|
|
||||||
|
if (typeof totalPrice == 'string') {
|
||||||
|
totalPrice = parseFloat(totalPrice)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (couponType === 'percentage') {
|
||||||
|
totalPrice = totalPrice - (totalPrice * couponValue / 100)
|
||||||
|
$('#coupon_discount_value').text("- " + couponValue + "%")
|
||||||
|
} else if (couponType === 'amount') {
|
||||||
|
totalPrice = totalPrice - couponValue
|
||||||
|
$('#coupon_discount_value').text(totalPrice)
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#total_price').text(totalPrice)
|
||||||
|
$('#total_price_input').val(totalPrice)
|
||||||
|
}
|
||||||
|
|
||||||
function checkCoupon() {
|
function checkCoupon() {
|
||||||
const couponCode = $('#coupon_code').val()
|
const couponCode = $('#coupon_code').val()
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "{{ route('admin.coupon.redeem') }}",
|
url: "{{ route('admin.coupon.redeem') }}",
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: { coupon_code: couponCode },
|
data: { couponCode: couponCode, productId: productId },
|
||||||
success: function(response) {
|
success: function(response) {
|
||||||
if (response.isValid && response.couponCode) {
|
if (response.isValid && response.couponCode) {
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
icon: 'success',
|
icon: 'success',
|
||||||
text: `The coupon '${response.couponCode}' was successfully inserted in your purchase.`,
|
text: 'The coupon was successfully added to your purchase.',
|
||||||
}).then(function(isConfirmed) {
|
}).then(function(isConfirmed) {
|
||||||
console.log('confirmou')
|
calcPriceWithCouponDiscount(response.couponValue, response.couponType)
|
||||||
|
|
||||||
$('#submit_form_button').prop('disabled', false).removeClass('disabled')
|
$('#submit_form_button').prop('disabled', false).removeClass('disabled')
|
||||||
$('#send_coupon_code').prop('disabled', true)
|
$('#send_coupon_code').prop('disabled', true)
|
||||||
$('#coupon_discount_details').prop('disabled', false).show()
|
$('#coupon_discount_details').prop('disabled', false).show()
|
||||||
|
|
Loading…
Reference in a new issue