Compare commits

..

No commits in common. 'cfea605fc169d7485e9cf8dfdc40153729fcd3f3' and 'aee6d9440c879c77f2fe781ba0cbc1f1be96e912' have entirely different histories.

@ -3,16 +3,11 @@ APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
MOBILE_AUTH_TOKEN=Gaobd5OKPdGARLGTD03vSFStrADAxmQ9
MOBILE_TOKEN=Gaobd5OKPdGARLGTD03vSFStrADAxmQ9
# for CORS
SANCTUM_STATEFUL_DOMAINS=[http://localhost:3000]
# for Indokargo
IK_BE_DOMAIN=
IK_SESSION_ID=
IK_OAUTH_ID=
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

@ -1,86 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Helper\Sts\Indokargo;
use App\Models\StsLog;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Http\Request;
class StsReschedule extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'sts:reschedule';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Resschedule failed sts to sts data';
/**
* Execute the console command.
*/
public function handle(): void {
$sleep = 30; // 30 second
while(true) {
$this->info('---------------------------');
$this->info('reschedule sts:' . Carbon::now()->toDateTimeString());
$this->info('---------------------------');
// get reschedu;e sts logs
$success = 0;
$failed = 0;
$rescheduleStsLogs = StsLog::where(['is_retry' => true])->get();
foreach($rescheduleStsLogs as $rescheduleStsLog) {
try {
$partner = $rescheduleStsLog->partner;
$module = $rescheduleStsLog->module;
$serviceName = $rescheduleStsLog->service_name;
$request = new Request((array) $rescheduleStsLog->request_data ?? []);
$localId = $rescheduleStsLog->local_id;
$partnerId = $rescheduleStsLog->partner_id;
$lastSeq = $rescheduleStsLog->seq;
if($partner == StsLog::PARTNER_INDOKARGO) {
if($module == StsLog::MODULE_TV) {
if($serviceName == StsLog::SERVICE_CREATE_TV_ADDRESS) {
Indokargo::createTVAddress($request, $localId, $lastSeq);
} else if($serviceName == StsLog::SERVICE_UPDATE_TV_ADDRESS) {
Indokargo::updateTVAddress($request, $localId, $partnerId, $lastSeq);
} else if($serviceName == StsLog::SERVICE_CHANGE_STATUS_TV_ADDRESS) {
Indokargo::changeStatusAddress($request, $localId, $partnerId, $lastSeq);
} else {
throw new \Exception("Service name '$partner' > '$module' > '$serviceName' not found service");
}
} else {
throw new \Exception("Module name '$partner' > '$module' not found service");
}
} else {
throw new \Exception("Partner name '$partner' not found service");
}
$success++;
} catch(\Throwable $th) {
$failed++;
$this->info("stsLog id: ". $rescheduleStsLog->id . " => " . $th->getMessage());
}
}
// save all retry request is retry false
$rescheduleStsLogIds = $rescheduleStsLogs->pluck('id')->toArray();
StsLog::whereIn('id', $rescheduleStsLogIds)->update(['is_retry' => false]);
$this->info('---------------------------');
$this->info("result: $success success, $failed failed" );
$this->info("Sleep in $sleep seconds" );
$this->info('---------------------------');
sleep($sleep);
}
}
}

@ -2,8 +2,6 @@
namespace App\Helper;
use Illuminate\Support\Facades\DB;
class Common {
public static function convertRequestConfig(?array $requestConfig): array {
$config = [];
@ -28,9 +26,4 @@ class Common {
public static function trueOrFalse(mixed $value): bool {
return ($value === "true" || $value === "1" || $value === 1 || $value === true) ? true : false;
}
public static function setTimezone($timezone) {
date_default_timezone_set($timezone);
DB::statement("SET TIME ZONE '$timezone'");
}
}

@ -25,13 +25,5 @@
];
}
public static function getSearchValidation() { return 'nullable|string'; }
public static function compileDirtyEloquentToArrMessage($model) {
$dirties = $model->getDirty();
foreach($dirties as $key => $dirty) {
$dirties[$key] = $model->getOriginal($key) . ' => ' . $dirty;
}
return $dirties;
}
}
?>

@ -1,51 +0,0 @@
<?php
namespace App\Helper\Frontend;
use App\Helper\JSONResponse;
use App\Models\Tv;
use Illuminate\Http\Request;
/**
* Note:
* if any of frontend component need specific api query / data specific.
* Please add function to get data here.
*
* But, if the parent component still needs to pass the url to the
* child component, the url api can be placed in the app/Http/Controllers/api/superadmin/GeneralController
*/
class ApiUtilities {
// for components/app/tv/button/excel.vue
public static function tvExcel(Request $request) {
$request->validate(['a' => 'nullable|string']);
switch($request->a) {
case 'excelTemplate':
return Tv::getExcelTemplate();
break;
case 'validateData':
$tvCodes = $request->tvCodes ?? [];
$tvs = $request->tvs ?? [];
$oValidation = TV::validateExcel($tvs, $tvCodes);
return JSONResponse::Success(['oValidation' => $oValidation]);
break;
case 'uploadExcel':
$tvCodes = $request->tvCodes ?? [];
$tvs = $request->tvs ?? [];
$oValidation = TV::validateExcel($tvs, $tvCodes);
$result = TV::uploadExcel($tvs, $oValidation, $request->user());
return JSONResponse::Success($result);
break;
case 'exportData':
return Tv::getExportData($request);
break;
case 'excelDetail':
return Tv::getExcelDetail($request);
break;
}
throw new \Exception('Invalid Request Command');
}
}
?>

