AsArrayObject::class]; //------------------------------------------------------------ // -- RELATED TO RELATIONSHIP // HAS ONE public function self(): HasOne { return $this->hasOne(self::class, 'id', 'id'); } /// BELONGS TO public function tv(): BelongsTo { return $this->belongsTo(Tv::class, 'tv_fk', 'id'); } // -- END RELATED TO RELATIONSHIP //------------------------------------------------------------ //------------------------------------------------------------ // -- RELATED TO SCOPE public function scopeAddColumnCanApprove(Builder $query) { $query->withCount(['self as can_approve' => function($q) { $q->whereNull('approved_at'); }]); } public function scopeAddColumnCanReject(Builder $query) { $query->withCount(['self as can_reject' => function($q) { $q->whereNull('approved_at'); }]); } // -- END RELATED TO SCOPE //------------------------------------------------------------ //------------------------------------------------------------ // -- RELATED TO DATA FUNCTION private static function _generateRandomCode(): string { $totalDigit = 6; $randomDigit = ''; while(true) { $randomDigit = strtoupper(Str::random($totalDigit)); $isExist = NewTvRequest::where('code', $randomDigit)->first(); if(!$isExist) break; } return $randomDigit; } /** * Rule: * 1. if it has not been approved for more than the expiry date, deleted it * 2. if it has been approved & has been responded more than expiry date, delete it * - case: when has been approved, but intenet connection missing, how can device know * that the new request tv has been approved? */ private static function _getMaxExpiredTime() :Carbon { return Carbon::now()->subHour(); } public static function deleteExpiredRequests() { $expiredTime = self::_getMaxExpiredTime()->toDateTimeString(); NewTvRequest::where(function($q) use ($expiredTime) { $q->whereNull('approved_at')->where('created_at', '<=', $expiredTime); })->orWhere(function($q) use ($expiredTime) { $q->where('responded_at', '<=', $expiredTime ); })->delete(); } // -- END RELATED TO DATA FUNCTION //------------------------------------------------------------ //------------------------------------------------------------ // -- RELATED TO FROM REQUEST FUNCTION private static function _checkOrCreateResponse(NewTvRequest $newTvReq) { if($newTvReq->approved_at) { // make sure waiting tv_device responded before deleted if(empty($newTvReq->responded_at)) { $newTvReq->responded_at = now(); $newTvReq->save(); } return JSONResponse::Success([ 'message' => 'approved', 'new_tv_request' => $newTvReq, 'tv' => $newTvReq->tv ]); } return JSONResponse::Success([ 'message' => 'not activate', 'new_tv_request' => $newTvReq, 'tv' => null ]); } public static function checkOrCreateFromRequest(Request $request) { $request->validate([ 'id' => 'nullable|string|required_with:code|integer', 'code' => 'nullable|string|required_with:id', 'device_info' => 'required|array' ]); if(!empty($request->id)) { $checkTvReq = NewTvRequest::where('code', $request->code)->find($request->id); if($checkTvReq) return self::_checkOrCreateResponse($checkTvReq); } $newTvReq = new self; $newTvReq->code = self::_generateRandomCode(); $newTvReq->device_info = $request->device_info; $newTvReq->save(); return self::_checkOrCreateResponse($newTvReq); } public static function approveFromRequest(Request $request) { $request->validate([ 'id' => 'required|integer|exists:App\Models\NewTvRequest', 'tv' => 'nullable|array', 'existingTv' => 'nullable|array', 'action' => 'required|string', ]); $newTvReq = NewTvRequest::addColumnCanApprove() ->findOrFail($request->id); if(!$newTvReq->can_approve) throw new \Exception('Cannot approve current request'); try { $tv = null; if($request->action == 'existing') { $existingTvRequest = new Request($request->existingTv); $existingTvRequest->validate([ 'id' => 'required|integer|exists:App\Models\Tv', ]); $tv = TV::findOrFail($existingTvRequest->id); } else if ($request->action == 'new') { $tvRequest = new Request($request->tv); if($tvRequest->code) $tvRequest->merge(['code' => strtoupper($tvRequest->code)]); $tvRequest->validate([ 'company_name' => 'nullable|string', 'address' => 'nullable|string', 'street_address' => 'nullable|string', 'col1' => 'nullable|string', 'col2' => 'nullable|string', 'col3' => 'nullable|string', 'col4' => 'nullable|string', 'col5' => 'nullable|string', 'col6' => 'nullable|string', 'col7' => 'nullable|string', 'col8' => 'nullable|string', 'col9' => 'nullable|string', 'col10' => 'nullable|string', 'notes' => 'nullable|string', ]); DB::beginTransaction(); $tv = new Tv(); $tv->code = TV::generateUniqueCode(); $tv->company_name = $tvRequest->company_name; $tv->address = $tvRequest->address; $tv->street_address = $tvRequest->street_address; $tv->col1 = $tvRequest->col1; $tv->col2 = $tvRequest->col2; $tv->col3 = $tvRequest->col3; $tv->col4 = $tvRequest->col4; $tv->col5 = $tvRequest->col5; $tv->col6 = $tvRequest->col6; $tv->col7 = $tvRequest->col7; $tv->col8 = $tvRequest->col8; $tv->col9 = $tvRequest->col9; $tv->col10 = $tvRequest->col10; $tv->notes = $tvRequest->notes; $tv->device_info = $newTvReq->device_info; $tv->installed_at = now(); $tv->save(); TvLog::historyCreate($request->user(), $tv->id, $tv); // TODO: waiting execution until update from ops // NEED TO REFACTOR (cause by add existing tv code) // // try to sys_to_sys with indokargo // DB::commit(); // $jsonResponse = Indokargo::createTVAddress($tvRequest, $tv->id); // return $jsonResponse; } else { throw new \Exception('INVALID FORM ACTION'); } $newTvReq->approved_at = now(); $newTvReq->tv_fk = $tv->id; $newTvReq->save(); DB::commit(); return JSONResponse::Success(['message'=>'Success to approve new tv request']); } catch(\Throwable $th) { DB::rollback(); throw $th; } } public static function rejectFromRequest(Request $request) { $request->validate([ 'id' => 'required|integer|exists:App\Models\NewTvRequest', ]); $newTvRequest = NewTvRequest::addColumnCanReject() ->findOrFail($request->id); if(!$newTvRequest->can_reject) throw new \Exception('Cannot reject current request'); $newTvRequest->delete(); return JSONResponse::Success(['data' => $newTvRequest ]); } // -- END RELATED TO FROM REQUEST FUNCTION //------------------------------------------------------------ }