osb/app/Http/Controllers/ServiceController.php

294 lines
8.3 KiB
PHP

<?php
namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\View\View;
use Symfony\Component\HttpKernel\Exception\HttpException;
use App\Mail\{CancelRequest,ChangeRequest};
use App\Models\Service;
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_info->put('change_product_id',$request->product_id);
$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
*
* @param Request $request
* @param Service $o
* @return RedirectResponse
* @deprecated - use update()
*/
public function domain_edit(Request $request,Service $o)
{
session()->flash('service_update',TRUE);
$validation = $request->validate([
'service.domain_name' => ['required',function($attribute,$value,$fail) use ($request,$o) {
if (Service\Domain::where('domain_name',$value)
->where('domain_tld_id',Arr::get($request,'service.domain_tld_id'))
->when($o->type,function($q) use ($o) { return $q->where('id','<>',$o->type->id); })
->count() > 0)
{
$fail('Domain already exists.');
}
}],
'service.domain_expire' => 'required|date',
'service.domain_tld_id' => 'required|exists:ab_domain_tld,id',
'service.domain_registrar_id' => 'required|exists:ab_domain_registrar,id',
'service.registrar_account' => 'required',
'service.registrar_username' => 'required|string|min:5',
'service.registrar_ns' => 'required|string|min:5',
]);
$o->type->forceFill($validation['service'])->save();
return redirect()->back()->with('success','Record updated.');
}
/**
* List all the domains managed by the user
*
* @return View
* @todo revalidate
*/
public function domain_list(): View
{
$o = Service\Domain::serviceActive()
->serviceUserAuthorised(Auth::user())
->select('service_domains.*')
->join('ab_service',['ab_service.id'=>'service_domains.service_id'])
->with(['service.account','registrar'])
->get();
return view('r.service.domain.list')
->with('o',$o);
}
public function email_list(): View
{
// @todo Need to add the with path when calculating next_billed and price
$o = Service\Email::serviceActive()
->serviceUserAuthorised(Auth::user())
->select('service_emails.*')
->join('ab_service',['ab_service.id'=>'service_emails.service_id'])
->with(['service.account','service.product.type.supplied.supplier_detail.supplier','tld'])
->get();
return view('r.service.email.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');
}
}