|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
namespace App\Models;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use App\Helper\DatabaseHelper;
|
|
|
|
use App\Helper\JSONResponse;
|
|
|
|
use App\Helper\JSONResponse;
|
|
|
|
use App\Helper\STS\Indokargo;
|
|
|
|
use App\Helper\STS\Indokargo;
|
|
|
|
use App\Helper\Traits\Models\CanMultiOrderBy;
|
|
|
|
use App\Helper\Traits\Models\CanMultiOrderBy;
|
|
|
|
@ -14,8 +15,10 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
use Illuminate\Validation\Rule;
|
|
|
|
use Illuminate\Validation\Rule;
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
|
|
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
|
|
|
|
|
|
|
|
class Tv extends Model {
|
|
|
|
class Tv extends Model {
|
|
|
|
use HasFactory;
|
|
|
|
use HasFactory;
|
|
|
|
@ -43,14 +46,14 @@ class Tv extends Model {
|
|
|
|
// -- RELATED TO DATA FUNCTION
|
|
|
|
// -- RELATED TO DATA FUNCTION
|
|
|
|
public static function generateUniqueCode() {
|
|
|
|
public static function generateUniqueCode() {
|
|
|
|
// init
|
|
|
|
// init
|
|
|
|
$totalSuffixDigit = 5;
|
|
|
|
$countSuffixDigit = 5;
|
|
|
|
date_default_timezone_set('Asia/Jakarta');
|
|
|
|
date_default_timezone_set('Asia/Jakarta');
|
|
|
|
$prefixCode = 'TV' . date('Ym');
|
|
|
|
$prefixCode = 'TV' . date('Ym');
|
|
|
|
|
|
|
|
|
|
|
|
// try to get unique suffix
|
|
|
|
// try to get unique suffix
|
|
|
|
$uniqueCode = '';
|
|
|
|
$uniqueCode = '';
|
|
|
|
while(true) {
|
|
|
|
while(true) {
|
|
|
|
$suffixCode = strtoupper(Str::random($totalSuffixDigit));
|
|
|
|
$suffixCode = strtoupper(Str::random($countSuffixDigit));
|
|
|
|
$uniqueCode = $prefixCode . $suffixCode;
|
|
|
|
$uniqueCode = $prefixCode . $suffixCode;
|
|
|
|
$isUnique = TV::where('code', $uniqueCode)->first();
|
|
|
|
$isUnique = TV::where('code', $uniqueCode)->first();
|
|
|
|
if(!$isUnique) break;
|
|
|
|
if(!$isUnique) break;
|
|
|
|
@ -62,14 +65,39 @@ class Tv extends Model {
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
// -- RELATED TO REQUEST
|
|
|
|
// -- RELATED TO REQUEST
|
|
|
|
|
|
|
|
public static function validateAndGetEloquentFromRequest(Request $request) {
|
|
|
|
|
|
|
|
$request->validate([
|
|
|
|
|
|
|
|
...DatabaseHelper::getOrderBysValidations(),
|
|
|
|
|
|
|
|
'search' => DatabaseHelper::getSearchValidation(),
|
|
|
|
|
|
|
|
'apkVersionCode' => 'nullable|integer',
|
|
|
|
|
|
|
|
'isActive' => 'nullable|boolean',
|
|
|
|
|
|
|
|
'lastConnectedAt' => 'nullable|array',
|
|
|
|
|
|
|
|
'lastConnectedAt.from' => 'nullable|date',
|
|
|
|
|
|
|
|
'lastConnectedAt.to' => 'nullable|date'
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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->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) {
|
|
|
|
public static function updateFromRequest(Request $request) {
|
|
|
|
if($request->code) $request->merge(['code' => strtoupper($request->code)]);
|
|
|
|
if($request->code) $request->merge(['code' => strtoupper($request->code)]);
|
|
|
|
$request->validate([
|
|
|
|
$request->validate([
|
|
|
|
'id' => 'required|integer|exists:App\Models\Tv',
|
|
|
|
'id' => 'required|integer|exists:App\Models\Tv',
|
|
|
|
'code' => ['required','string',Rule::unique('tvs', 'code')
|
|
|
|
'code' => ['required','string',Rule::unique('tvs', 'code')
|
|
|
|
->when($request->id, function($q, $id) {
|
|
|
|
->when($request->id, function($q, $id) { $q->whereNot('id', $id);})],
|
|
|
|
$q->whereNot('id', $id);
|
|
|
|
|
|
|
|
})],
|
|
|
|
|
|
|
|
'company_name' => 'nullable|string',
|
|
|
|
'company_name' => 'nullable|string',
|
|
|
|
'address' => 'nullable|string',
|
|
|
|
'address' => 'nullable|string',
|
|
|
|
'street_address' => 'nullable|string',
|
|
|
|
'street_address' => 'nullable|string',
|
|
|
|
@ -108,7 +136,7 @@ class Tv extends Model {
|
|
|
|
DB::commit();
|
|
|
|
DB::commit();
|
|
|
|
return JSONResponse::Success(['message'=>'Success to update tv data']);
|
|
|
|
return JSONResponse::Success(['message'=>'Success to update tv data']);
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: waiting from ops workflow
|
|
|
|
// TODO: waiting from ops workflow (Dont forget to resync co_name, address, street address in ik)
|
|
|
|
// // try to sys_to_sys with indokargo
|
|
|
|
// // try to sys_to_sys with indokargo
|
|
|
|
// $jsonResponse = Indokargo::updateTVAddress($request, $tv->id, $tv->ik_address_id);
|
|
|
|
// $jsonResponse = Indokargo::updateTVAddress($request, $tv->id, $tv->ik_address_id);
|
|
|
|
// DB::commit();
|
|
|
|
// DB::commit();
|
|
|
|
@ -129,7 +157,7 @@ class Tv extends Model {
|
|
|
|
DB::commit();
|
|
|
|
DB::commit();
|
|
|
|
return JSONResponse::Success(['message'=>'Success to change tv status']);
|
|
|
|
return JSONResponse::Success(['message'=>'Success to change tv status']);
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: waiting from ops workflow
|
|
|
|
// TODO: waiting from ops workflow (Dont forget to resync co_name, address, street address in ik)
|
|
|
|
// // try to sys_to_sys with indokargo
|
|
|
|
// // try to sys_to_sys with indokargo
|
|
|
|
// $jsonResponse = Indokargo::changeStatusAddress(new Request(['is_active' => $tv->is_active]),
|
|
|
|
// $jsonResponse = Indokargo::changeStatusAddress(new Request(['is_active' => $tv->is_active]),
|
|
|
|
// $tv->id, $tv->ik_address_id);
|
|
|
|
// $tv->id, $tv->ik_address_id);
|
|
|
|
@ -140,6 +168,193 @@ class Tv extends Model {
|
|
|
|
throw $th;
|
|
|
|
throw $th;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// -- END RELATED TO REQUES
|
|
|
|
// -- END RELATED TO REQUEST
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
// -- RELATED TO EXCEL
|
|
|
|
|
|
|
|
public static function getExcelDetail(Request $request) {
|
|
|
|
|
|
|
|
$cols = ['code', 'apk_version_code', 'apk_version_name', 'last_connected_at',
|
|
|
|
|
|
|
|
'company_name', 'address', 'street_address', 'notes',
|
|
|
|
|
|
|
|
'col1', 'col2', 'col3', 'col4', 'col5',
|
|
|
|
|
|
|
|
'col6', 'col7', 'col8', 'col9', 'col10',
|
|
|
|
|
|
|
|
'is_active'];
|
|
|
|
|
|
|
|
return JSONResponse::Success(['rows' => TV::validateAndGetEloquentFromRequest($request)->select(...$cols)->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)->select(...self::EXCEL_TEMPLATE_COLS)->get();
|
|
|
|
|
|
|
|
return JSONResponse::Success(['rows' => $rows]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------ 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) {
|
|
|
|
|
|
|
|
$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::saveHistory(TvLog::TYPE_CREATE, $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
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|