diff --git a/application/controllers/Workabledxcc.php b/application/controllers/Workabledxcc.php
index 76964818..fda5adb8 100644
--- a/application/controllers/Workabledxcc.php
+++ b/application/controllers/Workabledxcc.php
@@ -58,6 +58,19 @@ class Workabledxcc extends CI_Controller
$uniqueEntities = array_unique(array_filter($dxccEntities));
$dxccStatus = $this->Workabledxcc_model->batchDxccWorkedStatus($uniqueEntities);
+ // If JSON contains iota fields, batch process IOTA status
+ $iotas = [];
+ foreach ($dataResult as $item) {
+ if (!empty($item['iota'])) {
+ $iotas[] = $item['iota'];
+ }
+ }
+ $uniqueIotas = array_unique($iotas);
+ $iotaStatus = [];
+ if (!empty($uniqueIotas)) {
+ $iotaStatus = $this->Workabledxcc_model->batchIotaWorkedStatus($uniqueIotas);
+ }
+
// Process results
$requiredData = array();
foreach ($dataResult as $index => $item) {
@@ -80,6 +93,8 @@ class Workabledxcc extends CI_Controller
'start_date' => $StartDate,
'end_date' => $EndDate,
'country' => $item['2'],
+ 'iota' => isset($item['iota']) ? $item['iota'] : null,
+ 'iota_status' => (isset($item['iota']) && isset($iotaStatus[$item['iota']])) ? $iotaStatus[$item['iota']] : null,
'notes' => $item['6'],
'callsign' => $item['callsign'],
'workedBefore' => $worked['workedBefore'],
diff --git a/application/models/Workabledxcc_model.php b/application/models/Workabledxcc_model.php
index 55f765e5..a09e54c3 100644
--- a/application/models/Workabledxcc_model.php
+++ b/application/models/Workabledxcc_model.php
@@ -88,6 +88,100 @@ class Workabledxcc_model extends CI_Model
return $results;
}
+ /**
+ * Batch check IOTA worked/confirmed status
+ * @param array $iotas Array of unique IOTA tags
+ * @return array Array indexed by IOTA tag with ['worked'=>bool,'confirmed'=>bool]
+ */
+ public function batchIotaWorkedStatus($iotas)
+ {
+ if (empty($iotas)) {
+ return array();
+ }
+
+ $user_default_confirmation = $this->session->userdata('user_default_confirmation');
+ $this->load->model('logbooks_model');
+ $logbooks_locations_array = $this->logbooks_model->list_logbook_relationships($this->session->userdata('active_station_logbook'));
+
+ if (empty($logbooks_locations_array)) {
+ $out = [];
+ foreach ($iotas as $i) {
+ $out[$i] = ['worked' => false, 'confirmed' => false];
+ }
+ return $out;
+ }
+
+ // Build confirmation criteria once
+ $confirmationCriteria = $this->buildConfirmationCriteria($user_default_confirmation);
+
+ // Build case-insensitive WHERE conditions for COL_IOTA
+ $whereConditions = array();
+ foreach ($iotas as $iota) {
+ $whereConditions[] = "UPPER(COL_IOTA) = UPPER('" . $this->db->escape_str($iota) . "')";
+ }
+
+ if (empty($whereConditions)) {
+ return array();
+ }
+
+ $whereClause = '(' . implode(' OR ', $whereConditions) . ')';
+
+ // Worked query (any mode)
+ $this->db->select('COL_IOTA')
+ ->distinct()
+ ->from($this->config->item('table_name'))
+ ->where_in('station_id', $logbooks_locations_array)
+ ->where($whereClause);
+
+ $workedQuery = $this->db->get();
+ log_message('debug', 'Workable DXCC IOTA worked query: ' . $this->db->last_query());
+
+ $workedResults = array();
+ foreach ($workedQuery->result() as $row) {
+ foreach ($iotas as $iota) {
+ if (strtoupper($row->COL_IOTA) === strtoupper($iota)) {
+ $workedResults[$iota] = true;
+ break;
+ }
+ }
+ }
+
+ // Confirmed query (apply confirmation criteria, exclude satellite confirmations if desired)
+ $confirmedResults = array();
+ if ($confirmationCriteria !== '1=0') {
+ $this->db->select('COL_IOTA')
+ ->distinct()
+ ->from($this->config->item('table_name'))
+ ->where($confirmationCriteria)
+ ->where_in('station_id', $logbooks_locations_array)
+ ->where($whereClause);
+
+ $confirmedQuery = $this->db->get();
+ foreach ($confirmedQuery->result() as $row) {
+ foreach ($iotas as $iota) {
+ if (strtoupper($row->COL_IOTA) === strtoupper($iota)) {
+ $confirmedResults[$iota] = true;
+ break;
+ }
+ }
+ }
+ }
+
+ $out = array();
+ foreach ($iotas as $iota) {
+ $out[$iota] = [
+ 'worked' => isset($workedResults[$iota]),
+ 'confirmed' => isset($confirmedResults[$iota])
+ ];
+ }
+
+ // Debug
+ log_message('debug', 'Workable DXCC: IOTA worked results: ' . json_encode($workedResults));
+ log_message('debug', 'Workable DXCC: IOTA confirmed results: ' . json_encode($confirmedResults));
+
+ return $out;
+ }
+
/**
* Batch query to check which entities have been worked via satellite
*/
diff --git a/application/views/workabledxcc/components/dxcclist.php b/application/views/workabledxcc/components/dxcclist.php
index 83e0a4d1..5eda33d2 100644
--- a/application/views/workabledxcc/components/dxcclist.php
+++ b/application/views/workabledxcc/components/dxcclist.php
@@ -51,7 +51,32 @@ foreach ($grouped as $month => $dxccs) {
// Add satellite badge if worked via satellite
if (isset($dxcc['workedViaSatellite']) && $dxcc['workedViaSatellite']) {
- echo 'Worked via Satellite';
+ echo ' Worked via Satellite';
+ }
+
+ // IOTA handling: show badge if JSON contained an iota field
+ if (isset($dxcc['iota']) && !empty($dxcc['iota'])) {
+ $iotaTag = $dxcc['iota'];
+ $mapUrl = 'https://www.iota-world.org/iotamaps/?grpref=' . $iotaTag;
+ // Anchor inside badge should inherit readable text colour
+ $iotaAnchor = '' . $iotaTag . '';
+
+ if (isset($dxcc['iota_status'])) {
+ $s = $dxcc['iota_status'];
+
+ if (!empty($s) && isset($s['worked']) && $s['worked']) {
+ echo ' IOTA ' . $iotaAnchor . ' Worked';
+ } else {
+ echo ' IOTA ' . $iotaAnchor . ' Needed';
+ }
+
+ if (!empty($s) && isset($s['confirmed']) && $s['confirmed']) {
+ echo ' Confirmed';
+ }
+ } else {
+ // No status; render a neutral badge containing the link
+ echo ' ' . $iotaAnchor . '';
+ }
}
echo '