From 570d428b1cfec727e309db2d867ca631067cc7bc Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Sat, 25 Dec 2021 02:51:22 +0100 Subject: [PATCH] promotion 1.0 --- .env | 8 + .../Api/ShoppingUserController.php | 2 +- app/Http/Controllers/Pay/PayController.php | 44 +++- app/Http/Controllers/Pay/PayPalController.php | 95 ++++++++ app/Http/Controllers/SalesController.php | 5 +- .../Controllers/User/CheckoutController.php | 4 +- .../Controllers/User/PaymentController.php | 4 +- .../Controllers/User/PromotionController.php | 6 +- app/Http/Controllers/User/SalesController.php | 84 +++++++ .../Controllers/User/ShopSalesController.php | 2 +- .../Controllers/Web/PromotionController.php | 188 ++++++++++++--- app/Mail/MailCheckout.php | 8 +- app/Models/PromotionAdmin.php | 6 + app/Models/PromotionUserOrder.php | 126 ++++++++++ app/Models/ShippingPrice.php | 2 + app/Models/ShoppingOrder.php | 22 ++ app/Models/ShoppingOrderItem.php | 14 ++ app/Models/ShoppingPayment.php | 3 + app/Models/UserPayCredit.php | 3 +- app/Providers/RouteServiceProvider.php | 2 +- app/Repositories/CheckoutRepository.php | 226 ++++++++++++++++++ app/Services/CustomerPriority.php | 50 +++- app/Services/Payment.php | 40 +++- app/Services/PromotionCart.php | 22 +- app/Services/Yard.php | 69 ++++-- config/app.php | 1 + config/paypal.php | 25 ++ ...23_163527_create_shopping_orders_table.php | 4 +- ...3724_create_shopping_order_items_table.php | 3 +- ...1_135225_create_promotion_admins_table.php | 2 + ...3_create_promotion_user_products_table.php | 1 + ...513_create_promotion_user_orders_table.php | 76 ++++++ public/css/shop.css | 2 +- public/js/iq-promotion-cart.js | 13 +- public/js/iq-promotion-shop-cart.js | 21 +- resources/lang/de/email.php | 3 + resources/lang/de/payment.php | 3 + .../admin/modal/is_like_member.blade.php | 2 + .../views/admin/promotion/form.blade.php | 17 +- resources/views/admin/sales/_detail.blade.php | 19 +- .../views/admin/sales/customers.blade.php | 2 + resources/views/emails/checkout.blade.php | 28 +++ .../views/emails/checkout_status.blade.php | 39 ++- .../layouts/includes/layout-sidenav.blade.php | 5 +- resources/views/pdf/invoice.blade.php | 2 + resources/views/user/promotion/form.blade.php | 2 +- .../views/user/sales/order_detail.blade.php | 10 + resources/views/user/sales/orders.blade.php | 58 +++++ .../views/web/promotion/_checkout.blade.php | 38 +-- .../web/promotion/_free_product.blade.php | 8 +- .../views/web/promotion/_intro.blade.php | 1 - .../web/promotion/_invoice_details.blade.php | 76 +++++- .../_invoice_details_quick.blade.php | 133 +++++++++++ .../web/promotion/_promotion_cart.blade.php | 4 +- .../views/web/promotion/_shipping.blade.php | 7 +- .../web/promotion/_shop_products.blade.php | 37 ++- resources/views/web/promotion/index.blade.php | 114 +-------- .../views/web/promotion/thanksorder.blade.php | 65 +++-- routes/web.php | 12 +- vendor.tar | Bin 102374400 -> 104123392 bytes 60 files changed, 1596 insertions(+), 272 deletions(-) create mode 100644 app/Http/Controllers/Pay/PayPalController.php create mode 100755 app/Http/Controllers/User/SalesController.php create mode 100644 app/Models/PromotionUserOrder.php create mode 100644 app/Repositories/CheckoutRepository.php create mode 100644 config/paypal.php create mode 100644 database/migrations/2021_12_01_160513_create_promotion_user_orders_table.php create mode 100644 resources/views/user/sales/order_detail.blade.php create mode 100644 resources/views/user/sales/orders.blade.php create mode 100644 resources/views/web/promotion/_invoice_details_quick.blade.php diff --git a/.env b/.env index bf23ea0..d15f579 100644 --- a/.env +++ b/.env @@ -3,6 +3,7 @@ APP_ENV=local APP_KEY=base64:w0K6RjfleoAOpuICea14JnaZ28PNc6EMzIFMQZ3MVtU= APP_DEBUG=true APP_URL=https://partner.gruene-seele.test +APP_API_DOMAIN=gruene-seele.bio APP_DOMAIN=partner.gruene-seele.test APP_PROMO_URL=https://testemich.test APP_PROMO_DOMAIN=testemich.test @@ -54,6 +55,13 @@ MAIL_ENCRYPTION="" MAIL_FROM_ADDRESS=partner@gruene-seele.bio MAIL_FROM_NAME="Partner GRÜNE SEELE Naturkosmetik" +PAYPAL_MODE=sandbox +PAYPAL_SANDBOX_CLIENT_ID=AYePlmttXXyoUJTgECTiyXht7LKCOIe4tky4q943NQQRsqyFhLYLHUzYbyhXvKJAXp--lrO040iZWtRB +PAYPAL_SANDBOX_CLIENT_SECRET=EE9-80_RVcl6m7BRYPrVCrZFeQWhSAIClCLULOiC07DIxf_Sb4pyBdnCgewv_ULrGDwEcSIUeeBDiUQI +PAYPAL_LIVE_CLIENT_ID=AWz915k8LX6k4auJFVsP4Rwa5koRP718pEbnDAcXnaN--ox1ZsoPanBIE32EXdUscF292-XZNSTH8_t- +PAYPAL_LIVE_CLIENT_SECRET=EMWCXquC3j5f7rmBu4dkkSN4I3V0OLbGss2seXeCc0TfpR9cMbv7GGm3b0i1xgMTFlJNIsAWtB-FjRyW + + AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= AWS_DEFAULT_REGION=us-east-1 diff --git a/app/Http/Controllers/Api/ShoppingUserController.php b/app/Http/Controllers/Api/ShoppingUserController.php index 05073d6..fb1ff9b 100755 --- a/app/Http/Controllers/Api/ShoppingUserController.php +++ b/app/Http/Controllers/Api/ShoppingUserController.php @@ -265,7 +265,7 @@ class ShoppingUserController extends Controller $shopping_user = ShoppingUser::create($data); //Kundenhoheit prüfen - $priority = CustomerPriority::checkOne($shopping_user, true, false); + $priority = CustomerPriority::checkOne($shopping_user, true, false, true); \App\Services\Shop::newUserOrder($shopping_user->number); //exists //like //update $user = $this->prepareForShow($shopping_user); diff --git a/app/Http/Controllers/Pay/PayController.php b/app/Http/Controllers/Pay/PayController.php index 745b165..2c613d2 100644 --- a/app/Http/Controllers/Pay/PayController.php +++ b/app/Http/Controllers/Pay/PayController.php @@ -59,6 +59,8 @@ class PayController extends Controller private $reference; + private $payment_method; + public function __construct() { } @@ -77,6 +79,7 @@ class PayController extends Controller public function setPrePayment($payment_method, $amount, $currency, $ret = []){ $this->reference = $this->shopping_order->created_at->format('Ym').$this->shopping_order->id;//substr(uniqid('m', false), 0, 16); + $this->payment_method = $payment_method; $this->setMethod($payment_method, $ret); $this->prepayment = [ @@ -86,7 +89,6 @@ class PayController extends Controller "param" => $this->shopping_order->id, ]; - $this->shopping_payment = ShoppingPayment::create([ 'shopping_order_id' => $this->shopping_order->id, 'clearingtype' => $this->method["clearingtype"], @@ -119,6 +121,15 @@ class PayController extends Controller private function setMethod($payment_method, $ret = []){ //vorkasse + if($payment_method === 'non'){ + $this->method = [ + "clearingtype" => "non", + "wallettype" => "", + 'onlinebanktransfertype' => "", + "request" => "authorization", + ]; + } + if($payment_method === 'vor'){ $this->method = [ "clearingtype" => "vor", @@ -138,12 +149,21 @@ class PayController extends Controller ]; } + //Rechnungskauf + if($payment_method === 'pp'){ + $this->method = [ + "clearingtype" => "pp", + "wallettype" => "", + 'onlinebanktransfertype' => "", + "request" => "CAPTURE", + ]; + } + } - public function ResponseData($identifier){ + public function ResponseData($identifier, $payment_for = false){ $request = array_merge($this->default, $this->personalData, $this->deliveryData, $this->method, $this->prepayment, $this->urls); - //RECHNUNG MIV $payt = PaymentTransaction::create([ 'shopping_payment_id' => $this->shopping_payment->id, @@ -155,10 +175,26 @@ class PayController extends Controller 'txaction' => 'prev', 'mode' => $this->shopping_payment->mode, ]); + //paypal + if($this->payment_method === 'pp'){ + $paypal = new PayPalController; + $redirect = $paypal->payment($this->shopping_payment, $payt, $identifier, $this->shopping_order->promotion_user_id); + Util::setUserHistoryValue(['status'=>4], $identifier); + return $redirect; + } Util::setUserHistoryValue(['status'=>5], $identifier); - return redirect(route('user_checkout_final', [$payt->id, $this->reference, $identifier])); + switch ($payment_for) { + case 4: //promotion + return redirect(route('web_promotion_goto', ['thanksorder', $this->shopping_order->promotion_user_id, $payt->id, $this->reference, $identifier])); + break; + + default: + return redirect(route('user_checkout_final', [$payt->id, $this->reference, $identifier])); + break; + } + } } diff --git a/app/Http/Controllers/Pay/PayPalController.php b/app/Http/Controllers/Pay/PayPalController.php new file mode 100644 index 0000000..2d26568 --- /dev/null +++ b/app/Http/Controllers/Pay/PayPalController.php @@ -0,0 +1,95 @@ +setApiCredentials(config('paypal')); + $provider->setAccessToken($provider->getAccessToken()); + $provider->setCurrency('EUR'); + + $order = $provider->createOrder([ + "intent"=> "CAPTURE", + "purchase_units"=> [ + [ + "reference_id" => $shopping_payment->reference, + "shopping_order_id" => $shopping_payment->shopping_order_id, + "amount"=> [ + "currency_code"=> "USD", + "value"=> ($shopping_payment->amount / 100) + ], + 'description' => 'test' + ] + ], + 'application_context' => [ + 'cancel_url' => route('cancel.paypal_payment', [$promotion_user_id, $payt->id, $shopping_payment->reference, $identifier]), + 'return_url' => route('success.paypal_payment', [$promotion_user_id, $payt->id, $shopping_payment->reference, $identifier]) + ] + + ]); + $payt->key = $order['id']; + $payt->save(); + return redirect($order['links'][1]['href'])->send(); + + } + + public function paymentSuccess($id, $transactionId=false, $reference=false, $identifier=false) + { + $PromotionUser = PromotionUser::findOrFail($id); + $payt = PaymentTransaction::findOrFail($transactionId); + if($payt->shopping_payment->reference != $reference){ + abort(404); + } + // Init PayPal + $provider = \PayPal::setProvider(); + $provider->setApiCredentials(config('paypal')); + $provider->setAccessToken($provider->getAccessToken()); + + // Get PaymentOrder using our transaction ID + $order = $provider->capturePaymentOrder($payt->key); + if(isset($order['type'])){ + abort(403, 'PayPal Type: '.$order['type']); + } + + if(!isset($order['status']) || $order['status'] !== "COMPLETED"){ + abort(403, 'Error: Order Status '); + } + + if(Request::get('token') !== $payt->key){ + abort(403, 'Error: PayPal token'); + } + $payt->request = $order['status']; + $payt->save(); + return redirect(route('web_promotion_goto', ['thanksorder', $id, $payt->id, $reference, $identifier])); + + } + + public function paymentCancel($id, $transactionId=false, $reference=false, $identifier=false) + { + $PromotionUser = PromotionUser::findOrFail($id); + + return redirect(url($PromotionUser->url)); + dd('Your payment has been declend. The payment cancelation page goes here!'); + } + + + +} + + + + diff --git a/app/Http/Controllers/SalesController.php b/app/Http/Controllers/SalesController.php index bfd9dda..2e1d9cf 100755 --- a/app/Http/Controllers/SalesController.php +++ b/app/Http/Controllers/SalesController.php @@ -224,8 +224,8 @@ class SalesController extends Controller if($ShoppingOrder->shopping_user->is_for === 'ot'){ return 'Kundenbestellung'; } - if($ShoppingOrder->shopping_user->is_for === 'hp'){ - return 'Homepartybestellung'; + if($ShoppingOrder->shopping_user->is_for === 'pr'){ + return 'Promotion'; } return '-'; }) @@ -249,6 +249,7 @@ class SalesController extends Controller ->orderColumn('id', 'id $1') ->orderColumn('txaction', 'txaction $1') + ->orderColumn('is_for', 'is_for $1') ->orderColumn('member_id', 'member_id $1') ->orderColumn('shipped', 'shipped $1') ->orderColumn('total_shipping', 'total_shipping $1') diff --git a/app/Http/Controllers/User/CheckoutController.php b/app/Http/Controllers/User/CheckoutController.php index 3999290..f294a0e 100755 --- a/app/Http/Controllers/User/CheckoutController.php +++ b/app/Http/Controllers/User/CheckoutController.php @@ -106,7 +106,6 @@ class CheckoutController extends Controller $shopping_user->billing_state = Shop::getCountryShippingCountryId($shopping_user->billing_country_id); $shopping_user->shipping_state = Shop::getCountryShippingCountryId($shopping_user->shipping_country_id); $shopping_user->same_as_billing = $shopping_user->same_as_billing ? false : true; //reinvert - } if($shopping_user->same_as_billing === NULL){ $shopping_user->same_as_billing = false; @@ -518,6 +517,7 @@ class CheckoutController extends Controller $this->putPayments('shopping_order_margin_id', $shopping_order_margin->id); } } + private function putPayments($key, $value){ $content = $this->getContent(); $content->put($key, $value); @@ -581,8 +581,6 @@ class CheckoutController extends Controller ]; Payment::paymentStatusSendMail($shopping_order, $shopping_payment, $data); } - - } } \ No newline at end of file diff --git a/app/Http/Controllers/User/PaymentController.php b/app/Http/Controllers/User/PaymentController.php index 5187405..6b1dbca 100644 --- a/app/Http/Controllers/User/PaymentController.php +++ b/app/Http/Controllers/User/PaymentController.php @@ -45,10 +45,12 @@ class PaymentController extends Controller ->addColumn('message', function (UserPayCredit $user_pay_credit) { if($user_pay_credit->status === 3){ return nl2br($user_pay_credit->message); + }elseif($user_pay_credit->status === 5 || $user_pay_credit->status === 6){ + return trans('payment.'.$user_pay_credit->message). + '   '; }else{ return trans('payment.'.$user_pay_credit->message). '   '; - } }) ->addColumn('credit', function (UserPayCredit $user_pay_credit) { diff --git a/app/Http/Controllers/User/PromotionController.php b/app/Http/Controllers/User/PromotionController.php index 76a07b9..ce267a5 100644 --- a/app/Http/Controllers/User/PromotionController.php +++ b/app/Http/Controllers/User/PromotionController.php @@ -38,7 +38,10 @@ class PromotionController extends Controller if($user_promotion->user_id != Auth::user()->id){ abort(404); } - $user_promotion->about_you = !$user_promotion->about_you ? $user_promotion->user->account->about_you : $user_promotion->about_you; + + $user_promotion->description = $user_promotion->description ? $user_promotion->description : $user_promotion->promotion_admin->user_description; + $about_you = $user_promotion->user->account->about_you ?$user_promotion->user->account->about_you : $user_promotion->promotion_admin->user_about; + $user_promotion->about_you = $user_promotion->about_you ? $user_promotion->about_you : $about_you; $data = [ 'checkPaymentCredit' => $user_promotion->checkPaymentCredit(), 'user_promotion_cart' => PromotionUser::preCalculateCart($user_promotion, 'user_promotion'), @@ -66,7 +69,6 @@ class PromotionController extends Controller return redirect(route('user_promotion_detail', [$id]))->withErrors($validator)->withInput(Request::all()); } $model = $this->promoRepo->update($id, Request::all()); - } \Session()->flash('alert-save', true); return redirect(route('user_promotion_detail', [$model->id])); diff --git a/app/Http/Controllers/User/SalesController.php b/app/Http/Controllers/User/SalesController.php new file mode 100755 index 0000000..405c452 --- /dev/null +++ b/app/Http/Controllers/User/SalesController.php @@ -0,0 +1,84 @@ +middleware('active.account'); + } + + public function orders() + { + $data = [ + ]; + return view('user.sales.orders', $data); + } + + public function orderDetail($id) + { + $user = User::find(\Auth::user()->id); + $shopping_order = ShoppingOrder::findOrFail($id); + if($shopping_order->member_id !== $user->id){ + abort(404); + } + $data = [ + 'shopping_order' => $shopping_order, + 'isAdmin' => false, + ]; + return view('user.sales.order_detail', $data); + } + + public function ordersDatatable(){ + + $user = User::find(\Auth::user()->id); + $query = ShoppingOrder::with('shopping_user')->select('shopping_orders.*')->where('shopping_orders.member_id', $user->id); + + return \DataTables::eloquent($query) + ->addColumn('id', function (ShoppingOrder $ShoppingOrder) { + return ''; + }) + ->addColumn('created_at', function (ShoppingOrder $ShoppingOrder) { + return $ShoppingOrder->created_at->format("d.m.Y"); + }) + ->addColumn('txaction', function (ShoppingOrder $ShoppingOrder) { + return Payment::getShoppingOrderBadge($ShoppingOrder); + }) + ->addColumn('total_shipping', function (ShoppingOrder $ShoppingOrder) { + return $ShoppingOrder->getFormattedTotalShipping(); + }) + ->addColumn('orders', function (ShoppingOrder $ShoppingOrder) { + return $ShoppingOrder->shopping_user ? $ShoppingOrder->shopping_user->orders : ''; + }) + ->addColumn('user_shop_id', function (ShoppingOrder $ShoppingOrder) { + return $ShoppingOrder->user_shop ? ''.$ShoppingOrder->user_shop->getSubdomain(false).'' : ''; + }) + ->addColumn('is_for', function (ShoppingOrder $ShoppingOrder) { + if($ShoppingOrder->shopping_user->is_for === 'me'){ + return 'Vertriebspartnerbestellung'; + } + if($ShoppingOrder->shopping_user->is_for === 'ot'){ + return 'Kundenbestellung'; + } + if($ShoppingOrder->shopping_user->is_for === 'pr'){ + return 'Promotion'; + } + return '-'; + }) + ->orderColumn('id', 'id $1') + ->orderColumn('txaction', 'txaction $1') + ->rawColumns(['id', 'is_for', 'txaction', 'user_shop_id']) + ->make(true); + } + + + +} \ No newline at end of file diff --git a/app/Http/Controllers/User/ShopSalesController.php b/app/Http/Controllers/User/ShopSalesController.php index 2166766..766f697 100755 --- a/app/Http/Controllers/User/ShopSalesController.php +++ b/app/Http/Controllers/User/ShopSalesController.php @@ -8,7 +8,7 @@ use App\Services\Payment; use App\User; -class ShopSalesController extends Controller +class SalesController extends Controller { public function __construct() diff --git a/app/Http/Controllers/Web/PromotionController.php b/app/Http/Controllers/Web/PromotionController.php index a82f589..a7d36cf 100644 --- a/app/Http/Controllers/Web/PromotionController.php +++ b/app/Http/Controllers/Web/PromotionController.php @@ -2,16 +2,22 @@ namespace App\Http\Controllers\Web; +use Yard; use Request; use Response; use Validator; use App\Services\Util; use App\Models\Product; +use App\Models\UserHistory; use App\Models\PaymentMethod; use App\Models\PromotionUser; +use App\Models\ShoppingOrder; +use App\Models\ShoppingPayment; use App\Services\PromotionCart; +use App\Models\PaymentTransaction; use App\Http\Controllers\Controller; - +use App\Repositories\CheckoutRepository; +use App\Services\Payment; class PromotionController extends Controller { @@ -47,9 +53,8 @@ class PromotionController extends Controller return view('web.promotion.index', $data); } - public function goto($load, $id){ + public function goto($load, $id, $transactionId=false, $reference=false, $identifier=false){ $PromotionUser = PromotionUser::findOrFail($id); - $data = [ 'promotion_user' => $PromotionUser, ]; @@ -57,15 +62,29 @@ class PromotionController extends Controller if($load === 'thanksreminder'){ return view('web.promotion.thanksreminder', $data); } - if($load === 'thanksorder'){ - return view('web.promotion.thanksorder', $data); - } if($load === 'notactive'){ return view('web.promotion.notactive', $data); } + if($load === 'thanksorder'){ + $payt = PaymentTransaction::findOrFail($transactionId); + if($payt->shopping_payment->reference != $reference){ + abort(404); + } + Yard::instance('shopping')->destroy(); + $checkRepo = new CheckoutRepository(); + $checkRepo->destroy(); + if(($payt->status === 'fnc' || $payt->status === 'vor' || $payt->status === 'pp' || $payt->status === 'non') && $payt->txaction === 'prev'){ + $this->directPaymentStatus($payt, $identifier); + } + $data = [ + 'promotion_user' => $PromotionUser, + 'order_reference' => $payt->shopping_payment->reference, + 'pay_trans' => $payt, + ]; + return view('web.promotion.thanksorder', $data); + } } - public function store($id){ $PromotionUser = PromotionUser::findOrFail($id); @@ -78,13 +97,106 @@ class PromotionController extends Controller return redirect(route('web_promotion_goto', ['thanksreminder', $PromotionUser->id])); } - if($data['action'] === 'submit-promotion-order'){ - return redirect(route('web_promotion_goto', ['thanksorder', $PromotionUser->id])); + $rules = array( + 'billing_firstname'=>'required', + 'billing_lastname'=>'required', + 'billing_address'=>'required', + 'billing_zipcode'=>'required', + 'billing_city' => 'required', + 'billing_state' => 'required', + 'billing_email'=>'required|email', + ); + + if(Request::get('same_as_billing')){ + $rules = array_merge($rules, [ + 'shipping_firstname'=>'required', + 'shipping_lastname'=>'required', + 'shipping_address'=>'required', + 'shipping_zipcode'=>'required', + 'shipping_city' => 'required', + 'shipping_salutation' => 'required' + ]); + } + $validator = Validator::make(Request::all(), $rules); + + if ($validator->fails()) { + return back()->withErrors($validator)->withInput(Request::all()); + } + $identifier = Util::getToken(); + $data['is_from'] = 'shopping'; + $data['is_for'] = 'pr'; + unset($data['_token']); + Yard::instance('shopping')->putYardExtra('shopping_data', $data); + + UserHistory::create(['user_id' => $PromotionUser->user_id, 'action'=>'web_promotion_payment', 'status'=>1, 'product_id'=>null, 'identifier'=>$identifier]); + $checkRepo = new CheckoutRepository(); + $checkRepo->setPromotion(4, $PromotionUser); + $checkRepo->init($identifier, $data); + return $checkRepo->makePayment(); + + //$path = str_replace('http', 'https', $path); + //return redirect()->secure($path); + // return redirect(route('user_checkout', [$identifier])); + } - - dd($PromotionUser); } + + + + private function directPaymentStatus(PaymentTransaction $payt, $identifier){ + + if(isset($payt->transmitted_data['param'])){ + $shopping_order = ShoppingOrder::find($payt->transmitted_data['param']); + $shopping_payment = ShoppingPayment::where('reference', $payt->transmitted_data['reference'])->first(); + + $shopping_order->txaction = 'open'; + $shopping_order->save(); + $payt->txaction = "open"; + + //is Promotion Handel it + if($shopping_order->promotion_user_id > 0){ + Payment::handelPromotionProduct($shopping_order); + } + if($shopping_payment){ + //Payment::handelUserPayCredits($shopping_order, 'deduction'); + if($payt->status === 'vor'){ + $shopping_payment->txaction = 'open'; + $shopping_order->txaction = 'open'; + $payt->txaction = "open"; + } + if($payt->status === 'pp'){ + $send_link = Payment::paymentStatusPaidAction($shopping_order, true); + $shopping_payment->txaction = 'paid'; + $shopping_order->txaction = 'paid'; + $payt->txaction = "paid"; + } + if($payt->status === 'fnc'){ + $send_link = Payment::paymentStatusPaidAction($shopping_order, true); + $shopping_payment->txaction = 'open'; + $shopping_order->txaction = 'open'; + $payt->txaction = "open"; + } + if($payt->status === 'non'){ + $send_link = Payment::paymentStatusPaidAction($shopping_order, true); + $shopping_payment->txaction = 'paid'; + $shopping_order->txaction = 'paid'; + $payt->txaction = "paid"; + $shopping_order->save(); + \App\Services\Shop::newUserOrder($shopping_order->shopping_user->number); + } + $shopping_payment->save(); + } + $payt->save(); + $data = [ + 'mode' => $payt->transmitted_data['mode'], + 'txaction' => $payt->txaction, + 'send_link' => false, + ]; + Payment::paymentStatusSendMail($shopping_order, $shopping_payment, $data); + } + } + public function load(){ $data = Request::all(); $ret = ""; @@ -94,32 +206,36 @@ class PromotionController extends Controller $product = Product::find($data['id']); //current user form order $ret = view("web.promotion.show_product", compact('product', 'data'))->render(); } - if($data['action'] === 'switch-free-product'){ - \App\Services\PromotionCart::updateFeeProduct($data); - $ret = view("web.promotion._promotion_cart", compact('data'))->render(); + if($data['perform']){ + if($data['action'] === 'switch-free-product'){ + \App\Services\PromotionCart::updateFeeProduct($data); + } + if($data['action'] === 'add-shop-product'){ + $data['qty'] = \App\Services\PromotionCart::updateProduct($data, true); + } + if($data['action'] === 'update-shop-product'){ + $data['qty'] = \App\Services\PromotionCart::updateProduct($data); + } + if($data['action'] === 'remove-shop-product'){ + \App\Services\PromotionCart::updateProduct($data); + $data['qty'] = 0; + } + if($data['action'] === 'clear-cart'){ + \App\Services\PromotionCart::clearCart($data); + } + if($data['action'] === 'switch-shipping'){ + \App\Services\PromotionCart::switchShipping($data); + } + $cart = view("web.promotion._promotion_cart", compact('data'))->render(); + if(Yard::instance('shopping')->isQuickShipping()){ + $invoice = view("web.promotion._invoice_details_quick")->render(); + }else{ + $invoice = view("web.promotion._invoice_details")->render(); + } + $checkout = view("web.promotion._checkout")->render(); + + return response()->json(['response' => $data, 'cart'=>$cart, 'invoice'=>$invoice, 'checkout'=>$checkout, 'status'=>$status]); } - if($data['action'] === 'add-shop-product'){ - $data['qty'] = \App\Services\PromotionCart::updateProduct($data, true); - $ret = view("web.promotion._promotion_cart", compact('data'))->render(); - } - if($data['action'] === 'update-shop-product'){ - $data['qty'] = \App\Services\PromotionCart::updateProduct($data); - $ret = view("web.promotion._promotion_cart", compact('data'))->render(); - } - if($data['action'] === 'remove-shop-product'){ - \App\Services\PromotionCart::updateProduct($data); - $data['qty'] = 0; - $ret = view("web.promotion._promotion_cart", compact('data'))->render(); - } - if($data['action'] === 'clear-cart'){ - \App\Services\PromotionCart::clearCart($data); - $ret = view("web.promotion._promotion_cart", compact('data'))->render(); - } - - if($data['action'] === 'switch-shipping'){ - $ret = view("web.promotion._promotion_cart", compact('data'))->render(); - } - return response()->json(['response' => $data, 'html'=>$ret, 'status'=>$status]); } } diff --git a/app/Mail/MailCheckout.php b/app/Mail/MailCheckout.php index 2432bca..f726b3a 100644 --- a/app/Mail/MailCheckout.php +++ b/app/Mail/MailCheckout.php @@ -31,7 +31,11 @@ class MailCheckout extends Mailable $this->mode = $mode; if($this->txaction === 'paid'){ - $this->subject = __('email.checkout_subject_paid')." "; + if($this->shopping_payment->clearingtype === 'non') + $this->subject = __('email.checkout_subject_non_paid')." "; + else{ + $this->subject = __('email.checkout_subject_paid')." "; + } }elseif($this->txaction === 'extern'){ $this->subject = __('email.checkout_subject_extern').": "; $this->subject .= $shopping_order->member->account->m_first_name." ".$shopping_order->member->account->m_last_name." - "; @@ -45,7 +49,6 @@ class MailCheckout extends Mailable }*/ } - public function build() { $salutation = __('email.hello').","; @@ -82,6 +85,5 @@ class MailCheckout extends Mailable 'mode' => $this->mode ]); } - } } \ No newline at end of file diff --git a/app/Models/PromotionAdmin.php b/app/Models/PromotionAdmin.php index 794175d..ab7b1eb 100644 --- a/app/Models/PromotionAdmin.php +++ b/app/Models/PromotionAdmin.php @@ -53,6 +53,10 @@ use Illuminate\Database\Eloquent\Collection; * @property-read int|null $promotion_admin_products_active_count * @method static \Illuminate\Database\Eloquent\Builder|PromotionAdmin whereShop($value) * @method static \Illuminate\Database\Eloquent\Builder|PromotionAdmin whereType($value) + * @property string|null $user_description + * @property string|null $user_about + * @method static \Illuminate\Database\Eloquent\Builder|PromotionAdmin whereUserAbout($value) + * @method static \Illuminate\Database\Eloquent\Builder|PromotionAdmin whereUserDescription($value) */ class PromotionAdmin extends Model { @@ -77,6 +81,8 @@ class PromotionAdmin extends Model 'type', 'name', 'description', + 'user_description', + 'user_about', 'from', 'to', 'shop', diff --git a/app/Models/PromotionUserOrder.php b/app/Models/PromotionUserOrder.php new file mode 100644 index 0000000..3ac4fd8 --- /dev/null +++ b/app/Models/PromotionUserOrder.php @@ -0,0 +1,126 @@ + 'int', + 'promotion_user_id' => 'int', + 'promotion_user_product_id' => 'int', + 'product_id' => 'int', + 'shopping_order_item_id' => 'int', + 'shopping_order_id' => 'int', + 'shopping_user_id' => 'int', + 'qty' => 'int', + 'price' => 'float', + 'price_net' => 'float', + 'tax_rate' => 'float', + 'status' => 'int' + ]; + + protected $fillable = [ + 'promotion_admin_id', + 'promotion_user_id', + 'promotion_user_product_id', + 'product_id', + 'shopping_order_item_id', + 'shopping_order_id', + 'shopping_user_id', + 'qty', + 'price', + 'price_net', + 'tax_rate', + 'status' + ]; + + public function product() + { + return $this->belongsTo(Product::class); + } + + public function promotion_admin() + { + return $this->belongsTo(PromotionAdmin::class); + } + + public function promotion_user() + { + return $this->belongsTo(PromotionUser::class); + } + + public function promotion_user_product() + { + return $this->belongsTo(PromotionUserProduct::class); + } + + public function shopping_order() + { + return $this->belongsTo(ShoppingOrder::class); + } + + public function shopping_order_item() + { + return $this->belongsTo(ShoppingOrderItem::class); + } + + public function shopping_user() + { + return $this->belongsTo(ShoppingUser::class); + } +} diff --git a/app/Models/ShippingPrice.php b/app/Models/ShippingPrice.php index 0926e84..1c4548e 100644 --- a/app/Models/ShippingPrice.php +++ b/app/Models/ShippingPrice.php @@ -41,6 +41,8 @@ use Illuminate\Database\Eloquent\Model; * @property int|null $num_comp * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShippingPrice whereNumComp($value) * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShippingPrice wherePriceComp($value) + * @property int|null $shipping_for + * @method static \Illuminate\Database\Eloquent\Builder|ShippingPrice whereShippingFor($value) */ class ShippingPrice extends Model { diff --git a/app/Models/ShoppingOrder.php b/app/Models/ShoppingOrder.php index f6128b2..76116be 100644 --- a/app/Models/ShoppingOrder.php +++ b/app/Models/ShoppingOrder.php @@ -99,6 +99,11 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippedAt($value) * @property string|null $invoice_number * @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereInvoiceNumber($value) + * @property int|null $promotion_user_id + * @property string|null $shipping_option + * @property-read \App\Models\PromotionUser|null $promotion_user + * @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder wherePromotionUserId($value) + * @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereShippingOption($value) */ class ShoppingOrder extends Model { @@ -110,7 +115,9 @@ class ShoppingOrder extends Model protected $fillable = [ 'shopping_user_id', 'auth_user_id', + 'promotion_user_id', 'member_id', + 'payment_for', 'country_id', 'user_shop_id', 'total', @@ -135,6 +142,7 @@ class ShoppingOrder extends Model 'mode', 'shipped', 'shipped_at', + 'shipping_option', 'tracking' ]; @@ -152,6 +160,15 @@ class ShoppingOrder extends Model 10 => 'storniert' ]; + public static $paymentForTypes = [ + 0 => '', + 1 => 'wizzard', + 2 => 'user_order me', + 3 => 'user_order ot', + 4 => 'Promotion', + 10 => '' + ]; + public static $apiShippedTypes = [ 0 => 'open', //(Fullfilment durch Händler)', 1 => 'process', //(Fullfilment durch MIVITA: nicht Versand) @@ -183,6 +200,11 @@ class ShoppingOrder extends Model return $this->belongsTo('App\Models\ShippingCountry','country_id'); } + public function promotion_user() + { + return $this->belongsTo('App\Models\PromotionUser','promotion_user_id'); + } + //can null public function member() { diff --git a/app/Models/ShoppingOrderItem.php b/app/Models/ShoppingOrderItem.php index 2ab4689..ca7fd7f 100644 --- a/app/Models/ShoppingOrderItem.php +++ b/app/Models/ShoppingOrderItem.php @@ -45,6 +45,9 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property float|null $price_net * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrderItem whereComp($value) * @method static \Illuminate\Database\Eloquent\Builder|\App\Models\ShoppingOrderItem wherePriceNet($value) + * @property int|null $free_product_id + * @property-read \App\Models\PromotionUserProduct|null $promotion_user_product + * @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrderItem whereFreeProductId($value) */ class ShoppingOrderItem extends Model { @@ -58,6 +61,7 @@ class ShoppingOrderItem extends Model 'row_id', 'product_id', 'comp', + 'free_product_id', 'qty', 'price', 'price_net', @@ -97,4 +101,14 @@ class ShoppingOrderItem extends Model return formatNumber($this->attributes['price_net'] * $this->attributes['qty']); } + public function isFreeProduct() + { + return $this->free_product_id > 0 ? true : false; + } + + public function promotion_user_product() + { + return $this->belongsTo('App\Models\PromotionUserProduct','free_product_id'); + } + } \ No newline at end of file diff --git a/app/Models/ShoppingPayment.php b/app/Models/ShoppingPayment.php index d4f033a..7be293f 100644 --- a/app/Models/ShoppingPayment.php +++ b/app/Models/ShoppingPayment.php @@ -88,6 +88,9 @@ class ShoppingPayment extends Model if($this->clearingtype === 'fnc') { return 'Rechnung'; } + if($this->clearingtype === 'non') { + return 'keine'; + } } public function getPaymentAmount(){ diff --git a/app/Models/UserPayCredit.php b/app/Models/UserPayCredit.php index 7e1c5b9..7ba72c2 100644 --- a/app/Models/UserPayCredit.php +++ b/app/Models/UserPayCredit.php @@ -48,7 +48,8 @@ class UserPayCredit extends Model 2 => 'deduction from payment', 3 => 'manually added credit', 4 => 'return from order', - + 5 => 'deduction from promotion', + 6 => 'return from promotion', ]; protected $table = 'user_pay_credits'; diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 0c12570..8089d8f 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -72,7 +72,7 @@ class RouteServiceProvider extends ServiceProvider */ protected function mapApiRoutes() { - Route::domain('api.'.config('app.domain')) + Route::domain('api.'.config('app.api_domain')) ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); diff --git a/app/Repositories/CheckoutRepository.php b/app/Repositories/CheckoutRepository.php new file mode 100644 index 0000000..2273a37 --- /dev/null +++ b/app/Repositories/CheckoutRepository.php @@ -0,0 +1,226 @@ +session = app(SessionManager::class);; + $this->instance = sprintf('%s.%s', 'cart', 'payments'); + } + + public function setPromotion($payment_for, PromotionUser $PromotionUser) + { + $this->payment_for = $payment_for; + $this->PromotionUser = $PromotionUser; + } + + public function init($identifier, $data) + { + $this->identifier = $identifier; + $this->data = $data; + if($this->getPayments('identifier') !== $identifier){ + $this->destroy(); + $this->putPayments('identifier', $identifier); + } + + $shopping_data = Yard::instance('shopping')->getYardExtra('shopping_data'); + $this->data['is_from'] = isset($shopping_data['is_from']) ? $shopping_data['is_from'] : 'shopping'; //shopping + $this->data['is_from'] = isset($shopping_data['is_for']) ? $shopping_data['is_for'] : 'pr'; //promotion + + $this->shopping_user = $this->makeShoppingUser($data); + $this->shopping_order = $this->makeShoppingOrder($this->shopping_user); + + //CustomerPriority + if($this->shopping_user->is_from === 'shopping'){ + CustomerPriority::checkOne(ShoppingUser::find($this->shopping_user->id), true); + } + Util::setUserHistoryValue(['status'=>2, 'shopping_order_id'=>$this->shopping_order->id], $this->identifier); + + } + + public function makePayment() + { + //check credi t Card + if(!isset($this->data['payment_method'])){ + $this->data['payment_method'] = 'non'; + } + $ret = []; + //Rechnungskauf ohne PAYONE + if($this->data['payment_method'] === 'fnc#MIV'){ + + } + if($this->data['payment_method'] === 'pp'){ + + } + //other + $pay = new PayController(); + $pay->init($this->shopping_user, $this->shopping_order); + $amount = Yard::instance('shopping')->totalWithShipping(2, '.', '') * 100; + $reference = $pay->setPrePayment($this->data['payment_method'], $amount, 'EUR', $ret); + $this->putPayments('payment_reference', $reference); + $pay->setPersonalData(); + return $pay->ResponseData($this->identifier, $this->payment_for); + } + + + private function makeShoppingUser($data){ + $data['same_as_billing'] = isset($data['same_as_billing']) ? false : true; //reinvert + $data['accepted_data'] = isset($data['accepted_data']) ? true : false; + $data['billing_country_id'] = Shop::getShippingCountryCountryId($data['billing_state']); + $data['shipping_country_id'] = $data['billing_country_id']; + $data['member_id'] = $this->PromotionUser->user_id; + + if(isset($data['shipping_state'])){ + $data['shipping_country_id'] = Shop::getShippingCountryCountryId($data['shipping_state']); + } + $shopping_user = false; + if($this->getPayments('shopping_user_id')){ + $shopping_user = ShoppingUser::find($this->getPayments('shopping_user_id')); + if($shopping_user){ + $shopping_user->fill($data); + $shopping_user->mode = null; + $shopping_user->save(); + } + } + if(!$shopping_user){ + $shopping_user = ShoppingUser::create($data); + } + $this->putPayments('shopping_user_id', $shopping_user->id); + return $shopping_user; + } + + private function makeShoppingOrder($shopping_user){ + $data = [ + 'shopping_user_id' => $shopping_user->id, + 'auth_user_id' => $shopping_user->auth_user_id, + 'promotion_user_id' => $this->PromotionUser->id, + 'country_id' => Yard::instance('shopping')->getShippingCountryId(), + 'payment_for' => $this->payment_for, + 'total' => Yard::instance('shopping')->total(2, '.', ''), + 'subtotal_full' => Yard::instance('shopping')->subtotal(2, '.', '', false), + 'discount' => 0, + 'subtotal' => Yard::instance('shopping')->subtotal(2, '.', ''), + 'shipping' => Yard::instance('shopping')->shipping(2, '.', ','), + 'shipping_net' => Yard::instance('shopping')->shippingNet(2, '.', ''), + 'subtotal_shipping' => Yard::instance('shopping')->subtotalWithShipping(2, '.', ''), + 'tax' => Yard::instance('shopping')->taxWithShipping(2, '.', ''), + 'total_without_credit' => Yard::instance('shopping')->totalWithShippingWithoutCredit(2, '.', ''), + 'payment_credit' => Yard::instance('shopping')->totalfromCredit(2, '.', ''), + 'total_shipping' => Yard::instance('shopping')->totalWithShipping(2, '.', ''), + 'points' => Yard::instance('shopping')->points(), + 'weight' => Yard::instance('shopping')->weight(), + 'txaction' => 'prev', + 'shipping_option' => Yard::instance('shopping')->getShippingOption(), + 'mode' => Util::getUserShoppingMode(), + ]; + + $shopping_order= false; + if($this->getPayments('shopping_order_id')){ + $shopping_order = ShoppingOrder::find($this->getPayments('shopping_order_id')); + if($shopping_order){ + $shopping_order->fill($data); + $shopping_order->save(); + } + } + if(!$shopping_order){ + $shopping_order = ShoppingOrder::create($data); + } + //$this->makeOrderMargin($shopping_order); + + $this->putPayments('shopping_order_id', $shopping_order->id); + $items = Yard::instance('shopping')->getContentByOrder(); + $shopping_order->shopping_order_items()->each(function($model) use ($items, $shopping_order, $shopping_user) { + foreach ($items as $item) { + if ($model->row_id === $item->rowId) { + $data = [ + 'shopping_order_id' => $shopping_order->id, + 'row_id' => $item->rowId, + 'product_id' => $item->id, + 'free_product_id' => $item->options->free_product_id, //promotion_user_product_id + 'qty' => $item->qty, + 'price' => $item->price, + 'price_net' => Yard::instance('shopping')->rowPriceNet($item, 3, '.', ''), + 'tax_rate' => $item->taxRate, + 'slug' => $item->options->slug, + ]; + $model->fill($data)->save(); + return false; + } + } + return $model->delete(); + }); + + + foreach ($items as $item) { + if (!ShoppingOrderItem::where('shopping_order_id', $shopping_order->id)->where('row_id', $item->rowId)->count()){ + $data = [ + 'shopping_order_id' => $shopping_order->id, + 'row_id' => $item->rowId, + 'product_id' => $item->id, + 'free_product_id' => $item->options->free_product_id, //promotion_user_product_id + 'qty' => $item->qty, + 'price' => $item->price, + 'price_net' => Yard::instance('shopping')->rowPriceNet($item, 3, '.', ''), + 'tax_rate' => $item->taxRate, + 'slug' => $item->options->slug + ]; + $shopping_order_item = ShoppingOrderItem::create($data); + } + } + return $shopping_order; + } + + private function putPayments($key, $value){ + $content = $this->getContent(); + $content->put($key, $value); + $this->session->put($this->instance, $content); + + } + + private function getPayments($key){ + $content = $this->getContent(); + if ($content->has($key)){ + return $content->get($key); + } + return false; + } + + private function getContent() + { + if (is_null($this->session->get($this->instance))) { + return new Collection([]); + } + return $this->session->get($this->instance); + } + + public function destroy() + { + $this->session->remove($this->instance); + } +} \ No newline at end of file diff --git a/app/Services/CustomerPriority.php b/app/Services/CustomerPriority.php index 4522ca9..31a8765 100644 --- a/app/Services/CustomerPriority.php +++ b/app/Services/CustomerPriority.php @@ -29,10 +29,19 @@ class CustomerPriority return $shopping_users; } - public static function checkOne($shopping_user, $mail=false, $newCustomer = true){ - //look for entry - if(self::entryExists($shopping_user)){ - return 'exists'; + public static function checkOne($shopping_user, $mail=false, $newCustomer = true, $entryExistsLike = false){ + //look for entry + if($entryExistsLike){ + if(self::entryExistsLike($shopping_user)){ + if($mail){ //send mail + Mail::to(config('app.info_mail'))->send(new MailInfo($shopping_user, 'check_is_like_customer')); + } + return 'exists'; + } + }else{ + if(self::entryExists($shopping_user)){ + return 'exists'; + } } if(self::entryLike($shopping_user)){ if($mail){ //send mail @@ -122,6 +131,7 @@ class CustomerPriority ->where('number', '!=', NULL) //has number ->where('id', '!=', $shopping_user->id) ->where('billing_email', '=', $data['billing_email']) + ->where('member_id', '!=', $shopping_user->member_id) ->get()->pluck('number', 'id')->unique()->toArray(); if($found && count($found)){ foreach ($found as $key=>$val){ @@ -139,6 +149,7 @@ class CustomerPriority ->where('id', '!=', $shopping_user->id) ->where('billing_lastname', '=', $data['billing_lastname']) ->where('billing_zipcode', '=', $data['billing_zipcode']) + ->where('member_id', '!=', $shopping_user->member_id) ->get()->pluck('number', 'id')->unique()->toArray(); if($found && count($found)){ foreach ($found as $key=>$val){ @@ -193,11 +204,30 @@ class CustomerPriority $shopping_user->shopping_order->member_id = $match->member_id; $shopping_user->shopping_order->save(); } + \App\Services\Shop::newUserOrder($shopping_user->number); return true; } return false; } + private static function entryExistsLike($shopping_user) + { + $matches = ShoppingUser::where('auth_user_id', '=', NULL) + ->where('number', '!=', NULL) //has number + ->where('id', '!=', $shopping_user->id) + ->where('member_id', '!=', $shopping_user->member_id) + ->where('billing_email', '=', $shopping_user->billing_email) + ->get()->pluck('number', 'id')->unique()->toArray(); + + if($matches && count($matches)){ + $shopping_user->is_like = true; + $shopping_user->setNotice(self::$user_notice_key, $matches); + $shopping_user->save(); + return true; + } + return false; + } + private static function entryLike($shopping_user){ //check same last name und PLZ $matches = ShoppingUser::select('*') @@ -217,13 +247,16 @@ class CustomerPriority } private static function newCustomer($shopping_user){ - if($shopping_user->shopping_order && $shopping_user->shopping_order->member_id) { - $member_id = $shopping_user->shopping_order->member_id; + if($shopping_user->member_id) { + $member_id = $shopping_user->member_id; $shopping_user->member_id = $member_id; $shopping_user->number = self::nextNumber(); $shopping_user->save(); - $shopping_user->shopping_order->member_id = $member_id; - $shopping_user->shopping_order->save(); + if($shopping_user->shopping_order){ + $shopping_user->shopping_order->member_id = $member_id; + $shopping_user->shopping_order->save(); + } + \App\Services\Shop::newUserOrder($shopping_user->number); } } @@ -233,7 +266,6 @@ class CustomerPriority $shopping_user->number = self::nextNumber(); $shopping_user->save(); \App\Services\Shop::newUserOrder($shopping_user->number); - } private static function changeCustomer($shopping_user, $member_id, $number){ diff --git a/app/Services/Payment.php b/app/Services/Payment.php index 7364cb6..3f965f2 100644 --- a/app/Services/Payment.php +++ b/app/Services/Payment.php @@ -11,6 +11,7 @@ use App\Models\ShoppingOrder; use App\Models\UserPayCredit; use App\Models\ShoppingPayment; use App\Models\UserCreditMargin; +use App\Models\PromotionUserOrder; use Illuminate\Support\Facades\Mail; class Payment @@ -135,7 +136,7 @@ class Payment } } } - + /**/ public static function paymentStatusPaidAction(ShoppingOrder $shopping_order, $paid){ $send_link = false; @@ -197,7 +198,6 @@ class Payment } } - //if the order has action if($shopping_order->shopping_user->is_from === 'user_order'){ //is margin -> set paid @@ -209,10 +209,44 @@ class Payment return $send_link; } + public static function handelPromotionProduct(ShoppingOrder $shopping_order){ + //add the Promotion Product to Order + $shopping_order = ShoppingOrder::find($shopping_order->id); + foreach($shopping_order->shopping_order_items as $shopping_order_item){ + if($shopping_order_item->isFreeProduct()){ + if($promotion_user_product = $shopping_order_item->promotion_user_product){ + $promotion_admin_product = $promotion_user_product->promotion_admin_product; + $PromotionUserOrder = PromotionUserOrder::create([ + 'promotion_admin_id' => $promotion_user_product->promotion_admin_id, + 'promotion_user_id' => $shopping_order->promotion_user_id, + 'promotion_user_product_id' => $promotion_user_product->id, + 'product_id' => $promotion_user_product->product_id, + 'shopping_order_item_id' => $shopping_order_item->id, + 'shopping_order_id' => $shopping_order->id, + 'shopping_user_id' => $shopping_order->shopping_user_id, + 'qty' => $shopping_order_item->qty, + 'price' => $promotion_admin_product->getPriceWith(false), + 'price_net' => $promotion_admin_product->getPriceWith(true), + 'tax_rate' => $promotion_admin_product->product->tax, + ]); + + $promotion_user_product->open_items -= $PromotionUserOrder->qty; + $promotion_user_product->sell_items += $PromotionUserOrder->qty; + $promotion_user_product->used_budget_total += $PromotionUserOrder->price; + $promotion_user_product->save(); + + //TODO Guthaben abziehen + self::addUserPayCredits($promotion_user_product->promotion_user->user, ($PromotionUserOrder->price*-1), 5, 'promotion_order_deduction', $shopping_order->id); + } + } + } + } + + //remove form credit, every sale fnc / vor / etc from CheckoutController //when stone, put it back SalesController public static function handelUserPayCredits(ShoppingOrder $shopping_order, $do){ - //is payment credit, reduce Sae + //is payment credit, deduction or return if(!$shopping_order->shopping_order_margin){ return; } diff --git a/app/Services/PromotionCart.php b/app/Services/PromotionCart.php index 9317543..394b819 100644 --- a/app/Services/PromotionCart.php +++ b/app/Services/PromotionCart.php @@ -35,11 +35,19 @@ class PromotionCart } } - public static function clearCart($data, $add=false) + public static function clearCart($data) { Yard::instance('shopping')->destroy(); } - + + public static function switchShipping($data) + { + //pick_up//dhl_shipping + Yard::instance('shopping')->setShippingOption($data['shipping_option']); + Yard::instance('shopping')->reCalculateShippingPrice(); + + } + public static function updateProduct($data, $add=false) { if($product = Product::find($data['product_id'])){ @@ -77,13 +85,13 @@ class PromotionCart //wenn kleiner wurde ein produkt entfernt aufgrund der Anzahl //wenn gleich löschen, da neue Versandkosten - if($row->options->free_product) { + if($row->options->free_product_id) { Yard::instance('shopping')->remove($row->rowId); } } - if(isset($data['free_poduct_id'])) { - if ($product = Product::find($data['free_poduct_id'])) { + if(isset($data['free_product_id'])) { + if ($product = Product::find($data['product_id'])) { $image = ""; if ($product->images->count()) { $image = $product->images->first()->slug; @@ -92,8 +100,8 @@ class PromotionCart [ 'image' => $image, 'slug' => $product->slug, - 'weight' => 0, - 'free_product' => 1, + 'weight' => $product->weight, + 'free_product_id' => intval($data['free_product_id']), 'product_id' => $product->id ]); Yard::setTax($cartItem->rowId, 0); diff --git a/app/Services/Yard.php b/app/Services/Yard.php index 8524fe6..feeddab 100644 --- a/app/Services/Yard.php +++ b/app/Services/Yard.php @@ -44,6 +44,7 @@ class Yard extends Cart private $yard_margin; private $global_tax_rate = 0; + private $shipping_option; //pick_up//dhl_shipping public function __construct(SessionManager $session, Dispatcher $events) { @@ -53,42 +54,33 @@ class Yard extends Cart if($this->getYardExtra('shipping_price')){ $this->shipping_price = (float) ($this->getYardExtra('shipping_price')); } - if($this->getYardExtra('shipping_price_net')){ $this->shipping_price_net = (float) ($this->getYardExtra('shipping_price_net')); } - if($this->getYardExtra('shipping_tax_rate')){ $this->shipping_tax_rate = (float) ($this->getYardExtra('shipping_tax_rate')); } - if($this->getYardExtra('shipping_tax')){ $this->shipping_tax = (float) ($this->getYardExtra('shipping_tax')); } - if($this->getYardExtra('shipping_country_id')){ $this->shipping_country_id = $this->getYardExtra('shipping_country_id'); } - if($this->getYardExtra('shipping_is_for')){ $this->shipping_is_for = $this->getYardExtra('shipping_is_for'); } - if($this->getYardExtra('shopping_user')){ $this->user = $this->getYardExtra('shopping_user'); } - if($this->getYardExtra('user')){ $this->user = $this->getYardExtra('user'); } if($this->getYardExtra('payment_credit')){ $this->payment_credit = $this->getYardExtra('payment_credit'); } - if($this->getYardExtra('yard_commission')){ $this->yard_commission = $this->getYardExtra('yard_commission'); } - if($this->getYardExtra('yard_margin')){ $this->yard_margin = $this->getYardExtra('yard_margin'); } @@ -97,10 +89,12 @@ class Yard extends Cart }else{ $this->global_tax_rate = config('cart.tax'); } - if($this->getYardExtra('num_comp')){ $this->num_comp = $this->getYardExtra('num_comp'); } + if($this->getYardExtra('shipping_option')){ + $this->shipping_option = $this->getYardExtra('shipping_option'); + } parent::__construct($session, $events); @@ -123,10 +117,31 @@ class Yard extends Cart } public function setGlobalTaxRate($value){ - $this->global_tax_rate = floatval($value); $this->putYardExtra('global_tax_rate', $this->global_tax_rate); + } + public function setShippingOption($value){ + $this->shipping_option = $value; + $this->putYardExtra('shipping_option', $this->shipping_option); + } + + public function getShippingOption(){ + return $this->shipping_option; + } + + public function isQuickShipping(){ + if($this->shipping_option === 'pick_up' && $this->totalWithShipping(2, '.', '') == 0.00){ + return true; + } + return false; + } + + public function isWithPayments(){ + if($this->totalWithShipping(2, '.', '') == 0.00){ + return false; + } + return true; } public function putYardExtra($key, $value){ @@ -272,7 +287,6 @@ class Yard extends Cart } } - $margin->setCommission($this->yard_commission); $margin->calculate(); @@ -318,6 +332,15 @@ class Yard extends Cart private function calculateShippingPrice(){ + if($this->shipping_option && $this->shipping_option === 'pick_up'){ + $this->shipping_price = 0; + $this->shipping_tax_rate = 0; + $this->shipping_price_net = 0; + $this->shipping_tax = 0; + $this->putShippingPrices(); + return; + } + $shippingCountry = ShippingCountry::find($this->shipping_country_id); if(!$shippingCountry){ return; @@ -346,7 +369,6 @@ class Yard extends Cart } //default if(!$shipping_price){ - $shipping_price = $shipping->getShippingPricesBy($shipping_price_for)->first(); } } @@ -368,14 +390,18 @@ class Yard extends Cart $this->shipping_price_net = round($price / ((100+$shipping_price->tax_rate) / 100), 2); $this->shipping_tax = round($price / (100+$shipping_price->tax_rate) * 100, 2); - $this->putYardExtra('num_comp', $this->num_comp); - $this->putYardExtra('shipping_price', $this->shipping_price); - $this->putYardExtra('shipping_tax_rate', $this->shipping_tax_rate); - $this->putYardExtra('shipping_tax', $this->shipping_tax); - $this->putYardExtra('shipping_price_net', $this->shipping_price_net); + $this->putShippingPrices(); } } + private function putShippingPrices(){ + $this->putYardExtra('num_comp', $this->num_comp); + $this->putYardExtra('shipping_price', $this->shipping_price); + $this->putYardExtra('shipping_tax_rate', $this->shipping_tax_rate); + $this->putYardExtra('shipping_tax', $this->shipping_tax); + $this->putYardExtra('shipping_price_net', $this->shipping_price_net); + } + private function shippingPriceBySubTotal($prices, $total){ foreach ($prices as $price){ if($price->total_from > 0 && $price->total_to > 0){ @@ -386,6 +412,7 @@ class Yard extends Cart } return false; } + private function shippingPriceByWeight($prices, $weight){ foreach ($prices as $price){ if($price->weight_from > 0 && $price->weight_to > 0){ @@ -686,8 +713,8 @@ class Yard extends Cart public function getFreeProductId(){ foreach ($this->content() as $row) { - if($row->options->free_product) { - return $row->options->product_id; + if($row->options->free_product_id) { + return $row->options->free_product_id; } } return false; @@ -699,6 +726,8 @@ class Yard extends Cart foreach ($this->content() as $row) { if($row->options->comp){ $comp[100+$row->options->comp] = $row; + }elseif($row->options->free_product_id){ + $comp[200] = $row; }else{ $ret[] = $row; } diff --git a/config/app.php b/config/app.php index c2412c1..2054c5a 100644 --- a/config/app.php +++ b/config/app.php @@ -51,6 +51,7 @@ return [ | your application so that it is used when running Artisan tasks. | */ + 'api_domain' => env('APP_API_DOMAIN', 'gruene-seele.bio'), 'url' => env('APP_URL', 'https://partner.gruene-seele.bio'), 'domain' => env('APP_DOMAIN', 'partner.gruene-seele.bio'), diff --git a/config/paypal.php b/config/paypal.php new file mode 100644 index 0000000..372bf11 --- /dev/null +++ b/config/paypal.php @@ -0,0 +1,25 @@ +. + */ + +return [ + 'mode' => env('PAYPAL_MODE', 'sandbox'), // Can only be 'sandbox' Or 'live'. If empty or invalid, 'live' will be used. + 'sandbox' => [ + 'client_id' => env('PAYPAL_SANDBOX_CLIENT_ID', ''), + 'client_secret' => env('PAYPAL_SANDBOX_CLIENT_SECRET', ''), + 'app_id' => 'APP-80W284485P519543T', + ], + 'live' => [ + 'client_id' => env('PAYPAL_LIVE_CLIENT_ID', ''), + 'client_secret' => env('PAYPAL_LIVE_CLIENT_SECRET', ''), + 'app_id' => env('PAYPAL_LIVE_APP_ID', ''), + ], + + 'payment_action' => env('PAYPAL_PAYMENT_ACTION', 'Sale'), // Can only be 'Sale', 'Authorization' or 'Order' + 'currency' => env('PAYPAL_CURRENCY', 'EUR'), + 'notify_url' => env('PAYPAL_NOTIFY_URL', ''), // Change this accordingly for your application. + 'locale' => env('PAYPAL_LOCALE', 'de_DE'), // force gateway language i.e. it_IT, es_ES, en_US ... (for express checkout only) + 'validate_ssl' => env('PAYPAL_VALIDATE_SSL', true), // Validate SSL when creating api client. +]; diff --git a/database/migrations/2020_12_23_163527_create_shopping_orders_table.php b/database/migrations/2020_12_23_163527_create_shopping_orders_table.php index 70010fc..fd4ba5d 100644 --- a/database/migrations/2020_12_23_163527_create_shopping_orders_table.php +++ b/database/migrations/2020_12_23_163527_create_shopping_orders_table.php @@ -30,7 +30,6 @@ class CreateShoppingOrdersTable extends Migration $table->decimal('discount', 13, 2)->nullable(); $table->decimal('subtotal', 13, 2)->nullable(); - $table->decimal('shipping', 8, 2)->nullable(); $table->decimal('shipping_net', 8, 2)->nullable(); @@ -55,7 +54,8 @@ class CreateShoppingOrdersTable extends Migration $table->string('txaction', 20)->nullable()->index(); $table->unsignedTinyInteger('shipped')->default(0); $table->timestamp('shipped_at')->nullable(); - + $table->string('shipping_option', 20)->nullable()->index(); + $table->string('tracking', 255)->nullable(); $table->char('mode', 4)->nullable(); diff --git a/database/migrations/2020_12_23_163724_create_shopping_order_items_table.php b/database/migrations/2020_12_23_163724_create_shopping_order_items_table.php index c1f409c..5f937ca 100644 --- a/database/migrations/2020_12_23_163724_create_shopping_order_items_table.php +++ b/database/migrations/2020_12_23_163724_create_shopping_order_items_table.php @@ -21,12 +21,11 @@ class CreateShoppingOrderItemsTable extends Migration $table->unsignedInteger('product_id'); $table->unsignedTinyInteger('comp')->nullable(); - + $table->unsignedTinyInteger('free_product')->nullable(); $table->unsignedInteger('qty'); $table->decimal('price', 8, 2)->nullable(); $table->decimal('price_net', 8, 3)->nullable(); - $table->decimal('tax_rate', 5, 2)->nullable(); $table->string('slug')->nullable(); diff --git a/database/migrations/2021_10_11_135225_create_promotion_admins_table.php b/database/migrations/2021_10_11_135225_create_promotion_admins_table.php index f41ad72..63c3e2c 100644 --- a/database/migrations/2021_10_11_135225_create_promotion_admins_table.php +++ b/database/migrations/2021_10_11_135225_create_promotion_admins_table.php @@ -20,6 +20,8 @@ class CreatePromotionAdminsTable extends Migration $table->string('name', 255); $table->text('description')->nullable(); + $table->text('user_description')->nullable(); + $table->text('user_about')->nullable(); $table->date('from')->nullable(); $table->date('to')->nullable(); diff --git a/database/migrations/2021_10_11_135233_create_promotion_user_products_table.php b/database/migrations/2021_10_11_135233_create_promotion_user_products_table.php index 42a88a5..55ab4e6 100644 --- a/database/migrations/2021_10_11_135233_create_promotion_user_products_table.php +++ b/database/migrations/2021_10_11_135233_create_promotion_user_products_table.php @@ -14,6 +14,7 @@ class CreatePromotionUserProductsTable extends Migration public function up() { Schema::create('promotion_user_products', function (Blueprint $table) { + $table->increments('id'); $table->unsignedInteger('promotion_admin_id')->index(); diff --git a/database/migrations/2021_12_01_160513_create_promotion_user_orders_table.php b/database/migrations/2021_12_01_160513_create_promotion_user_orders_table.php new file mode 100644 index 0000000..179900a --- /dev/null +++ b/database/migrations/2021_12_01_160513_create_promotion_user_orders_table.php @@ -0,0 +1,76 @@ +increments('id'); + + $table->unsignedInteger('promotion_admin_id')->index(); + $table->unsignedInteger('promotion_user_id')->index(); + $table->unsignedInteger('promotion_user_product_id')->index(); + $table->unsignedInteger('product_id')->index(); + $table->unsignedInteger('shopping_order_item_id')->index(); + $table->unsignedInteger('shopping_order_id')->index(); + $table->unsignedInteger('shopping_user_id')->index(); + + $table->unsignedSmallInteger('qty')->nullable(); + $table->decimal('price', 8, 2)->nullable(); + $table->decimal('price_net', 8, 3)->nullable(); + $table->decimal('tax_rate', 5, 2)->nullable(); + + $table->unsignedTinyInteger('status')->index()->default(0); + + $table->foreign('promotion_admin_id') + ->references('id') + ->on('promotion_admins'); + + $table->foreign('promotion_user_id') + ->references('id') + ->on('promotion_users'); + + $table->foreign('promotion_user_product_id') + ->references('id') + ->on('promotion_user_products'); + + $table->foreign('product_id') + ->references('id') + ->on('products'); + + $table->foreign('shopping_order_item_id') + ->references('id') + ->on('shopping_order_items'); + + $table->foreign('shopping_order_id') + ->references('id') + ->on('shopping_orders'); + + $table->foreign('shopping_user_id') + ->references('id') + ->on('shopping_users'); + + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('promotion_user_orders'); + } +} diff --git a/public/css/shop.css b/public/css/shop.css index 09992a1..19383ee 100644 --- a/public/css/shop.css +++ b/public/css/shop.css @@ -251,7 +251,7 @@ label .required { transition: box-shadow 0.4s ease; position: relative; background-color: #fafafa; - padding: 30px 30px 40px; + padding: 30px 20px 40px; } .checkout-order:before { diff --git a/public/js/iq-promotion-cart.js b/public/js/iq-promotion-cart.js index 1c1b06a..d94f52a 100644 --- a/public/js/iq-promotion-cart.js +++ b/public/js/iq-promotion-cart.js @@ -77,7 +77,6 @@ var IqPromotionCart = { tempData.push({product_id: $(this).data('product-id'), qty: $(this).val()}); } }); - data.action = $(_self.table).data('action'); data.user_promotion_id = $(_self.table).data('user_promotion_id'); data.products = tempData; @@ -89,11 +88,15 @@ var IqPromotionCart = { update_poduct_price: function(){ console.log("s"); var _self = this; - - $('.calculate_product_qty_price').each(function(){ - var qty = _self.checkNumber($(_self.table).find('#'+$(this).data('qty-id')).val());; + + $('.calculate_product_qty_price_total').each(function(){ + var admin_product_id = $(this).data('admin_product_id'); var price = $(this).data('price'); - var total = price*qty; + var total = 0; + if($('#product_check_' + admin_product_id).is(':checked')){ + var qty = _self.checkNumber($(_self.table).find('#product_qty_' + admin_product_id).val());; + var total = price*qty; + } $(this).html(total.toFixed(2).replace('.', ',')) }); }, diff --git a/public/js/iq-promotion-shop-cart.js b/public/js/iq-promotion-shop-cart.js index 50da8e5..963e570 100644 --- a/public/js/iq-promotion-shop-cart.js +++ b/public/js/iq-promotion-shop-cart.js @@ -17,8 +17,10 @@ var IqPromotionShopCart = { url: null, action: null, cart_holder: '#promotion_cart_holder', + invoice_holder: '#invoice_details_holder', + checkout_holder: '#promotion_checkout_holder', - free_poduct_id: null, + free_product_id: null, shipping_option: null, @@ -77,9 +79,9 @@ var IqPromotionShopCart = { switchFreeProduct: function(_ele){ var _self = this; if(_ele.prop('checked')){ - if(_self.free_poduct_id != _ele.val()){ - _self.free_poduct_id = _ele.val(); - _self.performRequest({free_poduct_id: _self.free_poduct_id, action: 'switch-free-product'}) + if(_self.free_product_id != _ele.val()){ + _self.free_product_id = _ele.val(); + _self.performRequest({free_product_id: _self.free_product_id, product_id: _ele.data('product_id'), action: 'switch-free-product'}) .done(_self.refreshItemsAndView); } } @@ -119,12 +121,21 @@ var IqPromotionShopCart = { var qty = data.response.qty > 0 ? "x"+data.response.qty : 0; $('#badge_cart_indicator_'+data.response.product_id).html(qty); } - $(_self.cart_holder).html(data.html); + if(data.cart){ + $(_self.cart_holder).html(data.cart); + } + if(data.invoice){ + $(_self.invoice_holder).html(data.invoice); + } + if(data.checkout){ + $(_self.checkout_holder).html(data.checkout); + } _self.showInit(); }, performRequest : function(data) { var _self = this; var url = _self.url; + data.perform = true; _log(data); // _log(url); return $.ajax({ diff --git a/resources/lang/de/email.php b/resources/lang/de/email.php index 381f27a..15dbe5c 100644 --- a/resources/lang/de/email.php +++ b/resources/lang/de/email.php @@ -15,6 +15,7 @@ 'your_request_from' => 'Deine Anfrage von', 'checkout_subject' => 'Deine Bestellung', 'checkout_subject_paid' => 'Zahlungsbestätigung - Deine Bestellung', + 'checkout_subject_non_paid' => 'Bestätigung - Deine Bestellung', 'checkout_subject_extern' => 'Neue Bestellung', 'change_e_mail' => 'E-Mail Adresse ändern', 'salutation' => 'Hallo', @@ -66,6 +67,7 @@ 'checkout_mail_your_mail' => 'Deine E-Mai:', 'checkout_mail_invoice_addess' => 'Deine Rechnungsadresse:', 'checkout_mail_deliver_addess' => 'Deine Lieferadresse:', + 'checkout_mail_pickup_addess' => 'Ich hole die Ware persönlich ab:', 'checkout_mail_deliver_customer' => 'Lieferadresse des Kunden:', 'checkout_mail_order_for_me' => 'Beraterbestellung für Dich:', 'checkout_mail_order_for_ot' => 'Beraterbestellung für Deinen Kunden:', @@ -86,5 +88,6 @@ 'checkout_mail_bank_code' => 'Verwendungszweck', 'checkout_mail_pay_approved' => 'Deine Zahlung wurde genehmigt, eine Bestätigung der Zahlung wird automatisch erstellt.', 'checkout_mail_pay_invoice_open' => 'Deine Zahlung per Rechnung wurde genehmigt.', + 'checkout_mail_pay_non' => 'Deine Bestellung wurde ausgeführt.', 'checkout_mail_system_status' => 'SystemStatus:', ); \ No newline at end of file diff --git a/resources/lang/de/payment.php b/resources/lang/de/payment.php index 4120e51..1f7342d 100755 --- a/resources/lang/de/payment.php +++ b/resources/lang/de/payment.php @@ -23,4 +23,7 @@ return [ 'payment_for_account' => 'Aufladung durch Mitgliedschaft', 'user_order_deduction' => 'Abzug durch Bestellung', 'user_order_return' => 'Rückführung durch Storno', + 'promotion_order_deduction' => 'Abzug durch Promotion Produkt', + 'promotion_order_return' => 'Rückführung durch Promotion Produkt', + ]; \ No newline at end of file diff --git a/resources/views/admin/modal/is_like_member.blade.php b/resources/views/admin/modal/is_like_member.blade.php index 79c5ee8..b03beb8 100644 --- a/resources/views/admin/modal/is_like_member.blade.php +++ b/resources/views/admin/modal/is_like_member.blade.php @@ -75,6 +75,8 @@

