middleware('auth:customers'); $this->yard = Yard::instance($this->instance); } public function myAbo() { $user = Auth::guard('customers')->user(); if (! $user->shopping_user_id) { return view('portal.abo.my_abo_create', [ 'user' => $user, 'no_shopping_user' => true, 'step' => 0, ]); } $shopping_user = ShoppingUser::findOrFail($user->shopping_user_id); $user_abo = UserAbo::where('email', $shopping_user->billing_email) ->where('status', '>', 1) ->first(); if (! $user_abo) { return view('portal.abo.my_abo_create', [ 'shopping_user' => $shopping_user, 'step' => 0, ]); } $this->checkPortalPermission($user_abo); $view = 'portal'; // Init Yard und Customer-Detail AboOrderCart::initYard($user_abo); $customer_detail = AboOrderCart::getCustomerDetail(); AboOrderCart::makeOrderYard($user_abo); $baseCompCount = Yard::instance(AboOrderCart::INSTANCE)->getNumComp(); $oneTimeWindowOpen = AboHelper::isOneTimeWindowOpen($user_abo); if ($oneTimeWindowOpen) { AboOrderCart::addOneTimeItemsToYard($user_abo); AboOrderCart::checkNumOfCompProducts($user_abo); } $summary = AboOrderCart::getSplitSummary(); return view('portal.abo.my_abo', [ 'user_abo' => $user_abo, 'customer_detail' => $customer_detail, 'view' => $view, 'comp_products' => [], 'isAdmin' => false, 'one_time_window_open' => $oneTimeWindowOpen, 'summary' => $summary, 'base_comp_count' => $baseCompCount, ]); } public function update($view, $id) { $data = Request::all(); $user_abo = UserAbo::findOrFail($id); $this->checkPortalPermission($user_abo); $isAddOnlyMode = AboHelper::isAddOnlyMode($user_abo, $view); if (isset($data['action'])) { if ($data['action'] === 'abo_update_settings') { $user_abo = UserAbo::findOrFail($data['id']); $this->checkPortalPermission($user_abo); $aboRepository = new AboRepository; $aboRepository->setModel($user_abo); $aboRepository->update($data); return redirect(route('portal.my_subscriptions')); } if (Request::ajax()) { $message = false; // Yard für Gewichts-/Versandprüfung initialisieren (Versandland setzen) AboOrderCart::initYard($user_abo); // addProduct if ($data['action'] === 'addProduct') { if ($product = Product::find($data['product_id'])) { if (AboOrderCart::exceedsMaxWeight($user_abo, (int) $product->weight)) { $message = __('msg.cart_max_weight_reached'); } elseif ($UserAboItem = UserAboItem::where('user_abo_id', $user_abo->id)->where('product_id', $product->id)->where('comp', 0)->first()) { $qtyBefore = $UserAboItem->qty; $UserAboItem->qty = $UserAboItem->qty + 1; $UserAboItem->save(); AboItemHistoryService::logProductAdded($user_abo, $UserAboItem, $qtyBefore, $view); } else { $newItem = UserAboItem::create([ 'user_abo_id' => $user_abo->id, 'product_id' => $product->id, 'comp' => 0, 'qty' => 1, 'status' => 1, ]); AboItemHistoryService::logProductAdded($user_abo, $newItem, 0, $view); } } } // updateCart if ($data['action'] === 'updateCart') { if (isset($data['product_id']) && $product = Product::find($data['product_id'])) { if (isset($data['order_item_id']) && $UserAboItem = UserAboItem::find($data['order_item_id'])) { if (isset($data['qty'])) { $qtyBefore = $UserAboItem->qty; $qty = (int) $data['qty']; $qty = $qty < 1 ? 1 : $qty; $qty = $qty > 100 ? 100 : $qty; if ($isAddOnlyMode && $qty < $UserAboItem->qty) { $qty = $UserAboItem->qty; } $additionalWeight = (int) $product->weight * ($qty - $qtyBefore); if ($additionalWeight > 0 && AboOrderCart::exceedsMaxWeight($user_abo, $additionalWeight)) { $message = __('msg.cart_max_weight_reached'); } else { $UserAboItem->qty = $qty; $UserAboItem->save(); AboItemHistoryService::logQtyChanged($user_abo, $UserAboItem, $qtyBefore, $qty, $view); } } } } } // removeFromCart if ($data['action'] === 'removeFromCart') { if ($isAddOnlyMode) { return response()->json([ 'response' => false, 'message' => __('abo.error_add_only_no_remove'), ], 403); } if (! isset($data['product_id']) || ! ($product = Product::find($data['product_id']))) { $message = __('abo.product_not_found'); } if (! isset($data['order_item_id']) || ! ($userAboItem = UserAboItem::find($data['order_item_id']))) { $message = __('abo.abo_item_not_found'); } $has_basis_product = $this->checkNeedBasisProduct($user_abo, $product, $data['order_item_id']); if (! $has_basis_product) { $message = __('abo.need_basis_product'); } if (! $message) { AboItemHistoryService::logProductRemoved($user_abo, $userAboItem, $view); $userAboItem->delete(); $user_abo->refresh(); } } // updateCompProduct if ($data['action'] === 'updateCompProduct') { if ($UserAboItem = UserAboItem::where('user_abo_id', $user_abo->id)->where('comp', $data['comp_num'])->first()) { $oldProduct = $UserAboItem->product; $UserAboItem->product_id = $data['comp_product_id']; $UserAboItem->save(); $UserAboItem->load('product'); AboItemHistoryService::logCompProductChanged($user_abo, $UserAboItem, $oldProduct, $UserAboItem->product, $view); } else { $newItem = UserAboItem::create([ 'user_abo_id' => $user_abo->id, 'product_id' => $data['comp_product_id'], 'comp' => $data['comp_num'], 'qty' => 1, 'status' => 1, ]); AboItemHistoryService::logProductAdded($user_abo, $newItem, 0, $view); } } AboOrderCart::initYard($user_abo); AboOrderCart::makeOrderYard($user_abo); $baseCompCount = Yard::instance(AboOrderCart::INSTANCE)->getNumComp(); if (AboHelper::isOneTimeWindowOpen($user_abo)) { AboOrderCart::addOneTimeItemsToYard($user_abo->fresh()); } AboOrderCart::checkNumOfCompProducts($user_abo); $summary = AboOrderCart::getSplitSummary(); $error_message = $message ? $message : false; $html_cart = view('admin.abo._order_abo_show', [ 'user_abo' => $user_abo, 'error_message' => $error_message, 'split_mode' => AboHelper::isOneTimeWindowOpen($user_abo), 'summary' => $summary, 'add_only_mode' => $isAddOnlyMode, ])->render(); $html_comp = view('user.order.comp_product', array_merge($data, [ 'cart_instance' => AboOrderCart::INSTANCE, 'base_comp_count' => $baseCompCount, ]))->render(); $html_summary = view('admin.abo._order_combined_summary', [ 'summary' => $summary, ])->render(); $amount = $user_abo->getFormattedAmount(); return response()->json(['response' => true, 'data' => $data, 'html_cart' => $html_cart, 'html_comp' => $html_comp, 'html_summary' => $html_summary, 'amount' => $amount]); } } } public function datatable($user_abo_id) { $user_abo = UserAbo::findOrFail($user_abo_id); $this->checkPortalPermission($user_abo); $show_on_ids = ['12', '13']; $query = Product::select('products.*') ->where('active', true) ->where(function ($q) use ($show_on_ids) { foreach ($show_on_ids as $id) { $q->orWhereJsonContains('show_on', $id); } }) ->orderByRaw( "CASE WHEN JSON_CONTAINS(show_on, ?, '$') THEN 1 WHEN JSON_CONTAINS(show_on, ?, '$') THEN 2 ELSE 3 END", [$show_on_ids[0], isset($show_on_ids[1]) ? $show_on_ids[1] : $show_on_ids[0]] ); return \DataTables::eloquent($query) ->addColumn('add_card', function (Product $product) { $tax_free = Yard::instance(AboOrderCart::INSTANCE)->getUserTaxFree(); $price = $product->getFormattedPriceWith($tax_free, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()); return ''; }) ->addColumn('picture', function (Product $product) { if (count($product->images)) { return ''; } return ''; }) ->addColumn('name', function (Product $product) { return ''.$product->getLang('name').'
'.get_abo_type_badge_by_product($product); }) ->addColumn('points', function (Product $product) { return ''.$product->getFormattedPoints().''; }) ->addColumn('price_net', function (Product $product) { return ''.$product->getFormattedPriceWith(true, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €'.''.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).''; }) ->addColumn('price_gross', function (Product $product) { return ''.$product->getFormattedPriceWith(false, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €'.''.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).''; }) ->addColumn('action', function (Product $product) { return ''; }) ->filterColumn('product', function ($query, $keyword) { if ($keyword != '') { $query->where('name', 'LIKE', '%'.$keyword.'%'); } }) ->orderColumn('name', 'name $1') ->orderColumn('product', 'name $1') ->orderColumn('number', 'number $1') ->orderColumn('points', 'points $1') ->orderColumn('price_net', 'price_net $1') ->orderColumn('price_gross', 'price_gross $1') ->orderColumn('contents_total', 'contents_total $1') ->orderColumn('weight', 'weight $1') ->rawColumns(['add_card', 'points', 'product', 'name', 'quantity', 'picture', 'price_net', 'price_gross', 'action']) ->make(true); } public function modalLoad() { $data = Request::all(); $ret = ''; if (isset($data['action'])) { if ($data['action'] === 'abo-add-product') { $user_abo = UserAbo::find($data['id']); $this->checkPortalPermission($user_abo); $ret = view('user.abo.modal_abo_show_products', compact('data', 'user_abo'))->render(); } if ($data['action'] === 'abo-add-onetime') { $user_abo = UserAbo::find($data['id']); $this->checkPortalPermission($user_abo); $ret = view('user.abo.modal_abo_onetime_products', compact('data', 'user_abo'))->render(); } if ($data['action'] === 'abo_update_settings') { $user_abo = UserAbo::find($data['id']); $this->checkPortalPermission($user_abo); $route = route('user_abos_update', [$data['view'], $user_abo->id]); $ret = view('admin.abo.modal_abo_update', compact('user_abo', 'data', 'route'))->render(); } if ($data['action'] === 'user-order-show-product') { $product = Product::find($data['id']); $ret = view('admin.modal.show_product', compact('product', 'data'))->render(); } } if (Request::ajax()) { return response()->json(['response' => $data, 'html' => $ret, 'status' => true]); } abort(404); } public function oneTime(AboOneTimeItemRequest $request, $view, $id) { $user_abo = UserAbo::findOrFail($id); $this->checkPortalPermission($user_abo); $isAddOnlyMode = AboHelper::isAddOnlyMode($user_abo, $view); if (! AboHelper::isOneTimeWindowOpen($user_abo)) { return response()->json([ 'response' => false, 'message' => __('abo.onetime_window_closed'), ], 403); } AboOrderCart::initYard($user_abo); $message = (new AboOneTimeService)->handleAction($user_abo, $request->validated()); AboOrderCart::initYard($user_abo); AboOrderCart::makeOrderYard($user_abo); $baseCompCount = Yard::instance(AboOrderCart::INSTANCE)->getNumComp(); AboOrderCart::addOneTimeItemsToYard($user_abo->fresh()); AboOrderCart::checkNumOfCompProducts($user_abo); $user_abo = $user_abo->fresh(); $summary = AboOrderCart::getSplitSummary(); return response()->json([ 'response' => ! $message, 'message' => $message ?: null, 'summary' => $summary, 'one_time_items' => $this->oneTimeItemsPayload($user_abo), 'html_onetime' => view('admin.abo._order_onetime_show', [ 'user_abo' => $user_abo, 'summary' => $summary, 'error_message' => $message ?: false, ])->render(), 'html_abo' => view('admin.abo._order_abo_show', [ 'user_abo' => $user_abo, 'split_mode' => true, 'summary' => $summary, 'only_show_products' => false, 'add_only_mode' => $isAddOnlyMode, ])->render(), 'html_summary' => view('admin.abo._order_combined_summary', [ 'summary' => $summary, ])->render(), 'html_comp' => view('user.order.comp_product', [ 'comp_products' => [], 'cart_instance' => AboOrderCart::INSTANCE, 'base_comp_count' => $baseCompCount, ])->render(), ]); } public function oneTimeDatatable($user_abo_id) { $user_abo = UserAbo::findOrFail($user_abo_id); $this->checkPortalPermission($user_abo); AboOrderCart::initYard($user_abo); $query = Product::select('products.*') ->where('active', true) ->whereJsonContains('show_on', '3') ->orderBy('name', 'asc'); return \DataTables::eloquent($query) ->addColumn('add_card', function (Product $product) { $tax_free = Yard::instance(AboOrderCart::INSTANCE)->getUserTaxFree(); $price = $product->getFormattedPriceWith($tax_free, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()); return ''; }) ->addColumn('picture', function (Product $product) { if (count($product->images)) { return ''; } return ''; }) ->addColumn('name', function (Product $product) { return ''.$product->getLang('name').''; }) ->addColumn('points', function (Product $product) { return ''.$product->getFormattedPoints().''; }) ->addColumn('price_net', function (Product $product) { return ''.$product->getFormattedPriceWith(true, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €'; }) ->addColumn('price_gross', function (Product $product) { return ''.$product->getFormattedPriceWith(false, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €'; }) ->filterColumn('product', function ($query, $keyword) { if ($keyword != '') { $query->where('name', 'LIKE', '%'.$keyword.'%'); } }) ->orderColumn('name', 'name $1') ->orderColumn('number', 'number $1') ->rawColumns(['add_card', 'points', 'name', 'picture', 'price_net', 'price_gross']) ->make(true); } /** * @return array> */ private function oneTimeItemsPayload(UserAbo $user_abo): array { return $user_abo->one_time_items()->with('product')->get()->map(function (UserAboOneTimeItem $item) { return [ 'id' => $item->id, 'product_id' => $item->product_id, 'name' => $item->product?->getLang('name'), 'qty' => $item->qty, 'price' => $item->price, 'total' => round($item->price * $item->qty, 2), ]; })->all(); } public function checkNeedBasisProduct($user_abo, $product, $order_item_id) { if (AboHelper::getAboShowOn($product) !== 'base') { return true; } foreach ($user_abo->user_abo_items as $user_abo_item) { if ($user_abo_item->id == $order_item_id) { continue; } if ($user_abo_item->comp) { continue; } if (AboHelper::getAboShowOn($user_abo_item->product) === 'base') { return true; } } return false; } private function checkPortalPermission($user_abo) { $user = Auth::guard('customers')->user(); if (! $user || ! $user->shopping_user_id) { abort(403, 'Unauthorized action.'); } $shopping_user = ShoppingUser::find($user->shopping_user_id); if (! $shopping_user || $user_abo->email !== $shopping_user->billing_email) { abort(403, 'Unauthorized action.'); } } public function myAboCreate($step) { $user = Auth::guard('customers')->user(); if (! $user->shopping_user_id) { abort(403, 'Unauthorized action.'); } $shopping_user = ShoppingUser::findOrFail($user->shopping_user_id); $data = $this->prepareAboCreateData($shopping_user, $step); if (isset($data['checkout_url'])) { return redirect($data['checkout_url']); } return view('portal.abo.my_abo_create', $data); } private function prepareAboCreateData($shopping_user, $step) { $data = [ 'shopping_user' => $shopping_user, 'basis_products' => Product::where('active', true) ->whereJsonContains('show_on', ['12']) ->orderBy('pos', 'ASC') ->get(), 'upgrade_products' => Product::where('active', true) ->whereJsonContains('show_on', ['13']) ->orderBy('pos', 'ASC') ->get(), 'step' => 0, ]; if (Request::get('action') == 'back') { $step = $step - 2; } switch ($step) { case 0: $data['step'] = 0; break; case 1: $this->initYard($shopping_user); $data['step'] = 1; break; case 2: UserService::setInstance($this->instance); UserService::initCustomerYard($shopping_user, 'abo-ot-customer'); $data['step'] = 2; break; case 3: UserService::setInstance($this->instance); UserService::initCustomerYard($shopping_user, 'abo-ot-customer'); if (Request::get('action') == 'next') { if (! $this->checkBasisProduct()) { $data['error'] = __('abo.abo_error_basis_product'); $data['step'] = 2; } else { $data['step'] = 3; } } else { $data['step'] = 3; } break; case 4: UserService::setInstance($this->instance); UserService::initCustomerYard($shopping_user, 'abo-ot-customer'); $this->upgradeProductToCart(); $data['step'] = 4; break; case 5: UserService::setInstance($this->instance); UserService::initCustomerYard($shopping_user, 'abo-ot-customer'); if (Request::get('action') == 'checkout') { if (! Request::boolean('abo_order_info_checkbox')) { $data['error'] = __('abo.abo_order_info_checkbox_required'); $data['step'] = 4; } elseif (! in_array((int) Request::input('abo_interval'), UserAbo::$aboDeliveryDays, true)) { $data['error'] = __('abo.error_abo_interval'); $data['step'] = 4; } elseif (! $this->preCheckCheckout()) { $data['error'] = __('abo.abo_error_basis_product'); $data['step'] = 4; } else { $data['checkout_url'] = $this->processCheckout($shopping_user); } } $data['step'] = 4; break; default: abort(404, 'Page not found.'); } return $data; } private function initYard($shopping_user) { $delivery_country = $shopping_user->getDeliveryCountry(true); if (! $delivery_country) { abort(404, 'No delivery country found, please edit your personal data.'); } \Session::put('user_init_country', strtolower($delivery_country->code)); \Session::forget('user_init_country_options'); \Session::put('locale', strtolower(\App::getLocale())); Shop::initUserShopLang($delivery_country, $this->instance); } private function preCheckCheckout(): bool { return AboHelper::aboHasBaseProduct($this->yard->getContentByOrder()); } private function checkBasisProduct() { $data = Request::all(); $result = false; if (! isset($data['base_product_qty'])) { return false; } foreach ($data['base_product_qty'] as $product_id => $quantity) { $product = Product::find($product_id); if (! $product || intval($quantity) <= 0) { continue; } $result = true; $this->addProductToCart($product, $quantity); } return $result; } private function upgradeProductToCart() { $data = Request::all(); $result = false; if (! isset($data['upgrade_product_qty'])) { return false; } foreach ($data['upgrade_product_qty'] as $product_id => $quantity) { $product = Product::find($product_id); if (! $product) { continue; } $result = true; $this->addProductToCart($product, $quantity); } return $result; } private function addProductToCart($product, $quantity) { // Suche nach dem Produkt im Warenkorb $cartItems = $this->yard->search(function ($item) use ($product) { return $item->id === $product->id; }); // Wenn die Menge 0 ist, entferne das Produkt if ($quantity <= 0) { foreach ($cartItems as $item) { $this->yard->remove($item->rowId); } return; } $image = $product->images->first()->slug ?? ''; $price = $product->getPriceWith( $this->yard->getUserTaxFree(), false, $this->yard->getUserCountry() ); // Wenn das Produkt bereits im Warenkorb ist, aktualisiere die Menge if ($cartItems->count() > 0) { $cartItem = $cartItems->first(); $this->yard->update($cartItem->rowId, $quantity); } else { // Wenn das Produkt noch nicht im Warenkorb ist, füge es hinzu $cartItem = $this->yard->add( $product->id, $product->getLang('name'), $quantity, $price, false, false, [ 'image' => $image, 'slug' => $product->slug, 'weight' => $product->weight, 'points' => $product->points, 'no_commission' => $product->no_commission, 'no_free_shipping' => $product->no_free_shipping, 'show_on' => $product->show_on, ] ); } // $this->setProductTax($cartItem, $product); $this->yard->reCalculateShippingPrice(); } private function processCheckout(ShoppingUser $shoppingUser): string { $user_shop = Util::getUserShop(); if (! $user_shop) { $user_shop = Util::getDefaultUserShop(); } do { $identifier = Util::getToken(); } while (ShoppingInstance::where('identifier', $identifier)->count()); $aboInterval = (int) Request::input('abo_interval', 0); $fillable = (new ShoppingUser)->getFillable(); $shoppingData = array_merge( array_intersect_key($shoppingUser->getAttributes(), array_flip($fillable)), [ 'shopping_user_id' => $shoppingUser->id, 'is_from' => 'shopping', 'is_for' => 'abo-ot-customer', 'is_abo' => true, 'abo_interval' => $aboInterval, 'shipping_is_for' => 'abo-ot-customer', 'user_price_infos' => $this->yard->getUserPriceInfos(), 'mode' => config('app.mode') === 'test' ? 'test' : 'live', ] ); ShoppingInstance::create([ 'identifier' => $identifier, 'user_shop_id' => $user_shop->id, 'payment' => 1, 'subdomain' => url('/'), 'country_id' => $this->yard->getShippingCountryId(), 'language' => $shoppingUser->getLocale(), 'amount' => (float) $this->yard->totalWithShipping(2, '.', ''), 'shopping_user_id' => $shoppingUser->id, 'shopping_data' => $shoppingData, 'back' => url()->previous(), ]); $this->yard->store($identifier); $path = route('checkout.checkout_card', ['identifier' => $identifier]); if (strpos($path, 'https') === false) { $path = str_replace('http', 'https', $path); } return $path; } }