madbob/GASdottoNG

View on GitHub
code/app/Services/FastBookingsService.php

Summary

Maintainability
B
6 hrs
Test Coverage
<?php

namespace App\Services;

use Illuminate\Support\Facades\DB;

use App\Movement;
use App\Booking;

class FastBookingsService extends BaseService
{
    private function sumUpProducts($booking, &$datarow)
    {
        /*
            TODO: Nel caso di prenotazioni salvate sarebbe molto più efficiente
            cambiare semplicemente lo stato della prenotazione stessa, giacché
            tutte le quantità sono già al loro posto. Ma servirebbe comunque una
            funzione che gestisca questo caso speciale, con tutte le conseguenze
            (e.g. gestire la registrazione del movimento contabile di pagamento)
        */
        if ($booking->status == 'pending') {
            $quantity_attribute = 'true_quantity';
        }
        else {
            $quantity_attribute = 'true_delivered';
        }

        foreach($booking->products_with_friends as $booked) {
            $product_id = $booked->product_id;

            if ($booked->variants->isEmpty() == false) {
                if (isset($datarow['variant_quantity_' . $product_id]) == false) {
                    $datarow['variant_quantity_' . $product_id] = [];
                }

                foreach($booked->variants as $bpv) {
                    $combo = $bpv->variantsCombo();

                    foreach ($combo->values as $val) {
                        $variant_id = $val->variant->id;

                        if (isset($datarow['variant_selection_' . $variant_id]) == false) {
                            $datarow['variant_selection_' . $variant_id] = [];
                        }

                        $datarow['variant_selection_' . $variant_id][] = $val->id;
                    }

                    $datarow['variant_quantity_' . $product_id][] = $bpv->$quantity_attribute;
                }
            }
            else {
                if (isset($datarow[$booked->product_id]) == false) {
                    $datarow[$booked->product_id] = 0;
                }

                $datarow[$booked->product_id] += $booked->$quantity_attribute;
            }
        }
    }

    /*
        Se definito, $users è un array associativo che contiene come chiavi gli
        ID degli utenti le cui prenotazioni sono da consegnare e come valori gli
        identificativi per i relativi metodi di pagamento di usare.
        Se viene lasciato a NULL, tutte le prenotazioni sono consegnate con il
        metodo di pagamento di default
    */
    public function fastShipping($deliverer, $aggregate, $users = null)
    {
        DB::beginTransaction();

        $service = app()->make('BookingsService');

        $default_payment_method = defaultPaymentByType('booking-payment');
        $bookings = $aggregate->bookings;

        if ($users) {
            $users_ids = array_keys($users);
            $bookings = array_filter($bookings, function($booking) use ($users_ids) {
                return in_array($booking->user->id, $users_ids);
            });
        }

        foreach ($bookings as $booking) {
            $grand_total = 0;

            foreach ($booking->bookings as $book) {
                $datarow = [
                    'action' => 'shipped',
                ];

                $this->sumUpProducts($book, $datarow);
                $shipped_booking = $service->handleBookingUpdate($datarow, $deliverer, $book->order, $booking->user, true);

                /*
                    Qui forzo la rilettura della prenotazione direttamente dal
                    DB, essendo stati i prodotti referenziati nella prenotazione
                    manipolati da handleBookingUpdate() in modi impredicibili
                */
                $shipped_booking = Booking::find($shipped_booking->id);

                $grand_total += $shipped_booking->getValue('effective', true, true);
            }

            if ($grand_total != 0) {
                $booking->generateReceipt();

                $meta = $users[$booking->user->id] ?? [
                    'date' => date('Y-m-d'),
                    'method' => $default_payment_method,
                ];

                $movement = Movement::generate('booking-payment', $booking->user, $aggregate, $grand_total);
                $movement->method = $meta['method'];
                $movement->date = $meta['date'];
                $movement->save();
            }
        }

        unset($bookings);
        DB::commit();
    }
}