Service cancellation and ordering
This commit is contained in:
parent
b2e45fcaee
commit
f7439172b6
@ -2,21 +2,211 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Arr;
|
use Illuminate\Support\Arr;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
|
use App\Mail\{CancelRequest,ChangeRequest};
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
|
||||||
class ServiceController extends Controller
|
class ServiceController extends Controller
|
||||||
{
|
{
|
||||||
|
/* SERVICE WORKFLOW METHODS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a request to cancel a service
|
||||||
|
*
|
||||||
|
* @param Service $o
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function action_cancel_cancel(Service $o): bool
|
||||||
|
{
|
||||||
|
if (! $o->order_info)
|
||||||
|
$o->order_info = collect();
|
||||||
|
|
||||||
|
$o->order_info->put('cancel_cancel',Carbon::now()->format('Y-m-d H:i:s'));
|
||||||
|
$o->order_status = 'ACTIVE';
|
||||||
|
|
||||||
|
return $o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a request to change a service
|
||||||
|
*
|
||||||
|
* @param Service $o
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function action_change_cancel(Service $o): bool
|
||||||
|
{
|
||||||
|
if (! $o->order_info)
|
||||||
|
$o->order_info = collect();
|
||||||
|
|
||||||
|
$o->order_info->put('change_cancel',Carbon::now()->format('Y-m-d H:i:s'));
|
||||||
|
$o->order_status = 'ACTIVE';
|
||||||
|
|
||||||
|
return $o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to change a service order_status to another stage
|
||||||
|
* This is a generic function that can redirect the user to a page that is required to completed to enter
|
||||||
|
* the new stage
|
||||||
|
*
|
||||||
|
* @param Service $o
|
||||||
|
* @param string $stage
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
private function action_request_enter_redirect(Service $o,string $stage)
|
||||||
|
{
|
||||||
|
return redirect(sprintf('u/service/%d/%s',$o->id,strtolower($stage)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OTHER METHODS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a request to cancel a service
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Service $o
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function cancel_request(Request $request,Service $o)
|
||||||
|
{
|
||||||
|
if ($request->post()) {
|
||||||
|
$request->validate([
|
||||||
|
'date_end'=>'required|date',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (! $o->order_info)
|
||||||
|
$o->order_info = collect();
|
||||||
|
|
||||||
|
$o->date_end = $request->date_end;
|
||||||
|
$o->order_info->put('cancel_note',$request->notes);
|
||||||
|
$o->order_status = 'CANCEL-REQUEST';
|
||||||
|
$o->save();
|
||||||
|
|
||||||
|
//@todo Get email from DB.
|
||||||
|
Mail::to('help@graytech.net.au')
|
||||||
|
->queue((new CancelRequest($o,$request->notes))->onQueue('email'));
|
||||||
|
|
||||||
|
return redirect('u/service/'.$o->id)->with('success','Cancellation lodged');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('u.service.cancel_request')
|
||||||
|
->with('o',$o);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change the status of a service
|
||||||
|
*
|
||||||
|
* @note This route is protected by middleware @see ServicePolicy::progress()
|
||||||
|
* It is assumed that the next stage is valid for the services current stage - validated in ServicePolicy::progress()
|
||||||
|
* @param Service $o
|
||||||
|
* @param string $stage
|
||||||
|
* @return RedirectResponse
|
||||||
|
*/
|
||||||
|
public function change(Service $o,string $stage): RedirectResponse
|
||||||
|
{
|
||||||
|
// While stage has a string value, that indicates the next stage we want to go to
|
||||||
|
// If stage is NULL, the current stage hasnt been completed
|
||||||
|
// If stage is FALSE, then the current stage failed, and may optionally be directed to another stage.
|
||||||
|
|
||||||
|
while ($stage) {
|
||||||
|
// Check that stage is a valid next action for the user currently performing it
|
||||||
|
//$current = $this->getStageParameters($this->order_status);
|
||||||
|
$next = $o->getStageParameters($stage);
|
||||||
|
|
||||||
|
// If valid, call the method to confirm that the current stage is complete
|
||||||
|
if ($x=$next->get('enter_method')) {
|
||||||
|
if (! method_exists($this,$x))
|
||||||
|
abort(500,sprintf('ENTER_METHOD [%s]defined doesnt exist',$x));
|
||||||
|
|
||||||
|
Log::debug(sprintf('Running ENTER_METHOD [%s] on Service [%d] to go to stage [%s]',$x,$o->id,$stage));
|
||||||
|
|
||||||
|
// @todo Should call exit_method of the current stage first, to be sure we can change
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = $this->{$x}($o,$stage);
|
||||||
|
|
||||||
|
// If we have a form to complete, we need to return with a URL, so we can catch that with an Exception
|
||||||
|
} catch (HttpException $e) {
|
||||||
|
if ($e->getStatusCode() == 301)
|
||||||
|
return ($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// An Error Condition
|
||||||
|
if (is_null($result))
|
||||||
|
return redirect()->to('u/service/'.$o->id);
|
||||||
|
|
||||||
|
elseif ($result instanceof RedirectResponse)
|
||||||
|
return $result;
|
||||||
|
|
||||||
|
// The service cannot enter the next stage
|
||||||
|
elseif (! $result)
|
||||||
|
abort(500,'Current Method FAILED: '.$result);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$o->order_status = $stage;
|
||||||
|
$o->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If valid, call the method to start the next stage
|
||||||
|
$stage = ''; // @todo this is temporary, we havent written the code to automatically jump to the next stage if wecan
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->to('u/service/'.$o->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a request to cancel a service
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Service $o
|
||||||
|
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
*/
|
||||||
|
public function change_request(Request $request,Service $o)
|
||||||
|
{
|
||||||
|
if ($request->post()) {
|
||||||
|
$request->validate([
|
||||||
|
'change_date'=>'required|date',
|
||||||
|
'notes'=>'required|min:10',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (! $o->order_info)
|
||||||
|
$o->order_info = collect();
|
||||||
|
|
||||||
|
$o->order_info->put('change_note',$request->notes);
|
||||||
|
$o->order_info->put('change_date',$request->change_date);
|
||||||
|
$o->order_status = 'CHANGE-REQUEST';
|
||||||
|
$o->save();
|
||||||
|
|
||||||
|
//@todo Get email from DB.
|
||||||
|
Mail::to('help@graytech.net.au')
|
||||||
|
->queue((new ChangeRequest($o,$request->notes))->onQueue('email'));
|
||||||
|
|
||||||
|
return redirect('u/service/'.$o->id)->with('success','Upgrade requested');
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (get_class($o->type)) {
|
||||||
|
default:
|
||||||
|
return view('u.service.change_request')
|
||||||
|
->with('o',$o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit a domain service details
|
* Edit a domain service details
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Service $o
|
* @param Service $o
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return RedirectResponse
|
||||||
|
* @todo revalidate
|
||||||
*/
|
*/
|
||||||
public function domain_edit(Request $request,Service $o)
|
public function domain_edit(Request $request,Service $o)
|
||||||
{
|
{
|
||||||
@ -49,6 +239,7 @@ class ServiceController extends Controller
|
|||||||
* List all the domains managed by the user
|
* List all the domains managed by the user
|
||||||
*
|
*
|
||||||
* @return View
|
* @return View
|
||||||
|
* @todo revalidate
|
||||||
*/
|
*/
|
||||||
public function domain_list(): View
|
public function domain_list(): View
|
||||||
{
|
{
|
||||||
@ -62,95 +253,4 @@ class ServiceController extends Controller
|
|||||||
return view('r.service.domain.list')
|
return view('r.service.domain.list')
|
||||||
->with('o',$o);
|
->with('o',$o);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update a service
|
|
||||||
*
|
|
||||||
* @note: Route Middleware protects this path
|
|
||||||
* @param Request $request
|
|
||||||
* @param Service $o
|
|
||||||
* @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
|
|
||||||
*/
|
|
||||||
public function update(Request $request,Service $o)
|
|
||||||
{
|
|
||||||
switch ($o->order_status) {
|
|
||||||
case 'CANCEL-REQUEST':
|
|
||||||
if ($request->post()) {
|
|
||||||
if (! $request->post('date_end'))
|
|
||||||
return redirect()->back()->withErrors('Cancellation Date not provided');
|
|
||||||
|
|
||||||
$o->date_end = $request->post('date_end');
|
|
||||||
|
|
||||||
foreach (['cancel_notes'] as $key) {
|
|
||||||
if ($request->post($key))
|
|
||||||
$o->setOrderInfo($key,$request->post($key));
|
|
||||||
}
|
|
||||||
|
|
||||||
$o->order_status='CANCEL-PENDING';
|
|
||||||
$o->save();
|
|
||||||
|
|
||||||
return redirect()->to(url('u/service',$o->id))->with('updated','Service cancellation submitted.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->update_request_cancel($o);
|
|
||||||
|
|
||||||
case 'ORDER-SENT':
|
|
||||||
if ($request->post()) {
|
|
||||||
foreach (['reference','notes'] as $key) {
|
|
||||||
$o->setOrderInfo($key,$request->post($key));
|
|
||||||
}
|
|
||||||
|
|
||||||
$o->save();
|
|
||||||
|
|
||||||
foreach ($request->post($o->stype) as $k=>$v) {
|
|
||||||
$o->type->{$k} = $v;
|
|
||||||
}
|
|
||||||
|
|
||||||
$o->type->save();
|
|
||||||
|
|
||||||
return redirect()->to(url('u/service',$o->id))->with('updated','Order sent notes updated.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->update_order_status($o);
|
|
||||||
|
|
||||||
case 'PROVISION-PLANNED':
|
|
||||||
if ($request->post()) {
|
|
||||||
foreach (['provision_notes'] as $key) {
|
|
||||||
$o->setOrderInfo($key,$request->post($key));
|
|
||||||
}
|
|
||||||
|
|
||||||
$o->date_start = $request->post('date_start');
|
|
||||||
|
|
||||||
$o->save();
|
|
||||||
|
|
||||||
foreach ($request->post($o->stype) as $k=>$v) {
|
|
||||||
$o->type->{$k} = $v;
|
|
||||||
}
|
|
||||||
|
|
||||||
$o->type->save();
|
|
||||||
|
|
||||||
return redirect()->to(url('u/service',$o->id))->with('updated','Order sent notes updated.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->update_provision_planned($o);
|
|
||||||
|
|
||||||
default:
|
|
||||||
abort(499,'Not yet implemented');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function update_order_status(Service $o)
|
|
||||||
{
|
|
||||||
return View('r.service.order.sent',['o'=>$o]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function update_request_cancel(Service $o)
|
|
||||||
{
|
|
||||||
return View('u.service.order.cancel',['o'=>$o]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function update_provision_planned(Service $o)
|
|
||||||
{
|
|
||||||
return View('r.service.order.provision_plan',['o'=>$o]);
|
|
||||||
}
|
|
||||||
}
|
}
|
56
app/Mail/CancelRequest.php
Normal file
56
app/Mail/CancelRequest.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
use App\Models\Service;
|
||||||
|
|
||||||
|
class CancelRequest extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public Service $service;
|
||||||
|
public string $notes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param Service $o
|
||||||
|
* @param string $notes
|
||||||
|
*/
|
||||||
|
public function __construct(Service $o,string $notes='')
|
||||||
|
{
|
||||||
|
$this->service = $o;
|
||||||
|
$this->notes = $notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
switch (get_class($this->service->type)) {
|
||||||
|
case 'App\Models\Service\Adsl':
|
||||||
|
$subject = sprintf('CANCEL NBN: %s',$this->service->type->service_address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'App\Models\Service\Voip':
|
||||||
|
$subject = sprintf('CANCEL VOIP: %s',$this->service->type->service_number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$subject = 'Cancel Service Request';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->markdown('email.admin.service.cancel')
|
||||||
|
->subject($subject)
|
||||||
|
->with(['site'=>$this->service->site]);
|
||||||
|
}
|
||||||
|
}
|
56
app/Mail/ChangeRequest.php
Normal file
56
app/Mail/ChangeRequest.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Mail;
|
||||||
|
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
use App\Models\Service;
|
||||||
|
|
||||||
|
class ChangeRequest extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public Service $service;
|
||||||
|
public string $notes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*
|
||||||
|
* @param Service $o
|
||||||
|
* @param string $notes
|
||||||
|
*/
|
||||||
|
public function __construct(Service $o,string $notes='')
|
||||||
|
{
|
||||||
|
$this->service = $o;
|
||||||
|
$this->notes = $notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
switch (get_class($this->service->type)) {
|
||||||
|
case 'App\Models\Service\Adsl':
|
||||||
|
$subject = sprintf('Change NBN: %s',$this->service->type->service_address);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'App\Models\Service\Voip':
|
||||||
|
$subject = sprintf('Change VOIP: %s',$this->service->type->service_number);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
$subject = 'Change Service Request';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->markdown('email.admin.service.change')
|
||||||
|
->subject($subject)
|
||||||
|
->with(['site'=>$this->service->site]);
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,9 @@
|
|||||||
namespace App\Mail;
|
namespace App\Mail;
|
||||||
|
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
|
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
|
||||||
@ -13,8 +13,8 @@ class OrderRequest extends Mailable
|
|||||||
{
|
{
|
||||||
use Queueable, SerializesModels;
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
public $service;
|
public Service $service;
|
||||||
public $notes;
|
public string $notes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new message instance.
|
* Create a new message instance.
|
||||||
@ -22,7 +22,7 @@ class OrderRequest extends Mailable
|
|||||||
* @param Service $o
|
* @param Service $o
|
||||||
* @param string $notes
|
* @param string $notes
|
||||||
*/
|
*/
|
||||||
public function __construct(Service $o,$notes='')
|
public function __construct(Service $o,string $notes='')
|
||||||
{
|
{
|
||||||
$this->service = $o;
|
$this->service = $o;
|
||||||
$this->notes = $notes;
|
$this->notes = $notes;
|
||||||
@ -35,8 +35,7 @@ class OrderRequest extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
switch (get_class($this->service->type))
|
switch (get_class($this->service->type)) {
|
||||||
{
|
|
||||||
case 'App\Models\Service\Adsl':
|
case 'App\Models\Service\Adsl':
|
||||||
$subject = sprintf('NBN: %s',$this->service->type->service_address);
|
$subject = sprintf('NBN: %s',$this->service->type->service_address);
|
||||||
break;
|
break;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Illuminate\Database\Eloquent\Casts\AsCollection;
|
||||||
use Illuminate\Database\Eloquent\Collection as DatabaseCollection;
|
use Illuminate\Database\Eloquent\Collection as DatabaseCollection;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@ -62,7 +63,7 @@ class Service extends Model implements IDs
|
|||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'order_info'=>'collection',
|
'order_info'=>AsCollection::class,
|
||||||
];
|
];
|
||||||
public $dateFormat = 'U';
|
public $dateFormat = 'U';
|
||||||
|
|
||||||
@ -106,16 +107,30 @@ class Service extends Model implements IDs
|
|||||||
/**
|
/**
|
||||||
* Valid status shows the applicable next status for an action on a service
|
* Valid status shows the applicable next status for an action on a service
|
||||||
* Each status can be
|
* Each status can be
|
||||||
* + Approved, to proceed to the next valid status'
|
*
|
||||||
* + Held, to a holding pattern status
|
* The structure of each item is:
|
||||||
* + Rejected, reverted to an different status
|
* <ORDER_STATUS> => [
|
||||||
* + Cancel, to progress down a decomission route
|
* 'next' == next possible levels, initiated by who (array).
|
||||||
* + Updated, stay on the current status with new information
|
* who = 'role','system'
|
||||||
|
* 'enter_method' == the method run when we enter this stage - could be used to send email for example, if this method doesnt complete successfully, we dont enter this stage
|
||||||
|
* + If it returns NULL, An error condition
|
||||||
|
* + If it returns FALSE, the service cannot enter this stage
|
||||||
|
* + If it returns TRUE, the service has successfully changed to this stage
|
||||||
|
* + If it returns a VIEW/REDIRECT, that resulting page will handle the status change
|
||||||
|
* 'exit_method' == the method that determines that the order can leave this status (true = can, false = cant)
|
||||||
|
* + If it returns NULL, An error condition
|
||||||
|
* + If it returns FALSE, the service CANNOT leave this stage
|
||||||
|
* + If it returns TRUE, the service CAN leave this stage
|
||||||
|
* it will receive the next method as an argument
|
||||||
|
* 'title' == title shown on the menu, for the user to choose
|
||||||
|
* ]
|
||||||
|
* So when an order goes to the next state, the exit method will be tested immediately (if there is only 1 exit method for the user)
|
||||||
|
* to see if it can proceed further if not, it'll wait here for user/admin intervention
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public static $action_progress = [
|
private const ACTION_PROGRESS = [
|
||||||
// Order Submitted
|
// Order Submitted @todo redo
|
||||||
'ORDER-SUBMIT' => [
|
'ORDER-SUBMIT' => [
|
||||||
'fail'=>FALSE,
|
'fail'=>FALSE,
|
||||||
// Progress to next stages by who
|
// Progress to next stages by who
|
||||||
@ -128,7 +143,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_order_submit',
|
'method'=>'action_order_submit',
|
||||||
'title'=>'Order Submit',
|
'title'=>'Order Submit',
|
||||||
],
|
],
|
||||||
// Client accepts order, if performed by RW
|
// Client accepts order, if performed by RW @todo redo
|
||||||
'ORDER-ACCEPT' => [
|
'ORDER-ACCEPT' => [
|
||||||
'fail'=>FALSE,
|
'fail'=>FALSE,
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -138,7 +153,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_order_accept',
|
'method'=>'action_order_accept',
|
||||||
'title'=>'Client Accept Order',
|
'title'=>'Client Accept Order',
|
||||||
],
|
],
|
||||||
// If the product has a setup, collect payment information
|
// If the product has a setup, collect payment information @todo redo
|
||||||
'SETUP-PAYMENT-WAIT' => [
|
'SETUP-PAYMENT-WAIT' => [
|
||||||
'fail'=>FALSE,
|
'fail'=>FALSE,
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -148,6 +163,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_setup_payment_wait',
|
'method'=>'action_setup_payment_wait',
|
||||||
'title'=>'Setup Payment',
|
'title'=>'Setup Payment',
|
||||||
],
|
],
|
||||||
|
// @todo redo
|
||||||
'PAYMENT-WAIT' => [
|
'PAYMENT-WAIT' => [
|
||||||
'fail'=>FALSE,
|
'fail'=>FALSE,
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -157,6 +173,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_payment_wait',
|
'method'=>'action_payment_wait',
|
||||||
'title'=>'Service Payment',
|
'title'=>'Service Payment',
|
||||||
],
|
],
|
||||||
|
// @todo redo
|
||||||
'PAYMENT-CHECK' => [
|
'PAYMENT-CHECK' => [
|
||||||
'fail'=>'ORDER-HOLD',
|
'fail'=>'ORDER-HOLD',
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -166,13 +183,13 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_payment_check',
|
'method'=>'action_payment_check',
|
||||||
'title'=>'Validate Payment Method',
|
'title'=>'Validate Payment Method',
|
||||||
],
|
],
|
||||||
// Order On Hold (Reason)
|
// Order On Hold (Reason) @todo redo
|
||||||
'ORDER-HOLD' => ['release'=>'ORDER-SUBMIT','update_reference'=>'ORDER-SENT'],
|
'ORDER-HOLD' => ['release'=>'ORDER-SUBMIT','update_reference'=>'ORDER-SENT'],
|
||||||
// Order Rejected (Reason)
|
// Order Rejected (Reason) @todo redo
|
||||||
'ORDER-REJECTED' => [],
|
'ORDER-REJECTED' => [],
|
||||||
// Order Cancelled
|
// Order Cancelled @todo redo
|
||||||
'ORDER-CANCELLED' => [],
|
'ORDER-CANCELLED' => [],
|
||||||
// Order Sent to Supplier
|
// Order Sent to Supplier @todo redo
|
||||||
'ORDER-SENT' => [
|
'ORDER-SENT' => [
|
||||||
'fail'=>'ORDER-HOLD',
|
'fail'=>'ORDER-HOLD',
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -182,7 +199,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_order_sent',
|
'method'=>'action_order_sent',
|
||||||
'title'=>'Send Order',
|
'title'=>'Send Order',
|
||||||
],
|
],
|
||||||
// Order Confirmed by Supplier
|
// Order Confirmed by Supplier @todo redo
|
||||||
'ORDERED' => [
|
'ORDERED' => [
|
||||||
'fail'=>false,
|
'fail'=>false,
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -194,7 +211,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_ordered',
|
'method'=>'action_ordered',
|
||||||
'title'=>'Service Ordered',
|
'title'=>'Service Ordered',
|
||||||
],
|
],
|
||||||
// Service confirmed by supplier, optional connection date
|
// Service confirmed by supplier, optional connection date @todo redo
|
||||||
'PROVISION-PLANNED' => [
|
'PROVISION-PLANNED' => [
|
||||||
'fail'=>false,
|
'fail'=>false,
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -204,7 +221,7 @@ class Service extends Model implements IDs
|
|||||||
'method'=>'action_provision_planned',
|
'method'=>'action_provision_planned',
|
||||||
'title'=>'Provision Planned',
|
'title'=>'Provision Planned',
|
||||||
],
|
],
|
||||||
// Service has been provisioned by supplier
|
// Service has been provisioned by supplier @todo redo
|
||||||
'PROVISIONED' => [
|
'PROVISIONED' => [
|
||||||
'fail'=>false,
|
'fail'=>false,
|
||||||
'next'=>[
|
'next'=>[
|
||||||
@ -216,34 +233,56 @@ class Service extends Model implements IDs
|
|||||||
],
|
],
|
||||||
// Service is Active
|
// Service is Active
|
||||||
'ACTIVE' => [
|
'ACTIVE' => [
|
||||||
'fail'=>FALSE,
|
|
||||||
'next'=>[
|
'next'=>[
|
||||||
'UPGRADE-REQUEST'=>['customer'],
|
|
||||||
'CANCEL-REQUEST'=>['customer'],
|
'CANCEL-REQUEST'=>['customer'],
|
||||||
|
'CHANGE-REQUEST'=>['customer'],
|
||||||
],
|
],
|
||||||
'system'=>FALSE,
|
'exit'=>'action_active_exit',
|
||||||
'method'=>'action_active',
|
|
||||||
'title'=>'Service Active',
|
'title'=>'Service Active',
|
||||||
],
|
],
|
||||||
// Service to be Upgraded
|
// Service to be Upgraded
|
||||||
'UPGRADE-REQUEST' => [
|
'CANCEL-CANCEL' => [
|
||||||
'fail'=>FALSE,
|
|
||||||
'next'=>[
|
'next'=>[
|
||||||
'UPGRADE-PENDING'=>[],
|
'ACTIVE'=>['wholesaler'],
|
||||||
],
|
],
|
||||||
'system'=>FALSE,
|
'enter_method'=>'action_cancel_cancel',
|
||||||
'method'=>FALSE,
|
'title'=>'Cancel Cancellation Request',
|
||||||
'title'=>'Upgrade Service',
|
|
||||||
],
|
],
|
||||||
// Service to be Cancelled
|
// Service to be Cancelled
|
||||||
'CANCEL-REQUEST' => [
|
'CANCEL-REQUEST' => [
|
||||||
'fail'=>FALSE,
|
|
||||||
'next'=>[
|
'next'=>[
|
||||||
'CANCEL-PENDING'=>[],
|
'CANCEL-CANCEL'=>['wholesaler'],
|
||||||
|
'CANCEL-PENDING'=>['wholesaler'],
|
||||||
],
|
],
|
||||||
'system'=>FALSE,
|
'enter_method'=>'action_request_enter_redirect',
|
||||||
'method'=>'action_cancel_request',
|
'exit_method'=>'action_cancel_request_exit',
|
||||||
'title'=>'Cancel Service',
|
'title'=>'Cancel Request',
|
||||||
|
],
|
||||||
|
// Service Cancellation being processed
|
||||||
|
'CANCEL-PENDING' => [
|
||||||
|
'next'=>[
|
||||||
|
'CANCELLED'=>['wholesaler'],
|
||||||
|
],
|
||||||
|
'enter_method'=>'action_cancel_pending_enter',
|
||||||
|
'exit_method'=>'action_cancel_pending_exit',
|
||||||
|
'title'=>'Cancel Pending',
|
||||||
|
],
|
||||||
|
// Service to be Upgraded
|
||||||
|
'CHANGE-CANCEL' => [
|
||||||
|
'next'=>[
|
||||||
|
'ACTIVE'=>['wholesaler'],
|
||||||
|
],
|
||||||
|
'enter_method'=>'action_change_cancel',
|
||||||
|
'title'=>'Cancel Change Request',
|
||||||
|
],
|
||||||
|
// Service to be Upgraded
|
||||||
|
'CHANGE-REQUEST' => [
|
||||||
|
'next'=>[
|
||||||
|
'CHANGE-PENDING'=>['wholesaler'],
|
||||||
|
'CHANGE-CANCEL'=>['wholesaler'],
|
||||||
|
],
|
||||||
|
'enter_method'=>'action_request_enter_redirect',
|
||||||
|
'title'=>'Change Service',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -906,36 +945,13 @@ class Service extends Model implements IDs
|
|||||||
$this->attributes['date_last'] = $value->timestamp;
|
$this->attributes['date_last'] = $value->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GENERAL METHODS */
|
/* METHODS */
|
||||||
|
|
||||||
// The action methods will return: NULL for no progress|FALSE for a failed status|next stage name.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Action required before order can leave the ACTIVE status.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function action_active(): ?bool
|
|
||||||
{
|
|
||||||
// N/A
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request cancellation for an order when status ACTIVE stage.
|
|
||||||
* This method should have the client confirm/accept the cancellation, if it was placed by a reseller/wholesaler.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function action_cancel_request(): ?bool
|
|
||||||
{
|
|
||||||
throw new HttpException(301,url('u/service/cancel',$this->id));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Processing when service has been ordered.
|
* Processing when service has been ordered.
|
||||||
*
|
*
|
||||||
* @return bool|null
|
* @return bool|null
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_ordered(): ?bool
|
private function action_ordered(): ?bool
|
||||||
{
|
{
|
||||||
@ -948,6 +964,7 @@ class Service extends Model implements IDs
|
|||||||
* This method should have the client confirm/accept the order, if it was placed by a reseller/wholesaler.
|
* This method should have the client confirm/accept the order, if it was placed by a reseller/wholesaler.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_order_accept(): ?bool
|
private function action_order_accept(): ?bool
|
||||||
{
|
{
|
||||||
@ -958,6 +975,8 @@ class Service extends Model implements IDs
|
|||||||
/**
|
/**
|
||||||
* Action method when status ORDER_SENT
|
* Action method when status ORDER_SENT
|
||||||
* This method redirects to a form, where updating the form will progress to the next stage.
|
* This method redirects to a form, where updating the form will progress to the next stage.
|
||||||
|
*
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_order_sent(string $next)
|
private function action_order_sent(string $next)
|
||||||
{
|
{
|
||||||
@ -972,6 +991,7 @@ class Service extends Model implements IDs
|
|||||||
* Action method when status ORDER_SUBMIT
|
* Action method when status ORDER_SUBMIT
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_order_submit(): ?bool
|
private function action_order_submit(): ?bool
|
||||||
{
|
{
|
||||||
@ -984,6 +1004,7 @@ class Service extends Model implements IDs
|
|||||||
*
|
*
|
||||||
* @param string $next
|
* @param string $next
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_provision_planned(string $next)
|
private function action_provision_planned(string $next)
|
||||||
{
|
{
|
||||||
@ -995,6 +1016,7 @@ class Service extends Model implements IDs
|
|||||||
* This method should collect any setup fees payment.
|
* This method should collect any setup fees payment.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_setup_payment_wait(): ?bool
|
private function action_setup_payment_wait(): ?bool
|
||||||
{
|
{
|
||||||
@ -1007,6 +1029,7 @@ class Service extends Model implements IDs
|
|||||||
* This method should validate any payment details.
|
* This method should validate any payment details.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_payment_check(): ?bool
|
private function action_payment_check(): ?bool
|
||||||
{
|
{
|
||||||
@ -1019,6 +1042,7 @@ class Service extends Model implements IDs
|
|||||||
* This method should collect any service payment details.
|
* This method should collect any service payment details.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @todo Check
|
||||||
*/
|
*/
|
||||||
private function action_payment_wait(): ?bool
|
private function action_payment_wait(): ?bool
|
||||||
{
|
{
|
||||||
@ -1026,145 +1050,78 @@ class Service extends Model implements IDs
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Work out the next applicable actions for this service status, taking into account the user's role
|
||||||
|
*
|
||||||
|
* @notes
|
||||||
|
* + Clients can only progress 1 step, if they are in the next step.
|
||||||
|
* + Resellers/Wholesales can progress to the next Reseller/Wholesaler and any steps in between.
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function actions(): Collection
|
||||||
|
{
|
||||||
|
$next = $this->getStageParameters($this->order_status)->get('next');
|
||||||
|
return $next
|
||||||
|
? $next->map(function($item,$key) {
|
||||||
|
$authorized = FALSE;
|
||||||
|
|
||||||
|
if ($x=Arr::get(self::ACTION_PROGRESS,$key))
|
||||||
|
foreach ($item as $role) {
|
||||||
|
if ($this->isAuthorised($role)) {
|
||||||
|
$authorized = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $authorized ? $x['title'] : NULL;
|
||||||
|
})->filter()->sort()
|
||||||
|
: collect();
|
||||||
|
}
|
||||||
|
|
||||||
private function getOrderInfoValue(string $key): ?string
|
private function getOrderInfoValue(string $key): ?string
|
||||||
{
|
{
|
||||||
return $this->order_info ? $this->order_info->get($key) : NULL;
|
return $this->order_info ? $this->order_info->get($key) : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current stage parameters
|
* Get the stage parameters
|
||||||
*
|
*
|
||||||
* @param string $stage
|
* @param string $stage
|
||||||
* @return array
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
private function getStageParameters(string $stage): Collection
|
public function getStageParameters(string $stage): Collection
|
||||||
{
|
{
|
||||||
$result = collect(Arr::get(self::$action_progress,$stage));
|
$result = Arr::get(self::ACTION_PROGRESS,$stage);
|
||||||
$myrole = array_search(Auth::user()->role(),User::$role_order);
|
$myrole = array_search(Auth::user()->role(),User::$role_order);
|
||||||
|
|
||||||
// If we have no valid next stage, return an empty collection.
|
// If we have no valid next stage, return an empty collection.
|
||||||
if (! $result->count() OR $myrole===FALSE)
|
if (($myrole === FALSE) || (! $result))
|
||||||
return $result;
|
return collect();
|
||||||
|
|
||||||
// Filter the result based on who we are
|
// Filter the result based on who we are
|
||||||
$next = collect();
|
$next = collect();
|
||||||
|
|
||||||
foreach ($result->get('next') as $action=>$roles) {
|
if (array_key_exists('next',$result) && count($result['next'])) {
|
||||||
|
foreach ($result['next'] as $action => $roles) {
|
||||||
|
// Can the current user do this role?
|
||||||
|
$cando = FALSE;
|
||||||
|
|
||||||
// Can the current user do this role?
|
foreach ($roles as $role) {
|
||||||
$cando = FALSE;
|
if ($myrole <= array_search($role,User::$role_order)) {
|
||||||
foreach ($roles as $role) {
|
$cando = TRUE;
|
||||||
if ($myrole <= array_search($role,User::$role_order)) {
|
|
||||||
$cando = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($cando OR $result->get('system')) {
|
break;
|
||||||
$next->put($action,$roles);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result->put('next',$next);
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @notes
|
|
||||||
* + When progressing stages, we know who the user is that initiated the stage,
|
|
||||||
* + If no user, then we perform stages SYSTEM=TRUE
|
|
||||||
* + We need to validate that the current stage is complete, before progressing to the next stage
|
|
||||||
* + The current stage may require input from a user, or automation process to progress
|
|
||||||
* + Before leaving this method, we update the service with the stage that it is currently on.
|
|
||||||
*
|
|
||||||
* @param string $stage
|
|
||||||
* @return bool|int|string|null
|
|
||||||
*/
|
|
||||||
public function action(string $stage)
|
|
||||||
{
|
|
||||||
// While stage has a string value, that indicates the next stage we want to go to
|
|
||||||
// If stage is NULL, the current stage hasnt been completed
|
|
||||||
// If stage is FALSE, then the current stage failed, and may optionally be directed to another stage.
|
|
||||||
|
|
||||||
while ($stage) {
|
|
||||||
// Check that stage is a valid next action for the user currently performing it
|
|
||||||
$current = $this->getStageParameters($this->order_status);
|
|
||||||
$next = $this->getStageParameters($stage);
|
|
||||||
|
|
||||||
// If valid, call the method to confirm that the current stage is complete
|
|
||||||
if (method_exists($this,$current['method'])) {
|
|
||||||
try {
|
|
||||||
$result = $this->{$current['method']}($stage);
|
|
||||||
|
|
||||||
// If we have a form to complete, we need to return with a URL, so we can catch that with an Exception
|
|
||||||
} catch (HttpException $e) {
|
|
||||||
if ($e->getStatusCode() == 301)
|
|
||||||
return ($e->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo Implement a status message
|
|
||||||
if (is_null($result)) {
|
|
||||||
$stage = NULL;
|
|
||||||
abort(500,'Current Method Cannot Proceed: '.$result);
|
|
||||||
|
|
||||||
// @todo Implement a status message
|
|
||||||
} elseif (! $result) {
|
|
||||||
$stage = NULL;
|
|
||||||
abort(500,'Current Method FAILED: '.$result);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$this->order_status = $stage;
|
|
||||||
$this->save();
|
|
||||||
|
|
||||||
// If we have more than 1 next step for the next stage, we'll have to end.
|
|
||||||
if ($this->actions()->count() > 1) {
|
|
||||||
$stage = NULL;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$stage = $this->actions()->keys()->first();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo Implement a status message
|
if ($cando)
|
||||||
} else {
|
$next->put($action,$roles);
|
||||||
// Cant do anything, dont have a method to check if we can leave
|
|
||||||
$stage = NULL;
|
|
||||||
abort(500,'NO Method Cannot Proceed to leave this stage: '.$current['method']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If valid, call the method to start the next stage
|
$result['next'] = $next;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Work out the next applicable actions for this service status
|
|
||||||
*
|
|
||||||
* @notes
|
|
||||||
* + Clients can only progress 1 step, if they are in the next step.
|
|
||||||
* + Resellers/Wholesales can progress to the next Reseller/Wholesaler and any steps in between.
|
|
||||||
*
|
|
||||||
* @param bool $next Only show next actions
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
public function actions(): Collection
|
|
||||||
{
|
|
||||||
$result = collect();
|
|
||||||
$action = $this->getStageParameters($this->order_status);
|
|
||||||
|
|
||||||
if (! $action->count())
|
|
||||||
return $result;
|
|
||||||
|
|
||||||
// Next Action
|
|
||||||
foreach ($this->getStageParameters($this->order_status)->get('next') as $k=>$v) {
|
|
||||||
$result->put($k,Arr::get(self::$action_progress,$k.'.title'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No next actions, that will mean the current action hasnt completed.
|
return collect($result);
|
||||||
if (! $result->count())
|
|
||||||
$result->put($this->order_status,Arr::get($action,'title'));
|
|
||||||
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1209,6 +1166,54 @@ class Service extends Model implements IDs
|
|||||||
return $this->active OR ($this->order_status AND ! in_array($this->order_status,$this->inactive_status));
|
return $this->active OR ($this->order_status AND ! in_array($this->order_status,$this->inactive_status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the current user has the role for this service
|
||||||
|
*
|
||||||
|
* @param string $role
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isAuthorised(string $role): bool
|
||||||
|
{
|
||||||
|
switch(Auth::user()->role()) {
|
||||||
|
// Wholesalers are site admins, they can see everything
|
||||||
|
case 'wholesaler':
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case 'reseller':
|
||||||
|
switch ($role) {
|
||||||
|
case 'wholesaler':
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Check service is in the resellers/customers list
|
||||||
|
case 'reseller':
|
||||||
|
case 'customer':
|
||||||
|
dd(['m'=>__METHOD__,'not written']);
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort(500,'Unknown role for reseller: '.$role);
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'customer':
|
||||||
|
switch ($role) {
|
||||||
|
case 'reseller':
|
||||||
|
case 'wholesaler':
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
// Check service is in the customers list
|
||||||
|
case 'customer':
|
||||||
|
dd(['m'=>__METHOD__,'not written']);
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort(500,'Unknown role for customer: '.$role);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
abort(500,'Unknown user role: ',Auth::user()->role());
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do we bill for this service
|
* Do we bill for this service
|
||||||
*
|
*
|
||||||
|
26
resources/views/email/admin/service/cancel.blade.php
Normal file
26
resources/views/email/admin/service/cancel.blade.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@component('mail::message',['site'=>$site,'heading'=>'Cancel Service Request'])
|
||||||
|
Please cancel the following...
|
||||||
|
|
||||||
|
@component('mail::table')
|
||||||
|
| Service | Details |
|
||||||
|
| :---------- | :---------------- |
|
||||||
|
| Account | {{ $service->account_name }} ({!! $service->account->account_id_url !!}) |
|
||||||
|
| Service ID | {!! $service->service_id_url !!} |
|
||||||
|
| Product | {{ $service->product_name }} |
|
||||||
|
@switch($service->product_category)
|
||||||
|
@case('ADSL')
|
||||||
|
| Address | {{ $service->type->service_address }} |
|
||||||
|
@break;
|
||||||
|
@case('VOIP')
|
||||||
|
| Number | {{ $service->type->service_number }} |
|
||||||
|
| Supplier Details | {{ $service->order_info->join(':') }} |
|
||||||
|
@break;
|
||||||
|
@endswitch
|
||||||
|
@endcomponent
|
||||||
|
|
||||||
|
|
||||||
|
**NOTES:** {{ $notes }}
|
||||||
|
|
||||||
|
Thanks,<br>
|
||||||
|
{{ config('app.name') }}
|
||||||
|
@endcomponent
|
26
resources/views/email/admin/service/change.blade.php
Normal file
26
resources/views/email/admin/service/change.blade.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
@component('mail::message',['site'=>$site,'heading'=>'Cancel Service Request'])
|
||||||
|
Please change the following...
|
||||||
|
|
||||||
|
@component('mail::table')
|
||||||
|
| Service | Details |
|
||||||
|
| :---------- | :---------------- |
|
||||||
|
| Account | {{ $service->account_name }} ({!! $service->account->account_id_url !!}) |
|
||||||
|
| Service ID | {!! $service->service_id_url !!} |
|
||||||
|
| Product | {{ $service->product_name }} |
|
||||||
|
@switch($service->product_category)
|
||||||
|
@case('ADSL')
|
||||||
|
| Address | {{ $service->type->service_address }} |
|
||||||
|
@break;
|
||||||
|
@case('VOIP')
|
||||||
|
| Number | {{ $service->type->service_number }} |
|
||||||
|
| Supplier Details | {{ $service->order_info->join(':') }} |
|
||||||
|
@break;
|
||||||
|
@endswitch
|
||||||
|
@endcomponent
|
||||||
|
|
||||||
|
|
||||||
|
**NOTES:** {{ $notes }}
|
||||||
|
|
||||||
|
Thanks,<br>
|
||||||
|
{{ config('app.name') }}
|
||||||
|
@endcomponent
|
@ -27,7 +27,7 @@
|
|||||||
@include('common.service.widget.error')
|
@include('common.service.widget.error')
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<form class="form-horizontal" method="post" action="{{ url('r/service/update',$o->id) }}">
|
<form class="form-horizontal" method="POST">
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
|
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -48,9 +48,9 @@
|
|||||||
--}}
|
--}}
|
||||||
|
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="notes" class="col-sm-2 col-form-label text-right">Notes</label>
|
<label for="notes" class="col-2 col-form-label text-right">Notes</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-10">
|
||||||
<textarea class="textarea" name="cancel_notes">{{ $o->order_info_notes ?? '' }}</textarea>
|
<textarea class="form-control" rows="4" name="notes">{{ $o->order_info_notes ?? '' }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -67,8 +67,6 @@
|
|||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('page-scripts')
|
@section('page-scripts')
|
||||||
@css('//cdnjs.cloudflare.com/ajax/libs/summernote/0.8.12/summernote-bs4.css','summernote-css')
|
|
||||||
@js('//cdnjs.cloudflare.com/ajax/libs/summernote/0.8.12/summernote-bs4.js','summernote-js')
|
|
||||||
@js('//cdn.jsdelivr.net/momentjs/latest/moment.min.js','moment-js')
|
@js('//cdn.jsdelivr.net/momentjs/latest/moment.min.js','moment-js')
|
||||||
@js('//cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js','daterange-js')
|
@js('//cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js','daterange-js')
|
||||||
@css('//cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css','daterange-css')
|
@css('//cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css','daterange-css')
|
||||||
@ -83,18 +81,6 @@
|
|||||||
format: 'YYYY-MM-DD'
|
format: 'YYYY-MM-DD'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.textarea').summernote({
|
|
||||||
minHeight: 350,
|
|
||||||
toolbar: [
|
|
||||||
['style', ['style']],
|
|
||||||
['font', ['bold', 'underline', 'clear']],
|
|
||||||
['color', ['color']],
|
|
||||||
['para', ['ul', 'ol', 'paragraph']],
|
|
||||||
['table', ['table']],
|
|
||||||
['view', ['codeview', 'help']],
|
|
||||||
],
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@append
|
@append
|
@ -0,0 +1,86 @@
|
|||||||
|
@extends('adminlte::layouts.app')
|
||||||
|
|
||||||
|
@section('htmlheader_title')
|
||||||
|
{{ $o->sid }}
|
||||||
|
@endsection
|
||||||
|
@section('page_title')
|
||||||
|
{{ $o->sid }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('contentheader_title')
|
||||||
|
Service: {{ $o->sid }} <strong>{{ $o->product->name }}</strong>
|
||||||
|
@endsection
|
||||||
|
@section('contentheader_description')
|
||||||
|
{{ $o->sname }}: {{ $o->sdesc }}
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('main-content')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="card-title">Change Service</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Errors -->
|
||||||
|
@if ($errors->any())
|
||||||
|
@include('common.service.widget.error')
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<form class="form-horizontal" method="POST">
|
||||||
|
{{ csrf_field() }}
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="reference" class="col-sm-2 col-form-label text-right">Request Change Date</label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
||||||
|
</div>
|
||||||
|
<input type="text" class="form-control" id="datestop" name="change_date" value="{{ ($x=\Carbon\Carbon::now()->addDays(7)) ? $x->format('Y-m-d') : '' }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{--
|
||||||
|
@includeIf('u.service.widgets.'.$o->stype.'.order',['o'=>$o->type])
|
||||||
|
--}}
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="notes" class="col-2 col-form-label text-right">Notes</label>
|
||||||
|
<div class="col-10">
|
||||||
|
<textarea class="form-control" rows="4" name="notes" placeholder="Please let us know what you would like to change your service to">{{ $o->order_info_notes ?? '' }}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card-footer">
|
||||||
|
<button type="reset" class="btn btn-secondary mr-2" onclick="window.history.go(-1); return false;">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-success">Submit</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('page-scripts')
|
||||||
|
@js('//cdn.jsdelivr.net/momentjs/latest/moment.min.js','moment-js')
|
||||||
|
@js('//cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js','daterange-js')
|
||||||
|
@css('//cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css','daterange-css')
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('#datestop').daterangepicker({
|
||||||
|
singleDatePicker: true,
|
||||||
|
showDropdowns: true,
|
||||||
|
minDate: moment().add(7,'days'),
|
||||||
|
locale: {
|
||||||
|
format: 'YYYY-MM-DD'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@append
|
@ -49,14 +49,12 @@
|
|||||||
|
|
||||||
@can('update',$o)
|
@can('update',$o)
|
||||||
<ul class="nav nav-pills ml-auto p-2">
|
<ul class="nav nav-pills ml-auto p-2">
|
||||||
|
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">
|
<a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#">ACTION <span class="caret"></span></a>
|
||||||
ACTION <span class="caret"></span>
|
|
||||||
</a>
|
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
@foreach($o->actions() as $action => $title)
|
@foreach($o->actions() as $stage => $title)
|
||||||
<a class="dropdown-item" tabindex="-1" href="{{ url('u/service/progress',['id'=>$o->id,'action'=>$action]) }}">{{ $title }}</a>
|
<a class="dropdown-item" tabindex="-1" href="{{ url('u/service',['id'=>$o->id,'action'=>'change','stage'=>$stage]) }}">{{ $title }}</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
{{-- <div class="dropdown-divider"></div> --}}
|
{{-- <div class="dropdown-divider"></div> --}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -61,9 +61,6 @@ Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix
|
|||||||
// Route::get('supplier/create','SuppliersController@create');
|
// Route::get('supplier/create','SuppliersController@create');
|
||||||
// Route::post('supplier/store','SuppliersController@store');
|
// Route::post('supplier/store','SuppliersController@store');
|
||||||
Route::get('switch/start/{id}',[LeenooksAdminController::class,'user_switch_start'])->name('switch.user.stop');
|
Route::get('switch/start/{id}',[LeenooksAdminController::class,'user_switch_start'])->name('switch.user.stop');
|
||||||
// Route::match(['get','post'],'service/update/{o}','ServiceController@update')
|
|
||||||
// ->where('o','[0-9]+')
|
|
||||||
// ->middleware('can:update,o');
|
|
||||||
|
|
||||||
Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix'=>'report'],function() {
|
Route::group(['middleware'=>['theme:adminlte-be','auth','role:reseller'],'prefix'=>'report'],function() {
|
||||||
Route::get('domain',[ServiceController::class,'domain_list']);
|
Route::get('domain',[ServiceController::class,'domain_list']);
|
||||||
@ -93,10 +90,13 @@ Route::group(['middleware'=>['theme:adminlte-be','auth'],'prefix'=>'u'],function
|
|||||||
Route::get('service/{o}',[HomeController::class,'service'])
|
Route::get('service/{o}',[HomeController::class,'service'])
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:view,o');
|
->middleware('can:view,o');
|
||||||
// Route::get('service/cancel/{o}','ServiceController@update')
|
Route::match(['get','post'],'service/{o}/cancel-request',[ServiceController::class,'cancel_request'])
|
||||||
// ->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
// ->middleware('can:update,o');
|
->middleware('can:update,o');
|
||||||
Route::get('service/progress/{o}/{status}',[HomeController::class,'service_progress'])
|
Route::match(['get','post'],'service/{o}/change-request',[ServiceController::class,'change_request'])
|
||||||
|
->where('o','[0-9]+')
|
||||||
|
->middleware('can:update,o');
|
||||||
|
Route::get('service/{o}/change/{status}',[ServiceController::class,'change'])
|
||||||
->where('o','[0-9]+')
|
->where('o','[0-9]+')
|
||||||
->middleware('can:progress,o,status');
|
->middleware('can:progress,o,status');
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user