HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/farmfun/reserveren.farmfun.be/app/Komma/Reservations/ReservationService.php
<?php

namespace App\Komma\Reservations;

use App\Komma\Base\Service;
use App\Komma\Locations\Models\Location;
use App\Komma\Orders\Models\Order;
use App\Komma\Reservations\Models\RequestedProgram;
use App\Komma\Reservations\Models\Reservation;
use App\Komma\Reservations\Models\ReservationItem;
use App\Komma\ShoppingCart\Interfaces\ShoppingCartInterface;
use App\Mail\ClientAlmostReadyMail;
use App\Mail\ClientFavourMail;
use App\Mail\ClientInformationMail;
use App\Mail\ClientReminderMail;
use App\Mail\ClientReminderSimpleMail;
use App\Mail\LocationDayPlanMail;
use App\Mail\ProgramReminderMail;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\URL;

class ReservationService extends Service
{
    /**
     * Create reservation out of the shopping cart and order
     *
     * @param ShoppingCartInterface $shoppingCart
     * @param Order $order
     * @return Reservation
     */
    public function createReservation(ShoppingCartInterface $shoppingCart, Order $order): Reservation
    {
        $reservation = null;

        \DB::transaction(function () use ($shoppingCart, $order, &$reservation) {
            /** @var Reservation $reservation */
            $reservation = new Reservation();
            $reservation->order_id = $order->id;
            $reservation->reservation_number = $order->order_reservation_number;
            $reservation->po_number = $order->po_number;
            $reservation->status = Reservation::STATUS_NEW;
            $reservation->date = $shoppingCart->getDate();
            $reservation->location_id = $shoppingCart->getLocation()->id;

            $reservation->company_name = $order->company_name;
            $reservation->first_name = $order->first_name;
            $reservation->name_preposition = $order->name_preposition;
            $reservation->last_name = $order->last_name;
            $reservation->email = $order->email;
            $reservation->phone = $order->phone;
            $reservation->remarks = $order->remarks;

            $reservation->save();

            //Loop over all shopping cart items and create reservation items for them.
            foreach ($shoppingCart->getItems() as $shoppingCartItem) {
                $timeSlot = $shoppingCartItem->getSelectedTimeSlot();
                $product = $shoppingCartItem->getProduct();

                $reservationItem = new ReservationItem([
                    'date' => $shoppingCart->getDate(),
                    'location_id' => $shoppingCartItem->getLocation()->id,
                    'start_time' => isset($timeSlot->start) ? $timeSlot->start->format('H:i:s') : null,
                    'end_time' => isset($timeSlot->end) ? $timeSlot->end->format('H:i:s') : null,
                    'product_id' => $product->id,
                    'quantity' => (isset($shoppingCartItem->amountOfPersons) ? $shoppingCartItem->amountOfPersons : 1), // If amount of persons is undefined, it has a fixed amount like Bumperball
                    'remarks' => $shoppingCartItem->notification,

                    'price_each_unit' => $product->price_each_unit,
                    'price_start_up' => $product->price_start_up,
                    'price_total' => $shoppingCartItem->getTotal(true, false),
                ]);

                $reservation->items()->save($reservationItem);
            }
        });

        return $reservation;
    }

    public function previewClientReminder()
    {
        $reservation = Reservation::withTrashed()
            ->where('id', 19)
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->first();

        return new ClientReminderMail($reservation);
    }

    public function previewLocationDayPlan()
    {
        $date = Carbon::create(2020, 3, 7);

//        $this->sendDayPlansToLocations($date);

        $reservations = Reservation::with('items', 'items.product', 'items.product.translation')
            ->where('location_id', '1')
            ->get();

        $location = Location::with('translation')
            ->has('translation')
            ->where('id', 1)
            ->first();

        return new LocationDayPlanMail($location, $reservations, $date);
    }

