Initial commit
This commit is contained in:
272
app/Http/Controllers/QsoResultController.php
Normal file
272
app/Http/Controllers/QsoResultController.php
Normal file
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\QsoResult;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class QsoResultController extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// zápis pouze pro autentizované
|
||||
$this->middleware('auth:sanctum')->only(['store', 'update', 'destroy']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seznam QSO výsledků.
|
||||
* Filtrování podle evaluation_run_id, log_qso_id, log_id, call_like, matched_qso_id,
|
||||
* error_code, is_valid, is_duplicate, is_nil, only_ok.
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$perPage = (int) $request->get('per_page', 200);
|
||||
|
||||
$evalRunId = $request->filled('evaluation_run_id')
|
||||
? (int) $request->get('evaluation_run_id')
|
||||
: null;
|
||||
|
||||
$query = QsoResult::query()
|
||||
->with(['evaluationRun', 'logQso', 'matchedQso'])
|
||||
->when($evalRunId, function ($q) use ($evalRunId) {
|
||||
$q->with(['workingQso' => function ($wq) use ($evalRunId) {
|
||||
$wq->where('evaluation_run_id', $evalRunId);
|
||||
}]);
|
||||
});
|
||||
|
||||
if ($evalRunId !== null) {
|
||||
$query->where('evaluation_run_id', $evalRunId);
|
||||
}
|
||||
|
||||
if ($request->filled('log_qso_id')) {
|
||||
$query->where('log_qso_id', (int) $request->get('log_qso_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('log_id')) {
|
||||
$logId = (int) $request->get('log_id');
|
||||
$query->whereHas('logQso', function ($q) use ($logId) {
|
||||
$q->where('log_id', $logId);
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->filled('call_like')) {
|
||||
$raw = strtoupper((string) $request->get('call_like'));
|
||||
$pattern = str_replace(['*', '?'], ['%', '_'], $raw);
|
||||
if (strpos($pattern, '%') === false && strpos($pattern, '_') === false) {
|
||||
$pattern = '%' . $pattern . '%';
|
||||
}
|
||||
$query->where(function ($q) use ($pattern) {
|
||||
$q->whereHas('logQso', function ($qq) use ($pattern) {
|
||||
$qq->whereRaw('UPPER(my_call) LIKE ?', [$pattern])
|
||||
->orWhereRaw('UPPER(dx_call) LIKE ?', [$pattern]);
|
||||
})->orWhereHas('matchedQso', function ($qq) use ($pattern) {
|
||||
$qq->whereRaw('UPPER(my_call) LIKE ?', [$pattern])
|
||||
->orWhereRaw('UPPER(dx_call) LIKE ?', [$pattern]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if ($request->filled('matched_qso_id')) {
|
||||
$query->where('matched_qso_id', (int) $request->get('matched_qso_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('error_code')) {
|
||||
$query->where('error_code', $request->get('error_code'));
|
||||
}
|
||||
|
||||
if ($request->filled('is_valid')) {
|
||||
$query->where(
|
||||
'is_valid',
|
||||
filter_var($request->get('is_valid'), FILTER_VALIDATE_BOOL)
|
||||
);
|
||||
}
|
||||
|
||||
if ($request->filled('is_duplicate')) {
|
||||
$query->where(
|
||||
'is_duplicate',
|
||||
filter_var($request->get('is_duplicate'), FILTER_VALIDATE_BOOL)
|
||||
);
|
||||
}
|
||||
|
||||
if ($request->filled('is_nil')) {
|
||||
$query->where(
|
||||
'is_nil',
|
||||
filter_var($request->get('is_nil'), FILTER_VALIDATE_BOOL)
|
||||
);
|
||||
}
|
||||
|
||||
if ($request->filled('is_time_out_of_window')) {
|
||||
$query->where(
|
||||
'is_time_out_of_window',
|
||||
filter_var($request->get('is_time_out_of_window'), FILTER_VALIDATE_BOOL)
|
||||
);
|
||||
}
|
||||
|
||||
if (filter_var($request->get('only_problems'), FILTER_VALIDATE_BOOL)) {
|
||||
$query->where(function ($q) {
|
||||
$q->where(function ($qq) {
|
||||
$qq->whereNotNull('error_code')
|
||||
->where('error_code', '!=', 'OK');
|
||||
})
|
||||
->orWhere('is_nil', true)
|
||||
->orWhere('is_duplicate', true)
|
||||
->orWhere('is_busted_call', true)
|
||||
->orWhere('is_busted_exchange', true)
|
||||
->orWhere('is_time_out_of_window', true);
|
||||
});
|
||||
}
|
||||
|
||||
if (filter_var($request->get('only_ok'), FILTER_VALIDATE_BOOL)) {
|
||||
$query->where(function ($q) {
|
||||
$q->whereNull('error_code')
|
||||
->orWhere('error_code', 'OK');
|
||||
})
|
||||
->where('is_nil', false)
|
||||
->where('is_duplicate', false)
|
||||
->where('is_busted_call', false)
|
||||
->where('is_busted_exchange', false)
|
||||
->where('is_time_out_of_window', false);
|
||||
}
|
||||
|
||||
if (filter_var($request->get('missing_locator'), FILTER_VALIDATE_BOOL)) {
|
||||
$query->whereHas('workingQso', function ($q) use ($evalRunId) {
|
||||
if ($evalRunId !== null) {
|
||||
$q->where('evaluation_run_id', $evalRunId);
|
||||
}
|
||||
$q->whereNull('loc_norm')
|
||||
->orWhereNull('rloc_norm')
|
||||
->orWhereJsonContains('errors', 'INVALID_LOCATOR')
|
||||
->orWhereJsonContains('errors', 'INVALID_RLOCATOR');
|
||||
});
|
||||
}
|
||||
|
||||
$items = $query
|
||||
->orderBy('evaluation_run_id')
|
||||
->orderBy('log_qso_id')
|
||||
->paginate($perPage);
|
||||
|
||||
return response()->json($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vytvoření QSO výsledku.
|
||||
* Typicky voláno vyhodnocovačem, ne přímo z UI.
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$this->authorize('create', QsoResult::class);
|
||||
|
||||
$data = $this->validateData($request);
|
||||
|
||||
$result = QsoResult::create($data);
|
||||
|
||||
$result->load([
|
||||
'evaluationRun',
|
||||
'logQso',
|
||||
'matchedQso',
|
||||
'workingQso' => function ($q) use ($result) {
|
||||
$q->where('evaluation_run_id', $result->evaluation_run_id);
|
||||
},
|
||||
]);
|
||||
|
||||
return response()->json($result, 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detail jednoho QSO výsledku.
|
||||
*/
|
||||
public function show(QsoResult $qsoResult): JsonResponse
|
||||
{
|
||||
$qsoResult->load([
|
||||
'evaluationRun',
|
||||
'logQso',
|
||||
'matchedQso',
|
||||
'workingQso' => function ($q) use ($qsoResult) {
|
||||
$q->where('evaluation_run_id', $qsoResult->evaluation_run_id);
|
||||
},
|
||||
]);
|
||||
|
||||
return response()->json($qsoResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Aktualizace QSO výsledku (partial update).
|
||||
* Praktické pro ruční korekce / override.
|
||||
*/
|
||||
public function update(Request $request, QsoResult $qsoResult): JsonResponse
|
||||
{
|
||||
$this->authorize('update', $qsoResult);
|
||||
|
||||
$data = $this->validateData($request, partial: true);
|
||||
|
||||
$qsoResult->fill($data);
|
||||
$qsoResult->save();
|
||||
|
||||
$qsoResult->load([
|
||||
'evaluationRun',
|
||||
'logQso',
|
||||
'matchedQso',
|
||||
'workingQso' => function ($q) use ($qsoResult) {
|
||||
$q->where('evaluation_run_id', $qsoResult->evaluation_run_id);
|
||||
},
|
||||
]);
|
||||
|
||||
return response()->json($qsoResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Smazání QSO výsledku.
|
||||
*/
|
||||
public function destroy(QsoResult $qsoResult): JsonResponse
|
||||
{
|
||||
$this->authorize('delete', $qsoResult);
|
||||
|
||||
$qsoResult->delete();
|
||||
|
||||
return response()->json(null, 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validace vstupu pro store / update.
|
||||
*/
|
||||
protected function validateData(Request $request, bool $partial = false): array
|
||||
{
|
||||
$required = $partial ? 'sometimes' : 'required';
|
||||
|
||||
return $request->validate([
|
||||
'evaluation_run_id' => [$required, 'integer', 'exists:evaluation_runs,id'],
|
||||
'log_qso_id' => [$required, 'integer', 'exists:log_qsos,id'],
|
||||
|
||||
'is_valid' => ['sometimes', 'boolean'],
|
||||
'is_duplicate' => ['sometimes', 'boolean'],
|
||||
'is_nil' => ['sometimes', 'boolean'],
|
||||
'is_busted_call' => ['sometimes', 'boolean'],
|
||||
'is_busted_rst' => ['sometimes', 'boolean'],
|
||||
'is_busted_exchange' => ['sometimes', 'boolean'],
|
||||
'is_time_out_of_window' => ['sometimes', 'boolean'],
|
||||
|
||||
'points' => ['sometimes', 'integer'],
|
||||
'penalty_points' => ['sometimes', 'integer'],
|
||||
'distance_km' => ['sometimes', 'nullable', 'integer', 'min:0'],
|
||||
|
||||
'wwl' => ['sometimes', 'nullable', 'string', 'max:6'],
|
||||
'dxcc' => ['sometimes', 'nullable', 'string', 'max:10'],
|
||||
'country' => ['sometimes', 'nullable', 'string', 'max:100'],
|
||||
'section' => ['sometimes', 'nullable', 'string', 'max:50'],
|
||||
|
||||
'matched_qso_id' => ['sometimes', 'nullable', 'integer', 'exists:log_qsos,id'],
|
||||
'matched_log_qso_id' => ['sometimes', 'nullable', 'integer', 'exists:log_qsos,id'],
|
||||
'match_confidence' => ['sometimes', 'nullable', 'string', 'max:20'],
|
||||
|
||||
'error_code' => ['sometimes', 'nullable', 'string', 'max:50'],
|
||||
'error_side' => ['sometimes', 'nullable', 'string', 'max:10'],
|
||||
'error_detail' => ['sometimes', 'nullable', 'string'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user