'paymend_paid', 'appointed' => 'paymend_open', 'failed' => 'paymend_failed', 'extern' => 'extern_open', // offen 'extern_paid' => 'extern_paid', 'invoice_open' => 'invoice_open', 'invoice_paid' => 'invoice_paid', 'invoice_non' => 'invoice_no_payment', 'NULL' => 'no_payment', ]; public static function userHasAbo(User $user) { $user = $user ? $user : \Auth::user(); return UserAbo::where('user_id', $user->id)->where('is_for', 'me')->where('status', '>', 1)->first() === null ? false : true; } public static function memberHasAbo(ShoppingUser $shopping_user) { if (! $shopping_user) { return false; } return UserAbo::where('email', $shopping_user->billing_email)->where('is_for', 'ot')->where('status', '>', 1)->first() === null ? false : true; } public static function hasAboByEmail($email) { return UserAbo::where('email', $email)->where('status', '>', 1)->first() === null ? false : true; } public static function setAboStatus(ShoppingOrder $shopping_order, $status, $paid = false) { $user_abo = $shopping_order->getUserAbo(); if ($user_abo && $user_abo->status < 2) { // status < 2 is not active $user_abo->update(['status' => $status]); } UserAboOrder::where('user_abo_id', $user_abo->id)->where('shopping_order_id', $shopping_order->id)->update(['status' => $status, 'paid' => $paid]); } public static function setAboActive(ShoppingOrder $shopping_order, $status, $paid = false) { self::setAboStatus($shopping_order, $status, $paid); // delete UserAbo is not active status = 1 // is_for = me UserAbo::where('user_id', $shopping_order->auth_user_id)->where('is_for', 'me')->where('status', 1)->delete(); // is_for = ot UserAbo::where('member_id', $shopping_order->member_id)->where('email', $shopping_order->shopping_user->billing_email)->where('is_for', 'ot')->where('status', 1)->delete(); } public static function getAboMinDuration() { return \App\Models\Setting::getContentBySlug('abo-min-duration'); } public static function canCancelAbo(UserAbo $user_abo, $view = 'user') { $minDuration = self::getAboMinDuration(); if ($view === 'admin') { return true; } $paidOrdersCount = $user_abo->getCountPaidOrders(); return $paidOrdersCount >= (int) $minDuration; } public static function isAddOnlyMode(UserAbo $user_abo, $view = 'user'): bool { if ($view === 'admin') { return false; } return ! self::canCancelAbo($user_abo, $view); } public static function canEditAbo($user_abo, $view = 'user') { if ($view === 'portal') { return true; } $user = \Auth::user(); if ($view !== 'admin' && (! $user || ($user_abo->user_id != $user->id && $user_abo->member_id != $user->id))) { return false; } return true; } public static function aboHasBaseProduct($yard_products) { foreach ($yard_products as $product) { if (is_array($product->options->show_on)) { if (in_array('12', $product->options->show_on)) { return true; } } } return false; } public static function getAboShowOn(Product $product) { $show_on = $product->show_on; if (in_array('12', $show_on)) { return 'base'; } if (in_array('13', $show_on)) { return 'upgrade'; } return false; } public static function getAboTypeBadge($abo_type) { if ($abo_type === 'base') { return ' '.__('abo.'.$abo_type).''; } if ($abo_type === 'upgrade') { return ' '.__('abo.'.$abo_type).''; } return ''; } public static function setNextDate($date, $abo_interval) { $nextDate = Carbon::parse($date)->firstOfMonth(); $nextDate->addDays($abo_interval - 1); return $nextDate->gt($date) ? $nextDate : $nextDate->addMonth(1); } public static function getFirstAboDate($date, $abo_interval) { $nextDate = Carbon::parse($date)->firstOfMonth()->addMonth(1); $nextDate->addDays($abo_interval - 1); return $nextDate->gt($date) ? $nextDate : $nextDate->addMonth(1); } public static function createNewAbo(ShoppingPayment $shopping_payment) { // is Abo - create init Abo from PP or else if ($shopping_payment->shopping_order->is_abo && $shopping_payment->shopping_order->abo_interval > 0) { $payment_transaction = $shopping_payment->payment_transactions->last(); // next_date immer im nächsten Monat starten // is auth_user_id = Berater bestellung // is member_id = Kunden bestellung // is for = me = mich oder ot = kunde $user_abo = UserAbo::create([ 'user_id' => $shopping_payment->shopping_order->auth_user_id, 'member_id' => $shopping_payment->shopping_order->member_id, 'shopping_user_id' => $shopping_payment->shopping_order->shopping_user_id, 'email' => $shopping_payment->shopping_order->shopping_user->billing_email, 'is_for' => $shopping_payment->shopping_order->shopping_user->is_for, 'payone_userid' => $payment_transaction->userid, 'clearingtype' => $shopping_payment->clearingtype, 'wallettype' => $shopping_payment->wallettype, 'carddata' => $shopping_payment->carddata, 'amount' => $shopping_payment->amount, 'status' => 1, 'abo_interval' => $shopping_payment->abo_interval, 'start_date' => now(), 'last_date' => now(), 'next_date' => self::getFirstAboDate(now(), $shopping_payment->abo_interval), ]); if ($user_abo) { self::createAboItems($user_abo, $shopping_payment); UserAboOrder::create([ 'user_abo_id' => $user_abo->id, 'shopping_order_id' => $shopping_payment->shopping_order_id, 'status' => 1, ]); } } } public static function createAboItems($user_abo, ShoppingPayment $shopping_payment) { foreach ($shopping_payment->shopping_order->shopping_order_items as $item) { UserAboItem::create([ 'user_abo_id' => $user_abo->id, 'product_id' => $item->product_id, 'comp' => $item->comp ?? 0, 'qty' => $item->qty, 'status' => 1, ]); } $user_abo->load('user_abo_items'); AboItemHistoryService::logInitialCreation($user_abo, 'system'); } public static function getTransStatusFilterText() { $ret = []; foreach (self::$txaction_filter_text as $key => $val) { $ret[$key] = trans('payment.'.$val); } return $ret; } /** * Prüft effizient, ob ein User im Team eines anderen Users ist (Downline). * Traversiert die Sponsor-Hierarchie rekursiv (m_sponsor) statt die komplette * TreeCalcBot-Struktur aufzubauen. * * @param int $teamOwnerId ID des Team-Users (Berechtigter) * @param int $userToCheckId ID des zu prüfenden Users (z.B. Abo-Besitzer) * @param int $maxDepth Max. Tiefe (Schutz vor zirkulären Referenzen) * @return bool True wenn userToCheckId im Team von teamOwnerId ist */ public static function isUserInTeam(int $teamOwnerId, int $userToCheckId, int $maxDepth = 100): bool { if ($teamOwnerId === $userToCheckId) { return true; } $currentId = $userToCheckId; $depth = 0; while ($depth < $maxDepth) { $currentUser = User::where('id', $currentId)->select('m_sponsor')->first(); if (! $currentUser || ! $currentUser->m_sponsor) { return false; } if ($currentUser->m_sponsor === $teamOwnerId) { return true; } $currentId = $currentUser->m_sponsor; $depth++; } return false; } /** * Liefert alle User-IDs im Team (Downline) eines Users. * Traversiert die Sponsor-Hierarchie rekursiv nach unten statt TreeCalcBot. * * @param int $teamOwnerId ID des Team-Users * @param int $maxDepth Max. Tiefe (Schutz vor Endlosschleifen) * @return int[] */ public static function getTeamUserIds(int $teamOwnerId, int $maxDepth = 50): array { $teamUserIds = []; $toProcess = [$teamOwnerId]; $depth = 0; while (! empty($toProcess) && $depth < $maxDepth) { $children = User::whereIn('m_sponsor', $toProcess) ->whereNull('deleted_at') ->pluck('id') ->toArray(); $teamUserIds = array_merge($teamUserIds, $children); $toProcess = $children; $depth++; } return array_values(array_unique($teamUserIds)); } }