Abo Einmalprodukte und Bestätigung abschließen
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
2bdc9ada3c
commit
2269ce031f
57 changed files with 3647 additions and 371 deletions
|
|
@ -170,6 +170,10 @@ class ModalController extends Controller
|
|||
$user_abo = UserAbo::find($data['id']);
|
||||
$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']);
|
||||
$ret = view('user.abo.modal_abo_onetime_products', compact('data', 'user_abo'))->render();
|
||||
}
|
||||
|
||||
if ($data['action'] === 'create-dhl-shipment') {
|
||||
$this->authorizeDhlShipmentModal();
|
||||
|
|
|
|||
|
|
@ -3,14 +3,17 @@
|
|||
namespace App\Http\Controllers\Portal;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Abo\AboOneTimeItemRequest;
|
||||
use App\Models\Product;
|
||||
use App\Models\ShoppingInstance;
|
||||
use App\Models\ShoppingUser;
|
||||
use App\Models\UserAbo;
|
||||
use App\Models\UserAboItem;
|
||||
use App\Models\UserAboOneTimeItem;
|
||||
use App\Repositories\AboRepository;
|
||||
use App\Services\AboHelper;
|
||||
use App\Services\AboItemHistoryService;
|
||||
use App\Services\AboOneTimeService;
|
||||
use App\Services\AboOrderCart;
|
||||
use App\Services\Shop;
|
||||
use App\Services\UserService;
|
||||
|
|
@ -68,6 +71,14 @@ class AboController extends Controller
|
|||
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,
|
||||
|
|
@ -75,6 +86,9 @@ class AboController extends Controller
|
|||
'view' => $view,
|
||||
'comp_products' => [],
|
||||
'isAdmin' => false,
|
||||
'one_time_window_open' => $oneTimeWindowOpen,
|
||||
'summary' => $summary,
|
||||
'base_comp_count' => $baseCompCount,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -98,11 +112,15 @@ class AboController extends Controller
|
|||
|
||||
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 ($UserAboItem = UserAboItem::where('user_abo_id', $user_abo->id)->where('product_id', $product->id)->where('comp', 0)->first()) {
|
||||
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();
|
||||
|
|
@ -132,9 +150,14 @@ class AboController extends Controller
|
|||
if ($isAddOnlyMode && $qty < $UserAboItem->qty) {
|
||||
$qty = $UserAboItem->qty;
|
||||
}
|
||||
$UserAboItem->qty = $qty;
|
||||
$UserAboItem->save();
|
||||
AboItemHistoryService::logQtyChanged($user_abo, $UserAboItem, $qtyBefore, $qty, $view);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,15 +210,32 @@ class AboController extends Controller
|
|||
|
||||
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, 'add_only_mode' => $isAddOnlyMode])->render();
|
||||
$html_comp = view('user.order.comp_product', $data)->render();
|
||||
$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, 'amount' => $amount]);
|
||||
return response()->json(['response' => true, 'data' => $data, 'html_cart' => $html_cart, 'html_comp' => $html_comp, 'html_summary' => $html_summary, 'amount' => $amount]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -223,8 +263,8 @@ class AboController extends Controller
|
|||
|
||||
return \DataTables::eloquent($query)
|
||||
->addColumn('add_card', function (Product $product) {
|
||||
$tax_free = Yard::instance('shopping')->getUserTaxFree();
|
||||
$price = $product->getFormattedPriceWith($tax_free, false, Yard::instance('shopping')->getUserCountry());
|
||||
$tax_free = Yard::instance(AboOrderCart::INSTANCE)->getUserTaxFree();
|
||||
$price = $product->getFormattedPriceWith($tax_free, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry());
|
||||
|
||||
return '<button type="button" class="btn btn-sm btn-md-extra btn-secondary add-product-basket" data-product-id="'.$product->id.'" data-product-name="'.e($product->getLang('name')).'" data-product-price="'.$price.' €">
|
||||
<strong>€ '.$price.'</strong> +<span class="ion ion-md-cart"></span>
|
||||
|
|
@ -244,10 +284,10 @@ class AboController extends Controller
|
|||
return '<span class="no-line-break">'.$product->getFormattedPoints().'</span>';
|
||||
})
|
||||
->addColumn('price_net', function (Product $product) {
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(true, false, Yard::instance('shopping')->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance('shopping')->getUserCountry()).'</span>';
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(true, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).'</span>';
|
||||
})
|
||||
->addColumn('price_gross', function (Product $product) {
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(false, false, Yard::instance('shopping')->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance('shopping')->getUserCountry()).'</span>';
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(false, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).'</span>';
|
||||
})
|
||||
->addColumn('action', function (Product $product) {
|
||||
return '<button class="btn btn-default btn-sm icon-btn md-btn-flat product-tooltip" title="details" data-modal="modal-lg"
|
||||
|
|
@ -282,6 +322,11 @@ class AboController extends Controller
|
|||
$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);
|
||||
|
|
@ -301,6 +346,127 @@ class AboController extends Controller
|
|||
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 '<button type="button" class="btn btn-sm btn-md-extra btn-warning add-onetime-product-basket" data-product-id="'.$product->id.'" data-product-name="'.e($product->getLang('name')).'" data-product-price="'.$price.' €">
|
||||
<strong>€ '.$price.'</strong> +<span class="ion ion-md-cart"></span>
|
||||
</button>';
|
||||
})
|
||||
->addColumn('picture', function (Product $product) {
|
||||
if (count($product->images)) {
|
||||
return '<img class="img-fluid img-extra" alt="" src="'.route('product_image', [$product->images->first()->slug]).'">';
|
||||
}
|
||||
|
||||
return '';
|
||||
})
|
||||
->addColumn('name', function (Product $product) {
|
||||
return '<strong>'.$product->getLang('name').'</strong>';
|
||||
})
|
||||
->addColumn('points', function (Product $product) {
|
||||
return '<span class="no-line-break">'.$product->getFormattedPoints().'</span>';
|
||||
})
|
||||
->addColumn('price_net', function (Product $product) {
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(true, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>';
|
||||
})
|
||||
->addColumn('price_gross', function (Product $product) {
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(false, false, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>';
|
||||
})
|
||||
->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<int, array<string, mixed>>
|
||||
*/
|
||||
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') {
|
||||
|
|
|
|||
|
|
@ -238,6 +238,13 @@ class OrderController extends Controller
|
|||
$image = $product->images->first()?->slug ?? '';
|
||||
$yard = Yard::instance($this->instance);
|
||||
|
||||
$additionalWeight = (int) $product->weight * $quantity;
|
||||
if ($additionalWeight > 0 && $yard->exceedsMaxWeight($additionalWeight)) {
|
||||
\Session::flash('alert-error', __('msg.cart_max_weight_reached'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$cartItem = $yard->add(
|
||||
$product->id,
|
||||
$product->getLang('name'),
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@
|
|||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Abo\AboOneTimeItemRequest;
|
||||
use App\Models\Product;
|
||||
use App\Models\UserAbo;
|
||||
use App\Models\UserAboItem;
|
||||
use App\Models\UserAboOneTimeItem;
|
||||
use App\Repositories\AboRepository;
|
||||
use App\Services\AboHelper;
|
||||
use App\Services\AboItemHistoryService;
|
||||
|
|
@ -85,18 +87,30 @@ class AboController extends Controller
|
|||
// holt die aktuellen UserAccount Daten oder die Userdaten des 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);
|
||||
}
|
||||
|
||||
$comp_products = [];
|
||||
if ($user_abo->is_for === 'me') {
|
||||
$comp_products = Shop::getCompProducts('abo-me');
|
||||
}
|
||||
|
||||
$summary = AboOrderCart::getSplitSummary();
|
||||
|
||||
$data = [
|
||||
'user_abo' => $user_abo,
|
||||
'isAdmin' => false,
|
||||
'customer_detail' => $customer_detail,
|
||||
'view' => $view,
|
||||
'comp_products' => $comp_products,
|
||||
'one_time_window_open' => $oneTimeWindowOpen,
|
||||
'summary' => $summary,
|
||||
'base_comp_count' => $baseCompCount,
|
||||
];
|
||||
|
||||
return view('user.abo.detail', $data);
|
||||
|
|
@ -121,10 +135,14 @@ class AboController extends Controller
|
|||
|
||||
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 ($UserAboItem = UserAboItem::where('user_abo_id', $user_abo->id)->where('product_id', $product->id)->where('comp', 0)->first()) {
|
||||
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();
|
||||
|
|
@ -155,9 +173,14 @@ class AboController extends Controller
|
|||
if ($isAddOnlyMode && $qty < $UserAboItem->qty) {
|
||||
$qty = $UserAboItem->qty;
|
||||
}
|
||||
$UserAboItem->qty = $qty;
|
||||
$UserAboItem->save();
|
||||
AboItemHistoryService::logQtyChanged($user_abo, $UserAboItem, $qtyBefore, $qty, $editView);
|
||||
$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, $editView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -209,23 +232,112 @@ class AboController extends Controller
|
|||
|
||||
AboOrderCart::initYard($user_abo);
|
||||
AboOrderCart::makeOrderYard($user_abo); // reCalculateShippingPrice
|
||||
$baseCompCount = Yard::instance(AboOrderCart::INSTANCE)->getNumComp();
|
||||
if (AboHelper::isOneTimeWindowOpen($user_abo)) {
|
||||
AboOrderCart::addOneTimeItemsToYard($user_abo->fresh());
|
||||
}
|
||||
AboOrderCart::checkNumOfCompProducts($user_abo); // after reCalculateShippingPrice check it and remove or add comp product
|
||||
|
||||
if ($user_abo->is_for === 'me') {
|
||||
$data['comp_products'] = Shop::getCompProducts('abo-me');
|
||||
}
|
||||
$summary = AboOrderCart::getSplitSummary();
|
||||
$error_message = $message ? $message : false;
|
||||
$html_cart = view('admin.abo._order_abo_show', ['user_abo' => $user_abo, 'error_message' => $error_message, 'add_only_mode' => $isAddOnlyMode])->render();
|
||||
$html_comp = view('user.order.comp_product', $data)->render();
|
||||
$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();
|
||||
|
||||
// $html_total = view("user.homeparty.show_total_order", ['homeparty' => $homeparty])->render();
|
||||
return response()->json(['response' => true, 'data' => $data, 'html_cart' => $html_cart, 'html_comp' => $html_comp, 'amount' => $amount]);
|
||||
return response()->json(['response' => true, 'data' => $data, 'html_cart' => $html_cart, 'html_comp' => $html_comp, 'html_summary' => $html_summary, 'amount' => $amount]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function oneTime(AboOneTimeItemRequest $request, $view, $id)
|
||||
{
|
||||
$user_abo = UserAbo::findOrFail($id);
|
||||
$this->checkPermissions($view, $user_abo);
|
||||
$editView = \Auth::user()?->isAdmin() ? 'admin' : $view;
|
||||
$isAddOnlyMode = AboHelper::isAddOnlyMode($user_abo, $editView);
|
||||
|
||||
if (! AboHelper::isOneTimeWindowOpen($user_abo)) {
|
||||
return response()->json([
|
||||
'response' => false,
|
||||
'message' => __('abo.onetime_window_closed'),
|
||||
], 403);
|
||||
}
|
||||
|
||||
AboOrderCart::initYard($user_abo);
|
||||
$message = (new \App\Services\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();
|
||||
$compProducts = $user_abo->is_for === 'me' ? Shop::getCompProducts('abo-me') : [];
|
||||
|
||||
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' => $compProducts,
|
||||
'cart_instance' => AboOrderCart::INSTANCE,
|
||||
'base_comp_count' => $baseCompCount,
|
||||
])->render(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
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 check_need_basis_product($user_abo, $product, $order_item_id)
|
||||
{
|
||||
// Wenn das zu entfernende Produkt kein Basis-Produkt ist, keine weitere Prüfung nötig
|
||||
|
|
@ -278,9 +390,9 @@ class AboController extends Controller
|
|||
|
||||
->addColumn('add_card', function (Product $product) use ($user_abo) {
|
||||
$ufactor = $user_abo->is_for === 'me' ? true : false;
|
||||
$tax_free = $user_abo->is_for === 'me' ? true : Yard::instance('shopping')->getUserTaxFree();
|
||||
$tax_free = $user_abo->is_for === 'me' ? true : Yard::instance(AboOrderCart::INSTANCE)->getUserTaxFree();
|
||||
|
||||
$price = $product->getFormattedPriceWith($tax_free, $ufactor, Yard::instance('shopping')->getUserCountry());
|
||||
$price = $product->getFormattedPriceWith($tax_free, $ufactor, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry());
|
||||
|
||||
return '<button type="button" class="btn btn-sm btn-md-extra btn-secondary add-product-basket" data-product-id="'.$product->id.'" data-product-name="'.e($product->getLang('name')).'" data-product-price="'.$price.' €">
|
||||
<strong>€ '.$price.'</strong> +<span class="ion ion-md-cart"></span>
|
||||
|
|
@ -302,12 +414,12 @@ class AboController extends Controller
|
|||
->addColumn('price_net', function (Product $product) use ($user_abo) {
|
||||
$ufactor = $user_abo->is_for === 'me' ? true : false;
|
||||
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(true, $ufactor, Yard::instance('shopping')->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance('shopping')->getUserCountry()).'</span>';
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(true, $ufactor, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).'</span>';
|
||||
})
|
||||
->addColumn('price_gross', function (Product $product) use ($user_abo) {
|
||||
$ufactor = $user_abo->is_for === 'me' ? true : false;
|
||||
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(false, $ufactor, Yard::instance('shopping')->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance('shopping')->getUserCountry()).'</span>';
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(false, $ufactor, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>'.'<span class="no-line-break">'.$product->getFormattedPriceCurrencyWith(true, true, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).'</span>';
|
||||
})
|
||||
->addColumn('action', function (Product $product) {
|
||||
return '<button class="btn btn-default btn-sm icon-btn md-btn-flat product-tooltip" title="details" data-modal="modal-lg"
|
||||
|
|
@ -332,6 +444,67 @@ class AboController extends Controller
|
|||
->make(true);
|
||||
}
|
||||
|
||||
public function oneTimeDatatable($user_abo_id)
|
||||
{
|
||||
$user_abo = UserAbo::findOrFail($user_abo_id);
|
||||
|
||||
AboOrderCart::initYard($user_abo);
|
||||
|
||||
$show_on_ids = $user_abo->is_for === 'me' ? ['2'] : ['3'];
|
||||
$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);
|
||||
}
|
||||
})
|
||||
->orderBy('name', 'asc');
|
||||
|
||||
return \DataTables::eloquent($query)
|
||||
->addColumn('add_card', function (Product $product) use ($user_abo) {
|
||||
$ufactor = $user_abo->is_for === 'me' ? true : false;
|
||||
$tax_free = $user_abo->is_for === 'me' ? true : Yard::instance(AboOrderCart::INSTANCE)->getUserTaxFree();
|
||||
|
||||
$price = $product->getFormattedPriceWith($tax_free, $ufactor, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry());
|
||||
|
||||
return '<button type="button" class="btn btn-sm btn-md-extra btn-warning add-onetime-product-basket" data-product-id="'.$product->id.'" data-product-name="'.e($product->getLang('name')).'" data-product-price="'.$price.' €">
|
||||
<strong>€ '.$price.'</strong> +<span class="ion ion-md-cart"></span>
|
||||
</button>';
|
||||
})
|
||||
->addColumn('picture', function (Product $product) {
|
||||
if (count($product->images)) {
|
||||
return '<img class="img-fluid img-extra" alt="" src="'.route('product_image', [$product->images->first()->slug]).'">';
|
||||
}
|
||||
|
||||
return '';
|
||||
})
|
||||
->addColumn('name', function (Product $product) {
|
||||
return '<strong>'.$product->getLang('name').'</strong>';
|
||||
})
|
||||
->addColumn('points', function (Product $product) {
|
||||
return '<span class="no-line-break">'.$product->getFormattedPoints().'</span>';
|
||||
})
|
||||
->addColumn('price_net', function (Product $product) use ($user_abo) {
|
||||
$ufactor = $user_abo->is_for === 'me' ? true : false;
|
||||
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(true, $ufactor, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>';
|
||||
})
|
||||
->addColumn('price_gross', function (Product $product) use ($user_abo) {
|
||||
$ufactor = $user_abo->is_for === 'me' ? true : false;
|
||||
|
||||
return '<span class="no-line-break">'.$product->getFormattedPriceWith(false, $ufactor, Yard::instance(AboOrderCart::INSTANCE)->getUserCountry()).' €</span>';
|
||||
})
|
||||
->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);
|
||||
}
|
||||
|
||||
private function checkPermissions($view, $user_abo)
|
||||
{
|
||||
\Log::info('checkPermissions', ['view' => $view, 'user_abo' => $user_abo]);
|
||||
|
|
|
|||
|
|
@ -773,10 +773,11 @@ class OrderController extends Controller
|
|||
$isAbo = str_contains($is_for, 'abo');
|
||||
$qty = isset($data['qty']) ? (int) $data['qty'] : 0;
|
||||
if ($qty > 0 && ! ProductOrderContext::isProductAllowedInContext($product, $isAbo, $is_for)) {
|
||||
return response()->json([
|
||||
'response' => false,
|
||||
'message' => __('msg.cart_product_not_allowed_for_order_type'),
|
||||
]);
|
||||
return $this->cartUpdateRejected($data, __('msg.cart_product_not_allowed_for_order_type'));
|
||||
}
|
||||
|
||||
if ($qty > 0 && $this->exceedsCartMaxWeight(Yard::instance('shopping'), $product, $qty)) {
|
||||
return $this->cartUpdateRejected($data, __('msg.cart_max_weight_reached'));
|
||||
}
|
||||
|
||||
$image = '';
|
||||
|
|
@ -831,6 +832,67 @@ class OrderController extends Controller
|
|||
return response()->json(['response' => true, 'data' => $data, 'html_card' => $html_card, 'html_comp' => $html_comp]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lehnt ein Warenkorb-Update ab, ohne den Warenkorb zu verändern. Der Warenkorb
|
||||
* wird unverändert neu gerendert (Zähler bleibt stehen) und der Hinweis als
|
||||
* Inline-Meldung über dem Warenkorb ausgegeben.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
private function cartUpdateRejected(array $data, string $message): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
$data['error_message'] = $message;
|
||||
|
||||
if (isset($data['product_id'])) {
|
||||
$currentQty = 0;
|
||||
foreach (Yard::instance('shopping')->content() as $row) {
|
||||
if (! $row->options->comp && (int) $row->id === (int) $data['product_id']) {
|
||||
$currentQty = (int) $row->qty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data['qty'] = $currentQty;
|
||||
}
|
||||
|
||||
$html_card = view('user.order.yard_view_form', $data)->render();
|
||||
$html_comp = view('user.order.comp_product', $data)->render();
|
||||
|
||||
return response()->json([
|
||||
'response' => true,
|
||||
'data' => $data,
|
||||
'html_card' => $html_card,
|
||||
'html_comp' => $html_comp,
|
||||
'message' => $message,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob das Hochsetzen eines Produkts auf die Zielmenge das Maximalgewicht
|
||||
* des Versandlandes überschreiten würde. Mengenreduktionen werden nie blockiert.
|
||||
*/
|
||||
private function exceedsCartMaxWeight(\App\Services\Yard $yard, Product $product, int $targetQty): bool
|
||||
{
|
||||
$productWeight = (int) $product->weight;
|
||||
if ($productWeight <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$currentQty = 0;
|
||||
foreach ($yard->content() as $row) {
|
||||
if (! $row->options->comp && (int) $row->id === (int) $product->id) {
|
||||
$currentQty = (int) $row->qty;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$additionalWeight = $productWeight * ($targetQty - $currentQty);
|
||||
if ($additionalWeight <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $yard->exceedsMaxWeight($additionalWeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle updating shipping country
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ class CardController extends Controller
|
|||
{
|
||||
$product = Product::find($id);
|
||||
if ($product && ProductOrderContext::isProductAllowedInCustomerWebshop($product)) {
|
||||
$additionalWeight = (int) $product->weight * (int) $quantity;
|
||||
if ($additionalWeight > 0 && Yard::instance($this->instance)->exceedsMaxWeight($additionalWeight)) {
|
||||
\Session::flash('alert-error', __('msg.cart_max_weight_reached'));
|
||||
|
||||
return back();
|
||||
}
|
||||
$image = '';
|
||||
if ($product->images->count()) {
|
||||
$image = $product->images->first()->slug;
|
||||
|
|
@ -61,11 +67,17 @@ class CardController extends Controller
|
|||
$product = Product::find($id);
|
||||
|
||||
if ($product && ProductOrderContext::isProductAllowedInCustomerWebshop($product)) {
|
||||
$quantity = Request::get('quantity') ? Request::get('quantity') : 1;
|
||||
$additionalWeight = (int) $product->weight * (int) $quantity;
|
||||
if ($additionalWeight > 0 && Yard::instance($this->instance)->exceedsMaxWeight($additionalWeight)) {
|
||||
\Session::flash('alert-error', __('msg.cart_max_weight_reached'));
|
||||
|
||||
return back();
|
||||
}
|
||||
$image = '';
|
||||
if ($product->images->count()) {
|
||||
$image = $product->images->first()->slug;
|
||||
}
|
||||
$quantity = Request::get('quantity') ? Request::get('quantity') : 1;
|
||||
$cartItem = Yard::instance($this->instance)
|
||||
->add(
|
||||
$product->id,
|
||||
|
|
@ -122,6 +134,14 @@ class CardController extends Controller
|
|||
if ($product && $product->is_membership_only) {
|
||||
$qty = 1;
|
||||
}
|
||||
if ($product) {
|
||||
$additionalWeight = (int) $product->weight * ((int) $qty - (int) $cartItem->qty);
|
||||
if ($additionalWeight > 0 && Yard::instance($this->instance)->exceedsMaxWeight($additionalWeight)) {
|
||||
\Session::flash('alert-error', __('msg.cart_max_weight_reached'));
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
Yard::instance($this->instance)->update($rowId, $qty);
|
||||
Yard::instance($this->instance)->reCalculateShippingPrice();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue