You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tivi_kemana_saja_laravel/app/Models/NewTvRequest.php

211 lines
7.9 KiB
PHP

<?php
namespace App\Models;
use App\Helper\JSONResponse;
use App\Helper\STS\Indokargo;
use App\Helper\Traits\Models\CanMultiOrderBy;
use App\Helper\Traits\Models\CanMultiSearch;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class NewTvRequest extends Model {
use HasFactory;
use CanMultiSearch;
use CanMultiOrderBy;
protected $table = 'new_tv_requests';
protected $casts = ['device_info'=>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('activated_at');
}]);
}
public function scopeAddColumnCanReject(Builder $query) {
$query->withCount(['self as can_reject' => function($q) {
$q->whereNull('activated_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 activated for more than the expiry date, deleted it
* 2. if it has been activated & has been responded more than expiry date, delete it
* - case: when has been activated, but intenet connection missing, how can device know
* that the new request tv has been activated?
*/
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('activated_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->activated_at) {
// make sure waiting tv_device responded before deleted
if(empty($newTvReq->responded_at)) {
$newTvReq->responded_at = now();
$newTvReq->save();
}
return JSONResponse::Success([
'message' => 'activated',
'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' => 'required|array',
]);
$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',
]);
$newTvReq = NewTvRequest::addColumnCanApprove()
->findOrFail($request->id);
if(!$newTvReq->can_approve) throw new \Exception('Cannot approve current request');
try {
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);
$newTvReq->activated_at = now();
$newTvReq->tv_fk = $tv->id;
$newTvReq->save();
DB::commit();
return JSONResponse::Success(['message'=>'Success to update tv data']);
// TODO: waiting execution until update from ops
// // try to sys_to_sys with indokargo
// DB::commit();
// $jsonResponse = Indokargo::createTVAddress($tvRequest, $tv->id);
// return $jsonResponse;
} 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
//------------------------------------------------------------
}