'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));
}
}