<?php namespace App\Models; use Carbon\Carbon; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Leenooks\Traits\ScopeActive; use App\Models\Scopes\SiteScope; use App\Models\Supplier\{Broadband,Domain,Email,Ethernet,Generic,Host,HSPA,Phone,SSL,Type}; class Supplier extends Model { /** * The offerings types we provide */ private const offering_types = [ 'broadband' => Broadband::class, 'hspa' => HSPA::class, 'ethernet' => Ethernet::class, 'domainname' => Domain::class, 'email' => Email::class, 'generic' => Generic::class, 'hosting' => Host::class, 'phone' => Phone::class, 'ssl' => SSL::class, ]; use ScopeActive; public $timestamps = FALSE; /* STATIC METHODS */ /** * Return the offerings that this supplier provides * * @param Supplier|null $so * @return Collection */ public static function offeringTypes(self $so=NULL): Collection { $result = collect(); foreach (self::offering_types as $type) { $class = new $type; if ($so) { // If we have a connections configuration for that supplier, then build the child relationships if (Arr::get($so->detail->connections,$class->category)) { $result->put($class->category,(object)[ 'type' => $class->category_name, 'items' => $class->where('supplier_detail_id',$so->detail->id), ]); continue; } // Even if we dont have any connections, see if we have any products defined $o = new $class; $o->where('supplier_detail_id',$so->detail->id); if ($o->count()) $result->put($class->category,(object)[ 'type' => $class->category_name, 'items' => $class->where('supplier_detail_id',$so->detail->id), ]); } else { $result->put($class->category_name,$class); } } return $result; } /** * Return a new model object for the offering type * * @param string $type * @return Type */ public static function offeringTypeClass(string $type): Type { return ($class=collect(self::offering_types)->get($type)) ? new $class : new Generic; } /** * Return our supported offering type keys * * @return Collection */ public static function offeringTypeKeys(): Collection { return collect(self::offering_types)->keys(); } /* RELATIONS */ /** * Supplier Detail Configuration * * @return \Illuminate\Database\Eloquent\Relations\HasOne */ public function detail() { return $this->hasOne(SupplierDetail::class) ->withoutGlobalScope(SiteScope::class); } public function users() { return $this->belongsToMany(User::class) ->withPivot('id','created_at'); } /* METHODS */ public function api_class(): ?string { return config('services.supplier.'.strtolower($this->name).'.api'); } private function api_key(): string { return Arr::get($this->detail->connections,'api_key'); } private function api_secret(): string { return Arr::get($this->detail->connections,'api_secret'); } public function API(bool $forceprod=FALSE): mixed { return $this->hasAPIdetails() ? new ($this->api_class())($this->api_key(),$this->api_secret(),$forceprod) : NULL; } /** * Do we have API details for this supplier * * @return bool */ public function hasAPIdetails(): bool { return $this->api_class() && (collect(['api_key','api_secret'])->diff($this->detail->connections->keys())->count() === 0); } /** * If this supplier has a domain registrar, return it. * * @return DomainRegistrar|null */ public function registrar(): ?DomainRegistrar { return ($x=config('services.supplier.'.strtolower($this->name).'.registrar')) ? DomainRegistrar::where('name',$x)->single() : NULL; } /** * Return the traffic records, that were not matched to a service. * * @param Carbon $date * @return \Illuminate\Database\Eloquent\Collection */ public function trafficMismatch(Carbon $date): Collection { return Usage\Broadband::where('date',$date->format('Y-m-d')) ->where('supplier_id',$this->id) ->whereNULL('service_item_id') ->get(); } }