@ -1,180 +0,0 @@
<?php
namespace App\Helper\STS;
use App\Helper\JSONResponse;
use App\Models\StsLog;
use App\Models\Tv;
use Carbon\Carbon;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Validation\ValidationException;
class Indokargo {
const STATUS_SUCCESS = 'Success';
const STATUS_FAILURE = 'Failure';
// const STATUS_WARNING = 'Warning';
//------------------------------------------------------------------------
//-- UTILITIES
private static function _checkIkResponse($res) {
$status = $res['status'];
if($res['status'] == self::STATUS_SUCCESS) return;
else if($res['status'] == self::STATUS_FAILURE) {
// note: Indokargo error message can be array or string
$errorMessage = $res['error']['error_message'];
if(is_array($errorMessage)) throw ValidationException::withMessages($errorMessage);
else throw new \Exception($errorMessage);
}
else {
throw new \Exception("Indokargo status is not valid (ik status = $status)" );
}
}
private static function _HttpTransaction(StsLog $stsLog, $callback) {
try {
return $callback();
} catch(ConnectionException $e) {
// if error cause by connection error, try again later
$stsLog->error_info = [
'message' => $e->getMessage(),
'errors' => $e->getTrace()
];
$stsLog->result = StsLog::STATUS_FAILED;
$stsLog->is_retry = true;
$stsLog->save();
return JSONResponse::Success(['is_warning' => true,
'message' => "Failed to sync data with indokargo data, don't worry, we will sync data later"]);
} catch(\Throwable $th) {
DB::rollBack();
$stsLog->error_info = [
'message' => $th->getMessage(),
'errors' => $th->getTrace()
];
$stsLog->result = StsLog::STATUS_FAILED;
$stsLog->save();
throw $th;
}
}
//-- END UTILITIES
//------------------------------------------------------------------------
public static function createTVAddress(Request $request, int $tvFk, int $lastSeq = 0) {
$seq = $lastSeq + 1;
/**
* local id = TV FK, partnerId = ik_address_id
* Why not new tv request id as local_id?
* - New Tv request data will be deleted after TV data is inserted into the local DB
*/
$stsLog = new StsLog();
$stsLog->partner = StsLog::PARTNER_INDOKARGO;
$stsLog->is_outgoing = true;
$stsLog->module = StsLog::MODULE_TV;
$stsLog->service_name = StsLog::SERVICE_CREATE_TV_ADDRESS;
$stsLog->local_id = $tvFk;
$stsLog->partner_id = null;
$stsLog->seq = $seq;
$stsLog->request_data = $request->all();
$stsLog->request_time = Carbon::now();
return self::_HttpTransaction($stsLog, function() use($tvFk, $request, $stsLog) {
$request->validate(['code' => 'required|string']);
$result = Http::indokargo()->post('tv/address/create', $request->all());
$res = $result->throw()->json();
// update stsLog
$stsLog->response_data = $res;
$stsLog->response_time = Carbon::now();
self::_checkIkResponse($res);
$ikAddress = $res['data']['0'];
$ikAddressId = $ikAddress['id'];
$stsLog->partner_id = $ikAddressId;
// check ik address id is exist (almost impossible to happen, 0.01%)
$isDuplicateIkAddressId = TV::where([
['ik_address_id', '=', $ikAddressId],
['id', '!=', $tvFk]
])->first();
if($isDuplicateIkAddressId) throw new \Exception("IK Address ID Already exist in current db ($ikAddressId)");
DB::beginTransaction();
$tv = Tv::findOrFail($tvFk);
$tv->ik_address_id = $ikAddressId;
$tv->save();
$stsLog->result = StsLog::STATUS_SUCCESS;
$stsLog->save();
DB::commit();
return JSONResponse::Success(['is_warning' => false, 'message' => 'Success To Save Data']);
});
}
public static function updateTVAddress(Request $request, int $tvFk, String $ikAddressId, int $lastSeq = 0) {
$seq = $lastSeq + 1;
$request->merge(['ik_address_id' => $ikAddressId]);
$stsLog = new StsLog();
$stsLog->partner = StsLog::PARTNER_INDOKARGO;
$stsLog->is_outgoing = true;
$stsLog->module = StsLog::MODULE_TV;
$stsLog->service_name = StsLog::SERVICE_UPDATE_TV_ADDRESS;
$stsLog->local_id = $tvFk;
$stsLog->partner_id = $ikAddressId;
$stsLog->seq = $seq;
$stsLog->request_data = $request->all();
$stsLog->request_time = Carbon::now();
return self::_HttpTransaction($stsLog, function() use($stsLog, $request) {
$request->validate(['code' => 'required|string', 'ik_address_id' => 'required|string']);
$result = Http::indokargo()->post('tv/address/update-tv', $request->all());
$res = $result->throw()->json();
// update stsLog
$stsLog->response_data = $res;
$stsLog->response_time = Carbon::now();
self::_checkIkResponse($res);
$stsLog->result = StsLog::STATUS_SUCCESS;
$stsLog->save();
DB::commit();
return JSONResponse::Success(['message' => "Success to save data"]);
});
}
public static function changeStatusAddress(Request $request, int $tvFk, String $ikAddressId, int $lastSeq = 0) {
$seq = $lastSeq + 1;
$request->merge(['ik_address_id' => $ikAddressId]);
$stsLog = new StsLog();
$stsLog->partner = StsLog::PARTNER_INDOKARGO;
$stsLog->is_outgoing = true;
$stsLog->module = StsLog::MODULE_TV;
$stsLog->service_name = StsLog::SERVICE_CHANGE_STATUS_TV_ADDRESS;
$stsLog->local_id = $tvFk;
$stsLog->partner_id = $request->ik_address_id;
$stsLog->seq = $seq;
$stsLog->request_data = $request->all();
$stsLog->request_time = Carbon::now();
return self::_HttpTransaction($stsLog, function() use($stsLog, $request) {
$request->validate(['ik_address_id' => 'required|string', 'is_active'=> 'required|boolean']);
$result = Http::indokargo()->post('tv/address/change-status', $request->all());
$res = $result->throw()->json();
// update stsLog
$stsLog->response_data = $res;
$stsLog->response_time = Carbon::now();
self::_checkIkResponse($res);
$stsLog->result = StsLog::STATUS_SUCCESS;
$stsLog->save();
DB::commit();
return JSONResponse::Success(['is_warning' => false, 'message' => 'Success To Change Status']);
});
}
}
?>

