madbob/GASdottoNG

View on GitHub
code/app/BookedProductVariant.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;

use App\Models\Concerns\LeafReducibleTrait;

class BookedProductVariant extends Model
{
    use GASModel, LeafReducibleTrait, Cachable;

    public function product(): BelongsTo
    {
        return $this->belongsTo(BookedProduct::class, 'product_id');
    }

    public function components(): HasMany
    {
        return $this->hasMany(BookedProductComponent::class, 'productvariant_id')->with(['value']);
    }

    public function getStatusAttribute()
    {
        return $this->product->status;
    }

    public function hasCombination($variant_id, $value_id)
    {
        $components = $this->components;

        foreach ($components as $c) {
            if ($c->variant_id == $variant_id && $c->value_id == $value_id) {
                return true;
            }
        }

        return false;
    }

    public function variantsCombo()
    {
        $values = [];

        foreach ($this->components as $c) {
            $values[] = $c->value_id;
        }

        sort($values);
        $myid = join(' ', $values);

        return $this->product->product->variantCombos->first(function($v) use ($myid) {
            return $v->innerIdentifier() == $myid;
        });
    }

    public function unitPrice($rectify = true)
    {
        $combo = $this->variantsCombo();

        if ($combo) {
            return $combo->getPrice($rectify);
        }
        else {
            return $this->product->product->getPrice($rectify);
        }
    }

    public function fixWeight($attribute)
    {
        $base = $this->product->basicWeight($attribute);

        $combo = $this->variantsCombo();
        if ($combo) {
            $base += $combo->weight_offset * $this->$attribute;
        }

        return $base;
    }

    private function fixQuantity($attribute, $rectify)
    {
        return $this->unitPrice($rectify) * $this->$attribute;
    }

    public function quantityValue()
    {
        return $this->fixQuantity('quantity', true);
    }

    public function deliveredValue()
    {
        return $this->fixQuantity('delivered', false);
    }

    public function printableName()
    {
        $combo = $this->variantsCombo();
        if ($combo) {
            return $combo->printableShortName();
        }
        else {
            return '';
        }
    }

    private function normalizeQuantity($attribute)
    {
        $product = $this->product->product;
        if ($product->portion_quantity != 0)
            return $this->$attribute * $product->portion_quantity;
        else
            return $this->$attribute;
    }

    public function getTrueQuantityAttribute()
    {
        return $this->normalizeQuantity('quantity');
    }

    public function getTrueDeliveredAttribute()
    {
        return $this->normalizeQuantity('delivered');
    }

    public function getSupplierCodeAttribute()
    {
        $combo = $this->variantsCombo();
        if ($combo) {
            return $combo->code;
        }
        else {
            return '';
        }
    }

    /********************************************************* ReducibleTrait */

    protected function reduxBehaviour()
    {
        /*
            Essendo la variante prenotata la foglia piĆ¹ estrema dell'albero di
            riduzione, questa funzione non dovrebbe mai essere chiamata
        */
        throw new \Exception("Invocata funzione reduxBehaviour() su BookedProductVariant", 1);
    }

    public function reduxData($filters = null)
    {
        $ret = (object) [
            'id' => $this->printableName(),
            'variant' => $this,

            'relative_price' => 0,
            'relative_weight' => 0,
            'relative_quantity' => 0,
            'relative_pieces' => 0,
        ];

        $ret = $this->describingAttributesMerge($ret, (object) [
            'price' => $this->quantityValue(),
            'weight' => $this->fixWeight('quantity'),
            'quantity' => $this->product->product->portion_quantity > 0 ? $this->quantity * $this->product->product->portion_quantity : $this->quantity,
            'quantity_pieces' => $this->quantity,
            'price_delivered' => $this->deliveredValue(),
            'weight_delivered' => $this->fixWeight('delivered'),
            'delivered' => $this->delivered,

            /*
                Cfr. nota in BookedProduct
            */
            'delivered_pieces' => $this->delivered,
        ]);

        return $this->relativeRedux($ret);
    }
}