From 81fcfe768906d88b5565948df84536a3daebd8ce Mon Sep 17 00:00:00 2001 From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com> Date: Sun, 11 Jan 2026 18:38:27 +0100 Subject: [PATCH] Added support for handling iotas with multiple dxccs --- application/models/Logbookadvanced_model.php | 118 ++++++++++++++----- 1 file changed, 86 insertions(+), 32 deletions(-) diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php index 2f3cdb524..5989e4e4b 100644 --- a/application/models/Logbookadvanced_model.php +++ b/application/models/Logbookadvanced_model.php @@ -2078,43 +2078,33 @@ class Logbookadvanced_model extends CI_Model { return $query->result(); } + public function checkIota() { + $result1 = $this->checkSingleIota(); + $result2 = $this->checkMultiDxccIota(); + + $merged = array_merge($result1, $result2); + + // Sort merged results by station_profile_name, then col_time_on DESC + usort($merged, function($a, $b) { + $stationCompare = strcmp($a->station_profile_name, $b->station_profile_name); + if ($stationCompare !== 0) { + return $stationCompare; + } + // If same station, sort by time_on descending (newest first) + return strtotime($b->col_time_on) - strtotime($a->col_time_on); + }); + + return $merged; + } + /* * Get list of QSOs with IOTA that do not match the IOTAs listed for the DXCC. * Some islands are excluded as they can be in multiple DXCCs. * - * These are excluded by not having a dxccid or dxccid = 0 in the iota table. - * 'AF-034','AF-055','AF-071','AS-004','AS-034','AS-035','AS-052','EU-005','EU-053', - * 'EU-098','EU-115','EU-117','EU-129','EU-154','EU-191','EU-192','NA-015','NA-096', - * 'NA-105','OC-034','OC-061','OC-088','OC-148','SA-008','OC-295' + * These are excluded by not having a dxccid or dxccid = 0 + * */ - public function checkIota() { - - $sql = "select col_primary_key, col_time_on, col_call, col_band, col_gridsquare, col_dxcc, col_country, station_profile_name, col_lotw_qsl_rcvd, col_mode, col_submode, col_iota, - ( - select group_concat(distinct dxcc_entities.name order by dxcc_entities.name separator ', ') - from iota - join dxcc_entities on dxcc_entities.adif = iota.dxccid - where iota.tag = thcv.col_iota - order by iota.dxccid asc - ) as correctdxcc - from " . $this->config->item('table_name') . " thcv - join station_profile on thcv.station_id = station_profile.station_id - join dxcc_entities on dxcc_entities.adif = thcv.COL_DXCC - join iota on thcv.col_iota = iota.tag - where station_profile.user_id = ? - and thcv.col_dxcc > 0 - and not exists ( - select 1 - from iota - where dxccid = thcv.col_dxcc - and tag = thcv.col_iota - ) - and thcv.col_iota is not null - and thcv.col_iota <> '' - and iota.dxccid is not null - and iota.dxccid > 0 - order by station_profile_name, col_time_on desc;"; - + public function checkSingleIota() { $sql = "select col_primary_key, col_time_on, col_call, col_band, col_gridsquare, col_dxcc, col_country, station_profile_name, col_lotw_qsl_rcvd, col_mode, col_submode, col_iota, iotadxcc.name as correctdxcc from " . $this->config->item('table_name') . " thcv join station_profile on thcv.station_id = station_profile.station_id @@ -2132,4 +2122,68 @@ class Logbookadvanced_model extends CI_Model { $query = $this->db->query($sql, $bindings); return $query->result(); } + + /* + * Get list of QSOs with multi-DXCC IOTA tags where the DXCC prefix doesn't match + * any of the valid prefixes for that IOTA. + */ + public function checkMultiDxccIota() { + // Define IOTA tags that span multiple DXCCs with their valid prefixes + $multiDxccIotas = [ + 'AS-004' => ['5b', 'zc'], + 'EU-053' => ['oj0', 'sm'], + 'EU-115' => ['ei', 'gi', 'mi'], + 'EU-117' => ['r1m', 'oh'], + 'EU-129' => ['dl', 'sp1'], + 'EU-191' => ['yo', 'ur'], + 'EU-192' => ['sm', 'oh'], + 'NA-015' => ['co', 'kg4'], + 'NA-096' => ['hh', 'hi'], + 'NA-105' => ['fs', 'pj7'], + 'OC-034' => ['p2', 'yb9'], + 'OC-088' => ['9m6', '9m8', 'v85', 'yb7'], + 'OC-148' => ['yb9', '4w'], + 'SA-008' => ['lu', 'ce8'], + ]; + + $allResults = []; + + foreach ($multiDxccIotas as $iotaTag => $prefixes) { + // Build IN clause for SQL + $prefixList = "'" . implode("','", $prefixes) . "'"; + + $sql = "SELECT col_primary_key, col_time_on, col_call, col_band, col_gridsquare, + col_dxcc, col_country, station_profile_name, col_lotw_qsl_rcvd, + col_mode, col_submode, col_iota, iotadxcc.name as correctdxcc + FROM " . $this->config->item('table_name') . " thcv + JOIN station_profile ON thcv.station_id = station_profile.station_id + JOIN dxcc_entities ON dxcc_entities.adif = thcv.COL_DXCC + JOIN iota ON thcv.col_iota = iota.tag + JOIN dxcc_entities iotadxcc ON LOWER(iotadxcc.prefix) IN ($prefixList) + WHERE station_profile.user_id = ? + AND thcv.col_iota = ? + AND LOWER(dxcc_entities.prefix) NOT IN ($prefixList) + ORDER BY station_profile_name, col_time_on DESC"; + + $bindings = [$this->session->userdata('user_id'), $iotaTag]; + $query = $this->db->query($sql, $bindings); + $results = $query->result(); + + if (!empty($results)) { + $allResults = array_merge($allResults, $results); + } + } + + // Sort the merged results by station_profile_name, then col_time_on DESC + usort($allResults, function($a, $b) { + $stationCompare = strcmp($a->station_profile_name, $b->station_profile_name); + if ($stationCompare !== 0) { + return $stationCompare; + } + // If same station, sort by time_on descending (newest first) + return strtotime($b->col_time_on) - strtotime($a->col_time_on); + }); + + return $allResults; + } }