@ -10,11 +10,11 @@ use Illuminate\Http\Request;
class CheckUpdateController extends Controller {
public function videoUpdateLatest(Request $request) {
$lastestVideoUpdate = VideoUpdate::getLatestSelected();
$lastestVideoUpdate = VideoUpdate::selected()->latest('updated_at')->first();
return JSONResponse::Success(['latestVideoUpload' => $lastestVideoUpdate]);
}
public function apkUpdateLatest(Request $request) {
$latestApkUpdate = ApkUpdate::getLatest();
$latestApkUpdate = ApkUpdate::latest('version_code')->first();
return JSONResponse::Success(['latestApkUpdate' => $latestApkUpdate]);
}
}

@ -1,38 +0,0 @@
<?php
namespace App\Http\Controllers\api\mobile;
use App\Helper\JSONResponse;
use App\Http\Controllers\Controller;
use App\Models\ApkUpdate;
use App\Models\NewTvRequest;
use App\Models\Tv;
use App\Models\VideoUpdate;
use Illuminate\Http\Request;
class TvController extends Controller {
public function newRequest(Request $request) {
return NewTvRequest::checkOrCreateFromRequest($request);
}
public function checkUpdate(Request $request) {
$request->validate(['id' => 'nullable|integer',
'apk_version_code' => 'required|integer',
'apk_version_name' => 'required|string']);
$tv = null;
$latestApkUpdate = null;
$latestVideoUpdate = null;
if($request->id) {
$tv = Tv::find($request->id);
$tv->last_connected_at = now();
$tv->apk_version_code = $request->apk_version_code;
$tv->apk_version_name = $request->apk_version_name;
$tv->save();
$latestApkUpdate = ApkUpdate::getLatest();
$latestVideoUpdate = VideoUpdate::getLatestSelected();
}
return JSONResponse::Success(['tv' => $tv, 'latestApkUpdate' => $latestApkUpdate, 'latestVideoUpdate' => $latestVideoUpdate]);
}
}

@ -1,16 +0,0 @@
<?php
namespace App\Http\Controllers\api\superadmin;
use App\Helper\JSONResponse;
use App\Http\Controllers\Controller;
use App\Models\Tv;
use Illuminate\Http\Request;
class GeneralController extends Controller {
public function tvSearch(Request $request) {
$request->validate(['search' => 'nullable|string']);
$tvs = Tv::multiSearch($request->search, ['code'])->orderBy('code', 'asc')->limit(10)->get();
return JSONResponse::Success(['tvs' => $tvs ]);
}
}

@ -1,32 +0,0 @@
<?php
namespace App\Http\Controllers\api\superadmin\tv;
use App\Helper\DatabaseHelper;
use App\Helper\JSONResponse;
use App\Http\Controllers\Controller;
use App\Models\NewTvRequest;
use Illuminate\Http\Request;
class NewTvRequestController extends Controller {
public function init(Request $request) {
NewTvRequest::deleteExpiredRequests();
$request->validate([
'perPage' => 'nullable|integer|min:1',
...DatabaseHelper::getOrderBysValidations(),
'search' => DatabaseHelper::getSearchValidation()
]);
$newTvRequests = NewTvRequest::with('tv')
->addColumnCanApprove()
->addColumnCanReject()
->multiSearch($request->search, ['code'])
->multiOrderBy($request->orderBys, 'created_at desc')
->paginate($request->perPage ?? 10);
return JSONResponse::Success(['data' => $newTvRequests ]);
}
public function approve(Request $request) { return NewTvRequest::approveFromRequest($request); }
public function reject(Request $request) { return NewTvRequest::rejectFromRequest($request); }
}

@ -1,33 +0,0 @@
<?php
namespace App\Http\Controllers\api\superadmin\tv;
use App\Helper\DatabaseHelper;
use App\Helper\Frontend\ApiUtilities;
use App\Helper\JSONResponse;
use App\Http\Controllers\Controller;
use App\Models\ApkUpdate;
use App\Models\Tv;
use Illuminate\Http\Request;
class TvController extends Controller {
public function init(Request $request) {
$request->validate([
'perPage' => 'nullable|integer|min:1',
'isFirstTime' => 'nullable|boolean',
]);
$additionalData = [];
if($request->isFirstTime) {
$additionalData['apkUpdates'] = ApkUpdate::select('version_code', 'version_name')
->orderBy('version_code', 'desc')
->get();
}
$newTvRequests = TV::validateAndGetEloquentFromRequest($request)->paginate($request->perPage ?? 10);
return JSONResponse::Success(['data' => $newTvRequests, ...$additionalData ]);
}
public function excel(Request $request) { return ApiUtilities::tvExcel($request); }
public function update(Request $request) { return Tv::updateFromRequest($request); }
public function changeStatus(Request $request) { return Tv::changeStatusFromRequest($request); }
}

@ -14,12 +14,11 @@ class MobileMiddleware
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response {
$serverMobileAuthToken = env('MOBILE_AUTH_TOKEN', '');
if(!$serverMobileAuthToken) throw new \Exception('Mobile Auth token in server is not found');
$serverMobileToken = env('MOBILE_TOKEN', '');
if(!$serverMobileToken) throw new \Exception('Mobile token in server is not found');
$clientMobileAuthToken = $request->header('mobile-token', '');
if(!$clientMobileAuthToken) $clientMobileAuthToken = $request->header('mobile-auth-token', '');
if($serverMobileAuthToken != $clientMobileAuthToken) throw new \Exception('Invalid Mobile Auth Token');
$clientMobileToken = $request->header('mobile-token', '');
if($serverMobileToken != $clientMobileToken) throw new \Exception('Invalid Mobile Token');
return $next($request);
}
}

