10.April 2026
This commit is contained in:
parent
a00c42e770
commit
f58c709945
208 changed files with 19280 additions and 2914 deletions
411
app/Http/Controllers/Admin/IncentiveController.php
Normal file
411
app/Http/Controllers/Admin/IncentiveController.php
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Incentive;
|
||||
use App\Models\IncentiveNewAbo;
|
||||
use App\Models\IncentiveNewPartner;
|
||||
use App\Models\IncentiveParticipant;
|
||||
use App\Models\IncentivePointsLog;
|
||||
use App\Models\UserAboOrder;
|
||||
use App\Models\UserSalesVolume;
|
||||
use App\Services\Incentive\IncentiveCalculationService;
|
||||
use App\User;
|
||||
use Request;
|
||||
|
||||
class IncentiveController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('admin');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('admin.incentive.index');
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return view('admin.incentive.create', [
|
||||
'languages' => config('localization.supportedLocales'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
$data = Request::validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'subtitle' => 'nullable|string|max:255',
|
||||
'description' => 'nullable|string',
|
||||
'image' => 'nullable|string|max:255',
|
||||
'terms' => 'nullable|string',
|
||||
'qualification_start' => 'required|date',
|
||||
'qualification_end' => 'required|date|after_or_equal:qualification_start',
|
||||
'calculation_end' => 'required|date|after_or_equal:qualification_end',
|
||||
'points_partner_onetime' => 'required|integer|min:0',
|
||||
'points_abo_onetime' => 'required|integer|min:0',
|
||||
'min_direct_partners' => 'required|integer|min:0',
|
||||
'min_customer_abos' => 'required|integer|min:0',
|
||||
'max_winners' => 'required|integer|min:1',
|
||||
'status' => 'required|integer|in:0,1,2',
|
||||
]);
|
||||
|
||||
$data = array_merge($data, $this->extractTranslations());
|
||||
|
||||
Incentive::create($data);
|
||||
|
||||
\Session()->flash('alert-success', __('incentive.created'));
|
||||
|
||||
return redirect(route('admin_incentives'));
|
||||
}
|
||||
|
||||
public function show($id)
|
||||
{
|
||||
$incentive = Incentive::findOrFail($id);
|
||||
$participants = IncentiveParticipant::where('incentive_id', $incentive->id)
|
||||
->with('user', 'user.account')
|
||||
->orderByIncentiveLeaderboard()
|
||||
->get();
|
||||
|
||||
return view('admin.incentive.show', [
|
||||
'incentive' => $incentive,
|
||||
'participants' => $participants,
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
$incentive = Incentive::findOrFail($id);
|
||||
|
||||
return view('admin.incentive.edit', [
|
||||
'incentive' => $incentive,
|
||||
'languages' => config('localization.supportedLocales'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update($id)
|
||||
{
|
||||
$data = Request::validate([
|
||||
'name' => 'required|string|max:255',
|
||||
'subtitle' => 'nullable|string|max:255',
|
||||
'description' => 'nullable|string',
|
||||
'image' => 'nullable|string|max:255',
|
||||
'terms' => 'nullable|string',
|
||||
'qualification_start' => 'required|date',
|
||||
'qualification_end' => 'required|date|after_or_equal:qualification_start',
|
||||
'calculation_end' => 'required|date|after_or_equal:qualification_end',
|
||||
'points_partner_onetime' => 'required|integer|min:0',
|
||||
'points_abo_onetime' => 'required|integer|min:0',
|
||||
'min_direct_partners' => 'required|integer|min:0',
|
||||
'min_customer_abos' => 'required|integer|min:0',
|
||||
'max_winners' => 'required|integer|min:1',
|
||||
'status' => 'required|integer|in:0,1,2',
|
||||
]);
|
||||
|
||||
$data = array_merge($data, $this->extractTranslations());
|
||||
|
||||
$incentive = Incentive::findOrFail($id);
|
||||
$incentive->update($data);
|
||||
|
||||
\Session()->flash('alert-success', __('incentive.updated'));
|
||||
|
||||
return redirect(route('admin_incentive_show', [$id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{trans_name: array<string, string>, trans_description: array<string, string>, trans_terms: array<string, string>}
|
||||
*/
|
||||
private function extractTranslations(): array
|
||||
{
|
||||
$transName = [];
|
||||
$transDescription = [];
|
||||
$transTerms = [];
|
||||
|
||||
$transSubtitle = [];
|
||||
|
||||
foreach (config('localization.supportedLocales') as $locale => $localeData) {
|
||||
if ($locale !== 'de') {
|
||||
$transName[$locale] = Request::get('trans_name_'.$locale, '');
|
||||
$transSubtitle[$locale] = Request::get('trans_subtitle_'.$locale, '');
|
||||
$transDescription[$locale] = Request::get('trans_description_'.$locale, '');
|
||||
$transTerms[$locale] = Request::get('trans_terms_'.$locale, '');
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'trans_name' => $transName,
|
||||
'trans_subtitle' => $transSubtitle,
|
||||
'trans_description' => $transDescription,
|
||||
'trans_terms' => $transTerms,
|
||||
];
|
||||
}
|
||||
|
||||
public function recalculate($id)
|
||||
{
|
||||
$incentive = Incentive::findOrFail($id);
|
||||
$service = new IncentiveCalculationService;
|
||||
$stats = $service->recalculate($incentive, Request::has('force'));
|
||||
|
||||
\Session()->flash('alert-success', __('incentive.recalculated', [
|
||||
'participants' => $stats['participants'],
|
||||
'errors' => $stats['errors'],
|
||||
]));
|
||||
|
||||
return redirect(route('admin_incentive_show', [$id]));
|
||||
}
|
||||
|
||||
public function participantDetails($participant_id)
|
||||
{
|
||||
$participant = IncentiveParticipant::with('incentive', 'user', 'user.account')
|
||||
->findOrFail($participant_id);
|
||||
|
||||
$data = self::buildParticipantDetailData($participant);
|
||||
|
||||
return view('admin.incentive._participant_details', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Baut die Detail-Daten fuer einen Teilnehmer auf.
|
||||
* Wird von Admin und User Controller genutzt.
|
||||
*/
|
||||
public static function buildParticipantDetailData(IncentiveParticipant $participant): array
|
||||
{
|
||||
$incentive = $participant->incentive;
|
||||
$calculation_months = $incentive->getCalculationMonths();
|
||||
|
||||
// Alle Logs dieses Teilnehmers (ohne Stornos)
|
||||
$all_logs = IncentivePointsLog::where('participant_id', $participant->id)
|
||||
->where('is_storno', false)
|
||||
->with('salesVolume')
|
||||
->orderBy('created_at')
|
||||
->get();
|
||||
|
||||
// UserSalesVolume-IDs -> User-ID Mapping aufbauen (fuer akkumulierte Partner-Punkte)
|
||||
$sv_ids = $all_logs->whereNotNull('user_sales_volume_id')->pluck('user_sales_volume_id')->unique()->toArray();
|
||||
$sv_user_map = ! empty($sv_ids)
|
||||
? UserSalesVolume::whereIn('id', $sv_ids)->pluck('user_id', 'id')->toArray()
|
||||
: [];
|
||||
|
||||
// Partner aus Tracking-Tabelle
|
||||
$new_partners = IncentiveNewPartner::where('participant_id', $participant->id)
|
||||
->with('user', 'user.account')
|
||||
->orderBy('registered_at')
|
||||
->get();
|
||||
|
||||
$partner_logs = $all_logs->where('type', 'partner');
|
||||
|
||||
$partner_sources = $new_partners->map(function ($np) use ($partner_logs, $sv_user_map, $calculation_months, $incentive) {
|
||||
$monthly = [];
|
||||
$transactions = [];
|
||||
|
||||
foreach ($calculation_months as $period) {
|
||||
// Akkumulierte Logs: source_type=UserSalesVolume, deren USV.user_id == partner user_id
|
||||
$month_logs = $partner_logs
|
||||
->where('month', $period['month'])
|
||||
->where('year', $period['year'])
|
||||
->filter(function ($log) use ($np, $sv_user_map) {
|
||||
if ($log->source_type === User::class) {
|
||||
return false; // Einmal-Punkte nicht in Monatsspalte
|
||||
}
|
||||
|
||||
if ($log->incentive_new_partner_id) {
|
||||
return (int) $log->incentive_new_partner_id === (int) $np->id;
|
||||
}
|
||||
|
||||
// Legacy: USV.user_id muss zum Partner gehoeren
|
||||
return isset($sv_user_map[$log->user_sales_volume_id])
|
||||
&& $sv_user_map[$log->user_sales_volume_id] === $np->user_id;
|
||||
});
|
||||
|
||||
$month_points = (int) $month_logs->sum('points_accumulated');
|
||||
$monthly[] = $month_points;
|
||||
|
||||
foreach ($month_logs as $log) {
|
||||
$transactions[] = [
|
||||
'date' => $log->created_at->format('d.m.Y'),
|
||||
'month' => $period['month'],
|
||||
'year' => $period['year'],
|
||||
'label' => $log->source_label ?: 'KP #'.($log->user_sales_volume_id ?? $log->source_id),
|
||||
'points' => $log->points_accumulated,
|
||||
'type' => 'accumulated',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Einmal-Punkte als Transaktion hinzufuegen
|
||||
$onetime_log = $partner_logs
|
||||
->where('source_type', User::class)
|
||||
->first(function ($log) use ($np) {
|
||||
if ($log->incentive_new_partner_id) {
|
||||
return (int) $log->incentive_new_partner_id === (int) $np->id;
|
||||
}
|
||||
|
||||
return (int) $log->source_id === (int) $np->user_id;
|
||||
});
|
||||
|
||||
if ($onetime_log) {
|
||||
array_unshift($transactions, [
|
||||
'date' => $onetime_log->created_at->format('d.m.Y'),
|
||||
'month' => $onetime_log->month,
|
||||
'year' => $onetime_log->year,
|
||||
'label' => __('incentive.onetime_registration'),
|
||||
'points' => $onetime_log->points_onetime,
|
||||
'type' => 'onetime',
|
||||
]);
|
||||
}
|
||||
|
||||
return [
|
||||
'id' => $np->id,
|
||||
'label' => $np->user ? ($np->user->getFullName() ?: $np->user->email ?: 'User #'.$np->user_id) : 'User #'.$np->user_id,
|
||||
'month' => $np->registered_at->month,
|
||||
'year' => $np->registered_at->year,
|
||||
'onetime' => $incentive->points_partner_onetime,
|
||||
'monthly' => $monthly,
|
||||
'total' => $incentive->points_partner_onetime + array_sum($monthly),
|
||||
'transactions' => $transactions,
|
||||
];
|
||||
});
|
||||
|
||||
// Abos aus Tracking-Tabelle
|
||||
$new_abos = IncentiveNewAbo::where('participant_id', $participant->id)
|
||||
->with('userAbo')
|
||||
->orderBy('activated_at')
|
||||
->get();
|
||||
|
||||
$abo_logs = $all_logs->where('type', 'abo');
|
||||
|
||||
// Legacy-Fallback: USV -> user_abo_id (Logs ohne incentive_new_abo_id)
|
||||
$sv_user_abo_map = [];
|
||||
$needs_legacy_abo_map = $abo_logs->whereNull('incentive_new_abo_id')->whereNotNull('user_sales_volume_id')->isNotEmpty();
|
||||
if ($needs_legacy_abo_map && ! empty($sv_ids)) {
|
||||
$sv_rows = UserSalesVolume::query()
|
||||
->whereIn('id', $sv_ids)
|
||||
->whereNotNull('shopping_order_id')
|
||||
->get(['id', 'shopping_order_id']);
|
||||
$order_ids = $sv_rows->pluck('shopping_order_id')->unique()->filter()->values();
|
||||
if ($order_ids->isNotEmpty()) {
|
||||
$user_abo_id_by_order_id = UserAboOrder::query()
|
||||
->whereIn('shopping_order_id', $order_ids)
|
||||
->get(['shopping_order_id', 'user_abo_id'])
|
||||
->keyBy('shopping_order_id');
|
||||
foreach ($sv_rows as $sv) {
|
||||
$link = $user_abo_id_by_order_id->get($sv->shopping_order_id);
|
||||
if ($link) {
|
||||
$sv_user_abo_map[$sv->id] = (int) $link->user_abo_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$abo_sources = $new_abos->map(function ($na) use ($abo_logs, $sv_user_abo_map, $calculation_months, $incentive) {
|
||||
$monthly = [];
|
||||
$transactions = [];
|
||||
$tracked_user_abo_id = (int) $na->user_abo_id;
|
||||
|
||||
foreach ($calculation_months as $period) {
|
||||
$month_logs = $abo_logs
|
||||
->where('month', $period['month'])
|
||||
->where('year', $period['year'])
|
||||
->filter(function ($log) use ($na, $tracked_user_abo_id, $sv_user_abo_map) {
|
||||
if ($log->source_type !== UserSalesVolume::class) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($log->incentive_new_abo_id) {
|
||||
return (int) $log->incentive_new_abo_id === (int) $na->id;
|
||||
}
|
||||
|
||||
$usv_id = $log->user_sales_volume_id;
|
||||
if (! $usv_id || ! isset($sv_user_abo_map[$usv_id])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $sv_user_abo_map[$usv_id] === $tracked_user_abo_id;
|
||||
});
|
||||
|
||||
$month_points = (int) $month_logs->sum('points_accumulated');
|
||||
$monthly[] = $month_points;
|
||||
|
||||
foreach ($month_logs as $log) {
|
||||
$transactions[] = [
|
||||
'date' => $log->created_at->format('d.m.Y'),
|
||||
'month' => $period['month'],
|
||||
'year' => $period['year'],
|
||||
'label' => $log->source_label ?: 'SV #'.($log->user_sales_volume_id ?? $log->source_id),
|
||||
'points' => $log->points_accumulated,
|
||||
'type' => 'accumulated',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Einmal-Punkte als Transaktion
|
||||
$onetime_log = $abo_logs
|
||||
->where('source_type', '!=', UserSalesVolume::class)
|
||||
->first(function ($log) use ($na) {
|
||||
if ($log->incentive_new_abo_id) {
|
||||
return (int) $log->incentive_new_abo_id === (int) $na->id;
|
||||
}
|
||||
|
||||
return (int) $log->source_id === (int) $na->user_abo_id;
|
||||
});
|
||||
|
||||
if ($onetime_log) {
|
||||
array_unshift($transactions, [
|
||||
'date' => $onetime_log->created_at->format('d.m.Y'),
|
||||
'month' => $onetime_log->month,
|
||||
'year' => $onetime_log->year,
|
||||
'label' => __('incentive.onetime_abo_activation'),
|
||||
'points' => $onetime_log->points_onetime,
|
||||
'type' => 'onetime',
|
||||
]);
|
||||
}
|
||||
|
||||
$label = $na->userAbo?->email ?: ('Abo #'.$na->user_abo_id);
|
||||
|
||||
return [
|
||||
'id' => $na->id,
|
||||
'label' => $label,
|
||||
'month' => $na->activated_at->month,
|
||||
'year' => $na->activated_at->year,
|
||||
'onetime' => $incentive->points_abo_onetime,
|
||||
'monthly' => $monthly,
|
||||
'total' => $incentive->points_abo_onetime + array_sum($monthly),
|
||||
'transactions' => $transactions,
|
||||
];
|
||||
});
|
||||
|
||||
return [
|
||||
'incentive' => $incentive,
|
||||
'participant' => $participant,
|
||||
'calculation_months' => $calculation_months,
|
||||
'partner_sources' => $partner_sources,
|
||||
'abo_sources' => $abo_sources,
|
||||
];
|
||||
}
|
||||
|
||||
public function datatable()
|
||||
{
|
||||
$query = Incentive::query()->select('incentives.*');
|
||||
|
||||
return \DataTables::eloquent($query)
|
||||
->addColumn('action', function (Incentive $incentive) {
|
||||
return '<a href="'.route('admin_incentive_show', [$incentive->id]).'" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-eye"></span></a>
|
||||
<a href="'.route('admin_incentive_edit', [$incentive->id]).'" class="btn icon-btn btn-sm btn-warning"><span class="fa fa-edit"></span></a>';
|
||||
})
|
||||
->addColumn('status_label', function (Incentive $incentive) {
|
||||
return '<span class="badge badge-'.$incentive->getStatusColor().'">'.$incentive->getStatusType().'</span>';
|
||||
})
|
||||
->addColumn('period', function (Incentive $incentive) {
|
||||
return $incentive->qualification_start->format('d.m.Y').' - '.$incentive->qualification_end->format('d.m.Y');
|
||||
})
|
||||
->addColumn('participants_count', function (Incentive $incentive) {
|
||||
return $incentive->participants()->count();
|
||||
})
|
||||
->orderColumn('name', 'name $1')
|
||||
->orderColumn('status_label', 'status $1')
|
||||
->rawColumns(['action', 'status_label'])
|
||||
->make(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -105,29 +105,39 @@ class PayoneController extends Controller
|
|||
echo 'TSOK';
|
||||
exit;
|
||||
}
|
||||
|
||||
/* TODO -- need this? */
|
||||
/*
|
||||
* Payone sendet dieselbe txaction oft mehrfach (v. a. "appointed"). War der Status
|
||||
* bereits auf ShoppingPayment gespeichert, ist das ein Duplikat: TSOK, keine Doppel-Verarbeitung.
|
||||
* Ausnahme: erneutes "paid", obwohl die Bestellung noch nicht als bezahlt gefuehrt wird (Recovery).
|
||||
*/
|
||||
if ($shopping_payment->txaction == $data['txaction']) {
|
||||
|
||||
if ($data['txaction'] === 'paid' && $shopping_order->txaction === 'paid') {
|
||||
MyLog::writeLog(
|
||||
'payone',
|
||||
'error',
|
||||
'Error:2007 App\Http\Controllers\Api\PayoneController::paymentStatus same txaction - was already paid',
|
||||
'notice',
|
||||
'App\Http\Controllers\Api\PayoneController::paymentStatus duplicate callback ignored (already paid)',
|
||||
$data,
|
||||
false
|
||||
);
|
||||
// was already paid
|
||||
echo 'TSOK';
|
||||
exit;
|
||||
} else {
|
||||
}
|
||||
|
||||
if (in_array($data['txaction'], ['appointed', 'failed', 'pending'], true)) {
|
||||
MyLog::writeLog(
|
||||
'payone',
|
||||
'error',
|
||||
'Error:2007 App\Http\Controllers\Api\PayoneController::paymentStatus same txaction - show',
|
||||
$data,
|
||||
'info',
|
||||
'App\Http\Controllers\Api\PayoneController::paymentStatus duplicate callback ignored (same txaction)',
|
||||
[
|
||||
'reference' => $data['reference'] ?? null,
|
||||
'param' => $data['param'] ?? null,
|
||||
'txaction' => $data['txaction'],
|
||||
'txid' => $data['txid'] ?? null,
|
||||
],
|
||||
false
|
||||
);
|
||||
echo 'TSOK';
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -191,7 +201,6 @@ class PayoneController extends Controller
|
|||
$locked_order = ShoppingOrder::where('id', $shopping_order->id)
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
// Double-check if payment was already processed
|
||||
if (! $locked_order->paid) {
|
||||
$send_link = Payment::paymentStatusPaidAction($locked_order, true, $shopping_payment);
|
||||
|
|
@ -211,6 +220,7 @@ class PayoneController extends Controller
|
|||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$data['send_link'] = $send_link;
|
||||
if ($send_mail) {
|
||||
Payment::paymentStatusSendMail($shopping_order, $shopping_payment, $data);
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\DashboardNews;
|
||||
use App\Models\Incentive;
|
||||
use App\Models\IncentiveParticipant;
|
||||
use App\Models\ShoppingPayment;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
|
|
@ -20,6 +23,7 @@ class HomeController extends Controller
|
|||
|
||||
public function index()
|
||||
{
|
||||
|
||||
if (! Auth::check()) {
|
||||
return redirect('login');
|
||||
}
|
||||
|
|
@ -43,10 +47,26 @@ class HomeController extends Controller
|
|||
return redirect('login');
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
$activeIncentive = null;
|
||||
$incentiveParticipant = null;
|
||||
|
||||
if ($user->isActiveAccount()) {
|
||||
$activeIncentive = Incentive::active()->first();
|
||||
if ($activeIncentive) {
|
||||
$incentiveParticipant = IncentiveParticipant::where('incentive_id', $activeIncentive->id)
|
||||
->where('user_id', $user->id)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
$data = [
|
||||
'user' => Auth::user(),
|
||||
'user' => $user,
|
||||
'now' => Carbon::now(),
|
||||
'dashboardNews' => \App\Models\DashboardNews::getActiveNews(),
|
||||
'dashboardNews' => DashboardNews::getActiveNews(),
|
||||
'activeIncentive' => $activeIncentive,
|
||||
'incentiveParticipant' => $incentiveParticipant,
|
||||
];
|
||||
|
||||
return view('home', $data);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use App\Services\Payment;
|
|||
use App\Services\Util;
|
||||
use App\User;
|
||||
use Carbon;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Request;
|
||||
|
||||
class PaymentCreditController extends Controller
|
||||
|
|
@ -183,6 +184,36 @@ class PaymentCreditController extends Controller
|
|||
return $query;
|
||||
}
|
||||
|
||||
public function stats(): JsonResponse
|
||||
{
|
||||
$this->setFilterVars();
|
||||
|
||||
$month = Request::get('credit_filter_month', session('credit_filter_month'));
|
||||
$year = Request::get('credit_filter_year', session('credit_filter_year'));
|
||||
$name = Request::get('credit_filter_name', '');
|
||||
|
||||
$dateStart = Carbon::parse('01.'.$month.'.'.$year)->format('Y-m-d');
|
||||
$dateEnd = Carbon::parse('01.'.$month.'.'.$year)->endOfMonth()->format('Y-m-d');
|
||||
|
||||
$baseQuery = UserCredit::query()
|
||||
->whereBetween('date', [$dateStart, $dateEnd]);
|
||||
|
||||
if ($name) {
|
||||
$baseQuery->whereHas('user.account', function ($query) use ($name) {
|
||||
$query->where('first_name', 'LIKE', '%'.$name.'%')
|
||||
->orWhere('last_name', 'LIKE', '%'.$name.'%');
|
||||
});
|
||||
}
|
||||
|
||||
$count = (clone $baseQuery)->count();
|
||||
$total = (clone $baseQuery)->sum('total');
|
||||
|
||||
return response()->json([
|
||||
'count' => $count,
|
||||
'total' => number_format((float) $total, 2, ',', '.'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function datatable()
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Carbon;
|
||||
use Request;
|
||||
use App\Services\Payment;
|
||||
use App\Models\UserInvoice;
|
||||
use App\Services\HTMLHelper;
|
||||
use App\Services\Payment;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Request;
|
||||
|
||||
class PaymentInvoiceController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('admin');
|
||||
|
|
@ -26,16 +23,17 @@ class PaymentInvoiceController extends Controller
|
|||
'filter_months' => HTMLHelper::getTransMonths(),
|
||||
'filter_years' => HTMLHelper::getYearRange(),
|
||||
];
|
||||
|
||||
return view('admin.payment.invoice', $data);
|
||||
}
|
||||
|
||||
private function setFilterVars()
|
||||
{
|
||||
|
||||
if (!session('invoice_filter_month')) {
|
||||
if (! session('invoice_filter_month')) {
|
||||
session(['invoice_filter_month' => intval(date('m'))]);
|
||||
}
|
||||
if (!session('invoice_filter_year')) {
|
||||
if (! session('invoice_filter_year')) {
|
||||
session(['invoice_filter_year' => intval(date('Y'))]);
|
||||
}
|
||||
if (Request::get('invoice_filter_name')) {
|
||||
|
|
@ -61,12 +59,44 @@ class PaymentInvoiceController extends Controller
|
|||
|
||||
if (Request::get('invoice_filter_name')) {
|
||||
$query->whereHas('shopping_order.shopping_user', function ($query) {
|
||||
return $query->where('billing_firstname', 'LIKE', '%' . Request::get('invoice_filter_name') . '%')->orWhere('billing_lastname', 'LIKE', '%' . Request::get('invoice_filter_name') . '%')->orWhere('billing_email', 'LIKE', '%' . Request::get('invoice_filter_name') . '%');
|
||||
return $query->where('billing_firstname', 'LIKE', '%'.Request::get('invoice_filter_name').'%')->orWhere('billing_lastname', 'LIKE', '%'.Request::get('invoice_filter_name').'%')->orWhere('billing_email', 'LIKE', '%'.Request::get('invoice_filter_name').'%');
|
||||
})->get();
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function stats(): JsonResponse
|
||||
{
|
||||
$this->setFilterVars();
|
||||
|
||||
$month = Request::get('invoice_filter_month', session('invoice_filter_month'));
|
||||
$year = Request::get('invoice_filter_year', session('invoice_filter_year'));
|
||||
$name = Request::get('invoice_filter_name', '');
|
||||
|
||||
$baseQuery = UserInvoice::query()
|
||||
->where('user_invoices.month', $month)
|
||||
->where('user_invoices.year', $year);
|
||||
|
||||
if ($name) {
|
||||
$baseQuery->whereHas('shopping_order.shopping_user', function ($query) use ($name) {
|
||||
$query->where('billing_firstname', 'LIKE', '%'.$name.'%')
|
||||
->orWhere('billing_lastname', 'LIKE', '%'.$name.'%')
|
||||
->orWhere('billing_email', 'LIKE', '%'.$name.'%');
|
||||
});
|
||||
}
|
||||
|
||||
$count = (clone $baseQuery)->count();
|
||||
$total = (clone $baseQuery)
|
||||
->join('shopping_orders', 'shopping_orders.id', '=', 'user_invoices.shopping_order_id')
|
||||
->sum('shopping_orders.total_shipping');
|
||||
|
||||
return response()->json([
|
||||
'count' => $count,
|
||||
'total' => number_format((float) $total, 2, ',', '.'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function datatable()
|
||||
{
|
||||
|
||||
|
|
@ -75,32 +105,35 @@ class PaymentInvoiceController extends Controller
|
|||
return \DataTables::eloquent($query)
|
||||
->addColumn('id', function (UserInvoice $UserInvoice) {
|
||||
if ($UserInvoice->shopping_order->auth_user_id) {
|
||||
return '<a href="' . route('admin_sales_users_detail', [$UserInvoice->shopping_order->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
|
||||
return '<a href="'.route('admin_sales_users_detail', [$UserInvoice->shopping_order->id]).'" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
|
||||
}
|
||||
return '<a href="' . route('admin_sales_customers_detail', [$UserInvoice->shopping_order->id]) . '" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
|
||||
|
||||
return '<a href="'.route('admin_sales_customers_detail', [$UserInvoice->shopping_order->id]).'" class="btn icon-btn btn-sm btn-primary"><span class="fa fa-edit"></span></a>';
|
||||
})
|
||||
->addColumn('total_shipping', function (UserInvoice $UserInvoice) {
|
||||
return '<span class="no-line-break">' . $UserInvoice->shopping_order->getFormattedTotalShipping() . " €</span>";
|
||||
return '<span class="no-line-break">'.$UserInvoice->shopping_order->getFormattedTotalShipping().' €</span>';
|
||||
})
|
||||
->addColumn('created_at', function (UserInvoice $UserInvoice) {
|
||||
return $UserInvoice->created_at->format("d.m.Y");
|
||||
return $UserInvoice->created_at->format('d.m.Y');
|
||||
})
|
||||
->addColumn('txaction', function (UserInvoice $UserInvoice) {
|
||||
if ($UserInvoice->shopping_order) {
|
||||
return Payment::getShoppingOrderBadge($UserInvoice->shopping_order);
|
||||
}
|
||||
return "-";
|
||||
|
||||
return '-';
|
||||
})
|
||||
->addColumn('status', function (UserInvoice $UserInvoice) {
|
||||
return '<a href="#" data-toggle="modal" data-target="#modals-load-content" data-modal="modal-lg"
|
||||
data-id="' . $UserInvoice->id . '" data-route="' . route('modal_load') . '" data-action="user-credit-status" data-view="">
|
||||
<span class="badge badge-pill badge-' . $UserInvoice->getStatusColor() . '">' . $UserInvoice->getStatusType() . '</span>
|
||||
data-id="'.$UserInvoice->id.'" data-route="'.route('modal_load').'" data-action="user-credit-status" data-view="">
|
||||
<span class="badge badge-pill badge-'.$UserInvoice->getStatusColor().'">'.$UserInvoice->getStatusType().'</span>
|
||||
</a>';
|
||||
})
|
||||
->addColumn('invoice', function (UserInvoice $UserInvoice) {
|
||||
$ret = "";
|
||||
$ret .= '<a href="' . route('storage_file', [$UserInvoice->shopping_order->id, 'invoice', 'download']) . '" class="btn btn-primary btn-xs"><i class="fa fa-download"></i></a> ';
|
||||
$ret .= '<a href="' . route('storage_file', [$UserInvoice->shopping_order->id, 'invoice', 'stream']) . '" target="_blank" class="btn btn-warning btn-xs"><i class="fa fa-eye"></i></a>';
|
||||
$ret = '';
|
||||
$ret .= '<a href="'.route('storage_file', [$UserInvoice->shopping_order->id, 'invoice', 'download']).'" class="btn btn-primary btn-xs"><i class="fa fa-download"></i></a> ';
|
||||
$ret .= '<a href="'.route('storage_file', [$UserInvoice->shopping_order->id, 'invoice', 'stream']).'" target="_blank" class="btn btn-warning btn-xs"><i class="fa fa-eye"></i></a>';
|
||||
|
||||
return $ret;
|
||||
})
|
||||
->orderColumn('id', 'id $1')
|
||||
|
|
|
|||
|
|
@ -403,16 +403,20 @@ class AboController extends Controller
|
|||
$data['step'] = 4;
|
||||
break;
|
||||
case 5:
|
||||
// chekout verarbeiten
|
||||
UserService::setInstance($this->instance);
|
||||
UserService::initCustomerYard($shopping_user, 'abo-ot-customer');
|
||||
if (Request::get('action') == 'checkout') {
|
||||
// checkout verarbeiten
|
||||
if (! $this->preCheckCheckout()) {
|
||||
if (! Request::boolean('abo_order_info_checkbox')) {
|
||||
$data['error'] = __('abo.abo_order_info_checkbox_required');
|
||||
$data['step'] = 4;
|
||||
} elseif (! in_array((int) Request::input('abo_interval'), UserAbo::$aboDeliveryDays, true)) {
|
||||
$data['error'] = __('abo.error_abo_interval');
|
||||
$data['step'] = 4;
|
||||
} elseif (! $this->preCheckCheckout()) {
|
||||
$data['error'] = __('abo.abo_error_basis_product');
|
||||
$data['step'] = 4;
|
||||
} else {
|
||||
$data['checkout_url'] = $this->processCheckout();
|
||||
$data['checkout_url'] = $this->processCheckout($shopping_user);
|
||||
}
|
||||
}
|
||||
$data['step'] = 4;
|
||||
|
|
@ -439,18 +443,9 @@ class AboController extends Controller
|
|||
Shop::initUserShopLang($delivery_country, $this->instance);
|
||||
}
|
||||
|
||||
private function preCheckCheckout()
|
||||
private function preCheckCheckout(): bool
|
||||
{
|
||||
$result = false;
|
||||
// alle inhlate des warenkorb
|
||||
$cartItems = $this->yard->content();
|
||||
foreach ($cartItems as $item) {
|
||||
if (in_array(12, $item->options->show_on)) {
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
return AboHelper::aboHasBaseProduct($this->yard->getContentByOrder());
|
||||
}
|
||||
|
||||
private function checkBasisProduct()
|
||||
|
|
@ -550,7 +545,7 @@ class AboController extends Controller
|
|||
$this->yard->reCalculateShippingPrice();
|
||||
}
|
||||
|
||||
private function processCheckout()
|
||||
private function processCheckout(ShoppingUser $shoppingUser): string
|
||||
{
|
||||
$user_shop = Util::getUserShop();
|
||||
if (! $user_shop) {
|
||||
|
|
@ -560,24 +555,38 @@ class AboController extends Controller
|
|||
$identifier = Util::getToken();
|
||||
} while (ShoppingInstance::where('identifier', $identifier)->count());
|
||||
|
||||
$data = [];
|
||||
$data['is_from'] = 'shopping';
|
||||
$data['user_price_infos'] = $this->yard->getUserPriceInfos();
|
||||
$aboInterval = (int) Request::input('abo_interval', 0);
|
||||
|
||||
$fillable = (new ShoppingUser)->getFillable();
|
||||
$shoppingData = array_merge(
|
||||
array_intersect_key($shoppingUser->getAttributes(), array_flip($fillable)),
|
||||
[
|
||||
'shopping_user_id' => $shoppingUser->id,
|
||||
'is_from' => 'shopping',
|
||||
'is_for' => 'abo-ot-customer',
|
||||
'is_abo' => true,
|
||||
'abo_interval' => $aboInterval,
|
||||
'shipping_is_for' => 'abo-ot-customer',
|
||||
'user_price_infos' => $this->yard->getUserPriceInfos(),
|
||||
'mode' => config('app.mode') === 'test' ? 'test' : 'live',
|
||||
]
|
||||
);
|
||||
|
||||
ShoppingInstance::create([
|
||||
'identifier' => $identifier,
|
||||
'user_shop_id' => $user_shop->id,
|
||||
'payment' => 1, // Customer Shop Payment
|
||||
'payment' => 1,
|
||||
'subdomain' => url('/'),
|
||||
'country_id' => $this->yard->getShippingCountryId(),
|
||||
'language' => \App::getLocale(),
|
||||
'shopping_data' => $data,
|
||||
'language' => $shoppingUser->getLocale(),
|
||||
'amount' => (float) $this->yard->totalWithShipping(2, '.', ''),
|
||||
'shopping_user_id' => $shoppingUser->id,
|
||||
'shopping_data' => $shoppingData,
|
||||
'back' => url()->previous(),
|
||||
|
||||
]);
|
||||
|
||||
$this->yard->store($identifier);
|
||||
// add to DB
|
||||
|
||||
$path = route('checkout.checkout_card', ['identifier' => $identifier]);
|
||||
if (strpos($path, 'https') === false) {
|
||||
$path = str_replace('http', 'https', $path);
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@ use App\Models\ShoppingOrder;
|
|||
use App\Models\ShoppingPayment;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Services\Payment;
|
||||
use App\Services\ProductOrderContext;
|
||||
use App\Services\Shop;
|
||||
use App\Services\Util;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Yard;
|
||||
|
||||
class OrderController extends Controller
|
||||
|
|
@ -192,7 +194,7 @@ class OrderController extends Controller
|
|||
public function myOrderCreate(int $id)
|
||||
{
|
||||
$user = Auth::guard('customers')->user();
|
||||
$shopping_order = ShoppingOrder::findOrFail($id);
|
||||
$shopping_order = ShoppingOrder::with('member.shop')->findOrFail($id);
|
||||
|
||||
if ($shopping_order->shopping_user_id != $user->shopping_user_id) {
|
||||
$shopping_user = ShoppingUser::findOrFail($user->shopping_user_id);
|
||||
|
|
@ -202,6 +204,13 @@ class OrderController extends Controller
|
|||
}
|
||||
|
||||
$shopping_user = ShoppingUser::findOrFail($user->shopping_user_id);
|
||||
|
||||
if ($shopping_order->is_abo) {
|
||||
Session::flash('alert-error', __('order.reorder_abo_not_allowed'));
|
||||
|
||||
return redirect()->route('portal.my_orders.show', $shopping_order->id);
|
||||
}
|
||||
|
||||
$delivery_country = $shopping_user->getDeliveryCountry(true);
|
||||
|
||||
\Session::put('user_init_country', strtolower($delivery_country->code));
|
||||
|
|
@ -211,18 +220,18 @@ class OrderController extends Controller
|
|||
Shop::initUserShopLang($delivery_country, $this->instance);
|
||||
|
||||
foreach ($shopping_order->shopping_order_items as $item) {
|
||||
if ($item->product) {
|
||||
if ($item->product && ProductOrderContext::isProductAllowedInCustomerWebshop($item->product)) {
|
||||
$this->addToCart($item->product_id, $item->qty);
|
||||
}
|
||||
}
|
||||
|
||||
return redirect(Util::getMyMivitaShopUrl('/user/card/show'));
|
||||
return redirect(Util::getCustomerReorderCartUrl($shopping_order));
|
||||
}
|
||||
|
||||
private function addToCart(int $productId, int $quantity = 1): void
|
||||
{
|
||||
$product = Product::find($productId);
|
||||
if (! $product) {
|
||||
if (! $product || ! ProductOrderContext::isProductAllowedInCustomerWebshop($product)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
42
app/Http/Controllers/SAdmin/SAdminController.php
Normal file
42
app/Http/Controllers/SAdmin/SAdminController.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\SAdmin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\SyS\AboOrdersOverview;
|
||||
|
||||
class SAdminController extends Controller
|
||||
{
|
||||
protected $userRepo;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('superadmin');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
return view('sys.index');
|
||||
}
|
||||
|
||||
public function tool($serve)
|
||||
{
|
||||
switch ($serve) {
|
||||
|
||||
case 'abo_orders_overview':
|
||||
return AboOrdersOverview::show();
|
||||
break;
|
||||
}
|
||||
abort(403, 'not found tool');
|
||||
}
|
||||
|
||||
public function store($serve)
|
||||
{
|
||||
switch ($serve) {
|
||||
case 'abo_orders_overview':
|
||||
// return AboOrdersOverview::store();
|
||||
break;
|
||||
}
|
||||
abort(403, 'not found tool');
|
||||
}
|
||||
}
|
||||
|
|
@ -2,23 +2,23 @@
|
|||
|
||||
namespace App\Http\Controllers\SyS;
|
||||
|
||||
use Carbon;
|
||||
use Request;
|
||||
use App\Services\SyS\Sales;
|
||||
use App\Services\SyS\Import;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\SyS\AboOrdersOverview;
|
||||
use App\Services\SyS\BusinessStructur;
|
||||
use App\Services\SyS\BuyingsProducts;
|
||||
use App\Services\SyS\ChangeUserBusinesses;
|
||||
use App\Services\SyS\CleanHTMLProductDescription;
|
||||
use App\Services\SyS\Correction;
|
||||
use App\Services\SyS\Cronjobs;
|
||||
use App\Services\SyS\Customers;
|
||||
use App\Services\SyS\DomainSSL;
|
||||
use App\Services\SyS\Correction;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\SyS\ShoppingOrders;
|
||||
use App\Services\SyS\BuyingsProducts;
|
||||
use App\Services\SyS\BusinessStructur;
|
||||
use App\Services\SyS\Import;
|
||||
use App\Services\SyS\ImportDbipCountry;
|
||||
use App\Services\SyS\ChangeUserBusinesses;
|
||||
use App\Services\SyS\UserCreditItemsAddFrom;
|
||||
use App\Services\SyS\PayoneCallbackTestbench;
|
||||
use App\Services\SyS\RepairSalesVolumeInvoice;
|
||||
use App\Services\SyS\CleanHTMLProductDescription;
|
||||
use App\Services\SyS\Sales;
|
||||
use App\Services\SyS\ShoppingOrders;
|
||||
use App\Services\SyS\UserCreditItemsAddFrom;
|
||||
use App\Services\SyS\UserCreditItemsChangeMessage;
|
||||
|
||||
class SysController extends Controller
|
||||
|
|
@ -28,18 +28,17 @@ class SysController extends Controller
|
|||
public function __construct()
|
||||
{
|
||||
$this->middleware('sysadmin');
|
||||
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
{
|
||||
return view('sys.index');
|
||||
}
|
||||
|
||||
public function tool($serve)
|
||||
{
|
||||
{
|
||||
switch ($serve) {
|
||||
|
||||
|
||||
case 'user_credit_items_add_from':
|
||||
return UserCreditItemsAddFrom::show();
|
||||
break;
|
||||
|
|
@ -54,19 +53,19 @@ class SysController extends Controller
|
|||
break;
|
||||
case 'customers':
|
||||
return Customers::show();
|
||||
break;
|
||||
break;
|
||||
case 'cronjobs':
|
||||
return Cronjobs::show();
|
||||
break;
|
||||
break;
|
||||
case 'domainssl':
|
||||
return DomainSSL::show();
|
||||
break;
|
||||
case 'shopping_orders':
|
||||
return ShoppingOrders::show();
|
||||
break;
|
||||
break;
|
||||
case 'import':
|
||||
return Import::show();
|
||||
break;
|
||||
break;
|
||||
case 'corrections':
|
||||
return Correction::show();
|
||||
break;
|
||||
|
|
@ -75,27 +74,28 @@ class SysController extends Controller
|
|||
break;
|
||||
case 'repair_sales_volume_invoice':
|
||||
return RepairSalesVolumeInvoice::show();
|
||||
break;
|
||||
break;
|
||||
case 'user_credit_items_change_message':
|
||||
return UserCreditItemsChangeMessage::show();
|
||||
break;
|
||||
case 'clean_html_product_description':
|
||||
break;
|
||||
case 'clean_html_product_description':
|
||||
return CleanHTMLProductDescription::show();
|
||||
break;
|
||||
break;
|
||||
case 'import_dbip_country_lite':
|
||||
return ImportDbipCountry::show();
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
break;
|
||||
case 'abo_orders_overview':
|
||||
return AboOrdersOverview::show();
|
||||
break;
|
||||
case 'payone_callback_testbench':
|
||||
return PayoneCallbackTestbench::show();
|
||||
break;
|
||||
}
|
||||
abort(403, 'not found tool');
|
||||
abort(403, 'not found tool');
|
||||
}
|
||||
|
||||
|
||||
public function store($serve)
|
||||
{
|
||||
{
|
||||
switch ($serve) {
|
||||
case 'user_credit_items_add_from':
|
||||
return UserCreditItemsAddFrom::show();
|
||||
|
|
@ -111,38 +111,41 @@ class SysController extends Controller
|
|||
break;
|
||||
case 'customers':
|
||||
return Customers::store();
|
||||
break;
|
||||
break;
|
||||
case 'cronjobs':
|
||||
return Cronjobs::store();
|
||||
break;
|
||||
break;
|
||||
case 'domainssl':
|
||||
return DomainSSL::store();
|
||||
break;
|
||||
case 'shopping_orders':
|
||||
return ShoppingOrders::store();
|
||||
break;
|
||||
break;
|
||||
case 'import':
|
||||
return Import::store();
|
||||
break;
|
||||
break;
|
||||
case 'corrections':
|
||||
return Correction::store();
|
||||
break;
|
||||
case 'change_user_businesses':
|
||||
return ChangeUserBusinesses::store();
|
||||
break;
|
||||
break;
|
||||
case 'repair_sales_volume_invoice':
|
||||
return RepairSalesVolumeInvoice::store();
|
||||
break;
|
||||
break;
|
||||
case 'user_credit_items_change_message':
|
||||
return UserCreditItemsChangeMessage::store();
|
||||
break;
|
||||
break;
|
||||
case 'clean_html_product_description':
|
||||
return CleanHTMLProductDescription::store();
|
||||
break;
|
||||
break;
|
||||
case 'import_dbip_country_lite':
|
||||
return ImportDbipCountry::store();
|
||||
break;
|
||||
break;
|
||||
case 'payone_callback_testbench':
|
||||
return PayoneCallbackTestbench::store();
|
||||
break;
|
||||
}
|
||||
abort(403, 'not found tool');
|
||||
abort(403, 'not found tool');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,13 @@ class AboController extends Controller
|
|||
}
|
||||
|
||||
if ($view === 'ot') {
|
||||
$user_abos = UserAbo::where('member_id', \Auth::user()->id)
|
||||
$selectedYear = (int) \Request::get('year', now()->year);
|
||||
$baseQuery = UserAbo::where('member_id', \Auth::user()->id)
|
||||
->where('status', '>', 1)
|
||||
->where('is_for', 'ot')
|
||||
->where('is_for', 'ot');
|
||||
|
||||
$user_abos = (clone $baseQuery)
|
||||
->with(['user_abo_items', 'user_abo_items.product', 'shopping_user'])
|
||||
->orderBy('id', 'desc')
|
||||
->get();
|
||||
|
||||
|
|
@ -55,6 +59,10 @@ class AboController extends Controller
|
|||
'user_abos' => $user_abos,
|
||||
'view' => 'ot',
|
||||
'isAdmin' => false,
|
||||
'chartData' => AboHelper::getMonthlyAboCounts($baseQuery, $selectedYear, 'ot', \Auth::user()->id),
|
||||
'chartYear' => $selectedYear,
|
||||
'chartYears' => \App\Services\HTMLHelper::getYearRange(2026),
|
||||
'chartMonths' => \App\Services\HTMLHelper::getTransMonths(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
200
app/Http/Controllers/User/IncentiveController.php
Normal file
200
app/Http/Controllers/User/IncentiveController.php
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Admin\IncentiveController as AdminIncentiveController;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Incentive;
|
||||
use App\Models\IncentiveParticipant;
|
||||
use App\Models\UserAbo;
|
||||
use App\Services\Incentive\IncentivePointsLogRepairService;
|
||||
use App\Services\Incentive\IncentiveTracker;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Request;
|
||||
|
||||
class IncentiveController extends Controller
|
||||
{
|
||||
/**
|
||||
* Anzahl Plaetze in der User-Live-Rangliste (Gewinner-Highlight bleibt ueber max_winners, typ. Top 20).
|
||||
*/
|
||||
public const USER_RANKING_DISPLAY_LIMIT = 30;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('active.account');
|
||||
}
|
||||
|
||||
public function teaser($slug)
|
||||
{
|
||||
$incentive = Incentive::where('slug', $slug)
|
||||
->where('status', '!=', 0)
|
||||
->firstOrFail();
|
||||
|
||||
$user = Auth::user();
|
||||
$participant = IncentiveParticipant::where('incentive_id', $incentive->id)
|
||||
->where('user_id', $user->id)
|
||||
->first();
|
||||
|
||||
$galleryImages = $this->collectGalleryImages($incentive);
|
||||
|
||||
return view('user.incentive.teaser', [
|
||||
'incentive' => $incentive,
|
||||
'participant' => $participant,
|
||||
'galleryImages' => $galleryImages,
|
||||
]);
|
||||
}
|
||||
|
||||
public function show($slug)
|
||||
{
|
||||
$incentive = Incentive::where('slug', $slug)
|
||||
->where('status', '!=', 0) // not draft
|
||||
->firstOrFail();
|
||||
|
||||
$user = Auth::user();
|
||||
$participant = IncentiveParticipant::where('incentive_id', $incentive->id)
|
||||
->where('user_id', $user->id)
|
||||
->first();
|
||||
|
||||
$ranking = IncentiveParticipant::where('incentive_id', $incentive->id)
|
||||
->withRankingActivity()
|
||||
->with('user', 'user.account')
|
||||
->orderByIncentiveLeaderboard()
|
||||
->limit(self::USER_RANKING_DISPLAY_LIMIT)
|
||||
->get();
|
||||
|
||||
$participateHasTrackableAbos = false;
|
||||
if (! $participant?->accepted_terms_at) {
|
||||
$participateHasTrackableAbos = $this->userHasTrackableAbosForIncentive($user, $incentive);
|
||||
}
|
||||
|
||||
return view('user.incentive.show', [
|
||||
'incentive' => $incentive,
|
||||
'participant' => $participant,
|
||||
'hasConfirmedParticipation' => $participant && $participant->accepted_terms_at !== null,
|
||||
'ranking' => $ranking,
|
||||
'rankingDisplayLimit' => self::USER_RANKING_DISPLAY_LIMIT,
|
||||
'participateHasTrackableAbos' => $participateHasTrackableAbos,
|
||||
]);
|
||||
}
|
||||
|
||||
public function participate($slug)
|
||||
{
|
||||
$incentive = Incentive::where('slug', $slug)
|
||||
->active()
|
||||
->firstOrFail();
|
||||
|
||||
if (! Request::has('accept_terms')) {
|
||||
\Session()->flash('alert-error', __('incentive.terms_required'));
|
||||
|
||||
return redirect(route('user_incentive_show', [$slug]));
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
$participant = IncentiveParticipant::firstOrCreate(
|
||||
[
|
||||
'incentive_id' => $incentive->id,
|
||||
'user_id' => $user->id,
|
||||
],
|
||||
[
|
||||
'accepted_terms_at' => null,
|
||||
]
|
||||
);
|
||||
|
||||
if ($participant->accepted_terms_at !== null) {
|
||||
\Session()->flash('alert-info', __('incentive.already_participating'));
|
||||
|
||||
return redirect(route('user_incentive_show', [$slug]));
|
||||
}
|
||||
|
||||
$participant->accepted_terms_at = Carbon::now();
|
||||
$participant->save();
|
||||
|
||||
$repair = app(IncentivePointsLogRepairService::class);
|
||||
$repair->syncMissingTrackingAbos($participant);
|
||||
$repair->syncMissingSalesVolumeLogs($participant);
|
||||
$participant->refresh()->recalculateFromTrackingTables()->save();
|
||||
IncentiveTracker::updateRanking($incentive);
|
||||
|
||||
\Session()->flash('alert-success', __('incentive.participation_confirmed'));
|
||||
|
||||
return redirect(route('user_incentive_show', [$slug]));
|
||||
}
|
||||
|
||||
public function details($slug)
|
||||
{
|
||||
$incentive = Incentive::where('slug', $slug)
|
||||
->where('status', '!=', 0)
|
||||
->firstOrFail();
|
||||
|
||||
$user = Auth::user();
|
||||
$participant = IncentiveParticipant::with('incentive', 'user', 'user.account')
|
||||
->where('incentive_id', $incentive->id)
|
||||
->where('user_id', $user->id)
|
||||
->firstOrFail();
|
||||
|
||||
if ($participant->accepted_terms_at === null) {
|
||||
\Session()->flash('alert-info', __('incentive.details_requires_confirmation'));
|
||||
|
||||
return redirect(route('user_incentive_show', [$slug]));
|
||||
}
|
||||
|
||||
$data = AdminIncentiveController::buildParticipantDetailData($participant);
|
||||
|
||||
return view('user.incentive.details', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sammelt alle verfuegbaren Galerie-Bilder aus public/img/incentive/
|
||||
* (ohne das Hauptbild, das bereits als Hero verwendet wird).
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function collectGalleryImages(Incentive $incentive): array
|
||||
{
|
||||
$dir = public_path('img/incentive');
|
||||
|
||||
if (! is_dir($dir)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$files = glob($dir . '/*.{jpg,jpeg,png,webp}', GLOB_BRACE) ?: [];
|
||||
|
||||
$images = [];
|
||||
foreach ($files as $file) {
|
||||
$basename = basename($file);
|
||||
$images[] = 'img/incentive/' . $basename;
|
||||
}
|
||||
sort($images);
|
||||
|
||||
return $images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hinweis auf der Teilnehmen-Karte: Es gibt bereits ein Eigenabo oder ein Kundenabo im Qualifikationszeitraum.
|
||||
*/
|
||||
private function userHasTrackableAbosForIncentive(User $user, Incentive $incentive): bool
|
||||
{
|
||||
$qualEnd = $incentive->qualification_end->copy()->endOfDay();
|
||||
|
||||
$hasOwnActiveAbo = UserAbo::query()
|
||||
->where('user_id', $user->id)
|
||||
->where('is_for', 'me')
|
||||
->where('status', 2)
|
||||
->exists();
|
||||
|
||||
$hasCustomerAboInQualification = UserAbo::query()
|
||||
->where('member_id', $user->id)
|
||||
->where('is_for', 'ot')
|
||||
->where('status', 2)
|
||||
->whereBetween('created_at', [
|
||||
$incentive->qualification_start,
|
||||
$qualEnd,
|
||||
])
|
||||
->exists();
|
||||
|
||||
return $hasOwnActiveAbo || $hasCustomerAboInQualification;
|
||||
}
|
||||
}
|
||||
|
|
@ -63,7 +63,6 @@ class MembershipController extends Controller
|
|||
if ($user->isActiveAccount() && ! $user->isActiveShop()) {
|
||||
$payment_greaterThan = Carbon::parse($user->payment_account)->modify('-'.(config('mivita.renewal_days') + 1).' days');
|
||||
$userHistoryUpgradeOrder = UserHistory::whereUserId($user->id)->whereAction('upgrade_order')->where('created_at', '>=', $payment_greaterThan)->get()->last();
|
||||
|
||||
}
|
||||
$userHistoryDeleteMembership = UserHistory::whereUserId($user->id)->whereAction('delete_membership')->whereStatus(50)->get()->last();
|
||||
|
||||
|
|
@ -87,7 +86,6 @@ class MembershipController extends Controller
|
|||
];
|
||||
|
||||
return view('user.membership.index', $data);
|
||||
|
||||
}
|
||||
|
||||
private function checkShoppingCountry($user)
|
||||
|
|
@ -158,8 +156,11 @@ class MembershipController extends Controller
|
|||
if ($product->images->count()) {
|
||||
$image = $product->images->first()->slug;
|
||||
}
|
||||
$qty = Request::get('qty') ? Request::get('qty') : 1;
|
||||
$qty = $product->is_membership_only ? 1 : (Request::get('qty') ? Request::get('qty') : 1);
|
||||
$cartItem = Yard::instance('shopping')->add($product->id, $product->getLang('name'), $qty, $product->getPriceWith(\App\Services\UserService::getTaxFree(), false, \App\Services\UserService::$user_country), false, false, ['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]);
|
||||
if ($cartItem->qty > 1) {
|
||||
Yard::instance('shopping')->update($cartItem->rowId, 1);
|
||||
}
|
||||
if (\App\Services\UserService::getTaxFree()) {
|
||||
Yard::setTax($cartItem->rowId, 0);
|
||||
} else {
|
||||
|
|
@ -214,7 +215,6 @@ class MembershipController extends Controller
|
|||
\Session()->flash('alert-success', __('msg.booked_package_has_been_changed'));
|
||||
|
||||
return back();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -236,11 +236,9 @@ class MembershipController extends Controller
|
|||
\Session()->flash('alert-error', __('msg.error_checkbox_not_confirm'));
|
||||
|
||||
return back();
|
||||
|
||||
}
|
||||
\Session()->flash('alert-error', __('msg.error_checkbox_not_confirm'));
|
||||
|
||||
return back();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use App\Services\AboHelper;
|
|||
use App\Services\MyLog;
|
||||
use App\Services\OrderPaymentService;
|
||||
use App\Services\Payment;
|
||||
use App\Services\ProductOrderContext;
|
||||
use App\Services\Shop;
|
||||
use App\Services\UserService;
|
||||
use App\Services\Util;
|
||||
|
|
@ -182,6 +183,16 @@ class OrderController extends Controller
|
|||
$delivery_id = $shopping_user->id;
|
||||
}
|
||||
|
||||
$isAbo = str_contains($for, 'abo');
|
||||
$previousFor = session('user_order_flow_for');
|
||||
if ($previousFor !== null && $previousFor !== $for) {
|
||||
$previousAbo = str_contains($previousFor, 'abo');
|
||||
if (ProductOrderContext::allowedShowOnIds($previousAbo, $previousFor) !== ProductOrderContext::allowedShowOnIds($isAbo, $for)) {
|
||||
Yard::instance('shopping')->destroy();
|
||||
}
|
||||
}
|
||||
session(['user_order_flow_for' => $for]);
|
||||
|
||||
if ($for === 'ot-customer' || $for === 'abo-ot-customer') {
|
||||
UserService::initCustomerYard($shopping_user, $for);
|
||||
} else {
|
||||
|
|
@ -262,7 +273,7 @@ class OrderController extends Controller
|
|||
// Prepare common data
|
||||
$data['is_from'] = 'user_order';
|
||||
$data['is_for'] = $for;
|
||||
$data['is_abo'] = $data['is_abo'] ?? 0;
|
||||
$data['is_abo'] = str_contains($for, 'abo');
|
||||
$data['abo_interval'] = $data['abo_interval'] ?? 0;
|
||||
$data['shopping_user_id'] = $id;
|
||||
$data['user_price_infos'] = Yard::instance('shopping')->getUserPriceInfos();
|
||||
|
|
@ -406,6 +417,17 @@ class OrderController extends Controller
|
|||
throw new \Exception(__('msg.shipping_country_was_not_correctly'));
|
||||
}
|
||||
|
||||
$isAbo = str_contains($data['shipping_is_for'], 'abo');
|
||||
foreach (Yard::instance('shopping')->content() as $row) {
|
||||
$product = Product::find($row->id);
|
||||
if (! $product) {
|
||||
continue;
|
||||
}
|
||||
if (! ProductOrderContext::isProductAllowedInContext($product, $isAbo, $data['shipping_is_for'])) {
|
||||
throw new \Exception(__('msg.cart_product_not_allowed_for_order_type'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($data['shipping_is_for'] !== 'ot-customer') {
|
||||
if (Yard::instance('shopping')->shipping_free) {
|
||||
$identifier = 'error-'.time().mt_rand(1000000, 9999999);
|
||||
|
|
@ -748,6 +770,15 @@ class OrderController extends Controller
|
|||
return response()->json(['response' => false, 'message' => 'Product not found']);
|
||||
}
|
||||
|
||||
$isAbo = str_contains($is_for, 'abo');
|
||||
$qty = isset($data['qty']) ? (int) $data['qty'] : 0;
|
||||
if ($qty > 0 && ! ProductOrderContext::isProductAllowedInContext($product, $isAbo, $is_for)) {
|
||||
return response()->json([
|
||||
'response' => false,
|
||||
'message' => __('msg.cart_product_not_allowed_for_order_type'),
|
||||
]);
|
||||
}
|
||||
|
||||
$image = '';
|
||||
if ($product->images->count()) {
|
||||
$image = $product->images->first()->slug;
|
||||
|
|
|
|||
|
|
@ -713,9 +713,13 @@ class TeamController extends Controller
|
|||
// Hole Team-Mitglieder-IDs effizient via Sponsor-Hierarchie
|
||||
$teamUserIds = AboHelper::getTeamUserIds($user->id);
|
||||
|
||||
// Hole Abos der Team-Mitglieder
|
||||
$abos = \App\Models\UserAbo::whereIn('user_id', $teamUserIds)
|
||||
$selectedYear = (int) Request::get('year', now()->year);
|
||||
$baseQuery = \App\Models\UserAbo::whereIn('user_id', $teamUserIds)
|
||||
->where('is_for', 'me')
|
||||
->where('status', '>', 1);
|
||||
|
||||
// Hole Abos der Team-Mitglieder
|
||||
$abos = (clone $baseQuery)
|
||||
->with(['user', 'user.account', 'user_abo_items', 'user_abo_items.product'])
|
||||
->orderBy('next_date', 'asc')
|
||||
->get();
|
||||
|
|
@ -724,11 +728,45 @@ class TeamController extends Controller
|
|||
'filter_months' => HTMLHelper::getTransMonths(),
|
||||
'filter_years' => HTMLHelper::getYearRange(2022),
|
||||
'abos' => $abos,
|
||||
'chartData' => AboHelper::getMonthlyAboCounts($baseQuery, $selectedYear, 'team_abos', $user->id),
|
||||
'chartYear' => $selectedYear,
|
||||
'chartYears' => HTMLHelper::getYearRange(2026),
|
||||
'chartMonths' => HTMLHelper::getTransMonths(),
|
||||
];
|
||||
|
||||
return view('user.team.abos', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt eine Übersicht der Kunden-Abos aller Team-Mitglieder (anonymisiert)
|
||||
*/
|
||||
public function showTeamCustomerAbos(): \Illuminate\View\View
|
||||
{
|
||||
$user = User::find(\Auth::user()->id);
|
||||
$teamUserIds = AboHelper::getTeamUserIds($user->id);
|
||||
|
||||
$selectedYear = (int) Request::get('year', now()->year);
|
||||
$baseQuery = \App\Models\UserAbo::whereIn('member_id', $teamUserIds)
|
||||
->where('is_for', 'ot')
|
||||
->where('status', '>', 1);
|
||||
|
||||
$abos = (clone $baseQuery)
|
||||
->with(['member', 'member.account', 'user_abo_items', 'user_abo_items.product'])
|
||||
->orderBy('member_id')
|
||||
->orderBy('next_date', 'asc')
|
||||
->get();
|
||||
|
||||
$groupedByMember = $abos->groupBy('member_id');
|
||||
|
||||
return view('user.team.customer_abos', [
|
||||
'groupedByMember' => $groupedByMember,
|
||||
'chartData' => AboHelper::getMonthlyAboCounts($baseQuery, $selectedYear, 'team_cust_abos', $user->id),
|
||||
'chartYear' => $selectedYear,
|
||||
'chartYears' => HTMLHelper::getYearRange(2026),
|
||||
'chartMonths' => HTMLHelper::getTransMonths(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt die Detail-Ansicht eines Team-Abos an
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,46 +2,49 @@
|
|||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
|
||||
use Yard;
|
||||
use Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Product;
|
||||
use App\Models\ShoppingInstance;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Services\ProductOrderContext;
|
||||
use App\Services\Shop;
|
||||
use App\Services\Util;
|
||||
use App\Models\Product;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\ShoppingInstance;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Request;
|
||||
use Yard;
|
||||
|
||||
class CardController extends Controller
|
||||
{
|
||||
private $instance = 'webshop';
|
||||
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
public function __construct() {}
|
||||
|
||||
|
||||
|
||||
//Cart::instance('wishlist')->add('sdjk922', 'Product 2', 1, 19.95, ['size' => 'medium']);
|
||||
// Cart::instance('wishlist')->add('sdjk922', 'Product 2', 1, 19.95, ['size' => 'medium']);
|
||||
public function addToCardGet($id, $quantity = 1, $product_slug = false)
|
||||
{
|
||||
$product = Product::find($id);
|
||||
if($product){
|
||||
$image = "";
|
||||
if($product->images->count()){
|
||||
if ($product && ProductOrderContext::isProductAllowedInCustomerWebshop($product)) {
|
||||
$image = '';
|
||||
if ($product->images->count()) {
|
||||
$image = $product->images->first()->slug;
|
||||
}
|
||||
$cartItem = Yard::instance($this->instance)
|
||||
->add($product->id, $product->getLang('name'), $quantity,
|
||||
$product->getPriceWith(Yard::instance($this->instance)->getUserTaxFree(), false, Yard::instance($this->instance)->getUserCountry()), false, false,
|
||||
['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]);
|
||||
if(Yard::instance($this->instance)->getUserTaxFree()){
|
||||
->add(
|
||||
$product->id,
|
||||
$product->getLang('name'),
|
||||
$quantity,
|
||||
$product->getPriceWith(Yard::instance($this->instance)->getUserTaxFree(), false, Yard::instance($this->instance)->getUserCountry()),
|
||||
false,
|
||||
false,
|
||||
['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]
|
||||
);
|
||||
if (Yard::instance($this->instance)->getUserTaxFree()) {
|
||||
Yard::setTax($cartItem->rowId, 0);
|
||||
}else{
|
||||
} else {
|
||||
Yard::setTax($cartItem->rowId, $product->getTaxWith(Yard::instance($this->instance)->getUserCountry()));
|
||||
}
|
||||
Yard::instance($this->instance)->reCalculateShippingPrice();
|
||||
|
|
@ -50,7 +53,6 @@ class CardController extends Controller
|
|||
}
|
||||
|
||||
return back();
|
||||
|
||||
}
|
||||
|
||||
public function addToCardPost($id)
|
||||
|
|
@ -58,39 +60,45 @@ class CardController extends Controller
|
|||
|
||||
$product = Product::find($id);
|
||||
|
||||
if($product){
|
||||
$image = "";
|
||||
if($product->images->count()){
|
||||
if ($product && ProductOrderContext::isProductAllowedInCustomerWebshop($product)) {
|
||||
$image = '';
|
||||
if ($product->images->count()) {
|
||||
$image = $product->images->first()->slug;
|
||||
}
|
||||
$quantity = Request::get('quantity') ? Request::get('quantity') : 1;
|
||||
$cartItem = Yard::instance($this->instance)
|
||||
->add($product->id, $product->getLang('name'), $quantity,
|
||||
$product->getPriceWith(Yard::instance($this->instance)->getUserTaxFree(), false, Yard::instance($this->instance)->getUserCountry()), false, false,
|
||||
['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]);
|
||||
if(Yard::instance($this->instance)->getUserTaxFree()){
|
||||
->add(
|
||||
$product->id,
|
||||
$product->getLang('name'),
|
||||
$quantity,
|
||||
$product->getPriceWith(Yard::instance($this->instance)->getUserTaxFree(), false, Yard::instance($this->instance)->getUserCountry()),
|
||||
false,
|
||||
false,
|
||||
['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on]
|
||||
);
|
||||
if (Yard::instance($this->instance)->getUserTaxFree()) {
|
||||
Yard::setTax($cartItem->rowId, 0);
|
||||
}else{
|
||||
} else {
|
||||
Yard::setTax($cartItem->rowId, $product->getTaxWith(Yard::instance($this->instance)->getUserCountry()));
|
||||
}
|
||||
Yard::instance($this->instance)->reCalculateShippingPrice();
|
||||
|
||||
\Session()->flash('show-card-after-add', true);
|
||||
}
|
||||
|
||||
return back();
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function showCard(){
|
||||
public function showCard()
|
||||
{
|
||||
|
||||
if(Request::get('selected_country')){
|
||||
if (Request::get('selected_country')) {
|
||||
Yard::instance($this->instance)->setShippingCountryWithPrice(Request::get('selected_country'));
|
||||
}else{
|
||||
} else {
|
||||
Yard::instance($this->instance)->reCalculateShippingPrice();
|
||||
}
|
||||
|
||||
//show konflikt wenn user eingeloggt ist und country nicht gesetzt ist
|
||||
// show konflikt wenn user eingeloggt ist und country nicht gesetzt ist
|
||||
$shipping_error = $this->checkShippingError();
|
||||
$data = [
|
||||
'user_shop' => Util::getUserShop(),
|
||||
|
|
@ -98,30 +106,49 @@ class CardController extends Controller
|
|||
'yard_instance' => $this->instance,
|
||||
'shipping_error' => $shipping_error ?? false,
|
||||
];
|
||||
|
||||
return view('web.templates.card', $data);
|
||||
}
|
||||
|
||||
public function updateCard(){
|
||||
public function updateCard()
|
||||
{
|
||||
|
||||
$data = Request::all();
|
||||
if(isset($data['quantity'])){
|
||||
foreach ($data['quantity'] as $rowId => $qty){
|
||||
if (isset($data['quantity'])) {
|
||||
foreach ($data['quantity'] as $rowId => $qty) {
|
||||
$cartItem = Yard::instance($this->instance)->get($rowId);
|
||||
if ($cartItem) {
|
||||
$product = Product::find($cartItem->id);
|
||||
if ($product && $product->is_membership_only) {
|
||||
$qty = 1;
|
||||
}
|
||||
}
|
||||
Yard::instance($this->instance)->update($rowId, $qty);
|
||||
Yard::instance($this->instance)->reCalculateShippingPrice();
|
||||
}
|
||||
}else{
|
||||
$this->deleteCard();
|
||||
} else {
|
||||
$this->deleteCard();
|
||||
}
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
public function checkoutServer(){
|
||||
|
||||
public function checkoutServer()
|
||||
{
|
||||
foreach (Yard::instance($this->instance)->content() as $row) {
|
||||
$product = Product::find($row->id);
|
||||
if (! $product || ! ProductOrderContext::isProductAllowedInCustomerWebshop($product)) {
|
||||
\Session::flash('alert-error', __('msg.cart_product_not_allowed_for_order_type'));
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
}
|
||||
|
||||
$user_shop = Util::getUserShop();
|
||||
|
||||
|
||||
do {
|
||||
$identifier = Util::getToken();
|
||||
} while( ShoppingInstance::where('identifier', $identifier)->count() );
|
||||
} while (ShoppingInstance::where('identifier', $identifier)->count());
|
||||
|
||||
$data = [];
|
||||
$data['is_from'] = 'shopping';
|
||||
|
|
@ -130,7 +157,7 @@ class CardController extends Controller
|
|||
ShoppingInstance::create([
|
||||
'identifier' => $identifier,
|
||||
'user_shop_id' => $user_shop->id,
|
||||
'payment' => 1, //Customer Shop Payment
|
||||
'payment' => 1, // Customer Shop Payment
|
||||
'subdomain' => url('/'),
|
||||
'country_id' => Yard::instance($this->instance)->getShippingCountryId(),
|
||||
'language' => \App::getLocale(),
|
||||
|
|
@ -138,55 +165,63 @@ class CardController extends Controller
|
|||
'back' => url()->previous(),
|
||||
|
||||
]);
|
||||
|
||||
|
||||
Yard::instance($this->instance)->store($identifier);
|
||||
//add to DB
|
||||
$path = route('checkout.checkout_card', ['identifier'=>$identifier]);
|
||||
if(strpos($path, 'https') === false){
|
||||
// add to DB
|
||||
$path = route('checkout.checkout_card', ['identifier' => $identifier]);
|
||||
if (strpos($path, 'https') === false) {
|
||||
$path = str_replace('http', 'https', $path);
|
||||
}
|
||||
|
||||
return redirect()->secure($path);
|
||||
}
|
||||
|
||||
public function backToShop(){
|
||||
public function backToShop()
|
||||
{
|
||||
$this->deleteCard();
|
||||
return redirect(url('/'));
|
||||
|
||||
return redirect(url('/'));
|
||||
}
|
||||
public function removeCard($rowId){
|
||||
|
||||
public function removeCard($rowId)
|
||||
{
|
||||
|
||||
Yard::instance($this->instance)->remove($rowId);
|
||||
|
||||
return back();
|
||||
}
|
||||
|
||||
public function deleteCard(){
|
||||
public function deleteCard()
|
||||
{
|
||||
|
||||
$setCode = Shop::getUserShopLang(null, $this->instance);
|
||||
$mylangs = Shop::getLangChange($this->instance);
|
||||
foreach($mylangs as $code => $country){
|
||||
if(strtolower($setCode) === strtolower($code)){
|
||||
foreach ($mylangs as $code => $country) {
|
||||
if (strtolower($setCode) === strtolower($code)) {
|
||||
Shop::initUserShopLang($country, $this->instance);
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function checkShippingError(){
|
||||
private function checkShippingError()
|
||||
{
|
||||
$shipping_error = false;
|
||||
if(\Auth::guard('customers')->check()){
|
||||
if (\Auth::guard('customers')->check()) {
|
||||
$user = \Auth::guard('customers')->user();
|
||||
if($user->shopping_user_id){
|
||||
if ($user->shopping_user_id) {
|
||||
$shopping_user = ShoppingUser::find($user->shopping_user_id);
|
||||
if($shopping_user->same_as_billing){
|
||||
if($shopping_user->billing_country_id != Yard::instance($this->instance)->getUserCountryId()){
|
||||
if ($shopping_user->same_as_billing) {
|
||||
if ($shopping_user->billing_country_id != Yard::instance($this->instance)->getUserCountryId()) {
|
||||
$user_country = Yard::instance($this->instance)->getUserCountry();
|
||||
$user_country_name = $user_country ? $user_country->getLocated() : '';
|
||||
$billing_country = $shopping_user->billing_country;
|
||||
$country_name = $billing_country ? $billing_country->getLocated() : '';
|
||||
$shipping_error = __('website.shipping_error_billing', ['shipping_country' => $user_country_name, 'billing_country' => $country_name]);
|
||||
}
|
||||
}else{
|
||||
if($shopping_user->shipping_country_id != Yard::instance($this->instance)->getUserCountryId()){
|
||||
} else {
|
||||
if ($shopping_user->shipping_country_id != Yard::instance($this->instance)->getUserCountryId()) {
|
||||
$user_country = Yard::instance($this->instance)->getUserCountry();
|
||||
$user_country_name = $user_country ? $user_country->getLocated() : '';
|
||||
$shipping_country = $shopping_user->shipping_country;
|
||||
|
|
@ -194,9 +229,9 @@ class CardController extends Controller
|
|||
$shipping_error = __('website.shipping_error_delivery', ['shipping_country' => $user_country_name, 'billing_country' => $country_name]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $shipping_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,26 +2,24 @@
|
|||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
|
||||
use Yard;
|
||||
use Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Category;
|
||||
use App\Models\IqSite;
|
||||
use App\Models\Product;
|
||||
use App\Models\ProductCategory;
|
||||
use App\Services\LocaleGuard;
|
||||
use App\Services\Shop;
|
||||
use App\Services\Util;
|
||||
use App\Models\Product;
|
||||
use App\Models\Category;
|
||||
use App\Models\ProductCategory;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Request;
|
||||
|
||||
class SiteController extends Controller
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
$this->setIPInfo();
|
||||
$products = ['aloe-vera-gel-99', 'aloe-vera-saft-500-ml', 'aloe-vera-lippenbalsam'];
|
||||
// $set_products = ['aloe-vera-cleaner-set', 'aloe-vera-koerper-set', 'aloe-vera-repair-set'];
|
||||
$set_products = ['aloe-vera-koerper-set', 'baby-set', 'aloe-vera-gel-set'];
|
||||
$set_products = ['aloe-vera-koerper-set', 'baby-set', 'aloe-vera-gel-set'];
|
||||
$data = [
|
||||
'products' => Product::whereIn('slug', $products)->where('active', true)->whereJsonContains('show_on', '1')->get(),
|
||||
'set_products' => Product::whereIn('slug', $set_products)->where('active', true)->whereJsonContains('show_on', '1')->get(),
|
||||
|
|
@ -34,9 +32,9 @@ class SiteController extends Controller
|
|||
return view('web.index', $data);
|
||||
}
|
||||
|
||||
public function domainCheck()
|
||||
public function domainCheck()
|
||||
{
|
||||
die("checked");
|
||||
exit('checked');
|
||||
}
|
||||
|
||||
public function changeLang()
|
||||
|
|
@ -48,8 +46,12 @@ class SiteController extends Controller
|
|||
if (strtolower($data['change_country_id']) === strtolower($code)) {
|
||||
\Session::put('user_init_country', strtolower($code));
|
||||
\Session::forget('user_init_country_options');
|
||||
\Session::put('locale', strtolower($data['change_locale_id']));
|
||||
$locale = LocaleGuard::normalize($data['change_locale_id'] ?? null);
|
||||
if ($locale !== null) {
|
||||
\Session::put('locale', $locale);
|
||||
}
|
||||
Shop::initUserShopLang($country, 'webshop');
|
||||
|
||||
return back();
|
||||
}
|
||||
}
|
||||
|
|
@ -58,40 +60,41 @@ class SiteController extends Controller
|
|||
|
||||
private function setIPinfo()
|
||||
{
|
||||
//wurde schon gesetzt //cache
|
||||
// wurde schon gesetzt //cache
|
||||
$country = strtolower(Shop::getIPDatabaseInfo());
|
||||
if (\Session::has('user_init_country')) {
|
||||
return;
|
||||
}
|
||||
if (config('app.ipinfo')) {
|
||||
$country = strtolower(Shop::getIPDatabaseInfo());
|
||||
if ($country === 'de') { //$locale de - init AT
|
||||
if ($country === 'de') { // $locale de - init AT
|
||||
\Session::put('user_init_country', $country);
|
||||
|
||||
return;
|
||||
}
|
||||
if ($country === 'error') { //$locale at - init AT
|
||||
if ($country === 'error') { // $locale at - init AT
|
||||
$country = 'de';
|
||||
}
|
||||
} else {
|
||||
$country = 'de';
|
||||
}
|
||||
|
||||
//$locale = strtolower(\App::getLocale());
|
||||
//ist default
|
||||
// $locale = strtolower(\App::getLocale());
|
||||
// ist default
|
||||
|
||||
//sprache
|
||||
// sprache
|
||||
if (array_key_exists($country, \App\Services\UserService::getTransChange())) {
|
||||
\Session::put('user_init_country', $country);
|
||||
\Session::put('locale', $country);
|
||||
\App::setLocale($country);
|
||||
} else {
|
||||
//default EN
|
||||
// default EN
|
||||
\Session::put('user_init_country', 'de');
|
||||
\Session::put('locale', 'de');
|
||||
\App::setLocale('de');
|
||||
}
|
||||
|
||||
//bestelland / versandland
|
||||
// bestelland / versandland
|
||||
if (array_key_exists($country, Shop::getLangChange('webshop'))) {
|
||||
\Session::put('user_init_country_options', $country);
|
||||
} else {
|
||||
|
|
@ -119,6 +122,7 @@ class SiteController extends Controller
|
|||
'p_count' => Product::where('active', true)->whereJsonContains('show_on', '1')->count(),
|
||||
'yard_instance' => 'webshop',
|
||||
];
|
||||
|
||||
return view('web.templates.produkte-show', $data);
|
||||
}
|
||||
}
|
||||
|
|
@ -131,7 +135,7 @@ class SiteController extends Controller
|
|||
$headline_image = $category->iq_image;
|
||||
}
|
||||
|
||||
$product_categories = ProductCategory::where('category_id', $category->id)->whereHas('product', function ($query) use ($category) {
|
||||
$product_categories = ProductCategory::where('category_id', $category->id)->whereHas('product', function ($query) {
|
||||
$query->where('active', true)->whereJsonContains('show_on', '1');
|
||||
})->orderBy('pos', 'DESC')->get();
|
||||
|
||||
|
|
@ -147,7 +151,8 @@ class SiteController extends Controller
|
|||
'headline_image' => $headline_image,
|
||||
'yard_instance' => 'webshop',
|
||||
];
|
||||
return view('web.templates.' . $site, $data);
|
||||
|
||||
return view('web.templates.'.$site, $data);
|
||||
}
|
||||
}
|
||||
dd($subsite);
|
||||
|
|
@ -163,7 +168,8 @@ class SiteController extends Controller
|
|||
'headline_image' => false,
|
||||
'yard_instance' => 'webshop',
|
||||
];
|
||||
return view('web.templates.' . $site, $data);
|
||||
|
||||
return view('web.templates.'.$site, $data);
|
||||
}
|
||||
$data = [
|
||||
'user_shop' => Util::getUserShop(),
|
||||
|
|
@ -171,14 +177,16 @@ class SiteController extends Controller
|
|||
'yard_instance' => 'webshop',
|
||||
];
|
||||
if ($subsite) {
|
||||
if (!view()->exists('web.templates.' . $subsite)) {
|
||||
if (! view()->exists('web.templates.'.$subsite)) {
|
||||
abort(404);
|
||||
}
|
||||
return view('web.templates.' . $subsite, $data);
|
||||
|
||||
return view('web.templates.'.$subsite, $data);
|
||||
}
|
||||
if (!view()->exists('web.templates.' . $site)) {
|
||||
if (! view()->exists('web.templates.'.$site)) {
|
||||
abort(404);
|
||||
}
|
||||
return view('web.templates.' . $site, $data);
|
||||
|
||||
return view('web.templates.'.$site, $data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -605,6 +605,9 @@ class WizardController extends Controller
|
|||
$image = $product->images->first()->slug;
|
||||
}
|
||||
$cartItem = Yard::instance('shopping')->add($product->id, $product->getLang('name'), 1, $product->getPriceWith(\App\Services\UserService::getTaxFree(), false, \App\Services\UserService::$user_country), false, false, ['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'free_shipping_consultant' => $product->free_shipping_consultant, 'show_on' => $product->show_on]);
|
||||
if ($cartItem->qty > 1) {
|
||||
Yard::instance('shopping')->update($cartItem->rowId, 1);
|
||||
}
|
||||
if (\App\Services\UserService::getTaxFree()) {
|
||||
Yard::setTax($cartItem->rowId, 0);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2,29 +2,37 @@
|
|||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Carbon;
|
||||
use App\Services\LocaleGuard;
|
||||
use Closure;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
class Localization
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
* Session locale must be validated: arbitrary strings break Symfony/Carbon
|
||||
* (e.g. scanner payloads stored as "locale").
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next): mixed
|
||||
{
|
||||
if (\Session::has('locale')) {
|
||||
\App::setLocale(\Session::get('locale'));
|
||||
// Carbon::setLocale('\Session::get('locale')');
|
||||
//Carbon::setLocale('de');
|
||||
if (! Session::has('locale')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$raw = Session::get('locale');
|
||||
$normalized = LocaleGuard::normalize(is_string($raw) ? $raw : null);
|
||||
|
||||
if ($normalized !== null) {
|
||||
App::setLocale($normalized);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
Session::forget('locale');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue