Work on products, first completed broadband

This commit is contained in:
Deon George
2021-12-24 12:14:01 +11:00
parent 8f5293662e
commit 1e9f15b40f
62 changed files with 2139 additions and 894 deletions

View File

@@ -1,159 +0,0 @@
<?php
namespace App\Models\Product;
use Illuminate\Support\Collection;
use App\Interfaces\ProductSupplier;
use App\Models\Base\ProductType;
use App\Models\AdslSupplier;
use App\Models\AdslSupplierPlan;
use App\Traits\NextKey;
class Adsl extends ProductType implements ProductSupplier
{
use NextKey;
const RECORD_ID = 'adsl_plan';
protected $table = 'ab_adsl_plan';
public static $map = [
'base_up_offpeak'=>'extra_up_offpeak',
'base_down_offpeak'=>'extra_down_offpeak',
'base_up_peak'=>'extra_up_peak',
'base_down_peak'=>'extra_down_peak',
];
/**
* Map upstream metrics into traffic allowance metrics
*
* @var array
*/
public static $metrics = [
'down_peak'=>'base_down_peak',
'down_offpeak'=>'base_down_offpeak',
'up_peak'=>'base_up_peak',
'up_offpeak'=>'base_up_offpeak',
'peer'=>'base_down_peak',
'internal'=>'base_down_offpeak',
];
/**
* The suppliers product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function product()
{
return $this->hasOne(AdslSupplierPlan::class,'id','adsl_supplier_plan_id');
}
/**
* The supplier
*
* @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
*/
public function supplier()
{
return $this->hasOneThrough(AdslSupplier::class,AdslSupplierPlan::class,'id','id','adsl_supplier_plan_id','supplier_id');
}
public function __get($key)
{
switch($key) {
case 'speed':
return $this->product->speed;
}
// If we dont have a specific key, we'll resolve it normally
return parent::__get($key);
}
/** ATTRIBUTES **/
/**
* Calculate the allowance array or traffic used array
*
* @param array Traffic Used in each metric.
* @param bool $ceil Round the numbers to integers
* @return array|string
*/
public function allowance(array $data=[],bool $ceil=TRUE): Collection
{
$config = collect();
// Base Config
foreach (array_keys(static::$map) as $k) {
$config->put($k,$this->{$k});
}
// Excess Config
foreach (array_values(static::$map) as $k) {
$config->put($k,$this->{$k});
}
// Shaped or Charge
$config->put('shaped',$this->extra_shaped);
$config->put('charged',$this->extra_charged);
// Metric - used to round down data in $data.
$config->put('metric',$this->metric);
return $this->product->allowance($config,$data,$ceil);
}
/**
* Return the suppliers cost for this service
*
* @return float
*/
public function allowance_cost(): float
{
$result = 0;
foreach ($this->product->allowance(NULL,$this->allowance([])->toArray()) as $k=>$v) {
$result += -$v*$this->product->{static::$map[$k]};
}
return $result;
}
/**
* Render the allowance as a string
* eg: 50/100
*
* @return string
*/
public function allowance_string(): string
{
$result = '';
$data = $this->allowance();
foreach ([
'base_down_peak',
'base_up_peak',
'base_down_offpeak',
'base_up_offpeak',
] as $k)
{
if ($data->has($k)) {
if ($result)
$result .= '/';
$result .= $data->get($k);
}
}
return $result;
}
public function getCostAttribute(): float
{
// @todo Tax shouldnt be hard coded
return ($this->product->base_cost+$this->allowance_cost())*1.1;
}
public function getSupplierAttribute()
{
return $this->getRelationValue('supplier');
}
}

View File

