Enable editing of supplier products and listing services connected to them
This commit is contained in:
@@ -183,11 +183,10 @@ class Product extends Model implements IDs
|
||||
* Return the type of service is provided. eg: Broadband, Phone.
|
||||
*
|
||||
* @return string
|
||||
* @todo Does type need to be a mandatory attribute on a model - then we can remove this condition
|
||||
*/
|
||||
public function getCategoryAttribute(): string
|
||||
{
|
||||
return $this->type ? $this->type->getCategoryAttribute() : 'generic';
|
||||
return $this->supplied->getCategoryAttribute();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,11 +194,10 @@ class Product extends Model implements IDs
|
||||
* other logic of these types.
|
||||
*
|
||||
* @return string
|
||||
* @todo Does type need to be a mandatory attribute on a model - then we can remove this condition
|
||||
*/
|
||||
public function getCategoryNameAttribute(): string
|
||||
{
|
||||
return $this->type ? $this->type->getCategoryNameAttribute() : 'Generic';
|
||||
return $this->supplied->getCategoryNameAttribute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -15,8 +15,6 @@ final class Broadband extends Type implements ProductItem
|
||||
|
||||
protected $table = 'product_broadband';
|
||||
|
||||
protected const category_name = 'Broadband';
|
||||
|
||||
// Information required during the order process
|
||||
protected array $order_attributes = [
|
||||
'options.address'=>[
|
||||
|
@@ -12,8 +12,6 @@ final class Domain extends Type implements ProductItem
|
||||
{
|
||||
protected $table = 'product_domain';
|
||||
|
||||
protected const category_name = 'Domain Name';
|
||||
|
||||
// The model that is referenced when this product is ordered
|
||||
protected string $order_model = ServiceDomain::class;
|
||||
|
||||
|
@@ -12,8 +12,6 @@ final class Email extends Type implements ProductItem
|
||||
{
|
||||
protected $table = 'product_email';
|
||||
|
||||
protected const category_name = 'Email Hosting';
|
||||
|
||||
// The model that is referenced when this product is ordered
|
||||
protected string $order_model = ServiceEmail::class;
|
||||
|
||||
|
@@ -12,8 +12,6 @@ final class Generic extends Type implements ProductItem
|
||||
{
|
||||
protected $table = 'product_generic';
|
||||
|
||||
protected const category_name = 'Generic';
|
||||
|
||||
// The model that is referenced when this product is ordered
|
||||
protected string $order_model = ServiceGeneric::class;
|
||||
|
||||
|
@@ -12,8 +12,6 @@ final class Host extends Type implements ProductItem
|
||||
{
|
||||
protected $table = 'product_host';
|
||||
|
||||
protected const category_name = 'Web Hosting';
|
||||
|
||||
// The model that is referenced when this product is ordered
|
||||
protected string $order_model = ServiceHost::class;
|
||||
|
||||
|
@@ -12,8 +12,6 @@ final class Phone extends Type implements ProductItem
|
||||
{
|
||||
protected $table = 'product_phone';
|
||||
|
||||
protected const category_name = 'Telephone';
|
||||
|
||||
protected array $order_attributes = [
|
||||
'options.phonenumber'=>[
|
||||
'request'=>'options.phonenumber',
|
||||
|
@@ -12,8 +12,6 @@ final class SSL extends Type implements ProductItem
|
||||
{
|
||||
protected $table = 'product_ssl';
|
||||
|
||||
protected const category_name = 'SSL Certificate';
|
||||
|
||||
// The model that is referenced when this product is ordered
|
||||
protected string $order_model = ServiceSSL::class;
|
||||
|
||||
|
@@ -32,9 +32,11 @@ abstract class Type extends Model
|
||||
* other logic of these types.
|
||||
*
|
||||
* @return string
|
||||
* @deprecated - can this be replaced with product->supplied->category?
|
||||
*/
|
||||
final public function getCategoryAttribute(): string
|
||||
{
|
||||
abort(500,'use product->supplied->category_name');
|
||||
return strtolower((new \ReflectionClass($this))->getShortName());
|
||||
}
|
||||
|
||||
@@ -42,9 +44,11 @@ abstract class Type extends Model
|
||||
* Return a friendly name for this product, used for display
|
||||
*
|
||||
* @return string
|
||||
* @deprecated - can this be replaced with product->supplied->category_name
|
||||
*/
|
||||
final public function getCategoryNameAttribute(): string
|
||||
{
|
||||
abort(500,'use product->supplied->category_name');
|
||||
return static::category_name;
|
||||
}
|
||||
}
|
@@ -8,57 +8,93 @@ use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Leenooks\Traits\ScopeActive;
|
||||
|
||||
use App\Models\Supplier\{Broadband,Domain,Email,Ethernet,Generic,Host,HSPA,Phone,SSL};
|
||||
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 */
|
||||
|
||||
/**
|
||||
* The offerings we provide
|
||||
* @todo Use the product/* category instead of this const. The assumption is the supplier/* type is the same as the product/* type.
|
||||
* @deprecated - use the product/* category instead.
|
||||
* Return the offerings that this supplier provides
|
||||
*
|
||||
* @param Supplier|null $so
|
||||
* @return Collection
|
||||
*/
|
||||
public const offering_types = [
|
||||
'broadband' => [
|
||||
'name' => 'Broadband',
|
||||
'class' => Broadband::class,
|
||||
],
|
||||
'hspa' => [
|
||||
'name' => 'Mobile Broadband',
|
||||
'class' => HSPA::class,
|
||||
],
|
||||
'ethernet' => [
|
||||
'name' => 'Ethernet Broadband',
|
||||
'class' => Ethernet::class,
|
||||
],
|
||||
'domainname' => [
|
||||
'name' => 'Domain Name',
|
||||
'class' => Domain::class,
|
||||
],
|
||||
'email' => [
|
||||
'name' => 'Email Hosting',
|
||||
'class' => Email::class,
|
||||
],
|
||||
'generic' => [
|
||||
'name' => 'Generic',
|
||||
'class' => Generic::class,
|
||||
],
|
||||
'hosting' => [
|
||||
'name' => 'Hosting',
|
||||
'class' => Host::class,
|
||||
],
|
||||
'phone' => [
|
||||
'name' => 'Phone',
|
||||
'class' => Phone::class,
|
||||
],
|
||||
'ssl' => [
|
||||
'name' => 'SSL',
|
||||
'class' => SSL::class,
|
||||
],
|
||||
];
|
||||
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 */
|
||||
|
||||
@@ -73,43 +109,6 @@ class Supplier extends Model
|
||||
|
||||
/* METHODS */
|
||||
|
||||
/**
|
||||
* Return the offerings that this supplier provides
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function offeringTypes(): Collection
|
||||
{
|
||||
$result = collect();
|
||||
|
||||
// See if we have any configurations
|
||||
foreach (self::offering_types as $key => $type) {
|
||||
if (! ($class=Arr::get($type,'class')))
|
||||
continue;
|
||||
|
||||
if (Arr::get($this->detail->connections,$key)) {
|
||||
$result->put($key,(object)[
|
||||
'type' => Arr::get($type,'name'),
|
||||
'items' => (new $class)->where('supplier_detail_id',$this->detail->id),
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// See if we have any products defined
|
||||
$o = new $class;
|
||||
$o->where('supplier_detail_id',$this->detail->id);
|
||||
|
||||
if ($o->count())
|
||||
$result->put($key,(object)[
|
||||
'type' => Arr::get($type,'name'),
|
||||
'items' => (new $class)->where('supplier_detail_id',$this->detail->id),
|
||||
]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the traffic records, that were not matched to a service.
|
||||
*
|
||||
|
@@ -10,6 +10,8 @@ use App\Models\Product\Broadband as ProductBroadband;
|
||||
|
||||
class Broadband extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'Broadband';
|
||||
|
||||
protected $casts = [
|
||||
'offpeak_start' => 'datetime:H:i',
|
||||
'offpeak_end' => 'datetime:H:i',
|
||||
@@ -35,16 +37,16 @@ class Broadband extends Type implements SupplierItem
|
||||
|
||||
/* INTERFACES */
|
||||
|
||||
public function types()
|
||||
{
|
||||
return $this->belongsToMany(ProductBroadband::class,$this->table,'id','id','id','supplier_item_id');
|
||||
}
|
||||
|
||||
public function getBillingIntervalAttribute(): int
|
||||
{
|
||||
return 1; // Monthly
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->hasMany(ProductBroadband::class,'supplier_item_id','id');
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
/**
|
||||
@@ -156,14 +158,4 @@ class Broadband extends Type implements SupplierItem
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Broadband Speed
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function speed(): string
|
||||
{
|
||||
return $this->speed;
|
||||
}
|
||||
}
|
@@ -8,6 +8,8 @@ use App\Models\TLD;
|
||||
|
||||
final class Domain extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'Domain Name';
|
||||
|
||||
protected $table = 'supplier_domain';
|
||||
|
||||
/* INTERFACES */
|
||||
@@ -22,9 +24,9 @@ final class Domain extends Type implements SupplierItem
|
||||
return sprintf('%s: %s',$this->product_id,$this->tld->name);
|
||||
}
|
||||
|
||||
public function types()
|
||||
public function products()
|
||||
{
|
||||
return $this->belongsToMany(ProductDomain::class,$this->table,'id','id','id','supplier_item_id');
|
||||
return $this->hasMany(ProductDomain::class,'supplier_item_id','id');
|
||||
}
|
||||
|
||||
/* RELATIONS */
|
||||
|
@@ -7,6 +7,8 @@ use App\Models\Product\Email as ProductEmail;
|
||||
|
||||
final class Email extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'Email Hosting';
|
||||
|
||||
protected $table = 'supplier_email';
|
||||
|
||||
/* INTERFACES */
|
||||
@@ -16,8 +18,8 @@ final class Email extends Type implements SupplierItem
|
||||
return 4; // Yearly
|
||||
}
|
||||
|
||||
public function types()
|
||||
public function products()
|
||||
{
|
||||
return $this->belongsToMany(ProductEmail::class,$this->table,'id','id','id','supplier_item_id');
|
||||
return $this->hasMany(ProductEmail::class,$this->table,'supplier_item_id','id');
|
||||
}
|
||||
}
|
@@ -4,4 +4,5 @@ namespace App\Models\Supplier;
|
||||
|
||||
class Ethernet extends Broadband
|
||||
{
|
||||
protected const category_name = 'Broadband Ethernet';
|
||||
}
|
@@ -7,17 +7,19 @@ use App\Models\Product\Generic as ProductGeneric;
|
||||
|
||||
final class Generic extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'Generic';
|
||||
|
||||
protected $table = 'supplier_generic';
|
||||
|
||||
/* INTERFACES */
|
||||
|
||||
public function types()
|
||||
{
|
||||
return $this->belongsToMany(ProductGeneric::class,$this->table,'id','id','id','supplier_item_id');
|
||||
}
|
||||
|
||||
public function getBillingIntervalAttribute(): int
|
||||
{
|
||||
return 1; // Monthly
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->hasMany(ProductGeneric::class,'supplier_item_id','id');
|
||||
}
|
||||
}
|
@@ -4,4 +4,5 @@ namespace App\Models\Supplier;
|
||||
|
||||
class HSPA extends Broadband
|
||||
{
|
||||
protected const category_name = 'Mobile Broadband';
|
||||
}
|
@@ -7,17 +7,19 @@ use App\Models\Product\Host as ProductHost;
|
||||
|
||||
final class Host extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'Web Hosting';
|
||||
|
||||
protected $table = 'supplier_host';
|
||||
|
||||
/* INTERFACES */
|
||||
|
||||
public function types()
|
||||
{
|
||||
return $this->belongsToMany(ProductHost::class,$this->table,'id','id','id','supplier_item_id');
|
||||
}
|
||||
|
||||
public function getBillingIntervalAttribute(): int
|
||||
{
|
||||
return 4; // Yearly
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->belongsToMany(ProductHost::class,'supplier_item_id','id');
|
||||
}
|
||||
}
|
@@ -7,17 +7,19 @@ use App\Models\Product\Phone as ProductVoip;
|
||||
|
||||
final class Phone extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'Telephone';
|
||||
|
||||
protected $table = 'supplier_phone';
|
||||
|
||||
/* INTERFACES */
|
||||
|
||||
public function types()
|
||||
{
|
||||
return $this->belongsToMany(ProductVoip::class,$this->table,'id','id','id','supplier_item_id');
|
||||
}
|
||||
|
||||
public function getBillingIntervalAttribute(): int
|
||||
{
|
||||
return 1; // Monthly
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->hasMany(ProductVoip::class,'supplier_item_id','id');
|
||||
}
|
||||
}
|
@@ -7,17 +7,19 @@ use App\Models\Product\SSL as ProductSSL;
|
||||
|
||||
final class SSL extends Type implements SupplierItem
|
||||
{
|
||||
protected const category_name = 'SSL Certificate';
|
||||
|
||||
protected $table = 'supplier_ssl';
|
||||
|
||||
/* INTERFACES */
|
||||
|
||||
public function types()
|
||||
{
|
||||
return $this->belongsToMany(ProductSSL::class,$this->table,'id','id','id','supplier_item_id');
|
||||
}
|
||||
|
||||
public function getBillingIntervalAttribute(): int
|
||||
{
|
||||
return 4; // Yearly
|
||||
}
|
||||
|
||||
public function products()
|
||||
{
|
||||
return $this->belongsToMany(ProductSSL::class,'supplier_item_id','id');
|
||||
}
|
||||
}
|
@@ -27,6 +27,27 @@ abstract class Type extends Model
|
||||
return Tax::tax_calc($this->attributes['base_cost'],config('site')->taxes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will return the category of the product (eg: domain, hosting, etc) which is the basis for all
|
||||
* other logic of these types.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getCategoryAttribute(): string
|
||||
{
|
||||
return strtolower((new \ReflectionClass($this))->getShortName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a friendly name for this product, used for display
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
final public function getCategoryNameAttribute(): string
|
||||
{
|
||||
return static::category_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This contract term is the highest of
|
||||
* + The defined contract_term
|
||||
|
@@ -3,7 +3,9 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
|
||||
use App\Models\Supplier\{Broadband,Generic,Phone,Type};
|
||||
use App\Traits\SiteID;
|
||||
|
||||
class SupplierDetail extends Model
|
||||
@@ -14,8 +16,50 @@ class SupplierDetail extends Model
|
||||
|
||||
/* RELATIONS */
|
||||
|
||||
public function broadbands()
|
||||
{
|
||||
return $this->hasMany(Broadband::class);
|
||||
}
|
||||
|
||||
public function generics()
|
||||
{
|
||||
return $this->hasMany(Generic::class);
|
||||
}
|
||||
|
||||
public function phones()
|
||||
{
|
||||
return $this->hasMany(Phone::class);
|
||||
}
|
||||
|
||||
public function supplier()
|
||||
{
|
||||
return $this->belongsTo(Supplier::class);
|
||||
}
|
||||
|
||||
/* METHODS */
|
||||
|
||||
/**
|
||||
* Find a supplier product of a particular type
|
||||
*
|
||||
* @param string $type
|
||||
* @param int $id
|
||||
* @return Type
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function find(string $type,int $id): Type
|
||||
{
|
||||
switch ($type) {
|
||||
case 'broadband':
|
||||
$item = $this->broadbands->where('id',$id);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception('Unknown type: '.$type);
|
||||
}
|
||||
|
||||
if ($item->count() !== 1)
|
||||
throw new ModelNotFoundException(sprintf('Unknown Model of type [%s] with id [%d]',$type,$id));
|
||||
|
||||
return $item->pop();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user