- -
- @if(Yard::instance('shopping')->getUserTaxFree()) -
- - {{ Yard::instance('shopping')->totalWithShipping() }} € - Gesamtsumme: - - zur Kasse -
-
Sie werden auf unseren checkout Server weitergeletet, die Verbindung ist mit SSL verschlüsselt.
-diff --git a/.env.dhl.example b/.env.dhl.example new file mode 100644 index 00000000..67d49c93 --- /dev/null +++ b/.env.dhl.example @@ -0,0 +1,74 @@ +# ============================================================================= +# DHL VERSANDMODUL KONFIGURATION - BEISPIEL +# ============================================================================= +# Diese Datei enthält alle DHL-spezifischen Environment-Variablen +# Kopieren Sie die benötigten Variablen in Ihre .env Datei + +# DHL API Zugangsdaten +# Option 1: DHL Developer API (developer.dhl.com) - Empfohlen +DHL_API_KEY=your_api_key_from_developer_dhl_com +DHL_API_SECRET=your_api_secret_from_developer_dhl_com + +# Option 2: DHL Business Customer API (Klassisch) +DHL_API_USERNAME=your_dhl_username +DHL_API_PASSWORD=your_dhl_password +DHL_ACCOUNT_NUMBER=your_14_digit_account_number + +# API-Konfiguration +DHL_SANDBOX=true # false für Produktion +DHL_TEST_MODE=true # false für Produktion +DHL_API_TYPE=developer # 'developer' oder 'business_customer' + +# Absenderadresse (Ihre Firmenadresse) +DHL_SENDER_COMPANY="Ihr Firmenname" +DHL_SENDER_NAME="Versandabteilung" +DHL_SENDER_STREET="Ihre Straße" +DHL_SENDER_STREET_NUMBER=123 +DHL_SENDER_POSTAL_CODE=12345 +DHL_SENDER_CITY="Ihre Stadt" +DHL_SENDER_STATE= +DHL_SENDER_COUNTRY=DE +DHL_SENDER_EMAIL=versand@ihrefirma.de +DHL_SENDER_PHONE="+49 123 456789" + +# Standard-Einstellungen +DHL_DEFAULT_PRODUCT=V01PAK # V01PAK = DHL Paket +DHL_LABEL_FORMAT=PDF # PDF oder ZPL +DHL_LABEL_SIZE=A4 # A4 oder 10x15cm +DHL_LABEL_STORAGE_PATH=storage/app/dhl/labels +DHL_LABEL_PUBLIC_PATH=dhl/labels + +# Retouren +DHL_RETURNS_ENABLED=true +DHL_RETURN_PRODUCT=V07PAK # V07PAK = DHL Paket Return +DHL_RETURN_RECEIVER_ID=your_return_receiver_id + +# Tracking +DHL_TRACKING_ENABLED=true +DHL_TRACKING_AUTO_UPDATE=true +DHL_TRACKING_UPDATE_INTERVAL=60 # Minuten + +# Logging +DHL_LOGGING_ENABLED=true +DHL_LOGGING_LEVEL=info # debug, info, warning, error +DHL_LOG_REQUESTS=true +DHL_LOG_RESPONSES=true + +# Queue (verwende bestehende Queue-Konfiguration) +DHL_QUEUE_CONNECTION=database +DHL_QUEUE_NAME=dhl +DHL_QUEUE_TIMEOUT=60 +DHL_QUEUE_MAX_TRIES=3 + +# Fehlerbehandlung +DHL_THROW_EXCEPTIONS=true +DHL_ERROR_NOTIFICATION_EMAIL=admin@ihrefirma.de + +# Cache +DHL_CACHE_ENABLED=true +DHL_CACHE_TTL=3600 # Sekunden + +# Entwicklung/Testing +DHL_FAKE_API_CALLS=false # true um API-Calls zu simulieren +DHL_MOCK_RESPONSES=false # true um Mock-Responses zu verwenden +DHL_DEBUG_MODE=false # true für detaillierte Debug-Informationen \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..67d49c93 --- /dev/null +++ b/.env.example @@ -0,0 +1,74 @@ +# ============================================================================= +# DHL VERSANDMODUL KONFIGURATION - BEISPIEL +# ============================================================================= +# Diese Datei enthält alle DHL-spezifischen Environment-Variablen +# Kopieren Sie die benötigten Variablen in Ihre .env Datei + +# DHL API Zugangsdaten +# Option 1: DHL Developer API (developer.dhl.com) - Empfohlen +DHL_API_KEY=your_api_key_from_developer_dhl_com +DHL_API_SECRET=your_api_secret_from_developer_dhl_com + +# Option 2: DHL Business Customer API (Klassisch) +DHL_API_USERNAME=your_dhl_username +DHL_API_PASSWORD=your_dhl_password +DHL_ACCOUNT_NUMBER=your_14_digit_account_number + +# API-Konfiguration +DHL_SANDBOX=true # false für Produktion +DHL_TEST_MODE=true # false für Produktion +DHL_API_TYPE=developer # 'developer' oder 'business_customer' + +# Absenderadresse (Ihre Firmenadresse) +DHL_SENDER_COMPANY="Ihr Firmenname" +DHL_SENDER_NAME="Versandabteilung" +DHL_SENDER_STREET="Ihre Straße" +DHL_SENDER_STREET_NUMBER=123 +DHL_SENDER_POSTAL_CODE=12345 +DHL_SENDER_CITY="Ihre Stadt" +DHL_SENDER_STATE= +DHL_SENDER_COUNTRY=DE +DHL_SENDER_EMAIL=versand@ihrefirma.de +DHL_SENDER_PHONE="+49 123 456789" + +# Standard-Einstellungen +DHL_DEFAULT_PRODUCT=V01PAK # V01PAK = DHL Paket +DHL_LABEL_FORMAT=PDF # PDF oder ZPL +DHL_LABEL_SIZE=A4 # A4 oder 10x15cm +DHL_LABEL_STORAGE_PATH=storage/app/dhl/labels +DHL_LABEL_PUBLIC_PATH=dhl/labels + +# Retouren +DHL_RETURNS_ENABLED=true +DHL_RETURN_PRODUCT=V07PAK # V07PAK = DHL Paket Return +DHL_RETURN_RECEIVER_ID=your_return_receiver_id + +# Tracking +DHL_TRACKING_ENABLED=true +DHL_TRACKING_AUTO_UPDATE=true +DHL_TRACKING_UPDATE_INTERVAL=60 # Minuten + +# Logging +DHL_LOGGING_ENABLED=true +DHL_LOGGING_LEVEL=info # debug, info, warning, error +DHL_LOG_REQUESTS=true +DHL_LOG_RESPONSES=true + +# Queue (verwende bestehende Queue-Konfiguration) +DHL_QUEUE_CONNECTION=database +DHL_QUEUE_NAME=dhl +DHL_QUEUE_TIMEOUT=60 +DHL_QUEUE_MAX_TRIES=3 + +# Fehlerbehandlung +DHL_THROW_EXCEPTIONS=true +DHL_ERROR_NOTIFICATION_EMAIL=admin@ihrefirma.de + +# Cache +DHL_CACHE_ENABLED=true +DHL_CACHE_TTL=3600 # Sekunden + +# Entwicklung/Testing +DHL_FAKE_API_CALLS=false # true um API-Calls zu simulieren +DHL_MOCK_RESPONSES=false # true um Mock-Responses zu verwenden +DHL_DEBUG_MODE=false # true für detaillierte Debug-Informationen \ No newline at end of file diff --git a/app/Console/Commands/CheckPaymentsAccount.php b/app/Console/Commands/CheckPaymentsAccount.php index 64ed689a..ebe38672 100644 --- a/app/Console/Commands/CheckPaymentsAccount.php +++ b/app/Console/Commands/CheckPaymentsAccount.php @@ -38,23 +38,23 @@ class CheckPaymentsAccount extends Command $this->info('COMMAND [payments:check-accounts] started.'); // Die Logik wurde 1:1 aus der checkPaymentsAccounts-Methode übernommen - $renewalDate = Carbon::now()->modify('+'.(config('mivita.remind_first_days')+1).' days'); + $renewalDate = Carbon::now()->modify('+' . (config('mivita.remind_first_days') + 1) . ' days'); Log::channel('cron')->info('Erneuerungsdatum für Zahlungen: ' . $renewalDate->format('Y-m-d H:i:s')); - + $users = User::where('payment_account', '!=', NULL) - ->where('active', '=', 1) - ->where('blocked', '!=', 1) - ->where('payment_account', '<', $renewalDate) - ->get(); + ->where('active', '=', 1) + ->where('blocked', '!=', 1) + ->where('payment_account', '<', $renewalDate) + ->get(); Log::channel('cron')->info('Found ' . $users->count() . ' users for payment reminders.'); $this->info('Found ' . $users->count() . ' users for payment reminders.'); - foreach ($users as $user){ - Log::channel('cron')->info('Prüfe Zahlungserinnerungen für Benutzer: ' . $user->email); - $this->checkReminderPayments($user); + foreach ($users as $user) { + Log::channel('cron')->info('Prüfe Zahlungserinnerungen für Benutzer: ' . $user->email); + $this->checkReminderPayments($user); } - + Log::channel('cron')->info('COMMAND [payments:check-accounts] finished.'); $this->info('COMMAND [payments:check-accounts] finished.'); return 0; // Success @@ -79,28 +79,28 @@ class CheckPaymentsAccount extends Command private function checkReminderPayments(User $user) { //35 reminder_deaktiv, 36 reminder_deaktiv_sepa - if(!$user->isActiveAccount()){ + if (!$user->isActiveAccount()) { Log::channel('cron')->info('Inaktives Konto für Benutzer: ' . $user->email); $this->checkIsReminderSend($user, 35); return; } //34 reminder_last - if($user->daysActiveAccount() <= config('mivita.remind_last_days')){ + if ($user->daysActiveAccount() <= config('mivita.remind_last_days')) { Log::channel('cron')->info('Letzte Erinnerung für Benutzer: ' . $user->email . ' (Tage aktiv: ' . $user->daysActiveAccount() . ')'); $this->checkIsReminderSend($user, 34); return; } //33 reminder_sec - if($user->daysActiveAccount() <= config('mivita.remind_sec_days')){ + if ($user->daysActiveAccount() <= config('mivita.remind_sec_days')) { Log::channel('cron')->info('Zweite Erinnerung für Benutzer: ' . $user->email . ' (Tage aktiv: ' . $user->daysActiveAccount() . ')'); $this->checkIsReminderSend($user, 33); return; } //31 reminder_first - if($user->daysActiveAccount() > config('mivita.remind_sec_days')){ + if ($user->daysActiveAccount() > config('mivita.remind_sec_days')) { Log::channel('cron')->info('Erste Erinnerung für Benutzer: ' . $user->email . ' (Tage aktiv: ' . $user->daysActiveAccount() . ')'); $this->checkIsReminderSend($user, 31); return; @@ -117,28 +117,28 @@ class CheckPaymentsAccount extends Command private function checkIsReminderSend(User $user, $status) { $isSend = UserHistory::whereUserId($user->id) - ->whereAction('reminder_payments') - ->whereIdentifier($user->payment_account) - ->whereStatus($status) - ->latest() - ->first(); + ->whereAction('reminder_payments') + ->whereIdentifier($user->payment_account) + ->whereStatus($status) + ->latest() + ->first(); - if($isSend){ + if ($isSend) { Log::channel('cron')->info('Erinnerung bereits gesendet für Benutzer: ' . $user->email . ' (Status: ' . $status . ')'); return true; } - + Log::channel('cron')->info('Sende neue Erinnerung für Benutzer: ' . $user->email . ' (Status: ' . $status . ')'); $referenz = $this->sendReminderMail($user, $status); - + UserHistory::create([ - 'user_id' => $user->id, - 'action' => 'reminder_payments', - 'referenz' => $referenz, - 'identifier' => $user->payment_account, + 'user_id' => $user->id, + 'action' => 'reminder_payments', + 'referenz' => $referenz, + 'identifier' => $user->payment_account, 'status' => $status ]); - + return false; } @@ -155,8 +155,8 @@ class CheckPaymentsAccount extends Command $pay_date = Carbon::parse($user->payment_account)->modify('- ' . config('mivita.abo_booking_days') . ' days')->format('d.m.Y'); $datetime = $user->getPaymentAccountDateFormat(); $price = ""; - - if($user->payment_order_id && isset($user->payment_order_product->price)){ + + if ($user->payment_order_id && isset($user->payment_order_product->price)) { $price = 'von ' . $user->payment_order_product->getFormattedPrice() . ' EUR'; } @@ -171,16 +171,16 @@ class CheckPaymentsAccount extends Command 'subject' => __('reminder.subject') . " | ID: " . $status, 'message' => $message, 'message_last' => $message_last, - 'url' => route('user_membership'), + 'url' => config('app.url') . '/user/membership', 'button' => $button, ]; - + $sender = User::find(1); $customer_mail = UserMessage::create(['user_id' => $user->id, 'send_user_id' => $sender->id, 'email' => $user->email, 'subject' => $data['subject'], 'message' => $data['message'] . " " . $data['message_last']]); - + try { - if(!Util::isTestSystem()){ - if($status >= 34){ + if (!Util::isTestSystem()) { + if ($status >= 34) { Log::channel('cron')->info('Sende kritische Erinnerung mit BCC an: ' . $user->email); Mail::to($user->email) ->locale($user->getLocale()) @@ -195,19 +195,19 @@ class CheckPaymentsAccount extends Command } else { Log::channel('cron')->info('Testsystem: E-Mail-Versand simuliert für: ' . $user->email); } - } catch(\Exception $e) { + } catch (\Exception $e) { Log::channel('cron')->error('Mail-Fehler für Benutzer ' . $user->email . ': ' . $e->getMessage()); $customer_mail->fail = true; $customer_mail->error = $e->getMessage(); $customer_mail->save(); return 0; } - + $customer_mail->send = true; $customer_mail->sent_at = now(); $customer_mail->save(); - + Log::channel('cron')->info('Erinnerungsmail erfolgreich gesendet an: ' . $user->email); return 1; } -} \ No newline at end of file +} diff --git a/app/Http/Controllers/Web/CheckoutController.php b/app/Http/Controllers/Web/CheckoutController.php index 92df33ed..10343b28 100755 --- a/app/Http/Controllers/Web/CheckoutController.php +++ b/app/Http/Controllers/Web/CheckoutController.php @@ -25,7 +25,7 @@ class CheckoutController extends Controller { private $checkoutRepo; private $instance = 'checkout'; - + /** * Create a new controller instance. * @@ -50,7 +50,7 @@ class CheckoutController extends Controller {{ __('website.to_customer_portal') }} @endif @if(Auth::guard('user')->check()) - */ + */ $shopping_data = Yard::instance($this->instance)->getYardExtra('shopping_data'); $is_from = $shopping_data['is_from'] ?? 'shopping'; $is_for = $shopping_data['is_for'] ?? false; @@ -70,14 +70,17 @@ class CheckoutController extends Controller } } if (Session::has('new_session')) { - $this->checkoutRepo->sessionDestroy(); + $this->checkoutRepo->sessionDestroy(); Session::forget('new_session'); - } + } $shopping_user = $this->initializeShoppingUserSession($is_from, $is_for, $shopping_data, $homeparty_id); - + $this->prepareShoppingUserData($shopping_user); $payment_methods = $this->checkoutRepo->getPaymentsMethods($is_from, $is_abo); - + + if ($shopping_user === null) { + abort(403, 'ShoppingUser not found'); + } $data = [ 'is_from' => $is_from, 'is_for' => $is_for, @@ -97,8 +100,8 @@ class CheckoutController extends Controller return view('web.templates.checkout', $data); } - - + + /** * Bereitet die ShoppingUser-Daten vor * @@ -142,7 +145,7 @@ class CheckoutController extends Controller if (isset($data['payment_method'])) { $this->checkoutRepo->isPaymentsMethodsActive($data['payment_method'], $data['is_from'], $data['is_abo']); } - + Util::setInstanceStatus(2, true); // link_check // Länderwechsel verarbeiten @@ -155,16 +158,16 @@ class CheckoutController extends Controller if ($validator->fails()) { return back()->withErrors($validator)->withInput(Request::all()); } - + // Benutzer und Bestellung erstellen $shopping_user = $this->checkoutRepo->makeShoppingUser($data); $shopping_order = $this->checkoutRepo->makeShoppingOrder($shopping_user, $data); - + // CustomerPriority prüfen if ($shopping_user->is_from === 'shopping') { CustomerPriority::checkOne(ShoppingUser::find($shopping_user->id), true); } - + Util::setUserHistoryValue(['status' => 2, 'shopping_order_id' => $shopping_order->id]); // Zahlungsmethode verarbeiten @@ -188,7 +191,7 @@ class CheckoutController extends Controller } else { Yard::instance($this->instance)->setShippingCountryWithPrice($data['shipping_state'], $data['is_for']); } - + return back()->withInput(Request::all()); } @@ -220,7 +223,7 @@ class CheckoutController extends Controller 'shipping_salutation' => 'required' ]); } - + return Validator::make(Request::all(), $rules); } @@ -236,7 +239,7 @@ class CheckoutController extends Controller { $result = []; $payment_method = Request::get('payment_method'); - + // Kreditkarte prüfen if ($payment_method === 'cc') { $result = $this->checkCreditCard($data, $shopping_user, $shopping_order); @@ -260,7 +263,7 @@ class CheckoutController extends Controller $reference = $pay->setPrePayment($payment_method, $amount, 'EUR', $result); $this->checkoutRepo->putSessionPayments('payment_reference', $reference); $pay->setPersonalData(); - + return $pay->ResponseData(); } @@ -277,7 +280,7 @@ class CheckoutController extends Controller $pay = new PayoneController(); $pay->init($shopping_user, $shopping_order); $ret['cc'] = $pay->checkCreditCard($data); - + if ($ret['cc']['status'] === 'ERROR' || $ret['cc']['status'] === 'INVALID') { Session::flash('cc-error', 1); Session::flash('errormessage', $ret['cc']['errormessage']); @@ -303,14 +306,14 @@ class CheckoutController extends Controller $pay->init($shopping_user, $shopping_order); $amount = Yard::instance($this->instance)->totalWithShipping(2, '.', '') * 100; $ret['elv'] = $pay->checkBankAccount($data, $amount, 'EUR', $shopping_user); - + if ($ret['elv']['status'] === 'ERROR' || $ret['elv']['status'] === 'INVALID') { Session::flash('elv-error', 1); Session::flash('errormessage', $ret['elv']['errormessage']); Session::flash('customermessage', $ret['elv']['customermessage']); return redirect(route('checkout.checkout_card'))->withInput(Request::all()); } - + if ($ret['elv']['status'] === 'APPROVED' && $ret['elv']['mandate_status'] !== "active") { Session::flash('elv-managemandate', 1); Session::flash('elv-mandate_identification', $ret['elv']['mandate_identification']); @@ -318,7 +321,7 @@ class CheckoutController extends Controller Session::flash('elv-creditor_identifier', $ret['elv']['creditor_identifier']); return redirect(route('checkout.checkout_card'))->withInput(Request::all()); } - + $ret['elv']['bankaccountholder'] = $data['elv_bankaccountholder']; } else { $ret['elv'] = [ @@ -328,7 +331,7 @@ class CheckoutController extends Controller 'bic' => $data['elv_bic'], 'bankaccountholder' => $data['elv_bankaccountholder'] ]; - + $this->storeUserPaymentsData($shopping_user, $ret); } $ret['returnstatus'] = 'VALID'; @@ -347,7 +350,7 @@ class CheckoutController extends Controller 'is_checkout' => true, 'yard_instance' => $this->instance, ]; - + return view('web.templates.checkout-is-final', $data); } @@ -364,13 +367,13 @@ class CheckoutController extends Controller $ShoppingPayment = ShoppingPayment::where('shopping_order_id', $shopping_order_id) ->where('reference', $reference) ->first(); - + if (!$ShoppingPayment) { Util::setUserHistoryValue(['status' => 21]); Session::flash('checkout-error', 'Der Zahlungsvorgang konnte nicht abgeschlossen werden, die Zahlung wurde nicht gefunden: ' . $reference); return redirect(route('checkout.checkout_card')); } - + $ShoppingPayment->status = $status; $ShoppingPayment->save(); @@ -384,7 +387,7 @@ class CheckoutController extends Controller Session::flash('checkout-error', 'Der Zahlungsvorgang wurde abgebrochen, die Bestellung konnte nicht ausgeführt werden.'); return redirect(route('checkout.checkout_card')); } - + if ($status === "error") { Util::setUserHistoryValue(['status' => 23]); Util::setInstanceStatus(6); // link_failed @@ -419,7 +422,7 @@ class CheckoutController extends Controller 'is_checkout' => true, 'yard_instance' => $this->instance, ]; - + return view('web.templates.checkout-final', $data); } @@ -457,7 +460,7 @@ class CheckoutController extends Controller 'is_checkout' => true, 'yard_instance' => $this->instance, ]; - + return view('web.templates.checkout-final', $data); } @@ -493,20 +496,20 @@ class CheckoutController extends Controller $shopping_order = ShoppingOrder::find($payt->transmitted_data['param']); $shopping_order->txaction = 'invoice_open'; $shopping_order->save(); - + $shopping_payment = ShoppingPayment::where('reference', $payt->transmitted_data['reference'])->first(); if ($shopping_payment) { $shopping_payment->txaction = 'invoice_open'; $shopping_payment->save(); } - + $send_link = Payment::paymentStatusPaidAction($shopping_order, false, $shopping_payment); $data = [ 'mode' => $payt->transmitted_data['mode'], 'txaction' => $payt->txaction, 'send_link' => $send_link, ]; - + Payment::paymentStatusSendMail($shopping_order, $shopping_payment, $data); } } @@ -539,7 +542,7 @@ class CheckoutController extends Controller //Bestelllink if ($is_for === 'ot-customer' || $is_for === 'abo-ot-customer') { //customer shop mit den Daten aus dem Salescenter shopping_data - return $this->checkoutRepo->makeCustomerShoppingUser($shopping_data, $is_for, $is_from); + return $this->checkoutRepo->makeCustomerShoppingUser($shopping_data, $is_for, $is_from); } //Webshop return $this->checkoutRepo->initShoppingUser($is_for, $is_from, $homeparty_id); @@ -548,7 +551,7 @@ class CheckoutController extends Controller return $this->getExistingShoppingUser(); } - /** + /** * Holt den existierenden ShoppingUser und bereitet ihn vor * * @return ShoppingUser @@ -559,8 +562,7 @@ 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 - + return $shopping_user; } - -} \ No newline at end of file +} diff --git a/app/Mail/MailAutoReleaseAccount.php b/app/Mail/MailAutoReleaseAccount.php index 03ae254d..472de5df 100644 --- a/app/Mail/MailAutoReleaseAccount.php +++ b/app/Mail/MailAutoReleaseAccount.php @@ -1,4 +1,5 @@ user->account->salutation))." "; - $content .= $this->user->account->first_name." ".$this->user->account->last_name."\n"; - $content .= $this->user->account->address."\n"; - $content .= $this->user->account->zipcode." ".$this->user->account->city."\n"; - $content .= $this->user->account->country_id ? $this->user->account->country->de."\n\n" : "\n\n"; - if($this->user->account->phone){ + $content = __(strtoupper($this->user->account->salutation)) . " "; + $content .= $this->user->account->first_name . " " . $this->user->account->last_name . "\n"; + $content .= $this->user->account->address . "\n"; + $content .= $this->user->account->zipcode . " " . $this->user->account->city . "\n"; + $content .= $this->user->account->country_id ? $this->user->account->country->de . "\n\n" : "\n\n"; + if ($this->user->account->phone) { $content .= "Telefon: "; - $content .= $this->user->account->pre_phone_id ? $this->user->account->pre_phone->phone." " : " "; + $content .= $this->user->account->pre_phone_id ? $this->user->account->pre_phone->phone . " " : " "; $content .= $this->user->account->phone; } - if($this->user->account->mobil){ + if ($this->user->account->mobil) { $content .= "Mobil: "; - $content .= $this->user->account->pre_mobil_id ? $this->user->account->pre_mobil->phone." " : " "; + $content .= $this->user->account->pre_mobil_id ? $this->user->account->pre_mobil->phone . " " : " "; $content .= $this->user->account->mobil; } - $content .= "E-Mail: ".$this->user->email; + $content .= "E-Mail: " . $this->user->email; - $copy1line = "Ein neuer Berater hat sich registriert und wurde automatisch freigeschaltet. Seine Daten müssen nachträglich Überprüfung werden:"."\n"; - $copy1line .= "+ Überprüfung der Ausweisdaten"."\n"; - $copy1line .= "+ Überprüfung des Gewerbenachweises"."\n"; - $copy1line .= "+ Eintrag Account ID"."\n"; - $copy1line .= "+ Überprüfung / Kenntnisnahme Sponsor"."\n"; - $copy1line .= "+ Überprüfung der Rechnungsdaten"."\n"; - $copy1line .= 'Sollte Daten nicht vollständig sein, bitte Kontakt zum Berater aufnehmen.'."\n"; + $copy1line = "Ein neuer Berater hat sich registriert und wurde automatisch freigeschaltet. Seine Daten müssen nachträglich Überprüfung werden:" . "\n"; + $copy1line .= "+ Überprüfung der Ausweisdaten" . "\n"; + $copy1line .= "+ Überprüfung des Gewerbenachweises" . "\n"; + $copy1line .= "+ Eintrag Account ID" . "\n"; + $copy1line .= "+ Überprüfung / Kenntnisnahme Sponsor" . "\n"; + $copy1line .= "+ Überprüfung der Rechnungsdaten" . "\n"; + $copy1line .= 'Sollte Daten nicht vollständig sein, bitte Kontakt zum Berater aufnehmen.' . "\n"; return $this->view('emails.info')->with([ - 'url' => config('app.url_crm') . '/admin/lead/edit/' . $this->user->id . '?show=check_lead', + 'url' => \App\Services\Util::getMyMivitaUrl() . '/admin/lead/edit/' . $this->user->id . '?show=check_lead', 'title' => 'Berater Registrierung prüfen', 'button' => 'zur Berater Prüfung', 'copy1line' => $copy1line, @@ -59,4 +60,4 @@ class MailAutoReleaseAccount extends Mailable 'content' => $content, ]); } -} \ No newline at end of file +} diff --git a/app/Mail/MailInfo.php b/app/Mail/MailInfo.php index 3a24f0a6..681ce596 100644 --- a/app/Mail/MailInfo.php +++ b/app/Mail/MailInfo.php @@ -1,4 +1,5 @@ action = $action; $this->data = $data; - if($this->action === "delete_membership"){ + if ($this->action === "delete_membership") { $this->subject = 'Mitgliedschaft beenden - beantragt'; } - if($this->action === "check_is_like_customer"){ + if ($this->action === "check_is_like_customer") { $this->subject = 'Kunden überprüfen - Kundenhoheit'; } - if($this->action === "change_is_like_customer"){ + if ($this->action === "change_is_like_customer") { $this->subject = 'Kunden erneut überprüfen - Kundenhoheit'; } } @@ -40,68 +41,68 @@ class MailInfo extends Mailable { $content = ""; - if($this->action === "delete_membership"){ - $content .= __(strtoupper($this->user->account->salutation))." "; - $content .= $this->user->account->first_name." ".$this->user->account->last_name."\n"; - $content .= $this->user->account->address."\n"; - $content .= $this->user->account->zipcode." ".$this->user->account->city."\n"; - $content .= $this->user->account->country_id ? $this->user->account->country->de."\n\n" : "\n\n"; - if($this->user->account->phone){ + if ($this->action === "delete_membership") { + $content .= __(strtoupper($this->user->account->salutation)) . " "; + $content .= $this->user->account->first_name . " " . $this->user->account->last_name . "\n"; + $content .= $this->user->account->address . "\n"; + $content .= $this->user->account->zipcode . " " . $this->user->account->city . "\n"; + $content .= $this->user->account->country_id ? $this->user->account->country->de . "\n\n" : "\n\n"; + if ($this->user->account->phone) { $content .= "Telefon: "; - $content .= $this->user->account->pre_phone_id ? $this->user->account->pre_phone->phone." " : " "; + $content .= $this->user->account->pre_phone_id ? $this->user->account->pre_phone->phone . " " : " "; $content .= $this->user->account->phone; } - if($this->user->account->mobil){ + if ($this->user->account->mobil) { $content .= "Mobil: "; - $content .= $this->user->account->pre_mobil_id ? $this->user->account->pre_mobil->phone." " : " "; + $content .= $this->user->account->pre_mobil_id ? $this->user->account->pre_mobil->phone . " " : " "; $content .= $this->user->account->mobil; } - $content .= "E-Mail: ".$this->user->email; + $content .= "E-Mail: " . $this->user->email; - $copy1line = "Infos zum Berater:"."\n"; + $copy1line = "Infos zum Berater:" . "\n"; $button = "zum Berater"; $title = "Ein Berater möchte seine Mitgliedschaft beenden."; - $url = config('app.url_crm') . '/admin/lead/edit/' . $this->user->id . '?show=check_lead'; + $url = \App\Services\Util::getMyMivitaUrl() . '/admin/lead/edit/' . $this->user->id . '?show=check_lead'; } - if($this->action === "check_is_like_customer") { - $copy1line = "Hier geht es zum Kunden:"."\n"; + if ($this->action === "check_is_like_customer") { + $copy1line = "Hier geht es zum Kunden:" . "\n"; $button = "zum Kunden"; $title = "Ein Kunden muss überprüft werden und einem Berater zugeordnet werden, da die Adresse nicht eindeutig ist."; - $url = config('app.url_crm') . '/admin/customer/detail/' . $this->user->id; - $content .= $this->user ? 'Firma: '.$this->user->billing_company."\n" : ''; - $content .= \App\Services\HTMLHelper::getSalutationLang($this->user->billing_salutation)." "; - $content .= $this->user->billing_firstname." "; - $content .= $this->user->billing_lastname."\n"; + $url = \App\Services\Util::getMyMivitaUrl() . '/admin/customer/detail/' . $this->user->id; + $content .= $this->user ? 'Firma: ' . $this->user->billing_company . "\n" : ''; + $content .= \App\Services\HTMLHelper::getSalutationLang($this->user->billing_salutation) . " "; + $content .= $this->user->billing_firstname . " "; + $content .= $this->user->billing_lastname . "\n"; $content .= $this->user->billing_address; - $content .= $this->user->billing_address_2 ? '/ '.$this->user->billing_address_2."\n" : "\n"; - $content .= $this->user->billing_zipcode." "; - $content .= $this->user->billing_city."\n"; - $content .= $this->user->billing_email."\n"; - $content .= $this->user->billing_phone."\n"; + $content .= $this->user->billing_address_2 ? '/ ' . $this->user->billing_address_2 . "\n" : "\n"; + $content .= $this->user->billing_zipcode . " "; + $content .= $this->user->billing_city . "\n"; + $content .= $this->user->billing_email . "\n"; + $content .= $this->user->billing_phone . "\n"; $content .= $this->user->billing_country->getLocated(); } - if($this->action === "change_is_like_customer"){ - $copy1line = "Hier geht es zum Kunden:"."\n"; + if ($this->action === "change_is_like_customer") { + $copy1line = "Hier geht es zum Kunden:" . "\n"; $button = "zum Kunden"; $title = "Ein Kunden muss erneut überprüft werden, da bei einer Änderung eine bestehende Kundenhoheit gefunden wurde."; - $url = config('app.url_crm') . '/admin/customer/detail/' . $this->user->id; - $content .= "Folgende Daten für die Kundenhoheit wurden geändert:"."\n"; - foreach ($this->data as $key=>$value){ - $content .= $this->user->{$key}." => ".$value."\n"; + $url = \App\Services\Util::getMyMivitaUrl() . '/admin/customer/detail/' . $this->user->id; + $content .= "Folgende Daten für die Kundenhoheit wurden geändert:" . "\n"; + foreach ($this->data as $key => $value) { + $content .= $this->user->{$key} . " => " . $value . "\n"; } - $content .= "\n"."\n"."Rechnungsadresse des Kunden vor der Änderung:"."\n"; - $content .= $this->user ? 'Firma: '.$this->user->billing_company."\n" : ''; - $content .= \App\Services\HTMLHelper::getSalutationLang($this->user->billing_salutation)." "; - $content .= $this->user->billing_firstname." "; - $content .= $this->user->billing_lastname."\n"; + $content .= "\n" . "\n" . "Rechnungsadresse des Kunden vor der Änderung:" . "\n"; + $content .= $this->user ? 'Firma: ' . $this->user->billing_company . "\n" : ''; + $content .= \App\Services\HTMLHelper::getSalutationLang($this->user->billing_salutation) . " "; + $content .= $this->user->billing_firstname . " "; + $content .= $this->user->billing_lastname . "\n"; $content .= $this->user->billing_address; - $content .= $this->user->billing_address_2 ? '/ '.$this->user->billing_address_2."\n" : "\n"; - $content .= $this->user->billing_zipcode." "; - $content .= $this->user->billing_city."\n"; - $content .= $this->user->billing_email."\n"; - $content .= $this->user->billing_phone."\n"; + $content .= $this->user->billing_address_2 ? '/ ' . $this->user->billing_address_2 . "\n" : "\n"; + $content .= $this->user->billing_zipcode . " "; + $content .= $this->user->billing_city . "\n"; + $content .= $this->user->billing_email . "\n"; + $content .= $this->user->billing_phone . "\n"; $content .= $this->user->billing_country->getLocated(); } return $this->view('emails.info')->with([ @@ -113,4 +114,4 @@ class MailInfo extends Mailable 'content' => $content, ]); } -} \ No newline at end of file +} diff --git a/app/Mail/MailReleaseAccount.php b/app/Mail/MailReleaseAccount.php index 83284400..3c74d0f9 100644 --- a/app/Mail/MailReleaseAccount.php +++ b/app/Mail/MailReleaseAccount.php @@ -1,4 +1,5 @@ user->account->salutation))." "; - $content .= $this->user->account->first_name." ".$this->user->account->last_name."\n"; - $content .= $this->user->account->address."\n"; - $content .= $this->user->account->zipcode." ".$this->user->account->city."\n"; - $content .= $this->user->account->country_id ? $this->user->account->country->de."\n\n" : "\n\n"; - if($this->user->account->phone){ + $content = __(strtoupper($this->user->account->salutation)) . " "; + $content .= $this->user->account->first_name . " " . $this->user->account->last_name . "\n"; + $content .= $this->user->account->address . "\n"; + $content .= $this->user->account->zipcode . " " . $this->user->account->city . "\n"; + $content .= $this->user->account->country_id ? $this->user->account->country->de . "\n\n" : "\n\n"; + if ($this->user->account->phone) { $content .= "Telefon: "; - $content .= $this->user->account->pre_phone_id ? $this->user->account->pre_phone->phone." " : " "; + $content .= $this->user->account->pre_phone_id ? $this->user->account->pre_phone->phone . " " : " "; $content .= $this->user->account->phone; } - if($this->user->account->mobil){ + if ($this->user->account->mobil) { $content .= "Mobil: "; - $content .= $this->user->account->pre_mobil_id ? $this->user->account->pre_mobil->phone." " : " "; + $content .= $this->user->account->pre_mobil_id ? $this->user->account->pre_mobil->phone . " " : " "; $content .= $this->user->account->mobil; } - $content .= "E-Mail: ".$this->user->email; + $content .= "E-Mail: " . $this->user->email; - $copy1line = "Ein neuer Berater hat sich registriert und wartet auf die Überprüfung und Freigabe seiner Daten:"."\n"; - $copy1line .= "+ Überprüfung der Ausweisdaten"."\n"; - $copy1line .= "+ Überprüfung des Gewerbenachweises"."\n"; - $copy1line .= "+ Eintrag Account ID"."\n"; - $copy1line .= "+ Überprüfung / Kenntnisnahme Sponsor"."\n"; - $copy1line .= "+ Überprüfung der Rechnungsdaten"."\n"; - $copy1line .= 'Nach erfolgreicher Überprüfung mit dem Button „Daten vollständig => Berater freischalten“ den Berater freischalten.'."\n"; - $copy1line .= 'Der Berater erhält eine Mail, dass sein Account freigeschaltet wurde. Der Vertrag wird automatisch mit den Daten des Vertriebspartners erstellt.'."\n"; + $copy1line = "Ein neuer Berater hat sich registriert und wartet auf die Überprüfung und Freigabe seiner Daten:" . "\n"; + $copy1line .= "+ Überprüfung der Ausweisdaten" . "\n"; + $copy1line .= "+ Überprüfung des Gewerbenachweises" . "\n"; + $copy1line .= "+ Eintrag Account ID" . "\n"; + $copy1line .= "+ Überprüfung / Kenntnisnahme Sponsor" . "\n"; + $copy1line .= "+ Überprüfung der Rechnungsdaten" . "\n"; + $copy1line .= 'Nach erfolgreicher Überprüfung mit dem Button „Daten vollständig => Berater freischalten“ den Berater freischalten.' . "\n"; + $copy1line .= 'Der Berater erhält eine Mail, dass sein Account freigeschaltet wurde. Der Vertrag wird automatisch mit den Daten des Vertriebspartners erstellt.' . "\n"; return $this->view('emails.info')->with([ - 'url' => config('app.url_crm') . '/admin/lead/edit/' . $this->user->id . '?show=check_lead', + 'url' => \App\Services\Util::getMyMivitaUrl() . '/admin/lead/edit/' . $this->user->id . '?show=check_lead', 'title' => 'Berater Registrierung prüfen', 'button' => 'zur Berater Prüfung', 'copy1line' => $copy1line, @@ -60,4 +61,4 @@ class MailReleaseAccount extends Mailable 'content' => $content, ]); } -} \ No newline at end of file +} diff --git a/app/Mail/MailReleaseDocument.php b/app/Mail/MailReleaseDocument.php index 764ff1c4..cf386907 100644 --- a/app/Mail/MailReleaseDocument.php +++ b/app/Mail/MailReleaseDocument.php @@ -1,4 +1,5 @@ user->account->salutation))." "; - $content .= $this->user->account->first_name." ".$this->user->account->last_name."\n"; - $content .= $this->user->account->address."\n"; - $content .= $this->user->account->zipcode." ".$this->user->account->city."\n"; - $content .= $this->user->account->country_id ? $this->user->account->country->de."\n\n" : "\n\n"; - $content .= "E-Mail: ".$this->user->email; + $content = __(strtoupper($this->user->account->salutation)) . " "; + $content .= $this->user->account->first_name . " " . $this->user->account->last_name . "\n"; + $content .= $this->user->account->address . "\n"; + $content .= $this->user->account->zipcode . " " . $this->user->account->city . "\n"; + $content .= $this->user->account->country_id ? $this->user->account->country->de . "\n\n" : "\n\n"; + $content .= "E-Mail: " . $this->user->email; - $copy1line = "Ein Berater hat Daten zum Gewerbenachweis geändert, bitte um Prüfung:"."\n\n"; + $copy1line = "Ein Berater hat Daten zum Gewerbenachweis geändert, bitte um Prüfung:" . "\n\n"; $business_license_choose = $this->user->account->getNotice('business_license'); - if($business_license_choose === 'now'){ - $copy1line .= "+ Gewerbeschein jetzt zur Freigabe"."\n\n"; + if ($business_license_choose === 'now') { + $copy1line .= "+ Gewerbeschein jetzt zur Freigabe" . "\n\n"; } - if($business_license_choose === 'later'){ - $copy1line .= "+ Ich reiche meinen Gewerbeschein innerhalb der nächsten 4 Wochen nach"."\n\n"; + if ($business_license_choose === 'later') { + $copy1line .= "+ Ich reiche meinen Gewerbeschein innerhalb der nächsten 4 Wochen nach" . "\n\n"; } - if($business_license_choose === 'non'){ - $copy1line .= "+ Ich benötige keinen Gewerbeschein"."\n"; - $copy1line .= "+ Begründung: ".$this->user->account->getNotice('business_license_reason')."\n\n"; + if ($business_license_choose === 'non') { + $copy1line .= "+ Ich benötige keinen Gewerbeschein" . "\n"; + $copy1line .= "+ Begründung: " . $this->user->account->getNotice('business_license_reason') . "\n\n"; } - - $copy1line .= 'Bei fehlerhafter Angabe nimm bitte kontakt mit dem Berater auf.'."\n"; + + $copy1line .= 'Bei fehlerhafter Angabe nimm bitte kontakt mit dem Berater auf.' . "\n"; return $this->view('emails.info')->with([ - 'url' => config('app.url_crm') . '/admin/lead/edit/' . $this->user->id . '?show=check_lead', + 'url' => \App\Services\Util::getMyMivitaUrl() . '/admin/lead/edit/' . $this->user->id . '?show=check_lead', 'title' => 'Berater Unterlagen prüfen', 'button' => 'zur Berater Prüfung', 'copy1line' => $copy1line, @@ -56,4 +57,4 @@ class MailReleaseDocument extends Mailable 'content' => $content, ]); } -} \ No newline at end of file +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php index ec9dad76..bce50a8c 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -8,8 +8,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; // Wichtig! /** - * - * * @property int $id * @property string|null $name * @property string $email diff --git a/app/Providers/HorizonServiceProvider.php b/app/Providers/HorizonServiceProvider.php new file mode 100644 index 00000000..59599dc9 --- /dev/null +++ b/app/Providers/HorizonServiceProvider.php @@ -0,0 +1,36 @@ +email, [ + // + ]); + }); + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 361a2807..b71b50df 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -58,7 +58,7 @@ class RouteServiceProvider extends ServiceProvider /** @var DomainContext $context */ $context = app(DomainContext::class); $this->loadSharedRoutes(); - + \Log::info('loadDomainAwareRoutes', ['context' => $context]); match ($context->type) { 'main' => $this->loadDomainRoutes('main', 'main.php'), 'main-shop' => [ diff --git a/bootstrap/cache/events.php b/bootstrap/cache/events.php new file mode 100644 index 00000000..02e2fc9e --- /dev/null +++ b/bootstrap/cache/events.php @@ -0,0 +1,9 @@ + + array ( + 'App\\Events\\Event' => + array ( + 0 => 'App\\Listeners\\EventListener', + ), + ), +); \ No newline at end of file diff --git a/bootstrap/cache/packages.php b/bootstrap/cache/packages.php index bd818981..26049063 100755 --- a/bootstrap/cache/packages.php +++ b/bootstrap/cache/packages.php @@ -66,6 +66,17 @@ 0 => 'Laracasts\\Flash\\FlashServiceProvider', ), ), + 'laravel/horizon' => + array ( + 'aliases' => + array ( + 'Horizon' => 'Laravel\\Horizon\\Horizon', + ), + 'providers' => + array ( + 0 => 'Laravel\\Horizon\\HorizonServiceProvider', + ), + ), 'laravel/legacy-factories' => array ( 'providers' => diff --git a/bootstrap/cache/services.php b/bootstrap/cache/services.php index c49c1e7d..8650f4ef 100755 --- a/bootstrap/cache/services.php +++ b/bootstrap/cache/services.php @@ -31,31 +31,33 @@ 27 => 'JoeDixon\\Translation\\TranslationServiceProvider', 28 => 'JoeDixon\\Translation\\TranslationBindingsServiceProvider', 29 => 'Laracasts\\Flash\\FlashServiceProvider', - 30 => 'Illuminate\\Database\\Eloquent\\LegacyFactoryServiceProvider', - 31 => 'Laravel\\Passport\\PassportServiceProvider', - 32 => 'Laravel\\Sail\\SailServiceProvider', - 33 => 'Laravel\\Tinker\\TinkerServiceProvider', - 34 => 'Laravel\\Ui\\UiServiceProvider', - 35 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 36 => 'Carbon\\Laravel\\ServiceProvider', - 37 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - 38 => 'Termwind\\Laravel\\TermwindServiceProvider', - 39 => 'Pest\\Laravel\\PestServiceProvider', - 40 => 'Spatie\\Html\\HtmlServiceProvider', - 41 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', - 42 => 'Yajra\\DataTables\\DataTablesServiceProvider', - 43 => 'Laravel\\Tinker\\TinkerServiceProvider', - 44 => 'Acme\\Dhl\\DhlServiceProvider', - 45 => 'App\\Providers\\AppServiceProvider', - 46 => 'App\\Providers\\AuthServiceProvider', - 47 => 'App\\Providers\\EventServiceProvider', - 48 => 'App\\Providers\\DomainServiceProvider', - 49 => 'App\\Providers\\RouteServiceProvider', - 50 => 'Jenssegers\\Date\\DateServiceProvider', - 51 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 52 => 'Yajra\\DataTables\\DataTablesServiceProvider', - 53 => 'App\\Providers\\YardServiceProvider', - 54 => 'Alban\\LaravelCollectiveSpatieHtmlParser\\ServiceProvider', + 30 => 'Laravel\\Horizon\\HorizonServiceProvider', + 31 => 'Illuminate\\Database\\Eloquent\\LegacyFactoryServiceProvider', + 32 => 'Laravel\\Passport\\PassportServiceProvider', + 33 => 'Laravel\\Sail\\SailServiceProvider', + 34 => 'Laravel\\Tinker\\TinkerServiceProvider', + 35 => 'Laravel\\Ui\\UiServiceProvider', + 36 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 37 => 'Carbon\\Laravel\\ServiceProvider', + 38 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + 39 => 'Termwind\\Laravel\\TermwindServiceProvider', + 40 => 'Pest\\Laravel\\PestServiceProvider', + 41 => 'Spatie\\Html\\HtmlServiceProvider', + 42 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', + 43 => 'Yajra\\DataTables\\DataTablesServiceProvider', + 44 => 'Laravel\\Tinker\\TinkerServiceProvider', + 45 => 'Acme\\Dhl\\DhlServiceProvider', + 46 => 'App\\Providers\\AppServiceProvider', + 47 => 'App\\Providers\\AuthServiceProvider', + 48 => 'App\\Providers\\EventServiceProvider', + 49 => 'App\\Providers\\HorizonServiceProvider', + 50 => 'App\\Providers\\DomainServiceProvider', + 51 => 'App\\Providers\\RouteServiceProvider', + 52 => 'Jenssegers\\Date\\DateServiceProvider', + 53 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 54 => 'Yajra\\DataTables\\DataTablesServiceProvider', + 55 => 'App\\Providers\\YardServiceProvider', + 56 => 'Alban\\LaravelCollectiveSpatieHtmlParser\\ServiceProvider', ), 'eager' => array ( @@ -75,28 +77,30 @@ 13 => 'Jenssegers\\Date\\DateServiceProvider', 14 => 'JoeDixon\\Translation\\TranslationServiceProvider', 15 => 'Laracasts\\Flash\\FlashServiceProvider', - 16 => 'Illuminate\\Database\\Eloquent\\LegacyFactoryServiceProvider', - 17 => 'Laravel\\Passport\\PassportServiceProvider', - 18 => 'Laravel\\Ui\\UiServiceProvider', - 19 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 20 => 'Carbon\\Laravel\\ServiceProvider', - 21 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', - 22 => 'Termwind\\Laravel\\TermwindServiceProvider', - 23 => 'Pest\\Laravel\\PestServiceProvider', - 24 => 'Spatie\\Html\\HtmlServiceProvider', - 25 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', - 26 => 'Yajra\\DataTables\\DataTablesServiceProvider', - 27 => 'Acme\\Dhl\\DhlServiceProvider', - 28 => 'App\\Providers\\AppServiceProvider', - 29 => 'App\\Providers\\AuthServiceProvider', - 30 => 'App\\Providers\\EventServiceProvider', - 31 => 'App\\Providers\\DomainServiceProvider', - 32 => 'App\\Providers\\RouteServiceProvider', - 33 => 'Jenssegers\\Date\\DateServiceProvider', - 34 => 'Maatwebsite\\Excel\\ExcelServiceProvider', - 35 => 'Yajra\\DataTables\\DataTablesServiceProvider', - 36 => 'App\\Providers\\YardServiceProvider', - 37 => 'Alban\\LaravelCollectiveSpatieHtmlParser\\ServiceProvider', + 16 => 'Laravel\\Horizon\\HorizonServiceProvider', + 17 => 'Illuminate\\Database\\Eloquent\\LegacyFactoryServiceProvider', + 18 => 'Laravel\\Passport\\PassportServiceProvider', + 19 => 'Laravel\\Ui\\UiServiceProvider', + 20 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 21 => 'Carbon\\Laravel\\ServiceProvider', + 22 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', + 23 => 'Termwind\\Laravel\\TermwindServiceProvider', + 24 => 'Pest\\Laravel\\PestServiceProvider', + 25 => 'Spatie\\Html\\HtmlServiceProvider', + 26 => 'Spatie\\LaravelIgnition\\IgnitionServiceProvider', + 27 => 'Yajra\\DataTables\\DataTablesServiceProvider', + 28 => 'Acme\\Dhl\\DhlServiceProvider', + 29 => 'App\\Providers\\AppServiceProvider', + 30 => 'App\\Providers\\AuthServiceProvider', + 31 => 'App\\Providers\\EventServiceProvider', + 32 => 'App\\Providers\\HorizonServiceProvider', + 33 => 'App\\Providers\\DomainServiceProvider', + 34 => 'App\\Providers\\RouteServiceProvider', + 35 => 'Jenssegers\\Date\\DateServiceProvider', + 36 => 'Maatwebsite\\Excel\\ExcelServiceProvider', + 37 => 'Yajra\\DataTables\\DataTablesServiceProvider', + 38 => 'App\\Providers\\YardServiceProvider', + 39 => 'Alban\\LaravelCollectiveSpatieHtmlParser\\ServiceProvider', ), 'deferred' => array ( diff --git a/composer.json b/composer.json index 1ccd3c29..e56cadb9 100755 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "joedixon/laravel-translation": "2.x-dev", "laracasts/flash": "^3.2", "laravel/framework": "^11.0", + "laravel/horizon": "^5.33", "laravel/passport": "^12.0", "laravel/prompts": "^0.1.14", "laravel/tinker": "^2.9", @@ -29,16 +30,16 @@ "yajra/laravel-datatables-oracle": "^11.0" }, "require-dev": { - "spatie/laravel-ignition": "^2.0", - "nunomaduro/collision": "^8.1", - "fakerphp/faker": "^1.23", - "laravel/pint": "^1.0", - "laravel/sail": "^1.26", + "barryvdh/laravel-debugbar": "^3.13", + "barryvdh/laravel-ide-helper": "^3.6", + "fakerphp/faker": "^1.23", + "laravel/pint": "^1.0", + "laravel/sail": "^1.44", "mockery/mockery": "^1.6.2", - "pestphp/pest": "^2.0", - "pestphp/pest-plugin-laravel": "^2.0", - "barryvdh/laravel-debugbar": "^3.13", - "barryvdh/laravel-ide-helper": "^3.0" + "nunomaduro/collision": "^8.1", + "pestphp/pest": "^2.0", + "pestphp/pest-plugin-laravel": "^2.0", + "spatie/laravel-ignition": "^2.0" }, "config": { "optimize-autoloader": true, diff --git a/composer.lock b/composer.lock old mode 100644 new mode 100755 index 3f12675d..9e51763d --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7fc21677cad34a62767eaccbc243e7d6", + "content-hash": "925483d8104ae55ae4bf5fd0ada18726", "packages": [ { "name": "barryvdh/laravel-dompdf", @@ -1432,22 +1432,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.9.3", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1538,7 +1538,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -1554,20 +1554,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:37:11+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -1575,7 +1575,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { @@ -1621,7 +1621,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.2.0" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -1637,20 +1637,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:27:01+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -1666,7 +1666,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -1737,7 +1737,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.1" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -1753,20 +1753,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:30:47+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.4", + "version": "v1.0.5", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "30e286560c137526eccd4ce21b2de477ab0676d2" + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/30e286560c137526eccd4ce21b2de477ab0676d2", - "reference": "30e286560c137526eccd4ce21b2de477ab0676d2", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/4f4bbd4e7172148801e76e3decc1e559bdee34e1", + "reference": "4f4bbd4e7172148801e76e3decc1e559bdee34e1", "shasum": "" }, "require": { @@ -1775,7 +1775,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.36 || ^9.6.15", + "phpunit/phpunit": "^8.5.44 || ^9.6.25", "uri-template/tests": "1.0.0" }, "type": "library", @@ -1823,7 +1823,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.4" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.5" }, "funding": [ { @@ -1839,7 +1839,7 @@ "type": "tidelift" } ], - "time": "2025-02-03T10:55:03+00:00" + "time": "2025-08-22T14:27:06+00:00" }, { "name": "intervention/gif", @@ -2401,6 +2401,86 @@ }, "time": "2025-08-13T20:28:00+00:00" }, + { + "name": "laravel/horizon", + "version": "v5.33.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/horizon.git", + "reference": "678362049ce5b9ce96673ac0282bbfda3279eca9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/horizon/zipball/678362049ce5b9ce96673ac0282bbfda3279eca9", + "reference": "678362049ce5b9ce96673ac0282bbfda3279eca9", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-pcntl": "*", + "ext-posix": "*", + "illuminate/contracts": "^9.21|^10.0|^11.0|^12.0", + "illuminate/queue": "^9.21|^10.0|^11.0|^12.0", + "illuminate/support": "^9.21|^10.0|^11.0|^12.0", + "nesbot/carbon": "^2.17|^3.0", + "php": "^8.0", + "ramsey/uuid": "^4.0", + "symfony/console": "^6.0|^7.0", + "symfony/error-handler": "^6.0|^7.0", + "symfony/polyfill-php83": "^1.28", + "symfony/process": "^6.0|^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^7.0|^8.0|^9.0|^10.0", + "phpstan/phpstan": "^1.10|^2.0", + "phpunit/phpunit": "^9.0|^10.4|^11.5|^12.0", + "predis/predis": "^1.1|^2.0|^3.0" + }, + "suggest": { + "ext-redis": "Required to use the Redis PHP driver.", + "predis/predis": "Required when not using the Redis PHP driver (^1.1|^2.0|^3.0)." + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Horizon": "Laravel\\Horizon\\Horizon" + }, + "providers": [ + "Laravel\\Horizon\\HorizonServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Horizon\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Dashboard and code-driven configuration for Laravel queues.", + "keywords": [ + "laravel", + "queue" + ], + "support": { + "issues": "https://github.com/laravel/horizon/issues", + "source": "https://github.com/laravel/horizon/tree/v5.33.4" + }, + "time": "2025-08-25T13:31:24+00:00" + }, { "name": "laravel/legacy-factories", "version": "v1.4.1", @@ -3613,16 +3693,16 @@ }, { "name": "maatwebsite/excel", - "version": "3.1.66", + "version": "3.1.67", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "3b29c2426a46674f444890c45f742452a396aae8" + "reference": "e508e34a502a3acc3329b464dad257378a7edb4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/3b29c2426a46674f444890c45f742452a396aae8", - "reference": "3b29c2426a46674f444890c45f742452a396aae8", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/e508e34a502a3acc3329b464dad257378a7edb4d", + "reference": "e508e34a502a3acc3329b464dad257378a7edb4d", "shasum": "" }, "require": { @@ -3630,7 +3710,7 @@ "ext-json": "*", "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0", "php": "^7.0||^8.0", - "phpoffice/phpspreadsheet": "^1.29.12", + "phpoffice/phpspreadsheet": "^1.30.0", "psr/simple-cache": "^1.0||^2.0||^3.0" }, "require-dev": { @@ -3678,7 +3758,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.66" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.67" }, "funding": [ { @@ -3690,26 +3770,26 @@ "type": "github" } ], - "time": "2025-08-07T08:31:22+00:00" + "time": "2025-08-26T09:13:16+00:00" }, { "name": "maennchen/zipstream-php", - "version": "3.1.2", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/maennchen/ZipStream-PHP.git", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f" + "reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f", - "reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/9712d8fa4cdf9240380b01eb4be55ad8dcf71416", + "reference": "9712d8fa4cdf9240380b01eb4be55ad8dcf71416", "shasum": "" }, "require": { "ext-mbstring": "*", "ext-zlib": "*", - "php-64bit": "^8.2" + "php-64bit": "^8.3" }, "require-dev": { "brianium/paratest": "^7.7", @@ -3718,7 +3798,7 @@ "guzzlehttp/guzzle": "^7.5", "mikey179/vfsstream": "^1.6", "php-coveralls/php-coveralls": "^2.5", - "phpunit/phpunit": "^11.0", + "phpunit/phpunit": "^12.0", "vimeo/psalm": "^6.0" }, "suggest": { @@ -3760,7 +3840,7 @@ ], "support": { "issues": "https://github.com/maennchen/ZipStream-PHP/issues", - "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2" + "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.2.0" }, "funding": [ { @@ -3768,7 +3848,7 @@ "type": "github" } ], - "time": "2025-01-27T12:07:53+00:00" + "time": "2025-07-17T11:15:13+00:00" }, { "name": "markbaker/complex", @@ -6406,16 +6486,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.3.0", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", - "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b7dc69e71de420ac04bc9ab830cf3ffebba48191", + "reference": "b7dc69e71de420ac04bc9ab830cf3ffebba48191", "shasum": "" }, "require": { @@ -6466,7 +6546,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.3" }, "funding": [ { @@ -6477,12 +6557,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-22T09:11:45+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6630,16 +6714,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "6877c122b3a6cc3695849622720054f6e6fa5fa6" + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6877c122b3a6cc3695849622720054f6e6fa5fa6", - "reference": "6877c122b3a6cc3695849622720054f6e6fa5fa6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/7475561ec27020196c49bb7c4f178d33d7d3dc00", + "reference": "7475561ec27020196c49bb7c4f178d33d7d3dc00", "shasum": "" }, "require": { @@ -6689,7 +6773,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.3.2" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.3" }, "funding": [ { @@ -6709,20 +6793,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:47:49+00:00" + "time": "2025-08-20T08:04:18+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "6ecc895559ec0097e221ed2fd5eb44d5fede083c" + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/6ecc895559ec0097e221ed2fd5eb44d5fede083c", - "reference": "6ecc895559ec0097e221ed2fd5eb44d5fede083c", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/72c304de37e1a1cec6d5d12b81187ebd4850a17b", + "reference": "72c304de37e1a1cec6d5d12b81187ebd4850a17b", "shasum": "" }, "require": { @@ -6807,7 +6891,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.3.2" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.3" }, "funding": [ { @@ -6827,20 +6911,20 @@ "type": "tidelift" } ], - "time": "2025-07-31T10:45:04+00:00" + "time": "2025-08-29T08:23:45+00:00" }, { "name": "symfony/mailer", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "d43e84d9522345f96ad6283d5dfccc8c1cfc299b" + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/d43e84d9522345f96ad6283d5dfccc8c1cfc299b", - "reference": "d43e84d9522345f96ad6283d5dfccc8c1cfc299b", + "url": "https://api.github.com/repos/symfony/mailer/zipball/a32f3f45f1990db8c4341d5122a7d3a381c7e575", + "reference": "a32f3f45f1990db8c4341d5122a7d3a381c7e575", "shasum": "" }, "require": { @@ -6891,7 +6975,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.3.2" + "source": "https://github.com/symfony/mailer/tree/v7.3.3" }, "funding": [ { @@ -6911,7 +6995,7 @@ "type": "tidelift" } ], - "time": "2025-07-15T11:36:08+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "symfony/mime", @@ -7672,16 +7756,16 @@ }, { "name": "symfony/process", - "version": "v7.3.0", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", - "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "url": "https://api.github.com/repos/symfony/process/zipball/32241012d521e2e8a9d713adb0812bb773b907f1", + "reference": "32241012d521e2e8a9d713adb0812bb773b907f1", "shasum": "" }, "require": { @@ -7713,7 +7797,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.3.0" + "source": "https://github.com/symfony/process/tree/v7.3.3" }, "funding": [ { @@ -7724,12 +7808,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-17T09:11:12+00:00" + "time": "2025-08-18T09:42:54+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -7984,16 +8072,16 @@ }, { "name": "symfony/string", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca" + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/42f505aff654e62ac7ac2ce21033818297ca89ca", - "reference": "42f505aff654e62ac7ac2ce21033818297ca89ca", + "url": "https://api.github.com/repos/symfony/string/zipball/17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", + "reference": "17a426cce5fd1f0901fefa9b2a490d0038fd3c9c", "shasum": "" }, "require": { @@ -8051,7 +8139,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.3.2" + "source": "https://github.com/symfony/string/tree/v7.3.3" }, "funding": [ { @@ -8071,7 +8159,7 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:47:49+00:00" + "time": "2025-08-25T06:35:40+00:00" }, { "name": "symfony/translation", @@ -8326,16 +8414,16 @@ }, { "name": "symfony/var-dumper", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "53205bea27450dc5c65377518b3275e126d45e75" + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/53205bea27450dc5c65377518b3275e126d45e75", - "reference": "53205bea27450dc5c65377518b3275e126d45e75", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", + "reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f", "shasum": "" }, "require": { @@ -8389,7 +8477,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.3.2" + "source": "https://github.com/symfony/var-dumper/tree/v7.3.3" }, "funding": [ { @@ -8409,7 +8497,7 @@ "type": "tidelift" } ], - "time": "2025-07-29T20:02:46+00:00" + "time": "2025-08-13T11:49:31+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -11980,16 +12068,16 @@ }, { "name": "spatie/backtrace", - "version": "1.7.4", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe" + "reference": "8c0f16a59ae35ec8c62d85c3c17585158f430110" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/cd37a49fce7137359ac30ecc44ef3e16404cccbe", - "reference": "cd37a49fce7137359ac30ecc44ef3e16404cccbe", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/8c0f16a59ae35ec8c62d85c3c17585158f430110", + "reference": "8c0f16a59ae35ec8c62d85c3c17585158f430110", "shasum": "" }, "require": { @@ -12027,7 +12115,8 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.7.4" + "issues": "https://github.com/spatie/backtrace/issues", + "source": "https://github.com/spatie/backtrace/tree/1.8.1" }, "funding": [ { @@ -12039,7 +12128,7 @@ "type": "other" } ], - "time": "2025-05-08T15:41:09+00:00" + "time": "2025-08-26T08:22:30+00:00" }, { "name": "spatie/error-solutions", @@ -12360,16 +12449,16 @@ }, { "name": "symfony/yaml", - "version": "v7.3.2", + "version": "v7.3.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "b8d7d868da9eb0919e99c8830431ea087d6aae30" + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/b8d7d868da9eb0919e99c8830431ea087d6aae30", - "reference": "b8d7d868da9eb0919e99c8830431ea087d6aae30", + "url": "https://api.github.com/repos/symfony/yaml/zipball/d4f4a66866fe2451f61296924767280ab5732d9d", + "reference": "d4f4a66866fe2451f61296924767280ab5732d9d", "shasum": "" }, "require": { @@ -12412,7 +12501,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.3.2" + "source": "https://github.com/symfony/yaml/tree/v7.3.3" }, "funding": [ { @@ -12432,7 +12521,7 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:47:49+00:00" + "time": "2025-08-27T11:34:33+00:00" }, { "name": "ta-tikoma/phpunit-architecture-test", @@ -12554,6 +12643,6 @@ "platform": { "php": "^8.2" }, - "platform-dev": [], - "plugin-api-version": "2.2.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/config/app.php b/config/app.php index f12baf38..227cd05e 100755 --- a/config/app.php +++ b/config/app.php @@ -59,7 +59,7 @@ return [ 'tld_shop' => env('APP_TLD_SHOP', '.lshop'), 'protocol' => env('APP_PROTOCOL', 'https://'), 'pre_url_main' => env('APP_URL_MAIN', ''), - 'pre_url_crm' => env('APP_URL_CRM', 'my.'), + 'pre_url_crm' => env('APP_PRE_URL_CRM', 'my.'), 'pre_url_portal' => env('APP_URL_PORTAL', 'in.'), 'checkout_url' => env('APP_URL_CHECKOUT', 'checkout.'), @@ -198,6 +198,7 @@ return [ App\Providers\AuthServiceProvider::class, // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, + App\Providers\HorizonServiceProvider::class, App\Providers\DomainServiceProvider::class, App\Providers\RouteServiceProvider::class, Jenssegers\Date\DateServiceProvider::class, diff --git a/config/domains.php b/config/domains.php index 4aeb664b..b45b8ac2 100644 --- a/config/domains.php +++ b/config/domains.php @@ -30,13 +30,13 @@ return [ // Das CRM (z.B. my.mivita.care) 'crm' => [ - 'host' => env('APP_URL_CRM', 'my.') . env('APP_DOMAIN', 'mivita') . env('APP_TLD_CARE', '.care'), + 'host' => env('APP_PRE_URL_CRM', 'my.') . env('APP_DOMAIN', 'mivita') . env('APP_TLD_CARE', '.care'), 'type' => 'crm', ], // Das Partner-Portal (z.B. in.mivita.care) 'portal' => [ - 'host' => env('APP_URL_PORTAL', 'in.') . env('APP_DOMAIN', 'mivita') . env('APP_TLD_CARE', '.care'), + 'host' => env('APP_PRE_URL_PORTAL', 'in.') . env('APP_DOMAIN', 'mivita') . env('APP_TLD_CARE', '.care'), 'type' => 'portal', ], diff --git a/config/horizon.php b/config/horizon.php new file mode 100644 index 00000000..5101f6f0 --- /dev/null +++ b/config/horizon.php @@ -0,0 +1,213 @@ + env('HORIZON_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | Horizon Path + |-------------------------------------------------------------------------- + | + | This is the URI path where Horizon will be accessible from. Feel free + | to change this path to anything you like. Note that the URI will not + | affect the paths of its internal API that aren't exposed to users. + | + */ + + 'path' => env('HORIZON_PATH', 'horizon'), + + /* + |-------------------------------------------------------------------------- + | Horizon Redis Connection + |-------------------------------------------------------------------------- + | + | This is the name of the Redis connection where Horizon will store the + | meta information required for it to function. It includes the list + | of supervisors, failed jobs, job metrics, and other information. + | + */ + + 'use' => 'default', + + /* + |-------------------------------------------------------------------------- + | Horizon Redis Prefix + |-------------------------------------------------------------------------- + | + | This prefix will be used when storing all Horizon data in Redis. You + | may modify the prefix when you are running multiple installations + | of Horizon on the same server so that they don't have problems. + | + */ + + 'prefix' => env( + 'HORIZON_PREFIX', + Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' + ), + + /* + |-------------------------------------------------------------------------- + | Horizon Route Middleware + |-------------------------------------------------------------------------- + | + | These middleware will get attached onto each Horizon route, giving you + | the chance to add your own middleware to this list or change any of + | the existing middleware. Or, you can simply stick with this list. + | + */ + + 'middleware' => ['web'], + + /* + |-------------------------------------------------------------------------- + | Queue Wait Time Thresholds + |-------------------------------------------------------------------------- + | + | This option allows you to configure when the LongWaitDetected event + | will be fired. Every connection / queue combination may have its + | own, unique threshold (in seconds) before this event is fired. + | + */ + + 'waits' => [ + 'redis:default' => 60, + ], + + /* + |-------------------------------------------------------------------------- + | Job Trimming Times + |-------------------------------------------------------------------------- + | + | Here you can configure for how long (in minutes) you desire Horizon to + | persist the recent and failed jobs. Typically, recent jobs are kept + | for one hour while all failed jobs are stored for an entire week. + | + */ + + 'trim' => [ + 'recent' => 60, + 'pending' => 60, + 'completed' => 60, + 'recent_failed' => 10080, + 'failed' => 10080, + 'monitored' => 10080, + ], + + /* + |-------------------------------------------------------------------------- + | Silenced Jobs + |-------------------------------------------------------------------------- + | + | Silencing a job will instruct Horizon to not place the job in the list + | of completed jobs within the Horizon dashboard. This setting may be + | used to fully remove any noisy jobs from the completed jobs list. + | + */ + + 'silenced' => [ + // App\Jobs\ExampleJob::class, + ], + + /* + |-------------------------------------------------------------------------- + | Metrics + |-------------------------------------------------------------------------- + | + | Here you can configure how many snapshots should be kept to display in + | the metrics graph. This will get used in combination with Horizon's + | `horizon:snapshot` schedule to define how long to retain metrics. + | + */ + + 'metrics' => [ + 'trim_snapshots' => [ + 'job' => 24, + 'queue' => 24, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Fast Termination + |-------------------------------------------------------------------------- + | + | When this option is enabled, Horizon's "terminate" command will not + | wait on all of the workers to terminate unless the --wait option + | is provided. Fast termination can shorten deployment delay by + | allowing a new instance of Horizon to start while the last + | instance will continue to terminate each of its workers. + | + */ + + 'fast_termination' => false, + + /* + |-------------------------------------------------------------------------- + | Memory Limit (MB) + |-------------------------------------------------------------------------- + | + | This value describes the maximum amount of memory the Horizon master + | supervisor may consume before it is terminated and restarted. For + | configuring these limits on your workers, see the next section. + | + */ + + 'memory_limit' => 64, + + /* + |-------------------------------------------------------------------------- + | Queue Worker Configuration + |-------------------------------------------------------------------------- + | + | Here you may define the queue worker settings used by your application + | in all environments. These supervisors and settings handle all your + | queued jobs and will be provisioned by Horizon during deployment. + | + */ + + 'defaults' => [ + 'supervisor-1' => [ + 'connection' => 'redis', + 'queue' => ['default'], + 'balance' => 'auto', + 'autoScalingStrategy' => 'time', + 'maxProcesses' => 1, + 'maxTime' => 0, + 'maxJobs' => 0, + 'memory' => 128, + 'tries' => 1, + 'timeout' => 60, + 'nice' => 0, + ], + ], + + 'environments' => [ + 'production' => [ + 'supervisor-1' => [ + 'maxProcesses' => 10, + 'balanceMaxShift' => 1, + 'balanceCooldown' => 3, + ], + ], + + 'local' => [ + 'supervisor-1' => [ + 'maxProcesses' => 3, + ], + ], + ], +]; diff --git a/cron_script.sh b/cron_script.sh deleted file mode 100644 index a4d076b9..00000000 --- a/cron_script.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -echo $(date) # Will print the output of date command -/Applications/MAMP/bin/php/php7.3.33/bin/php -v -/Applications/MAMP/bin/php/php7.3.33/bin/php ../artisan business:store 0 0 2>&1 -#/usr/bin/php74 -v -#/usr/bin/php74 ../artisan business:store 0 0 2>&1 -# php /path/to/artisan schedule:run 1>> /dev/null 2>&1 -# cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 \ No newline at end of file diff --git a/database/migrations/2022_03_07_131701_create_user_credits_table.php b/database/migrations/2022_03_07_131701_create_user_credits_table.php deleted file mode 100644 index 1a9db250..00000000 --- a/database/migrations/2022_03_07_131701_create_user_credits_table.php +++ /dev/null @@ -1,79 +0,0 @@ -id(); - - $table->unsignedInteger('auth_user_id')->nullable(); - $table->unsignedInteger('shopping_order_id')->nullable(); - $table->unsignedInteger('shopping_user_id')->nullable(); - - //invoice //credit - $table->string('type', 7)->index(); - - $table->string('str_number', 255)->nullable(); - $table->unsignedInteger('number', 255)->nullable(); - - $table->decimal('net', 13, 2)->nullable(); - $table->decimal('tax_rate', 8, 2)->nullable(); - $table->decimal('tax', 8, 2)->nullable(); - $table->decimal('total', 13, 2)->nullable(); - - $table->text('file')->nullable(); - $table->text('contents')->nullable(); - $table->text('infos')->nullable(); - - $table->string('subject')->nullable(); - $table->text('address')->nullable(); - - $table->boolean('paid')->default(false); - $table->date('paid_date')->nullable(); - - $table->unsignedInteger('cancellation_id')->nullable(); - $table->date('cancellation_date')->nullable(); - - $table->unsignedTinyInteger('status')->index()->default(0); - - $table->timestamps(); - $table->softDeletes(); - - $table->foreign('auth_user_id') - ->references('id') - ->on('users'); - - $table->foreign('shopping_order_id') - ->references('id') - ->on('shopping_orders'); - - $table->foreign('shopping_user_id') - ->references('id') - ->on('shopping_users'); - - $table->foreign('cancellation_id') - ->references('id') - ->on('users'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('user_credits'); - } -} diff --git a/database/migrations/2022_03_07_131701_create_user_invoice_credits_table.php b/database/migrations/2022_03_07_131701_create_user_invoice_credits_table.php deleted file mode 100644 index 079ec6d2..00000000 --- a/database/migrations/2022_03_07_131701_create_user_invoice_credits_table.php +++ /dev/null @@ -1,81 +0,0 @@ -increments('id'); - - $table->unsignedInteger('auth_user_id')->index()->nullable(); - $table->unsignedInteger('shopping_order_id')->index()->nullable(); - $table->unsignedInteger('shopping_user_id')->index()->nullable(); - - //invoice //credit - $table->string('type', 7)->index(); - $table->unsignedTinyInteger('month')->nullable(); - $table->unsignedSmallInteger('year')->nullable(); - - $table->string('full_number', 255)->nullable(); - $table->unsignedInteger('number')->nullable(); - - $table->decimal('net', 13, 2)->nullable(); - $table->decimal('tax_rate', 8, 2)->nullable(); - $table->decimal('tax', 8, 2)->nullable(); - $table->decimal('total', 13, 2)->nullable(); - - $table->text('file')->nullable(); - $table->text('contents')->nullable(); - $table->text('infos')->nullable(); - - $table->string('subject')->nullable(); - $table->text('address')->nullable(); - - $table->boolean('paid')->default(false); - $table->date('paid_date')->nullable(); - - $table->unsignedInteger('cancellation_id')->nullable(); - $table->date('cancellation_date')->nullable(); - - $table->unsignedTinyInteger('status')->index()->default(0); - - $table->timestamps(); - $table->softDeletes(); - - $table->foreign('auth_user_id') - ->references('id') - ->on('users'); - - $table->foreign('shopping_order_id') - ->references('id') - ->on('shopping_orders'); - - $table->foreign('shopping_user_id') - ->references('id') - ->on('shopping_users'); - - $table->foreign('cancellation_id') - ->references('id') - ->on('user_invoice_credits'); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('user_invoice_credits'); - } -} diff --git a/database/migrations/2022_03_08_102231_create_users_sales_volumes_table.php b/database/migrations/2022_03_08_102231_create_users_sales_volumes_table.php deleted file mode 100644 index cb765995..00000000 --- a/database/migrations/2022_03_08_102231_create_users_sales_volumes_table.php +++ /dev/null @@ -1,56 +0,0 @@ -increments('id'); - $table->unsignedInteger('user_id'); - $table->unsignedInteger('shopping_order_id')->index()->nullable(); - - $table->unsignedTinyInteger('month')->nullable(); - $table->unsignedSmallInteger('year')->nullable(); - $table->date('date')->nullable(); - - $table->unsignedInteger('points')->nullable(); - $table->unsignedInteger('month_points')->nullable(); - - $table->decimal('total_net', 13, 2)->nullable(); - $table->decimal('month_total_net', 13, 2)->nullable(); - - $table->string('message', 255)->nullable(); - $table->unsignedTinyInteger('status')->index()->default(0); - - $table->timestamps(); - - $table->foreign('user_id') - ->references('id') - ->on('users'); - - $table->foreign('shopping_order_id') - ->references('id') - ->on('shopping_orders'); - - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('users_sales_volumes'); - } -} diff --git a/database/migrations/2022_07_25_140152_create_user_businesses_table.php b/database/migrations/2022_07_25_140152_create_user_businesses_table.php deleted file mode 100644 index 5a5dc0b0..00000000 --- a/database/migrations/2022_07_25_140152_create_user_businesses_table.php +++ /dev/null @@ -1,95 +0,0 @@ -increments('id'); - - $table->unsignedInteger('user_id'); - $table->unsignedTinyInteger('month')->nullable(); - $table->unsignedSmallInteger('year')->nullable(); - - $table->unsignedInteger('m_level_id')->nullable(); - $table->unsignedInteger('m_sponsor_id')->nullable(); - $table->text('sponsor')->nullable(); - - $table->string('m_sponsor_name')->nullable(); - $table->string('user_level_name')->nullable(); - - $table->boolean('active_account')->default(false); - $table->date('payment_account_date')->nullable(); - $table->date('active_date')->nullable(); - - $table->unsignedInteger('m_account')->nullable(); - - $table->string('email')->nullable(); - $table->string('first_name')->nullable(); - $table->string('last_name')->nullable(); - - $table->integer('sales_volume_points')->nullable(); - $table->integer('sales_volume_points_shop')->nullable(); - $table->integer('sales_volume_points_sum')->nullable(); - - $table->decimal('sales_volume_total', 13, 2)->nullable(); - $table->decimal('sales_volume_total_shop', 13, 2)->nullable(); - $table->decimal('sales_volume_total_sum', 13, 2)->nullable(); - - $table->unsignedTinyInteger('margin')->nullable(); - $table->unsignedTinyInteger('margin_shop')->nullable(); - - $table->decimal('commission_shop_sales', 13, 2)->nullable(); - - $table->unsignedSmallInteger('qual_kp')->nullable(); - $table->unsignedInteger('qual_tp')->nullable(); - - $table->integer('total_tp')->nullable(); - $table->integer('total_qual_tp')->nullable(); - - $table->decimal('commission_lines_total', 13, 2)->nullable(); - $table->decimal('commission_shop_sales', 13, 2)->nullable(); - - $table->text('businessLines')->nullable(); - $table->text('userItems')->nullable(); - $table->text('qual_user_level')->nullable(); - - - $table->timestamps(); - - /*$table->foreign('user_id') - ->references('id') - ->on('users'); - - $table->foreign('m_level') - ->references('id') - ->on('user_levels'); - - $table->foreign('m_sponsor') - ->references('id') - ->on('users');*/ - - - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('user_businesses'); - } -} diff --git a/database/migrations/2025_08_19_150653_create_jobs_table.php b/database/migrations/2025_08_19_150653_create_jobs_table.php new file mode 100644 index 00000000..6098d9b1 --- /dev/null +++ b/database/migrations/2025_08_19_150653_create_jobs_table.php @@ -0,0 +1,32 @@ +bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jobs'); + } +}; diff --git a/database/migrations/2025_08_19_150658_create_failed_jobs_table.php b/database/migrations/2025_08_19_150658_create_failed_jobs_table.php new file mode 100644 index 00000000..249da817 --- /dev/null +++ b/database/migrations/2025_08_19_150658_create_failed_jobs_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/dev/bak/RouteServiceProvider.php.bak b/dev/bak/RouteServiceProvider.php similarity index 100% rename from dev/bak/RouteServiceProvider.php.bak rename to dev/bak/RouteServiceProvider.php diff --git a/dev/bak/Subdomain.php.bak b/dev/bak/Subdomain.php similarity index 100% rename from dev/bak/Subdomain.php.bak rename to dev/bak/Subdomain.php diff --git a/dev/code/Services/BusinessPlan/TreeCalcBot.php b/dev/code/Services/BusinessPlan/TreeCalcBot.php deleted file mode 100644 index fdceab90..00000000 --- a/dev/code/Services/BusinessPlan/TreeCalcBot.php +++ /dev/null @@ -1,599 +0,0 @@ -validateInput($month, $year); - $this->initializeDate($month, $year); - $this->initFrom = $initFrom; - - // Dependency Injection mit Fallback - $this->repository = $repository ?? new BusinessUserRepository($month, $year); - $this->renderer = $renderer ?? new TreeHtmlRenderer($initFrom); - $this->logger = $logger ?? app(LogContract::class); - } - - /** - * Initialisiert die Business-Struktur für Admin-Ansicht - */ - public function initStructureAdmin(bool $check = true): void - { - try { - $storedStructure = null; - - if ($check) { - $storedStructure = $this->repository->getStoredStructure(); - } - - if ($storedStructure) { - $this->logger->info("Loading stored business structure for {$this->date->month}/{$this->date->year}"); - $this->loadStoredStructure($storedStructure); - } else { - $this->logger->info("Building fresh business structure for {$this->date->month}/{$this->date->year}"); - $this->buildFreshStructure(); - } - - } catch (\Exception $e) { - $this->logger->error("Error initializing admin structure: " . $e->getMessage()); - throw $e; - } - } - - /** - * Initialisiert die Struktur für einen spezifischen User - */ - public function initStructureUser(int $userId): void - { - try { - $this->logger->info("Initializing structure for user: {$userId}"); - - $user = $this->repository->getUserWithRelations($userId); - if (!$user) { - $this->logger->warning("User not found: {$userId}"); - return; - } - - $businessUserItem = new BusinessUserItemOptimized($this->date); - $businessUserItem->makeUserFromModel($user); // ✅ Nutzt bereits geladene Relations - $this->addUserIdToProcessed($userId); - $this->businessUsers[] = $businessUserItem; - - $storedStructure = $this->repository->getStoredStructure(); - if ($storedStructure) { - $this->loadStoredParentsUsers($storedStructure); - if (isset($this->businessUsers[0]) && $this->businessUsers[0]->sponsor) { - $this->loadStoredSponsorUser($this->businessUsers[0]->sponsor->user_id); - } - } else { - $this->loadParentsUsers(); - $this->loadSponsorUser($userId); - } - - } catch (\Exception $e) { - $this->logger->error("Error initializing user structure for {$userId}: " . $e->getMessage()); - throw $e; - } - } - - /** - * Initialisiert detaillierte Business-User-Informationen - */ - public function initBusinesslUserDetail(User $user): void - { - try { - $this->logger->info("Initializing business user details for: {$user->id}"); - - $this->businessUser = new BusinessUserItemOptimized($this->date); - $this->businessUser->makeUserFromModel($user); // ✅ Nutzt bereits User-Objekt - $this->businessUser->checkSponsor($user); - - if (!$this->businessUser->isSave()) { - // Aufbau der Struktur für den User in die unendliche Tiefe - $this->businessUser->readParentsBusinessUsers(); - - // Calculate Points in Lines (optimiert für Memory-Effizienz) - if (count($this->businessUser->businessUserItems) > 0) { - $this->calculateUserPointsOptimized($this->businessUser->businessUserItems, 1); - } - - // Qualifikation nach qual_kp (KundenPoints) und qual_pp (PaylinePoints) - $this->businessUser->calcQualPP(); - } - - } catch (\Exception $e) { - $this->logger->error("Error initializing business user details for {$user->id}: " . $e->getMessage()); - throw $e; - } - } - - /** - * Gibt Growth Bonus zurück (ab Linie 6) - */ - public function getGrowthBonus(): array - { - if (!$this->businessUser || !$this->businessUser->business_lines) { - return []; - } - - if (count($this->businessUser->business_lines) > 6) { - $bLines = $this->businessUser->business_lines->toArray(); - return array_slice($bLines, 6); - } - - return []; - } - - /** - * Gibt Wert für spezifische Linie zurück - */ - public function getKeybyLine(int $line, string $key) - { - if (!$this->businessUser || !$this->businessUser->business_lines) { - return 0; - } - - $bLines = $this->businessUser->business_lines; - if (!isset($bLines[$line])) { - return 0; - } - - $lineData = $bLines[$line]; - - if ($lineData instanceof stdClass) { - return $lineData->{$key} ?? 0; - } - - if (is_array($lineData)) { - return $lineData[$key] ?? 0; - } - - return 0; - } - - /** - * HTML-Rendering Methoden (Delegation an Renderer) - */ - public function makeHtmlTree(): string - { - return $this->renderer->renderTree($this->businessUsers); - } - - public function makeParentlessHtml(): string - { - return $this->renderer->renderParentless($this->parentless); - } - - public function makeSponsorHtml(): string - { - return $this->renderer->renderSponsor($this->sponsor); - } - - /** - * Getter-Methoden (Rückwärtskompatibilität) - */ - public function getItems(): array - { - return $this->businessUsers; - } - - public function isParentless(): bool - { - return !empty($this->parentless); - } - - /** - * Static Methoden (Rückwärtskompatibilität) - */ - public static function isFromStored(int $month, int $year): ?UserBusinessStructure - { - $structure = UserBusinessStructure::where('year', $year) - ->where('month', $month) - ->first(); - - return ($structure && $structure->completed) ? $structure : null; - } - - public static function addUserID(int $id): void - { - // Deprecated: Wird durch Instanz-Methode ersetzt - // Bleibt für Rückwärtskompatibilität erhalten - } - - // ===== Private Methoden ===== - - /** - * Validiert Eingabeparameter - */ - private function validateInput(int $month, int $year): void - { - if ($month < 1 || $month > 12) { - throw new \InvalidArgumentException("Invalid month: {$month}"); - } - - $currentYear = (int) date('Y'); - if ($year < 2020 || $year > $currentYear + 1) { - throw new \InvalidArgumentException("Invalid year: {$year}"); - } - } - - /** - * Initialisiert Datums-Objekt - */ - private function initializeDate(int $month, int $year): void - { - $this->date = new stdClass(); - $date = Carbon::parse($year . '-' . $month . '-1'); - $this->date->month = $month; - $this->date->year = $year; - $this->date->start_date = $date->format('Y-m-d H:i:s'); - $this->date->end_date = $date->endOfMonth()->format('Y-m-d H:i:s'); - } - - /** - * Lädt gespeicherte Struktur - */ - private function loadStoredStructure(UserBusinessStructure $structure): void - { - $this->loadStoredRootUsers($structure); - $this->loadStoredParentsUsers($structure); - $this->loadStoredParentlessUsers($structure); - } - - /** - * Baut frische Struktur auf - */ - private function buildFreshStructure(): void - { - $this->loadRootUsers(); - $this->loadParentsUsers(); - $this->loadParentlessUsers(); - } - - /** - * Lädt Root-Users (optimiert mit Memory-Monitoring) - */ - private function loadRootUsers(): void - { - $startMemory = memory_get_usage(); - $users = $this->repository->getRootUsers(); - - foreach ($users as $user) { - // Memory-Check vor jeder User-Verarbeitung - $this->checkMemoryUsage('loadRootUsers', $user->id); - - $businessUserItem = new BusinessUserItemOptimized($this->date); - $businessUserItem->makeUserFromModel($user); // ✅ Nutzt bereits geladene Relations - $this->addUserIdToProcessed($user->id); - $this->businessUsers[] = $businessUserItem; - } - - $endMemory = memory_get_usage(); - $memoryUsed = $this->formatBytes($endMemory - $startMemory); - - $this->logger->info("Loaded " . count($users) . " root users with optimized relations. Memory used: {$memoryUsed}"); - } - - /** - * Lädt Parent-Users für alle Business-Users - */ - private function loadParentsUsers(): void - { - foreach ($this->businessUsers as $businessUser) { - $businessUser->readParentsBusinessUsers(); - } - } - - /** - * Lädt parentlose Users (Memory-optimiert) - */ - private function loadParentlessUsers(): void - { - $count = 0; - $excludeIds = array_keys($this->processedUserIds); - - foreach ($this->repository->getParentlessUsers($excludeIds) as $user) { - $businessUserItem = new BusinessUserItemOptimized($this->date); - $businessUserItem->makeUserFromModel($user); // ✅ Nutzt bereits geladene Relations - $this->parentless[] = $businessUserItem; - $count++; - } - - $this->logger->info("Loaded {$count} parentless users with optimized relations"); - } - - /** - * Lädt Sponsor für User - */ - private function loadSponsorUser(int $userId): void - { - try { - $sponsorUser = $this->repository->getSponsorForUser($userId); - - if ($sponsorUser) { - $this->sponsor = new BusinessUserItem($this->date); - $this->sponsor->makeUser($sponsorUser->id); - $this->logger->info("Loaded sponsor {$sponsorUser->id} for user {$userId}"); - } - } catch (\Exception $e) { - $this->logger->warning("Could not load sponsor for user {$userId}: " . $e->getMessage()); - } - } - - /** - * Gespeicherte Root-Users laden - */ - private function loadStoredRootUsers(UserBusinessStructure $structure): void - { - if (!$structure->structure) { - return; - } - - foreach ($structure->structure as $obj) { - $businessUserItem = new BusinessUserItem($this->date); - $businessUserItem->makeUser($obj->user_id); - $this->addUserIdToProcessed($obj->user_id); - $this->businessUsers[] = $businessUserItem; - } - } - - /** - * Gespeicherte Parent-Users laden - */ - private function loadStoredParentsUsers(UserBusinessStructure $structure): void - { - foreach ($this->businessUsers as $businessUser) { - $businessUser->readStoredParentsBusinessUsers($structure->structure); - } - } - - /** - * Gespeicherte parentlose Users laden - */ - private function loadStoredParentlessUsers(UserBusinessStructure $structure): void - { - if (!$structure->parentless) { - return; - } - - foreach ($structure->parentless as $obj) { - if (!isset($this->processedUserIds[$obj->user_id])) { - $businessUserItem = new BusinessUserItem($this->date); - $businessUserItem->makeUser($obj->user_id); - $this->parentless[] = $businessUserItem; - } - } - } - - /** - * Gespeicherten Sponsor laden - */ - private function loadStoredSponsorUser(int $userId): void - { - $this->sponsor = new BusinessUserItem($this->date); - $this->sponsor->makeUser($userId); - } - - /** - * Optimierte Punkte-Berechnung (Stack-basiert mit korrekter Depth-First Reihenfolge) - * - * KRITISCH: Stack muss gleiche Reihenfolge wie Original-Rekursion produzieren - * Original: Depth-First Traversierung (erst tief, dann Punkte addieren) - * Stack: Muss umgekehrt arbeiten - erst alle Kinder sammeln, dann von tief zu flach verarbeiten - */ - private function calculateUserPointsOptimized(array $businessUserItems, int $startLine): void - { - $processingStack = []; - $collectionStack = []; // Sammelt Items in korrekter Reihenfolge - - // Phase 1: Sammle alle Items in Depth-First Reihenfolge - foreach ($businessUserItems as $item) { - $collectionStack[] = ['item' => $item, 'line' => $startLine, 'depth' => 0]; - } - - // Expandiere alle Kinder (Depth-First) - $processedItems = []; - while (!empty($collectionStack)) { - $current = array_shift($collectionStack); // FIFO für Breadth-First Sammlung - $item = $current['item']; - $line = $current['line']; - $depth = $current['depth']; - - // Markiere für Verarbeitung (mit Tiefe für spätere Sortierung) - $processingStack[] = [ - 'item' => $item, - 'line' => $line, - 'depth' => $depth, - 'id' => $item->user_id ?? uniqid() - ]; - - // Füge Kinder hinzu (werden später verarbeitet = Depth-First) - if (isset($item->businessUserItems) && count($item->businessUserItems) > 0) { - // Kinder in umgekehrter Reihenfolge hinzufügen für korrekte Stack-Verarbeitung - $children = array_reverse($item->businessUserItems); - foreach ($children as $childItem) { - array_unshift($collectionStack, [ - 'item' => $childItem, - 'line' => $line + 1, - 'depth' => $depth + 1 - ]); - } - } - } - - // Phase 2: Sortiere nach Tiefe (tiefste zuerst, wie bei Rekursion) - usort($processingStack, function($a, $b) { - return $b['depth'] <=> $a['depth']; // Tiefste zuerst - }); - - // Phase 3: Verarbeite in korrekter Reihenfolge (von tief zu flach) - foreach ($processingStack as $current) { - $item = $current['item']; - $line = $current['line']; - - try { - // Business Line initialisieren falls nötig - if (!isset($this->businessUser->business_lines[$line])) { - $obj = new stdClass(); - $obj->points = 0; - $this->businessUser->addBusinessLineToUser($line, $obj); - } - - // Punkte hinzufügen (mit Validierung) - $points = (float) ($item->sales_volume_points_TP_sum ?? 0); - if ($points > 0) { - $this->businessUser->addBusinessLinePoints($line, $points); - $this->businessUser->addTotalTP($points); - } - - $this->logger->debug("Processed user {$current['id']} at line {$line} with {$points} points"); - - } catch (\Exception $e) { - $this->logger->error("Error processing user points for {$current['id']}: " . $e->getMessage()); - } - } - - $this->logger->info("Processed " . count($processingStack) . " business user items in depth-first order"); - } - - /** - * User-ID zu verarbeiteten IDs hinzufügen - */ - private function addUserIdToProcessed(int $id): void - { - $this->processedUserIds[$id] = true; - } - - /** - * Prüft ob User bereits verarbeitet wurde - */ - private function isUserProcessed(int $id): bool - { - return isset($this->processedUserIds[$id]); - } - - /** - * Memory-Monitoring Methoden - */ - private function checkMemoryUsage(string $operation, $identifier = null): void - { - $currentMemory = memory_get_usage(); - $memoryLimit = $this->parseMemoryLimit(ini_get('memory_limit')); - $memoryPercent = ($currentMemory / $memoryLimit) * 100; - - if ($memoryPercent > 80) { - $currentFormatted = $this->formatBytes($currentMemory); - $limitFormatted = $this->formatBytes($memoryLimit); - - $this->logger->warning("High memory usage detected in {$operation}", [ - 'identifier' => $identifier, - 'current_memory' => $currentFormatted, - 'memory_limit' => $limitFormatted, - 'usage_percent' => round($memoryPercent, 2) - ]); - - // Garbage Collection bei hohem Memory-Verbrauch - if ($memoryPercent > 90) { - $this->logger->warning("Critical memory usage - forcing garbage collection"); - gc_collect_cycles(); - } - } - } - - private function parseMemoryLimit(string $limit): int - { - $limit = trim($limit); - $last = strtolower($limit[strlen($limit)-1]); - $number = (int) $limit; - - switch($last) { - case 'g': $number *= 1024; - case 'm': $number *= 1024; - case 'k': $number *= 1024; - } - - return $number; - } - - private function formatBytes(int $bytes, int $precision = 2): string - { - $units = array('B', 'KB', 'MB', 'GB', 'TB'); - - for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) { - $bytes /= 1024; - } - - return round($bytes, $precision) . ' ' . $units[$i]; - } - - /** - * Public Properties für Rückwärtskompatibilität - */ - public function __get(string $name) - { - switch ($name) { - case 'date': - return $this->date; - case 'business_user': - return $this->businessUser; - case 'business_users': - return $this->businessUsers; - case 'parentless': - return $this->parentless; - default: - throw new \InvalidArgumentException("Property {$name} does not exist"); - } - } - - public function __set(string $name, $value) - { - switch ($name) { - case 'business_users': - $this->businessUsers = $value; - break; - case 'parentless': - $this->parentless = $value; - break; - default: - throw new \InvalidArgumentException("Property {$name} cannot be set"); - } - } -} \ No newline at end of file diff --git a/dev/subdomain-optimization/DomainService.php b/dev/subdomain-optimization/DomainService.php deleted file mode 100644 index 3567d642..00000000 --- a/dev/subdomain-optimization/DomainService.php +++ /dev/null @@ -1,272 +0,0 @@ -domainConfig = $this->loadDomainConfiguration(); - } - - /** - * Load domain configuration from config files - */ - private function loadDomainConfiguration(): array - { - return [ - 'main_domain' => config('app.domain'), - 'main_tld' => config('app.tld_care'), - 'shop_tld' => config('app.tld_shop'), - 'protocol' => config('app.protocol'), - 'subdomains' => [ - 'crm' => config('app.pre_url_crm', 'my.'), - 'portal' => config('app.pre_url_portal', 'in.'), - 'checkout' => config('app.pre_url_checkout', 'checkout.'), - ] - ]; - } - - /** - * Determine the type of subdomain - */ - public function getSubdomainType(string $subdomain): string - { - // Check if it's a fixed subdomain - if (in_array($subdomain, self::FIXED_SUBDOMAINS)) { - return match($subdomain) { - 'my' => 'crm', - 'in' => 'portal', - 'checkout' => 'checkout', - default => 'unknown' - }; - } - - // Check if it's a valid user shop - if ($this->isValidUserShop($subdomain)) { - return 'user-shop'; - } - - return 'unknown'; - } - - /** - * Check if a subdomain represents a valid user shop - */ - public function isValidUserShop(string $slug): bool - { - $cacheKey = "user_shop_valid_{$slug}"; - - return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($slug) { - $userShop = UserShop::where('slug', $slug)->first(); - - if (!$userShop) { - return false; - } - - if (!$userShop->active) { - return false; - } - - if (!$userShop->user) { - return false; - } - - if (!$userShop->user->isActiveShop()) { - return false; - } - - return true; - }); - } - - /** - * Get user shop by slug with caching - */ - public function getUserShop(string $slug): ?UserShop - { - if (!$this->isValidUserShop($slug)) { - return null; - } - - $cacheKey = "user_shop_{$slug}"; - - return Cache::remember($cacheKey, self::CACHE_TTL, function () use ($slug) { - return UserShop::where('slug', $slug) - ->with('user') - ->first(); - }); - } - - /** - * Parse domain from request and determine context - */ - public function parseDomain(string $host): array - { - $parts = explode('.', $host); - - // Handle different TLD scenarios - if (count($parts) < 2) { - return [ - 'type' => 'invalid', - 'domain' => $host, - 'subdomain' => null, - 'tld' => null - ]; - } - - // Extract TLD and domain - $tld = '.' . end($parts); - $domain = $parts[count($parts) - 2]; - - // Check for subdomain - $subdomain = null; - if (count($parts) > 2) { - $subdomain = $parts[0]; - } - - // Determine domain type - $type = $this->determineDomainType($domain, $subdomain, $tld); - - return [ - 'type' => $type, - 'domain' => $domain, - 'subdomain' => $subdomain, - 'tld' => $tld, - 'full_domain' => $host - ]; - } - - /** - * Determine domain type based on domain, subdomain, and TLD - */ - private function determineDomainType(string $domain, ?string $subdomain, string $tld): string - { - // Check if it's the main domain - if ($domain === $this->domainConfig['main_domain']) { - if ($subdomain === null) { - // Main domain without subdomain - if ($tld === $this->domainConfig['shop_tld']) { - return 'main-shop'; // mivita.shop - } - return 'main'; // mivita.care - } - - // Main domain with subdomain - return $this->getSubdomainType($subdomain); - } - - return 'unknown'; - } - - /** - * Build URL for specific domain type - */ - public function buildUrl(string $type, ?string $path = null, ?string $slug = null): string - { - $base = $this->domainConfig['protocol']; - - switch ($type) { - case 'main': - $base .= $this->domainConfig['main_domain'] . $this->domainConfig['main_tld']; - break; - - case 'main-shop': - $base .= $this->domainConfig['main_domain'] . $this->domainConfig['shop_tld']; - break; - - case 'crm': - $base .= rtrim($this->domainConfig['subdomains']['crm'], '.') . - $this->domainConfig['main_domain'] . $this->domainConfig['main_tld']; - break; - - case 'portal': - $base .= rtrim($this->domainConfig['subdomains']['portal'], '.') . - $this->domainConfig['main_domain'] . $this->domainConfig['main_tld']; - break; - - case 'checkout': - $base .= rtrim($this->domainConfig['subdomains']['checkout'], '.') . - $this->domainConfig['main_domain'] . $this->domainConfig['main_tld']; - break; - - case 'user-shop': - if (!$slug) { - throw new \InvalidArgumentException('Slug required for user-shop URLs'); - } - $base .= $slug . '.' . $this->domainConfig['main_domain'] . $this->domainConfig['main_tld']; - break; - - default: - throw new \InvalidArgumentException("Unknown domain type: {$type}"); - } - - if ($path) { - $base .= '/' . ltrim($path, '/'); - } - - return $base; - } - - /** - * Get domain configuration - */ - public function getDomainConfiguration(): array - { - return $this->domainConfig; - } - - /** - * Clear user shop cache - */ - public function clearUserShopCache(string $slug): void - { - Cache::forget("user_shop_valid_{$slug}"); - Cache::forget("user_shop_{$slug}"); - } - - /** - * Get default user shop for main domain (fallback) - */ - public function getDefaultUserShop(): ?UserShop - { - return $this->getUserShop('aloevera'); // Current hardcoded fallback - } - - /** - * Validate domain configuration - */ - public function validateConfiguration(): array - { - $errors = []; - - if (empty($this->domainConfig['main_domain'])) { - $errors[] = 'Main domain not configured'; - } - - if (empty($this->domainConfig['main_tld'])) { - $errors[] = 'Main TLD not configured'; - } - - if (empty($this->domainConfig['protocol'])) { - $errors[] = 'Protocol not configured'; - } - - return $errors; - } -} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..7869eac3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,121 @@ +services: + laravel.test: + build: + context: './docker/8.4' + dockerfile: Dockerfile + args: + WWWGROUP: '${WWWGROUP}' + image: 'sail-8.4/app' + extra_hosts: + - 'host.docker.internal:host-gateway' + ports: + # - '${APP_PORT:-80}:80' + - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' + environment: + WWWUSER: '${WWWUSER}' + LARAVEL_SAIL: 1 + XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' + XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' + IGNITION_LOCAL_SITES_PATH: '${PWD}' + volumes: + - '.:/var/www/html' + networks: + - sail + - proxy + depends_on: + - mysql + - redis + - mailpit + labels: + - "traefik.enable=true" + # Hauptdomain + - "traefik.http.routers.mivita.rule=Host(`mivita.test`)" + - "traefik.http.routers.mivita.entrypoints=websecure" + - "traefik.http.routers.mivita.tls=true" + - "traefik.http.routers.mivita.service=mivita-service" + # Wildcard für alle Subdomains - WICHTIG: Gleicher Service! + - "traefik.http.routers.mivita-sub.rule=HostRegexp(`^.+\\.mivita\\.test$`)" + - "traefik.http.routers.mivita-sub.entrypoints=websecure" + - "traefik.http.routers.mivita-sub.tls=true" + - "traefik.http.routers.mivita-sub.service=mivita-service" + - "traefik.http.routers.mivita-sub.priority=10" + # Service Definition - NUR EINMAL! + - "traefik.http.services.mivita-service.loadbalancer.server.port=80" + - "traefik.docker.network=proxy" + horizon: + image: sail-8.4/app + container_name: mivita-horizon-1 + restart: unless-stopped + command: php /var/www/html/artisan horizon + volumes: + - '.:/var/www/html' + networks: + - sail + depends_on: + - mysql + - redis + mysql: + image: 'mysql/mysql-server:8.0' + ports: + - '${FORWARD_DB_PORT:-33061}:3306' + environment: + MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' + MYSQL_ROOT_HOST: '%' + MYSQL_DATABASE: '${DB_DATABASE}' + MYSQL_USER: '${DB_USERNAME}' + MYSQL_PASSWORD: '${DB_PASSWORD}' + MYSQL_ALLOW_EMPTY_PASSWORD: 1 + MYSQL_EXTRA_OPTIONS: '${MYSQL_EXTRA_OPTIONS}' + volumes: + - 'sail-mysql:/var/lib/mysql' + - './docker/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' + networks: + - sail + healthcheck: + test: + - CMD + - mysqladmin + - ping + - '-p${DB_PASSWORD}' + retries: 3 + timeout: 5s + redis: + image: 'redis:alpine' + ports: + - '${FORWARD_REDIS_PORT:-6379}:6379' + volumes: + - 'sail-redis:/data' + networks: + - sail + healthcheck: + test: + - CMD + - redis-cli + - ping + retries: 3 + timeout: 5s + mailpit: + image: 'axllent/mailpit:latest' + ports: + - '${FORWARD_MAILPIT_PORT:-1025}:1025' + - '${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025' + networks: + - sail + - proxy + labels: + - "traefik.enable=true" + - "traefik.http.routers.mivita-mail.rule=Host(`mivita-mail.test`)" + - "traefik.http.routers.mivita-mail.entrypoints=websecure" + - "traefik.http.routers.mivita-mail.tls=true" + - "traefik.http.services.mivita-mail.loadbalancer.server.port=8025" + - "traefik.docker.network=proxy" +networks: + sail: + driver: bridge + proxy: + external: true +volumes: + sail-mysql: + driver: local + sail-redis: + driver: local diff --git a/docker/8.0/Dockerfile b/docker/8.0/Dockerfile new file mode 100644 index 00000000..b7b34e27 --- /dev/null +++ b/docker/8.0/Dockerfile @@ -0,0 +1,70 @@ +FROM ubuntu:24.04 + +LABEL maintainer="Taylor Otwell" + +ARG WWWGROUP +ARG NODE_VERSION=22 +ARG POSTGRES_VERSION=17 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC +ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80" +ENV SUPERVISOR_PHP_USER="sail" + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom + +RUN apt-get update && apt-get upgrade -y \ + && mkdir -p /etc/apt/keyrings \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano \ + && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /usr/share/keyrings/ppa_ondrej_php.gpg > /dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php8.0-cli php8.0-dev \ + php8.0-pgsql php8.0-sqlite3 php8.0-gd php8.0-imagick \ + php8.0-curl php8.0-memcached php8.0-mongodb \ + php8.0-imap php8.0-mysql php8.0-mbstring \ + php8.0-xml php8.0-zip php8.0-bcmath php8.0-soap \ + php8.0-intl php8.0-readline php8.0-pcov \ + php8.0-msgpack php8.0-igbinary php8.0-ldap \ + php8.0-redis php8.0-swoole php8.0-xdebug \ + && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install -y nodejs \ + && npm install -g npm \ + && npm install -g bun \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarnkey.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/pgdg.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y mysql-client \ + && apt-get install -y postgresql-client-$POSTGRES_VERSION \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN update-alternatives --set php /usr/bin/php8.0 + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.0 + +RUN userdel -r ubuntu +RUN groupadd --force -g $WWWGROUP sail +RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +COPY start-container /usr/local/bin/start-container +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY php.ini /etc/php/8.0/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +EXPOSE 80/tcp + +ENTRYPOINT ["start-container"] diff --git a/docker/8.0/php.ini b/docker/8.0/php.ini new file mode 100644 index 00000000..0d8ce9e2 --- /dev/null +++ b/docker/8.0/php.ini @@ -0,0 +1,5 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS +pcov.directory = . diff --git a/docker/8.0/start-container b/docker/8.0/start-container new file mode 100644 index 00000000..40c55dfe --- /dev/null +++ b/docker/8.0/start-container @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then + echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'." + exit 1 +fi + +if [ ! -z "$WWWUSER" ]; then + usermod -u $WWWUSER sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ]; then + if [ "$SUPERVISOR_PHP_USER" = "root" ]; then + exec "$@" + else + exec gosu $WWWUSER "$@" + fi +else + exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/docker/8.0/supervisord.conf b/docker/8.0/supervisord.conf new file mode 100644 index 00000000..656da8a9 --- /dev/null +++ b/docker/8.0/supervisord.conf @@ -0,0 +1,14 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=%(ENV_SUPERVISOR_PHP_COMMAND)s +user=%(ENV_SUPERVISOR_PHP_USER)s +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker/8.1/Dockerfile b/docker/8.1/Dockerfile new file mode 100644 index 00000000..cc5c6114 --- /dev/null +++ b/docker/8.1/Dockerfile @@ -0,0 +1,69 @@ +FROM ubuntu:24.04 + +LABEL maintainer="Taylor Otwell" + +ARG WWWGROUP +ARG NODE_VERSION=22 +ARG POSTGRES_VERSION=17 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC +ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80" +ENV SUPERVISOR_PHP_USER="sail" + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom + +RUN apt-get update && apt-get upgrade -y \ + && mkdir -p /etc/apt/keyrings \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano \ + && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /usr/share/keyrings/ppa_ondrej_php.gpg > /dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php8.1-cli php8.1-dev \ + php8.1-pgsql php8.1-sqlite3 php8.1-gd php8.1-imagick \ + php8.1-curl php8.1-mongodb \ + php8.1-imap php8.1-mysql php8.1-mbstring \ + php8.1-xml php8.1-zip php8.1-bcmath php8.1-soap \ + php8.1-intl php8.1-readline \ + php8.1-ldap \ + php8.1-msgpack php8.1-igbinary php8.1-redis php8.1-swoole \ + php8.1-memcached php8.1-pcov php8.1-xdebug \ + && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install -y nodejs \ + && npm install -g npm \ + && npm install -g bun \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /usr/share/keyrings/yarn.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /usr/share/keyrings/pgdg.gpg >/dev/null \ + && echo "deb [signed-by=/usr/share/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y mysql-client \ + && apt-get install -y postgresql-client-$POSTGRES_VERSION \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.1 + +RUN userdel -r ubuntu +RUN groupadd --force -g $WWWGROUP sail +RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +COPY start-container /usr/local/bin/start-container +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY php.ini /etc/php/8.1/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +EXPOSE 80/tcp + +ENTRYPOINT ["start-container"] diff --git a/docker/8.1/php.ini b/docker/8.1/php.ini new file mode 100644 index 00000000..0d8ce9e2 --- /dev/null +++ b/docker/8.1/php.ini @@ -0,0 +1,5 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS +pcov.directory = . diff --git a/docker/8.1/start-container b/docker/8.1/start-container new file mode 100644 index 00000000..40c55dfe --- /dev/null +++ b/docker/8.1/start-container @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then + echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'." + exit 1 +fi + +if [ ! -z "$WWWUSER" ]; then + usermod -u $WWWUSER sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ]; then + if [ "$SUPERVISOR_PHP_USER" = "root" ]; then + exec "$@" + else + exec gosu $WWWUSER "$@" + fi +else + exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/docker/8.1/supervisord.conf b/docker/8.1/supervisord.conf new file mode 100644 index 00000000..656da8a9 --- /dev/null +++ b/docker/8.1/supervisord.conf @@ -0,0 +1,14 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=%(ENV_SUPERVISOR_PHP_COMMAND)s +user=%(ENV_SUPERVISOR_PHP_USER)s +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker/8.2/Dockerfile b/docker/8.2/Dockerfile new file mode 100644 index 00000000..536dffe1 --- /dev/null +++ b/docker/8.2/Dockerfile @@ -0,0 +1,70 @@ +FROM ubuntu:24.04 + +LABEL maintainer="Taylor Otwell" + +ARG WWWGROUP +ARG NODE_VERSION=22 +ARG POSTGRES_VERSION=17 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC +ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80" +ENV SUPERVISOR_PHP_USER="sail" + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom + +RUN apt-get update && apt-get upgrade -y \ + && mkdir -p /etc/apt/keyrings \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano \ + && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php8.2-cli php8.2-dev \ + php8.2-pgsql php8.2-sqlite3 php8.2-gd php8.2-imagick \ + php8.2-curl php8.2-mongodb \ + php8.2-imap php8.2-mysql php8.2-mbstring \ + php8.2-xml php8.2-zip php8.2-bcmath php8.2-soap \ + php8.2-intl php8.2-readline \ + php8.2-ldap \ + php8.2-msgpack php8.2-igbinary php8.2-redis php8.2-swoole \ + php8.2-memcached php8.2-pcov php8.2-xdebug \ + && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install -y nodejs \ + && npm install -g npm \ + && npm install -g pnpm \ + && npm install -g bun \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y mysql-client \ + && apt-get install -y postgresql-client-$POSTGRES_VERSION \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.2 + +RUN userdel -r ubuntu +RUN groupadd --force -g $WWWGROUP sail +RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +COPY start-container /usr/local/bin/start-container +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY php.ini /etc/php/8.2/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +EXPOSE 80/tcp + +ENTRYPOINT ["start-container"] diff --git a/docker/8.2/php.ini b/docker/8.2/php.ini new file mode 100644 index 00000000..0d8ce9e2 --- /dev/null +++ b/docker/8.2/php.ini @@ -0,0 +1,5 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS +pcov.directory = . diff --git a/docker/8.2/start-container b/docker/8.2/start-container new file mode 100644 index 00000000..40c55dfe --- /dev/null +++ b/docker/8.2/start-container @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then + echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'." + exit 1 +fi + +if [ ! -z "$WWWUSER" ]; then + usermod -u $WWWUSER sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ]; then + if [ "$SUPERVISOR_PHP_USER" = "root" ]; then + exec "$@" + else + exec gosu $WWWUSER "$@" + fi +else + exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/docker/8.2/supervisord.conf b/docker/8.2/supervisord.conf new file mode 100644 index 00000000..656da8a9 --- /dev/null +++ b/docker/8.2/supervisord.conf @@ -0,0 +1,14 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=%(ENV_SUPERVISOR_PHP_COMMAND)s +user=%(ENV_SUPERVISOR_PHP_USER)s +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker/8.3/Dockerfile b/docker/8.3/Dockerfile new file mode 100644 index 00000000..ef5904bb --- /dev/null +++ b/docker/8.3/Dockerfile @@ -0,0 +1,71 @@ +FROM ubuntu:24.04 + +LABEL maintainer="Taylor Otwell" + +ARG WWWGROUP +ARG NODE_VERSION=22 +ARG MYSQL_CLIENT="mysql-client" +ARG POSTGRES_VERSION=17 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC +ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80" +ENV SUPERVISOR_PHP_USER="sail" + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom + +RUN apt-get update && apt-get upgrade -y \ + && mkdir -p /etc/apt/keyrings \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano \ + && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php8.3-cli php8.3-dev \ + php8.3-pgsql php8.3-sqlite3 php8.3-gd \ + php8.3-curl php8.3-mongodb \ + php8.3-imap php8.3-mysql php8.3-mbstring \ + php8.3-xml php8.3-zip php8.3-bcmath php8.3-soap \ + php8.3-intl php8.3-readline \ + php8.3-ldap \ + php8.3-msgpack php8.3-igbinary php8.3-redis \ + php8.3-memcached php8.3-pcov php8.3-imagick php8.3-xdebug php8.3-swoole \ + && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install -y nodejs \ + && npm install -g npm \ + && npm install -g pnpm \ + && npm install -g bun \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y $MYSQL_CLIENT \ + && apt-get install -y postgresql-client-$POSTGRES_VERSION \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.3 + +RUN userdel -r ubuntu +RUN groupadd --force -g $WWWGROUP sail +RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +COPY start-container /usr/local/bin/start-container +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY php.ini /etc/php/8.3/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +EXPOSE 80/tcp + +ENTRYPOINT ["start-container"] diff --git a/docker/8.3/php.ini b/docker/8.3/php.ini new file mode 100644 index 00000000..0d8ce9e2 --- /dev/null +++ b/docker/8.3/php.ini @@ -0,0 +1,5 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS +pcov.directory = . diff --git a/docker/8.3/start-container b/docker/8.3/start-container new file mode 100644 index 00000000..40c55dfe --- /dev/null +++ b/docker/8.3/start-container @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then + echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'." + exit 1 +fi + +if [ ! -z "$WWWUSER" ]; then + usermod -u $WWWUSER sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ]; then + if [ "$SUPERVISOR_PHP_USER" = "root" ]; then + exec "$@" + else + exec gosu $WWWUSER "$@" + fi +else + exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/docker/8.3/supervisord.conf b/docker/8.3/supervisord.conf new file mode 100644 index 00000000..656da8a9 --- /dev/null +++ b/docker/8.3/supervisord.conf @@ -0,0 +1,14 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=%(ENV_SUPERVISOR_PHP_COMMAND)s +user=%(ENV_SUPERVISOR_PHP_USER)s +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker/8.4/Dockerfile b/docker/8.4/Dockerfile new file mode 100644 index 00000000..cb0fbdc1 --- /dev/null +++ b/docker/8.4/Dockerfile @@ -0,0 +1,71 @@ +FROM ubuntu:24.04 + +LABEL maintainer="Taylor Otwell" + +ARG WWWGROUP +ARG NODE_VERSION=22 +ARG MYSQL_CLIENT="mysql-client" +ARG POSTGRES_VERSION=17 + +WORKDIR /var/www/html + +ENV DEBIAN_FRONTEND=noninteractive +ENV TZ=UTC +ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80" +ENV SUPERVISOR_PHP_USER="sail" + +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + +RUN echo "Acquire::http::Pipeline-Depth 0;" > /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::http::No-Cache true;" >> /etc/apt/apt.conf.d/99custom && \ + echo "Acquire::BrokenProxy true;" >> /etc/apt/apt.conf.d/99custom + +RUN apt-get update && apt-get upgrade -y \ + && mkdir -p /etc/apt/keyrings \ + && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python3 dnsutils librsvg2-bin fswatch ffmpeg nano \ + && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xb8dc7e53946656efbce4c1dd71daeaab4ad4cab6' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu noble main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ + && apt-get update \ + && apt-get install -y php8.4-cli php8.4-dev \ + php8.4-pgsql php8.4-sqlite3 php8.4-gd \ + php8.4-curl php8.4-mongodb \ + php8.4-imap php8.4-mysql php8.4-mbstring \ + php8.4-xml php8.4-zip php8.4-bcmath php8.4-soap \ + php8.4-intl php8.4-readline \ + php8.4-ldap \ + php8.4-msgpack php8.4-igbinary php8.4-redis php8.4-swoole \ + php8.4-memcached php8.4-pcov php8.4-imagick php8.4-xdebug \ + && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ + && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ + && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ + && apt-get update \ + && apt-get install -y nodejs \ + && npm install -g npm \ + && npm install -g pnpm \ + && npm install -g bun \ + && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ + && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \ + && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt noble-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ + && apt-get update \ + && apt-get install -y yarn \ + && apt-get install -y $MYSQL_CLIENT \ + && apt-get install -y postgresql-client-$POSTGRES_VERSION \ + && apt-get -y autoremove \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.4 + +RUN userdel -r ubuntu +RUN groupadd --force -g $WWWGROUP sail +RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 sail + +COPY start-container /usr/local/bin/start-container +COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY php.ini /etc/php/8.4/cli/conf.d/99-sail.ini +RUN chmod +x /usr/local/bin/start-container + +EXPOSE 80/tcp + +ENTRYPOINT ["start-container"] diff --git a/docker/8.4/php.ini b/docker/8.4/php.ini new file mode 100644 index 00000000..0d8ce9e2 --- /dev/null +++ b/docker/8.4/php.ini @@ -0,0 +1,5 @@ +[PHP] +post_max_size = 100M +upload_max_filesize = 100M +variables_order = EGPCS +pcov.directory = . diff --git a/docker/8.4/start-container b/docker/8.4/start-container new file mode 100644 index 00000000..40c55dfe --- /dev/null +++ b/docker/8.4/start-container @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "sail" ]; then + echo "You should set SUPERVISOR_PHP_USER to either 'sail' or 'root'." + exit 1 +fi + +if [ ! -z "$WWWUSER" ]; then + usermod -u $WWWUSER sail +fi + +if [ ! -d /.composer ]; then + mkdir /.composer +fi + +chmod -R ugo+rw /.composer + +if [ $# -gt 0 ]; then + if [ "$SUPERVISOR_PHP_USER" = "root" ]; then + exec "$@" + else + exec gosu $WWWUSER "$@" + fi +else + exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf +fi diff --git a/docker/8.4/supervisord.conf b/docker/8.4/supervisord.conf new file mode 100644 index 00000000..656da8a9 --- /dev/null +++ b/docker/8.4/supervisord.conf @@ -0,0 +1,14 @@ +[supervisord] +nodaemon=true +user=root +logfile=/var/log/supervisor/supervisord.log +pidfile=/var/run/supervisord.pid + +[program:php] +command=%(ENV_SUPERVISOR_PHP_COMMAND)s +user=%(ENV_SUPERVISOR_PHP_USER)s +environment=LARAVEL_SAIL="1" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 diff --git a/docker/mariadb/create-testing-database.sh b/docker/mariadb/create-testing-database.sh new file mode 100644 index 00000000..d3b19d90 --- /dev/null +++ b/docker/mariadb/create-testing-database.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +/usr/bin/mariadb --user=root --password="$MYSQL_ROOT_PASSWORD" <<-EOSQL + CREATE DATABASE IF NOT EXISTS testing; + GRANT ALL PRIVILEGES ON \`testing%\`.* TO '$MYSQL_USER'@'%'; +EOSQL diff --git a/docker/mysql/create-testing-database.sh b/docker/mysql/create-testing-database.sh new file mode 100644 index 00000000..aeb1826f --- /dev/null +++ b/docker/mysql/create-testing-database.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +mysql --user=root --password="$MYSQL_ROOT_PASSWORD" <<-EOSQL + CREATE DATABASE IF NOT EXISTS testing; + GRANT ALL PRIVILEGES ON \`testing%\`.* TO '$MYSQL_USER'@'%'; +EOSQL diff --git a/docker/pgsql/create-testing-database.sql b/docker/pgsql/create-testing-database.sql new file mode 100644 index 00000000..d84dc07b --- /dev/null +++ b/docker/pgsql/create-testing-database.sql @@ -0,0 +1,2 @@ +SELECT 'CREATE DATABASE testing' +WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'testing')\gexec diff --git a/mivita.code-workspace b/mivita.code-workspace index 29881eba..362d7c25 100644 --- a/mivita.code-workspace +++ b/mivita.code-workspace @@ -3,8 +3,5 @@ { "path": "." } - ], - "settings": { - "CodeGPT.apiKey": "CodeGPT Plus Beta" - } + ] } \ No newline at end of file diff --git a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000000_create_shipments_table.php b/packages/acme-laravel-dhl/database/migrations/2025_01_01_000000_create_shipments_table.php deleted file mode 100644 index f266ba88..00000000 --- a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000000_create_shipments_table.php +++ /dev/null @@ -1,29 +0,0 @@ -id(); - $t->unsignedBigInteger('order_id')->nullable(); - $t->string('carrier')->default('dhl'); - $t->string('dhl_shipment_no')->nullable()->index(); - $t->string('product_code')->nullable(); - $t->string('billing_number')->nullable(); - $t->decimal('weight_kg', 8, 3)->nullable(); - $t->string('status')->default('created'); - $t->string('label_format')->nullable(); - $t->string('label_path')->nullable(); - $t->json('meta')->nullable(); - $t->timestamps(); - }); - } - public function down(): void - { - Schema::dropIfExists('shipments'); - } -}; diff --git a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000100_create_shipment_labels_table.php b/packages/acme-laravel-dhl/database/migrations/2025_01_01_000100_create_shipment_labels_table.php deleted file mode 100644 index 7f6270a3..00000000 --- a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000100_create_shipment_labels_table.php +++ /dev/null @@ -1,22 +0,0 @@ -id(); - $t->foreignId('shipment_id')->constrained('shipments')->cascadeOnDelete(); - $t->string('format')->default('PDF'); - $t->string('path'); - $t->timestamps(); - }); - } - public function down(): void - { - Schema::dropIfExists('shipment_labels'); - } -}; diff --git a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000200_create_tracking_events_table.php b/packages/acme-laravel-dhl/database/migrations/2025_01_01_000200_create_tracking_events_table.php deleted file mode 100644 index a736351a..00000000 --- a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000200_create_tracking_events_table.php +++ /dev/null @@ -1,24 +0,0 @@ -id(); - $t->foreignId('shipment_id')->constrained('shipments')->cascadeOnDelete(); - $t->string('status_code')->nullable(); - $t->string('status_text')->nullable(); - $t->string('location')->nullable(); - $t->timestamp('event_time')->nullable(); - $t->json('raw')->nullable(); - }); - } - public function down(): void - { - Schema::dropIfExists('tracking_events'); - } -}; diff --git a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000300_create_return_labels_table.php b/packages/acme-laravel-dhl/database/migrations/2025_01_01_000300_create_return_labels_table.php deleted file mode 100644 index 057a2333..00000000 --- a/packages/acme-laravel-dhl/database/migrations/2025_01_01_000300_create_return_labels_table.php +++ /dev/null @@ -1,22 +0,0 @@ -id(); - $t->unsignedBigInteger('order_id')->nullable()->index(); - $t->string('dhl_return_no')->nullable()->index(); - $t->string('label_path')->nullable(); - $t->timestamps(); - }); - } - public function down(): void - { - Schema::dropIfExists('return_labels'); - } -}; diff --git a/packages/acme-laravel-dhl/src/Models/ReturnLabel.php b/packages/acme-laravel-dhl/src/Models/ReturnLabel.php deleted file mode 100644 index 9bf910cc..00000000 --- a/packages/acme-laravel-dhl/src/Models/ReturnLabel.php +++ /dev/null @@ -1,10 +0,0 @@ -belongsTo(Shipment::class); - } -} diff --git a/packages/acme-laravel-dhl/src/Models/TrackingEvent.php b/packages/acme-laravel-dhl/src/Models/TrackingEvent.php deleted file mode 100644 index 925f3f00..00000000 --- a/packages/acme-laravel-dhl/src/Models/TrackingEvent.php +++ /dev/null @@ -1,16 +0,0 @@ - 'array', 'event_time' => 'datetime',]; - public function shipment() - { - return $this->belongsTo(Shipment::class); - } -} diff --git a/packages/laravel-collective-spatie-html-parser/.vscode/settings.json b/packages/laravel-collective-spatie-html-parser/.vscode/settings.json new file mode 100644 index 00000000..6c2ff60b --- /dev/null +++ b/packages/laravel-collective-spatie-html-parser/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "master" + ] +} \ No newline at end of file diff --git a/public/phpinfo.php b/public/phpinfo.php new file mode 100644 index 00000000..d7c34698 --- /dev/null +++ b/public/phpinfo.php @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/resources/lang/en.json b/resources/lang/en.json index 2c84d076..c31a5b05 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -1,6 +1,7 @@ { "MR": "Mr", "MS": "Ms", + "DIV": "Various", "please select": "please choose", "please specify": "Please specify.", "further countries": "more countrys", diff --git a/resources/lang/es.json b/resources/lang/es.json index 7b8a96a4..2920f422 100644 --- a/resources/lang/es.json +++ b/resources/lang/es.json @@ -1,6 +1,7 @@ { "MR": "Sr.", "MS": "Sra.", + "DIV": "Varios", "please select": "seleccione", "please specify": "Especifíquelo.", "further countries": "otros paises", diff --git a/resources/views/admin/business/index.blade.php b/resources/views/admin/business/index.blade.php deleted file mode 100644 index 973b727e..00000000 --- a/resources/views/admin/business/index.blade.php +++ /dev/null @@ -1,109 +0,0 @@ -@extends('layouts.layout-2') - -@section('content') -
| {{__('ID') }} | -{{__('Berater-ID') }} | -{{__('Points')}} | -{{__('Points Shop')}} | -{{__('Gesamt')}} | -{{__('Umsatz')}} | -{{__('Umsatz Shop')}} | -{{__('Gesamt Shop')}} | -{{__('E-Mail')}} | - -{{__('Vorname')}} | -{{__('Nachname')}} | -{{__('Level')}} | -{{__('Mitglied')}} | -
|---|
@if($country->currency_calc) Preis Berechnung automatisch @else Preis manuell - angegeben @endif
-| {{ __('abo.' . $productType . '_product') }} | -- | {{ __('order.unit_price') }} | -
|---|---|---|
|
-
-
-
-
-
-
-
-
-
-
-
- |
-
-
- @if(count($product->images))
-
-
-
-
- {{$product->getLang('name')}}
-
- {!! $product->getLang('copy') !!}
- |
- - - {{ $product->getFormattedPriceWith(\App\Services\UserService::getTaxFree(), false, \App\Services\UserService::$user_country) }} € - - @if(\App\Services\UserService::$user_country && \App\Services\UserService::$user_country->currency) - - {!! $product->getFormattedPriceCurrencyWith(\App\Services\UserService::getTaxFree(), false, \App\Services\UserService::$user_country) !!} - - @endif - | -
{{__('membership.home_copy_last_35', ['days'=>$user->daysActiveAccount(), 'datetime'=>$user->getPaymentAccountDateFormat()])}}
- @else - {{-- 35, 36 --}} - @if($user->daysActiveAccount() == 0) -{{__('membership.home_copy_last_36', ['days'=>$user->daysActiveAccount(), 'datetime'=>$user->getPaymentAccountDateFormat()])}}
- @endif - @elseif($user->daysActiveAccount() < config('mivita.remind_last_days') ) - {{-- 33 --}} -{{__('membership.home_copy_last_34', ['days'=>$user->daysActiveAccount(), 'datetime'=>$user->getPaymentAccountDateFormat()])}}
- @elseif($user->daysActiveAccount() < config('mivita.remind_sec_days')) - {{-- 33 --}} -{{ __('membership.home_copy_SEPA_33', ['price'=> 'von '.$user->payment_order_product->getFormattedPrice().' EUR', 'pay_date'=>Carbon::parse($user->payment_account)->modify('- '.config('mivita.abo_booking_days').' days')->format('d.m.Y')]) }}
- @else -{{ __('membership.home_copy_SEPA_32', ['price'=> 'von '.$user->payment_order_product->getFormattedPrice().' EUR', 'pay_date'=>Carbon::parse($user->payment_account)->modify('- '.config('mivita.abo_booking_days').' days')->format('d.m.Y')]) }}
- @endif -{{__('membership.home_copy_last_33', ['days'=>$user->daysActiveAccount()])}}
- @else - {{-- 32 / 31 --}} -{{__('membership.home_copy_last_31', ['days'=>$user->daysActiveAccount()])}}
- - @endif -|
- -
|
-
{{ __('customer.customer_sovereignty_info1') }}
- -| # | -{{__('tables.date')}} | -{{__('tables.amount')}} | -{{__('tables.status')}} | -{{__('tables.shipping')}} | -{{__('tables.firstname')}} | -{{__('tables.lastname')}} | -{{__('tables.email')}} | -{{__('tables.invoice')}} | -{{__('tables.art')}} | -
|---|---|---|---|---|---|---|---|---|---|
| - - - - | -{{ $shopping_order->created_at->format('d.m.Y') }} | -- - {{ $shopping_order->getFormattedTotalShipping() }} € - - | -{!! \App\Services\Payment::getShoppingOrderBadge($shopping_order) !!} | -- - {{ $shopping_order->getShippedType() }} - - | -{{ $shopping_order->shopping_user->billing_firstname }} | -{{ $shopping_order->shopping_user->billing_lastname }} | -{{ $shopping_order->shopping_user->billing_email }} | -{{ $shopping_order->isInvoice() ? ' - ' : '-'; - }} | -{!! \App\Services\Payment::getPaymentForBadge($shopping_order) !!} | -
| {{ __('order.no_orders_found') }} | -|||||||||
+ Verfolgen Sie den Status Ihrer DHL-Sendung in Echtzeit +
+
+ Probleme bei der Sendungsverfolgung?
+ Kontaktieren Sie uns unter
+ support@mivita.care
+ oder besuchen Sie unsere
+ Kontaktseite.
+
| ID | -{{__('Mail')}} | -{{__('is like')}} | -{{__('OrderID')}} | -{{__('txaction')}} | -{{__('Action')}} | -
|---|---|---|---|---|---|
| {{$shopping_user->id}} | -{{$shopping_user->billing_email}} | -{{$shopping_user->is_like}} | -@if($shopping_user->shopping_order){{$shopping_user->shopping_order->id}}@endif | -@if($shopping_user->shopping_order){{$shopping_user->shopping_order->txaction}}@endif | -- |
| ID | -User-ID | -{{__('Name')}} | -{{__('seit')}} | -Datum | -Erreichbar | -{{__('Status')}} | -
|---|---|---|---|---|---|---|
| {{ $value->id }} | -{{ $value->user_id }} | -{{ $value->name }}.mivita.care | -{{ $value->getActiveDateFormatSmall() }} | -- @if($value->user && $value->user->payment_shop) - @if($value->user->isActiveShop()) - {{ $value->user->getPaymentShopDateFormat() }} - @else - {{ $value->user->getPaymentShopDateFormat() }} - @endif - @else - - @endif - - | -- @if($value->getSubdomainAvailable()) - {{ __('available') }} - @if($value->getSubdomainSslSin()) HTTPS @else HTTP @endif - - @else - {{ __('not available') }} HTTP - @endif - | -{!! get_active_badge($value->active) !!} | -
| {{__('Datei')}}: | -{{ $file }} | -
| {{__('Import Position start')}}: | -{{$skip}} | -
| {{__('Import limit')}}: | -{{ $limit }} | -
{{$value->billing_email}} | {{$value->orders}}
- @endforeach
- | {{__('Vorname')}} | -{{__('Nachname') }} | -{{__('E-Mail') }} | -{{__('Betrag') }} | -{{__('Datum') }} | -{{__('Order')}} | -{{__('Status')}} | -
|---|---|---|---|---|---|---|
| {{ $value->shopping_user->billing_firstname }} | -{{ $value->shopping_user->billing_lastname }} | -{{ $value->shopping_user->billing_email }} | -{{ $value->getFormattedTotalShipping()." €" }} | -{{ $value->created_at->format("d.m.Y") }} | -@foreach($value->shopping_order_items as $shopping_order_item)
- {{ $shopping_order_item->product->name }} - @endforeach - - |
-
- {!! App\Services\Payment::getShoppingOrderBadge($value) !!} | -
| {{ __('tables.product') }} | -@if($yard_shopping_items['tax_free']) - {{ __('tables.net_price') }} - @else - {{ __('tables.price') }} - @endif - | -{{ __('tables.quantity') }} | -{{ __('tables.sum') }} | -
|---|---|---|---|
|
-
- @if($item->image)
-
-
-
- {{ $item->name }}
- {!! get_abo_type_badge($item->abo_type) !!}
-
-
- {{ __('order.content') }}: {{ $item->contents }}
- {{ __('order.art_no') }}: {{ $item->number }}
- |
-
- - @if($yard_shopping_items['tax_free']) - {{ formatNumber($item->price_net, 2) }} € - @else - {{ formatNumber($item->price, 2) }} € - @endif - | -- {{ $item->qty }} - | -- @if($yard_shopping_items['tax_free']) - {{ formatNumber($item->price_net_total, 2) }} € - @else - {{ formatNumber($item->price_total, 2) }} € - @endif - | -
| - {{__('order.subtotal')}} - | -- {{ $yard_shopping_items['total']['subtotal'] }} € - | -||
| - {{__('Delivery country')}} - | -- {{ $yard_shopping_items['total']['shippingCountryName'] }} - | -||
| - {{__('order.shipping_costs')}} - | -- {{ $yard_shopping_items['total']['shippingNet'] }} € - | -||
| - {{__('order.total_without_VAT')}} - | -- {{ $yard_shopping_items['total']['subtotalWithShipping'] }} € - | -||
| - {{__('order.plus_VAT')}} - | -- {{ $yard_shopping_items['total']['taxWithShipping'] }} € - | -||
| - {{__('order.total_net')}} - | -- {{ $yard_shopping_items['total']['totalWithShipping'] }} € - | -||
| - {{__('order.total_net')}} - | -
- {{ $yard_shopping_items['total']['totalWithShipping'] }} €
- - {{__('email.checkout_mail_subtotal_ws')}} - |
- ||
| - {{__('order.total_gross')}} - | -
- {{ $yard_shopping_items['total']['totalWithShipping'] }} €
- - {{__('email.checkout_mail_tax_info')}} - |
- ||
| Produkt | -Preis | -Anzahl | -Summe | -- |
|---|---|---|---|---|
|
-
-
-
-
- |
- - $57.55 - | -- - | -- 115.1 € - | -- × - | -
|
-
-
-
-
- WALKING 400 BLUE CAT3
-
- Ships from: Germany
-
-
- |
- - $20.55 - | -- - | -- $20.55 - | -- × - | -
| {{__('Datum') }} | -{{__('Points')}} | -{{__('Umsatz netto')}} | -{{__('Art')}} | -{{__('Bestellung')}} | -{{__('Info') }} | -
|---|
Sie werden auf unseren checkout Server weitergeletet, die Verbindung ist mit SSL verschlüsselt.
-Alle Preise inkl. gesetzl. Mehrwertsteuer zzgl. Versandkosten, wenn nicht anders beschrieben
- -
- Nesciunt tofu stumptown aliqua, retro synth master cleanse.
-Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. |
- |
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. |
- |
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. |
- |
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. |
- |
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. |
-
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
-
-
- {{ __('website.contact_address') }}
- {{ __('website.phone_number') }}
- {{ __('website.email') }}: {{ __('website.email_address') }}
-
-
-
-
Geschäftsinhaber:
Alois Ried
-
- Registergericht:
Memmingen
-
- Registernummer:
HRA 12236
-
- USt-ID-Nr.:
DE 244162340
Support mivita:
- Telefon: +49 (0) 8333 946 17 67
- E-Mail:: info@mivita.care
Nutzungshinweis:
-
Eine unerlaubte Verwendung, Reproduktion, Weitergabe, Veröffentlichungen oder eine kommerzielle Nutzung ohne Genehmigung des Urhebers der auf dieser Website befindlichen Inhalte ist untersagt und wird sowohl straf- als auch zivilrechtlich verfolgt!
Neben Studenten, Berufseinsteigern, jungen Eltern und alleinerziehenden Müttern bzw. Vätern besteht das MIVITA Vertriebsteam auch aus Unternehmern, die schon vor dem Schritt in den Direktvertrieb ihre Zukunft in die eigenen Hände gelegt haben. So liegt es nahe, dass wir mit diesen Dienstleistern, die unsere Arbeit und den Markt am besten verstehen, auch geschäftlich zusammenarbeiten. Ob Werbemittel wie Autobeschriftung, Flyer, Webdesign, Reisen etc. - wir bauen auch diese Infrastruktur weiter aus, so dass Du Zugriff auf die unterschiedlichsten Dienstleister hast, die Dir maßgeschneidert in Dein eigenes Business helfen.
- -
- Nutze Dein Auto als Werbefläche und mache auf Dich und Dein Produkt aufmerksam. Du möchtest das MIVITA Logo auf Deinem Auto oder hast eine ganz konkrete Vorstellung? Kein Problem. Kontaktiere unseren Vertriebspartner Stefan, der Dich gerne dazu berät:
-
- DV Dienstleistungsservice
- Stefan Del Vecchio
- Steinstraße.33
- 51702 Bergneustadt
-
- DV.Dienstleistungsservice@web.de
- Festnetz: +49 2261 912 36 26
- Mobil: +49 174 525 69 00
-
- Wir legen jedem Berater ans Herz, mit uns gemeinsam die Aloe Vera Schulung auf Mallorca zu erleben. Hierzu haben wir für Euch gemeinsam mit unserem Reise-Portal NETWORKTRIPS und angeschlossenem Reisebüro STERN TOURS in Berlin verschiedene Buchungsmöglichkeiten für
-
- • Nur-Hotel
- • Hotel & Flug
- • Event-Package
-
- vorbereitet. Dieses Portal ist nicht öffentlich und eine Registrierung kann nur über einen Einladungslink erfolgen. Bitte fragt Euren Sponsor oder in einer Eurer WhatsApp Gruppen nach.
-
- NETWORTRIPS
- Ansprechpartner: Thomas Krummel
- www.networktrips.agency
- support@networktrips.agency
- Festnetz: +49 2203 186 90 14
- Mobil: +49 162 251 48 71
-
Die weltweit einmaligen und herausragenden Eigenschaften der Aloe Vera sind dem einzigartigen - Zusammenspiel und der Symbiose der unterschiedlichen Inhalts- und Wirkstoffe zu verdanken. Keine - andere bisher bekannte Pflanze verfügt über derart vielseitige Möglichkeiten der heilenden und - pflegenden Anwendung. Insgesamt sind in der medizinischen Literatur derzeit weit mehr als 250 - aktive Substanzen bekannt, und stetig werden neue entdeckt. Die Entschlüsselung des komplexen - Zusammenspiels aller Substanzen steht zwar erst ganz am Anfang, die Wirkungen sind inzwischen - aber sehr gut belegt.
- - -Von des Deutschen liebster Urlaubsinsel
-Die Farm auf Mallorca hat eine Größe von etwa 40 Hektar. Dort werden die Aloe Vera - Pflanzen gezüchtet und gepflegt. Die 200.000 Pflanzen müssen mindestens 5 Jahre alt - sein, bis die Blätter geerntet werden können. Eine Pflanze benötigt mindestens 2.000 - Sonnenstunden im Jahr, um die wertvollen Nährstoffe für den Saft aufzubauen.
- - -Bio-zertifizierte Handarbeit aus Mallorca<
-Wir garantieren beste Qualität durch manuelle Produktion und biologische Inhaltsstoffe. - Das typische Klima von Mallorca fordert die Pflanzen heraus. Tests haben ergeben, dass - gerade dieses Klima optimal für eine perfekte Entwicklung der Pflanze ist.
- -why is different than any other template
-Sed odio sit amet nibh vulputate cursus a sit amet mauris. Morbi accumsan ipsum velit. Nam - nec tellus a odio tincidunt auctor a ornare odio. Sed non mauris vitae erat consequat auctor - eu in elit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos - himenaeos. Nulla augue justo nibh ac diam.
- -Nullam id dolor id nibh ultricies vehicula ut id - elit. Integer posuere erat a ante venenatis.
-- {{ __('website.sales_partner_or_questions') }} -
- @if(Util::isCheckout()) - @if(isset($order_reference)) -
-
-
-
-
- - {{ __('website.sales_partner_or_questions') }} -
- @if(Util::isCheckout()) - @if(isset($order_reference)) -
-
-
-
-
-
-
-
- @else
-
-
-
-
- @endif
-
- @else
-
- @endif
-
-
-
-
- @endif
-
-
-
- @else
-
-
-
-
- @endif
-
- @else
-
- @endif
-
-
-
-
- @endif
-