20-02-2026
This commit is contained in:
parent
a8b395e20d
commit
a00c42e770
252 changed files with 28785 additions and 8907 deletions
|
|
@ -3,25 +3,22 @@
|
|||
namespace App\Services;
|
||||
|
||||
use App\Models\Product;
|
||||
use Yard;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
use App\Models\UserAbo;
|
||||
use App\Models\UserAboItem;
|
||||
use App\Models\UserAboOrder;
|
||||
use App\Models\ShoppingOrder;
|
||||
use App\Models\ShoppingPayment;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\UserAbo;
|
||||
use App\Models\UserAboItem;
|
||||
use App\Models\UserAboOrder;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class AboHelper
|
||||
{
|
||||
|
||||
|
||||
public static $txaction_filter_text = [
|
||||
'paid' => 'paymend_paid',
|
||||
'appointed' => 'paymend_open',
|
||||
'failed' => 'paymend_failed',
|
||||
'extern' => 'extern_open', //offen
|
||||
'extern' => 'extern_open', // offen
|
||||
'extern_paid' => 'extern_paid',
|
||||
'invoice_open' => 'invoice_open',
|
||||
'invoice_paid' => 'invoice_paid',
|
||||
|
|
@ -29,18 +26,19 @@ class AboHelper
|
|||
'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) {
|
||||
if (! $shopping_user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return UserAbo::where('email', $shopping_user->billing_email)->where('is_for', 'ot')->where('status', '>', 1)->first() === null ? false : true;
|
||||
}
|
||||
|
||||
|
|
@ -52,19 +50,20 @@ class AboHelper
|
|||
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
|
||||
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
|
||||
// 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
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
|
@ -80,14 +79,29 @@ class AboHelper
|
|||
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 !== 'admin' && ($user_abo->user_id != \Auth::user()->id && $user_abo->member_id != \Auth::user()->id)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -100,8 +114,10 @@ class AboHelper
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getAboShowOn(Product $product)
|
||||
{
|
||||
$show_on = $product->show_on;
|
||||
|
|
@ -111,16 +127,19 @@ class AboHelper
|
|||
if (in_array('13', $show_on)) {
|
||||
return 'upgrade';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function getAboTypeBadge($abo_type)
|
||||
{
|
||||
if ($abo_type === 'base') {
|
||||
return '<span class="badge badge-pill badge-warning"><i class="fas fa-star"></i> ' . __('abo.' . $abo_type) . '</span></a>';
|
||||
return '<span class="badge badge-pill badge-warning"><i class="fas fa-star"></i> '.__('abo.'.$abo_type).'</span></a>';
|
||||
}
|
||||
if ($abo_type === 'upgrade') {
|
||||
return '<span class="badge badge-pill badge-info"><i class="far fa-star"></i> ' . __('abo.' . $abo_type) . '</span></a>';
|
||||
return '<span class="badge badge-pill badge-info"><i class="far fa-star"></i> '.__('abo.'.$abo_type).'</span></a>';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +147,7 @@ class AboHelper
|
|||
{
|
||||
$nextDate = Carbon::parse($date)->firstOfMonth();
|
||||
$nextDate->addDays($abo_interval - 1);
|
||||
|
||||
return $nextDate->gt($date) ? $nextDate : $nextDate->addMonth(1);
|
||||
}
|
||||
|
||||
|
|
@ -135,19 +155,20 @@ class AboHelper
|
|||
{
|
||||
$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
|
||||
// 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
|
||||
// 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,
|
||||
|
|
@ -188,15 +209,82 @@ class AboHelper
|
|||
'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);
|
||||
$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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
361
app/Services/AboItemHistoryService.php
Normal file
361
app/Services/AboItemHistoryService.php
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Product;
|
||||
use App\Models\UserAbo;
|
||||
use App\Models\UserAboItem;
|
||||
use App\Models\UserAboItemHistory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class AboItemHistoryService
|
||||
{
|
||||
/**
|
||||
* Log alle Items eines neu erstellten Abos als initial-Einträge.
|
||||
*/
|
||||
public static function logInitialCreation(UserAbo $userAbo, string $channel = 'system'): void
|
||||
{
|
||||
$batchId = Str::uuid()->toString();
|
||||
$actor = self::resolveActor();
|
||||
|
||||
foreach ($userAbo->user_abo_items as $item) {
|
||||
$product = $item->product;
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $product->id,
|
||||
'action' => UserAboItemHistory::ACTION_INITIAL,
|
||||
'product_name' => $product->getLang('name'),
|
||||
'product_number' => $product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'qty_before' => null,
|
||||
'qty_after' => $item->qty,
|
||||
'comp' => $item->comp ?? 0,
|
||||
'changed_by_user_id' => $actor['id'],
|
||||
'changed_by_name' => $actor['name'],
|
||||
'channel' => $channel,
|
||||
'batch_id' => $batchId,
|
||||
'is_initial' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log: Produkt hinzugefügt oder Menge erhöht (bei bereits vorhandenem Produkt).
|
||||
*/
|
||||
public static function logProductAdded(UserAbo $userAbo, UserAboItem $item, int $qtyBefore, string $view): void
|
||||
{
|
||||
$product = $item->product;
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
$actor = self::resolveActor();
|
||||
$channel = self::resolveChannel($view);
|
||||
|
||||
$action = $qtyBefore === 0
|
||||
? UserAboItemHistory::ACTION_ADDED
|
||||
: UserAboItemHistory::ACTION_QTY_CHANGED;
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $product->id,
|
||||
'action' => $action,
|
||||
'product_name' => $product->getLang('name'),
|
||||
'product_number' => $product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'qty_before' => $qtyBefore > 0 ? $qtyBefore : null,
|
||||
'qty_after' => $item->qty,
|
||||
'comp' => $item->comp ?? 0,
|
||||
'changed_by_user_id' => $actor['id'],
|
||||
'changed_by_name' => $actor['name'],
|
||||
'channel' => $channel,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log: Menge eines Produkts geändert.
|
||||
*/
|
||||
public static function logQtyChanged(UserAbo $userAbo, UserAboItem $item, int $qtyBefore, int $qtyAfter, string $view): void
|
||||
{
|
||||
if ($qtyBefore === $qtyAfter) {
|
||||
return;
|
||||
}
|
||||
|
||||
$product = $item->product;
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
$actor = self::resolveActor();
|
||||
$channel = self::resolveChannel($view);
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $product->id,
|
||||
'action' => UserAboItemHistory::ACTION_QTY_CHANGED,
|
||||
'product_name' => $product->getLang('name'),
|
||||
'product_number' => $product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $qtyAfter,
|
||||
'qty_before' => $qtyBefore,
|
||||
'qty_after' => $qtyAfter,
|
||||
'comp' => $item->comp ?? 0,
|
||||
'changed_by_user_id' => $actor['id'],
|
||||
'changed_by_name' => $actor['name'],
|
||||
'channel' => $channel,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log: Produkt entfernt (vor dem delete aufrufen!).
|
||||
*/
|
||||
public static function logProductRemoved(UserAbo $userAbo, UserAboItem $item, string $view): void
|
||||
{
|
||||
$product = $item->product;
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
$actor = self::resolveActor();
|
||||
$channel = self::resolveChannel($view);
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $product->id,
|
||||
'action' => UserAboItemHistory::ACTION_REMOVED,
|
||||
'product_name' => $product->getLang('name'),
|
||||
'product_number' => $product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'qty_before' => $item->qty,
|
||||
'qty_after' => 0,
|
||||
'comp' => $item->comp ?? 0,
|
||||
'changed_by_user_id' => $actor['id'],
|
||||
'changed_by_name' => $actor['name'],
|
||||
'channel' => $channel,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log: Comp-Produkt getauscht.
|
||||
*/
|
||||
public static function logCompProductChanged(UserAbo $userAbo, UserAboItem $item, Product $oldProduct, Product $newProduct, string $view): void
|
||||
{
|
||||
// Item hat bereits das neue Produkt — getPrice() liefert den korrekten Anzeige-Preis
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
$actor = self::resolveActor();
|
||||
$channel = self::resolveChannel($view);
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $newProduct->id,
|
||||
'action' => UserAboItemHistory::ACTION_COMP_CHANGED,
|
||||
'product_name' => $newProduct->getLang('name'),
|
||||
'product_number' => $newProduct->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'old_product_id' => $oldProduct->id,
|
||||
'old_product_name' => $oldProduct->getLang('name'),
|
||||
'comp' => $item->comp,
|
||||
'changed_by_user_id' => $actor['id'],
|
||||
'changed_by_name' => $actor['name'],
|
||||
'channel' => $channel,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log: System hat Comp-Produkt hinzugefügt.
|
||||
*/
|
||||
public static function logSystemCompAdded(UserAbo $userAbo, UserAboItem $item): void
|
||||
{
|
||||
$product = $item->product;
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $product->id,
|
||||
'action' => UserAboItemHistory::ACTION_COMP_ADDED,
|
||||
'product_name' => $product->getLang('name'),
|
||||
'product_number' => $product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'qty_after' => $item->qty,
|
||||
'comp' => $item->comp,
|
||||
'changed_by_user_id' => null,
|
||||
'changed_by_name' => 'System',
|
||||
'channel' => UserAboItemHistory::CHANNEL_SYSTEM,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log: System hat Comp-Produkt entfernt (vor dem delete aufrufen!).
|
||||
*/
|
||||
public static function logSystemCompRemoved(UserAbo $userAbo, UserAboItem $item): void
|
||||
{
|
||||
$product = $item->product;
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $product->id,
|
||||
'action' => UserAboItemHistory::ACTION_COMP_REMOVED,
|
||||
'product_name' => $product->getLang('name'),
|
||||
'product_number' => $product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'qty_before' => $item->qty,
|
||||
'qty_after' => 0,
|
||||
'comp' => $item->comp,
|
||||
'changed_by_user_id' => null,
|
||||
'changed_by_name' => 'System',
|
||||
'channel' => UserAboItemHistory::CHANNEL_SYSTEM,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt das Abo auf den Ursprungszustand zurück.
|
||||
*/
|
||||
public static function rollbackToInitial(UserAbo $userAbo): bool
|
||||
{
|
||||
$initialItems = $userAbo->user_abo_item_histories()
|
||||
->where('is_initial', true)
|
||||
->get();
|
||||
|
||||
if ($initialItems->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$batchId = Str::uuid()->toString();
|
||||
$actor = self::resolveActor();
|
||||
|
||||
// Aktuelle Items loggen und löschen
|
||||
foreach ($userAbo->user_abo_items as $item) {
|
||||
$unitPrice = self::resolveItemPrice($item);
|
||||
UserAboItemHistory::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'user_abo_item_id' => $item->id,
|
||||
'product_id' => $item->product_id,
|
||||
'action' => UserAboItemHistory::ACTION_ROLLBACK,
|
||||
'product_name' => $item->product->getLang('name'),
|
||||
'product_number' => $item->product->number ?? null,
|
||||
'unit_price' => $unitPrice,
|
||||
'total_price' => $unitPrice * $item->qty,
|
||||
'qty_before' => $item->qty,
|
||||
'qty_after' => 0,
|
||||
'comp' => $item->comp ?? 0,
|
||||
'changed_by_user_id' => $actor['id'],
|
||||
'changed_by_name' => $actor['name'],
|
||||
'channel' => UserAboItemHistory::CHANNEL_ADMIN,
|
||||
'batch_id' => $batchId,
|
||||
]);
|
||||
}
|
||||
|
||||
// Alle aktuellen Items löschen
|
||||
UserAboItem::where('user_abo_id', $userAbo->id)->delete();
|
||||
|
||||
// Neue Items aus Initial-History erstellen
|
||||
foreach ($initialItems as $historyItem) {
|
||||
UserAboItem::create([
|
||||
'user_abo_id' => $userAbo->id,
|
||||
'product_id' => $historyItem->product_id,
|
||||
'comp' => $historyItem->comp,
|
||||
'qty' => $historyItem->qty_after,
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt den exakten Anzeige-Preis des UserAboItems.
|
||||
* Nutzt UserAboItem::getPrice() — das ist genau der Preis, der dem User
|
||||
* in der Produktliste und im Warenkorb angezeigt wird (netto+UserFactor
|
||||
* für Berater, brutto für Kunden, länderspezifisch).
|
||||
*
|
||||
* Fallback-Kette wenn Yard nicht verfügbar:
|
||||
* 1. getPriceWith() ohne Country (netto/ufactor je nach is_for)
|
||||
* 2. Rohpreis des Produkts
|
||||
*/
|
||||
private static function resolveItemPrice(UserAboItem $item): float
|
||||
{
|
||||
// 1. Exakter Anzeige-Preis via UserAboItem::getPrice() (nutzt Yard)
|
||||
try {
|
||||
return (float) $item->getPrice();
|
||||
} catch (\Throwable $e) {
|
||||
// Yard nicht initialisiert — weiter zum Fallback
|
||||
}
|
||||
|
||||
// 2. Manuelle Berechnung ohne Yard (ohne Country-spezifische Preise)
|
||||
try {
|
||||
$isMe = $item->user_abo->is_for === 'me';
|
||||
|
||||
return (float) $item->product->getPriceWith($isMe, $isMe);
|
||||
} catch (\Throwable $e) {
|
||||
// Letzter Fallback
|
||||
}
|
||||
|
||||
// 3. Roher Produktpreis
|
||||
return (float) ($item->product->price ?? 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktuellen Benutzer ermitteln (CRM Auth oder Kunden-Guard).
|
||||
*/
|
||||
private static function resolveActor(): array
|
||||
{
|
||||
// CRM User (Admin/Berater)
|
||||
$user = \Auth::user();
|
||||
if ($user) {
|
||||
$name = '';
|
||||
if ($user->account) {
|
||||
$name = trim($user->account->first_name.' '.$user->account->last_name);
|
||||
}
|
||||
if (! $name) {
|
||||
$name = $user->email ?? 'User #'.$user->id;
|
||||
}
|
||||
|
||||
return ['id' => $user->id, 'name' => $name];
|
||||
}
|
||||
|
||||
// Portal Kunde
|
||||
$customer = \Auth::guard('customers')->user();
|
||||
if ($customer) {
|
||||
return ['id' => null, 'name' => $customer->name ?? $customer->email ?? 'Kunde'];
|
||||
}
|
||||
|
||||
return ['id' => null, 'name' => 'System'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel aus View-Parameter und Auth-Kontext ableiten.
|
||||
*/
|
||||
private static function resolveChannel(string $view): string
|
||||
{
|
||||
if ($view === 'portal') {
|
||||
return UserAboItemHistory::CHANNEL_PORTAL;
|
||||
}
|
||||
|
||||
if ($view === 'admin') {
|
||||
return UserAboItemHistory::CHANNEL_ADMIN;
|
||||
}
|
||||
|
||||
// Bei user views: Prüfen ob Admin die Änderung vornimmt
|
||||
$user = \Auth::user();
|
||||
if ($user && $user->isAdmin()) {
|
||||
return UserAboItemHistory::CHANNEL_ADMIN;
|
||||
}
|
||||
|
||||
if ($view === 'me') {
|
||||
return UserAboItemHistory::CHANNEL_USER_ME;
|
||||
}
|
||||
|
||||
if ($view === 'ot') {
|
||||
return UserAboItemHistory::CHANNEL_USER_OT;
|
||||
}
|
||||
|
||||
return UserAboItemHistory::CHANNEL_SYSTEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,24 +2,20 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use Yard;
|
||||
use App\User;
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Product;
|
||||
use App\Models\UserAbo;
|
||||
use App\Models\UserAboItem;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\UserAboOrder;
|
||||
use App\Models\ShoppingOrder;
|
||||
use App\Models\ShippingCountry;
|
||||
use App\Models\ShoppingPayment;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\UserAboItem;
|
||||
use App\User;
|
||||
use Yard;
|
||||
|
||||
class AboOrderCart
|
||||
{
|
||||
private static $user_abo;
|
||||
private static $is_for;
|
||||
private static $customer_detail;
|
||||
|
||||
private static $is_for;
|
||||
|
||||
private static $customer_detail;
|
||||
|
||||
public static function initYard($user_abo)
|
||||
{
|
||||
|
|
@ -37,12 +33,12 @@ class AboOrderCart
|
|||
|
||||
\Log::info('AboOrderCart::initYard: Yard geleert', [
|
||||
'abo_id' => $user_abo->id,
|
||||
'items_vor_destroy' => $itemsBeforeDestroy
|
||||
'items_vor_destroy' => $itemsBeforeDestroy,
|
||||
]);
|
||||
$itemsAfterDestroy = $yard->content()->count();
|
||||
\Log::info('AboOrderCart::initYard: Yard geleert', [
|
||||
'abo_id' => $user_abo->id,
|
||||
'items_after_destroy' => $itemsAfterDestroy
|
||||
'items_after_destroy' => $itemsAfterDestroy,
|
||||
]);
|
||||
|
||||
self::$customer_detail = self::makeCustomerDetail($user_abo);
|
||||
|
|
@ -56,6 +52,7 @@ class AboOrderCart
|
|||
if ($country_id && $shipping_country = ShippingCountry::whereCountryId($country_id)->first()) {
|
||||
if ($shipping_country->shipping && $shipping_country->shipping->active) {
|
||||
UserService::initUserYard($user_abo->user, $shipping_country->id, 'abo-me');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +61,7 @@ class AboOrderCart
|
|||
if ($user_abo->is_for === 'ot') {
|
||||
self::$is_for = 'abo-ot-customer';
|
||||
UserService::initCustomerYard(self::$customer_detail, 'abo-ot-customer');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +88,7 @@ class AboOrderCart
|
|||
if ($itemsBefore > 0) {
|
||||
\Log::warning('AboOrderCart::makeOrderYard: Yard war nicht leer vor makeOrderYard und wurde geleert', [
|
||||
'abo_id' => $user_abo->id,
|
||||
'items_before' => $itemsBefore
|
||||
'items_before' => $itemsBefore,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -105,9 +103,9 @@ class AboOrderCart
|
|||
'id' => $item->id,
|
||||
'product_id' => $item->product_id,
|
||||
'qty' => $item->qty,
|
||||
'comp' => $item->comp
|
||||
'comp' => $item->comp,
|
||||
];
|
||||
})->toArray()
|
||||
})->toArray(),
|
||||
]);
|
||||
|
||||
foreach ($abo_items as $abo_item) {
|
||||
|
|
@ -141,10 +139,11 @@ class AboOrderCart
|
|||
'weight' => 0,
|
||||
'points' => 0,
|
||||
'comp' => $item->comp,
|
||||
'product_id' => $product->id
|
||||
'product_id' => $product->id,
|
||||
]
|
||||
);
|
||||
Yard::setTax($cartItem->rowId, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (self::$is_for === 'ot-customer' || self::$is_for === 'abo-ot-customer') {
|
||||
|
|
@ -153,10 +152,10 @@ class AboOrderCart
|
|||
$product->id,
|
||||
$product->getLang('name'),
|
||||
$item->qty,
|
||||
round($product->getPriceWith($tax_free, false, $user_country, false, self::$user_abo->user), 1),
|
||||
round($product->getPriceWith($tax_free, false, $user_country, false, self::$user_abo->user), 1),
|
||||
false,
|
||||
false,
|
||||
['image' => '', 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'show_on' => $product->show_on]
|
||||
['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]
|
||||
);
|
||||
} else {
|
||||
$cartItem = Yard::instance('shopping')
|
||||
|
|
@ -164,10 +163,10 @@ class AboOrderCart
|
|||
$product->id,
|
||||
$product->getLang('name'),
|
||||
$item->qty,
|
||||
$product->getPriceWith($tax_free, true, $user_country, false, self::$user_abo->user),
|
||||
$product->getPriceWith($tax_free, true, $user_country, false, self::$user_abo->user),
|
||||
false,
|
||||
false,
|
||||
['image' => '', 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'show_on' => $product->show_on]
|
||||
['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 ($tax_free) {
|
||||
|
|
@ -189,7 +188,7 @@ class AboOrderCart
|
|||
return true;
|
||||
}
|
||||
|
||||
//need to add
|
||||
// need to add
|
||||
if (count($UserAboItems) < $needNumComp) {
|
||||
$product = Product::whereActive(true)->where('shipping_addon', true)->whereJsonContains('show_on', '12')->orderBy('pos', 'DESC')->first();
|
||||
for ($i = count($UserAboItems); $i <= $needNumComp; $i++) {
|
||||
|
|
@ -200,13 +199,15 @@ class AboOrderCart
|
|||
'qty' => 1,
|
||||
'status' => 1,
|
||||
]);
|
||||
AboItemHistoryService::logSystemCompAdded($user_abo, $UserAboItem);
|
||||
self::addProductToCart($UserAboItem);
|
||||
}
|
||||
}
|
||||
//need to remove
|
||||
// need to remove
|
||||
if (count($UserAboItems) > $needNumComp) {
|
||||
foreach ($UserAboItems as $UserAboItem) {
|
||||
if ($UserAboItem->comp > $needNumComp) {
|
||||
AboItemHistoryService::logSystemCompRemoved($user_abo, $UserAboItem);
|
||||
$UserAboItem->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -230,20 +231,20 @@ class AboOrderCart
|
|||
{
|
||||
|
||||
if ($user_abo->is_for === 'me') {
|
||||
//only on Abo!
|
||||
// only on Abo!
|
||||
$user = $user_abo->user;
|
||||
|
||||
// WICHTIG: Wenn bereits ein shopping_user existiert, diesen replizieren um alle Felder zu behalten
|
||||
// Ansonsten neues Objekt erstellen
|
||||
if ($user_abo->shopping_user) {
|
||||
$shopping_user = $user_abo->shopping_user->replicate();
|
||||
\Log::info('AboOrderCart::makeCustomerDetail: ShoppingUser repliziert für Abo ID: ' . $user_abo->id, [
|
||||
\Log::info('AboOrderCart::makeCustomerDetail: ShoppingUser repliziert für Abo ID: '.$user_abo->id, [
|
||||
'abo_id' => $user_abo->id,
|
||||
'original_shopping_user_id' => $user_abo->shopping_user->id
|
||||
'original_shopping_user_id' => $user_abo->shopping_user->id,
|
||||
]);
|
||||
} else {
|
||||
$shopping_user = new ShoppingUser();
|
||||
\Log::info('AboOrderCart::makeCustomerDetail: Neuer ShoppingUser erstellt für Abo ID: ' . $user_abo->id);
|
||||
$shopping_user = new ShoppingUser;
|
||||
\Log::info('AboOrderCart::makeCustomerDetail: Neuer ShoppingUser erstellt für Abo ID: '.$user_abo->id);
|
||||
}
|
||||
|
||||
// Account-Daten überschreiben/aktualisieren
|
||||
|
|
@ -258,9 +259,10 @@ class AboOrderCart
|
|||
$shopping_user->billing_country_id = $user->account->country_id;
|
||||
$shopping_user->billing_phone = $user->account->phone;
|
||||
$shopping_user->billing_email = $user->email ?? null;
|
||||
$shopping_user->language = $user->account->getLocale();
|
||||
|
||||
// Auth User ID setzen falls noch nicht gesetzt
|
||||
if (!$shopping_user->auth_user_id) {
|
||||
if (! $shopping_user->auth_user_id) {
|
||||
$shopping_user->auth_user_id = $user->id;
|
||||
}
|
||||
if ($user->account->same_as_billing) {
|
||||
|
|
@ -293,9 +295,10 @@ class AboOrderCart
|
|||
}
|
||||
|
||||
if ($user_abo->is_for === 'ot') {
|
||||
//look for the primary user of this abo
|
||||
// look for the primary user of this abo
|
||||
$shopping_user = $user_abo->shopping_user->replicate();
|
||||
}
|
||||
|
||||
return $shopping_user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ class SalesPointsVolume
|
|||
$form_user = User::find($form_user_id);
|
||||
|
||||
$shoppingOrder->user_sales_volume->user_id = $to_user_id;
|
||||
$shoppingOrder->user_sales_volume->message = 'zugewiesen: ' . date('d.m.Y');
|
||||
$shoppingOrder->user_sales_volume->message = 'zugewiesen: '.date('d.m.Y');
|
||||
|
||||
$syslog = $shoppingOrder->user_sales_volume->syslog;
|
||||
$from_email = $form_user ? $form_user->email : '';
|
||||
$to_email = $to_user ? $to_user->email : '';
|
||||
$syslog[date('d.m.Y-h:i:s')] = 'change form: #' . $form_user_id . ' ' . $from_email . ' to: #' . $to_user_id . ' ' . $to_email;
|
||||
$syslog[date('d.m.Y-h:i:s')] = 'change form: #'.$form_user_id.' '.$from_email.' to: #'.$to_user_id.' '.$to_email;
|
||||
$shoppingOrder->user_sales_volume->syslog = $syslog;
|
||||
|
||||
$shoppingOrder->user_sales_volume->save();
|
||||
|
|
@ -100,6 +100,17 @@ class SalesPointsVolume
|
|||
case 5: // Registrierung
|
||||
$month_points = self::add_KP_TP_Points($userSalesVolume, $month_points);
|
||||
$month_total_net += $userSalesVolume->total_net;
|
||||
break;
|
||||
case 6: // Storno - negative Punkte und Beträge
|
||||
$month_points = self::add_KP_TP_Points($userSalesVolume, $month_points);
|
||||
|
||||
if ($userSalesVolume->status_turnover === 2) {
|
||||
$month_shop_points += $userSalesVolume->points; // bereits negativ
|
||||
$month_shop_total_net += $userSalesVolume->total_net; // bereits negativ
|
||||
} else {
|
||||
$month_total_net += $userSalesVolume->total_net; // bereits negativ
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
$userSalesVolume->month_shop_points = $month_shop_points;
|
||||
|
|
@ -200,13 +211,13 @@ class SalesPointsVolume
|
|||
$user_sales_volume->total_net = Util::reFormatNumber($data['total_net']);
|
||||
$user_sales_volume->points = Util::reFormatNumber($data['points']);
|
||||
|
||||
$user_sales_volume->message = 'geändert: ' . date('d.m.Y');
|
||||
$user_sales_volume->message = 'geändert: '.date('d.m.Y');
|
||||
$user_sales_volume->info = $data['info'];
|
||||
$user_sales_volume->status_points = $data['status_points'];
|
||||
$user_sales_volume->status_turnover = isset($data['status_turnover']) ? intval($data['status_turnover']) : null;
|
||||
|
||||
$syslog = $user_sales_volume->syslog;
|
||||
$syslog[date('d.m.Y-h:i:s')] = 'edit points: #' . $old_points . ' ' . $user_sales_volume->points . ' total: #' . $old_total_net . ' ' . $user_sales_volume->total_net;
|
||||
$syslog[date('d.m.Y-h:i:s')] = 'edit points: #'.$old_points.' '.$user_sales_volume->points.' total: #'.$old_total_net.' '.$user_sales_volume->total_net;
|
||||
$user_sales_volume->syslog = $syslog;
|
||||
|
||||
$user_sales_volume->save();
|
||||
|
|
@ -231,7 +242,7 @@ class SalesPointsVolume
|
|||
|
||||
$total_net = isset($data['total_net']) ? Util::reFormatNumber($data['total_net']) : 0;
|
||||
$points = isset($data['points']) ? Util::reFormatNumber($data['points']) : 0;
|
||||
$syslog[date('d.m.Y-h:i:s')] = 'add points: #' . $points . ' total: #' . $total_net;
|
||||
$syslog[date('d.m.Y-h:i:s')] = 'add points: #'.$points.' total: #'.$total_net;
|
||||
$status = isset($data['status']) ? intval($data['status']) : 4;
|
||||
$status_turnover = isset($data['status_turnover']) ? intval($data['status_turnover']) : null;
|
||||
|
||||
|
|
@ -245,7 +256,7 @@ class SalesPointsVolume
|
|||
'status_points' => $data['status_points'],
|
||||
'status_turnover' => $status_turnover,
|
||||
'total_net' => $total_net,
|
||||
'message' => 'hinzugefügt: ' . date('d.m.Y'),
|
||||
'message' => 'hinzugefügt: '.date('d.m.Y'),
|
||||
'info' => $data['info'],
|
||||
'syslog' => $syslog,
|
||||
'status' => $status,
|
||||
|
|
@ -255,4 +266,61 @@ class SalesPointsVolume
|
|||
|
||||
\Session()->flash('alert-success', 'Points hinzugefügt');
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt einen Storno-Eintrag für eine stornierte Rechnung
|
||||
* Negative Punkte werden dem aktuellen Monat zugeordnet
|
||||
*
|
||||
* @param UserSalesVolume $original_sales_volume Der ursprüngliche Sales Volume Eintrag
|
||||
* @param int $cancellation_invoice_id Die ID der Stornorechnung
|
||||
* @return UserSalesVolume
|
||||
*/
|
||||
public static function cancelSalesPointsVolume(UserSalesVolume $original_sales_volume, $cancellation_invoice_id)
|
||||
{
|
||||
$month = date('m');
|
||||
$year = date('Y');
|
||||
$date = date('d.m.Y');
|
||||
|
||||
$syslog = [
|
||||
date('d.m.Y H:i:s') => 'Stornorechnung erstellt - Punkte korrigiert (Original Invoice: #'.$original_sales_volume->user_invoice_id.')',
|
||||
];
|
||||
|
||||
// Negativen Eintrag erstellen (alle Werte negativ)
|
||||
$cancellation_sales_volume = UserSalesVolume::create([
|
||||
'user_id' => $original_sales_volume->user_id,
|
||||
'shopping_order_id' => $original_sales_volume->shopping_order_id,
|
||||
'user_invoice_id' => $cancellation_invoice_id,
|
||||
'month' => $month,
|
||||
'year' => $year,
|
||||
'date' => $date,
|
||||
'points' => -$original_sales_volume->points, // Negativ!
|
||||
'month_points' => 0, // Wird durch reCalculate gesetzt
|
||||
'month_KP_points' => 0,
|
||||
'month_TP_points' => 0,
|
||||
'month_shop_points' => 0,
|
||||
'total_net' => -$original_sales_volume->total_net, // Negativ!
|
||||
'month_total_net' => 0,
|
||||
'status' => 6, // Status 6 = cancelled/storniert
|
||||
'status_points' => $original_sales_volume->status_points,
|
||||
'status_turnover' => $original_sales_volume->status_turnover,
|
||||
'message' => 'Storniert am '.date('d.m.Y'),
|
||||
'info' => 'Storno für Invoice #'.$original_sales_volume->user_invoice_id,
|
||||
'syslog' => $syslog,
|
||||
]);
|
||||
|
||||
// Neuberechnung für aktuellen Monat
|
||||
self::reCalculateSalesPointsVolume($original_sales_volume->user_id, $month, $year);
|
||||
|
||||
\Log::info('Punktekorrektur für Stornorechnung durchgeführt', [
|
||||
'original_invoice_id' => $original_sales_volume->user_invoice_id,
|
||||
'cancellation_invoice_id' => $cancellation_invoice_id,
|
||||
'original_points' => $original_sales_volume->points,
|
||||
'cancellation_points' => $cancellation_sales_volume->points,
|
||||
'user_id' => $original_sales_volume->user_id,
|
||||
'month' => $month,
|
||||
'year' => $year,
|
||||
]);
|
||||
|
||||
return $cancellation_sales_volume;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,90 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Services\Util;
|
||||
use App\Models\Setting;
|
||||
use App\Mail\MailCredit;
|
||||
use App\Models\Setting;
|
||||
use App\Models\UserCredit;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class Credit
|
||||
{
|
||||
|
||||
public static function getCreditNumber(){
|
||||
//return (int) Setting::getContentBySlug('credit-number');
|
||||
public static function getCreditNumber()
|
||||
{
|
||||
// return (int) Setting::getContentBySlug('credit-number');
|
||||
return (int) Setting::getContentBySlug('invoice-number');
|
||||
}
|
||||
|
||||
|
||||
public static function makeNextCreditNumber(){
|
||||
public static function makeNextCreditNumber()
|
||||
{
|
||||
$credit_number = self::getCreditNumber();
|
||||
$credit_number = $credit_number+1;
|
||||
//Setting::setContentBySlug('credit-number', $credit_number, 'int');
|
||||
$credit_number = $credit_number + 1;
|
||||
// Setting::setContentBySlug('credit-number', $credit_number, 'int');
|
||||
Setting::setContentBySlug('invoice-number', $credit_number, 'int');
|
||||
|
||||
return $credit_number;
|
||||
}
|
||||
|
||||
public static function createCreditNumber($credit_number, $credit_date){
|
||||
public static function createCreditNumber($credit_number, $credit_date)
|
||||
{
|
||||
|
||||
$prefix = "GS".\Carbon::parse($credit_date)->format('Y');
|
||||
$prefix = 'GS'.\Carbon::parse($credit_date)->format('Y');
|
||||
$credit_number = str_pad($credit_number, 5, '0', STR_PAD_LEFT);
|
||||
|
||||
return $prefix.$credit_number;
|
||||
}
|
||||
|
||||
public static function getCreditStorageDir($credit_date){
|
||||
return "/credit/".\Carbon::parse($credit_date)->format('Y/m/');
|
||||
public static function getCreditStorageDir($credit_date)
|
||||
{
|
||||
return '/credit/'.\Carbon::parse($credit_date)->format('Y/m/');
|
||||
}
|
||||
|
||||
public static function getCreditDetailStorageDir($credit_date){
|
||||
return "/credit_details/".\Carbon::parse($credit_date)->format('Y/m/');
|
||||
public static function getCreditDetailStorageDir($credit_date)
|
||||
{
|
||||
return '/credit_details/'.\Carbon::parse($credit_date)->format('Y/m/');
|
||||
}
|
||||
|
||||
public static function makeCreditFilename($credit_number){
|
||||
return $credit_number."-MIVITA-Gutschrift.pdf";
|
||||
public static function makeCreditFilename($credit_number)
|
||||
{
|
||||
return $credit_number.'-MIVITA-Gutschrift.pdf';
|
||||
}
|
||||
|
||||
public static function makeCreditDetailFilename($credit_number){
|
||||
return $credit_number."-MIVITA-Report.pdf";
|
||||
public static function makeCreditDetailFilename($credit_number)
|
||||
{
|
||||
return $credit_number.'-MIVITA-Report.pdf';
|
||||
}
|
||||
|
||||
public static function isCredit(UserCredit $user_credit){
|
||||
/**
|
||||
* Erstellt den Dateinamen für eine lokalisierte Gutschrift.
|
||||
* Deutsch (de) ist das Original ohne Suffix.
|
||||
*
|
||||
* @param string $credit_number
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
public static function makeCreditFilenameLocale($credit_number, $locale)
|
||||
{
|
||||
if ($locale === 'de' || ! $locale) {
|
||||
return self::makeCreditFilename($credit_number);
|
||||
}
|
||||
|
||||
return $credit_number.'-MIVITA-Gutschrift-'.$locale.'.pdf';
|
||||
}
|
||||
|
||||
public static function isCredit(UserCredit $user_credit)
|
||||
{
|
||||
return $user_credit->isCredit();
|
||||
}
|
||||
|
||||
/*public static function getFilename(UserCredit $user_credit){
|
||||
return $user_credit->filename;
|
||||
/*public static function getFilename(UserCredit $user_credit){
|
||||
return $user_credit->filename;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static function getDir(UserCredit $user_credit){
|
||||
return $user_credit->dir;
|
||||
return $user_credit->dir;
|
||||
}
|
||||
|
||||
public static function getDownloadURL(UserCredit $user_credit, $do = false){
|
||||
return route('storage_file', [$user_credit->id, 'cms_download_file', $do]);
|
||||
return route('storage_file', [$user_credit->id, 'cms_download_file', $do]);
|
||||
}
|
||||
|
||||
|
||||
public static function getDownloadPath(UserCredit $user_credit, $full = false){
|
||||
$dir = self::getDir($user_credit);
|
||||
$filename = self::getFilename($user_credit);
|
||||
if(!$full){
|
||||
return $dir.$filename;
|
||||
}
|
||||
return \Storage::disk('public')->path($dir.$filename);
|
||||
$dir = self::getDir($user_credit);
|
||||
$filename = self::getFilename($user_credit);
|
||||
if(!$full){
|
||||
return $dir.$filename;
|
||||
}
|
||||
return \Storage::disk('public')->path($dir.$filename);
|
||||
}*/
|
||||
|
||||
public static function sendCreditMail(UserCredit $user_credit){
|
||||
public static function sendCreditMail(UserCredit $user_credit)
|
||||
{
|
||||
$bcc = [];
|
||||
$email = $user_credit->user->email;
|
||||
if(!$email){
|
||||
if($user_credit->user->mode === 'test'){
|
||||
}else{
|
||||
if (! $email) {
|
||||
if ($user_credit->user->mode === 'test') {
|
||||
} else {
|
||||
$email = config('app.checkout_mail');
|
||||
}
|
||||
}
|
||||
if($user_credit->user->mode === 'test'){
|
||||
if ($user_credit->user->mode === 'test') {
|
||||
$bcc[] = config('app.checkout_test_mail');
|
||||
}else{
|
||||
} else {
|
||||
$bcc[] = config('app.checkout_mail');
|
||||
}
|
||||
Mail::to($email)->bcc($bcc)->locale($user_credit->user->getLocale())->send(new MailCredit($user_credit));
|
||||
|
|
|
|||
1079
app/Services/DatevExportService.php
Normal file
1079
app/Services/DatevExportService.php
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -3,9 +3,11 @@
|
|||
namespace App\Services;
|
||||
|
||||
use Acme\Dhl\Models\DhlShipment;
|
||||
use Acme\Dhl\Models\DhlTrackingEvent;
|
||||
use App\Http\Controllers\SettingController;
|
||||
use App\Jobs\TrackShipmentJob;
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
|
|
@ -42,6 +44,7 @@ class DhlTrackingService
|
|||
Log::info('[DHL Tracking Service] Tracking shipment with Unified API', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'is_sandbox' => $this->isSandbox,
|
||||
'has_api_key' => ! empty($this->apiKey),
|
||||
]);
|
||||
|
||||
$response = Http::withHeaders([
|
||||
|
|
@ -60,16 +63,21 @@ class DhlTrackingService
|
|||
CURLOPT_CONNECTTIMEOUT => config('dhl.ssl.connect_timeout', 10),
|
||||
CURLOPT_TIMEOUT => config('dhl.ssl.timeout', 30),
|
||||
CURLOPT_USERAGENT => 'acme-laravel-dhl/1.0',
|
||||
]
|
||||
],
|
||||
])
|
||||
->get('https://api.dhl.com/track/shipments', [
|
||||
->get('https://api-eu.dhl.com/track/shipments', [
|
||||
'trackingNumber' => $trackingNumber,
|
||||
'service' => 'express,parcel',
|
||||
'requesterCountryCode' => 'DE',
|
||||
'originCountryCode' => 'DE',
|
||||
'language' => 'de',
|
||||
]);
|
||||
|
||||
Log::info('[DHL Tracking Service] Unified API response', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'status_code' => $response->status(),
|
||||
'successful' => $response->successful(),
|
||||
]);
|
||||
|
||||
if ($response->successful()) {
|
||||
$data = $response->json();
|
||||
|
||||
|
|
@ -80,8 +88,8 @@ class DhlTrackingService
|
|||
'success' => true,
|
||||
'tracking_number' => $shipment['id'],
|
||||
'status' => $shipment['status']['statusCode'] ?? 'unknown',
|
||||
'status_text' => $shipment['status']['status'] ?? 'Unbekannt',
|
||||
'description' => $shipment['status']['description'] ?? '',
|
||||
'status_text' => $shipment['status']['description'] ?? ($shipment['status']['status'] ?? 'Unbekannt'),
|
||||
'description' => $shipment['status']['remark'] ?? ($shipment['status']['description'] ?? ''),
|
||||
'last_update' => $shipment['status']['timestamp'] ?? null,
|
||||
'origin' => $shipment['origin']['address']['addressLocality'] ?? null,
|
||||
'destination' => $shipment['destination']['address']['addressLocality'] ?? null,
|
||||
|
|
@ -91,6 +99,12 @@ class DhlTrackingService
|
|||
}
|
||||
}
|
||||
|
||||
Log::warning('[DHL Tracking Service] Unified API did not find shipment, trying Parcel DE API', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'status_code' => $response->status(),
|
||||
'response_snippet' => mb_substr($response->body(), 0, 500),
|
||||
]);
|
||||
|
||||
// If Unified API fails, try Parcel DE API
|
||||
return $this->trackShipmentDE($trackingNumber, $options);
|
||||
} catch (Exception $e) {
|
||||
|
|
@ -113,13 +127,14 @@ class DhlTrackingService
|
|||
Log::info('[DHL Tracking Service] Tracking shipment with Parcel DE API', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'is_sandbox' => $this->isSandbox,
|
||||
'has_api_key' => ! empty($this->apiKey),
|
||||
'has_api_secret' => ! empty($this->apiSecret),
|
||||
]);
|
||||
|
||||
$response = Http::withBasicAuth($this->apiKey, $this->apiSecret)
|
||||
->withHeaders([
|
||||
'Accept' => 'application/json',
|
||||
'dhl-api-key' => $this->apiKey,
|
||||
])
|
||||
$response = Http::withHeaders([
|
||||
'DHL-API-Key' => $this->apiKey,
|
||||
'Accept' => 'application/json',
|
||||
])
|
||||
->withOptions([
|
||||
'verify' => config('dhl.ssl.verify_peer', true),
|
||||
'http_errors' => false,
|
||||
|
|
@ -132,13 +147,20 @@ class DhlTrackingService
|
|||
CURLOPT_CONNECTTIMEOUT => config('dhl.ssl.connect_timeout', 10),
|
||||
CURLOPT_TIMEOUT => config('dhl.ssl.timeout', 30),
|
||||
CURLOPT_USERAGENT => 'acme-laravel-dhl/1.0',
|
||||
]
|
||||
],
|
||||
])
|
||||
->get('https://api.dhl.com/parcel/de/tracking/v1/shipments', [
|
||||
'trackingNumber' => $trackingNumber,
|
||||
->get('https://api-eu.dhl.com/parcel/de/tracking/v0/shipments', [
|
||||
'shipmentId' => $trackingNumber,
|
||||
'language' => 'de',
|
||||
]);
|
||||
|
||||
Log::info('[DHL Tracking Service] Parcel DE API response', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'status_code' => $response->status(),
|
||||
'successful' => $response->successful(),
|
||||
'response_body' => $response->body(),
|
||||
]);
|
||||
|
||||
if ($response->successful()) {
|
||||
$data = $response->json();
|
||||
|
||||
|
|
@ -158,21 +180,33 @@ class DhlTrackingService
|
|||
}
|
||||
}
|
||||
|
||||
// Log detailed error information
|
||||
Log::warning('[DHL Tracking Service] Shipment not found or not yet tracked', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'status_code' => $response->status(),
|
||||
'response_body' => $response->body(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Sendung nicht gefunden oder noch nicht im System erfasst.',
|
||||
'message' => 'Sendung nicht gefunden oder noch nicht im System erfasst. HTTP Status: '.$response->status(),
|
||||
'tracking_number' => $trackingNumber,
|
||||
'api_used' => 'parcel_de',
|
||||
'debug_info' => [
|
||||
'status_code' => $response->status(),
|
||||
'response' => $response->json(),
|
||||
],
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Tracking Service] Parcel DE API failed', [
|
||||
'tracking_number' => $trackingNumber,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Abrufen der Tracking-Informationen: ' . $e->getMessage(),
|
||||
'message' => 'Fehler beim Abrufen der Tracking-Informationen: '.$e->getMessage(),
|
||||
'tracking_number' => $trackingNumber,
|
||||
'api_used' => 'parcel_de',
|
||||
];
|
||||
|
|
@ -208,11 +242,10 @@ class DhlTrackingService
|
|||
CURLOPT_CONNECTTIMEOUT => config('dhl.ssl.connect_timeout', 10),
|
||||
CURLOPT_TIMEOUT => config('dhl.ssl.timeout', 30),
|
||||
CURLOPT_USERAGENT => 'acme-laravel-dhl/1.0',
|
||||
]
|
||||
],
|
||||
])
|
||||
->get('https://api.dhl.com/track/shipments', [
|
||||
->get('https://api-eu.dhl.com/track/shipments', [
|
||||
'trackingNumber' => implode(',', $trackingNumbers),
|
||||
'service' => 'parcel',
|
||||
'requesterCountryCode' => 'DE',
|
||||
'language' => 'de',
|
||||
]);
|
||||
|
|
@ -250,7 +283,7 @@ class DhlTrackingService
|
|||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Abrufen der Tracking-Informationen: ' . $e->getMessage(),
|
||||
'message' => 'Fehler beim Abrufen der Tracking-Informationen: '.$e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -302,7 +335,7 @@ class DhlTrackingService
|
|||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Einreihen des Tracking-Updates: ' . $e->getMessage(),
|
||||
'message' => 'Fehler beim Einreihen des Tracking-Updates: '.$e->getMessage(),
|
||||
'queued' => false,
|
||||
];
|
||||
}
|
||||
|
|
@ -333,17 +366,31 @@ class DhlTrackingService
|
|||
$result = $this->trackShipment($shipment->dhl_shipment_no);
|
||||
|
||||
if ($result['success']) {
|
||||
$internalStatus = $this->mapDhlStatusToInternal($result['status']);
|
||||
|
||||
// Update shipment with tracking data
|
||||
$shipment->update([
|
||||
'status' => $this->mapDhlStatusToInternal($result['status']),
|
||||
$updateData = [
|
||||
'status' => $internalStatus,
|
||||
'tracking_status' => $result['status_text'],
|
||||
'last_tracked_at' => now(),
|
||||
]);
|
||||
];
|
||||
|
||||
// Mark tracking as completed if terminal status reached
|
||||
if (in_array($internalStatus, DhlShipment::TERMINAL_STATUSES)) {
|
||||
$updateData['tracking_completed_at'] = now();
|
||||
}
|
||||
|
||||
$shipment->update($updateData);
|
||||
|
||||
// Save tracking events
|
||||
$this->saveTrackingEvents($shipment, $result['events'] ?? []);
|
||||
|
||||
Log::info('[DHL Tracking Service] Tracking updated successfully (sync)', [
|
||||
'shipment_id' => $shipment->id,
|
||||
'dhl_shipment_no' => $shipment->dhl_shipment_no,
|
||||
'tracking_status' => $result['status'],
|
||||
'tracking_completed' => in_array($internalStatus, DhlShipment::TERMINAL_STATUSES),
|
||||
'events_count' => count($result['events'] ?? []),
|
||||
'api_used' => $result['api_used'],
|
||||
]);
|
||||
|
||||
|
|
@ -353,6 +400,7 @@ class DhlTrackingService
|
|||
'queued' => false,
|
||||
'shipment_id' => $shipment->id,
|
||||
'tracking_status' => $result['status'],
|
||||
'tracking_completed' => in_array($internalStatus, DhlShipment::TERMINAL_STATUSES),
|
||||
'tracking_details' => $result,
|
||||
];
|
||||
} else {
|
||||
|
|
@ -371,13 +419,177 @@ class DhlTrackingService
|
|||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Aktualisieren der Tracking-Informationen: ' . $e->getMessage(),
|
||||
'message' => 'Fehler beim Aktualisieren der Tracking-Informationen: '.$e->getMessage(),
|
||||
'queued' => false,
|
||||
'shipment_id' => $shipment->id,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tracking for a batch of DHL shipments using the multi-tracking API.
|
||||
* Processes shipments in chunks of 10 (DHL API limit) with rate-limiting pauses.
|
||||
*
|
||||
* @param Collection<DhlShipment> $shipments
|
||||
* @return array{updated: int, failed: int, completed: int, results: array}
|
||||
*/
|
||||
public function updateTrackingBatch(Collection $shipments): array
|
||||
{
|
||||
$stats = [
|
||||
'updated' => 0,
|
||||
'failed' => 0,
|
||||
'completed' => 0,
|
||||
'results' => [],
|
||||
];
|
||||
|
||||
// Process in chunks of 10 (DHL API limit)
|
||||
$chunks = $shipments->chunk(10);
|
||||
$chunkIndex = 0;
|
||||
|
||||
foreach ($chunks as $chunk) {
|
||||
// Rate limiting: pause 1 second between batch API calls
|
||||
if ($chunkIndex > 0) {
|
||||
sleep(1);
|
||||
}
|
||||
$chunkIndex++;
|
||||
|
||||
// Build tracking number => shipment mapping
|
||||
$shipmentMap = [];
|
||||
foreach ($chunk as $shipment) {
|
||||
$shipmentMap[$shipment->dhl_shipment_no] = $shipment;
|
||||
}
|
||||
|
||||
$trackingNumbers = array_keys($shipmentMap);
|
||||
|
||||
try {
|
||||
$batchResult = $this->trackMultipleShipments($trackingNumbers);
|
||||
|
||||
if ($batchResult['success'] && ! empty($batchResult['shipments'])) {
|
||||
// Process each result from the batch API
|
||||
foreach ($batchResult['shipments'] as $trackingResult) {
|
||||
$trackingNo = $trackingResult['tracking_number'];
|
||||
$shipment = $shipmentMap[$trackingNo] ?? null;
|
||||
|
||||
if (! $shipment) {
|
||||
Log::warning('[DHL Tracking Service] Batch: tracking number not mapped', [
|
||||
'tracking_number' => $trackingNo,
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove from map so we can detect missing ones later
|
||||
unset($shipmentMap[$trackingNo]);
|
||||
|
||||
$internalStatus = $this->mapDhlStatusToInternal($trackingResult['status']);
|
||||
|
||||
$updateData = [
|
||||
'status' => $internalStatus,
|
||||
'tracking_status' => $trackingResult['status_text'],
|
||||
'last_tracked_at' => now(),
|
||||
];
|
||||
|
||||
// Mark tracking as completed if terminal status reached
|
||||
$isCompleted = in_array($internalStatus, DhlShipment::TERMINAL_STATUSES);
|
||||
if ($isCompleted) {
|
||||
$updateData['tracking_completed_at'] = now();
|
||||
$stats['completed']++;
|
||||
}
|
||||
|
||||
$shipment->update($updateData);
|
||||
|
||||
// Save tracking events
|
||||
$this->saveTrackingEvents($shipment, $trackingResult['events'] ?? []);
|
||||
|
||||
$stats['updated']++;
|
||||
$stats['results'][] = [
|
||||
'shipment_id' => $shipment->id,
|
||||
'tracking_number' => $trackingNo,
|
||||
'status' => $internalStatus,
|
||||
'completed' => $isCompleted,
|
||||
'success' => true,
|
||||
];
|
||||
}
|
||||
|
||||
// Any remaining shipments in the map were not returned by the API
|
||||
foreach ($shipmentMap as $trackingNo => $shipment) {
|
||||
// Update last_tracked_at so we don't immediately retry
|
||||
$shipment->update(['last_tracked_at' => now()]);
|
||||
$stats['failed']++;
|
||||
$stats['results'][] = [
|
||||
'shipment_id' => $shipment->id,
|
||||
'tracking_number' => $trackingNo,
|
||||
'success' => false,
|
||||
'message' => 'Nicht in Batch-Antwort enthalten',
|
||||
];
|
||||
}
|
||||
} else {
|
||||
// Entire batch failed - fall back to individual tracking
|
||||
Log::warning('[DHL Tracking Service] Batch tracking failed, falling back to individual tracking', [
|
||||
'tracking_numbers' => $trackingNumbers,
|
||||
'message' => $batchResult['message'] ?? 'Unknown error',
|
||||
]);
|
||||
|
||||
foreach ($chunk as $shipment) {
|
||||
try {
|
||||
$result = $this->updateTracking($shipment, ['auto_retrack' => false]);
|
||||
if ($result['success']) {
|
||||
$stats['updated']++;
|
||||
if (! empty($result['tracking_completed'])) {
|
||||
$stats['completed']++;
|
||||
}
|
||||
} else {
|
||||
$stats['failed']++;
|
||||
}
|
||||
$stats['results'][] = [
|
||||
'shipment_id' => $shipment->id,
|
||||
'tracking_number' => $shipment->dhl_shipment_no,
|
||||
'success' => $result['success'],
|
||||
'fallback' => true,
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
$stats['failed']++;
|
||||
$stats['results'][] = [
|
||||
'shipment_id' => $shipment->id,
|
||||
'tracking_number' => $shipment->dhl_shipment_no,
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
'fallback' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Tracking Service] Batch tracking exception', [
|
||||
'tracking_numbers' => $trackingNumbers,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
// Mark all as failed but update last_tracked_at
|
||||
foreach ($chunk as $shipment) {
|
||||
$shipment->update(['last_tracked_at' => now()]);
|
||||
$stats['failed']++;
|
||||
$stats['results'][] = [
|
||||
'shipment_id' => $shipment->id,
|
||||
'tracking_number' => $shipment->dhl_shipment_no,
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log::info('[DHL Tracking Service] Batch tracking completed', [
|
||||
'total' => $shipments->count(),
|
||||
'updated' => $stats['updated'],
|
||||
'failed' => $stats['failed'],
|
||||
'completed' => $stats['completed'],
|
||||
'chunks' => $chunks->count(),
|
||||
]);
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map DHL status codes to internal status
|
||||
*/
|
||||
|
|
@ -414,6 +626,39 @@ class DhlTrackingService
|
|||
return $descriptions[$statusCode] ?? 'Unbekannter Status';
|
||||
}
|
||||
|
||||
/**
|
||||
* Save tracking events from API response to database
|
||||
*/
|
||||
private function saveTrackingEvents(DhlShipment $shipment, array $events): void
|
||||
{
|
||||
if (empty($events)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($events as $event) {
|
||||
$eventTime = isset($event['timestamp']) ? \Carbon\Carbon::parse($event['timestamp']) : now();
|
||||
|
||||
// Upsert: avoid duplicates based on shipment + event_time + status_code
|
||||
DhlTrackingEvent::updateOrCreate(
|
||||
[
|
||||
'shipment_id' => $shipment->id,
|
||||
'event_time' => $eventTime,
|
||||
'status_code' => $event['statusCode'] ?? ($event['status'] ?? 'unknown'),
|
||||
],
|
||||
[
|
||||
'status_text' => $event['description'] ?? ($event['remark'] ?? 'Unbekannt'),
|
||||
'location' => $event['location']['address']['addressLocality'] ?? null,
|
||||
'raw' => $event,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Log::info('[DHL Tracking Service] Tracking events saved', [
|
||||
'shipment_id' => $shipment->id,
|
||||
'events_saved' => count($events),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SSL version constant based on configuration
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Mail\MailInvoice;
|
||||
|
|
@ -8,60 +9,171 @@ use Illuminate\Support\Facades\Mail;
|
|||
|
||||
class Invoice
|
||||
{
|
||||
|
||||
public static function getInvoiceNumber(){
|
||||
public static function getInvoiceNumber()
|
||||
{
|
||||
return (int) Setting::getContentBySlug('invoice-number');
|
||||
}
|
||||
|
||||
public static function makeNextInvoiceNumber(){
|
||||
$invoice_number = self::getInvoiceNumber();
|
||||
$invoice_number = $invoice_number+1;
|
||||
Setting::setContentBySlug('invoice-number', $invoice_number, 'int');
|
||||
return $invoice_number;
|
||||
/**
|
||||
* Atomically get and increment the invoice number with database locking
|
||||
* to prevent race conditions when multiple invoices are created simultaneously
|
||||
*/
|
||||
public static function makeNextInvoiceNumber()
|
||||
{
|
||||
return \DB::transaction(function () {
|
||||
// Lock the setting row for update to prevent concurrent reads
|
||||
$setting = Setting::where('slug', 'invoice-number')
|
||||
->lockForUpdate()
|
||||
->first();
|
||||
|
||||
if (! $setting) {
|
||||
// Create if not exists
|
||||
$setting = Setting::create([
|
||||
'slug' => 'invoice-number',
|
||||
'type' => 'int',
|
||||
'int' => 1,
|
||||
]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
$invoice_number = (int) $setting->int;
|
||||
$invoice_number = $invoice_number + 1;
|
||||
|
||||
// Update directly on the locked row
|
||||
$setting->int = $invoice_number;
|
||||
$setting->save();
|
||||
|
||||
return $invoice_number;
|
||||
});
|
||||
}
|
||||
|
||||
public static function createInvoiceNumber($invoice_number, $invoice_date){
|
||||
public static function createInvoiceNumber($invoice_number, $invoice_date)
|
||||
{
|
||||
$prefix = \Carbon::parse($invoice_date)->format('Y');
|
||||
$invoice_number = str_pad($invoice_number, 5, '0', STR_PAD_LEFT);
|
||||
|
||||
return $prefix.$invoice_number;
|
||||
}
|
||||
|
||||
public static function getInvoiceStorageDir($invoice_date){
|
||||
return "invoice/".\Carbon::parse($invoice_date)->format('Y/m/');
|
||||
public static function getInvoiceStorageDir($invoice_date)
|
||||
{
|
||||
return 'invoice/'.\Carbon::parse($invoice_date)->format('Y/m/');
|
||||
}
|
||||
|
||||
public static function getDeliveryStorageDir($invoice_date){
|
||||
return "delivery/".\Carbon::parse($invoice_date)->format('Y/m/');
|
||||
public static function getDeliveryStorageDir($invoice_date)
|
||||
{
|
||||
return 'delivery/'.\Carbon::parse($invoice_date)->format('Y/m/');
|
||||
}
|
||||
|
||||
public static function makeInvoiceFilename($invoice_number){
|
||||
return $invoice_number."-MIVITA-Rechnung.pdf";
|
||||
public static function makeInvoiceFilename($invoice_number)
|
||||
{
|
||||
return $invoice_number.'-MIVITA-Rechnung.pdf';
|
||||
}
|
||||
|
||||
public static function makeDeliveryFilename($invoice_number){
|
||||
return $invoice_number."-MIVITA-Lieferschein.pdf";
|
||||
public static function makeDeliveryFilename($invoice_number)
|
||||
{
|
||||
return $invoice_number.'-MIVITA-Lieferschein.pdf';
|
||||
}
|
||||
|
||||
public static function isInvoice(ShoppingOrder $shopping_order){
|
||||
/**
|
||||
* Erstellt den Dateinamen für eine Stornorechnung
|
||||
*
|
||||
* @param string $invoice_number
|
||||
* @return string
|
||||
*/
|
||||
public static function makeCancellationFilename($invoice_number)
|
||||
{
|
||||
return $invoice_number.'-MIVITA-Stornorechnung.pdf';
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt den Dateinamen für einen Storno-Lieferschein
|
||||
*
|
||||
* @param string $invoice_number
|
||||
* @return string
|
||||
*/
|
||||
public static function makeCancellationDeliveryFilename($invoice_number)
|
||||
{
|
||||
return $invoice_number.'-MIVITA-Storno-Lieferschein.pdf';
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt den Dateinamen für eine lokalisierte Rechnung.
|
||||
* Deutsch (de) ist das Original ohne Suffix.
|
||||
*
|
||||
* @param string $invoice_number
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
public static function makeInvoiceFilenameLocale($invoice_number, $locale)
|
||||
{
|
||||
if ($locale === 'de' || ! $locale) {
|
||||
return self::makeInvoiceFilename($invoice_number);
|
||||
}
|
||||
|
||||
return $invoice_number.'-MIVITA-Rechnung-'.$locale.'.pdf';
|
||||
}
|
||||
|
||||
/**
|
||||
* Erstellt den Dateinamen für einen lokalisierten Lieferschein.
|
||||
* Deutsch (de) ist das Original ohne Suffix.
|
||||
*
|
||||
* @param string $invoice_number
|
||||
* @param string $locale
|
||||
* @return string
|
||||
*/
|
||||
public static function makeDeliveryFilenameLocale($invoice_number, $locale)
|
||||
{
|
||||
if ($locale === 'de' || ! $locale) {
|
||||
return self::makeDeliveryFilename($invoice_number);
|
||||
}
|
||||
|
||||
return $invoice_number.'-MIVITA-Lieferschein-'.$locale.'.pdf';
|
||||
}
|
||||
|
||||
public static function isInvoice(ShoppingOrder $shopping_order)
|
||||
{
|
||||
return $shopping_order->isInvoice();
|
||||
}
|
||||
|
||||
public static function sendInvoiceMail($shopping_order, $user_invoice){
|
||||
/**
|
||||
* Holt die Rechnungsnummer einer Bestellung
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getNumber(ShoppingOrder $shopping_order)
|
||||
{
|
||||
return $shopping_order->user_invoice ? $shopping_order->user_invoice->full_number : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt das Rechnungsdatum einer Bestellung
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public static function getDate(ShoppingOrder $shopping_order)
|
||||
{
|
||||
return $shopping_order->user_invoice ? $shopping_order->user_invoice->date : null;
|
||||
}
|
||||
|
||||
public static function sendInvoiceMail($shopping_order, $user_invoice)
|
||||
{
|
||||
$bcc = [];
|
||||
$billing_email = $shopping_order->shopping_user->billing_email;
|
||||
if(!$billing_email){
|
||||
if($shopping_order->mode === 'test'){
|
||||
if (! $billing_email) {
|
||||
if ($shopping_order->mode === 'test') {
|
||||
$billing_email = config('app.checkout_test_mail');
|
||||
}else{
|
||||
} else {
|
||||
$billing_email = config('app.checkout_mail');
|
||||
}
|
||||
}
|
||||
if($shopping_order->mode === 'test'){
|
||||
if ($shopping_order->mode === 'test') {
|
||||
$bcc[] = config('app.checkout_test_mail');
|
||||
}else{
|
||||
} else {
|
||||
$bcc[] = config('app.checkout_mail');
|
||||
}
|
||||
|
||||
|
||||
Mail::to($billing_email)->bcc($bcc)->locale($shopping_order->getLocale())->send(new MailInvoice($shopping_order, $user_invoice));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,19 +2,18 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\ShoppingInstance;
|
||||
use App\Models\ShoppingUser;
|
||||
use Yard;
|
||||
|
||||
class OrderPaymentService
|
||||
{
|
||||
|
||||
public static function deleteInstance($identifier)
|
||||
{
|
||||
|
||||
Yard::instance('shopping')->deleteStoredCart($identifier);
|
||||
\App\Models\ShoppingInstance::where('identifier', $identifier)->delete();
|
||||
//delete session
|
||||
\App\Models\ShoppingInstance::where('identifier', $identifier)->delete();
|
||||
// delete session
|
||||
/* if(\Session::has('user_shop_payment') && \Session::get('user_shop_payment') === 6){
|
||||
$user_shop_identifier = \Session::get('user_shop_identifier');
|
||||
Yard::instance('shopping')->deleteStoredCart($identifier);
|
||||
|
|
@ -24,7 +23,7 @@ class OrderPaymentService
|
|||
|
||||
public static function updateInstanceStatus($identifier, $status, $lower = true)
|
||||
{
|
||||
if (!ShoppingInstance::where('identifier', $identifier)->exists()) {
|
||||
if (! ShoppingInstance::where('identifier', $identifier)->exists()) {
|
||||
return false;
|
||||
}
|
||||
if ($lower) {
|
||||
|
|
@ -39,9 +38,10 @@ class OrderPaymentService
|
|||
public static function getInstanceStatus($identifier)
|
||||
{
|
||||
$shopping_instance = ShoppingInstance::where('identifier', $identifier)->first();
|
||||
if (!$shopping_instance) {
|
||||
if (! $shopping_instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $shopping_instance->getStatus();
|
||||
}
|
||||
|
||||
|
|
@ -49,33 +49,39 @@ class OrderPaymentService
|
|||
{
|
||||
$isFor = $shoppingInstance->shopping_data['is_for'] ?? '-';
|
||||
if ($isFor === 'abo-ot-customer') {
|
||||
return ' <span class="badge badge-pill badge-warning">' . __('abo.abo') . '</span>';
|
||||
return ' <span class="badge badge-pill badge-warning">'.__('abo.abo').'</span>';
|
||||
}
|
||||
if ($isFor === 'ot-customer') {
|
||||
return ' <span class="badge badge-pill badge-secondary">' . __('order.order') . '</span>';
|
||||
return ' <span class="badge badge-pill badge-secondary">'.__('order.order').'</span>';
|
||||
}
|
||||
return "";
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function getStatusBadgeClasses()
|
||||
{
|
||||
return [
|
||||
'link_sent' => 'default',
|
||||
'link_openly' => 'info',
|
||||
'link_check' => 'warning',
|
||||
'link_pending' => 'warning',
|
||||
'link_appointed' => 'warning',
|
||||
'link_paid' => 'secondary',
|
||||
'link_failed' => 'danger',
|
||||
'link_canceled' => 'danger',
|
||||
];
|
||||
}
|
||||
|
||||
public static function getStatusBadge(ShoppingInstance $shoppingInstance)
|
||||
{
|
||||
$status = $shoppingInstance->getStatus();
|
||||
$badgeClasses = [
|
||||
'link_sent' => 'info',
|
||||
'link_openly' => 'info',
|
||||
'link_paid' => 'secondary',
|
||||
'link_check' => 'warning',
|
||||
'link_pending' => 'warning',
|
||||
'link_appointed' => 'warning',
|
||||
'link_failed' => 'danger',
|
||||
'link_canceled' => 'danger'
|
||||
];
|
||||
$badgeClasses = self::getStatusBadgeClasses();
|
||||
|
||||
if (isset($badgeClasses[$status])) {
|
||||
return sprintf(
|
||||
' <span class="badge badge-pill badge-%s">%s</span>',
|
||||
$badgeClasses[$status],
|
||||
__('payment.' . $status)
|
||||
__('payment.'.$status)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -100,7 +106,7 @@ class OrderPaymentService
|
|||
return sprintf(
|
||||
' <div class="alert alert-%s">%s</div>',
|
||||
$badgeClasses[$status],
|
||||
__('payment.alert_' . $status)
|
||||
__('payment.alert_'.$status)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -111,12 +117,12 @@ class OrderPaymentService
|
|||
{
|
||||
|
||||
$shopping_instance = ShoppingInstance::where('identifier', $identifier)->first();
|
||||
if (!$shopping_instance) {
|
||||
if (! $shopping_instance) {
|
||||
abort(403, __('msg.shopping_instance_not_found'));
|
||||
}
|
||||
$shopping_data = $shopping_instance->shopping_data;
|
||||
$shopping_user = $shopping_data['shopping_user_id'] ? ShoppingUser::find($shopping_data['shopping_user_id']) : null;
|
||||
if (!$shopping_user) {
|
||||
if (! $shopping_user) {
|
||||
abort(403, __('msg.shopping_user_not_found'));
|
||||
}
|
||||
$yard_shopping_items = self::getRestoredYardShoppingItems($shopping_instance);
|
||||
|
|
@ -130,6 +136,7 @@ class OrderPaymentService
|
|||
'is_for' => $shopping_instance->shopping_data['is_for'] ?? false,
|
||||
'backlink' => false,
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
|
@ -145,7 +152,6 @@ class OrderPaymentService
|
|||
Yard::instance('shopping')->setUserPriceInfos($shopping_instance->shopping_data['user_price_infos']);
|
||||
Yard::instance('shopping')->setShippingCountryWithPrice($shopping_instance->country_id, $is_for);
|
||||
|
||||
|
||||
$rows = Yard::instance('shopping')->getContentByOrder();
|
||||
$ret = [];
|
||||
$ret['items'] = [];
|
||||
|
|
@ -154,12 +160,12 @@ class OrderPaymentService
|
|||
|
||||
foreach ($rows as $row) {
|
||||
$product = \App\Models\Product::find($row->id);
|
||||
$item = new \stdClass();
|
||||
$item = new \stdClass;
|
||||
$item->image = $row->options->has('image') ? $row->options->image : null;
|
||||
$item->price_net = (float) Yard::instance('shopping')->rowPriceNet($row, 3, '.', '');
|
||||
$item->price_net_total = (float) Yard::instance('shopping')->rowSubtotalNet($row, 2, '.', '');
|
||||
$item->price_currency = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('rowPriceNetCurrency', $row, 3) . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$item->price_currency_total = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('rowSubtotalCurrency', $row, 3) . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$item->price_currency = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('rowPriceNetCurrency', $row, 3).' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$item->price_currency_total = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('rowSubtotalCurrency', $row, 3).' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$item->price = $row->price;
|
||||
$item->price_total = ($row->qty * $row->price);
|
||||
$item->qty = $row->qty;
|
||||
|
|
@ -174,16 +180,16 @@ class OrderPaymentService
|
|||
|
||||
$ret['tax_free'] = $tax_free;
|
||||
$ret['total']['subtotal'] = Yard::instance('shopping')->subtotal();
|
||||
$ret['total']['subtotal_currency'] = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('subtotal') . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['subtotal_currency'] = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('subtotal').' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['shippingCountryName'] = Yard::instance('shopping')->getShippingCountryName();
|
||||
$ret['total']['shippingNet'] = Yard::instance('shopping')->shippingNet();
|
||||
$ret['total']['shippingNet currency'] = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('shippingNet') . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['shippingNet currency'] = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('shippingNet').' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['subtotalWithShipping'] = Yard::instance('shopping')->subtotalWithShipping();
|
||||
$ret['total']['subtotalWithShipping_currency'] = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('subtotalWithShipping') . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['subtotalWithShipping_currency'] = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('subtotalWithShipping').' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['taxWithShipping'] = Yard::instance('shopping')->taxWithShipping();
|
||||
$ret['total']['taxWithShipping_currency'] = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('taxWithShipping') . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['taxWithShipping_currency'] = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('taxWithShipping').' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['totalWithShipping'] = Yard::instance('shopping')->totalWithShipping();
|
||||
$ret['total']['totalWithShipping_currency'] = $is_currency ? "~" . Yard::instance('shopping')->getCurrencyByKey('totalWithShipping') . " " . Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
$ret['total']['totalWithShipping_currency'] = $is_currency ? '~'.Yard::instance('shopping')->getCurrencyByKey('totalWithShipping').' '.Yard::instance('shopping')->getPriceCurrencyUnit() : null;
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
|
||||
use App\Mail\MailCheckout;
|
||||
use App\Models\ProductBuying;
|
||||
use App\Models\ShoppingOrder;
|
||||
|
|
@ -10,26 +9,22 @@ use App\Models\ShoppingPayment;
|
|||
use App\Models\UserCreditItem;
|
||||
use App\Models\UserLevel;
|
||||
use App\Repositories\InvoiceRepository;
|
||||
use App\Services\AboHelper;
|
||||
use App\Services\BusinessPlan\SalesPointsVolume;
|
||||
use App\Services\ShopApiOrderCart;
|
||||
use App\Services\UserUtil;
|
||||
use App\Services\Util;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class Payment
|
||||
{
|
||||
|
||||
public static $txaction_text = [
|
||||
'paid' => 'paid',
|
||||
'appointed' => 'open',
|
||||
'failed' => 'failed',
|
||||
'extern' => 'open', //offen
|
||||
'extern' => 'open', // offen
|
||||
'extern_paid' => 'paid',
|
||||
'invoice_open' => 'open',
|
||||
'invoice_paid' => 'paid',
|
||||
'invoice_non' => 'no_payment',
|
||||
'cancelled' => 'cancelled',
|
||||
'NULL' => 'no_payment',
|
||||
];
|
||||
|
||||
|
|
@ -37,11 +32,12 @@ class Payment
|
|||
'paid' => 'paymend_paid',
|
||||
'appointed' => 'paymend_open',
|
||||
'failed' => 'paymend_failed',
|
||||
'extern' => 'extern_open', //offen
|
||||
'extern' => 'extern_open', // offen
|
||||
'extern_paid' => 'extern_paid',
|
||||
'invoice_open' => 'invoice_open',
|
||||
'invoice_paid' => 'invoice_paid',
|
||||
'invoice_non' => 'invoice_no_payment',
|
||||
'cancelled' => 'cancelled',
|
||||
'NULL' => 'no_payment',
|
||||
];
|
||||
|
||||
|
|
@ -60,15 +56,16 @@ class Payment
|
|||
'invoice_open' => 'warning',
|
||||
'invoice_paid' => 'success',
|
||||
'invoice_non' => 'failed',
|
||||
'cancelled' => 'danger',
|
||||
];
|
||||
|
||||
|
||||
public static function getFormattedTxaction($txaction)
|
||||
{
|
||||
if ($txaction && isset(self::$txaction_text[$txaction])) {
|
||||
return __('payment.' . self::$txaction_text[$txaction]);
|
||||
return __('payment.'.self::$txaction_text[$txaction]);
|
||||
}
|
||||
return __('payment.' . self::$txaction_text['NULL']);
|
||||
|
||||
return __('payment.'.self::$txaction_text['NULL']);
|
||||
}
|
||||
|
||||
public static function getFormattedTxactionColor($txaction)
|
||||
|
|
@ -76,15 +73,17 @@ class Payment
|
|||
if ($txaction && isset(self::$txaction_color[$txaction])) {
|
||||
return self::$txaction_color[$txaction];
|
||||
}
|
||||
return "warning";
|
||||
|
||||
return 'warning';
|
||||
}
|
||||
|
||||
public static function getTransTxactionFilterText()
|
||||
{
|
||||
$ret = [];
|
||||
foreach (self::$txaction_filter_text as $key => $val) {
|
||||
$ret[$key] = trans('payment.' . $val);
|
||||
$ret[$key] = trans('payment.'.$val);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
|
@ -92,8 +91,9 @@ class Payment
|
|||
{
|
||||
$ret = [];
|
||||
foreach (self::$txaction_invoice as $key => $val) {
|
||||
$ret[$key] = trans('payment.' . $val);
|
||||
$ret[$key] = trans('payment.'.$val);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
|
@ -101,29 +101,32 @@ class Payment
|
|||
{
|
||||
|
||||
if ($shopping_order->mode === 'test') {
|
||||
return '<span class="badge badge-pill badge-default">' . strtoupper($shopping_order->mode) . ' - ' . self::getFormattedTxaction($shopping_order->txaction) . '</span>';
|
||||
return '<span class="badge badge-pill badge-default">'.strtoupper($shopping_order->mode).' - '.self::getFormattedTxaction($shopping_order->txaction).'</span>';
|
||||
}
|
||||
if ($shopping_order->mode === 'dev') {
|
||||
return '<span class="badge badge-pill badge-info">' . strtoupper($shopping_order->mode) . ' - ' . self::getFormattedTxaction($shopping_order->txaction) . '</span>';
|
||||
return '<span class="badge badge-pill badge-info">'.strtoupper($shopping_order->mode).' - '.self::getFormattedTxaction($shopping_order->txaction).'</span>';
|
||||
}
|
||||
return '<span class="badge badge-pill badge-' . self::getFormattedTxactionColor($shopping_order->txaction) . '">' . self::getFormattedTxaction($shopping_order->txaction) . '</span>';
|
||||
|
||||
return '<span class="badge badge-pill badge-'.self::getFormattedTxactionColor($shopping_order->txaction).'">'.self::getFormattedTxaction($shopping_order->txaction).'</span>';
|
||||
}
|
||||
|
||||
public static function getPaymentForBadge(ShoppingOrder $shopping_order)
|
||||
{
|
||||
$abo = '';
|
||||
if ($shopping_order->is_abo) {
|
||||
$abo = ' <span class="badge badge-pill badge-success">' . __('abo.abo') . '</span>';
|
||||
$abo = ' <span class="badge badge-pill badge-success">'.__('abo.abo').'</span>';
|
||||
}
|
||||
return '<span class="badge badge-pill badge-' . $shopping_order->getPaymentForColor() . '">' . $shopping_order->getPaymentForType() . '</span>' . $abo;
|
||||
|
||||
return '<span class="badge badge-pill badge-'.$shopping_order->getPaymentForColor().'">'.$shopping_order->getPaymentForType().'</span>'.$abo;
|
||||
}
|
||||
|
||||
public static function getShoppingPaymentBadge(ShoppingPayment $shopping_payment)
|
||||
{
|
||||
if ($shopping_payment->mode === 'test') {
|
||||
return '<span class="badge badge-pill badge-default">' . strtoupper($shopping_payment->mode) . ' - ' . self::getFormattedTxaction($shopping_payment->txaction) . '</span>';
|
||||
return '<span class="badge badge-pill badge-default">'.strtoupper($shopping_payment->mode).' - '.self::getFormattedTxaction($shopping_payment->txaction).'</span>';
|
||||
}
|
||||
return '<span class="badge badge-pill badge-' . self::getFormattedTxactionColor($shopping_payment->txaction) . '">' . self::getFormattedTxaction($shopping_payment->txaction) . '</span>';
|
||||
|
||||
return '<span class="badge badge-pill badge-'.self::getFormattedTxactionColor($shopping_payment->txaction).'">'.self::getFormattedTxaction($shopping_payment->txaction).'</span>';
|
||||
}
|
||||
|
||||
public static function addUserCreditMargin(User $user, $credit, $status, $message)
|
||||
|
|
@ -133,7 +136,7 @@ class Payment
|
|||
'credit' => $credit,
|
||||
'message' => $message,
|
||||
'from_month' => date('n'),
|
||||
'from_year' => date('Y'),
|
||||
'from_year' => date('Y'),
|
||||
'status' => $status,
|
||||
]);
|
||||
}
|
||||
|
|
@ -143,7 +146,7 @@ class Payment
|
|||
ProductBuying::create([
|
||||
'user_id' => $user->id,
|
||||
'product_id' => $product_id,
|
||||
'amount' => 1
|
||||
'amount' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -155,9 +158,9 @@ class Payment
|
|||
'user_id' => $user->user_sponsor->id,
|
||||
'total_net' => 0,
|
||||
'points' => $product->sponsor_buying_points_amount,
|
||||
'info' => 'VP: ' . $user->getFullName(false) . ' | ' . $product->name,
|
||||
'info' => 'VP: '.$user->getFullName(false).' | '.$product->name,
|
||||
'status_points' => 2,
|
||||
'status' => 5
|
||||
'status' => 5,
|
||||
];
|
||||
SalesPointsVolume::addSalesPointsVolume($data);
|
||||
}
|
||||
|
|
@ -165,7 +168,7 @@ class Payment
|
|||
|
||||
public static function updateUserLevel(User $user, $to_level_id)
|
||||
{
|
||||
//nur updaten, wenn der user->m_level kleiner ist als $to_level_id
|
||||
// nur updaten, wenn der user->m_level kleiner ist als $to_level_id
|
||||
if ($user->user_level) {
|
||||
$ToUserLevel = UserLevel::find($to_level_id);
|
||||
if ($user->user_level->pos < $ToUserLevel->pos) {
|
||||
|
|
@ -190,7 +193,7 @@ class Payment
|
|||
$shopping_order->paid = $paid;
|
||||
$shopping_order->save();
|
||||
|
||||
//if product has actions
|
||||
// if product has actions
|
||||
if ($shopping_order->shopping_order_items && $shopping_order->auth_user_id) {
|
||||
foreach ($shopping_order->shopping_order_items as $shopping_order_item) {
|
||||
if ($shopping_order_item->product) {
|
||||
|
|
@ -204,17 +207,19 @@ class Payment
|
|||
}
|
||||
if ($shopping_order_item->product->action) {
|
||||
$send_link = true;
|
||||
//new date
|
||||
// new date
|
||||
$date = \Carbon::now()->modify('1 year');
|
||||
if ($user->payment_account && $user->daysActiveAccount() > 0) {
|
||||
$date = \Carbon::parse($user->payment_account)->modify('1 year');
|
||||
}
|
||||
foreach ($shopping_order_item->product->action as $do) {
|
||||
// bzw. product_id 34 = 0 => payment_for_account => payment_order_id = 35 = 0 => payment_for_account, 1 => payment_for_shop, 2 => payment_for_shop_upgrade
|
||||
// 0 => payment_for_account, 1 => payment_for_shop, 2 => payment_for_shop_upgrade
|
||||
if ($shopping_order_item->product->getActionName($do) === 'payment_for_account') {
|
||||
$user->payment_order_id = $shopping_order_item->product->id; //34
|
||||
$user->payment_order_id = $shopping_order_item->product->id;
|
||||
$user->payment_account = $date;
|
||||
$user->wizard = 100;
|
||||
//only date is > now and acount is deactive.
|
||||
// only date is > now and acount is deactive.
|
||||
if ($date > \Carbon::now()) {
|
||||
if ($user->active === 0) {
|
||||
$user->active = true;
|
||||
|
|
@ -224,19 +229,22 @@ class Payment
|
|||
|
||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
||||
}
|
||||
// 1 => payment_for_shop
|
||||
if ($shopping_order_item->product->getActionName($do) === 'payment_for_shop') {
|
||||
$user->payment_order_id = $shopping_order_item->product->id; //35
|
||||
$user->payment_order_id = $shopping_order_item->product->id; // 35
|
||||
$user->payment_shop = $date;
|
||||
$user->wizard = 100;
|
||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
||||
}
|
||||
// 2 => payment_for_shop_upgrade
|
||||
if ($shopping_order_item->product->getActionName($do) === 'payment_for_shop_upgrade') {
|
||||
if ($shopping_order_item->product->upgrade_to_id) {
|
||||
$user->payment_order_id = $shopping_order_item->product->upgrade_to_id;
|
||||
}
|
||||
$user->payment_shop = $user->payment_account; //same Date, is upgrade
|
||||
$user->payment_shop = $user->payment_account; // same Date, is upgrade
|
||||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
||||
}
|
||||
// 4 => payment_for_lead_upgrade
|
||||
if ($shopping_order_item->product->getActionName($do) === 'payment_for_lead_upgrade') {
|
||||
if ($shopping_order_item->product->upgrade_to_id) {
|
||||
self::updateUserLevel($user, $shopping_order_item->product->upgrade_to_id);
|
||||
|
|
@ -259,20 +267,26 @@ class Payment
|
|||
$shopping_order->setUserHistoryValue(['status' => 9]);
|
||||
ShopApiOrderCart::finishOrder($shopping_order->shopping_collect_order);
|
||||
}
|
||||
//the Order is Pay, so we can set the Status in the Abo
|
||||
|
||||
// Set payment link status to paid for all orders
|
||||
if ($shopping_payment) {
|
||||
Util::setInstanceStatusByPayment($shopping_payment, 10); // link_paid
|
||||
$shopping_payment->identifier = null;
|
||||
$shopping_payment->save();
|
||||
}
|
||||
|
||||
// the Order is Pay, so we can set the Status in the Abo
|
||||
if ($shopping_order->is_abo) {
|
||||
if ($shopping_payment) {
|
||||
Util::setInstanceStatusByPayment($shopping_payment, 10); //link_paid
|
||||
$shopping_payment->identifier = null;
|
||||
$shopping_payment->save();
|
||||
}
|
||||
AboHelper::setAboActive($shopping_order, 2, true);
|
||||
}
|
||||
|
||||
//make Invoice is not exist and is live
|
||||
// make Invoice is not exist and is live
|
||||
if ($shopping_order->mode === 'live' || Util::isTestSystem(true)) {
|
||||
$invoice_repo = new InvoiceRepository($shopping_order);
|
||||
if (!$shopping_order->isInvoice()) {
|
||||
// Reload the shopping order to check for invoice again (defense against race conditions)
|
||||
$shopping_order->refresh();
|
||||
|
||||
if (! $shopping_order->isInvoice()) {
|
||||
$invoice_repo = new InvoiceRepository($shopping_order);
|
||||
$invoice_repo->createAndSalesVolume();
|
||||
}
|
||||
}
|
||||
|
|
@ -287,15 +301,15 @@ class Payment
|
|||
|
||||
// Überprüfung der Billing-E-Mail-Adresse
|
||||
|
||||
if (!$billing_email) {
|
||||
if (! $billing_email) {
|
||||
if ($data['mode'] === 'test') {
|
||||
$billing_email = config('app.checkout_test_mail');
|
||||
} else {
|
||||
$billing_email = config('app.checkout_mail');
|
||||
}
|
||||
}
|
||||
if (!filter_var($billing_email, FILTER_VALIDATE_EMAIL)) {
|
||||
\Log::channel('payment')->error("Invalid billing email at shopping_order " . $shopping_order->id, ['billing_email' => $billing_email]);
|
||||
if (! filter_var($billing_email, FILTER_VALIDATE_EMAIL)) {
|
||||
\Log::channel('payment')->error('Invalid billing email at shopping_order '.$shopping_order->id, ['billing_email' => $billing_email]);
|
||||
$billing_email = config('app.checkout_mail');
|
||||
}
|
||||
|
||||
|
|
@ -305,7 +319,7 @@ class Payment
|
|||
$bcc[] = config('app.checkout_mail');
|
||||
}
|
||||
|
||||
if (!$shopping_order->shopping_user->is_like && $shopping_order->shopping_user->member) {
|
||||
if (! $shopping_order->shopping_user->is_like && $shopping_order->shopping_user->member) {
|
||||
$bcc[] = $shopping_order->shopping_user->member->email;
|
||||
}
|
||||
$data['payment_error'] = isset($data['payment_error']) ? $data['payment_error'] : false;
|
||||
|
|
|
|||
|
|
@ -2,24 +2,20 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
use Yard;
|
||||
use App\User;
|
||||
use App\Models\UserHistory;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Http\Controllers\Pay\PayoneController;
|
||||
use App\Models\PaymentTransaction;
|
||||
use App\Models\ShoppingOrder;
|
||||
use App\Models\ShoppingOrderItem;
|
||||
use App\Models\PaymentTransaction;
|
||||
use App\Http\Controllers\Pay\PayoneController;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\UserHistory;
|
||||
use Yard;
|
||||
|
||||
class PaymentHelper
|
||||
{
|
||||
|
||||
|
||||
|
||||
public function setProduct($product)
|
||||
{
|
||||
Yard::instance('shopping')->destroy();
|
||||
Yard::instance('shopping')->add($product->id, $product->getLang('name'), 1, $product->price, false, false, ['image' => "", 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'show_on' => $product->show_on]);
|
||||
Yard::instance('shopping')->add($product->id, $product->getLang('name'), 1, $product->price, false, false, ['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]);
|
||||
}
|
||||
|
||||
public function initELVPayment($user)
|
||||
|
|
@ -28,17 +24,16 @@ class PaymentHelper
|
|||
$shopping_user = $this->makeShoppingUser($user);
|
||||
$shopping_order = $this->makeShoppingOrder($user, $shopping_user);
|
||||
|
||||
|
||||
$pay = new PayoneController();
|
||||
$pay = new PayoneController;
|
||||
$pay->init($shopping_user, $shopping_order);
|
||||
$amount = Yard::instance('shopping')->totalWithShipping(2, '.', '') * 100;
|
||||
|
||||
$payment_method = 'elv';
|
||||
$ret['elv']['mandate_identification'] = isset($user->account->payment_data['mandate_identification']) ? $user->account->payment_data['mandate_identification'] : "";
|
||||
$ret['elv']['creditor_identifier'] = isset($user->account->payment_data['creditor_identifier']) ? $user->account->payment_data['creditor_identifier'] : "";
|
||||
$ret['elv']['iban'] = isset($user->account->payment_data['iban']) ? $user->account->payment_data['iban'] : "";
|
||||
$ret['elv']['bic'] = isset($user->account->payment_data['bic']) ? $user->account->payment_data['bic'] : "";
|
||||
$ret['elv']['bankaccountholder'] = isset($user->account->payment_data['bankaccountholder']) ? $user->account->payment_data['bankaccountholder'] : "";
|
||||
$ret['elv']['mandate_identification'] = isset($user->account->payment_data['mandate_identification']) ? $user->account->payment_data['mandate_identification'] : '';
|
||||
$ret['elv']['creditor_identifier'] = isset($user->account->payment_data['creditor_identifier']) ? $user->account->payment_data['creditor_identifier'] : '';
|
||||
$ret['elv']['iban'] = isset($user->account->payment_data['iban']) ? $user->account->payment_data['iban'] : '';
|
||||
$ret['elv']['bic'] = isset($user->account->payment_data['bic']) ? $user->account->payment_data['bic'] : '';
|
||||
$ret['elv']['bankaccountholder'] = isset($user->account->payment_data['bankaccountholder']) ? $user->account->payment_data['bankaccountholder'] : '';
|
||||
$reference = $pay->setPrePayment($payment_method, $amount, 'EUR', $ret);
|
||||
|
||||
$pay->setPersonalData();
|
||||
|
|
@ -71,12 +66,12 @@ class PaymentHelper
|
|||
if ($response['status'] === 'APPROVED') {
|
||||
$payT = PaymentTransaction::create([
|
||||
'shopping_payment_id' => $shopping_payment->id,
|
||||
'request' => 'authorization',
|
||||
'request' => 'authorization',
|
||||
'txid' => $response['txid'],
|
||||
'userid' => $response['userid'],
|
||||
'status' => $response['status'],
|
||||
'transmitted_data' => $response,
|
||||
'mode' => $shopping_payment->mode
|
||||
'mode' => $shopping_payment->mode,
|
||||
]);
|
||||
UserHistory::create(['user_id' => $user->id, 'shopping_order_id' => $shopping_order->id, 'action' => 'abo_open_payment', 'referenz' => $payT->id, 'identifier' => $user->payment_account, 'status' => 5]);
|
||||
}
|
||||
|
|
@ -84,7 +79,7 @@ class PaymentHelper
|
|||
|
||||
public function makeShoppingUser($user, $is_from = 'membership', $is_for = 'me')
|
||||
{
|
||||
$shopping_user = new ShoppingUser();
|
||||
$shopping_user = new ShoppingUser;
|
||||
$shopping_user->auth_user_id = $user->id;
|
||||
$shopping_user->mode = 'prev';
|
||||
$shopping_user->language = $user->getLocale();
|
||||
|
|
@ -99,6 +94,7 @@ class PaymentHelper
|
|||
$shopping_user->billing_country_id = $user->account->country_id;
|
||||
$shopping_user->billing_phone = $user->account->phone;
|
||||
$shopping_user->billing_email = $user->email;
|
||||
$shopping_user->language = $user->getLocale();
|
||||
$shopping_user->faker_mail = false;
|
||||
$shopping_user->shipping_email = $user->email;
|
||||
$shopping_user->accepted_data_checkbox = 1;
|
||||
|
|
@ -118,6 +114,7 @@ class PaymentHelper
|
|||
$shopping_user->shipping_phone = $user->account->shipping_phone;
|
||||
$shopping_user->shipping_postnumber = $user->account->shipping_postnumber;
|
||||
$shopping_user->save();
|
||||
|
||||
return $shopping_user;
|
||||
}
|
||||
|
||||
|
|
@ -147,12 +144,12 @@ class PaymentHelper
|
|||
$shopping_order = ShoppingOrder::create($data);
|
||||
$items = Yard::instance('shopping')->getContentByOrder();
|
||||
foreach ($items as $item) {
|
||||
if (!ShoppingOrderItem::where('shopping_order_id', $shopping_order->id)->where('row_id', $item->rowId)->count()) {
|
||||
if (! ShoppingOrderItem::where('shopping_order_id', $shopping_order->id)->where('row_id', $item->rowId)->count()) {
|
||||
$price_net = Yard::instance('shopping')->rowPriceNet($item, 2, '.', '');
|
||||
$tax = $item->price - $price_net;
|
||||
$data = [
|
||||
'shopping_order_id' => $shopping_order->id,
|
||||
'row_id' => $item->rowId,
|
||||
'row_id' => $item->rowId,
|
||||
'product_id' => $item->id,
|
||||
'comp' => $item->options->comp,
|
||||
'qty' => $item->qty,
|
||||
|
|
@ -163,12 +160,13 @@ class PaymentHelper
|
|||
'price_vk_net' => $shopping_order->getPriceVkNetBy($item->id),
|
||||
'discount' => $item->options->no_commission ? 0 : $shopping_order->getUserDiscount(),
|
||||
'points' => $item->options->points,
|
||||
'slug' => $item->options->slug
|
||||
'slug' => $item->options->slug,
|
||||
];
|
||||
$shopping_order_item = ShoppingOrderItem::create($data);
|
||||
}
|
||||
}
|
||||
$shopping_order->makeTaxSplit();
|
||||
|
||||
return $shopping_order;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Services;
|
||||
|
||||
|
||||
use App\Http\Controllers\Api\KasController;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\ShoppingUserMemberLog;
|
||||
|
|
@ -12,8 +11,6 @@ use App\User;
|
|||
|
||||
class UserUtil
|
||||
{
|
||||
|
||||
|
||||
public static function setShoppingUserToNewMember($pre_member_id, $new_member_id)
|
||||
{
|
||||
$ShoppingUsers = ShoppingUser::where('member_id', $pre_member_id)->get();
|
||||
|
|
@ -21,7 +18,7 @@ class UserUtil
|
|||
ShoppingUserMemberLog::create([
|
||||
'pre_member_id' => $shopping_user->member_id,
|
||||
'shopping_user_id' => $shopping_user->id,
|
||||
'new_member_id' => $new_member_id
|
||||
'new_member_id' => $new_member_id,
|
||||
]);
|
||||
$shopping_user->member_id = $new_member_id;
|
||||
$shopping_user->save();
|
||||
|
|
@ -30,8 +27,8 @@ class UserUtil
|
|||
|
||||
public static function setNewSponsorToChilds($inactive_sponsor_id, $new_sponsor_id)
|
||||
{
|
||||
//alle User die diesen inaktivien Sponsor haben
|
||||
$child_users = User::where('m_sponsor', $inactive_sponsor_id)->get(); //auch deaktiverte
|
||||
// alle User die diesen inaktivien Sponsor haben
|
||||
$child_users = User::where('m_sponsor', $inactive_sponsor_id)->get(); // auch deaktiverte
|
||||
foreach ($child_users as $child_user) {
|
||||
UserCleanUpLog::create([
|
||||
'inactive_sponsor_id' => $inactive_sponsor_id,
|
||||
|
|
@ -45,12 +42,12 @@ class UserUtil
|
|||
|
||||
public static function resetChildsToSponsor($re_sponsor_id)
|
||||
{
|
||||
//alle alten Childs vom re_sponsor_id / User wieder herstellen
|
||||
// alle alten Childs vom re_sponsor_id / User wieder herstellen
|
||||
$UserCleanUpUsers = UserCleanUpLog::where('inactive_sponsor_id', $re_sponsor_id)->get();
|
||||
foreach ($UserCleanUpUsers as $UserCleanUpUser) {
|
||||
$child_user = User::find($UserCleanUpUser->child_user_id);
|
||||
if ($child_user) {
|
||||
//delete Logs from user child where is newer then this
|
||||
// delete Logs from user child where is newer then this
|
||||
$deleteUserCleanUpLogs = UserCleanUpLog::where('child_user_id', $UserCleanUpUser->child_user_id)->where('created_at', '>', $UserCleanUpUser->created_at)->get();
|
||||
foreach ($deleteUserCleanUpLogs as $deleteUserCleanUpLog) {
|
||||
$deleteUserCleanUpLog->delete();
|
||||
|
|
@ -58,11 +55,11 @@ class UserUtil
|
|||
if ($child_user->m_sponsor) { // child is active
|
||||
$child_user->m_sponsor = $re_sponsor_id;
|
||||
}
|
||||
if ($child_user->pre_sponsor) { //child is inactive
|
||||
if ($child_user->pre_sponsor) { // child is inactive
|
||||
$child_user->pre_sponsor = $re_sponsor_id;
|
||||
}
|
||||
$child_user->save();
|
||||
//delete this log
|
||||
// delete this log
|
||||
$UserCleanUpUser->delete();
|
||||
}
|
||||
}
|
||||
|
|
@ -72,10 +69,22 @@ class UserUtil
|
|||
{
|
||||
$user = User::find($user_id);
|
||||
|
||||
if ($user) {
|
||||
if (! $user) {
|
||||
\Log::channel('cleanup')->error('setUserToClient: User not found, user_id: '.$user_id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $user->account) {
|
||||
\Log::channel('cleanup')->error('setUserToClient: User has no account data, user_id: '.$user_id);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$data = [
|
||||
'member_id' => $sponsor_id,
|
||||
'language' => $user->lang ? $user->lang : 'de',
|
||||
'language' => $user->lang ?? 'de',
|
||||
'billing_salutation' => $user->account->salutation,
|
||||
'billing_company' => $user->account->company,
|
||||
'billing_firstname' => $user->account->first_name,
|
||||
|
|
@ -87,6 +96,7 @@ class UserUtil
|
|||
'billing_country_id' => $user->account->country_id,
|
||||
'billing_phone' => $user->account->getPhoneNumber(),
|
||||
'billing_email' => $user->email,
|
||||
'language' => $user->account->getLocale(),
|
||||
'same_as_billing' => $user->account->same_as_billing,
|
||||
'shipping_salutation' => $user->account->shipping_salutation,
|
||||
'shipping_company' => $user->account->shipping_company,
|
||||
|
|
@ -100,11 +110,17 @@ class UserUtil
|
|||
'shipping_phone' => $user->account->getShippingPhoneFull(),
|
||||
'shipping_postnumber' => $user->account->shipping_postnumber,
|
||||
];
|
||||
|
||||
ShoppingUser::create($data);
|
||||
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
\Log::channel('cleanup')->error('setUserToClient failed for user_id: '.$user_id.' | Error: '.$e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
find next activ sponsor on user id
|
||||
first $sponsor_id can user_id, looks has m_sponsor or pre_sponsor.
|
||||
|
|
@ -113,27 +129,28 @@ class UserUtil
|
|||
{
|
||||
|
||||
$user = User::withTrashed()->find($sponsor_id);
|
||||
if (!$user) { //kein User unter der ID - to root
|
||||
if (! $user) { // kein User unter der ID - to root
|
||||
return User::find(6);
|
||||
}
|
||||
//user ist aktiv
|
||||
// user ist aktiv
|
||||
if ($user->isActiveAccount()) {
|
||||
return $user;
|
||||
}
|
||||
if ($user->m_sponsor) { //hat der User einen m_sponsor
|
||||
if ($user->m_sponsor) { // hat der User einen m_sponsor
|
||||
return self::findNextActiveSponsor($user->m_sponsor);
|
||||
}
|
||||
if ($user->pre_sponsor) { //hat der User einen pre_sponsor - schon inaktiv
|
||||
if ($user->pre_sponsor) { // hat der User einen pre_sponsor - schon inaktiv
|
||||
return self::findNextActiveSponsor($user->pre_sponsor);
|
||||
}
|
||||
//dump('not sponsor');
|
||||
|
||||
// dump('not sponsor');
|
||||
return $user;
|
||||
}
|
||||
|
||||
public static function deactiveUser($user)
|
||||
{
|
||||
|
||||
$user->pre_sponsor = $user->m_sponsor; //den sponsor speichern für wiederherstellung
|
||||
$user->pre_sponsor = $user->m_sponsor; // den sponsor speichern für wiederherstellung
|
||||
$user->m_sponsor = null;
|
||||
$user->active = false;
|
||||
$user->save();
|
||||
|
|
@ -143,7 +160,7 @@ class UserUtil
|
|||
{
|
||||
if ($user->pre_sponsor) {
|
||||
$pre_sponsor = self::findNextActiveSponsor($user->pre_sponsor);
|
||||
$user->m_sponsor = $pre_sponsor->id; //den sponsor wiederherstellen
|
||||
$user->m_sponsor = $pre_sponsor->id; // den sponsor wiederherstellen
|
||||
$user->pre_sponsor = null;
|
||||
}
|
||||
$user->active = true;
|
||||
|
|
@ -152,14 +169,14 @@ class UserUtil
|
|||
|
||||
public static function deleteUser(User $user, $complete = false)
|
||||
{
|
||||
//shop wird gelöscht
|
||||
// shop wird gelöscht
|
||||
if ($user->shop) {
|
||||
// $subdomain_name = $user->shop->slug . '.mivita.care';
|
||||
$user->shop->name = "delete" . $user->shop->id;
|
||||
$user->shop->slug = "delete" . $user->shop->id;
|
||||
$user->shop->name = 'delete'.$user->shop->id;
|
||||
$user->shop->slug = 'delete'.$user->shop->id;
|
||||
$user->shop->save();
|
||||
$user->shop->delete();
|
||||
//isset KAS - delete Subdomain
|
||||
// isset KAS - delete Subdomain
|
||||
/*if (!Util::isTestSystem()) {
|
||||
$kas = new KasController();
|
||||
$pra = array(
|
||||
|
|
@ -169,12 +186,12 @@ class UserUtil
|
|||
}*/
|
||||
}
|
||||
|
||||
//user soll nicht komplett gelöscht werden
|
||||
$user->email = "delete-" . $user->email;
|
||||
//password wird gelöscht
|
||||
$user->password = "delete" . time();
|
||||
// user soll nicht komplett gelöscht werden
|
||||
$user->email = 'delete-'.$user->email;
|
||||
// password wird gelöscht
|
||||
$user->password = 'delete'.time();
|
||||
$user->confirmed = 0;
|
||||
$user->confirmation_code = "delete" . time();
|
||||
$user->confirmation_code = 'delete'.time();
|
||||
$user->confirmation_date = null;
|
||||
$user->confirmation_code_to = null;
|
||||
$user->confirmation_code_remider = 2;
|
||||
|
|
@ -185,9 +202,9 @@ class UserUtil
|
|||
$user->admin = 0;
|
||||
$user->deleted_at = now();
|
||||
$user->pre_deleted_at = now();
|
||||
//user soll komplett gelöscht werden
|
||||
// user soll komplett gelöscht werden
|
||||
if ($complete) {
|
||||
$user->email = "delete-" . time() . "-" . rand(1000, 9999);
|
||||
$user->email = 'delete-'.time().'-'.rand(1000, 9999);
|
||||
if ($user->account) {
|
||||
$user->account->delete();
|
||||
}
|
||||
|
|
@ -198,14 +215,16 @@ class UserUtil
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function checkEmailExists($user)
|
||||
{
|
||||
$email = str_replace("delete-", "", $user->email);
|
||||
$email = str_replace('delete-', '', $user->email);
|
||||
|
||||
$user = User::where('email', $email)->first();
|
||||
if ($user) {
|
||||
return 'Der Account kann nicht wieder hergestellt werden, da die E-Mail-Adresse <b>' . $email . '</b> bereits in Verwendung ist.';
|
||||
return 'Der Account kann nicht wieder hergestellt werden, da die E-Mail-Adresse <b>'.$email.'</b> bereits in Verwendung ist.';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -213,11 +232,11 @@ class UserUtil
|
|||
{
|
||||
if ($user->pre_sponsor) {
|
||||
$pre_sponsor = self::findNextActiveSponsor($user->pre_sponsor);
|
||||
$user->m_sponsor = $pre_sponsor->id; //den sponsor wiederherstellen
|
||||
$user->m_sponsor = $pre_sponsor->id; // den sponsor wiederherstellen
|
||||
$user->pre_sponsor = null;
|
||||
}
|
||||
|
||||
$user->email = str_replace("delete-", "", $user->email);
|
||||
$user->email = str_replace('delete-', '', $user->email);
|
||||
$user->confirmed = 1;
|
||||
$user->confirmation_date = now();
|
||||
$user->confirmation_code = null;
|
||||
|
|
@ -242,13 +261,13 @@ class UserUtil
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static function reactiveUserResetChilds($user_id, $info = '')
|
||||
{
|
||||
|
||||
$user = User::find($user_id);
|
||||
if (!$user) {
|
||||
\Log::channel('cleanup')->error('reactiveUserResetChilds find no user by user_id:' . $user_id);
|
||||
if (! $user) {
|
||||
\Log::channel('cleanup')->error('reactiveUserResetChilds find no user by user_id:'.$user_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
$data = [
|
||||
|
|
@ -258,7 +277,7 @@ class UserUtil
|
|||
'm_first_name' => $user->account ? $user->account->m_first_name : '',
|
||||
'm_last_name' => $user->account ? $user->account->m_last_name : '',
|
||||
];
|
||||
\Log::channel('cleanup')->info('reactiveUserResetChilds ' . $info . ' : ' . json_encode($data));
|
||||
\Log::channel('cleanup')->info('reactiveUserResetChilds '.$info.' : '.json_encode($data));
|
||||
|
||||
self::reactiveUser($user);
|
||||
self::resetChildsToSponsor($user->id);
|
||||
|
|
@ -268,8 +287,9 @@ class UserUtil
|
|||
{
|
||||
|
||||
$user = User::find($user_id);
|
||||
if (!$user) {
|
||||
\Log::channel('cleanup')->error('deactiveUserNewSponsorChilds find no user by user_id:' . $user_id);
|
||||
if (! $user) {
|
||||
\Log::channel('cleanup')->error('deactiveUserNewSponsorChilds find no user by user_id:'.$user_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
$data = [
|
||||
|
|
@ -284,9 +304,9 @@ class UserUtil
|
|||
if ($active_sponsor) {
|
||||
self::setNewSponsorToChilds($user->id, $active_sponsor->id);
|
||||
} else {
|
||||
\Log::channel('cleanup')->error('cleanUpInActiveUser find no active_sponsor by inactive_user:' . $user->id);
|
||||
\Log::channel('cleanup')->error('cleanUpInActiveUser find no active_sponsor by inactive_user:'.$user->id);
|
||||
}
|
||||
\Log::channel('cleanup')->info('deactiveUserNewSponsorChilds ' . $info . ' : ' . json_encode($data));
|
||||
\Log::channel('cleanup')->info('deactiveUserNewSponsorChilds '.$info.' : '.json_encode($data));
|
||||
self::deactiveUser($user);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ class Yard extends Cart
|
|||
if (! $shipping_price) {
|
||||
return;
|
||||
}
|
||||
if ($this->weight() == 0) {
|
||||
if ($this->allItemsFreeShippingConsultant() || $this->weight() == 0) {
|
||||
$shipping_price->price = 0;
|
||||
$shipping_price->price_comp = 0;
|
||||
} else {
|
||||
|
|
@ -416,6 +416,18 @@ class Yard extends Cart
|
|||
return $total;
|
||||
}
|
||||
|
||||
public function allItemsFreeShippingConsultant()
|
||||
{
|
||||
$content = $this->getContent();
|
||||
if ($content->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $content->every(function (CartItem $cartItem) {
|
||||
return (bool) $cartItem->options->free_shipping_consultant;
|
||||
});
|
||||
}
|
||||
|
||||
public function points()
|
||||
{
|
||||
$content = $this->getContent();
|
||||
|
|
@ -510,7 +522,7 @@ class Yard extends Cart
|
|||
}
|
||||
$price = $product->price;
|
||||
if ($set_price === 'with') {
|
||||
$cartItem = $this->getCartItem($product->id, $product->getLang('name'), 1, $price, ['image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'show_on' => $product->show_on]);
|
||||
$cartItem = $this->getCartItem($product->id, $product->getLang('name'), 1, $price, ['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]);
|
||||
$price = $product->getPriceWith(false, true, $this->getUserCountry());
|
||||
}
|
||||
if ($set_price === 'withTaxFree') {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue