madbob/GASdottoNG

View on GitHub
code/app/Supplier.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Collection;
use GeneaLabs\LaravelModelCaching\Traits\Cachable;

use Auth;
use URL;

use App\Models\Concerns\AttachableTrait;
use App\Models\Concerns\ContactableTrait;
use App\Models\Concerns\PayableTrait;
use App\Models\Concerns\CreditableTrait;
use App\Models\Concerns\ExportableTrait;
use App\Models\Concerns\SuspendableTrait;
use App\Models\Concerns\ModifiableTrait;
use App\Models\Concerns\TracksUpdater;
use App\Models\Concerns\WithinGas;
use App\Events\SluggableCreating;
use App\Events\AttachableToGas;

class Supplier extends Model
{
    use HasFactory, Notifiable, SoftDeletes, TracksUpdater,
        AttachableTrait, ContactableTrait, CreditableTrait, PayableTrait, ExportableTrait, SuspendableTrait, ModifiableTrait,
        GASModel, SluggableID, WithinGas, Cachable;

    public $incrementing = false;
    protected $keyType = 'string';

    protected $dispatchesEvents = [
        'creating' => SluggableCreating::class,
        'created' => AttachableToGas::class,
    ];

    protected static function boot()
    {
        parent::boot();
        static::initTrackingEvents();
    }

    public static function commonClassName()
    {
        return _i('Fornitore');
    }

    public function products(): HasMany
    {
        return $this->hasMany('App\Product')->with('measure');
    }

    public function orders(): HasMany
    {
        return $this->hasMany('App\Order')->orderBy('end', 'asc');
    }

    public function bookings(): HasManyThrough
    {
        return $this->hasManyThrough('App\Booking', 'App\Order');
    }

    public function invoices(): HasMany
    {
        return $this->hasMany('App\Invoice');
    }

    public function calendarDates(): MorphMany
    {
        return $this->morphMany('App\Date', 'target')->orderBy('date', 'asc');
    }

    public function scopeFilterEnabled($query)
    {
        $user = Auth::user();
        if ($user->can('supplier.add', $user->gas))
            return $query->withTrashed();
        else
            return $query;
    }

    public function getActiveOrdersAttribute()
    {
        return $this->orders()->whereNotIn('status', ['shipped', 'archived'])->get();
    }

    public function involvedEmails()
    {
        $contacts = $this->contacts()->where('type', 'email')->get();

        $users = everybodyCan('supplier.modify', $this);
        foreach($users as $u) {
            $contacts = $contacts->merge($u->contacts()->where('type', 'email')->get());
        }

        return $contacts;
    }

    /******************************************************** AttachableTrait */

    protected function requiredAttachmentPermission()
    {
        return 'supplier.modify';
    }

    protected function defaultAttachments()
    {
        $cataloguepdf = new Attachment();
        $cataloguepdf->name = _i('Listino PDF (autogenerato)');
        $cataloguepdf->url = route('suppliers.catalogue', ['id' => $this->id, 'format' => 'pdf']);
        $cataloguepdf->internal = true;

        $cataloguecsv = new Attachment();
        $cataloguecsv->name = _i('Listino CSV (autogenerato)');
        $cataloguecsv->url = route('suppliers.catalogue', ['id' => $this->id, 'format' => 'csv']);
        $cataloguecsv->internal = true;

        return [$cataloguepdf, $cataloguecsv];
    }

    /*********************************************************** PayableTrait */

    private function innerQuery($query, $direction, $supplier, $with_invoices)
    {
        $type = $direction . '_type';
        $id = $direction . '_id';

        $query->where(function($query) use ($supplier, $type, $id, $with_invoices) {
            $query->where(function($query) use ($supplier, $type, $id) {
                $query->where($type, 'App\Supplier')->where($id, $supplier->id);
            })->orWhere(function($query) use ($supplier, $type, $id) {
                $query->where($type, 'App\Order')->whereIn($id, $supplier->orders()->pluck('orders.id'));
            })->orWhere(function($query) use ($supplier, $type, $id) {
                $query->where($type, 'App\Booking')->whereIn($id, $supplier->bookings()->pluck('bookings.id'));
            });

            if ($with_invoices) {
                $query->orWhere(function($query) use ($supplier, $type, $id) {
                    $query->where($type, 'App\Invoice')->whereIn($id, $supplier->invoices()->pluck('invoices.id'));
                });
            }
        });
    }

    public function queryMovements($query = null, $type = 'all')
    {
        if (is_null($query)) {
            $query = Movement::orderBy('created_at', 'desc');
        }

        $supplier = $this;

        switch($type) {
            case 'all':
                $query->where(function($query) use ($supplier) {
                    $query->where(function($query) use ($supplier) {
                        $this->innerQuery($query, 'sender', $supplier, true);
                    })->orWhere(function($query) use ($supplier) {
                        $this->innerQuery($query, 'target', $supplier, true);
                    });
                });
                break;

            case 'invoices':
                $invoices = $supplier->invoices()->pluck('invoices.id');

                $query->where(function($query) use ($invoices) {
                    $query->where('sender_type', 'App\Invoice')->whereIn('sender_id', $invoices);
                })->orWhere(function($query) use ($invoices) {
                    $query->where('target_type', 'App\Invoice')->whereIn('target_id', $invoices);
                });

                break;

            case 'sender':
                $this->innerQuery($query, 'sender', $supplier, false);
                break;

            case 'target':
                $this->innerQuery($query, 'target', $supplier, false);
                break;
        }

        return $query;
    }

    /******************************************************** CreditableTrait */

    public function balanceFields()
    {
        return [
            'bank' => _i('Ordini'),
        ];
    }

    /******************************************************** ExportableTrait */

    public function exportXML()
    {
        return view('gdxp.xml.supplier', ['obj' => $this])->render();
    }

    public function exportJSON()
    {
        return view('gdxp.json.supplier', ['obj' => $this])->render();
    }
}