diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 29cf8d4..ad9a136 100644 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -186,11 +186,11 @@ class AdminController extends Controller $validation = $request->validate([ 'name' => 'required|string|min:2|max:255', 'active' => 'sometimes|accepted', - 'address1' => 'required|string|min:2|max:255', + 'address1' => 'nullable|string|min:2|max:255', 'address2' => 'nullable|string|min:2|max:255', - 'city' => 'required|string|min:2|max:64', - 'state' => 'required|string|min:2|max:32', - 'postcode' => 'required|string|min:2|max:8', + 'city' => 'nullable|string|min:2|max:64', + 'state' => 'nullable|string|min:2|max:32', + 'postcode' => 'nullable|string|min:2|max:8', 'supplier_details.notes' => 'nullable|string|min:3', 'supplier_details.accounts' => 'nullable|email', 'supplier_details.support' => 'nullable|email', diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 6b9fb7a..7b563dc 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -207,7 +207,7 @@ class ServiceController extends Controller * @param Request $request * @param Service $o * @return RedirectResponse - * @todo revalidate + * @deprecated - use update() */ public function domain_edit(Request $request,Service $o) { @@ -254,4 +254,27 @@ class ServiceController extends Controller return view('r.service.domain.list') ->with('o',$o); } + + /** + * Update details about a service + * + * @param Request $request + * @param Service $o + * @return RedirectResponse + * @todo This needs to be reworked, to take into account our different service types + * @todo Add Validation + */ + public function update(Request $request,Service $o) + { + if ($request->post($o->type->type)) { + $o->type->forceFill($request->post($o->type->type))->save(); + } + + if ($request->post('date_start')) + $o->date_start = $request->post('date_start'); + + $o->save(); + + return redirect()->back()->with('success','Record Updated'); + } } \ No newline at end of file diff --git a/app/Interfaces/ProductItem.php b/app/Interfaces/ProductItem.php index f5c54fc..9e6a71c 100644 --- a/app/Interfaces/ProductItem.php +++ b/app/Interfaces/ProductItem.php @@ -2,75 +2,56 @@ namespace App\Interfaces; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\BelongsToMany; +use Illuminate\Support\Collection; interface ProductItem { - /* RELATIONS */ + public function product(); + + public function supplied(); /** - * Supplier that provides this offering + * Return the traffic inclusion with the service * - * @return BelongsTo + * @return mixed */ - //public function supplier_detail(): BelongsTo; + public function allowance(): Collection; /** - * Available products created from this supplier offering + * Render the traffic inclusion as a string * - * @return BelongsToMany + * @return mixed */ - //public function types(): BelongsToMany; - - /* ATTRIBUTES */ + public function allowance_string(): string; /** - * Return the billing interval base cost including tax + * Return the contract term for this product when sold as a service * - * @return float - */ - public function getBaseCostTaxableAttribute(): float; - - /** - * Return the billing interval that the supplier charges - * - * @return string - */ - public function getBillingIntervalAttribute(): int; - - /** - * The term that the supplier imposes on this service being connected - * - * @return int + * @return int Months */ public function getContractTermAttribute(): int; /** - * Suppliers offering name (short) - * - * @return string - */ - public function getNameAttribute(): string; - - /** - * Suppliers offering name (long) - * - * @return string - */ - public function getNameLongAttribute(): string; - - /** - * Return the setup cost including tax + * Return the product cost * * @return float */ - public function getSetupCostTaxableAttribute(): float; + public function getCostAttribute(): float; /** - * Return the type of offering this is. + * Return the supplier class + * If there is a model relationship return: + * return $this->getRelationValue('supplier'); + * otherwise return a stdClass with name * - * @return string + * @return mixed */ - public function getTypeAttribute(); + public function getSupplierAttribute(); + + /** + * Does this offering capture usage information + * + * @return bool + */ + public function hasUsage(): bool; } \ No newline at end of file diff --git a/app/Interfaces/ProductSupplier.php b/app/Interfaces/ProductSupplier.php deleted file mode 100644 index 837d2cf..0000000 --- a/app/Interfaces/ProductSupplier.php +++ /dev/null @@ -1,56 +0,0 @@ -getRelationValue('supplier'); - * otherwise return a stdClass with name - * - * @return mixed - */ - public function getSupplierAttribute(); - - /** - * Does this offering capture usage information - * - * @return bool - */ - public function hasUsage(): bool; -} \ No newline at end of file diff --git a/app/Interfaces/SupplierItem.php b/app/Interfaces/SupplierItem.php index 5cd7546..b43e5b3 100644 --- a/app/Interfaces/SupplierItem.php +++ b/app/Interfaces/SupplierItem.php @@ -2,9 +2,6 @@ namespace App\Interfaces; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\BelongsToMany; - interface SupplierItem { /* RELATIONS */ @@ -12,16 +9,16 @@ interface SupplierItem /** * Supplier that provides this offering * - * @return BelongsTo + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function supplier_detail(): BelongsTo; + public function supplier_detail(); /** * Available products created from this supplier offering * - * @return BelongsToMany + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ - public function types(): BelongsToMany; + public function types(); /* ATTRIBUTES */ diff --git a/app/Models/Base/ProductType.php b/app/Models/Base/ProductType.php deleted file mode 100644 index 09a2b63..0000000 --- a/app/Models/Base/ProductType.php +++ /dev/null @@ -1,12 +0,0 @@ -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); } diff --git a/app/Models/Product/Broadband.php b/app/Models/Product/Broadband.php index ddf48a8..75be01f 100644 --- a/app/Models/Product/Broadband.php +++ b/app/Models/Product/Broadband.php @@ -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 = ''; diff --git a/app/Models/Product/Domain.php b/app/Models/Product/Domain.php index 348d59e..cc5534a 100644 --- a/app/Models/Product/Domain.php +++ b/app/Models/Product/Domain.php @@ -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 { diff --git a/app/Models/Product/Generic.php b/app/Models/Product/Generic.php index 6d81e20..b853029 100644 --- a/app/Models/Product/Generic.php +++ b/app/Models/Product/Generic.php @@ -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. + } } diff --git a/app/Models/Product/Host.php b/app/Models/Product/Host.php index e9f23d2..3e9ae2a 100644 --- a/app/Models/Product/Host.php +++ b/app/Models/Product/Host.php @@ -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. + } } \ No newline at end of file diff --git a/app/Models/Product/SSL.php b/app/Models/Product/SSL.php index 0896bbb..f7f4858 100644 --- a/app/Models/Product/SSL.php +++ b/app/Models/Product/SSL.php @@ -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 { diff --git a/app/Models/Product/Type.php b/app/Models/Product/Type.php new file mode 100644 index 0000000..992d645 --- /dev/null +++ b/app/Models/Product/Type.php @@ -0,0 +1,25 @@ +morphOne(Product::class, null,'model','model_id'); + } +} \ No newline at end of file diff --git a/app/Models/Product/Voip.php b/app/Models/Product/Voip.php index e271dc5..66f6c6f 100644 --- a/app/Models/Product/Voip.php +++ b/app/Models/Product/Voip.php @@ -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. + } } \ No newline at end of file diff --git a/app/Models/Service.php b/app/Models/Service.php index 9405f0a..e9723ff 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -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', diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index 50c6014..ce0fefa 100644 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -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)) { diff --git a/app/Models/Supplier/Broadband.php b/app/Models/Supplier/Broadband.php index d7e18fa..f70fabb 100644 --- a/app/Models/Supplier/Broadband.php +++ b/app/Models/Supplier/Broadband.php @@ -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 */ /** diff --git a/app/Models/Supplier/Domain.php b/app/Models/Supplier/Domain.php new file mode 100644 index 0000000..a80ce0f --- /dev/null +++ b/app/Models/Supplier/Domain.php @@ -0,0 +1,36 @@ +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); + } +} \ No newline at end of file diff --git a/app/Models/Supplier/Generic.php b/app/Models/Supplier/Generic.php new file mode 100644 index 0000000..73e6417 --- /dev/null +++ b/app/Models/Supplier/Generic.php @@ -0,0 +1,23 @@ +belongsToMany(ProductGeneric::class,$this->table,'id','id','id',$this->table.'_id'); + } + + public function getBillingIntervalAttribute(): int + { + return 1; // Monthly + } +} \ No newline at end of file diff --git a/app/Models/Supplier/Host.php b/app/Models/Supplier/Host.php new file mode 100644 index 0000000..48f6b7a --- /dev/null +++ b/app/Models/Supplier/Host.php @@ -0,0 +1,23 @@ +belongsToMany(ProductHost::class,$this->table,'id','id','id',$this->table.'_id'); + } + + public function getBillingIntervalAttribute(): int + { + return 4; // Yearly + } +} \ No newline at end of file diff --git a/app/Models/Supplier/SSL.php b/app/Models/Supplier/SSL.php new file mode 100644 index 0000000..2098479 --- /dev/null +++ b/app/Models/Supplier/SSL.php @@ -0,0 +1,23 @@ +belongsToMany(ProductSSL::class,$this->table,'id','id','id',$this->table.'_id'); + } + + public function getBillingIntervalAttribute(): int + { + return 4; // Yearly + } +} \ No newline at end of file diff --git a/app/Models/Supplier/Type.php b/app/Models/Supplier/Type.php new file mode 100644 index 0000000..b0d13c0 --- /dev/null +++ b/app/Models/Supplier/Type.php @@ -0,0 +1,71 @@ +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'); + } +} \ No newline at end of file diff --git a/app/Models/Supplier/Voip.php b/app/Models/Supplier/Voip.php new file mode 100644 index 0000000..cd9b1b3 --- /dev/null +++ b/app/Models/Supplier/Voip.php @@ -0,0 +1,23 @@ +belongsToMany(ProductVoip::class,$this->table,'id','id','id',$this->table.'_id'); + } + + public function getBillingIntervalAttribute(): int + { + return 1; // Monthly + } +} \ No newline at end of file diff --git a/app/Models/TLD.php b/app/Models/TLD.php new file mode 100644 index 0000000..9174ae8 --- /dev/null +++ b/app/Models/TLD.php @@ -0,0 +1,17 @@ +[ 'request'=>'options.input', 'key'=>'column', @@ -20,7 +23,7 @@ trait OrderServiceOptions ], ]; - protected $order_model = NULL; + protected string $order_model = NULL; */ public function orderValidation(Request $request): ?Model diff --git a/app/Traits/ProductDetails.php b/app/Traits/ProductDetails.php index 9ada39a..dd8146f 100644 --- a/app/Traits/ProductDetails.php +++ b/app/Traits/ProductDetails.php @@ -16,6 +16,6 @@ trait ProductDetails */ public function getBillingIntervalStringAttribute(): string { - return Invoice::billing_name(self::getBillingIntervalAttribute()); + return Invoice::billing_name(static::getBillingIntervalAttribute()); } } \ No newline at end of file diff --git a/database/migrations/2021_12_20_225017_optimize_product.php b/database/migrations/2021_12_20_225017_optimize_product.php index 11f9683..3b837a0 100644 --- a/database/migrations/2021_12_20_225017_optimize_product.php +++ b/database/migrations/2021_12_20_225017_optimize_product.php @@ -13,7 +13,6 @@ class OptimizeProduct extends Migration */ public function up() { - /* Schema::table('ab_product', function (Blueprint $table) { $table->dropForeign(['site_id']); $table->dropIndex(['id','site_id']); @@ -30,11 +29,13 @@ class OptimizeProduct extends Migration $table->dateTime('updated_at')->nullable()->after('created_at'); }); + DB::statement('ALTER TABLE suppliers MODIFY address1 varchar(255),MODIFY city varchar(255),MODIFY state varchar(255),MODIFY postcode varchar(255)'); + Schema::table('supplier_details', function (Blueprint $table) { $table->jsonb('connections')->nullable(); }); - foreach (\Illuminate\Support\Facades\DB::select('SELECT * FROM AB_ADSL_SUPPLIER') as $o) { + foreach (\Illuminate\Support\Facades\DB::select('SELECT * FROM ab_adsl_supplier') as $o) { switch($o->name) { case 'PeopleAgent': $type = 'broadband'; @@ -66,15 +67,7 @@ class OptimizeProduct extends Migration } $so = \App\Models\Supplier::where('name',$name)->singleOrNew(); - - if (! $so->exists) { - $so->name = $name; - $so->address1 = '...'; - $so->city = '...'; - $so->state = '...'; - $so->postcode = '...'; - } - + $so->name = $name; $so->active = $so->active ?: $o->active; $so->save(); @@ -134,7 +127,7 @@ class OptimizeProduct extends Migration \Illuminate\Support\Facades\DB::select("UPDATE products SET model='App\\\\Models\\\\Product\\\\Broadband' where model='App\\\\Models\\\\Product\\\\Adsl'"); // Convert to use the new supplier - foreach (\Illuminate\Support\Facades\DB::select('SELECT * FROM AB_ADSL_SUPPLIER') as $o) { + foreach (\Illuminate\Support\Facades\DB::select('SELECT * FROM ab_adsl_supplier') as $o) { switch ($o->name) { case 'PeopleAgent': $so = \App\Models\Supplier::where('name','People Telecom')->singleOrFail(); @@ -278,9 +271,347 @@ class OptimizeProduct extends Migration Schema::table('products', function (Blueprint $table) { $table->dropColumn(['date_orig','date_last','group_avail','avail_category','price_recurr_day','price_recurr_weekday','prod_plugin_file']); }); - */ + Schema::dropIfExists('ab_voip_plan'); - abort(500,'here'); + Schema::create('tlds',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->string('name',64)->unique(); + }); + + Schema::create('supplier_domain',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->boolean('active'); + $table->integer('supplier_detail_id')->unsigned(); + $table->string('product_id',16); + $table->string('product_desc',128)->nullable(); + $table->float('base_cost'); + $table->float('setup_cost')->nullable(); + $table->integer('contract_term')->unsigned()->nullable(); + $table->integer('tld_id')->unsigned(); + $table->text('whois_url')->nullable(); + $table->text('config')->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['tld_id'])->references(['id'])->on('tlds'); + $table->foreign(['supplier_detail_id','site_id'])->references(['id','site_id'])->on('supplier_details'); + }); + Schema::create('supplier_host',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->boolean('active'); + $table->integer('supplier_detail_id')->unsigned(); + $table->string('product_id',16); + $table->string('product_desc',128)->nullable(); + $table->float('base_cost'); + $table->float('setup_cost')->nullable(); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_detail_id','site_id'])->references(['id','site_id'])->on('supplier_details'); + }); + Schema::create('supplier_ssl',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->boolean('active'); + $table->integer('supplier_detail_id')->unsigned(); + $table->string('product_id',16); + $table->string('product_desc',128)->nullable(); + $table->float('base_cost'); + $table->float('setup_cost')->nullable(); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_detail_id','site_id'])->references(['id','site_id'])->on('supplier_details'); + }); + Schema::create('supplier_generic',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->boolean('active'); + $table->integer('supplier_detail_id')->unsigned(); + $table->string('product_id',16); + $table->string('product_desc',128)->nullable(); + $table->float('base_cost'); + $table->float('setup_cost')->nullable(); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_detail_id','site_id'])->references(['id','site_id'])->on('supplier_details'); + }); + Schema::create('supplier_voip',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->boolean('active'); + $table->integer('supplier_detail_id')->unsigned(); + $table->string('product_id',16); + $table->string('product_desc',128)->nullable(); + $table->float('base_cost'); + $table->float('setup_cost')->nullable(); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_detail_id','site_id'])->references(['id','site_id'])->on('supplier_details'); + }); + + Schema::create('product_domain',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->integer('supplier_domain_id')->unsigned(); + $table->string('name',64); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_domain_id','site_id'])->references(['id','site_id'])->on('supplier_domain'); + }); + Schema::create('product_host',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->integer('supplier_host_id')->unsigned(); + $table->string('name',64); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_host_id','site_id'])->references(['id','site_id'])->on('supplier_host'); + }); + Schema::create('product_ssl',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->integer('supplier_ssl_id')->unsigned(); + $table->string('name',64); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_ssl_id','site_id'])->references(['id','site_id'])->on('supplier_ssl'); + }); + Schema::create('product_generic',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->integer('supplier_generic_id')->unsigned(); + $table->string('name',64); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_generic_id','site_id'])->references(['id','site_id'])->on('supplier_generic'); + }); + Schema::create('product_voip',function (Blueprint $table) { + $table->integer('id',TRUE)->unsigned(); + $table->timestamps(); + $table->integer('site_id')->unsigned(); + $table->integer('supplier_voip_id')->unsigned(); + $table->string('name',64); + $table->integer('contract_term')->unsigned()->nullable(); + + $table->index(['id','site_id']); + $table->foreign(['site_id'])->references(['id'])->on('sites'); + $table->foreign(['supplier_voip_id','site_id'])->references(['id','site_id'])->on('supplier_voip'); + }); + + // Setup Domains + foreach (\Illuminate\Support\Facades\DB::select('SELECT * FROM ab_domain_tld') as $o) { + $oo = new \App\Models\TLD; + + if ($o->date_orig) + $oo->created_at = \Carbon\Carbon::createFromTimestamp($o->date_orig); + if ($o->date_last) + $oo->created_at = \Carbon\Carbon::createFromTimestamp($o->date_last); + + $oo->name = strtolower($o->name); + $oo->save(); + }; + + foreach (\Illuminate\Support\Facades\DB::select('SELECT * FROM ab_domain_registrar') as $o) { + $so = \App\Models\Supplier::where('name',$o->name)->singleOrNew(); + $so->name = $o->name; + $so->active = $so->active ?: $o->active; + $so->save(); + + $sdo = \App\Models\SupplierDetail::withoutGlobalScope(\App\Models\Scopes\SiteScope::class) + ->where('supplier_id',$so->id) + ->where('site_id',1) + ->firstOrNew(); + + $sdo->site_id = 1; + $connects = collect(); + if ($o->whitelabel_url) + $connects->put('whitelabel_url',$o->whitelabel_url); + if ($o->manage_url) + $connects->put('manage_url',$o->manage_url); + + $sdo->connections = $connects; + $so->detail()->save($sdo); + + foreach (\App\Models\TLD::cursor() as $tldo) { + $sd = \App\Models\Supplier\Domain::withoutGlobalScope(\App\Models\Scopes\SiteScope::class) + ->where('tld_id',$tldo->id) + ->where('site_id',$sdo->site_id) + ->where('supplier_detail_id',$sdo->id) + ->firstOrNew(); + + $sd->supplier_detail_id = $sdo->id; + $sd->tld_id = $tldo->id; + $sd->site_id = $sdo->site_id; + $sd->active = TRUE; + $sd->product_id = 'Domain Name'; + $sd->product_desc = 'Domain Name License'; + $sd->base_cost = '.01'; + $sd->contract_term = 12; + + $sd->save(); + + $pd = \App\Models\Product\Domain::withoutGlobalScope(\App\Models\Scopes\SiteScope::class) + ->where('site_id',$sdo->site_id) + ->where('supplier_domain_id',$sd->id) + ->firstOrNew(); + + $pd->supplier_domain_id = $sd->id; + $pd->site_id = $sd->site_id; + $pd->name = $sd->name; + + $pd->save(); + } + } + + // SSL + $so = \App\Models\Supplier::where('name','Graytech Hosting Pty Ltd')->firstOrNew(); + $so->name = 'Graytech Hosting Pty Ltd'; + $so->active = TRUE; + $so->save(); + + $sdo = \App\Models\SupplierDetail::withoutGlobalScope(\App\Models\Scopes\SiteScope::class) + ->where('site_id','1') + ->where('supplier_id',$so->id) + ->firstOrNew(); + $sdo->site_id = 1; + $so->detail()->save($sdo); + + $o = new \App\Models\Supplier\SSL; + $o->site_id = $sdo->site_id; + $o->active = TRUE; + $o->product_id = 'Graytech SSL'; + $o->base_cost = 0; + $o->setup_cost = 0; + $o->supplier_detail_id = $sdo->id; + $o->save(); + + $oo = new \App\Models\Product\SSL; + $oo->site_id = $sdo->site_id; + $oo->supplier_ssl_id = $o->id; + $oo->name = 'Graytech SSL'; + $oo->save(); + + $o = new \App\Models\Supplier\Host; + $o->site_id = $sdo->site_id; + $o->active = TRUE; + $o->product_id = 'Graytech Hosting'; + $o->base_cost = 0; + $o->setup_cost = 0; + $o->supplier_detail_id = $sdo->id; + $o->save(); + + $oo = new \App\Models\Product\Host; + $oo->site_id = $sdo->site_id; + $oo->supplier_host_id = $o->id; + $oo->name = 'Graytech Hosting'; + $oo->save(); + + $so = \App\Models\Supplier::where('name','crazydomain')->firstOrFail(); + $sdo = \App\Models\SupplierDetail::withoutGlobalScope(\App\Models\Scopes\SiteScope::class) + ->where('site_id','1') + ->where('supplier_id',$so->id) + ->firstOrNew(); + $sdo->site_id = 1; + $so->detail()->save($sdo); + + $o = new \App\Models\Supplier\Host; + $o->site_id = $sdo->site_id; + $o->active = TRUE; + $o->product_id = 'CD Host'; + $o->base_cost = 0; + $o->supplier_detail_id = $sdo->id; + $o->save(); + + $oo = new \App\Models\Product\Host; + $oo->site_id = $sdo->site_id; + $oo->supplier_host_id = $o->id; + $oo->name = 'Crazy Domains Hosting'; + $oo->save(); + + // VOIP + $so = \App\Models\Supplier::where('name','Exetel')->firstOrFail(); + $sdo = \App\Models\SupplierDetail::withoutGlobalScope(\App\Models\Scopes\SiteScope::class) + ->where('site_id','1') + ->where('supplier_id',$so->id) + ->firstOrNew(); + $sdo->site_id = 1; + $so->detail()->save($sdo); + + $o = new \App\Models\Supplier\Voip; + $o->site_id = $sdo->site_id; + $o->active = TRUE; + $o->product_id = 'VOIP $10'; + $o->base_cost = 9.09; + $o->setup_cost = 0; + $o->supplier_detail_id = $sdo->id; + $o->save(); + + $oo = new \App\Models\Product\Voip; + $oo->site_id = $sdo->site_id; + $oo->supplier_voip_id = $o->id; + $oo->name = 'VOIP $10'; + $oo->save(); + + $o = new \App\Models\Supplier\Voip; + $o->site_id = $sdo->site_id; + $o->active = TRUE; + $o->product_id = 'VOIP'; + $o->base_cost = 0; + $o->setup_cost = 0; + $o->supplier_detail_id = $sdo->id; + $o->save(); + + $oo = new \App\Models\Product\Voip; + $oo->site_id = $sdo->site_id; + $oo->supplier_voip_id = $o->id; + $oo->name = 'VOIP'; + $oo->save(); + + $o = new \App\Models\Supplier\Voip; + $o->site_id = $sdo->site_id; + $o->active = TRUE; + $o->product_id = 'VOIP B-100'; + $o->product_desc = 'VOIP Business 100 Lines'; + $o->base_cost = 22.727; + $o->setup_cost = 0; + $o->supplier_detail_id = $sdo->id; + $o->save(); + + $oo = new \App\Models\Product\Voip; + $oo->site_id = $sdo->site_id; + $oo->supplier_voip_id = $o->id; + $oo->name = 'VOIP B-10'; + $oo->save(); + + // Manually run this, since we havent worked out site_id when running migrate. + // update products set model_id=49,model='App\\Models\\Product\\Domain' where id=78; } /** @@ -290,6 +621,6 @@ class OptimizeProduct extends Migration */ public function down() { - //abort(500,'Cant go back'); + abort(500,'Cant go back'); } } diff --git a/resources/views/theme/backend/adminlte/a/service/widgets/broadband/update.blade.php b/resources/views/theme/backend/adminlte/a/service/widgets/broadband/update.blade.php new file mode 100644 index 0000000..6bef20d --- /dev/null +++ b/resources/views/theme/backend/adminlte/a/service/widgets/broadband/update.blade.php @@ -0,0 +1,71 @@ +
{!! $o->description !!}
+{!! $o->name_long !!}