diff --git a/app/Console/Commands/ServiceList.php b/app/Console/Commands/ServiceList.php index 8e1d946..da3417b 100644 --- a/app/Console/Commands/ServiceList.php +++ b/app/Console/Commands/ServiceList.php @@ -40,22 +40,23 @@ class ServiceList extends Command 'Type', 'Product', 'Name', - 'active', - 'status', - 'invoice next', - 'start date', - 'stop date', - 'connect date', - 'first invoice' + 'Active', + 'Status', + 'Next Invoice', + 'Start Date', + 'Stop Date', + 'Connect Date', + 'First Invoice' )); foreach (Service::withoutGlobalScope(\App\Models\Scopes\SiteScope::class)->with(['site'])->cursor() as $o) { + //dd($o,$o->site); if ((! $this->option('inactive')) AND ! $o->isActive()) continue; Config::set('site',$o->site); - if ($this->option('type') AND ($o->product->getProductTypeAttribute() !== $this->option('type'))) + if ($this->option('type') AND ($o->product->getCategoryAttribute() !== $this->option('type'))) continue; $c = $o->invoice_items->filter(function($item) {return $item->item_type === 0; })->sortby('start_at')->first(); @@ -67,14 +68,14 @@ class ServiceList extends Command $this->info(sprintf($header, $o->sid, - $o->product->getProductTypeAttribute(), + $o->product->getCategoryNameAttribute(), substr($o->product->getNameAttribute(),0,35), substr($o->name_short,0,40), $o->active ? 'active' : 'inactive', $o->status, - $o->invoice_next ? $o->invoice_next->format('Y-m-d') : NULL, - $o->start_at ? $o->start_at->format('Y-m-d') : NULL, - $o->stop_at ? $o->stop_at->format('Y-m-d') : NULL, + $o->invoice_next?->format('Y-m-d'), + $o->start_at?->format('Y-m-d'), + $o->stop_at?->format('Y-m-d'), ($o->type AND $o->type->connect_at) ? $o->type->connect_at->format('Y-m-d') : NULL, ($c && $c->date_start) ? $c->date_start->format('Y-m-d') : NULL, )); diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 94b3395..8db3f39 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -294,12 +294,12 @@ class ServiceController extends Controller */ 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($o->product->category)) { + $o->type->forceFill($request->post($o->product->category))->save(); } if ($request->post('start_at')) - $o->date_start = $request->start_at; + $o->start_at = $request->start_at; $o->save(); diff --git a/app/Interfaces/SupplierItem.php b/app/Interfaces/SupplierItem.php index b43e5b3..096a43f 100644 --- a/app/Interfaces/SupplierItem.php +++ b/app/Interfaces/SupplierItem.php @@ -77,11 +77,4 @@ interface SupplierItem * @return float */ public function getSetupCostTaxableAttribute(): float; - - /** - * Return the type of offering this is. - * - * @return string - */ - public function getTypeAttribute(); } \ No newline at end of file diff --git a/app/Models/Account.php b/app/Models/Account.php index 5d03261..92e17c0 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -149,6 +149,11 @@ class Account extends Model implements IDs return $this->company ?: ($this->user_id ? $this->user->getSurFirstNameAttribute() : 'LID:'.$this->id); } + /** + * Return the type of account this is - if it has a company name, then its a business account. + * + * @return string + */ public function getTypeAttribute() { return $this->company ? 'Business' : 'Private'; diff --git a/app/Models/Product.php b/app/Models/Product.php index 89da219..702acf3 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -26,6 +26,8 @@ use App\Traits\{ProductDetails,SiteID}; * Attributes for products: * + lid : Local ID for product (part number) * + sid : System ID for product (part number) + * + category : Type of product supplied + * + category_name : Type of product supplied (Friendly Name for display, not for internal logic) * + supplied : Supplier product provided for this offering * + supplier : Supplier for this offering * + name : Brief Name for our product // @todo we should change this to be consistent with service @@ -97,6 +99,7 @@ class Product extends Model implements IDs /** * Return a child model with details of the service + * This will return a product/* model. * * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ @@ -176,6 +179,29 @@ class Product extends Model implements IDs return max($this->price_recur_default,$this->getSuppliedAttribute()->getBillingIntervalAttribute()); } + /** + * 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'; + } + + /** + * 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 + * @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'; + } + /** * How long must this product be purchased for as a service. * @@ -241,17 +267,6 @@ class Product extends Model implements IDs return $this->description->description_full; } - /** - * Get our product type - * - * @return string - * @todo is the test of type and type->supplied necessary? (It seems some hosting entries have no type, are they old?) - */ - public function getProductTypeAttribute(): string - { - return ($this->type && $this->type->supplied) ? $this->getSuppliedAttribute()->getTypeAttribute() : 'Unknown'; - } - /** * Suppliers * diff --git a/app/Models/Product/Broadband.php b/app/Models/Product/Broadband.php index 46e444b..25514ed 100644 --- a/app/Models/Product/Broadband.php +++ b/app/Models/Product/Broadband.php @@ -15,6 +15,8 @@ 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'=>[ diff --git a/app/Models/Product/Domain.php b/app/Models/Product/Domain.php index a4fdabc..97d46af 100644 --- a/app/Models/Product/Domain.php +++ b/app/Models/Product/Domain.php @@ -12,6 +12,8 @@ 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; @@ -57,11 +59,6 @@ final class Domain extends Type implements ProductItem return ''; } - public function getTypeAttribute() - { - return 'Domain Name'; - } - public function hasUsage(): bool { return FALSE; diff --git a/app/Models/Product/Email.php b/app/Models/Product/Email.php index 7d3b955..e6d5cd7 100644 --- a/app/Models/Product/Email.php +++ b/app/Models/Product/Email.php @@ -12,6 +12,8 @@ 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; @@ -57,11 +59,6 @@ final class Email extends Type implements ProductItem return ''; } - public function getTypeAttribute() - { - return 'Domain Name'; - } - public function hasUsage(): bool { return FALSE; diff --git a/app/Models/Product/Generic.php b/app/Models/Product/Generic.php index 0750957..dcd62a0 100644 --- a/app/Models/Product/Generic.php +++ b/app/Models/Product/Generic.php @@ -12,6 +12,8 @@ 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; @@ -34,11 +36,6 @@ final class Generic extends Type implements ProductItem return 0; } - public function getTypeAttribute() - { - return 'Generic'; - } - public function hasUsage(): bool { return FALSE; diff --git a/app/Models/Product/Host.php b/app/Models/Product/Host.php index 093a0c8..e42397f 100644 --- a/app/Models/Product/Host.php +++ b/app/Models/Product/Host.php @@ -12,6 +12,8 @@ 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; @@ -34,11 +36,6 @@ final class Host extends Type implements ProductItem return 12; } - public function getTypeAttribute() - { - return 'Hosting'; - } - public function hasUsage(): bool { return FALSE; diff --git a/app/Models/Product/Phone.php b/app/Models/Product/Phone.php index 1b6c84b..af17f53 100644 --- a/app/Models/Product/Phone.php +++ b/app/Models/Product/Phone.php @@ -12,6 +12,8 @@ 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', @@ -62,11 +64,6 @@ final class Phone extends Type implements ProductItem return 12; } - public function getTypeAttribute() - { - return 'PHONE'; - } - public function hasUsage(): bool { return FALSE; diff --git a/app/Models/Product/SSL.php b/app/Models/Product/SSL.php index 5e44d7f..64e260e 100644 --- a/app/Models/Product/SSL.php +++ b/app/Models/Product/SSL.php @@ -12,6 +12,8 @@ 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; @@ -61,11 +63,6 @@ final class SSL extends Type implements ProductItem return $o; } - public function getTypeAttribute() - { - return 'SSL Certificate'; - } - public function hasUsage(): bool { return FALSE; diff --git a/app/Models/Product/Type.php b/app/Models/Product/Type.php index 092fe92..125afa4 100644 --- a/app/Models/Product/Type.php +++ b/app/Models/Product/Type.php @@ -26,4 +26,25 @@ abstract class Type extends Model { return $this->morphOne(Product::class, null,'model','model_id'); } + + /** + * 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; + } } \ No newline at end of file diff --git a/app/Models/Service.php b/app/Models/Service.php index bd58e0a..cdf26b1 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -20,6 +20,7 @@ use Leenooks\Carbon as LeenooksCarbon; use App\Interfaces\IDs; use App\Traits\ScopeServiceUserAuthorised; +use App\Traits\SiteID; /** * Class Service @@ -50,7 +51,7 @@ use App\Traits\ScopeServiceUserAuthorised; */ class Service extends Model implements IDs { - use HasFactory,ScopeServiceUserAuthorised; + use HasFactory,ScopeServiceUserAuthorised,SiteID; protected $casts = [ 'order_info'=>AsCollection::class, @@ -472,25 +473,6 @@ class Service extends Model implements IDs return number_format($this->getBillingChargeAttribute()/Arr::get(Invoice::billing_periods,$this->recur_schedule.'.interval',1),2); } - /** - * Return the type of service is provided. eg: Broadband, Phone. - * - * @return string - */ - public function getCategoryAttribute(): string - { - switch ($x=$this->type->getTypeAttribute()) { - case 'ssl': - $type = 'SSL'; - break; - - default: - $type = ucfirst($x); - } - - return $type; - } - /** * The date the contract ends * @@ -707,16 +689,9 @@ class Service extends Model implements IDs */ public function getInvoiceToAttribute(): ?LeenooksCarbon { - $result = ($x=$this->invoice_items->filter(function($item) { return $item->item_type === 0;}))->count() + return ($x=$this->invoice_items->filter(function($item) { return $item->item_type === 0;}))->count() ? $x->last()->stop_at : NULL; - - // For SSL Certificates, the invoice_to date is the expiry date of the Cert - // @todo can we use the expire_at attribute? - if (is_null($result) AND $this->type AND $this->type->type == 'ssl' AND $this->type->expire_at) - return $this->type->expire_at; - - return $result; } /** diff --git a/app/Models/Service/Broadband.php b/app/Models/Service/Broadband.php index 883105f..8e68cf6 100644 --- a/app/Models/Service/Broadband.php +++ b/app/Models/Service/Broadband.php @@ -105,12 +105,13 @@ class Broadband extends Type implements ServiceUsage * Return the suppliers offering that this service is providing * * @return SupplierType + * @todo This column provided_adsl_plan_id should either be deprecated or renamed. */ public function supplied(): SupplierType { return $this->provided_adsl_plan_id ? SupplierBroadband::findOrFail($this->provided_adsl_plan_id) - : $this->service->product->type->supplied; + : $this->service->offering->supplied; } /** diff --git a/app/Models/Service/Type.php b/app/Models/Service/Type.php index c953a2e..46841a8 100644 --- a/app/Models/Service/Type.php +++ b/app/Models/Service/Type.php @@ -91,11 +91,6 @@ abstract class Type extends Model implements ServiceItem return LeenooksCarbon::create($value); } - public function getTypeAttribute() - { - return strtolower((new \ReflectionClass($this))->getShortName()); - } - /* METHODS */ /** @@ -105,6 +100,6 @@ abstract class Type extends Model implements ServiceItem */ public function supplied(): SupplierType { - return $this->service->product->type->supplied; + return $this->service->offering->supplied ?: new \App\Models\Supplier\Generic(); } } \ No newline at end of file diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php index e658867..e21350f 100644 --- a/app/Models/Supplier.php +++ b/app/Models/Supplier.php @@ -16,7 +16,11 @@ class Supplier extends Model public $timestamps = FALSE; - /* The offerings we provide */ + /** + * 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. + */ public const offering_types = [ 'broadband' => [ 'name' => 'Broadband', diff --git a/app/Models/Supplier/Type.php b/app/Models/Supplier/Type.php index b0d13c0..5ee41d8 100644 --- a/app/Models/Supplier/Type.php +++ b/app/Models/Supplier/Type.php @@ -63,9 +63,4 @@ abstract class Type extends Model { 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/resources/views/theme/backend/adminlte/a/product/details.blade.php b/resources/views/theme/backend/adminlte/a/product/details.blade.php index eee57a3..5771cc8 100644 --- a/resources/views/theme/backend/adminlte/a/product/details.blade.php +++ b/resources/views/theme/backend/adminlte/a/product/details.blade.php @@ -26,11 +26,7 @@
Type | -{{ $o->product_type }} | +{{ $o->category_name }} |
---|---|---|
Setup Charges * | @@ -30,9 +30,13 @@||
- * Additional setup charges may apply for complex installations. - + Additional charges may apply for regional installations. - | ||
+
+ * Additional setup charges may apply for complex installations. + + Additional charges may apply for regional installations. + + |
+
{!! $o->name_long !!}
+Type | +{{ $o->category_name }} | +
---|---|
Setup Charges * | +${{ number_format($o->setup_charge_taxable,2) }} | +
Cost + | +${{ number_format($o->base_charge_taxable,2) }} | +
Default Billing | +{{ $o->billing_interval_string }} | +
Contract Term | +{{ $o->contract_term }} mths | +
Minimum Costs +* | +${{ number_format($o->min_charge_taxable,2) }} | +
{!! $o->name_long !!}
+Type | +{{ $o->category_name }} | +
---|---|
Setup Charges * | +${{ number_format($o->setup_charge_taxable,2) }} | +
Cost + | +${{ number_format($o->base_charge_taxable,2) }} | +
Default Billing | +{{ $o->billing_interval_string }} | +
Contract Term | +{{ $o->contract_term }} mths | +
Minimum Costs +* | +${{ number_format($o->min_charge_taxable,2) }} | +
{!! $o->name_long !!}
+Type | +{{ $o->category_name }} | +
---|---|
Setup Charges * | +${{ number_format($o->setup_charge_taxable,2) }} | +
Cost + | +${{ number_format($o->base_charge_taxable,2) }} | +
Default Billing | +{{ $o->billing_interval_string }} | +
Contract Term | +{{ $o->contract_term }} mths | +
Minimum Costs +* | +${{ number_format($o->min_charge_taxable,2) }} | +
Type | -{{ $o->product_type }} | +{{ $o->category_name }} |
---|---|---|
Setup Charges | diff --git a/resources/views/theme/frontend/metronic/order/widget/order.blade.php b/resources/views/theme/frontend/metronic/order/widget/order.blade.php index e8661c9..7711434 100644 --- a/resources/views/theme/frontend/metronic/order/widget/order.blade.php +++ b/resources/views/theme/frontend/metronic/order/widget/order.blade.php @@ -1,5 +1,5 @@ - -@if(View::exists('order.widget.order.'.strtolower($o->product_type))) + +@if(View::exists('order.widget.order.'.$o->category))