From f36203b87aa5385ce85ac15599ebbea1d5f0f2f1 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sat, 20 Dec 2025 12:06:23 +0100
Subject: [PATCH 1/8] [DBTools] Some fixes
---
application/views/logbookadvanced/dbtoolsdialog.php | 2 +-
.../views/logbookadvanced/showMissingDxccQsos.php | 11 ++++++++++-
2 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/application/views/logbookadvanced/dbtoolsdialog.php b/application/views/logbookadvanced/dbtoolsdialog.php
index 543052a43..fedec1139 100644
--- a/application/views/logbookadvanced/dbtoolsdialog.php
+++ b/application/views/logbookadvanced/dbtoolsdialog.php
@@ -90,7 +90,7 @@
- config->item('callbook_batch_lookup')): ?>
+ config->item('callbook_batch_lookup') ?? true): ?>
= __("Lookup QSOs with missing grid in callbook") ?>
diff --git a/application/views/logbookadvanced/showMissingDxccQsos.php b/application/views/logbookadvanced/showMissingDxccQsos.php
index f98c3049a..8a6f3e7f7 100644
--- a/application/views/logbookadvanced/showMissingDxccQsos.php
+++ b/application/views/logbookadvanced/showMissingDxccQsos.php
@@ -1,3 +1,12 @@
+session->userdata('user_date_format')) {
+ // If Logged in and session exists
+ $custom_date_format = $this->session->userdata('user_date_format');
+} else {
+ // Get Default date format from /config/wavelog.php
+ $custom_date_format = $this->config->item('qso_date_format');
+}
+?>
0): ?>
@@ -21,7 +30,7 @@
| col_primary_key . ')">' . htmlspecialchars($qso->col_call) . ''; ?> |
- col_time_on)); ?> |
+ col_time_on)); ?> |
col_mode; ?> |
col_band; ?> |
col_state; ?> |
From 5537f6ed43fb178fc488a6803cc88e8dcdd07cb0 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sat, 20 Dec 2025 12:53:31 +0100
Subject: [PATCH 2/8] Changed header in table
---
application/models/Logbookadvanced_model.php | 120 +++++++++++++++++-
.../logbookadvanced/showMissingDxccQsos.php | 2 +-
2 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index f5a7522d7..6161260dd 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1609,7 +1609,7 @@ class Logbookadvanced_model extends CI_Model {
$count = 0;
foreach ($query->result() as $qso) {
- $result = $this->fixStateSingle($qso->COL_PRIMARY_KEY);
+ $result = $this->fixStateDxcc($qso->COL_PRIMARY_KEY);
if ($result['success']) {
$count++;
} else {
@@ -1625,6 +1625,124 @@ class Logbookadvanced_model extends CI_Model {
return $results;
}
+ /**
+ * Fix state for a batch of QSOs, based on the DXCC
+ *
+ * @param int $qso_id QSO primary key
+ * @return array Result array with success, dxcc_name, dxcc_number, state_code, skipped
+ */
+ function fixStateDxcc($qso_id) {
+ $this->load->library('Geojson');
+
+ // Get QSO data
+ $sql = "SELECT COL_PRIMARY_KEY, COL_CALL, COL_GRIDSQUARE, COL_DXCC, COL_STATE, d.name as dxcc_name
+ FROM " . $this->config->item('table_name') . " qsos
+ JOIN station_profile ON qsos.station_id = station_profile.station_id
+ LEFT JOIN dxcc_entities d ON qsos.COL_DXCC = d.adif
+ WHERE qsos.COL_PRIMARY_KEY = ? AND station_profile.user_id = ?";
+
+ $query = $this->db->query($sql, [$qso_id, $this->session->userdata('user_id')]);
+
+ if ($query->num_rows() === 0) {
+ return [
+ 'success' => false,
+ 'skipped' => true,
+ 'reason' => 'QSO not found'
+ ];
+ }
+
+ $qso = $query->row();
+ $callsign = $qso->COL_CALL ?? 'Unknown';
+ $dxcc = (int)$qso->COL_DXCC;
+ $gridsquare = $qso->COL_GRIDSQUARE;
+ $state = $qso->COL_STATE ?? '';
+ $dxcc_name = $qso->dxcc_name ?? 'Unknown';
+
+ // Skip if state is already populated
+ if (!empty($state)) {
+ return [
+ 'success' => false,
+ 'skipped' => true,
+ 'callsign' => $callsign,
+ 'dxcc_number' => $dxcc,
+ 'dxcc_name' => $dxcc_name,
+ 'reason' => 'State already set'
+ ];
+ }
+
+ // Check if gridsquare exists
+ if (empty($gridsquare)) {
+ return [
+ 'success' => false,
+ 'skipped' => true,
+ 'callsign' => $callsign,
+ 'dxcc_number' => $dxcc,
+ 'dxcc_name' => $dxcc_name,
+ 'reason' => 'No gridsquare'
+ ];
+ }
+
+ // Check if gridsquare is precise enough (at least 6 characters)
+ if (strlen($gridsquare) < 6) {
+ return [
+ 'success' => false,
+ 'skipped' => true,
+ 'callsign' => $callsign,
+ 'dxcc_number' => $dxcc,
+ 'dxcc_name' => $dxcc_name,
+ 'reason' => 'Gridsquare not precise enough'
+ ];
+ }
+
+ // Check if state is supported for this DXCC
+ if (!$this->geojson->isStateSupported($dxcc)) {
+ return [
+ 'success' => false,
+ 'skipped' => true,
+ 'callsign' => $callsign,
+ 'dxcc_number' => $dxcc,
+ 'dxcc_name' => $dxcc_name,
+ 'reason' => 'DXCC not supported'
+ ];
+ }
+
+ // Find state from gridsquare
+ $state = $this->geojson->findStateFromGridsquare($gridsquare, $dxcc);
+
+ if ($state === null || !isset($state['code'])) {
+ // Get coordinates for debugging
+ $coords = $this->geojson->gridsquareToLatLng($gridsquare);
+ return [
+ 'success' => false,
+ 'skipped' => false,
+ 'callsign' => $callsign,
+ 'dxcc_number' => $dxcc,
+ 'dxcc_name' => $dxcc_name,
+ 'gridsquare' => $gridsquare,
+ 'lat' => $coords['lat'] ?? null,
+ 'lng' => $coords['lng'] ?? null,
+ 'reason' => 'State not found in GeoJSON'
+ ];
+ }
+
+ // Update the state
+ $update_sql = "UPDATE " . $this->config->item('table_name') . "
+ SET COL_STATE = ?
+ WHERE COL_PRIMARY_KEY = ?";
+
+ $this->db->query($update_sql, [$state['code'], $qso_id]);
+
+ return [
+ 'success' => true,
+ 'skipped' => false,
+ 'callsign' => $callsign,
+ 'dxcc_number' => $dxcc,
+ 'dxcc_name' => $dxcc_name,
+ 'state_code' => $state['code'],
+ 'state_name' => $state['name'] ?? null
+ ];
+ }
+
function getStateListQsos($dxcc) {
$sql = "SELECT col_primary_key, col_call, col_time_on, col_mode, col_submode, col_band, col_state, col_gridsquare, d.name as dxcc_name, station_profile.station_profile_name FROM " . $this->config->item('table_name') . " qsos
JOIN station_profile ON qsos.station_id = station_profile.station_id
diff --git a/application/views/logbookadvanced/showMissingDxccQsos.php b/application/views/logbookadvanced/showMissingDxccQsos.php
index 8a6f3e7f7..4f6b58f7f 100644
--- a/application/views/logbookadvanced/showMissingDxccQsos.php
+++ b/application/views/logbookadvanced/showMissingDxccQsos.php
@@ -23,7 +23,7 @@ if($this->session->userdata('user_date_format')) {
= __("State") ?> |
= __("Gridsquare") ?> |
= __("DXCC") ?> |
- = __("Station") ?> |
+ = __("Station Location") ?> |
From 5375f03fb8e89606823b625f791c0fe332ac5e07 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sat, 20 Dec 2025 15:53:05 +0100
Subject: [PATCH 3/8] Load geojson file in constructor
---
application/libraries/Geojson.php | 18 +++++++++++++-----
application/models/Logbookadvanced_model.php | 4 +---
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/application/libraries/Geojson.php b/application/libraries/Geojson.php
index 8d3890dc2..db4b87772 100644
--- a/application/libraries/Geojson.php
+++ b/application/libraries/Geojson.php
@@ -66,11 +66,17 @@ class Geojson {
];
private $qra;
+ private $geojsonFile = null;
+ private $geojsonData = null;
- public function __construct() {
+ public function __construct($dxcc = null) {
$CI =& get_instance();
$CI->load->library('qra');
$this->qra = $CI->qra;
+ if ($dxcc !== null) {
+ $this->geojsonFile = "assets/json/geojson/states_{$dxcc}.geojson";
+ $this->geojsonData = $this->loadGeoJsonFile($geojsonFile);
+ }
}
// ============================================================================
@@ -114,14 +120,16 @@ class Geojson {
return null;
}
- $geojsonFile = "assets/json/geojson/states_{$dxcc}.geojson";
- $geojsonData = $this->loadGeoJsonFile($geojsonFile);
+ if ($this->geojsonFile === null) {
+ $this->geojsonFile = "assets/json/geojson/states_{$dxcc}.geojson";
+ $this->geojsonData = $this->loadGeoJsonFile($this->geojsonFile);
+ }
- if ($geojsonData === null) {
+ if ($this->geojsonData === null) {
return null;
}
- return $this->findFeatureContainingPoint($lat, $lng, $geojsonData);
+ return $this->findFeatureContainingPoint($lat, $lng, $this->geojsonData);
}
/**
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index 6161260dd..5052e6e50 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1583,7 +1583,7 @@ class Logbookadvanced_model extends CI_Model {
* @return array Result array with success, dxcc_name, dxcc_number, state_code, skipped
*/
function fixStateBatch($dxcc) {
- $this->load->library('Geojson');
+ $this->load->library('Geojson', $dxcc);
// Get QSO data
$sql = "SELECT COL_PRIMARY_KEY, COL_CALL, COL_GRIDSQUARE, COL_DXCC, COL_STATE, d.name as dxcc_name, station_profile.station_profile_name
@@ -1632,8 +1632,6 @@ class Logbookadvanced_model extends CI_Model {
* @return array Result array with success, dxcc_name, dxcc_number, state_code, skipped
*/
function fixStateDxcc($qso_id) {
- $this->load->library('Geojson');
-
// Get QSO data
$sql = "SELECT COL_PRIMARY_KEY, COL_CALL, COL_GRIDSQUARE, COL_DXCC, COL_STATE, d.name as dxcc_name
FROM " . $this->config->item('table_name') . " qsos
From 136f2213dccf6e077ace326d3e549b5abcb96bae Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sat, 20 Dec 2025 16:05:28 +0100
Subject: [PATCH 4/8] Optimize state setting
---
application/models/Logbookadvanced_model.php | 72 +-------------------
1 file changed, 3 insertions(+), 69 deletions(-)
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index 5052e6e50..beba8c37a 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1609,7 +1609,7 @@ class Logbookadvanced_model extends CI_Model {
$count = 0;
foreach ($query->result() as $qso) {
- $result = $this->fixStateDxcc($qso->COL_PRIMARY_KEY);
+ $result = $this->fixStateDxcc($qso);
if ($result['success']) {
$count++;
} else {
@@ -1631,79 +1631,13 @@ class Logbookadvanced_model extends CI_Model {
* @param int $qso_id QSO primary key
* @return array Result array with success, dxcc_name, dxcc_number, state_code, skipped
*/
- function fixStateDxcc($qso_id) {
- // Get QSO data
- $sql = "SELECT COL_PRIMARY_KEY, COL_CALL, COL_GRIDSQUARE, COL_DXCC, COL_STATE, d.name as dxcc_name
- FROM " . $this->config->item('table_name') . " qsos
- JOIN station_profile ON qsos.station_id = station_profile.station_id
- LEFT JOIN dxcc_entities d ON qsos.COL_DXCC = d.adif
- WHERE qsos.COL_PRIMARY_KEY = ? AND station_profile.user_id = ?";
-
- $query = $this->db->query($sql, [$qso_id, $this->session->userdata('user_id')]);
-
- if ($query->num_rows() === 0) {
- return [
- 'success' => false,
- 'skipped' => true,
- 'reason' => 'QSO not found'
- ];
- }
-
- $qso = $query->row();
+ function fixStateDxcc($qso) {
$callsign = $qso->COL_CALL ?? 'Unknown';
$dxcc = (int)$qso->COL_DXCC;
$gridsquare = $qso->COL_GRIDSQUARE;
$state = $qso->COL_STATE ?? '';
$dxcc_name = $qso->dxcc_name ?? 'Unknown';
- // Skip if state is already populated
- if (!empty($state)) {
- return [
- 'success' => false,
- 'skipped' => true,
- 'callsign' => $callsign,
- 'dxcc_number' => $dxcc,
- 'dxcc_name' => $dxcc_name,
- 'reason' => 'State already set'
- ];
- }
-
- // Check if gridsquare exists
- if (empty($gridsquare)) {
- return [
- 'success' => false,
- 'skipped' => true,
- 'callsign' => $callsign,
- 'dxcc_number' => $dxcc,
- 'dxcc_name' => $dxcc_name,
- 'reason' => 'No gridsquare'
- ];
- }
-
- // Check if gridsquare is precise enough (at least 6 characters)
- if (strlen($gridsquare) < 6) {
- return [
- 'success' => false,
- 'skipped' => true,
- 'callsign' => $callsign,
- 'dxcc_number' => $dxcc,
- 'dxcc_name' => $dxcc_name,
- 'reason' => 'Gridsquare not precise enough'
- ];
- }
-
- // Check if state is supported for this DXCC
- if (!$this->geojson->isStateSupported($dxcc)) {
- return [
- 'success' => false,
- 'skipped' => true,
- 'callsign' => $callsign,
- 'dxcc_number' => $dxcc,
- 'dxcc_name' => $dxcc_name,
- 'reason' => 'DXCC not supported'
- ];
- }
-
// Find state from gridsquare
$state = $this->geojson->findStateFromGridsquare($gridsquare, $dxcc);
@@ -1728,7 +1662,7 @@ class Logbookadvanced_model extends CI_Model {
SET COL_STATE = ?
WHERE COL_PRIMARY_KEY = ?";
- $this->db->query($update_sql, [$state['code'], $qso_id]);
+ $this->db->query($update_sql, [$state['code'], $qso->COL_PRIMARY_KEY]);
return [
'success' => true,
From 3b1f7f71b0dbc3641a352098be2a0abf80d28169 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sun, 21 Dec 2025 08:11:22 +0100
Subject: [PATCH 5/8] We don't need coordinates
---
application/models/Logbookadvanced_model.php | 4 ----
1 file changed, 4 deletions(-)
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index beba8c37a..6e8ff6cd1 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1642,8 +1642,6 @@ class Logbookadvanced_model extends CI_Model {
$state = $this->geojson->findStateFromGridsquare($gridsquare, $dxcc);
if ($state === null || !isset($state['code'])) {
- // Get coordinates for debugging
- $coords = $this->geojson->gridsquareToLatLng($gridsquare);
return [
'success' => false,
'skipped' => false,
@@ -1651,8 +1649,6 @@ class Logbookadvanced_model extends CI_Model {
'dxcc_number' => $dxcc,
'dxcc_name' => $dxcc_name,
'gridsquare' => $gridsquare,
- 'lat' => $coords['lat'] ?? null,
- 'lng' => $coords['lng'] ?? null,
'reason' => 'State not found in GeoJSON'
];
}
From 97868db3c86be350c54e4b95fef849f60204d623 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sun, 21 Dec 2025 08:20:40 +0100
Subject: [PATCH 6/8] Batch update
---
application/models/Logbookadvanced_model.php | 28 ++++++++++++--------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index 6e8ff6cd1..ed4d2011d 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1605,13 +1605,17 @@ class Logbookadvanced_model extends CI_Model {
}
$results = [];
-
- $count = 0;
+ $batch_updates = [];
foreach ($query->result() as $qso) {
$result = $this->fixStateDxcc($qso);
+
if ($result['success']) {
- $count++;
+ // Prepare data for batch update
+ $batch_updates[] = [
+ 'COL_PRIMARY_KEY' => $qso->COL_PRIMARY_KEY,
+ 'COL_STATE' => $result['state_code']
+ ];
} else {
$result['station_profile_name'] = $qso->station_profile_name;
$result['id'] = $qso->COL_PRIMARY_KEY;
@@ -1620,6 +1624,13 @@ class Logbookadvanced_model extends CI_Model {
}
}
+ // Perform batch update if there are any updates
+ $count = 0;
+ if (!empty($batch_updates)) {
+ $this->db->update_batch($this->config->item('table_name'), $batch_updates, 'COL_PRIMARY_KEY');
+ $count = count($batch_updates);
+ }
+
$results['count'] = $count;
return $results;
@@ -1627,8 +1638,9 @@ class Logbookadvanced_model extends CI_Model {
/**
* Fix state for a batch of QSOs, based on the DXCC
+ * Note: This now only validates and prepares data
*
- * @param int $qso_id QSO primary key
+ * @param object $qso QSO object
* @return array Result array with success, dxcc_name, dxcc_number, state_code, skipped
*/
function fixStateDxcc($qso) {
@@ -1653,13 +1665,7 @@ class Logbookadvanced_model extends CI_Model {
];
}
- // Update the state
- $update_sql = "UPDATE " . $this->config->item('table_name') . "
- SET COL_STATE = ?
- WHERE COL_PRIMARY_KEY = ?";
-
- $this->db->query($update_sql, [$state['code'], $qso->COL_PRIMARY_KEY]);
-
+ // Return success with state info
return [
'success' => true,
'skipped' => false,
From 09bbaf18989898b23b6626f71c895067b7ca2067 Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sun, 21 Dec 2025 08:28:52 +0100
Subject: [PATCH 7/8] Remove commented out text
---
application/views/logbookadvanced/index.php | 8 --------
1 file changed, 8 deletions(-)
diff --git a/application/views/logbookadvanced/index.php b/application/views/logbookadvanced/index.php
index 3e8a453c8..1b773023b 100644
--- a/application/views/logbookadvanced/index.php
+++ b/application/views/logbookadvanced/index.php
@@ -773,14 +773,6 @@ $options = json_decode($options);
-
From bf8b8b71008b49d4ad41c37ec168f5b4656ca42a Mon Sep 17 00:00:00 2001
From: Andreas Kristiansen <6977712+AndreasK79@users.noreply.github.com>
Date: Sun, 21 Dec 2025 08:41:48 +0100
Subject: [PATCH 8/8] Limit callbook grid fixer to 150 per run, and add batch
update
---
application/models/Logbookadvanced_model.php | 30 +++++++++++++------
.../views/logbookadvanced/dbtoolsdialog.php | 2 +-
2 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index ed4d2011d..c7f0bce01 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1776,29 +1776,41 @@ class Logbookadvanced_model extends CI_Model {
$result = $this->getMissingGridQsos();
$count = 0;
+ $batch_updates = [];
+
$this->db->trans_start();
+
if (count($result) > 0) {
+ if (!$this->load->is_loaded('callbook')) {
+ $this->load->library('callbook');
+ }
+
foreach ($result as $row) {
$callsign = $row->col_call;
- if (!$this->load->is_loaded('callbook')) {
- $this->load->library('callbook');
- }
-
$callbook = $this->callbook->getCallbookData($callsign);
if (isset($callbook)) {
if (isset($callbook['error'])) {
log_message('error', "Error: " . $callbook['error']);
} else {
- if ($callbook['gridsquare'] != '') {
- $sql = "update " . $this->config->item('table_name') . " set COL_GRIDSQUARE = ? where COL_PRIMARY_KEY = ?";
- $this->db->query($sql, array($callbook['gridsquare'], $row->col_primary_key));
- $count++;
+ if (isset($callbook['gridsquare']) && $callbook['gridsquare'] != '') {
+ // Prepare data for batch update
+ $batch_updates[] = [
+ 'COL_PRIMARY_KEY' => $row->col_primary_key,
+ 'COL_GRIDSQUARE' => $callbook['gridsquare']
+ ];
}
}
}
}
+
+ // Perform batch update if there are any updates
+ if (!empty($batch_updates)) {
+ $this->db->update_batch($this->config->item('table_name'), $batch_updates, 'COL_PRIMARY_KEY');
+ $count = count($batch_updates);
+ }
}
+
$this->db->trans_complete();
return $count;
@@ -1810,7 +1822,7 @@ class Logbookadvanced_model extends CI_Model {
WHERE station_profile.user_id = ?
AND (qsos.COL_GRIDSQUARE IS NULL OR qsos.COL_GRIDSQUARE = '')
AND (qsos.COL_VUCC_GRIDS IS NULL OR qsos.COL_VUCC_GRIDS = '')
- ORDER BY COL_TIME_ON DESC limit 250";
+ ORDER BY COL_TIME_ON DESC limit 150";
$query = $this->db->query($sql, [$this->session->userdata('user_id')]);
diff --git a/application/views/logbookadvanced/dbtoolsdialog.php b/application/views/logbookadvanced/dbtoolsdialog.php
index fedec1139..c9a14318c 100644
--- a/application/views/logbookadvanced/dbtoolsdialog.php
+++ b/application/views/logbookadvanced/dbtoolsdialog.php
@@ -95,7 +95,7 @@
= __("Lookup QSOs with missing grid in callbook") ?>
= __("Use callbook lookup to set gridsquare") ?>
-
= __("This is limited to 250 callsigns for each run!") ?>
+
= __("This is limited to 150 callsigns for each run!") ?>