    /**
     * Send the day plans to the location if there are reservation for the given date.
     * Will be used
     *
     * @param Carbon $date
     */
    public function sendDayPlansToLocations(Carbon $date)
    {
        $reservationsGroupByLocation = Reservation::where('date', $date->format('Y-m-d'))
            ->with('items', 'items.product', 'items.product.translation')
            ->get()
            ->groupBy('location_id');

        if ($reservationsGroupByLocation->count() == 0) {
            Log::channel('daily')->info(self::class . ': No day plan mail has been sent.');

//            Log::info(self::class.': No day plan mail has been sent.');
            return;
        }

        foreach ($reservationsGroupByLocation as $locationId => $reservations) {

            try {
                $location = Location::with('translation')
                    ->has('translation')
                    ->where('id', $locationId)
                    ->first();

                Mail::to($location->email)->send(new LocationDayPlanMail($location, $reservations, $date));
                Log::channel('daily')->info(self::class . ': ' . $location->translation->name . ' day plan has been send for ' . $reservations->count() . ' reservation.');

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }
    }

    /**
     * Send the client reminders by looking up the amount of days before we send the mails and add it to the given date as range indication.
     * Then send all the reservation which haven't been sent and are within the range.
     *
     * @param Carbon $date
     */
    public function sendClientReminders(Carbon $date)
    {
        $dateOfSendsReminderMails = clone $date;
        $dateOfSendsReminderMails = $dateOfSendsReminderMails->addDays(config('site.send_client_reminder_days'))->startOfDay();

        $reservationsToSend = Reservation::where('date', '<=', $dateOfSendsReminderMails)
            ->where('email', '!=', '')
            ->where(function ($query) {
                $query->where('client_reminder_sent', '!=', 1)
                    ->orWhereNull('client_reminder_sent');
            })
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->get();

        if ($reservationsToSend->count() == 0) {
            Log::channel('daily')->info(self::class . ': No client reminders mail has been sent.');

            return;
        }

        $sendCounter = 0;

        foreach ($reservationsToSend as $reservation) {

            try {
                Mail::to($reservation->email)->send(new ClientReminderMail($reservation));
                $reservation->client_reminder_sent = true;
                $reservation->save();

                $sendCounter++;

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }

        }

        Log::channel('daily')->info(self::class . ': ' . $sendCounter . ' client reminders mails have been sent.');
    }

    public function sendClientInformation(Carbon $date)
    {
        $dateOfSendsInformationMails = clone $date;
        $dateOfSendsInformationMails = $dateOfSendsInformationMails->subDays(config('site.send_client_information_days'))->startOfDay();

        $reservationsToSend = Reservation::query()
            ->where('created_at', '<=', $dateOfSendsInformationMails)
            ->where('email', '!=', '')
            ->where(function ($query) {
                $query->where('client_information_sent', '!=', 1)
                    ->orWhereNull('client_information_sent');
            })
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->orderByDesc('created_at')
            ->get();

        if ($reservationsToSend->count() == 0) {
            Log::channel('daily')->info(self::class . ': No client information mail has been sent.');

            return;
        }

        $sendCounter = 0;

        foreach ($reservationsToSend as $reservation) {

            try {
                Mail::to($reservation->email)->send(new ClientInformationMail($reservation));
                $reservation->client_information_sent = true;
                $reservation->save();

                $sendCounter++;

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }

        Log::channel('daily')->info(self::class . ': ' . $sendCounter . ' client information mails have been sent.');
    }

    public function sendClientSimpleReminders(Carbon $date)
    {
        $dateOfSendsReminderMails = clone $date;
        $dateOfSendsReminderMails = $dateOfSendsReminderMails->addDays(config('site.send_client_reminder_simple_days'))->startOfDay();

        $reservationsToSend = Reservation::where('date', '<=', $dateOfSendsReminderMails)
            ->where('email', '!=', '')
            ->where(function ($query) {
                $query->where('client_simple_reminder_sent', '!=', 1)
                    ->orWhereNull('client_simple_reminder_sent');
            })
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->get();

        if ($reservationsToSend->count() == 0) {
            Log::channel('daily')->info(self::class . ': No client simple reminders mail has been sent.');

            return;
        }

        $sendCounter = 0;

        foreach ($reservationsToSend as $reservation) {

            try {
                Mail::to($reservation->email)->send(new ClientReminderSimpleMail($reservation));
                $reservation->client_simple_reminder_sent = true;
                $reservation->save();

                $sendCounter++;

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }

        Log::channel('daily')->info(self::class . ': ' . $sendCounter . ' client simple reminders mails have been sent.');
    }

    public function sendClientAlmostReady(Carbon $date)
    {
        $dateOfSendsAlmostReadyMails = clone $date;
        $dateOfSendsAlmostReadyMails = $dateOfSendsAlmostReadyMails->addDays(config('site.send_client_almost_ready_days'))->startOfDay();

        $reservationsToSend = Reservation::where('date', '<=', $dateOfSendsAlmostReadyMails)
            ->where('email', '!=', '')
            ->where(function ($query) {
                $query->where('client_almost_ready_sent', '!=', 1)
                    ->orWhereNull('client_almost_ready_sent');
            })
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->get();

        if ($reservationsToSend->count() == 0) {
            Log::channel('daily')->info(self::class . ': No client almost ready mail has been sent.');

            return;
        }

        $sendCounter = 0;

        foreach ($reservationsToSend as $reservation) {

            try {
                Mail::to($reservation->email)->send(new ClientAlmostReadyMail($reservation));
                $reservation->client_almost_ready_sent = true;
                $reservation->save();

                $sendCounter++;

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }

        Log::channel('daily')->info(self::class . ': ' . $sendCounter . ' client almost ready mails have been sent.');
    }

    public function sendClientFavour(Carbon $date)
    {
        $dateOfSendsFavourMails = clone $date;
        $dateOfSendsFavourMails = $dateOfSendsFavourMails->addDays(config('site.send_client_favour_days'))->startOfDay();

        $reservationsToSend = Reservation::where('date', '<=', $dateOfSendsFavourMails)
            ->where('email', '!=', '')
            ->where(function ($query) {
                $query->where('client_favour_sent', '!=', 1)
                    ->orWhereNull('client_favour_sent');
            })
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->get();

        if ($reservationsToSend->count() == 0) {
            Log::channel('daily')->info(self::class . ': No client favour mail has been sent.');

            return;
        }

        $sendCounter = 0;

        foreach ($reservationsToSend as $reservation) {

            try {
                Mail::to($reservation->email)->send(new ClientFavourMail($reservation));
                $reservation->client_favour_sent = true;
                $reservation->save();

                $sendCounter++;

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }

        Log::channel('daily')->info(self::class . ': ' . $sendCounter . ' client favour mails have been sent.');
    }

    /**
     * Send the client program reminders.
     *
     * @param Carbon $date
     */
    public function sendProgramReminders(Carbon $date)
    {
        $date = today()->subDays(config('site.send_program_reminder_days'));

        $remindersToSend = RequestedProgram::where('created_at', '<=', $date)
            ->where('reminded', 0)
            ->get();

        if ($remindersToSend->count() == 0) {
            Log::channel('daily')->info(self::class . ': No program reminders mail has been sent.');

            return;
        }

        foreach ($remindersToSend as $reminder) {

            try {

                $reservationWithSameMailCreatedAfterDay = Reservation::where('email', $reminder->email)->where('created_at', '>=', $reminder->created_at->startOfDay())->count();

                // If no reservation is found, send reminder mail
                if ($reservationWithSameMailCreatedAfterDay === 0) {
                    Mail::to($reminder->email)->send(new ProgramReminderMail($reminder));
                }

                // Set as reminded
                $reminder->reminded = true;
                $reminder->reminded_date = now();
                $reminder->save();

            } catch (\Exception $e) {
                Log::warning($e->getMessage());
            }
        }

        Log::channel('daily')->info(self::class . ': ' . $remindersToSend->count() . ' program reminders mails have been sent.');
    }

    public function previewChangeReservation()
    {
        $reservation = Reservation::withTrashed()
            ->with('items', 'items.product', 'items.product.translation', 'location')
            ->get()
            ->random(1)
            ->first();

        $url = URL::signedRoute('reservation.change', ['reservation' => $reservation->id]);
        echo '<a target="_blank" href="' . $url . '">Wijzig reservering #' . $reservation->id . '</a>';
    }
}