@@ -0,0 +1,178 @@
<?php
namespace App\Models\Product;
use Illuminate\Support\Collection;
use App\Interfaces\ProductSupplier;
use App\Models\Base\ProductType;
use App\Models\{Product,Supplier};
use App\Models\Service\Broadband as ServiceBroadband;
use App\Models\Supplier\Broadband as SupplierBroadband;
use App\Traits\{OrderServiceOptions,SiteID};
class Broadband extends ProductType implements ProductSupplier
{
use SiteID;
use OrderServiceOptions;
protected $table = 'product_broadband';
// Information required during the order process
private array $order_attributes = [
'options.address'=>[
'request'=>'options.address',
'key'=>'service_address',
'validation'=>'required|string:10|unique:ab_service__adsl,service_address',
'validation_message'=>'Address is a required field.',
],
'options.notes'=>[
'request'=>'options.notes',
'key'=>'order_info.notes',
'validation'=>'present',
'validation_message'=>'Special Instructions here.',
],
];
protected string $order_model = ServiceBroadband::class;
/* RELATIONS */
/**
* The product that sells this type
*
* @return \Illuminate\Database\Eloquent\Relations\MorphOne
*/
public function product()
{
return $this->morphOne(Product::class, null,'model','model_id');
}
/**
* The offering supplied with this product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function supplied()
{
return $this->hasOne(SupplierBroadband::class,'id','supplier_broadband_id');
}
/**
* The supplier
*
* @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
*/
// @todo To check
public function supplier()
{
return $this->hasOneThrough(Supplier::class,SupplierBroadband::class,'id','id','adsl_supplier_plan_id','supplier_id');
}
/* INTERFACES */
/**
* Calculate the allowance array or traffic used array
*
* @param array Traffic Used in each metric.
* @param bool $ceil Round the numbers to integers
* @return array|string
*/
public function allowance(array $data=[],bool $ceil=TRUE): Collection
{
$config = collect();
foreach (array_keys(Supplier\Broadband::traffic_map) as $k => $v) {
// Base Config
$config->put($k,$this->{$k});
// Excess Config
$config->put($v,$this->{$v});
}
// Shaped or Charge
$config->put('shaped',$this->extra_shaped);
$config->put('charged',$this->extra_charged);
// Metric - used to round down data in $data.
$config->put('metric',$this->metric);
return $this->supplied->allowance($config,$data,$ceil);
}
/* ATTRIBUTES */
/**
* Return the suppliers cost for this service
*
* @return float
*/
// @todo To check
public function allowance_cost(): float
{
$result = 0;
foreach ($this->supplied->allowance(NULL,$this->allowance([])->toArray()) as $k=>$v) {
$result += -$v*$this->supplied->{Supplier\Broadband::traffic_map[$k]};
}
return $result;
}
/**
* Render the allowance as a string
* eg: 50/100
*
* @return string
*/
public function allowance_string(): string
{
$result = '';
$data = $this->allowance();
foreach ([
'base_down_peak',
'base_up_peak',
'base_down_offpeak',
'base_up_offpeak',
] as $k)
{
if ($data->has($k)) {
if ($result)
$result .= '/';
$result .= $data->get($k);
}
}
return $result;
}
/**
* The product contract term is the highest of
* + This defined contract_term
* + The suppliers contract_term
*
* @return int
*/
public function getContractTermAttribute(): int
{
return max($this->attributes['contract_term'],$this->supplied->getContractTermAttribute());
}
public function getCostAttribute(): float
{
abort(500,'deprecated');
// @todo Tax shouldnt be hard coded
return ($this->supplied->base_cost+$this->allowance_cost())*1.1;
}
public function getSupplierAttribute()
{
abort(500,'deprecated');
return $this->getRelationValue('supplier');
}
public function hasUsage(): bool
{
return TRUE;
}
}

View File

@@ -25,6 +25,11 @@ class Domain extends ProductType implements ProductSupplier
return '';
}
public function getContractTermAttribute(): int
{
return 12;
}
public function getCostAttribute(): float
{
// N/A
@@ -35,4 +40,14 @@ class Domain extends ProductType implements ProductSupplier
{
return '';
}
public function getTypeAttribute()
{
return 'Domain Name';
}
public function hasUsage(): bool
{
return FALSE;
}
}

View File

@@ -6,4 +6,18 @@ use App\Models\Base\ProductType;
class Generic extends ProductType
{
public function getContractTermAttribute(): int
{
return 0;
}
public function getTypeAttribute()
{
return 'Generic';
}
public function hasUsage(): bool
{
return FALSE;
}
}

View File

@@ -9,4 +9,19 @@ class Host extends ProductType
{
use NextKey;
const RECORD_ID = '';
public function getContractTermAttribute(): int
{
return 12;
}
public function getTypeAttribute()
{
return 'Hosting';
}
public function hasUsage(): bool
{
return FALSE;
}
}

View File

@@ -27,6 +27,11 @@ class SSL extends ProductType implements ProductSupplier
return '';
}
public function getContractTermAttribute(): int
{
return 12;
}
public function getCostAttribute(): float
{
// N/A
@@ -51,4 +56,14 @@ class SSL extends ProductType implements ProductSupplier
return $o;
}
public function getTypeAttribute()
{
return 'SSL Certificate';
}
public function hasUsage(): bool
{
return FALSE;
}
}

View File

@@ -4,9 +4,56 @@ namespace App\Models\Product;
use App\Models\Base\ProductType;
use App\Traits\NextKey;
use App\Traits\OrderServiceOptions;
class Voip extends ProductType
{
use NextKey;
const RECORD_ID = '';
use OrderServiceOptions;
protected $order_attributes = [
'options.phonenumber'=>[
'request'=>'options.phonenumber',
'key'=>'service_number',
'validation'=>'nullable|size:10|unique:ab_service__voip,service_number',
'validation_message'=>'Phone Number is a required field.',
],
'options.supplier'=>[
'request'=>'options.supplier',
'key'=>'order_info.supplier',
'validation'=>'required_with:options.phonenumber',
'validation_message'=>'Phone Supplier is a required field.',
],
'options.supplieraccnum'=>[
'request'=>'options.supplieraccnum',
'key'=>'order_info.supplieraccnum',
'validation'=>'required_with:options.phonenumber',
'validation_message'=>'Phone Supplier Account Number is a required field.',
],
'options.notes'=>[
'request'=>'options.notes',
'key'=>'order_info.notes',
'validation'=>'required_if:options.phonenumber,null',
'validation_message'=>'Special Instructions here.',
],
];
protected $order_model = \App\Models\Service\Voip::class;
public function getContractTermAttribute(): int
{
return 12;
}
public function getTypeAttribute()
{
return 'VOIP';
}
public function hasUsage(): bool
{
return TRUE;
}
}