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 */ public function change_pending(ServiceChangeRequest $request,Service $o) { if ($request->post()) { foreach ($this->service_change_charges($request,$o) as $co) $co->save(); $o->product_id = Arr::get($request->broadband,'product_id'); $o->order_status = 'ACTIVE'; $o->save(); return redirect()->to(url('u/service',[$o->id])); } return view('service.change_pending') ->with('breadcrumb',collect()->merge($o->account->breadcrumb)) ->with('o',$o); } /** * 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([ 'stop_at'=>'required|date', ]); if (! $o->order_info) $o->order_info = collect(); $o->stop_at = $request->stop_at; $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('service.cancel_request') ->with('o',$o); } /** * Change the status of a service * @todo This needs to be optimized * * @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; if ($stage == 'ACTIVE') $o->active = TRUE; $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('service.change_request') ->with('breadcrumb',collect()->merge($o->account->breadcrumb)) ->with('o',$o); } } /** * 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_domain.*') ->join('services',['services.id'=>'service_domain.service_id']) ->with(['service.account','registrar']) ->get(); return view('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_email.*') ->join('services',['services.id'=>'service_email.service_id']) ->with(['service.account','service.product.type.supplied.supplier_detail.supplier','tld']) ->get(); return view('service.email.list') ->with('o',$o); } /** * Return details on the users service * * @param Service $o * @return View */ public function home(Service $o): View { return View('service.home') ->with('breadcrumb',collect()->merge($o->account->breadcrumb)) ->with('o',$o); } public function hosting_list(): View { // @todo Need to add the with path when calculating next_billed and price $o = Service\Host::serviceActive() ->serviceUserAuthorised(Auth::user()) ->select('service_host.*') ->join('services',['services.id'=>'service_host.service_id']) ->with(['service.account','service.product.type.supplied.supplier_detail.supplier','tld']) ->get(); return view('service.host.list') ->with('o',$o); } private function service_change_charges(Request $request,Service $o): Collection { $charges = collect(); $po = Product::findOrFail(Arr::get($request->broadband,'product_id')); $start_at = Carbon::create(Arr::get($request->broadband,'start_at')); // Get the invoiced items covering the start_at date foreach ($o->invoice_items->filter(function($item) use ($start_at) { return ($item->start_at < $start_at) && ($item->stop_at > $start_at) && ($item->item_type === 0); }) as $iio) { // Reverse the original charge $co = new Charge; $co->active = TRUE; $co->service_id = $o->id; $co->account_id = $o->account_id; $co->sweep_type = 6; $co->product_id = $iio->product_id; $co->description = 'Plan Upgrade Adjustment'; $co->user_id = Auth::id(); $co->type = $iio->item_type; $co->start_at = $start_at; $co->stop_at = $iio->stop_at; $co->amount = $iio->price_base; $co->taxable = TRUE; // @todo this should be determined $co->quantity = -1*$start_at->diff($iio->stop_at)->days/$iio->start_at->diff($iio->stop_at)->days; $charges->push($co); // Add the new charge $co = new Charge; $co->active = TRUE; $co->service_id = $o->id; $co->account_id = $o->account_id; $co->sweep_type = 6; $co->product_id = $po->id; $co->description = 'Plan Upgrade Adjustment'; $co->user_id = Auth::id(); $co->type = $iio->item_type; $co->start_at = $start_at; $co->stop_at = $iio->stop_at; $co->amount = $po->base_charge; $co->taxable = TRUE; // @todo this should be determined $co->quantity = $start_at->diff($iio->stop_at)->days/$iio->start_at->diff($iio->stop_at)->days; $charges->push($co); } // Add any fee if (Arr::get($request->broadband,'change_fee')) { $co = new Charge; $co->active = TRUE; $co->service_id = $o->id; $co->account_id = $o->account_id; $co->sweep_type = 6; $co->product_id = $po->id; $co->description = 'Plan Upgrade Fee'; $co->user_id = Auth::id(); $co->type = 3; $co->start_at = $start_at; $co->stop_at = $start_at; $co->amount = Arr::get($request->broadband,'change_fee'); $co->taxable = TRUE; // @todo this should be determined $co->quantity = 1; $charges->push($co); } return $charges; } /** * This is an API method, that works with service change - to return the new charges as a result of changing a service * * @param Request $request * @param Service $o * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View */ public function service_change_charges_display(Request $request,Service $o) { return view('a.charge.service_change') ->with('charges',$this->service_change_charges($request,$o)); } /** * Update details about a service * * @param Request $request * @param Service $o * @return RedirectResponse */ public function update(Request $request,Service $o) { if ($o->type->validation()) { Session::put('service_update',true); $validator = Validator::make($x=$request->post($o->category),$o->type->validation()); if ($validator->fails()) { return redirect() ->back() ->withErrors($validator) ->withInput(); } $o->type->forceFill(Arr::except($x,['start_at'])); } elseif ($request->post($o->product->category)) { $o->type->forceFill($request->post($o->product->category)); } $o->type->save(); // Also update our service start_at date. if ($request->post('start_at')) $o->start_at = $request->start_at; $o->save(); return redirect()->back()->with('success','Record Updated'); } }