Merge pull request #575 from ok236449/Partners-and-discounts
Partners and discounts
This commit is contained in:
commit
8b8d73c3b2
23 changed files with 1060 additions and 96 deletions
|
@ -40,6 +40,7 @@ class Misc
|
|||
'enable_referral' => 'nullable|string',
|
||||
'referral_reward' => 'nullable|numeric',
|
||||
'referral_allowed' => 'nullable|string',
|
||||
'always_give_commission' => 'nullable|string',
|
||||
'referral_percentage' => 'nullable|numeric',
|
||||
'referral_mode' => 'nullable|string',
|
||||
'ticket_enabled' => 'nullable|string',
|
||||
|
@ -87,6 +88,7 @@ class Misc
|
|||
"SETTINGS::REFERRAL::REWARD" => "referral_reward",
|
||||
"SETTINGS::REFERRAL::ALLOWED" => "referral_allowed",
|
||||
"SETTINGS::REFERRAL:MODE" => "referral_mode",
|
||||
"SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION" => "always_give_commission",
|
||||
"SETTINGS::REFERRAL:PERCENTAGE" => "referral_percentage",
|
||||
"SETTINGS::TICKET:ENABLED" => "ticket_enabled"
|
||||
|
||||
|
|
|
@ -52,6 +52,19 @@ class OverViewController extends Controller
|
|||
$counters['payments']['thisMonth']->timeEnd = Carbon::today()->toDateString();
|
||||
$counters['payments']['lastMonth']->timeStart = Carbon::today()->startOfMonth()->subMonth()->toDateString();
|
||||
$counters['payments']['lastMonth']->timeEnd = Carbon::today()->endOfMonth()->subMonth()->toDateString();
|
||||
|
||||
|
||||
//Prepare subCollection 'taxPayments'
|
||||
$counters->put('taxPayments', collect());
|
||||
//Get and save taxPayments from last 2 years for later filtering and looping
|
||||
$taxPayments = Payment::query()->where('created_at', '>=', Carbon::today()->startOfYear()->subYear())->where('status', 'paid')->get();
|
||||
//Prepare collections and set a few variables
|
||||
$counters['taxPayments']->put('thisYear', collect());
|
||||
$counters['taxPayments']->put('lastYear', collect());
|
||||
$counters['taxPayments']['thisYear']->timeStart = Carbon::today()->startOfYear()->toDateString();
|
||||
$counters['taxPayments']['thisYear']->timeEnd = Carbon::today()->toDateString();
|
||||
$counters['taxPayments']['lastYear']->timeStart = Carbon::today()->startOfYear()->subYear()->toDateString();
|
||||
$counters['taxPayments']['lastYear']->timeEnd = Carbon::today()->endOfYear()->subYear()->toDateString();
|
||||
|
||||
//Fill out variables for each currency separately
|
||||
foreach($payments->where('created_at', '>=', Carbon::today()->startOfMonth()) as $payment){
|
||||
|
@ -76,6 +89,35 @@ class OverViewController extends Controller
|
|||
}
|
||||
$counters['payments']->total = Payment::query()->count();
|
||||
|
||||
foreach($taxPayments->where('created_at', '>=', Carbon::today()->startOfYear()->subYear()) as $taxPayment){
|
||||
$paymentCurrency = $payment->currency_code;
|
||||
if(!isset($counters['taxPayments']['thisYear'][$paymentCurrency])){
|
||||
$counters['taxPayments']['thisYear']->put($paymentCurrency, collect());
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->total = 0;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->count = 0;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->price = 0;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->taxes = 0;
|
||||
}
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->total += $taxPayment->total_price;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->count ++;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->price += $taxPayment->price;
|
||||
$counters['taxPayments']['thisYear'][$paymentCurrency]->taxes += $taxPayment->tax_value;
|
||||
}
|
||||
foreach($taxPayments->where('created_at', '<', Carbon::today()->startOfYear()) as $taxPayment){
|
||||
$paymentCurrency = $payment->currency_code;
|
||||
if(!isset($counters['taxPayments']['lastYear'][$paymentCurrency])){
|
||||
$counters['taxPayments']['lastYear']->put($paymentCurrency, collect());
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->total = 0;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->count = 0;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->price = 0;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->taxes = 0;
|
||||
}
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->total += $taxPayment->total_price;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->count ++;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->price += $taxPayment->price;
|
||||
$counters['taxPayments']['lastYear'][$paymentCurrency]->taxes += $taxPayment->tax_value;
|
||||
}
|
||||
|
||||
$lastEgg = Egg::query()->latest('updated_at')->first();
|
||||
$syncLastUpdate = $lastEgg ? $lastEgg->updated_at->isoFormat('LLL') : __('unknown');
|
||||
|
||||
|
@ -124,33 +166,30 @@ class OverViewController extends Controller
|
|||
|
||||
|
||||
//Get latest tickets
|
||||
$tickets = Cache::remember('tickets', self::TTL, function(){
|
||||
$output = collect();
|
||||
foreach(Ticket::query()->latest()->take(3)->get() as $ticket){
|
||||
$output->put($ticket->ticket_id, collect());
|
||||
$output[$ticket->ticket_id]->title = $ticket->title;
|
||||
$user = User::query()->where('id', $ticket->user_id)->first();
|
||||
$output[$ticket->ticket_id]->user_id = $user->id;
|
||||
$output[$ticket->ticket_id]->user = $user->name;
|
||||
$output[$ticket->ticket_id]->status = $ticket->status;
|
||||
$output[$ticket->ticket_id]->last_updated = $ticket->updated_at->diffForHumans();
|
||||
switch ($ticket->status) {
|
||||
case 'Open':
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-success';
|
||||
break;
|
||||
case 'Closed':
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-danger';
|
||||
break;
|
||||
case 'Answered':
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-info';
|
||||
break;
|
||||
default:
|
||||
$output[$ticket->ticket_id]->statusBadgeColor = 'badge-warning';
|
||||
break;
|
||||
}
|
||||
$tickets = collect();
|
||||
foreach(Ticket::query()->latest()->take(5)->get() as $ticket){
|
||||
$tickets->put($ticket->ticket_id, collect());
|
||||
$tickets[$ticket->ticket_id]->title = $ticket->title;
|
||||
$user = User::query()->where('id', $ticket->user_id)->first();
|
||||
$tickets[$ticket->ticket_id]->user_id = $user->id;
|
||||
$tickets[$ticket->ticket_id]->user = $user->name;
|
||||
$tickets[$ticket->ticket_id]->status = $ticket->status;
|
||||
$tickets[$ticket->ticket_id]->last_updated = $ticket->updated_at->diffForHumans();
|
||||
switch ($ticket->status) {
|
||||
case 'Open':
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-success';
|
||||
break;
|
||||
case 'Closed':
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-danger';
|
||||
break;
|
||||
case 'Answered':
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-info';
|
||||
break;
|
||||
default:
|
||||
$tickets[$ticket->ticket_id]->statusBadgeColor = 'badge-warning';
|
||||
break;
|
||||
}
|
||||
return $output;
|
||||
});
|
||||
}
|
||||
|
||||
return view('admin.overview.index', [
|
||||
'counters' => $counters,
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
|
|||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\InvoiceSettings;
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\Payment;
|
||||
use App\Models\ShopProduct;
|
||||
use App\Models\Settings;
|
||||
|
@ -57,10 +58,13 @@ class PaymentController extends Controller
|
|||
public function checkOut(Request $request, ShopProduct $shopProduct)
|
||||
{
|
||||
return view('store.checkout')->with([
|
||||
'product' => $shopProduct,
|
||||
'taxvalue' => $shopProduct->getTaxValue(),
|
||||
'taxpercent' => $shopProduct->getTaxPercent(),
|
||||
'total' => $shopProduct->getTotalPrice()
|
||||
'product' => $shopProduct,
|
||||
'discountpercent' => PartnerDiscount::getDiscount(),
|
||||
'discountvalue' => PartnerDiscount::getDiscount() * $shopProduct->price/100,
|
||||
'discountedprice' => $shopProduct->getPriceAfterDiscount(),
|
||||
'taxvalue' => $shopProduct->getTaxValue(),
|
||||
'taxpercent' => $shopProduct->getTaxPercent(),
|
||||
'total' => $shopProduct->getTotalPrice()
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -78,7 +82,7 @@ class PaymentController extends Controller
|
|||
"purchase_units" => [
|
||||
[
|
||||
"reference_id" => uniqid(),
|
||||
"description" => $shopProduct->description,
|
||||
"description" => $shopProduct->display . (PartnerDiscount::getDiscount()?(" (" . __('Discount') . " " . PartnerDiscount::getDiscount() . '%)'):""),
|
||||
"amount" => [
|
||||
"value" => $shopProduct->getTotalPrice(),
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
|
@ -86,7 +90,7 @@ class PaymentController extends Controller
|
|||
'item_total' =>
|
||||
[
|
||||
'currency_code' => strtoupper($shopProduct->currency_code),
|
||||
'value' => $shopProduct->price,
|
||||
'value' => $shopProduct->getPriceAfterDiscount(),
|
||||
],
|
||||
'tax_total' =>
|
||||
[
|
||||
|
@ -180,15 +184,31 @@ class PaymentController extends Controller
|
|||
$user->increment('server_limit', $shopProduct->quantity);
|
||||
}
|
||||
|
||||
//give referral commission always
|
||||
if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "true"){
|
||||
if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity*(PartnerDiscount::getCommission($ref_user->id))/100,0,"","");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
activity()
|
||||
->performedOn($user)
|
||||
->causedBy($ref_user)
|
||||
->log('gained '. $increment.' '.config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME").' for commission-referral of '.$user->name.' (ID:'.$user->id.')');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//update role give Referral-reward
|
||||
if ($user->role == 'member') {
|
||||
$user->update(['role' => 'client']);
|
||||
|
||||
if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits"){
|
||||
//give referral commission only on first purchase
|
||||
if((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type=="Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "false"){
|
||||
if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()){
|
||||
$ref_user = User::findOrFail($ref_user->referral_id);
|
||||
$increment = number_format($shopProduct->quantity/100*config("SETTINGS::REFERRAL:PERCENTAGE"),0,"","");
|
||||
$increment = number_format($shopProduct->quantity*(PartnerDiscount::getCommission($ref_user->id))/100,0,"","");
|
||||
$ref_user->increment('credits', $increment);
|
||||
|
||||
//LOGS REFERRALS IN THE ACTIVITY LOG
|
||||
|
@ -210,7 +230,7 @@ class PaymentController extends Controller
|
|||
'type' => $shopProduct->type,
|
||||
'status' => 'paid',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price,
|
||||
'price' => $shopProduct->price - ($shopProduct->price*PartnerDiscount::getDiscount()/100),
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
|
@ -273,10 +293,10 @@ class PaymentController extends Controller
|
|||
'price_data' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'product_data' => [
|
||||
'name' => $shopProduct->display,
|
||||
'name' => $shopProduct->display . (PartnerDiscount::getDiscount()?(" (" . __('Discount') . " " . PartnerDiscount::getDiscount() . '%)'):""),
|
||||
'description' => $shopProduct->description,
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->price * 100, 2),
|
||||
'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
|
||||
],
|
||||
'quantity' => 1,
|
||||
],
|
||||
|
@ -284,7 +304,7 @@ class PaymentController extends Controller
|
|||
'price_data' => [
|
||||
'currency' => $shopProduct->currency_code,
|
||||
'product_data' => [
|
||||
'name' => 'Product Tax',
|
||||
'name' => __('Tax'),
|
||||
'description' => $shopProduct->getTaxPercent() . "%",
|
||||
],
|
||||
'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
|
||||
|
@ -373,7 +393,7 @@ class PaymentController extends Controller
|
|||
'type' => $shopProduct->type,
|
||||
'status' => 'paid',
|
||||
'amount' => $shopProduct->quantity,
|
||||
'price' => $shopProduct->price,
|
||||
'price' => $shopProduct->price - ($shopProduct->price*PartnerDiscount::getDiscount()/100),
|
||||
'tax_value' => $shopProduct->getTaxValue(),
|
||||
'total_price' => $shopProduct->getTotalPrice(),
|
||||
'tax_percent' => $shopProduct->getTaxPercent(),
|
||||
|
@ -611,7 +631,7 @@ class PaymentController extends Controller
|
|||
->name(__("Invoice"))
|
||||
->buyer($customer)
|
||||
->seller($seller)
|
||||
->discountByPercent(0)
|
||||
->discountByPercent(PartnerDiscount::getDiscount())
|
||||
->taxRate(floatval($shopProduct->getTaxPercent()))
|
||||
->shipping(0)
|
||||
->addItem($item)
|
||||
|
@ -654,7 +674,8 @@ class PaymentController extends Controller
|
|||
|
||||
return datatables($query)
|
||||
->editColumn('user', function (Payment $payment) {
|
||||
return $payment->user->name;
|
||||
return
|
||||
($payment->user)?'<a href="'.route('admin.users.show', $payment->user->id).'">'.$payment->user->name.'</a>':__('Unknown user');
|
||||
})
|
||||
->editColumn('price', function (Payment $payment) {
|
||||
return $payment->formatToCurrency($payment->price);
|
||||
|
@ -675,7 +696,7 @@ class PaymentController extends Controller
|
|||
->addColumn('actions', function (Payment $payment) {
|
||||
return '<a data-content="' . __("Download") . '" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.invoices.downloadSingleInvoice', "id=" . $payment->payment_id) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-file-download"></i></a>';
|
||||
})
|
||||
->rawColumns(['actions'])
|
||||
->rawColumns(['actions', 'user'])
|
||||
->make(true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -288,7 +288,8 @@ class UserController extends Controller
|
|||
return $user->discordUser ? $user->discordUser->id : '';
|
||||
})
|
||||
->addColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
return ['display' => $user->last_seen ? $user->last_seen->diffForHumans() : '',
|
||||
'raw' => $user->last_seen ? strtotime($user->last_seen) : ''];
|
||||
})
|
||||
->addColumn('actions', function (User $user) {
|
||||
$suspendColor = $user->isSuspended() ? "btn-success" : "btn-warning";
|
||||
|
@ -331,9 +332,9 @@ class UserController extends Controller
|
|||
->editColumn('name', function (User $user) {
|
||||
return '<a class="text-info" target="_blank" href="' . config("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/admin/users/view/' . $user->pterodactyl_id . '">' . strip_tags($user->name) . '</a>';
|
||||
})
|
||||
->orderColumn('last_seen', function ($query) {
|
||||
/*->orderColumn('last_seen', function ($query) {
|
||||
$query->orderBy('last_seen', "desc");
|
||||
})
|
||||
})*/
|
||||
->rawColumns(['avatar', 'name', 'credits', 'role', 'usage', 'referrals', 'actions', 'last_seen'])
|
||||
->make(true);
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\UsefulLink;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
@ -105,7 +107,10 @@ class HomeController extends Controller
|
|||
'useful_links' => UsefulLink::all()->sortBy('id'),
|
||||
'bg' => $bg,
|
||||
'boxText' => $boxText,
|
||||
'unit' => $unit
|
||||
'unit' => $unit,
|
||||
'numberOfReferrals' => DB::table('user_referrals')->where("referral_id","=",Auth::user()->id)->count(),
|
||||
'partnerDiscount' => PartnerDiscount::where('user_id', Auth::user()->id)->first(),
|
||||
'myDiscount' => PartnerDiscount::getDiscount()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
206
app/Http/Controllers/PartnerController.php
Normal file
206
app/Http/Controllers/PartnerController.php
Normal file
|
@ -0,0 +1,206 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\PartnerDiscount;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PartnerController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('admin.partners.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('admin.partners.create', [
|
||||
'partners' =>PartnerDiscount::get(),
|
||||
'users' => User::orderBy('name')->get()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'user_id' => 'required|integer|min:0',
|
||||
'partner_discount' => 'required|integer|max:100|min:0',
|
||||
'registered_user_discount' => 'required|integer|max:100|min:0'
|
||||
]);
|
||||
|
||||
PartnerDiscount::create($request->all());
|
||||
|
||||
return redirect()->route('admin.partners.index')->with('success', __('partner has been created!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Voucher $voucher
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Voucher $voucher)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param Voucher $voucher
|
||||
* @return Application|Factory|View
|
||||
*/
|
||||
public function edit(PartnerDiscount $partner)
|
||||
{
|
||||
return view('admin.partners.edit', [
|
||||
'partners' =>PartnerDiscount::get(),
|
||||
'partner' => $partner,
|
||||
'users' => User::orderBy('name')->get()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Voucher $voucher
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, PartnerDiscount $partner)
|
||||
{
|
||||
//dd($request);
|
||||
$request->validate([
|
||||
'user_id' => 'required|integer|min:0',
|
||||
'partner_discount' => 'required|integer|max:100|min:0',
|
||||
'registered_user_discount' => 'required|integer|max:100|min:0'
|
||||
]);
|
||||
|
||||
$partner->update($request->all());
|
||||
|
||||
return redirect()->route('admin.partners.index')->with('success', __('partner has been updated!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param Voucher $voucher
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(PartnerDiscount $partner)
|
||||
{
|
||||
$partner->delete();
|
||||
return redirect()->back()->with('success', __('partner has been removed!'));
|
||||
}
|
||||
|
||||
public function users(Voucher $voucher)
|
||||
{
|
||||
return view('admin.vouchers.users', [
|
||||
'voucher' => $voucher
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function redeem(Request $request)
|
||||
{
|
||||
#general validations
|
||||
$request->validate([
|
||||
'code' => 'required|exists:vouchers,code'
|
||||
]);
|
||||
|
||||
#get voucher by code
|
||||
$voucher = Voucher::where('code', '=', $request->input('code'))->firstOrFail();
|
||||
|
||||
#extra validations
|
||||
if ($voucher->getStatus() == 'USES_LIMIT_REACHED') throw ValidationException::withMessages([
|
||||
'code' => __('This voucher has reached the maximum amount of uses')
|
||||
]);
|
||||
|
||||
if ($voucher->getStatus() == 'EXPIRED') throw ValidationException::withMessages([
|
||||
'code' => __('This voucher has expired')
|
||||
]);
|
||||
|
||||
if (!$request->user()->vouchers()->where('id', '=', $voucher->id)->get()->isEmpty()) throw ValidationException::withMessages([
|
||||
'code' => __('You already redeemed this voucher code')
|
||||
]);
|
||||
|
||||
if ($request->user()->credits + $voucher->credits >= 99999999) throw ValidationException::withMessages([
|
||||
'code' => "You can't redeem this voucher because you would exceed the limit of " . CREDITS_DISPLAY_NAME
|
||||
]);
|
||||
|
||||
#redeem voucher
|
||||
$voucher->redeem($request->user());
|
||||
|
||||
event(new UserUpdateCreditsEvent($request->user()));
|
||||
|
||||
return response()->json([
|
||||
'success' => "{$voucher->credits} " . CREDITS_DISPLAY_NAME ." ". __("have been added to your balance!")
|
||||
]);
|
||||
}
|
||||
|
||||
public function usersDataTable(Voucher $voucher)
|
||||
{
|
||||
$users = $voucher->users();
|
||||
|
||||
return datatables($users)
|
||||
->editColumn('name', function (User $user) {
|
||||
return '<a class="text-info" target="_blank" href="' . route('admin.users.show', $user->id) . '">' . $user->name . '</a>';
|
||||
})
|
||||
->addColumn('credits', function (User $user) {
|
||||
return '<i class="fas fa-coins mr-2"></i> ' . $user->credits();
|
||||
})
|
||||
->addColumn('last_seen', function (User $user) {
|
||||
return $user->last_seen ? $user->last_seen->diffForHumans() : '';
|
||||
})
|
||||
->rawColumns(['name', 'credits', 'last_seen'])
|
||||
->make();
|
||||
}
|
||||
public function dataTable()
|
||||
{
|
||||
$query = PartnerDiscount::query();
|
||||
|
||||
return datatables($query)
|
||||
->addColumn('actions', function (PartnerDiscount $partner) {
|
||||
return '
|
||||
<a data-content="'.__("Edit").'" data-toggle="popover" data-trigger="hover" data-placement="top" href="' . route('admin.partners.edit', $partner->id) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
|
||||
<form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.partners.destroy', $partner->id) . '">
|
||||
' . csrf_field() . '
|
||||
' . method_field("DELETE") . '
|
||||
<button data-content="'.__("Delete").'" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
';
|
||||
})
|
||||
->addColumn('user', function (PartnerDiscount $partner) {
|
||||
return ($user=User::where('id', $partner->user_id)->first())?'<a href="'.route('admin.users.show', $partner->user_id).'">'.$user->name.'</a>':__('Unknown user');
|
||||
})
|
||||
->editColumn('created_at', function (PartnerDiscount $partner) {
|
||||
return $partner->created_at ? $partner->created_at->diffForHumans() : '';
|
||||
})
|
||||
->editColumn('partner_discount', function (PartnerDiscount $partner) {
|
||||
return $partner->partner_discount ? $partner->partner_discount . "%" : "0%";
|
||||
})
|
||||
->editColumn('registered_user_discount', function (PartnerDiscount $partner) {
|
||||
return $partner->registered_user_discount ? $partner->registered_user_discount . "%" : "0%";
|
||||
})
|
||||
->editColumn('referral_system_commission', function (PartnerDiscount $partner) {
|
||||
return $partner->referral_system_commission>=0 ? $partner->referral_system_commission . "%" : __('Default') . " (" . config("SETTINGS::REFERRAL:PERCENTAGE") . "%)";
|
||||
})
|
||||
->rawColumns(['user', 'actions'])
|
||||
->make();
|
||||
}
|
||||
}
|
41
app/Models/PartnerDiscount.php
Normal file
41
app/Models/PartnerDiscount.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class PartnerDiscount extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'partner_discount',
|
||||
'registered_user_discount',
|
||||
'referral_system_commission'
|
||||
];
|
||||
|
||||
public static function getDiscount()
|
||||
{
|
||||
if($partnerDiscount = PartnerDiscount::where('user_id', Auth::user()->id)->first()){
|
||||
return $partnerDiscount->partner_discount;
|
||||
}
|
||||
else if($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', Auth::user()->id)->first()){
|
||||
if($partnerDiscount = PartnerDiscount::where('user_id', $ref_user->referral_id)->first()){
|
||||
return $partnerDiscount->registered_user_discount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
public static function getCommission($user_id)
|
||||
{
|
||||
if($partnerDiscount = PartnerDiscount::where('user_id', $user_id)->first()){
|
||||
if($partnerDiscount->referral_system_commission>=0) return $partnerDiscount->referral_system_commission>=0;
|
||||
}
|
||||
return config("SETTINGS::REFERRAL:PERCENTAGE");
|
||||
}
|
||||
}
|
|
@ -63,6 +63,11 @@ class ShopProduct extends Model
|
|||
return $tax < 0 ? 0 : $tax;
|
||||
}
|
||||
|
||||
public function getPriceAfterDiscount()
|
||||
{
|
||||
return number_format($this->price - ($this->price * PartnerDiscount::getDiscount() / 100), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description Returns the tax as Number
|
||||
*
|
||||
|
@ -70,7 +75,7 @@ class ShopProduct extends Model
|
|||
*/
|
||||
public function getTaxValue()
|
||||
{
|
||||
return number_format($this->price * $this->getTaxPercent() / 100, 2);
|
||||
return number_format($this->getPriceAfterDiscount() * $this->getTaxPercent() / 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -80,6 +85,6 @@ class ShopProduct extends Model
|
|||
*/
|
||||
public function getTotalPrice()
|
||||
{
|
||||
return number_format($this->price + $this->getTaxValue(), 2);
|
||||
return number_format($this->getPriceAfterDiscount() + $this->getTaxValue(), 2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePartnerDiscountsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('partner_discounts', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id');
|
||||
$table->integer('partner_discount');
|
||||
$table->integer('registered_user_discount');
|
||||
$table->integer('referral_system_commission');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('partner_discounts');
|
||||
}
|
||||
}
|
|
@ -479,6 +479,13 @@ class SettingsSeeder extends Seeder
|
|||
'type' => 'string',
|
||||
'description' => 'Enable or disable the referral system'
|
||||
]);
|
||||
Settings::firstOrCreate([
|
||||
'key' => 'SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION',
|
||||
], [
|
||||
'value' =>"false",
|
||||
'type' => 'string',
|
||||
'description' => 'Whether referrals get percentage commission only on first purchase or on every purchase'
|
||||
]);
|
||||
Settings::firstOrCreate([
|
||||
'key' => 'SETTINGS::REFERRAL::REWARD',
|
||||
], [
|
||||
|
|
|
@ -254,6 +254,7 @@
|
|||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<hr style="width: 100%; height:2px; border-width:0; background-color:#6c757d; margin-top: 0px;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
|
@ -266,32 +267,36 @@
|
|||
</div>
|
||||
<div class="card-body py-1">
|
||||
<div class="row">
|
||||
<div class="col-md-6" style="border-right:1px solid #6c757d">
|
||||
<span style="margin:auto; display:table; font-size: 18px; font-weight:700">{{__('Last month')}}:
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('Payments in this time window') }}:<br>{{$counters['payments']['lastMonth']->timeStart}} - {{$counters['payments']['lastMonth']->timeEnd}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><b>{{__('Currency')}}</b></th>
|
||||
<th>{{__('Number of payments')}}</th>
|
||||
<th>{{__('Total income')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($counters['payments']['lastMonth'] as $currency => $income)
|
||||
<tr>
|
||||
<td>{{$currency}}</td>
|
||||
<td>{{$income->count}}</td>
|
||||
<td>{{$income->total}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="width: 100%; height:1px; border-width:0; background-color:#6c757d; margin-top: -16px">
|
||||
</div><div class="col-md-6">
|
||||
@if($counters['payments']['lastMonth']->count())
|
||||
<div class="col-md-6" style="border-right:1px solid #6c757d">
|
||||
<span style="margin:auto; display:table; font-size: 18px; font-weight:700">{{__('Last month')}}:
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('Payments in this time window') }}:<br>{{$counters['payments']['lastMonth']->timeStart}} - {{$counters['payments']['lastMonth']->timeEnd}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><b>{{__('Currency')}}</b></th>
|
||||
<th>{{__('Number of payments')}}</th>
|
||||
<th>{{__('Total amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($counters['payments']['lastMonth'] as $currency => $income)
|
||||
<tr>
|
||||
<td>{{$currency}}</td>
|
||||
<td>{{$income->count}}</td>
|
||||
<td>{{$income->total}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="width: 100%; height:1px; border-width:0; background-color:#6c757d; margin-top: -16px">
|
||||
</div>
|
||||
@endif
|
||||
@if($counters['payments']['lastMonth']->count()) <div class="col-md-6">
|
||||
@else <div class="col-md-12"> @endif
|
||||
<span style="margin:auto; display:table; font-size: 18px; font-weight:700">{{__('This month')}}:
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('Payments in this time window') }}:<br>{{$counters['payments']['thisMonth']->timeStart}} - {{$counters['payments']['thisMonth']->timeEnd}}"
|
||||
|
@ -302,7 +307,7 @@
|
|||
<tr>
|
||||
<th><b>{{__('Currency')}}</b></th>
|
||||
<th>{{__('Number of payments')}}</th>
|
||||
<th>{{__('Total income')}}</th>
|
||||
<th>{{__('Total amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
@ -321,6 +326,75 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="card-title ">
|
||||
<span><i class="fas fa-hand-holding-usd mr-2"></i>{{__('Tax overview')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body py-1">
|
||||
@if($counters['taxPayments']['lastYear']->count())
|
||||
<span style="margin:auto; display:table; font-size: 18px; font-weight:700">{{__('Last year')}}:
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('Payments in this time window') }}:<br>{{$counters['taxPayments']['lastYear']->timeStart}} - {{$counters['taxPayments']['lastYear']->timeEnd}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><b>{{__('Currency')}}</b></th>
|
||||
<th>{{__('Number of payments')}}</th>
|
||||
<th><b>{{__('Base amount')}}</b></th>
|
||||
<th><b>{{__('Total taxes')}}</b></th>
|
||||
<th>{{__('Total amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($counters['taxPayments']['lastYear'] as $currency => $income)
|
||||
<tr>
|
||||
<td>{{$currency}}</td>
|
||||
<td>{{$income->count}}</td>
|
||||
<td>{{$income->price}}</td>
|
||||
<td>{{$income->taxes}}</td>
|
||||
<td>{{$income->total}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="width: 100%; height:2px; border-width:0; background-color:#6c757d; margin-top: 0px; margin-bottom: 8px">
|
||||
@endif
|
||||
<span style="margin:auto; display:table; font-size: 18px; font-weight:700">{{__('This year')}}:
|
||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||
data-content="{{ __('Payments in this time window') }}:<br>{{$counters['taxPayments']['thisYear']->timeStart}} - {{$counters['taxPayments']['thisYear']->timeEnd}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</span>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><b>{{__('Currency')}}</b></th>
|
||||
<th>{{__('Number of payments')}}</th>
|
||||
<th><b>{{__('Base amount')}}</b></th>
|
||||
<th><b>{{__('Total taxes')}}</b></th>
|
||||
<th>{{__('Total amount')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($counters['taxPayments']['thisYear'] as $currency => $income)
|
||||
<tr>
|
||||
<td>{{$currency}}</td>
|
||||
<td>{{$income->count}}</td>
|
||||
<td>{{$income->price}}</td>
|
||||
<td>{{$income->taxes}}</td>
|
||||
<td>{{$income->total}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="width: 100%; height:2px; border-width:0; background-color:#6c757d; margin-top: 0px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
139
resources/views/admin/partners/create.blade.php
Normal file
139
resources/views/admin/partners/create.blade.php
Normal file
|
@ -0,0 +1,139 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('content')
|
||||
<!-- CONTENT HEADER -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>{{__('Vouchers')}}</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{route('admin.partners.index')}}">{{__('Vouchers')}}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.partners.create')}}">{{__('Create')}}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-handshake mr-2"></i>{{__('Partner details')}}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{route('admin.partners.store')}}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="form-group">
|
||||
<label for="user_id">{{__('User')}}</label>
|
||||
<select id="user_id" style="width:100%"
|
||||
class="custom-select @error('user') is-invalid @enderror" name="user_id" autocomplete="off">
|
||||
@foreach($users as $user)
|
||||
<option @if($partners->contains('user_id' , $user->id)) disabled @endif
|
||||
value="{{$user->id}}">{{$user->name}} ({{$user->email}})</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('user')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="partner_discount">{{__('Partner discount')}}</label>
|
||||
<input value="{{old('partner_discount')}}" placeholder="{{__('Discount in percent')}}" id="partner_discount" name="partner_discount"
|
||||
type="number" step="any" min="0" max="100"
|
||||
class="form-control @error('partner_discount') is-invalid @enderror">
|
||||
@error('partner_discount')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="registered_user_discount">{{__('Registered user discount')}}</label>
|
||||
<div class="input-group">
|
||||
<input value="{{old('registered_user_discount')}}" placeholder="Discount in percent" id="registered_user_discount" name="registered_user_discount"
|
||||
type="number" class="form-control @error('registered_user_discount') is-invalid @enderror"
|
||||
required="required">
|
||||
</div>
|
||||
@error('registered_user_discount')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="referral_system_commission">{{__('Referral system commission')}}
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{__('Override value for referral system commission. You can set it to -1 to get the default commission from settings.')}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</label>
|
||||
<input value="{{old('referral_system_commission')}}" placeholder="{{__('Commission in percent')}}" id="referral_system_commission" name="referral_system_commission"
|
||||
type="number" step="any" min="-1" max="100"
|
||||
class="form-control @error('referral_system_commission') is-invalid @enderror">
|
||||
@error('referral_system_commission')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group text-right">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{__('Submit')}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<i class="fas"></i>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
$('#expires_at').datetimepicker({
|
||||
format: 'DD-MM-yyyy HH:mm:ss',
|
||||
icons: {
|
||||
time: 'far fa-clock',
|
||||
date: 'far fa-calendar',
|
||||
up: 'fas fa-arrow-up',
|
||||
down: 'fas fa-arrow-down',
|
||||
previous: 'fas fa-chevron-left',
|
||||
next: 'fas fa-chevron-right',
|
||||
today: 'fas fa-calendar-check',
|
||||
clear: 'far fa-trash-alt',
|
||||
close: 'far fa-times-circle'
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
158
resources/views/admin/partners/edit.blade.php
Normal file
158
resources/views/admin/partners/edit.blade.php
Normal file
|
@ -0,0 +1,158 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('content')
|
||||
<!-- CONTENT HEADER -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>{{__('Partners')}}</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{route('admin.partners.index')}}">{{__('Partners')}}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.partners.edit' , $partner->id)}}">{{__('Edit')}}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title">
|
||||
<i class="fas fa-handshake mr-2"></i>{{__('Partner details')}}
|
||||
</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{{route('admin.partners.update' , $partner->id)}}" method="POST">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
|
||||
<div class="form-group">
|
||||
<label for="user_id">{{__('User')}}</label>
|
||||
<select id="user_id" style="width:100%"
|
||||
class="custom-select @error('user') is-invalid @enderror" name="user_id" autocomplete="off">
|
||||
@foreach($users as $user)
|
||||
<option @if($partners->contains('user_id' , $user->id)&&$partner->user_id!=$user->id) disabled @endif
|
||||
@if($partner->user_id==$user->id) selected @endif
|
||||
value="{{$user->id}}">{{$user->name}} ({{$user->email}})</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('user')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="partner_discount">{{__('Partner discount')}}</label>
|
||||
<input value="{{$partner->partner_discount}}" placeholder="{{__('Discount in percent')}}" id="partner_discount" name="partner_discount"
|
||||
type="number" step="any" min="0" max="100"
|
||||
class="form-control @error('partner_discount') is-invalid @enderror">
|
||||
@error('partner_discount')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="registered_user_discount">{{__('Registered user discount')}}</label>
|
||||
<div class="input-group">
|
||||
<input value="{{$partner->registered_user_discount}}" placeholder="Discount in percent" id="registered_user_discount" name="registered_user_discount"
|
||||
type="number" class="form-control @error('registered_user_discount') is-invalid @enderror"
|
||||
required="required">
|
||||
</div>
|
||||
@error('registered_user_discount')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="referral_system_commission">{{__('Referral system commission')}}
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{__('Override value for referral system commission. You can set it to -1 to get the default commission from settings.')}}"
|
||||
class="fas fa-info-circle"></i>
|
||||
</label>
|
||||
<input value="{{$partner->referral_system_commission}}" placeholder="{{__('Commission in percent')}}" id="referral_system_commission" name="referral_system_commission"
|
||||
type="number" step="any" min="-1" max="100"
|
||||
class="form-control @error('referral_system_commission') is-invalid @enderror">
|
||||
@error('referral_system_commission')
|
||||
<div class="text-danger">
|
||||
{{$message}}
|
||||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group text-right">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{{__('Submit')}}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', (event) => {
|
||||
$('#expires_at').datetimepicker({
|
||||
format: 'DD-MM-yyyy HH:mm:ss',
|
||||
icons: {
|
||||
time: 'far fa-clock',
|
||||
date: 'far fa-calendar',
|
||||
up: 'fas fa-arrow-up',
|
||||
down: 'fas fa-arrow-down',
|
||||
previous: 'fas fa-chevron-left',
|
||||
next: 'fas fa-chevron-right',
|
||||
today: 'fas fa-calendar-check',
|
||||
clear: 'far fa-trash-alt',
|
||||
close: 'far fa-times-circle'
|
||||
}
|
||||
});
|
||||
})
|
||||
function setMaxUses() {
|
||||
let element = document.getElementById('uses')
|
||||
element.value = element.max;
|
||||
console.log(element.max)
|
||||
}
|
||||
function setRandomCode() {
|
||||
let element = document.getElementById('code')
|
||||
element.value = getRandomCode(36)
|
||||
}
|
||||
function getRandomCode(length) {
|
||||
let result = '';
|
||||
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-';
|
||||
let charactersLength = characters.length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() *
|
||||
charactersLength));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
94
resources/views/admin/partners/index.blade.php
Normal file
94
resources/views/admin/partners/index.blade.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
@extends('layouts.main')
|
||||
|
||||
@section('content')
|
||||
<!-- CONTENT HEADER -->
|
||||
<section class="content-header">
|
||||
<div class="container-fluid">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-6">
|
||||
<h1>{{__('Partners')}}</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<ol class="breadcrumb float-sm-right">
|
||||
<li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.partners.index')}}">{{__('Partners')}}</a></li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT HEADER -->
|
||||
|
||||
<!-- MAIN CONTENT -->
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
|
||||
<div class="card">
|
||||
|
||||
<div class="card-header">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h5 class="card-title"><i class="fas fa-handshake mr-2"></i>{{__('Partners')}}</h5>
|
||||
<a href="{{route('admin.partners.create')}}" class="btn btn-sm btn-primary"><i
|
||||
class="fas fa-plus mr-1"></i>{{__('Create new')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body table-responsive">
|
||||
|
||||
<table id="datatable" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{__('User')}}</th>
|
||||
<th>{{__('Partner discount')}}</th>
|
||||
<th>{{__('Registered user discount')}}</th>
|
||||
<th>{{__('Referral system commission')}}</th>
|
||||
<th>{{__('Created')}}</th>
|
||||
<th>{{__('Actions')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- END CUSTOM CONTENT -->
|
||||
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
function submitResult() {
|
||||
return confirm("{{__('Are you sure you wish to delete?')}}") !== false;
|
||||
}
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
$('#datatable').DataTable({
|
||||
language: {
|
||||
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("SETTINGS::LOCALE:DATATABLES")}}.json'
|
||||
},
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
stateSave: true,
|
||||
ajax: "{{route('admin.partners.datatable')}}",
|
||||
columns: [
|
||||
{data: 'user'},
|
||||
{data: 'partner_discount'},
|
||||
{data: 'registered_user_discount'},
|
||||
{data: 'referral_system_commission'},
|
||||
{data: 'created_at'},
|
||||
{data: 'actions', sortable: false}
|
||||
],
|
||||
fnDrawCallback: function( oSettings ) {
|
||||
$('[data-toggle="popover"]').popover();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
@endsection
|
|
@ -39,6 +39,7 @@
|
|||
<tr>
|
||||
<th>{{ __('ID') }}</th>
|
||||
<th>{{ __('Type') }}</th>
|
||||
<th>{{ __('User') }}</th>
|
||||
<th>{{ __('Amount') }}</th>
|
||||
<th>{{ __('Product Price') }}</th>
|
||||
<th>{{ __('Tax Value') }}</th>
|
||||
|
@ -77,6 +78,7 @@
|
|||
columns: [
|
||||
{data: 'id',name: 'payments.id'},
|
||||
{data: 'type'},
|
||||
{data: 'user', sortable: false},
|
||||
{data: 'amount'},
|
||||
{data: 'price'},
|
||||
{data: 'tax_value'},
|
||||
|
|
|
@ -222,6 +222,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="custom-control mb-3 p-0">
|
||||
<div class="col m-0 p-0 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<input value="true" id="always_give_commission" name="always_give_commission"
|
||||
{{ config('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION') == 'true' ? 'checked' : '' }}
|
||||
type="checkbox">
|
||||
<label for="always_give_commission">{{ __('Always give commission') }}:
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{ __('Should users recieve the commission only for the first payment, or for every payment?') }}" class="fas fa-info-circle"></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="custom-control mb-3 p-0">
|
||||
<label for="referral_mode">{{ __('Mode') }}:
|
||||
<i data-toggle="popover" data-trigger="hover"
|
||||
|
|
|
@ -90,10 +90,10 @@
|
|||
{data: 'role'},
|
||||
{data: 'email', name: 'users.email'},
|
||||
{data: 'credits' , name : 'users.credits'},
|
||||
{data: 'servers' , sortable : false},
|
||||
{data: 'servers'},
|
||||
{data: 'referrals'},
|
||||
{data: 'verified' , sortable : false},
|
||||
{data: 'last_seen'},
|
||||
{data: 'last_seen', type: 'num', render: {_: 'display', sort: 'raw'}},
|
||||
{data: 'actions' , sortable : false},
|
||||
],
|
||||
fnDrawCallback: function( oSettings ) {
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<li class="breadcrumb-item"><a href="{{route('admin.vouchers.index')}}">{{__('Vouchers')}}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.products.create')}}">{{__('Create')}}</a>
|
||||
href="{{route('admin.vouchers.create')}}">{{__('Create')}}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<li class="breadcrumb-item"><a href="{{route('admin.vouchers.index')}}">{{__('Vouchers')}}</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item"><a class="text-muted"
|
||||
href="{{route('admin.products.edit' , $voucher->id)}}">{{__('Edit')}}</a>
|
||||
href="{{route('admin.vouchers.edit' , $voucher->id)}}">{{__('Edit')}}</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
|
|
@ -140,8 +140,7 @@
|
|||
<!-- /.card-header -->
|
||||
<div class="card-body py-0 pb-2">
|
||||
<ul class="list-group list-group-flush">
|
||||
@foreach (Auth::user()->actions()->take(8)->orderBy('created_at', 'desc')->get()
|
||||
as $log)
|
||||
@foreach (Auth::user()->actions()->take(8)->orderBy('created_at', 'desc')->get() as $log)
|
||||
<li class="list-group-item d-flex justify-content-between text-muted">
|
||||
<span>
|
||||
@if(str_starts_with($log->description,"created"))
|
||||
|
@ -168,6 +167,80 @@
|
|||
<!-- /.card-body -->
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
@if((config('SETTINGS::REFERRAL::ENABLED') ==true))<!--PartnerDiscount::getDiscount()--->
|
||||
<div class="card card-default">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">
|
||||
<i class="fas fa-handshake mr-2"></i>
|
||||
{{ __('Partner program') }}
|
||||
</h3>
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body py-0 pb-2">
|
||||
@if((config('SETTINGS::REFERRAL::ALLOWED') == "client" && Auth::user()->role != "member") || config('SETTINGS::REFERRAL::ALLOWED') == "everyone")
|
||||
<div class="row">
|
||||
<div class="mt-3 col-md-8">
|
||||
<span class="badge badge-success" style="font-size: 14px">
|
||||
<i class="fa fa-user-check mr-2"></i>
|
||||
{{__("Your referral URL")}}:
|
||||
<span onmouseover="hoverIn()" onmouseout="hoverOut()" onclick="onClickCopy()" id="RefLink" style="cursor: pointer;">
|
||||
{{__('Click to copy')}}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="mt-3 col-md-4">
|
||||
<span class="badge badge-info" style="font-size: 14px">{{__("Number of referred users:")}} {{$numberOfReferrals}}</span>
|
||||
</div>
|
||||
</div>
|
||||
@if($partnerDiscount)
|
||||
<hr style="width: 100%; height:1px; border-width:0; background-color:#6c757d; margin-bottom: 0px">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{__('Your discount')}}</th>
|
||||
<th>{{__('Discount for your new users')}}</th>
|
||||
<th>{{__('Reward per registered user')}}</th>
|
||||
<th>{{__('New user payment commision')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{$partnerDiscount->partner_discount}}%</td>
|
||||
<td>{{$partnerDiscount->registered_user_discount}}%</td>
|
||||
<td>{{config('SETTINGS::REFERRAL::REWARD')}} {{config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME')}}</td>
|
||||
<td>{{($partnerDiscount->referral_system_commission==-1)?config('SETTINGS::REFERRAL:PERCENTAGE'):($partnerDiscount->referral_system_commission)}}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="width: 100%; height:1px; border-width:0; background-color:#6c757d; margin-top: 0px">
|
||||
@else
|
||||
<hr style="width: 100%; height:1px; border-width:0; background-color:#6c757d; margin-bottom: 0px">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{__('Reward per registered user')}}</th>
|
||||
<th>{{__('New user payment commision')}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{config('SETTINGS::REFERRAL::REWARD')}} {{config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME')}}</td>
|
||||
<td>{{config('SETTINGS::REFERRAL:PERCENTAGE')}}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<hr style="width: 100%; height:1px; border-width:0; background-color:#6c757d; margin-top: 0px">
|
||||
@endif
|
||||
@else
|
||||
<span class="badge badge-warning"><i
|
||||
class="fa fa-user-check mr-2"></i>
|
||||
{{__("Make a purchase to reveal your referral-URL")}}</span>
|
||||
@endif
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
</div>
|
||||
@endif
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
|
||||
|
@ -176,5 +249,41 @@
|
|||
</div>
|
||||
</section>
|
||||
<!-- END CONTENT -->
|
||||
|
||||
<script>
|
||||
var originalText = document.getElementById('RefLink').innerText;
|
||||
var link = "<?php echo ((route("register")) . '?ref=' . (Auth::user()->referral_code));?>";
|
||||
var timeoutID;
|
||||
function hoverIn() {
|
||||
document.getElementById('RefLink').innerText = link;
|
||||
timeoutID = setTimeout(function() {
|
||||
document.getElementById('RefLink').innerText = originalText;
|
||||
}, 2000);
|
||||
}
|
||||
function hoverOut() {
|
||||
document.getElementById('RefLink').innerText = originalText;
|
||||
clearTimeout(timeoutID);
|
||||
}
|
||||
function onClickCopy() {
|
||||
if(navigator.clipboard) {
|
||||
navigator.clipboard.writeText(link).then(() => {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: '{{ __("URL copied to clipboard")}}',
|
||||
position: 'top-middle',
|
||||
showConfirmButton: false,
|
||||
background: '#343a40',
|
||||
toast: false,
|
||||
timer: 1000,
|
||||
timerProgressBar: true,
|
||||
didOpen: (toast) => {
|
||||
toast.addEventListener('mouseenter', Swal.stopTimer)
|
||||
toast.addEventListener('mouseleave', Swal.resumeTimer)
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
console.log('Browser Not compatible')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
@ -330,6 +330,14 @@
|
|||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('admin.partners.index') }}"
|
||||
class="nav-link @if (Request::routeIs('admin.partners.*')) active @endif">
|
||||
<i class="nav-icon fas fa-handshake"></i>
|
||||
<p>{{ __('Partners') }}</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{-- <li class="nav-header">Pterodactyl</li> --}}
|
||||
|
||||
{{-- <li class="nav-item"> --}}
|
||||
|
|
|
@ -107,18 +107,20 @@
|
|||
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
@if($discountpercent&&$discountvalue)
|
||||
<tr>
|
||||
<th>{{ __('Discount') }} ({{ $discountpercent }}%):</th>
|
||||
<td>{{$product->formatToCurrency($discountvalue)}}</td>
|
||||
</tr>
|
||||
@endif
|
||||
<tr>
|
||||
<th style="width:50%">{{ __('Subtotal') }}:</th>
|
||||
<td>{{ $product->formatToCurrency($product->price) }}</td>
|
||||
<td>{{ $product->formatToCurrency($discountedprice) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ __('Tax') }} ({{ $taxpercent }}%)</th>
|
||||
<th>{{ __('Tax') }} ({{ $taxpercent }}%):</th>
|
||||
<td>{{ $product->formatToCurrency($taxvalue) }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ __('Quantity') }}:</th>
|
||||
<td>1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ __('Total') }}:</th>
|
||||
<td>{{ $product->formatToCurrency($total) }}</td>
|
||||
|
@ -154,7 +156,6 @@
|
|||
//loading
|
||||
paymentMethod: '',
|
||||
paymentRoute: '',
|
||||
|
||||
setPaymentRoute(provider) {
|
||||
switch (provider) {
|
||||
case 'paypal':
|
||||
|
@ -167,12 +168,9 @@
|
|||
this.paymentRoute = '{{ route('payment.PaypalPay', $product->id) }}';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@endsection
|
||||
@endsection
|
|
@ -30,6 +30,7 @@ use Illuminate\Support\Facades\Route;
|
|||
use App\Classes\Settings\Language;
|
||||
use App\Classes\Settings\Invoices;
|
||||
use App\Classes\Settings\System;
|
||||
use App\Http\Controllers\PartnerController;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -184,6 +185,11 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
|||
Route::get('vouchers/{voucher}/users', [VoucherController::class, 'users'])->name('vouchers.users');
|
||||
Route::resource('vouchers', VoucherController::class);
|
||||
|
||||
#partners
|
||||
Route::get('partners/datatable', [PartnerController::class, 'datatable'])->name('partners.datatable');
|
||||
Route::get('partners/{voucher}/users', [PartnerController::class, 'users'])->name('partners.users');
|
||||
Route::resource('partners', PartnerController::class);
|
||||
|
||||
#api-keys
|
||||
Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
|
||||
Route::resource('api', ApplicationApiController::class)->parameters([
|
||||
|
@ -209,4 +215,4 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
|
|||
});
|
||||
|
||||
Route::get('/home', [HomeController::class, 'index'])->name('home');
|
||||
});
|
||||
});
|
Loading…
Add table
Reference in a new issue