#{{$current->member->number}}
{{$current->member->getFullName()}}
+ @if(isset($current->member->account->zipcode)){{$current->member->account->zipcode}} @endif + @if(isset($current->member->account->city)){{$current->member->account->city}} @endif
{{$current->member->account->zipcode}} {{$current->member->account->city}}
@if($current->member->shop) @if($current->member->isActive() && $current->member->isActiveShop()) diff --git a/resources/views/admin/promotion/form.blade.php b/resources/views/admin/promotion/form.blade.php index f138d91..f86cea1 100644 --- a/resources/views/admin/promotion/form.blade.php +++ b/resources/views/admin/promotion/form.blade.php @@ -34,17 +34,28 @@

- {{ Form::textarea('description', $promotion->description , array('placeholder'=>__('Interne Notiz'), 'class'=>'form-control', 'rows'=>2, 'id'=>'description')) }} + {{ Form::textarea('description', $promotion->description , array('placeholder'=>__('Interne Notiz'), 'class' => 'form-control text-autosize', 'rows' => 1, 'id'=>'description')) }}
- +
+ + {{ Form::textarea('user_description', $promotion->user_description , array('placeholder'=>__('Kurzbeschreibung'), 'class' => 'form-control bootstrap-maxlength text-autosize', 'maxlength'=>600, 'rows' => 1, 'id'=>'description')) }} +
+
+ +
+
+ + {{ Form::textarea('user_about', $promotion->user_about , array('placeholder'=>__('Text über Dich'), 'class' => 'form-control bootstrap-maxlength text-autosize', 'maxlength'=>600, 'rows' => 1, 'id'=>'description')) }} +
+
+
{{ Form::text('max_bugdet', $promotion->getFormattedMaxBugdet(), array('placeholder'=>__('Budget in Euro / Brutto'), 'class'=>'form-control', 'id'=>'max_bugdet')) }}
-
{{ Form::text('max_items', $promotion->max_items, array('placeholder'=>__('Einheiten in Stück'), 'class'=>'form-control', 'id'=>'max_items')) }} diff --git a/resources/views/admin/sales/_detail.blade.php b/resources/views/admin/sales/_detail.blade.php index 3fc0416..fdcf317 100644 --- a/resources/views/admin/sales/_detail.blade.php +++ b/resources/views/admin/sales/_detail.blade.php @@ -300,7 +300,14 @@ Vertriebspartnerbestellung für Mitgliedschaft @endif @if($shopping_order->shopping_user->is_from === 'shopping') - Kundenbestellung über Shop + @if($shopping_order->payment_for === 4) + Kundenbestellung über Promotion + @if($shopping_order->promotion_user) +
{{ $shopping_order->promotion_user->name }} || {{ $shopping_order->promotion_user->user->getFullName() }} + @endif + @else + Kundenbestellung über Shop + @endif @endif @if($shopping_order->shopping_user->is_from === 'homeparty')
Vertriebspartnerbestellung für eine Homeparty
@@ -319,7 +326,6 @@ } -
@@ -352,7 +358,10 @@ Inhalt: {{ $shopping_order_item->product->contents }}
Gewicht: {{ $shopping_order_item->product->weight }} g
- {{-- Points: {{ $shopping_order_item->product->points }} --}} + @if($shopping_order_item->isFreeProduct()) + Promotionprodukt
+ @endif + {{-- Points: {{ $shopping_order_item->product->points }} --}}
@endif @@ -379,7 +388,6 @@ @endforeach -