More works on products

This commit is contained in:
Deon George
2022-02-01 16:40:46 +11:00
parent 1e9f15b40f
commit b9b4416737
36 changed files with 952 additions and 312 deletions

View File

@@ -1,12 +0,0 @@
<?php
namespace App\Models\Base;
use Illuminate\Database\Eloquent\Model;
/**
* @deprecated
*/
abstract class ProductType extends Model
{
}

View File

@@ -5,6 +5,9 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Leenooks\Traits\ScopeActive;
/**
* @deprecated
*/
class DomainRegistrar extends Model
{
use ScopeActive;

View File

@@ -5,6 +5,9 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Leenooks\Traits\ScopeActive;
/**
* @deprecated
*/
class DomainTld extends Model
{
use ScopeActive;
@@ -24,4 +27,9 @@ class DomainTld extends Model
{
return strtoupper($value);
}
public function getPriceGroupAttribute($value): array
{
return unserialize($value);
}
}

View File

@@ -8,6 +8,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Leenooks\Traits\ScopeActive;
use App\Interfaces\IDs;
@@ -299,7 +300,7 @@ class Product extends Model implements IDs
*/
public function hasUsage(): bool
{
return $this->type->supplied->hasUsage();
return $this->type->hasUsage();
}
/**
@@ -324,12 +325,24 @@ class Product extends Model implements IDs
$timeperiod = $this->getBillingIntervalAttribute();
// If the price doesnt exist for $go->id, use $go->id = 0 which is all users.
if (! $price=Arr::get($this->pricing,sprintf('%d.%d.%s',$timeperiod,$go->id,$type)))
$price = Arr::get($this->pricing,sprintf('%d.%d.%s',$timeperiod,0,$type));
if (! $price=Arr::get($this->pricing,sprintf('%d.%d.%s',$timeperiod,$go->id,$type))) {
$alt_tp = $timeperiod;
while (is_null($price=Arr::get($this->pricing,sprintf('%d.%d.%s',$alt_tp,0,$type))) && ($alt_tp >= 0)) {
$alt_tp--;
}
if (! is_null($price) && $alt_tp !== $timeperiod) {
$price = $price*Invoice::billing_change($alt_tp,$timeperiod);
}
}
// @todo - if price doesnt exist for the time period, reduce down to timeperiod 1 and multiply appropriately.
if (is_null($price))
abort(500,sprintf('Price is NULL, we need to find it timeperiod[%s] group[%s]',$timeperiod,$go->id));
if (is_null($price)) {
Log::error(sprintf('Price is still null for [%d] timeperiod [%d] group [%d]',$this->id,$timeperiod,$go->id));
$price = 0;
}
return round($price,2);
}

View File

@@ -4,18 +4,13 @@ namespace App\Models\Product;
use Illuminate\Support\Collection;
use App\Interfaces\ProductSupplier;
use App\Models\Base\ProductType;
use App\Models\{Product,Supplier};
use App\Interfaces\ProductItem;
use App\Models\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
final class Broadband extends Type implements ProductItem
{
use SiteID;
use OrderServiceOptions;
protected $table = 'product_broadband';
// Information required during the order process
@@ -34,20 +29,11 @@ class Broadband extends ProductType implements ProductSupplier
],
];
// The model that is referenced when this product is ordered
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
*
@@ -123,6 +109,7 @@ class Broadband extends ProductType implements ProductSupplier
*
* @return string
*/
// @todo To check
public function allowance_string(): string
{
$result = '';

View File

@@ -4,14 +4,30 @@ namespace App\Models\Product;
use Illuminate\Support\Collection;
use App\Interfaces\ProductSupplier;
use App\Models\Base\ProductType;
use App\Traits\NextKey;
use App\Interfaces\ProductItem;
use App\Models\Service\Domain as ServiceDomain;
use App\Models\Supplier\Domain as SupplierDomain;
class Domain extends ProductType implements ProductSupplier
final class Domain extends Type implements ProductItem
{
use NextKey;
const RECORD_ID = '';
protected $table = 'product_domain';
// The model that is referenced when this product is ordered
protected string $order_model = ServiceDomain::class;
/* RELATIONS */
/**
* The offering supplied with this product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function supplied()
{
return $this->hasOne(SupplierDomain::class,'id','supplier_domain_id');
}
/* INTERFACES */
public function allowance(): Collection
{

View File

@@ -2,10 +2,33 @@
namespace App\Models\Product;
use App\Models\Base\ProductType;
use Illuminate\Support\Collection;
class Generic extends ProductType
use App\Interfaces\ProductItem;
use App\Models\Service\Generic as ServiceGeneric;
use App\Models\Supplier\Generic as SupplierGeneric;
final class Generic extends Type implements ProductItem
{
protected $table = 'product_generic';
// The model that is referenced when this product is ordered
protected string $order_model = ServiceGeneric::class;
/* RELATIONS */
/**
* The offering supplied with this product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function supplied()
{
return $this->hasOne(SupplierGeneric::class,'id','supplier_generic_id');
}
/* INTERFACES */
public function getContractTermAttribute(): int
{
return 0;
@@ -20,4 +43,24 @@ class Generic extends ProductType
{
return FALSE;
}
public function allowance(): Collection
{
// TODO: Implement allowance() method.
}
public function allowance_string(): string
{
// TODO: Implement allowance_string() method.
}
public function getCostAttribute(): float
{
// TODO: Implement getCostAttribute() method.
}
public function getSupplierAttribute()
{
// TODO: Implement getSupplierAttribute() method.
}
}

View File

@@ -2,13 +2,32 @@
namespace App\Models\Product;
use App\Models\Base\ProductType;
use App\Traits\NextKey;
use Illuminate\Support\Collection;
class Host extends ProductType
use App\Interfaces\ProductItem;
use App\Models\Service\Host as ServiceHost;
use App\Models\Supplier\Host as SupplierHost;
final class Host extends Type implements ProductItem
{
use NextKey;
const RECORD_ID = '';
protected $table = 'product_host';
// The model that is referenced when this product is ordered
protected string $order_model = ServiceHost::class;
/* RELATIONS */
/**
* The offering supplied with this product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function supplied()
{
return $this->hasOne(SupplierHost::class,'id','supplier_host_id');
}
/* INTERFACES */
public function getContractTermAttribute(): int
{
@@ -24,4 +43,24 @@ class Host extends ProductType
{
return FALSE;
}
public function allowance(): Collection
{
// TODO: Implement allowance() method.
}
public function allowance_string(): string
{
// TODO: Implement allowance_string() method.
}
public function getCostAttribute(): float
{
// TODO: Implement getCostAttribute() method.
}
public function getSupplierAttribute()
{
// TODO: Implement getSupplierAttribute() method.
}
}

View File

@@ -4,16 +4,30 @@ namespace App\Models\Product;
use Illuminate\Support\Collection;
use App\Interfaces\ProductSupplier;
use App\Models\Base\ProductType;
use App\Traits\NextKey;
use App\Interfaces\ProductItem;
use App\Models\Service\SSL as ServiceSSL;
use App\Models\Supplier\SSL as SupplierSSL;
class SSL extends ProductType implements ProductSupplier
final class SSL extends Type implements ProductItem
{
use NextKey;
const RECORD_ID = 'ssl';
protected $table = 'product_ssl';
protected $table = 'ab_ssl';
// The model that is referenced when this product is ordered
protected string $order_model = ServiceSSL::class;
/* RELATIONS */
/**
* The offering supplied with this product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function supplied()
{
return $this->hasOne(SupplierSSL::class,'id','supplier_ssl_id');
}
/* INTERFACES */
public function allowance(): Collection
{

View File

@@ -0,0 +1,25 @@
<?php
namespace App\Models\Product;
use Illuminate\Database\Eloquent\Model;
use App\Models\Product;
use App\Traits\{OrderServiceOptions,SiteID};
abstract class Type extends Model
{
use SiteID,OrderServiceOptions;
/* 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');
}
}

View File

@@ -2,16 +2,15 @@
namespace App\Models\Product;
use App\Models\Base\ProductType;
use App\Traits\NextKey;
use App\Traits\OrderServiceOptions;
use Illuminate\Support\Collection;
class Voip extends ProductType
use App\Interfaces\ProductItem;
use App\Models\Service\Voip as ServiceVoip;
use App\Models\Supplier\Voip as SupplierVoip;
final class Voip extends Type implements ProductItem
{
use NextKey;
const RECORD_ID = '';
use OrderServiceOptions;
protected $table = 'product_voip';
protected $order_attributes = [
'options.phonenumber'=>[
@@ -40,7 +39,22 @@ class Voip extends ProductType
],
];
protected $order_model = \App\Models\Service\Voip::class;
// The model that is referenced when this product is ordered
protected string $order_model = ServiceVoip::class;
/* RELATIONS */
/**
* The offering supplied with this product
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function supplied()
{
return $this->hasOne(SupplierVoip::class,'id','supplier_voip_id');
}
/* INTERFACES */
public function getContractTermAttribute(): int
{
@@ -56,4 +70,24 @@ class Voip extends ProductType
{
return TRUE;
}
public function allowance(): Collection
{
// TODO: Implement allowance() method.
}
public function allowance_string(): string
{
// TODO: Implement allowance_string() method.
}
public function getCostAttribute(): float
{
// TODO: Implement getCostAttribute() method.
}
public function getSupplierAttribute()
{
// TODO: Implement getSupplierAttribute() method.
}
}

View File

@@ -183,7 +183,7 @@ class Service extends Model implements IDs
'PAYMENT-CHECK' => [
'fail'=>'ORDER-HOLD',
'next'=>[
'ORDER-SENT'=>[],
'ORDER-SENT'=>['wholesaler'],
],
'system'=>TRUE,
'method'=>'action_payment_check',

View File

@@ -7,7 +7,7 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Leenooks\Traits\ScopeActive;
use App\Models\Supplier\{Broadband,Ethernet,HSPA};
use App\Models\Supplier\{Broadband,Domain,Ethernet,Generic,Host,HSPA,Voip};
class Supplier extends Model
{
@@ -31,19 +31,19 @@ class Supplier extends Model
],
'domainname' => [
'name' => 'Domain Name',
//'class' => Domain::class,
'class' => Domain::class,
],
'generic' => [
'name' => 'Generic',
//'class' => Generic::class,
'class' => Generic::class,
],
'hosting' => [
'name' => 'Hosting',
//'class' => Host::class,
'class' => Host::class,
],
'voip' => [
'name' => 'VOIP Telephone',
//'class' => Voip::class,
'class' => Voip::class,
],
];
@@ -67,7 +67,7 @@ class Supplier extends Model
// See if we have any configurations
foreach (self::offering_types as $key => $type) {
if (! $class = Arr::get($type,'class'))
if (! ($class=Arr::get($type,'class')))
continue;
if (Arr::get($this->detail->connections,$key)) {

View File

@@ -2,23 +2,14 @@
namespace App\Models\Supplier;
use App\Traits\ProductDetails;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Leenooks\Traits\ScopeActive;
use App\Interfaces\SupplierItem;
use App\Models\{Invoice,Supplier,SupplierDetail,Tax};
use App\Models\Product\Broadband as ProductBroadband;
use App\Traits\SiteID;
class Broadband extends Model implements SupplierItem
class Broadband extends Type implements SupplierItem
{
use SiteID,ScopeActive,ProductDetails;
protected $casts = [
'offpeak_start' => 'datetime:H:i',
'offpeak_end' => 'datetime:H:i',
@@ -44,19 +35,9 @@ class Broadband extends Model implements SupplierItem
/* INTERFACES */
public function supplier_detail(): BelongsTo
public function types()
{
return $this->belongsTo(SupplierDetail::class);
}
public function types(): BelongsToMany
{
return $this->belongsToMany(ProductBroadband::class,'supplier_broadband','id','id','id','supplier_broadband_id');
}
public function getBaseCostTaxableAttribute(): float
{
return Tax::tax_calc($this->attributes['base_cost'],config('site')->taxes);
return $this->belongsToMany(ProductBroadband::class,$this->table,'id','id','id',$this->table.'_id');
}
public function getBillingIntervalAttribute(): int
@@ -64,48 +45,6 @@ class Broadband extends Model implements SupplierItem
return 1; // Monthly
}
/**
* This contract term is the highest of
* + The defined contract_term
* + The default months in a billing interval
*
* @return int
*/
public function getContractTermAttribute(): int
{
return max(Invoice::billing_period(self::getBillingIntervalAttribute()),Arr::get($this->attributes,'contract_term'));
}
public function getMinCostAttribute(): float
{
return $this->attributes['setup_cost']+$this->attributes['base_cost']*Invoice::billing_term($this->getContractTermAttribute(),$this->getBillingIntervalAttribute());
}
public function getMinCostTaxableAttribute(): float
{
return Tax::tax_calc($this->getMinCostAttribute(),config('site')->taxes);
}
public function getNameAttribute(): string
{
return $this->product_id ?: 'Supplier PID Unknown';
}
public function getNameLongAttribute(): string
{
return $this->product_desc ?: 'Supplier NAME Unknown';
}
public function getSetupCostTaxableAttribute(): float
{
return Tax::tax_calc($this->attributes['setup_cost'],config('site')->taxes);
}
public function getTypeAttribute(): string
{
return Arr::get(collect(Supplier::offering_types)->firstWhere('class',get_class($this)),'name','Unknown');
}
/* METHODS */
/**

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Models\Supplier;
use App\Interfaces\SupplierItem;
use App\Models\Product\Domain as ProductDomain;
use App\Models\TLD;
final class Domain extends Type implements SupplierItem
{
protected $table = 'supplier_domain';
/* INTERFACES */
public function types()
{
return $this->belongsToMany(ProductDomain::class,$this->table,'id','id','id',$this->table.'_id');
}
public function getBillingIntervalAttribute(): int
{
return 4; // Yearly
}
public function getNameAttribute(): string
{
return sprintf('%s: %s',$this->product_id,$this->tld->name);
}
/* RELATIONS */
public function tld()
{
return $this->belongsTo(TLD::class);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Models\Supplier;
use App\Interfaces\SupplierItem;
use App\Models\Product\Generic as ProductGeneric;
final class Generic extends Type implements SupplierItem
{
protected $table = 'supplier_generic';
/* INTERFACES */
public function types()
{
return $this->belongsToMany(ProductGeneric::class,$this->table,'id','id','id',$this->table.'_id');
}
public function getBillingIntervalAttribute(): int
{
return 1; // Monthly
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Models\Supplier;
use App\Interfaces\SupplierItem;
use App\Models\Product\Host as ProductHost;
final class Host extends Type implements SupplierItem
{
protected $table = 'supplier_host';
/* INTERFACES */
public function types()
{
return $this->belongsToMany(ProductHost::class,$this->table,'id','id','id',$this->table.'_id');
}
public function getBillingIntervalAttribute(): int
{
return 4; // Yearly
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Models\Supplier;
use App\Interfaces\SupplierItem;
use App\Models\Product\SSL as ProductSSL;
final class SSL extends Type implements SupplierItem
{
protected $table = 'supplier_ssl';
/* INTERFACES */
public function types()
{
return $this->belongsToMany(ProductSSL::class,$this->table,'id','id','id',$this->table.'_id');
}
public function getBillingIntervalAttribute(): int
{
return 4; // Yearly
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace App\Models\Supplier;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Leenooks\Traits\ScopeActive;
use App\Models\{Invoice,Supplier,SupplierDetail,Tax};
use App\Traits\{ProductDetails,SiteID};
abstract class Type extends Model
{
use SiteID,ScopeActive,ProductDetails;
/* RELATIONS */
public function supplier_detail()
{
return $this->belongsTo(SupplierDetail::class);
}
/* ATTRIBUTES */
public function getBaseCostTaxableAttribute(): float
{
return Tax::tax_calc($this->attributes['base_cost'],config('site')->taxes);
}
/**
* This contract term is the highest of
* + The defined contract_term
* + The default months in a billing interval
*
* @return int
*/
public function getContractTermAttribute(): int
{
return max(Invoice::billing_period(static::getBillingIntervalAttribute()),Arr::get($this->attributes,'contract_term'));
}
public function getMinCostAttribute(): float
{
return $this->attributes['setup_cost']+$this->attributes['base_cost']*Invoice::billing_term($this->getContractTermAttribute(),$this->getBillingIntervalAttribute());
}
public function getMinCostTaxableAttribute(): float
{
return Tax::tax_calc($this->getMinCostAttribute(),config('site')->taxes);
}
public function getNameAttribute(): string
{
return $this->product_id ?: 'Supplier PID Unknown';
}
public function getNameLongAttribute(): string
{
return $this->product_desc ?: 'Supplier NAME Unknown';
}
public function getSetupCostTaxableAttribute(): float
{
return Tax::tax_calc($this->attributes['setup_cost'],config('site')->taxes);
}
public function getTypeAttribute(): string
{
return Arr::get(collect(Supplier::offering_types)->firstWhere('class',get_class($this)),'name','Unknown');
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Models\Supplier;
use App\Interfaces\SupplierItem;
use App\Models\Product\Voip as ProductVoip;
final class Voip extends Type implements SupplierItem
{
protected $table = 'supplier_voip';
/* INTERFACES */
public function types()
{
return $this->belongsToMany(ProductVoip::class,$this->table,'id','id','id',$this->table.'_id');
}
public function getBillingIntervalAttribute(): int
{
return 1; // Monthly
}
}

17
app/Models/TLD.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TLD extends Model
{
protected $table = 'tlds';
/* ATTRIBUTES */
public function getNameAttribute($value): string
{
return strtoupper($value);
}
}