@ -34,12 +34,6 @@ class ApkUpdate extends Model {
// -- END RELATED TO SCOPE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO GET DATA
public static function getLatest(){ return self::latest('version_code')->first(); }
// -- END RELATED TO GET DATA
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO MODIFICATION DATA FROM REQUEST
public static function upsertFromRequest(Request $request) {
@ -47,8 +41,7 @@ class ApkUpdate extends Model {
'id' => 'nullable|integer|exists:App\Models\ApkUpdate,id',
'name' => 'required|string',
'file' => 'required_without:id|file|' . FileHelper::convertToStrLaraValidation(FileHelper::$allowedApkExtensions),
'version_code' => 'required|integer|min:1|unique:apk_updates,version_code',
'version_name' => 'required|string',
'version_code' => 'required|integer|min:1',
'change_note' => 'nullable|string'
], [
'file' => ['required_without' => 'The file field is required.']
@ -73,7 +66,6 @@ class ApkUpdate extends Model {
}
$apkUpdate->name = $request->name;
$apkUpdate->version_code = $request->version_code;
$apkUpdate->version_name = $request->version_name;
$apkUpdate->change_note = $request->change_note;
$apkUpdate->save();

@ -1,22 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TvAppInfo extends Model {
use HasFactory;
protected $table = 'tv_app_infos';
protected $primaryKey = 'tv_fk';
public $incrementing = false;
//------------------------------------------------------------
// -- RELATED TO RELATIONSHIP
/// BELONGS TO
public function tv(): BelongsTo { return $this->belongsTo(Tv::class, 'tv_fk', 'id'); }
// -- END RELATED TO RELATIONSHIP
//------------------------------------------------------------
}

@ -1,18 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TvConnectLog extends Model {
use HasFactory;
//------------------------------------------------------------
// -- RELATED TO RELATIONSHIP
/// BELONGS TO
public function tv(): BelongsTo { return $this->belongsTo(Tv::class, 'tv_fk', 'id'); }
// -- END RELATED TO RELATIONSHIP
//------------------------------------------------------------
}

@ -1,18 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class TvSession extends Model {
use HasFactory;
//------------------------------------------------------------
// -- RELATED TO RELATIONSHIP
/// BELONGS TO
public function tv(): BelongsTo { return $this->belongsTo(Tv::class, 'tv_fk', 'id'); }
// -- END RELATED TO RELATIONSHIP
//------------------------------------------------------------
}

@ -1,225 +0,0 @@
<?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('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
//------------------------------------------------------------
}

@ -1,20 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Outlet extends Model {
use HasFactory;
protected $table = 'outlets';
//------------------------------------------------------------
// -- RELATED TO MIGRATION
/// HAS ONE
public function tv_app_info(): HasOne { return $this->hasOne(Tv::class, 'outlet_fk', 'id'); }
// -- END RELATED TO MIGRATION2
//------------------------------------------------------------
}

@ -1,49 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\AsArrayObject;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class StsLog extends Model {
use HasFactory;
protected $table = 'sts_logs';
protected $fillable = [
'partner',
'is_outgoing',
'module',
'service_name',
'local_id',
'partner_id',
'seq',
'result',
'error_info',
'request_data',
'request_time',
'response_data',
'response_time',
'is_retry',
'created_at',
'updated_at'
];
protected $casts = [
'error_info' => AsArrayObject::class,
'request_data' => AsArrayObject::class,
'response_data' => AsArrayObject::class,
];
const STATUS_SUCCESS = 'success';
const STATUS_FAILED = 'failed';
const STATUS_WARNING = 'warning';
const PARTNER_INDOKARGO = 'indokargo';
// related to indokargo
const MODULE_TV = 'tv';
const SERVICE_CREATE_TV_ADDRESS = 'create-tv-address';
const SERVICE_UPDATE_TV_ADDRESS = 'update-tv-address';
const SERVICE_CHANGE_STATUS_TV_ADDRESS = 'change-statustv-address';
}

@ -1,372 +0,0 @@
<?php
namespace App\Models;
use App\Helper\Common;
use App\Helper\DatabaseHelper;
use App\Helper\JSONResponse;
use App\Helper\STS\Indokargo;
use App\Helper\Traits\Models\CanMultiOrderBy;
use App\Helper\Traits\Models\CanMultiSearch;
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\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
class Tv extends Model {
use HasFactory;
use CanMultiSearch;
use CanMultiOrderBy;
protected $table = 'tvs';
protected $hidden = ['ik_cust_id', 'ik_address_id'];
protected $casts = ['device_info'=>AsArrayObject::class];
//------------------------------------------------------------
// -- RELATED TO RELATIONSHIP
/// HAS ONE
public function new_tv_request(): HasOne { return $this->hasOne(NewTvRequest::class, 'tv_fk', 'id'); }
public function tv_app_info(): HasOne { return $this->hasOne(TvAppInfo::class, 'tv_fk', 'id'); }
/// HAS MANY
public function tv_connect_logs(): HasMany { return $this->hasMany(TvConnectLog::class, 'tv_fk', 'id'); }
public function tv_sessions(): HasMany { return $this->hasMany(TvSession::class, 'tv_fk', 'id'); }
/// BELONGS TO
public function outlet(): BelongsTo { return $this->belongsTo(Outlet::class, 'outlet_fk', 'id'); }
// -- END RELATED TO RELATIONSHIP
//------------------------------------------------------------
//------------------------------------------------------------
// -- RELATED TO DATA FUNCTION
public static function generateUniqueCode() {
// init
$countSuffixDigit = 5;
date_default_timezone_set('Asia/Jakarta');
$prefixCode = 'TV' . date('Ym');
// try to get unique suffix
$uniqueCode = '';
while(true) {
$suffixCode = strtoupper(Str::random($countSuffixDigit));
$uniqueCode = $prefixCode . $suffixCode;
$isUnique = TV::where('code', $uniqueCode)->first();
if(!$isUnique) break;
}
return $uniqueCode;
}
// -- END RELATED TO DATA FUNCTION
//------------------------------------------------------------
//------------------------------------------------------------
// -- RELATED TO REQUEST
public static function validateAndGetEloquentFromRequest(Request $request) {
$request->validate([
...DatabaseHelper::getOrderBysValidations(),
'search' => DatabaseHelper::getSearchValidation(),
'apkVersionCode' => 'nullable|integer',
'tz' => 'required|timezone',
'isActive' => 'nullable|boolean',
'installedAt' => 'nullable|array',
'installedAt.from' => 'nullable|date',
'installedAt.to' => 'nullable|date',
'lastConnectedAt' => 'nullable|array',
'lastConnectedAt.from' => 'nullable|date',
'lastConnectedAt.to' => 'nullable|date',
'lastConnectedDay' => 'nullable|int'
]);
Common::setTimezone($request->tz);
return Tv::when($request->isActive != null, function($q) use($request) {
$q->where('is_active', $request->isActive);
})
->when($request->apkVersionCode, function($q, $apkVersionCode) {
$q->where('apk_version_code', $apkVersionCode);
})
->when($request->installedAt['from'] ?? '', function($q, $from) {
$q->where(DB::raw('DATE(installed_at)'), '>=', $from);
})
->when($request->installedAt['to'] ?? '', function($q, $to) {
$q->where(DB::raw('DATE(installed_at)'), '<=', $to);
})
->when($request->lastConnectedAt['from'] ?? '', function($q, $from) {
$q->where(DB::raw('DATE(last_connected_at)'), '>=', $from);
})
->when($request->lastConnectedAt['to'] ?? '', function($q, $to) {
$q->where(DB::raw('DATE(last_connected_at)'), '<=', $to);
})
->multiSearch($request->search, ['code', 'company_name'])
->multiOrderBy($request->orderBys, 'created_at desc');
}
public static function updateFromRequest(Request $request) {
if($request->code) $request->merge(['code' => strtoupper($request->code)]);
$request->validate([
'id' => 'required|integer|exists:App\Models\Tv',
'code' => ['required','string',Rule::unique('tvs', 'code')
->when($request->id, function($q, $id) { $q->whereNot('id', $id);})],
'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',
]);
try {
DB::beginTransaction();
$tv = TV::findOrFail($request->id);
$oldTv = $tv->replicate();
$tv->company_name = $request->company_name;
$tv->address = $request->address;
$tv->street_address = $request->street_address;
$tv->code = $request->code;
$tv->col1 = $request->col1;
$tv->col2 = $request->col2;
$tv->col3 = $request->col3;
$tv->col4 = $request->col4;
$tv->col5 = $request->col5;
$tv->col6 = $request->col6;
$tv->col7 = $request->col7;
$tv->col8 = $request->col8;
$tv->col9 = $request->col9;
$tv->col10 = $request->col10;
$tv->notes = $request->notes;
$tv->update();
TvLog::historyUpdate($request->user(), $tv->id, $oldTv, $tv);
DB::commit();
return JSONResponse::Success(['message'=>'Success to update tv data']);
// TODO: waiting from ops workflow (Dont forget to resync co_name, address, street address in ik)
// // try to sys_to_sys with indokargo
// $jsonResponse = Indokargo::updateTVAddress($request, $tv->id, $tv->ik_address_id);
// DB::commit();
// return $jsonResponse;
} catch(\Throwable $th) {
DB::rollback();
throw $th;
}
}
public static function changeStatusFromRequest(Request $request) {
$request->validate(['id' => 'required|integer|exists:App\Models\TV,id']);
try {
DB::beginTransaction();
$tv = Tv::findOrFail($request->id);
$tv->is_active = !$tv->is_active;
$tv->save();
DB::commit();
return JSONResponse::Success(['message'=>'Success to change tv status']);
// TODO: waiting from ops workflow (Dont forget to resync co_name, address, street address in ik)
// // try to sys_to_sys with indokargo
// $jsonResponse = Indokargo::changeStatusAddress(new Request(['is_active' => $tv->is_active]),
// $tv->id, $tv->ik_address_id);
// DB::commit();
// return $jsonResponse;
} catch(\Throwable $th) {
DB::rollback();
throw $th;
}
}
// -- END RELATED TO REQUEST
//------------------------------------------------------------
//------------------------------------------------------------
// -- RELATED TO EXCEL
public static function getExcelDetail(Request $request) {
return JSONResponse::Success(['rows' => TV::validateAndGetEloquentFromRequest($request)->get()]);
}
// ---- RELATED TO EXPORT IMPORT
const EXCEL_SUCCESS = 'success';
const EXCEL_FAILED = 'failed';
const EXCEL_NO_CHANGE = 'no_change';
const EXCEL_UPDATE = 'update';
const EXCEL_TEMPLATE_COLS = ['code', 'company_name', 'address', 'street_address', 'notes',
'col1', 'col2', 'col3', 'col4', 'col5',
'col6', 'col7', 'col8', 'col9', 'col10',
'is_active'];
public static function getExcelTemplate() {
$row = [];
foreach(self::EXCEL_TEMPLATE_COLS as $col) { $row[$col] = ''; }
$rows = [$row];
return JSONResponse::Success(['rows' => $rows]);
}
public static function getExportData(Request $request) {
$rows = TV::validateAndGetEloquentFromRequest($request)->get();
return JSONResponse::Success(['rows' => $rows, 'cols' => self::EXCEL_TEMPLATE_COLS]);
}
// ------ RELATED TO IMPORT
private static function _checkExcelFormat($tvRows) {
if(!$tvRows) throw new \Exception("No Data");
$firstTvRow = $tvRows[0];
if(!$firstTvRow) throw new \Exception('Column not found');
// check if excel is empty or not
$firstTvRow['row'] = null;
if(!array_filter($firstTvRow)) throw new \Exception("Excel is empty");
// check is header col is exists
$errors = [];
foreach(self::EXCEL_TEMPLATE_COLS as $col) {
if(!array_key_exists($col, $firstTvRow)) $errors[$col] = "Column $col is Required";
}
if($errors) throw ValidationException::withMessages($errors);
}
private static function _getCountTvCodes($tvRows, $tvCodes) {
if(!$tvCodes) $tvCodes = array_column($tvRows, 'code');
$tvCodes = array_map(function($code) { return DatabaseHelper::trimUpperNull($code) ?? ''; }, $tvCodes);
return array_count_values($tvCodes);
}
private static function _changeModelFromTvRow(Tv $tv, $tvRow) {
$tv->company_name = $tvRow['company_name'];
$tv->address = $tvRow['address'];
$tv->street_address = $tvRow['street_address'];
$tv->code = $tvRow['code'];
$tv->col1 = $tvRow['col1'];
$tv->col2 = $tvRow['col2'];
$tv->col3 = $tvRow['col3'];
$tv->col4 = $tvRow['col4'];
$tv->col5 = $tvRow['col5'];
$tv->col6 = $tvRow['col6'];
$tv->col7 = $tvRow['col7'];
$tv->col8 = $tvRow['col8'];
$tv->col9 = $tvRow['col9'];
$tv->col10 = $tvRow['col10'];
$tv->notes = $tvRow['notes'];
return $tv;
}
public static function validateExcel($tvRows, $tvCodes = []) {
self::_checkExcelFormat($tvRows);
$countTvCodes = self::_getCountTvCodes($tvRows, $tvCodes);
$endStatus = self::EXCEL_SUCCESS;
$results = [];
foreach($tvRows as $tvRow) {
$status = self::EXCEL_NO_CHANGE;
$message = '';
$tvRow['code'] = strtoupper($tvRow['code'] ?? '');
try {
// STEP 1: check validation
$validator = Validator::make($tvRow, [
'row' => 'required|integer',
'code' => 'required|string',
'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',
]);
if($validator->fails()) {
$errors = $validator->errors()->toArray();
$messages = [];
foreach($errors as $eMessages) { $messages = array_merge($messages, $eMessages); }
throw new \Exception(implode(', ', $messages));
}
// STEP 2: check code is duplicate or not or not
$code = $tvRow['code'];
if(($countTvCodes[$code] ?? 0) > 1) throw new \Exception('Code is Duplicate in Excel');
// STEP 3: check code existing in database or not
$tvCheck = Tv::where('code', 'ilike', $code)->first();
if(!$tvCheck) throw new \Exception("TV Code '$code' not found in database");
// STEP 4: check has update data or not
$tvCheck = self::_changeModelFromTvRow($tvCheck, $tvRow);
if($tvCheck->isDirty()) {
$status = self::EXCEL_UPDATE;
$message = DatabaseHelper::compileDirtyEloquentToArrMessage($tvCheck);
}
} catch (\Throwable $th) {
$endStatus = self::EXCEL_FAILED;
$status = self::EXCEL_FAILED;
$message = $th->getMessage();
}
$results[] = ['row' => $tvRow['row'], 'status' => $status, 'message' => $message];
}
return ['status' => $endStatus, 'results' => $results];
}
public static function uploadExcel($tvRows, $oValidation, User $user) {
$validationResults = $oValidation['results'];
$countUploads = [
self::EXCEL_UPDATE => 0, self::EXCEL_NO_CHANGE => 0, self::EXCEL_FAILED => 0
];
$additionalErrors = [];
foreach($validationResults as $result) {
$validateStatus = $result['status'];
try {
switch($validateStatus) {
case self::EXCEL_FAILED:
throw new \Exception($result['message']);
break;
case self::EXCEL_UPDATE:
// get sparepart data
$idxTvRow = array_search($result['row'], array_column($tvRows, 'row'));
if($idxTvRow === false) throw new \Exception('Row Not Found');
$tvRow = $tvRows[$idxTvRow];
$tvRow['code'] = strtoupper($tvRow['code'] ?? '');
// try to upsert
DB::beginTransaction();
$tv = TV::where('code', 'ilike', $tvRow['code'])->firstOrFail();
$oldTV = $tv->replicate();
$newTv = self::_changeModelFromTvRow($tv, $tvRow);
if(!$newTv->isDirty()) throw new \Exception('No Change');
$newTv->save();
// save data log
TvLog::historyUpdateExcel($user, $newTv->id, $oldTV, $newTv);
DB::commit();
break;
case self::EXCEL_NO_CHANGE:
default:
break;
}
} catch (\Throwable $th) {
DB::rollBack();
$validateStatus = self::EXCEL_FAILED;
$additionalErrors[] = 'row ' . ($result['row'] ?? '-') . ' => ' . $th->getMessage();
}
$countUploads[$validateStatus]++;
}
return ['countUploads' => $countUploads, 'additionalErrors' => $additionalErrors];
}
// ------ END RELATED TO IMPORT
// ---- END RELATED TO EXPORT IMPORT
// -- END RELATED TO EXCEL
//------------------------------------------------------------
}

@ -1,39 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class TvLog extends Model {
use HasFactory;
protected $table = 'tv_logs';
protected $hidden = ['ik_cust_id', 'ik_address_id'];
protected $casts = ['from'=>'object', 'to'=>'object'];
const TYPES = ['create', 'update', 'update-excel'];
public static function historyCreate(User $user, int $tvFk, Tv $newTv) { self::saveHistory('create', $user, $tvFk, null, $newTv); }
public static function historyUpdate(User $user, int $tvFk, Tv $oldTv, Tv $newTv) { self::saveHistory('update', $user, $tvFk, $oldTv, $newTv); }
public static function historyUpdateExcel(User $user, int $tvFk, Tv $oldTv, Tv $newTv) { self::saveHistory('update-excel', $user, $tvFk, $oldTv, $newTv); }
private static function saveHistory(String $type, ?User $user, int $tvFk, ?Tv $oldTv, ?Tv $newTv) {
if(!in_array($type, self::TYPES)) throw new \Exception("Type '$type' No Valid");
$tvLog = new TvLog();
$tvLog->tv_fk = $tvFk;
$tvLog->type = $type;
if($oldTv) {
$oldTv = $oldTv->toArray();
unset($oldTv['id']);
$tvLog->from =$oldTv;
}
if($newTv) {
$newTv = $newTv->toArray();
unset($newTv['id']);
$tvLog->to = $newTv;
}
if($user) { $tvLog->user_fk = $user->id; }
$tvLog->save();
}
}

@ -63,10 +63,10 @@ class User extends Authenticatable
'username' => 'required|string',
'email' => 'required|email',
'password' => 'required_without:id|string|min:8',
'is_active' => 'required_with:id|boolean',
'is_active' => 'required_with:id|in:true,false',
], [
'password.required_without' => 'The password field is required.',
'is_active.required_with' => 'The is active field is required.'
'password' => ['required_with' => 'The password field is required.'],
'is_active' => ['required_with' => 'The is active field is required.']
]);
try {

@ -24,7 +24,7 @@ class VideoUpdate extends Model {
protected $table = 'video_updates';
protected $hidden = ['file'];
protected $appends = ['file_url', 'file_size_mb'];
protected $appends = ['file_url'];
// ---------------------------------------------------------------------------------------
// -- RELATED TO SCOPE
@ -34,28 +34,12 @@ class VideoUpdate extends Model {
// -- END RELATED TO SCOPE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO GET DATA
public static function getLatestSelected(){ return self::selected()->latest('updated_at')->first(); }
// -- END RELATED TO GET DATA
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO ATTRIBUTE
protected function fileSizeMb(): Attribute {
return Attribute::make(
fn() => $this->file_size_kb != null ? round($this->file_size_kb / 1024, 2) : null
);
}
// -- END RELATED TO ATTRIBUTE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// -- RELATED TO MODIFICATION DATA FROM REQUEST
public static function upsertFromRequest(Request $request) {
$request->validate([
'id' => 'nullable|integer|exists:App\Models\VideoUpdate,id',
'is_selected' => 'nullable|boolean',
'is_selected' => 'nullable|in:true,false',
'file' => 'required_without:id|file|' . FileHelper::convertToStrLaraValidation(FileHelper::$allowedVideoExtensions),
'file_name' => 'required|string',
], [
@ -64,13 +48,9 @@ class VideoUpdate extends Model {
$delOldDbFileLocation = '';
$newDbFileLocation = '';
$newFileSizeKb = 0;
try {
// save video to storage & get file size
if($request->file) {
$newDbFileLocation = self::saveFile($request->file)['db_url'];
$newFileSizeKb = round($request->file('file')->getSize() / 1024, 2);
}
// save photo
if($request->file) $newDbFileLocation = self::saveFile($request->file)['db_url'];
// try to upsert data
DB::beginTransaction();
@ -82,7 +62,6 @@ class VideoUpdate extends Model {
if($newDbFileLocation) {
if($videoUpdate->file) $delOldDbFileLocation = $videoUpdate->file;
$videoUpdate->file = $newDbFileLocation;
$videoUpdate->file_size_kb = $newFileSizeKb;
}
$videoUpdate->file_name = $request->file_name;

@ -2,7 +2,6 @@
namespace App\Providers;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -18,15 +17,8 @@ class AppServiceProvider extends ServiceProvider
/**
* Bootstrap any application services.
*/
public function boot(): void {
Http::macro('indokargo', function() {
$headers = [
'oauth' => env('INDOKARGO_API_OAUTH', ''),
'session' => env('INDOKARGO_API_SESSION_ID', '')
];
return Http::withHeaders($headers)->timeout(120)
->baseUrl(env('INDOKARGO_API_URL', '').'/v1/');
});
public function boot(): void
{
//
}
}

@ -1,4 +0,0 @@
Notes:
- Auto Update app
- Auto Update video
- Laravel Sanctum

@ -1,2 +0,0 @@
Notes:
- TV information & Logs

@ -1,43 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void {
Schema::create('outlets', function (Blueprint $table) {
$table->id();
$table->string('code', 50)->index();
$table->string('name', 255)->nullable()->index();
$table->string('address', 255)->nullable();
$table->string('street_address', 255)->nullable();
$table->string('phone', 50)->nullable()->index();
$table->double('lat')->default(0);
$table->double('long')->default(0);
$table->string('notes', 255)->nullable();
$table->string('country', 255);
$table->string('ik_country_id', 255);
$table->string('state', 255);
$table->string('ik_state_id', 255);
$table->string('region', 255);
$table->string('ik_region_id', 255);
$table->string('city', 255);
$table->string('ik_city_id', 255);
$table->string('zipcode', 255)->nullable();
$table->timestampTz('last_visited_at')->nullable();
$table->timestampsTz();
});
}
/**
* Reverse the migrations.
*/
public function down(): void {
Schema::drop('outlets');
}
};

@ -1,109 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void {
Schema::create('tvs', function (Blueprint $table) {
$table->id();
$table->string('code', 50)->unique();
$table->string('ik_address_id', 255)->nullable();
$table->integer('apk_version_code')->nullable();
$table->string('apk_version_name')->nullable();
$table->string('company_name')->nullable();
$table->string('address')->nullable();
$table->string('street_address')->nullable();
$table->string('col1', 255)->nullable();
$table->string('col2', 255)->nullable();
$table->string('col3', 255)->nullable();
$table->string('col4', 255)->nullable();
$table->string('col5', 255)->nullable();
$table->string('col6', 255)->nullable();
$table->string('col7', 255)->nullable();
$table->string('col8', 255)->nullable();
$table->string('col9', 255)->nullable();
$table->string('col10', 255)->nullable();
$table->string('notes', 255)->nullable();
$table->boolean('is_active')->default(true);
$table->jsonb('device_info')->nullable();
$table->timestampTz('installed_at');
$table->timestampTz('last_connected_at')->nullable();
$table->timestampsTz();
});
Schema::create('new_tv_requests', function (Blueprint $table) {
$table->id();
$table->string('code', 50);
$table->jsonb('device_info')->nullable();
$table->foreignId('tv_fk')->nullable();
$table->timestampTz('approved_at')->nullable();
$table->timestampTz('responded_at')->nullable();
$table->timestampsTz();
});
Schema::create('tv_logs', function (Blueprint $table) {
$table->id();
$table->foreignId('tv_fk');
$table->string('type');
$table->json('from')->nullable();
$table->json('to')->nullable();
$table->foreignId('user_fk')->nullable();
$table->timestampsTz();
$table->foreign('tv_fk')->references('id')->on('tvs')->cascadeOnDelete();
$table->foreign('user_fk')->references('id')->on('users');
});
// Schema::create('tv_sessions', function (Blueprint $table) {
// $table->id();
// $table->foreignId('tv_fk')->index();
// $table->timestampTz('started_at')->index();
// $table->timestampTz('finished_at')->nullable()->index();
// $table->boolean('is_playing_video');
// $table->jsonb('current_videos')->nullable();
// $table->timestampsTz();
// $table->foreign('tv_fk')->references('id')->on('tvs');
// });
// Schema::create('tv_app_infos', function (Blueprint $table) {
// $table->foreignId('tv_fk')->unique()->index();
// $table->timestampTz('installed_at')->nullable()->index();
// $table->jsonb('current_videos')->nullable();
// $table->timestampTz('last_updated_video')->nullable()->index();
// $table->timestampsTz();
// $table->foreign('tv_fk')->references('id')->on('tvs');
// });
// Schema::create('tv_app_logs', function (Blueprint $table) {
// $table->id();
// $table->foreignId('tv_fk')->index();
// $table->string('requested_to');
// $table->string('ip', 50);
// $table->jsonb('request_data')->nullable();
// $table->enum('result', ['success', 'failed']);
// $table->jsonb('response_data')->nullable();
// $table->timestampsTz();
// $table->foreign('tv_fk')->references('id')->on('tvs');
// });
}
/**
* Reverse the migrations.
*/
public function down(): void {
// Schema::drop('tv_app_logs');
// Schema::drop('tv_app_infos');
// Schema::drop('tv_sessions');
Schema::drop('tv_logs');
Schema::drop('new_tv_requests');
Schema::drop('tvs');
}
};

@ -1,39 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void {
Schema::create('sts_logs', function (Blueprint $table) {
$table->id();
$table->string('partner', 255)->nullable();
$table->boolean('is_outgoing');
$table->string('module', 255)->nullable();
$table->string('service_name', 255)->nullable();
$table->string('local_id', 255)->nullable();
$table->string('partner_id', 255)->nullable();
$table->enum('result', ['success', 'failed', 'warning']);
$table->jsonb('error_info')->nullable();
$table->tinyInteger('seq');
$table->jsonb('request_data')->nullable();
$table->timestampTz('request_time')->nullable();
$table->jsonb('response_data')->nullable();
$table->timestampTz('response_time')->nullable();
$table->boolean('is_retry')->default('false');
$table->timestampsTz();
});
}
/**
* Reverse the migrations.
*/
public function down(): void {
Schema::drop('sts_logs');
}
};

@ -1,26 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void {
Schema::table('video_updates', function(Blueprint $table) {
$table->double('file_size_kb')->default(0);
});
}
/**
* Reverse the migrations.
*/
public function down(): void {
Schema::table('video_updates', function(Blueprint $table) {
$table->dropColumn('file_size_kb');
});
}
};

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('apk_updates', function (Blueprint $table) {
$table->string('version_name', 50)->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('apk_updates', function (Blueprint $table) {
$table->dropColumn('version_name');
});
}
};

@ -1,16 +1,10 @@
<?php
use App\Http\Controllers\api\mobile\CheckUpdateController;
use App\Http\Controllers\api\mobile\TvController;
use Illuminate\Support\Facades\Route;
Route::controller(CheckUpdateController::class)->group(function() {
Route::post('/check-update/video-update/latest', 'videoUpdateLatest');
Route::post('/check-update/apk-update/latest', 'apkUpdateLatest');
});
Route::controller(TvController::class)->group(function() {
Route::post('/tv/new-request', 'newRequest');
Route::post('/tv/check-update', 'checkUpdate');
});
})
?>

@ -1,17 +1,10 @@
<?php
use App\Http\Controllers\api\superadmin\ApkUploadController;
use App\Http\Controllers\api\superadmin\GeneralController;
use App\Http\Controllers\api\superadmin\tv\NewTvRequestController;
use App\Http\Controllers\api\superadmin\tv\TvController;
use App\Http\Controllers\api\superadmin\UserManagementController;
use App\Http\Controllers\api\superadmin\VideoUploadController;
use Illuminate\Support\Facades\Route;
Route::controller(GeneralController::class)->group(function() {
Route::post('/general/tv/search', 'tvSearch');
});
Route::controller(VideoUploadController::class)->group(function() {
Route::post('/video-upload', 'init');
Route::post('/video-upload/save', 'save');
@ -36,17 +29,4 @@ Route::controller(UserManagementController::class)->group(function() {
Route::post('/user-management/delete', 'delete');
});
Route::controller(TvController::class)->group(function() {
Route::post('/tv/tv', 'init');
Route::post('/tv/tv/update', 'update');
Route::post('/tv/tv/change-status', 'changeStatus');
Route::post('/tv/tv/excel', 'excel');
});
Route::controller(NewTvRequestController::class)->group(function() {
Route::post('/tv/new-tv-request', 'init');
Route::post('/tv/new-tv-request/approve', 'approve');
Route::post('/tv/new-tv-request/reject', 'reject');
Route::post('/tv/new-tv-request/tv/search', 'tvSearch');
});
?>
Loading…
Cancel
Save