diff --git a/application/controllers/Logbookadvanced.php b/application/controllers/Logbookadvanced.php
index 8b963fefa8..4e7e9d12f3 100644
--- a/application/controllers/Logbookadvanced.php
+++ b/application/controllers/Logbookadvanced.php
@@ -785,7 +785,6 @@ public function fixCqZones() {
header("Content-Type: application/json");
print json_encode($q);
-
}
public function fixItuZones() {
@@ -834,8 +833,11 @@ public function fixContinent() {
$this->load->model('logbookadvanced_model');
$result = $this->logbookadvanced_model->check_missing_continent();
- header("Content-Type: application/json");
- print json_encode($result);
+ $data['result'] = $result;
+
+ $data['type'] = 'continent';
+
+ $this->load->view('logbookadvanced/showUpdateResult', $data);
}
public function fixStateProgress() {
@@ -874,14 +876,110 @@ public function fixStateProgress() {
}
public function updateDistances() {
+ if(!clubaccess_check(9)) return;
+
$this->load->model('logbookadvanced_model');
$result = $this->logbookadvanced_model->update_distances_batch();
- header("Content-Type: application/json");
- print json_encode($result);
+ $data['result'] = $result;
+
+ $data['type'] = 'distance';
+
+ $this->load->view('logbookadvanced/showUpdateResult', $data);
}
public function callbookDialog() {
$this->load->view('logbookadvanced/callbookdialog');
}
+
+ public function dbtoolsDialog() {
+ $this->load->view('logbookadvanced/dbtoolsdialog');
+ }
+
+ public function checkDb() {
+ if(!clubaccess_check(9)) return;
+
+ $type = $this->input->post('type', true);
+ $this->load->model('logbookadvanced_model');
+
+ $data['result'] = $this->logbookadvanced_model->runCheckDb($type);
+ if ($type == 'checkstate') {
+ $this->load->view('logbookadvanced/statecheckresult', $data);
+ } else {
+ $data['type'] = $type;
+ $this->load->view('logbookadvanced/checkresult', $data);
+ }
+
+ }
+
+ public function fixStateBatch() {
+ if(!clubaccess_check(9)) return;
+
+ $this->load->model('logbook_model');
+ $this->load->model('logbookadvanced_model');
+
+ $dxcc = $this->input->post('dxcc', true);
+ $data['country'] = $this->input->post('country', true);
+
+ // Process for batch QSO state fix
+ $result = $this->logbookadvanced_model->fixStateBatch($dxcc);
+
+ $data['result'] = $result;
+
+ $data['type'] = 'state';
+
+ $this->load->view('logbookadvanced/showUpdateResult', $data);
+ }
+
+ public function openStateList() {
+ if(!clubaccess_check(9)) return;
+
+ $this->load->model('logbookadvanced_model');
+
+ $data['dxcc'] = $this->input->post('dxcc', true);
+ $data['country'] = $this->input->post('country', true);
+
+ // Process for batch QSO state fix
+ $data['qsos'] = $this->logbookadvanced_model->getStateListQsos($data['dxcc']);
+
+ $this->load->view('logbookadvanced/showStateQsos', $data);
+ }
+
+ public function fixMissingDxcc() {
+ if(!clubaccess_check(9)) return;
+
+ $all = $this->input->post('all', true);
+ $this->load->model('logbookadvanced_model');
+ $result = $this->logbookadvanced_model->check_missing_dxcc_id($all);
+
+ $data['result'] = $result;
+ $data['all'] = $all;
+ $data['type'] = 'dxcc';
+
+ $this->load->view('logbookadvanced/showUpdateResult', $data);
+ }
+
+ public function openMissingDxccList() {
+ if(!clubaccess_check(9)) return;
+
+ $this->load->model('logbookadvanced_model');
+
+ $data['qsos'] = $this->logbookadvanced_model->getMissingDxccQsos();
+
+ $this->load->view('logbookadvanced/showMissingDxccQsos', $data);
+ }
+
+ public function batchFix() {
+ if(!clubaccess_check(9)) return;
+
+ $type = $this->input->post('type', true);
+ $this->load->model('logbookadvanced_model');
+ $result = $this->logbookadvanced_model->batchFix($type);
+
+ $data['result'] = $result;
+ $data['type'] = $type;
+
+ $this->load->view('logbookadvanced/showUpdateResult', $data);
+ }
+
}
diff --git a/application/controllers/Update.php b/application/controllers/Update.php
index 6b51601f10..855e713fd4 100644
--- a/application/controllers/Update.php
+++ b/application/controllers/Update.php
@@ -327,17 +327,6 @@ private function fix_migrations(){
}
}
- public function check_missing_dxcc($all = false){
- $this->load->model('user_model');
- if (!$this->user_model->authorize(99)) {
- $this->session->set_flashdata('error', __("You're not allowed to do that!"));
- redirect('dashboard');
- }
-
- $this->load->model('logbook_model');
- $this->logbook_model->check_missing_dxcc_id($all);
- }
-
public function update_clublog_scp() {
$lockfilename='/tmp/.update_clublog_scp_running';
if (!file_exists($lockfilename)) {
diff --git a/application/libraries/Geojson.php b/application/libraries/Geojson.php
index 618143f422..8d3890dc25 100644
--- a/application/libraries/Geojson.php
+++ b/application/libraries/Geojson.php
@@ -22,47 +22,47 @@ class Geojson {
* Value: Array with 'name' and 'enabled' flag
*/
const SUPPORTED_STATES = [
- 1 => ['name' => 'Canada', 'enabled' => true], // 13 provinces/territories
- 6 => ['name' => 'Alaska', 'enabled' => true], // 1 state
- 27 => ['name' => 'Belarus', 'enabled' => true], // 7 subdivisions
- 29 => ['name' => 'Canary Islands', 'enabled' => true], // 2 provinces
- 32 => ['name' => 'Ceuta & Melilla', 'enabled' => true], // 2 autonomous cities
- 50 => ['name' => 'Mexico', 'enabled' => true], // 32 states
- 100 => ['name' => 'Argentina', 'enabled' => true], // 24 subdivisions
- 108 => ['name' => 'Brazil', 'enabled' => true], // 27 subdivisions
- 112 => ['name' => 'Chile', 'enabled' => true], // 16 regions
+ 1 => ['name' => 'Canada', 'enabled' => true], // 13 provinces/territories
+ 6 => ['name' => 'Alaska', 'enabled' => true], // 1 state
+ 27 => ['name' => 'Belarus', 'enabled' => true], // 7 subdivisions
+ 29 => ['name' => 'Canary Islands', 'enabled' => true], // 2 provinces
+ 32 => ['name' => 'Ceuta & Melilla', 'enabled' => true], // 2 autonomous cities
+ 50 => ['name' => 'Mexico', 'enabled' => true], // 32 states
+ 100 => ['name' => 'Argentina', 'enabled' => true], // 24 subdivisions
+ 108 => ['name' => 'Brazil', 'enabled' => true], // 27 subdivisions
+ 110 => ['name' => 'Hawaii', 'enabled' => true], // 1 state
+ 112 => ['name' => 'Chile', 'enabled' => true], // 16 regions
137 => ['name' => 'Republic of Korea', 'enabled' => true], // 17 subdivisions
- 110 => ['name' => 'Hawaii', 'enabled' => true], // 1 state
- 144 => ['name' => 'Uruguay', 'enabled' => true], // 19 subdivisions
- 148 => ['name' => 'Venezuela', 'enabled' => true], // 24 states
- 149 => ['name' => 'Azores', 'enabled' => true], // 1 autonomous region
- 150 => ['name' => 'Australia', 'enabled' => true], // 8 subdivisions
- 163 => ['name' => 'Papua New Guinea', 'enabled' => true], // 22 provinces
- 170 => ['name' => 'New Zealand', 'enabled' => true], // 16 regions
- 209 => ['name' => 'Belgium', 'enabled' => true], // 11 subdivisions
- 212 => ['name' => 'Bulgaria', 'enabled' => true], // 28 subdivisions
- 214 => ['name' => 'Corsica', 'enabled' => true], // 2 departments (2A, 2B)
- 225 => ['name' => 'Sardinia', 'enabled' => true], // 5 provinces
- 227 => ['name' => 'France', 'enabled' => true], // 96 departments
- 230 => ['name' => 'Germany', 'enabled' => true], // 16 federal states
- 239 => ['name' => 'Hungary', 'enabled' => true], // 20 subdivisions
- 245 => ['name' => 'Ireland', 'enabled' => true], // 27 subdivisions
- 248 => ['name' => 'Italy', 'enabled' => true], // 107 provinces
- 256 => ['name' => 'Madeira Islands', 'enabled' => true], // 1 autonomous region
- 263 => ['name' => 'Netherlands', 'enabled' => true], // 12 provinces
- 266 => ['name' => 'Norway', 'enabled' => true], // 11 counties
- 269 => ['name' => 'Poland', 'enabled' => true], // 16 voivodeships
- 272 => ['name' => 'Portugal', 'enabled' => true], // 18 districts
- 275 => ['name' => 'Romania', 'enabled' => true], // 42 counties
- 281 => ['name' => 'Spain', 'enabled' => true], // 47 provinces
- 284 => ['name' => 'Sweden', 'enabled' => true], // 21 subdivisions
- 287 => ['name' => 'Switzerland', 'enabled' => true], // 26 cantons
- 291 => ['name' => 'USA', 'enabled' => true], // 52 states/territories
- 318 => ['name' => 'China', 'enabled' => true], // 31 provinces
- 324 => ['name' => 'India', 'enabled' => true], // 36 states/territories
- 339 => ['name' => 'Japan', 'enabled' => true], // 47 prefectures
- 386 => ['name' => 'Taiwan', 'enabled' => true], // 22 subdivisions
- 497 => ['name' => 'Croatia', 'enabled' => true], // 21 subdivisions
+ 144 => ['name' => 'Uruguay', 'enabled' => true], // 19 subdivisions
+ 148 => ['name' => 'Venezuela', 'enabled' => true], // 24 states
+ 149 => ['name' => 'Azores', 'enabled' => true], // 1 autonomous region
+ 150 => ['name' => 'Australia', 'enabled' => true], // 8 subdivisions
+ 163 => ['name' => 'Papua New Guinea', 'enabled' => true], // 22 provinces
+ 170 => ['name' => 'New Zealand', 'enabled' => true], // 16 regions
+ 209 => ['name' => 'Belgium', 'enabled' => true], // 11 subdivisions
+ 212 => ['name' => 'Bulgaria', 'enabled' => true], // 28 subdivisions
+ 214 => ['name' => 'Corsica', 'enabled' => true], // 2 departments (2A, 2B)
+ 225 => ['name' => 'Sardinia', 'enabled' => true], // 5 provinces
+ 227 => ['name' => 'France', 'enabled' => true], // 96 departments
+ 230 => ['name' => 'Germany', 'enabled' => true], // 16 federal states
+ 239 => ['name' => 'Hungary', 'enabled' => true], // 20 subdivisions
+ 245 => ['name' => 'Ireland', 'enabled' => true], // 27 subdivisions
+ 248 => ['name' => 'Italy', 'enabled' => true], // 107 provinces
+ 256 => ['name' => 'Madeira Islands', 'enabled' => true], // 1 autonomous region
+ 263 => ['name' => 'Netherlands', 'enabled' => true], // 12 provinces
+ 266 => ['name' => 'Norway', 'enabled' => true], // 15 counties
+ 269 => ['name' => 'Poland', 'enabled' => true], // 16 voivodeships
+ 272 => ['name' => 'Portugal', 'enabled' => true], // 18 districts
+ 275 => ['name' => 'Romania', 'enabled' => true], // 42 counties
+ 281 => ['name' => 'Spain', 'enabled' => true], // 47 provinces
+ 284 => ['name' => 'Sweden', 'enabled' => true], // 21 subdivisions
+ 287 => ['name' => 'Switzerland', 'enabled' => true], // 26 cantons
+ 291 => ['name' => 'USA', 'enabled' => true], // 52 states/territories
+ 318 => ['name' => 'China', 'enabled' => true], // 31 provinces
+ 324 => ['name' => 'India', 'enabled' => true], // 36 states/territories
+ 339 => ['name' => 'Japan', 'enabled' => true], // 47 prefectures
+ 386 => ['name' => 'Taiwan', 'enabled' => true], // 22 subdivisions
+ 497 => ['name' => 'Croatia', 'enabled' => true], // 21 subdivisions
];
private $qra;
@@ -134,6 +134,15 @@ public function isStateSupported($dxcc) {
return isset(self::SUPPORTED_STATES[$dxcc]) && self::SUPPORTED_STATES[$dxcc]['enabled'] === true;
}
+ /**
+ * Retrieve list of DXCC entities that support state/province lookups
+ *
+ * @return array List of supported DXCC entities
+ */
+ public function getSupportedDxccs() {
+ return self::SUPPORTED_STATES;
+ }
+
// ============================================================================
// COORDINATE CONVERSION
// ============================================================================
diff --git a/application/models/Logbook_model.php b/application/models/Logbook_model.php
index c8547e4854..bfa3a06577 100644
--- a/application/models/Logbook_model.php
+++ b/application/models/Logbook_model.php
@@ -5996,80 +5996,6 @@ public function get_entity($dxcc) {
return '';
}
-
- public function check_missing_dxcc_id($all) {
- ini_set('memory_limit', '-1'); // This consumes a much of Memory!
- $this->db->trans_start(); // Transaction has to be started here, because otherwise we're trying to update rows which are locked by the select
- $this->db->select("COL_PRIMARY_KEY, COL_CALL, COL_TIME_ON, COL_TIME_OFF"); // get all records with no COL_DXCC
-
- if (!$all) { // check which to update - records with no dxcc or all records
- $this->db->where("COL_DXCC is NULL");
- }
-
- $r = $this->db->get($this->config->item('table_name'));
-
- $count = 0;
- if ($r->num_rows() > 0) { //query dxcc_prefixes
- $sql = "update " . $this->config->item('table_name') . " set COL_COUNTRY = ?, COL_DXCC=? where COL_PRIMARY_KEY=?";
- $q = $this->db->conn_id->prepare($sql); // PREPARE this statement. For DB this means: No parsing overhead, parse once use many (see execute query below)
- foreach ($r->result_array() as $row) {
- $qso_date = $row['COL_TIME_OFF'] == '' ? $row['COL_TIME_ON'] : $row['COL_TIME_OFF'];
- $qso_date = date("Y-m-d", strtotime($qso_date));
- $d = $this->check_dxcc_table($row['COL_CALL'], $qso_date);
- if ($d[0] != 'Not Found') {
- $q->execute(array(addslashes(ucwords(strtolower($d[1]), "- (/")), $d[0], $row['COL_PRIMARY_KEY']));
- $count++;
- }
- }
- }
- $this->db->trans_complete();
- print("$count updated\n");
- }
-
- public function check_missing_grid_id($all) {
- // get all records with no COL_GRIDSQUARE
- $this->db->select("COL_PRIMARY_KEY, COL_CALL, COL_TIME_ON, COL_TIME_OFF");
-
- $this->db->where("(COL_GRIDSQUARE is NULL or COL_GRIDSQUARE = '') AND (COL_VUCC_GRIDS is NULL or COL_VUCC_GRIDS = '')");
-
- $r = $this->db->get($this->config->item('table_name'));
-
- $count = 0;
- $this->db->trans_start();
- if ($r->num_rows() > 0) {
- foreach ($r->result_array() 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'])) {
- printf("Error: " . $callbook['error'] . "
");
- } else {
- $return['callsign_qra'] = $callbook['gridsquare'];
- if ($return['callsign_qra'] != '') {
- $sql = sprintf(
- "update %s set COL_GRIDSQUARE = '%s' where COL_PRIMARY_KEY=%d",
- $this->config->item('table_name'),
- $return['callsign_qra'],
- $row['COL_PRIMARY_KEY']
- );
- $this->db->query($sql);
- printf("Updating %s to %s\n
", $row['COL_PRIMARY_KEY'], $return['callsign_qra']);
- $count++;
- }
- }
- }
- }
- }
- $this->db->trans_complete();
-
- print("$count updated\n");
- }
-
public function check_for_station_id() {
$this->db->select('COL_PRIMARY_KEY, COL_TIME_ON, COL_CALL, COL_MODE, COL_BAND, COL_STATION_CALLSIGN');
$this->db->where('station_id =', NULL);
diff --git a/application/models/Logbookadvanced_model.php b/application/models/Logbookadvanced_model.php
index f283af0580..f5a7522d78 100644
--- a/application/models/Logbookadvanced_model.php
+++ b/application/models/Logbookadvanced_model.php
@@ -1255,21 +1255,38 @@ function getSubdivisons($dxccid) {
return $query->result();
}
- function fixCqZones($ids) {
+ function fixCqZones($ids = null) {
+ if ($ids == null) {
+ $sql = "UPDATE ".$this->config->item('table_name')." JOIN dxcc_entities ON ". $this->config->item('table_name').".col_dxcc = dxcc_entities.adif JOIN station_profile ON ". $this->config->item('table_name').".station_id = station_profile.station_id" .
+ " SET " . $this->config->item('table_name').".COL_CQZ = dxcc_entities.cqz" .
+ " WHERE station_profile.user_id = ? and (" . $this->config->item('table_name').".COL_CQZ IS NULL OR " . $this->config->item('table_name').".COL_CQZ = '')";
+
+ $query = $this->db->query($sql, array($this->session->userdata('user_id')));
+ return $this->db->affected_rows();
+ }
$sql = "UPDATE ".$this->config->item('table_name')." JOIN dxcc_entities ON ". $this->config->item('table_name').".col_dxcc = dxcc_entities.adif JOIN station_profile ON ". $this->config->item('table_name').".station_id = station_profile.station_id" .
" SET " . $this->config->item('table_name').".COL_CQZ = dxcc_entities.cqz" .
" WHERE " . $this->config->item('table_name').".col_primary_key in ? and station_profile.user_id = ?";
$query = $this->db->query($sql, array(json_decode($ids, true), $this->session->userdata('user_id')));
+ return $this->db->affected_rows();
}
- function fixItuZones($ids) {
+ function fixItuZones($ids = null) {
+ if ($ids == null) {
+ $sql = "UPDATE ".$this->config->item('table_name')." JOIN dxcc_entities ON ". $this->config->item('table_name').".col_dxcc = dxcc_entities.adif JOIN station_profile ON ". $this->config->item('table_name').".station_id = station_profile.station_id" .
+ " SET " . $this->config->item('table_name').".COL_ITUZ = dxcc_entities.ituz" .
+ " WHERE station_profile.user_id = ? and (" . $this->config->item ('table_name').".COL_ITUZ IS NULL OR " . $this->config->item('table_name').".COL_ITUZ = '')";
+ $query = $this->db->query($sql, array($this->session->userdata('user_id')));
+ return $this->db->affected_rows();
+ }
$sql = "UPDATE ".$this->config->item('table_name')." JOIN dxcc_entities ON ". $this->config->item('table_name').".col_dxcc = dxcc_entities.adif JOIN station_profile ON ". $this->config->item('table_name').".station_id = station_profile.station_id" .
" SET " . $this->config->item('table_name').".COL_ITUZ = dxcc_entities.ituz" .
" WHERE " . $this->config->item('table_name').".col_primary_key in ? and station_profile.user_id = ?";
$query = $this->db->query($sql, array(json_decode($ids, true), $this->session->userdata('user_id')));
+ return $this->db->affected_rows();
}
/**
@@ -1397,7 +1414,8 @@ public function check_missing_continent() {
JOIN dxcc_entities ON " . $this->config->item('table_name') . ".col_dxcc = dxcc_entities.adif
JOIN station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
SET col_cont = dxcc_entities.cont
- WHERE COALESCE(" . $this->config->item('table_name') . ".col_cont, '') = '' and station_profile.user_id = ?";
+ WHERE (COALESCE(" . $this->config->item('table_name') . ".col_cont, '') = '' or " . $this->config->item('table_name') . ".col_cont not in ('AF', 'AN', 'AS', 'EU', 'NA', 'OC', 'SA'))
+ and station_profile.user_id = ?";
$query = $this->db->query($sql, array($this->session->userdata('user_id')));
$result = $this->db->affected_rows();
@@ -1421,6 +1439,8 @@ public function update_distances_batch() {
$recordcount = $query->num_rows();
+ $count = 0;
+
if ($recordcount > 0) {
$this->load->library('Qra');
@@ -1433,10 +1453,14 @@ public function update_distances_batch() {
$row->COL_ANT_PATH ?? null
);
- $updates[] = [
- 'COL_PRIMARY_KEY' => $row->COL_PRIMARY_KEY,
- 'COL_DISTANCE' => $distance,
- ];
+ if ($distance != 0) {
+ $updates[] = [
+ 'COL_PRIMARY_KEY' => $row->COL_PRIMARY_KEY,
+ 'COL_DISTANCE' => $distance,
+ ];
+ $count++;
+ }
+
}
if (!empty($updates)) {
@@ -1444,6 +1468,300 @@ public function update_distances_batch() {
}
}
- return $recordcount;
+ return $count;
+ }
+
+ public function runCheckDb($type) {
+ switch ($type) {
+ case 'checkdistance':
+ return $this->check_missing_distance();
+ case 'checkcontinent':
+ return $this->check_qsos_missing_continent();
+ case 'checkdxcc':
+ return $this->check_missing_dxcc();
+ case 'checkstate':
+ return $this->check_missing_state();
+ case 'checkcqzones':
+ return $this->check_missing_cq_zones();
+ case 'checkituzones':
+ return $this->check_missing_itu_zones();
+ case 'checkgrids':
+ return $this->getMissingGridQsos();
+ return null;
+ }
+ }
+
+ public function check_missing_dxcc() {
+ $sql = "select count(*) as count from " . $this->config->item('table_name') . "
+ join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ where user_id = ? and coalesce(col_dxcc, '') = ''";
+
+ $bindings[] = [$this->session->userdata('user_id')];
+
+ $query = $this->db->query($sql, $bindings);
+ return $query->result();
+ }
+
+ public function check_qsos_missing_continent() {
+ $sql = "select count(*) as count from " . $this->config->item('table_name') . "
+ join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ where user_id = ?
+ and (coalesce(col_cont, '') = '' or col_cont not in ('AF', 'AN', 'AS', 'EU', 'NA', 'OC', 'SA'))
+ and col_dxcc is not null
+ and col_dxcc != ''
+ and col_dxcc != 0";
+
+ $bindings[] = [$this->session->userdata('user_id')];
+
+ $query = $this->db->query($sql, $bindings);
+ return $query->result();
+ }
+
+ public function check_missing_distance() {
+ $sql = "select count(*) as count from " . $this->config->item('table_name') . "
+ join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ where user_id = ?
+ AND (COL_DISTANCE = '' or COL_DISTANCE is NULL)
+ and COL_GRIDSQUARE != station_gridsquare
+ and COL_GRIDSQUARE is NOT NULL
+ and COL_GRIDSQUARE != ''";
+
+ $bindings[] = [$this->session->userdata('user_id')];
+
+ $query = $this->db->query($sql, $bindings);
+ return $query->result();
+ }
+
+ public function check_missing_state() {
+ $this->load->library('Geojson');
+ $supported_dxcc_list = $this->geojson->getSupportedDxccs();
+ $supported_dxcc_array = array_keys($supported_dxcc_list);
+
+ $sql = "select count(*) as count, col_dxcc, dxcc_entities.name as dxcc_name, dxcc_entities.prefix from " . $this->config->item('table_name') . "
+ join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ join dxcc_entities on " . $this->config->item('table_name') . ".col_dxcc = dxcc_entities.adif
+ where user_id = ? and coalesce(col_state, '') = ''
+ and col_dxcc in (" . implode(',', array_map('intval', $supported_dxcc_array)) . ")
+ and length(col_gridsquare) >= 6
+ group by col_dxcc, dxcc_entities.name, dxcc_entities.prefix
+ order by dxcc_entities.prefix";
+
+ $bindings[] = [$this->session->userdata('user_id')];
+
+ $query = $this->db->query($sql, $bindings);
+ return $query->result();
+ }
+
+ public function check_missing_cq_zones() {
+ $sql = "select count(*) as count from " . $this->config->item('table_name') . "
+ join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ join dxcc_entities on " . $this->config->item('table_name') . ".col_dxcc = dxcc_entities.adif
+ where user_id = ? and coalesce(col_cqz, '') = ''";
+
+ $bindings[] = [$this->session->userdata('user_id')];
+
+ $query = $this->db->query($sql, $bindings);
+ return $query->result();
+ }
+
+ public function check_missing_itu_zones() {
+ $sql = "select count(*) as count from " . $this->config->item('table_name') . "
+ join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ join dxcc_entities on " . $this->config->item('table_name') . ".col_dxcc = dxcc_entities.adif
+ where user_id = ? and coalesce(col_ituz, '') = ''";
+
+ $bindings[] = [$this->session->userdata('user_id')];
+
+ $query = $this->db->query($sql, $bindings);
+ return $query->result();
+ }
+
+ /**
+ * Fix state for a batch of QSOs using GeoJSON lookup
+ *
+ * @param int $dxcc DXCC entity number for which to fix states
+ * @return array Result array with success, dxcc_name, dxcc_number, state_code, skipped
+ */
+ function fixStateBatch($dxcc) {
+ $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, station_profile.station_profile_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_DXCC = ? AND station_profile.user_id = ?
+ AND (qsos.COL_STATE IS NULL OR qsos.COL_STATE = '')
+ AND LENGTH(COALESCE(qsos.COL_GRIDSQUARE, '')) >= 6";
+
+ $query = $this->db->query($sql, [$dxcc, $this->session->userdata('user_id')]);
+
+ if ($query->num_rows() === 0) {
+ return [
+ 'success' => false,
+ 'skipped' => true,
+ 'reason' => 'QSOs not found'
+ ];
+ }
+
+ $results = [];
+
+ $count = 0;
+
+ foreach ($query->result() as $qso) {
+ $result = $this->fixStateSingle($qso->COL_PRIMARY_KEY);
+ if ($result['success']) {
+ $count++;
+ } else {
+ $result['station_profile_name'] = $qso->station_profile_name;
+ $result['id'] = $qso->COL_PRIMARY_KEY;
+ $result['gridsquare'] = $qso->COL_GRIDSQUARE;
+ $results[] = $result;
+ }
+ }
+
+ $results['count'] = $count;
+
+ return $results;
+ }
+
+ 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
+ LEFT JOIN dxcc_entities d ON qsos.COL_DXCC = d.adif
+ WHERE qsos.COL_DXCC = ? AND station_profile.user_id = ?
+ AND (qsos.COL_STATE IS NULL OR qsos.COL_STATE = '')
+ AND LENGTH(COALESCE(qsos.COL_GRIDSQUARE, '')) >= 6
+ ORDER BY COL_TIME_ON DESC";
+
+ $query = $this->db->query($sql, [$dxcc, $this->session->userdata('user_id')]);
+
+ return $query->result();
+ }
+
+ /*
+ This was moved from update to the advanced logbook. Maninly because it affected all QSOs in the logbook, without filters on users or stations.
+ We need to ensure that we only update the relevant QSOs, filtered on user.
+ */
+ public function check_missing_dxcc_id($all = false) {
+ ini_set('memory_limit', '-1'); // This consumes a lot of Memory!
+ $this->db->trans_start(); // Transaction has to be started here, because otherwise we're trying to update rows which are locked by the select
+ $sql = "select COL_PRIMARY_KEY, COL_CALL, COL_TIME_ON, COL_TIME_OFF, station_profile.station_profile_name from " . $this->config->item('table_name') .
+ " join station_profile on " . $this->config->item('table_name') . ".station_id = station_profile.station_id
+ where station_profile.user_id = ?";
+
+ if ($all == 'false') { // check which to update - records with no dxcc or all records
+ $sql .= " and (COL_DXCC is NULL or COL_DXCC = '')";
+ }
+ $r = $this->db->query($sql, array($this->session->userdata('user_id')));
+ $this->load->model('logbook_model');
+
+ $count = 0;
+ if ($r->num_rows() > 0) { //query dxcc_prefixes
+ $sql = "update " . $this->config->item('table_name') . " set COL_COUNTRY = ?, COL_DXCC = ? where COL_PRIMARY_KEY = ?";
+ $q = $this->db->conn_id->prepare($sql); // PREPARE this statement. For DB this means: No parsing overhead, parse once use many (see execute query below)
+ foreach ($r->result_array() as $row) {
+ $qso_date = $row['COL_TIME_OFF'] == '' ? $row['COL_TIME_ON'] : $row['COL_TIME_OFF'];
+ $qso_date = date("Y-m-d", strtotime($qso_date));
+ $d = $this->logbook_model->check_dxcc_table($row['COL_CALL'], $qso_date);
+ if ($d[0] == 'Not Found') {
+ $result[] = [
+ 'id' => $row['COL_PRIMARY_KEY'],
+ 'callsign' => $row['COL_CALL'],
+ 'reason' => 'DXCC Not Found',
+ 'location' => $row['station_profile_name'],
+ 'id' => $row['COL_PRIMARY_KEY']
+ ];
+ } else {
+ $q->execute(array(addslashes(ucwords(strtolower($d[1]), "- (/")), $d[0], $row['COL_PRIMARY_KEY']));
+ $count++;
+ }
+ }
+ }
+ $this->db->trans_complete();
+ $result['count'] = $count;
+
+ return $result;
+ }
+
+ function getMissingDxccQsos() {
+ $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
+ LEFT JOIN dxcc_entities d ON qsos.COL_DXCC = d.adif
+ WHERE station_profile.user_id = ?
+ AND (qsos.COL_DXCC IS NULL OR qsos.COL_DXCC = '')
+ ORDER BY COL_TIME_ON DESC";
+
+ $query = $this->db->query($sql, [$this->session->userdata('user_id')]);
+
+ return $query->result();
+ }
+
+ function batchFix($type) {
+ switch ($type) {
+ case 'dxcc':
+ return $this->check_missing_dxcc_id('true');
+ case 'distance':
+ return $this->update_distances_batch();
+ case 'continent':
+ return $this->check_missing_continent();
+ case 'cqzones':
+ return $this->fixCqZones();
+ case 'ituzones':
+ return $this->fixItuZones();
+ case 'grids':
+ return $this->check_missing_grid();
+ default:
+ return null;
+ }
+ }
+
+ /*
+ Another function moved from update to the advanced logbook, to be used in the dbtools section.
+ It did not have filter on user or location.
+ */
+ public function check_missing_grid() {
+ $result = $this->getMissingGridQsos();
+
+ $count = 0;
+ $this->db->trans_start();
+ if (count($result) > 0) {
+ 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++;
+ }
+ }
+ }
+ }
+ }
+ $this->db->trans_complete();
+
+ return $count;
+ }
+
+ public function getMissingGridQsos() {
+ $sql = "SELECT col_primary_key, col_call, col_time_on, col_mode, col_submode, col_band, col_state, col_gridsquare, station_profile.station_profile_name FROM " . $this->config->item('table_name') . " qsos
+ JOIN station_profile ON qsos.station_id = station_profile.station_id
+ 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";
+
+ $query = $this->db->query($sql, [$this->session->userdata('user_id')]);
+
+ return $query->result();
}
}
diff --git a/application/views/logbookadvanced/checkresult.php b/application/views/logbookadvanced/checkresult.php
new file mode 100644
index 0000000000..12bbc8364e
--- /dev/null
+++ b/application/views/logbookadvanced/checkresult.php
@@ -0,0 +1,91 @@
+
+
= __("Update missing CQ zone information") ?>
+= __("Update missing ITU zone information") ?>
+= __("Update missing or incorrect continent information") ?>
+= __("Update missing state/province information") ?>
+= __("Calculate and update distance information for QSOs") ?>
+= __("Identify QSOs that are missing DXCC information") ?>
+= __("Use Wavelog to determine DXCC for all QSOs.") ?>
+= __("This will overwrite ALL existing DXCC information!") ?>
+= __("Use callbook lookup to set gridsquare") ?>
+= __("This is limited to 100 callsigns for each run!") ?>
++ +
+| = __("Call") ?> | += __("Date/Time") ?> | += __("Mode") ?> | += __("Band") ?> | += __("State") ?> | += __("Gridsquare") ?> | += __("DXCC") ?> | += __("Station") ?> | +
|---|---|---|---|---|---|---|---|
| col_primary_key . ')">' . htmlspecialchars($qso->col_call) . ''; ?> | +col_time_on)); ?> | +col_mode; ?> | +col_band; ?> | +col_state; ?> | +col_gridsquare; ?> | +dxcc_name; ?> | +station_profile_name; ?> | +
+ +
+| = __("Call") ?> | += __("Date/Time") ?> | += __("Mode") ?> | += __("Band") ?> | += __("State") ?> | += __("Gridsquare") ?> | += __("DXCC") ?> | += __("Station") ?> | +
|---|---|---|---|---|---|---|---|
| col_primary_key . ')">' . htmlspecialchars($qso->col_call) . ''; ?> | +col_time_on)); ?> | +col_mode; ?> | +col_band; ?> | +col_state; ?> | +col_gridsquare; ?> | +dxcc_name), "- (/"), ENT_QUOTES, 'UTF-8'); ?> | +station_profile_name; ?> | +
= __("QSOs with missing state and gridsquares with 6 or more characters found for the following DXCC's:"); ?>
+ +| = __("Prefix"); ?> | += __("DXCC"); ?> | += __("QSOs"); ?> | += __("Action"); ?> | +
|---|---|---|---|
| prefix; ?> | ++ | + | + + + | +
= __("No QSOs were found where state information can be fixed."); ?>
+
- = __("After updating, Wavelog can fill in missing callsign information in the logbook using the newly-obtained DXCC data.
- You can choose to check just the QSOs in the logbook that are missing DXCC metadata or to re-check the entire logbook
- and update existing metadata as well, in case it has changed."); ?>
-
= __("WARNING"); ?>: = __("This affects ALL QSOs of ANY user on this instance. The function is deprectated and will be removed in a future version of Wavelog. As replacement use the Logbook-Advanced!"); ?>
-