Commit graph

1742 commits

Author SHA1 Message Date
Peter Goodhall
9913eb08a2 Improve callsign lookup, caching & recent details
Add a cached DXCC lookup and a jsondxcc endpoint to speed up country resolution and reduce DB load (file-cache with 1h TTL). Introduce cached_dxcc_lookup(), build_confirmation_where(), and callsign_status() in the Logbook controller; refactor confirmed_grid_before() and worked_grid_before() to accept logbook relationships and confirmation prefs to avoid redundant queries. Use a new Logbook_model::get_recent_callsign_details() to populate recent name/gridsquare/qth/iota/qsl/state/county values in a single query. Update JS to better manage lookup state, invalidate in-flight requests, and perform a debounced quick DXCC lookup to improve UX. Tweak previous-contacts pagination to a compact sliding window and remove a redundant UI note.
2026-04-13 13:57:03 +01:00
Peter Goodhall
6e8d73e07b Recalculate highlight DX using grid/DXCC
Add helper methods to determine a QSO's primary grid, lookup DXCC coordinates (with caching and logbook_model.dxcc_lookup fallback), and resolve candidate distances by preferring grid-to-grid QRA distance with a DXCC-coordinate fallback. Update highlight DX queries to select time, DXCC and DXCC lat/long and join dxcc_entities. Replace duplicated inline distance logic with a single build_highlight_dx_from_candidates routine that picks the farthest candidate and sets COL_DISTANCE (rounded to int). This centralizes distance computation and ensures QSOs without stored distances but with grids or DXCC data are correctly considered.
2026-04-10 11:36:40 +01:00
Peter Goodhall
e197a5c1f2 Add toggle for QSL Cards menu item
Introduce a user-controllable option to show/hide the "View QSL Cards" link in the Logbook menu. Controller: initialize menu_show_qsl_cards, load/save the 'show_qsl_cards' menu option and sync it to the session during profile updates. Model: fetch the 'show_qsl_cards' option and expose user_show_qsl_cards in the user data. Views: add a checkbox in the user edit form to control the setting, remove the duplicate SSTV storage card UI, and update the header to robustly read the session value and conditionally render the QSL menu item. Defaults to showing the menu item when the option is unset.
2026-04-08 22:26:05 +01:00
Peter Goodhall
297ff0af42 Add SSTV menu toggle for users
Introduce a user preference to show or hide the "View SSTV Images" menu item. Controller: initialize menu_show_sstv_images, load/save the 'menu:show_sstv_images' option and set session user_show_sstv_images when profile is saved. Model: fetches the menu option and exposes user_show_sstv_images (and has_eqsl_credentials) in the returned user data. Views: add a checkbox to the user edit form to toggle the setting, and conditionally render the eQSL/SSTV menu items in the header based on session flags. This lets users control visibility of the SSTV menu entry from their profile.
2026-04-08 22:18:02 +01:00
Peter Goodhall
e904595a9d Lazy-load QSO lists; add time index migration
Bump migration version to 265 and add a migration (265_add_station_time_on_index) that creates idx_station_time_on on (station_id, COL_TIME_ON) for faster time-based queries. Introduce lazy QSO loading: controller now sets defer_qso_list and uses a new POST endpoint get_filtered_qsos to fetch filtered QSO lists and summaries; also updated cache keys/render version and added per-entry cache deletion. Note model: add include_qso_list flag, memoize QSO summaries/lists and station IDs, replace DATE(COL_TIME_ON) filters with half-open datetime ranges (start inclusive, end exclusive) via helper methods to improve index use and performance. View: update public_index to render QSO list containers with data attributes, add JS to fetch and render QSO rows on demand, and support highlight DX updates. Overall changes optimize QSO queries and enable deferred loading to reduce initial page load and DB cost.
2026-04-06 11:11:03 +01:00
Peter Goodhall
aaf3aa85a6 Add API endpoint for accessible public slugs
Introduce API method logbook_public_slugs_accessible($key) that authorizes the API key, updates last-used timestamp, and returns JSON of all station logbooks (owned or shared) that have non-empty public slugs for the key owner. Add Logbooks_model::public_slugs_accessible_by_user($user_id) to select matching logbooks, label access_level as "owner" for owners or the stored permission_level for shared entries, and order results by logbook_name. Endpoint returns 401 for missing/invalid keys and a success payload with status, count, and logbooks on success.
2026-04-03 22:35:25 +01:00
Peter Goodhall
78209d497b Add API endpoint for logbook public slugs
Introduce GET /api/logbook_public_slugs/{key} in the API controller to return a JSON list of the API key owner's station logbooks that have non-empty public slugs. The endpoint authorizes the key, updates last-used timestamp, responds with 401 for missing/invalid keys or 200 with status, count and logbook entries. Add Logbooks_model::public_slugs_by_user to query station_logbooks for non-null/non-empty public_slug values ordered by logbook_name.
2026-04-03 22:00:35 +01:00
Peter Goodhall
b6a1eb830c Add embeddable on-air widget
Introduce an embeddable "on air" status widget. Adds Widgets::on_air controller action to lookup a user by callsign, sanitize input, and render a new widgets/on_air view (iframe-friendly). Adds Cat::recent_status_by_user_id to fetch recent CAT entries (last 15 minutes) for public display. View shows ON AIR/ QRT badges, radio/satellite details, and includes auto-refresh and minimal styling; usage: /widgets/on_air/YOURCALL.
2026-03-29 14:24:26 +01:00
Peter Goodhall
9bbc58d805 Use COL_VUCC_GRIDS as fallback for grids
Prefer COL_GRIDSQUARE when present and fall back to COL_VUCC_GRIDS when building grid information. Added COL_VUCC_GRIDS to select lists in Note model queries and updated Logbook_model to set plot HTML to VUCC grids if gridsquare is missing. Also updated the public station diary view to display VUCC grids in the table when COL_GRIDSQUARE is empty. Files changed: Logbook_model.php, Note.php, public_index.php.
2026-03-29 14:12:25 +01:00
Peter Goodhall
0b272dc1c8 Improve highlight DX selection using gridsquares
Expand highlight DX query to include QSOs with gridsquares/VUCC when stored distance is missing. Join station_profile to access station_gridsquare, select up to 50 candidate QSOs, prefer stored COL_DISTANCE but compute distances via the Qra library when needed, and pick the farthest candidate (rounded to int). Apply the same logic for daily and date-range queries and preserve the satellite-only filter. Replaces the previous strict COL_DISTANCE>0 single-row lookup to avoid excluding valid DXs derivable from grids.
2026-03-29 14:09:31 +01:00
Peter Goodhall
cee6cd2def Refactor DXCC checks; add CW RBN lock UI
Replace inline DB queries in Dxcluster with a new Logbook_model::check_if_dxcc_worked_in_logbook method to centralize DXCC existence checks (per-band and overall). Remove several debug log statements from Dxcluster. Add client-side logic in dxcluster and qso views to enforce a CW↔RBN rule: when mode is 'cw' the "hide RBN" option is forced off and the checkbox is disabled (and restored when leaving CW), and apply that lock on load and mode changes. Also disable track-band when the user manually changes band in the QSO cluster UI.
2026-03-29 13:37:16 +01:00
Peter Goodhall
4c1dd7a42d Add Cabrillo export modal & format improvements
Add a full Cabrillo export workflow and harden Cabrillo/QSO formatting. Introduces a modal UI to export contest logs (new button + modal form with fields for location, category time, operators, club, soapbox, date range and other Cabrillo categories). Controller updates pass the new fields to the export action. Cabrilloformat library extended to accept and emit LOCATION and CATEGORY-TIME, improve header field ordering and presence checks, map ADIF modes to the five Cabrillo modes (CW/PH/FM/RY/DG), fix a band label (2.4G -> 2.3G), and emit placeholders for missing received exchanges to preserve column alignment. Contesting_model: more robust date parsing with UTC fallback, ensure session QSO marker only persists when timestamp valid, and build start timestamp when LIVE mode omits start_date/start_time. Frontend JS: setSession() now returns the ajax promise so callers can await it; several callers updated to await setSession and re-fetch session data before refreshing the QSO table; restore full table search on callsign blur and when suggestions are cleared. Misc: small form/input fixes (club field type, default overlay option) and additional server-supplied data loaded into the contesting view (active station id, contest session, station profile). These changes add required Cabrillo fields for certain contests and make exports and session handling more reliable.
2026-03-27 00:04:21 +00:00
Peter Goodhall
d847e4819e Add pagination and DXCC tab to previous QSOs
Implement server-side pagination for previous contacts and add a DXCC Summary tab. Controller Qso now uses last_custom_paginated and exposes total_rows/total_pages/current_page/limit. Logbook_model gained last_custom_paginated and last_custom_count to support paged queries. The previous_contacts view was updated with HTMX pagination controls and wrapping for a scrollable table; qso/index was refactored to a tabbed UI (Previous Contacts / DXCC Summary). Lookup result display was improved: responsive table, sticky header, consolidation of LSB/USB into SSB and filtering out empty modes. JS and CSS updates load DXCC HTML into the new tab, hide legacy dxccsummary elements, and add form reset / Escape handling to return focus to the previous contacts tab.
2026-03-26 22:26:47 +00:00
Peter Goodhall
36757e3e34 Add option to count satellite QSOs in DXPeditions
Introduce a user preference to treat satellite QSOs as "worked" for DXPedition status and wire it through the UI, controller, and model. Changes: add dashboard_dxpedition_sat_worked default and POST handling in User controller, add checkbox to user settings view to toggle the option, update Workabledxcc_model to optionally include satellite results when computing workedBefore via a new shouldIncludeSatelliteWorked() helper, and tweak upcoming_dxccs view styling and row classes to visually indicate worked vs needed DXPeditions. This makes DXPedition cards respect users' preference for counting satellite contacts.
2026-03-26 15:00:56 +00:00
Peter Goodhall
10ce6d1b7d Use 'Unknown' for placeholder callsigns
Replace dash placeholder with the string "Unknown" for DXpedition callsign display. The Workabledxcc_model::normalize method now returns "Unknown" for empty or placeholder patterns (e.g. F/H, M/S). The upcoming_dxccs view was updated to default to and check for "Unknown" when rendering callsigns and tooltips so the UI shows a clearer, consistent placeholder.
2026-03-26 14:44:23 +00:00
Peter Goodhall
ec5b90017f Normalize DXped callsigns, add paginated UI
Add normalizeDxpedCallsign() to Workabledxcc_model and use it in the controller and model to standardize/replace placeholder callsigns (e.g. F/H, M/S) with '-'. Improve week filtering and date handling: set explicit times for start/end of week and records, use overlap logic to include DXpeditions that intersect the week, and compute daysLeft with proper past/last-day labeling. Revamp upcoming_dxccs view: implement client-side pagination, page size, prev/next controls, escaped tooltips, and graceful display for placeholder callsigns; add a link to the full list. These changes improve display consistency and UI usability.
2026-03-26 14:36:29 +00:00
Peter Goodhall
6e43503116 Enforce unique callsigns and protect last admin
Add callsign uniqueness checks and prevent demotion of the last admin. Introduces ECALLSIGNEXISTS and ELASTADMIN constants, new model methods (exists_by_callsign, count_admin_users, would_remove_last_admin) and integrates checks into add/update flows to return appropriate error codes. Update User controller to add validation callbacks (check_unique_callsign, check_last_admin_role) and wire errors into multiple user actions. Update signup/edit views to display callsign and usertype validation feedback using Bootstrap invalid-feedback and improve alert layout.
2026-03-26 14:22:02 +00:00
Peter Goodhall
294044ac28 Support compound callsign matching and base extraction
Handle compound callsigns (e.g. F/MM9SQL/P) when looking up call history and database records. Added extract_base_callsign() to normalize and extract the longest segment of a slash-separated callsign, updated controller lookup to fall back to the base callsign and to skip empty rows, and tightened matching logic to accept either the full input or its base call. Updated model WHERE clause to match normalized COL_CALL against exact, first, middle, or last slash-separated segments (with Ø→0 normalization) to ensure compound variants are found.
2026-03-26 13:07:25 +00:00
Peter Goodhall
fbe95feaab Show selected count and correct applied count
Include the number of selected QSOs in the flash notice and update feedback to show both selected and actually updated counts. Also fix the model logic to only increment the applied counter when DB affected_rows() > 0 (previously >= 0), preventing non-updates from being counted.
2026-03-24 23:38:45 +00:00
Peter Goodhall
9f324f3435 Add start date filter to callhistory
Add an optional start_date filter to the callhistory preview workflow. Controller: validate YYYY-MM-DD input, set flash notice and redirect on invalid format, pass the start_date to the model and include it in view data. Model: accept a start_date parameter and apply a COL_TIME_ON >= start_date 00:00:00 WHERE clause when provided. View: add a date input to the form and display the selected start date in the no-matches message to indicate the time scope.
2026-03-24 23:31:56 +00:00
Peter Goodhall
ed0578cd18 Add scan preview/apply for call history
Adds a workflow to scan uploaded call history files for matching QSOs and apply SIG/SIG_INFO backfills. Controller Callhistory: loads logbooks, adds scan_preview and scan_apply actions, CSV parsing helpers, and safety checks to ensure files are readable and station ownership matches. Model Callhistory_model: adds get_station_ids_for_logbook, get_qsos_for_callsigns, and apply_sig_backfill to fetch candidate QSOs within a user's station/logbook scope and apply updates in a DB transaction. View callhistory/index.php: introduces a preview UI with selection controls, logbook scope selector, and client-side JS to manage selections and submission. Changes include normalization/heuristics for extracting callsigns/exchanges and only propose updates where existing SIG fields are blank.
2026-03-24 23:22:21 +00:00
Peter Goodhall
894d9af38f Add Call History upload and lookup feature
Introduce a new Call History feature: adds Callhistory controller, Callhistory_model, migration (create callhistory_files table) and view for uploading/managing call history files. Implements CSV/TXT upload handling, storage per-user, activation/priority controls, checksum, and server-side lookup that scans active files for matching callsigns. Integrates UI: header menu link, contesting and QSO views show call history results inline, and JavaScript to perform lookups and render results with copy-to-SIG functionality. Also updates .gitignore to exclude uploaded callhistory directory and bumps migration_version to 261.
2026-03-24 22:36:54 +00:00
Peter Goodhall
c3a5410805 Normalize county/state fields and use in queries
Normalize COL_CNTY/COL_STATE handling and use normalized expressions in queries to ensure consistent grouping/filtering and avoid mismatches.

- application/models/Counties.php: add normalized SQL expressions (trim/case/substring) and apply them to counting, grouping and ordering queries; filter out empty normalized states and adjust joins to compare normalized values.
- application/models/Logbook_model.php: normalize incoming $county/$state, add dxcc_entities join and selects, and use normalized WHERE clauses (case/trim and substring for 'ST, County' formats); also standardize band filter to COL_BAND != 'SAT'.
- application/views/view_log/partial/log_ajax.php: avoid undefined property notices by checking for name/end on the row object and use those values for Country and Flag display.

These changes address inconsistent imported county/state formats (e.g. "ST, County"), whitespace/case variations, and prevent PHP notices while keeping query semantics intact.
2026-03-24 16:04:23 +00:00
Peter Goodhall
14af3fda19 Support multiple POTA refs, DB + UI
Add support for comma-separated POTA references across the app: bump migration version to 259 and add migration 260 to expand COL_MY_POTA_REF and station_pota to VARCHAR(255). Introduce Pota::split_refs and collect_refs_from_rows to normalize and aggregate multiple refs; refactor Pota counts to compute unique refs per band/mode. Normalize station_pota when saving in Stations and Logbook_model (uses normalize_pota_refs), and adjust POTA search to match refs inside comma-separated values. Update views to render multiple POTA links and hashtags, and add Selectize-based autocomplete for station POTA input on create/edit forms. Also minor change to user_owns_station query (removed user_id where clause).
2026-03-24 14:32:17 +00:00
Peter Goodhall
2537f66d8f Support multi POTA refs in QSO entry and ADIF export 2026-03-24 14:20:17 +00:00
Peter Goodhall
66900a9f86 Add MY_NAME to ADIF exports from user profile (#3391) 2026-03-23 22:43:44 +00:00
Peter Goodhall
44f15d5f55 Use primary key for eQSL batch updates
Refactor eQSL batch update to operate on resolved primary keys instead of re-matching QSOs by time/callsign/band/mode. Eqslmethods_model now queries current eQSL status by COL_PRIMARY_KEY, builds update batches keyed by primary key, and returns updated_ids and duplicate_ids. This avoids re-querying with un-normalized ADIF modes, improves reliability (avoids CI3 affected_rows() pitfalls), and makes duplicate detection deterministic. EqslImporter was updated to enqueue qso_id for batch updates and to mark QSOs as Updated or Already received based on the returned ID lists.
2026-03-18 15:29:10 +00:00
Peter Goodhall
5747413a46 AMSAT-Status - Sat name changes
AMSAT has decided to change value names so this fixes it
2026-03-11 11:37:41 +00:00
Peter Goodhall
e430b6a306 Handle date-only created_at inputs
Enhance created_at parsing to accept date-only inputs (YYYY-MM-DD). If only a date is provided, append a time part: reuse the existing note's time if available and valid, otherwise use the current time. For other input formats, attempt to parse with strtotime and normalize to Y-m-d H:i:s. All stored values are xss_clean()-sanitized and invalid/unparsable inputs are ignored.
2026-03-10 13:09:13 +00:00
Peter Goodhall
7ba915e29c Add public QSO map to station diary
Add interactive QSO map support for public station diary entries. Controller: add stationdiary::get_qso_map_data() to return JSON map data for a given entry/date range/logbook with station location. Models: Note::get_public_entry_user_id() to resolve the entry owner; Logbook_model: get_qsos_for_public_map() to query QSOs for the map, set a default stn_loc fallback, and skip markers with invalid 0,0 coordinates. View: public_index.php includes Leaflet CSS/JS, a Show/Hide QSO Map toggle, map container per entry, client-side map initialization and marker/popups loaded via POST to the new endpoint. These changes ensure public diary entries can display QSO locations and the station marker while avoiding bogus markers and limiting results to the correct user/logbook context.
2026-03-09 13:50:34 +00:00
Peter Goodhall
a4d284a0c0 Add reactions to station diary entries
Introduce a reactions feature for public station diary entries. Adds a migration to create station_diary_reactions with indexes and a unique (diary_id, visitor_hash) constraint; bumps migration version to 257 and registers a new route for /entry/:id/react. Controller: implements visitor token/hash creation, a react() endpoint to accept POSTed reactions (like, love, fire), increments/updates reactions, invalidates cache and returns totals and visitor reaction. Model: new methods to get totals, fetch visitor reaction and save/update reactions. View: UI, styles and client-side JS for reaction buttons, counts, and copy/share enhancements; integrates totals and visitor state into the single-entry view.
2026-03-09 13:29:14 +00:00
Peter Goodhall
bef2981945 Allow 1-based image position in shortcodes
Add a fallback in Note::process_image_shortcodes to treat numeric identifiers as 1-based positions into the $images array when no image was found by earlier lookups. Validates the position is within range and converts it to zero-based indexing, enabling shortcodes like [image:1] to reference the first image.
2026-03-09 13:11:02 +00:00
Peter Goodhall
da4c4201ca Support public QSO datetime format & sharing
Add handling for public QSO datetime formatting and single-entry sharing. Introduce get_public_qso_datetime_format() in Stationdiary controller (defaults and appends time if missing) and pass qso_datetime_format, is_single_entry and current_entry_permalink to the public view. Update Note model to select and return user_date_format from auth table so user preferences flow through. Update public_index view to use the public QSO datetime format for QSO rows and add social share buttons (Facebook, X, Bluesky) when viewing a single entry.
2026-03-09 11:00:21 +00:00
Peter Goodhall
0b07e5ac18 Add public diary entry view and routing
Add support for viewing individual public Station Diary entries. Adds a new route for /station-diary/:callsign/entry/:id, a Stationdiary::entry controller method with caching (per-call sign + entry + cache version, 86400s TTL), and a Note model method get_public_station_diary_entry() that loads images and optional QSO summaries/lists. Update public_index view to link entry titles to their permalink and include entry IDs in article IDs, and update RSS feed to use the entry permalink/guid. Also include small CSS tweaks for entry title links.
2026-03-09 10:57:38 +00:00
Peter Goodhall
6e4575d5c4 Include satellite fields in note queries
Update Note model SELECT lists to include COL_PROP_MODE, COL_SAT_NAME and COL_SAT_MODE so propagation and satellite metadata are returned for single-day and date-range queries in application/models/Note.php.
2026-03-08 17:53:18 +00:00
Peter Goodhall
07c3527cb6 Render diary images & improve diary cache
Load and render station diary images inline and separately, and make cache handling more robust. Notes controller: load diary_images for print view and invalidate public diary cache when an image caption is updated. Stationdiary controller: include a render-version token in the public diary cache key to force re-renders when markup changes. Note model: make touch_public_diary_cache_version more resilient (unique value, fallback to file_put_contents and cache clean), add invalidate_public_diary_cache_for_note helper, and enhance process_image_shortcodes to handle encoded brackets, tolerant shortcode spacing, modifiers (alignment and size) with deterministic styling, and return used image ids. Views: update station_diary_print and note view to process shortcodes, remove empty paragraph artifacts, show inline images via shortcodes, and display remaining images with captions and improved print CSS.
2026-03-08 15:11:33 +00:00
Peter Goodhall
a6e3c62fd1 Support multiple image shortcode modifiers
Extend image shortcode parsing to accept multiple colon-separated modifiers (e.g. [image:ID:left:small]). Updated the regex to capture optional modifier strings and renamed the variable to $modifierString. Modifiers are split and processed so alignment (left/right/center) and size (small/medium/large) can be applied together; alignment sets wrapper classes and a default max-width only if not already set, while size modifiers set explicit max-widths. Minor refactor preserves existing behavior and tracks used image IDs.
2026-03-08 14:54:33 +00:00
Peter Goodhall
f8dffa8776 Add image shortcodes and caption editing
Support inline diary images via shortcodes and improve notes UI. Introduces a Note::process_image_shortcodes() method (ID/caption lookup and modifiers like left/right/center/small/medium/large), and updates station diary rendering to process shortcodes and avoid duplicate image output. Adds an AJAX endpoint notes/update_image_caption with ownership checks to save image captions, plus client-side JS to edit/save captions from the note edit view. Refactors notes add/edit views: reorganized form into sections/accordion, Quill editor min-height, image upload tips, improved buttons and layout, and QSO summary layout tweaks.
2026-03-08 14:36:56 +00:00
Peter Goodhall
50c24aede1 Add public station diary & QSO filters
Introduce Public Station Diary feature and QSO filtering support.

- Add migrations: 255 adds public_station_diary_enabled option (default enabled), 256 adds qso_date_start, qso_date_end, qso_satellite_only columns to notes.
- Bump migration version to 256.
- Add controller actions (Options::public_diary, public_diary_save) and new options view to manage the public diary setting; add sidebar link.
- Extend Note model to persist QSO filter fields and provide new methods to fetch QSO lists/summaries for date ranges and satellite-only filtering; wire filter usage into summary generation.
- Update notes add/edit views to include QSO Summary Filters (date range + satellite-only).
- Add translations for the new options keys across multiple language files.
- Update public station diary listing view styling/path and minor content cleanup; other views updated to support feature.
- Remove obsolete cache files (.htaccess, index.html).

These changes enable admins to toggle a public station diary and let note authors control which QSOs are included in summaries via date ranges and SAT-only filtering.
2026-03-08 13:34:31 +00:00
Peter Goodhall
dbed529f5d Require logbook for QSO summary; fix band ordering
Add numeric band sorting in Note model and make logbook selection required when including a QSO summary. Note model: select COL_BAND+0 as band_num and order by band_num to ensure proper numeric ordering. Views (notes/add, notes/edit, view_log/index): update labels and placeholder option text, mark the logbook <select> as required, adjust helper text, and add JS to toggle the required attribute and visibility based on the "Include QSO summary" checkbox (including setting initial state for validation).
2026-03-08 11:48:17 +00:00
Peter Goodhall
5d034d0963 Add public Station Diary with images & RSS
Introduce public Station Diary functionality: add global config flag, routes, controller, model changes, views and DB migrations. New migrations (252-254) add is_public/include_qso_summary, diary_images table and logbook_id on notes. Notes model updated to handle public flags, diary images, qso summaries, caching (per-user cache version), and helper methods for listing/counting public diary entries. New Stationdiary controller serves paginated public pages and RSS feed with caching. Notes controller updated to handle image uploads, attach images to diary entries, and provide an AJAX endpoint to delete images. Views updated to support public visibility options, logbook selector, image upload UI and Quill editor assets; routes and migration version bumped accordingly. Includes file upload example added to uploads/diary.
2026-03-08 11:42:41 +00:00
Peter Goodhall
ad81bd81de Support batch updates by primary key
Allow LoTW batch updates to reference QSOs by COL_PRIMARY_KEY for reliable matching. Controller: include 'primary_key' in batch update payloads. Model: collect numeric primary keys, expand WHERE to include COL_PRIMARY_KEY IN (...) alongside the existing datetime/call/band/station match, add early exit/log when no usable keys provided, and build an id-based lookup (qso_map_by_id) to prefer primary-key matches while remaining backward-compatible with the composite key lookup. This reduces ambiguous matches and improves update accuracy.
2026-02-17 15:28:53 +00:00
Peter Goodhall
392a1389d6 Map additional satellite names in Logbook_model
Add mappings for QMR-KWT-2 -> QMR-KWT-2_(RS95S) and Lobachevsky -> Lobachevsky_(RS83S), and introduce conditional APRS name mapping for BOTAN (when COL_MODE == 'PKT') and SONATE-2 (when COL_MODE == 'PKT'). These changes extend satellite name normalization in application/models/Logbook_model.php to handle these satellites and modes.
2026-02-17 14:21:24 +00:00
Peter Goodhall
c57c250b45 Use distinct() and fix station field
In Logbook_model.php, replace select('DISTINCT user_id') with $this->db->distinct(); $this->db->select('user_id') to use CI's distinct API and produce correct SQL. Also correct the where clause to use station_logbooks_relationship.station_location_id instead of station_id so shared-access users are filtered by the proper station location.
2026-02-11 14:16:51 +00:00
Peter Goodhall
41a8849d7e Cache dashboard stats and add DB indexes
Add per-user/logbook file caching for dashboard statistics (15min TTL) and update Dashboard controller to use cached qso, countries, VUCC and QSL queries. Introduce clear_dashboard_cache() in Logbook_model and call it on QSO create/update/delete to invalidate affected users' cache entries. Add migration (249) to create composite indexes (idx_dxcc_stats, idx_vucc_gridsquare, idx_vucc_grids) to improve dashboard query performance, and bump migration_version to 249. Also include generated cache files under application/cache for current stats.
2026-02-11 13:18:52 +00:00
Peter Goodhall
d4a7e4cfac Batch eQSL updates and add indexes
Add batch processing for eQSL imports/exports and introduce performance indexes. Bump migration_version to 248 and add Migration_add_eqsl_performance_indexes to create idx_eqsl_qslrdate and idx_eqsl_confirmation_match indexes to speed up eQSL queries and batch matching. Modify Eqsl controller to collect successful uploads and perform a single batch mark-as-sent update. Update EqslImporter to queue confirmations and run a single batch update at the end. Implement eqsl_update_batch() and eqsl_mark_sent_batch() in Eqslmethods_model to perform efficient batch DB operations and logging, reducing per-record queries for large eQSL operations.
2026-02-11 11:32:25 +00:00
Peter Goodhall
cfa24d9f1a Add LoTW batch updates and performance indexes
Bump migration version to 247 and add a migration that creates performance indexes for LoTW workflows (idx_lotw_qslrdate, idx_lotw_qsos_to_upload, idx_lotw_confirmation_match) to speed common queries. Refactor Lotw controller to collect records in memory, build rows for rendering, and perform a single batch confirmation update via a new Logbook_model::lotw_update_batch() method instead of many individual updates. Implement lotw_update_batch() to look up matching QSOs, perform update_batch() calls, and separately update gridsquares/distances using the Qra library. Simplify LotwCert::toggle_archive_certificate() to toggle archived state with a single UPDATE and return the resulting status.
2026-02-11 11:14:59 +00:00
Peter Goodhall
2cb8d62860 Add gridsquare prefix index and optimizations
Bump migration version and add a new migration (246) to create/drop a 4-char prefix index on COL_GRIDSQUARE to speed LIKE queries; migration 245 now also drops the prefix index if present. Add Stations::user_owns_station and use it in Logbookadvanced_model to avoid N+1 station lookups. Add caching to Logbooks_model::list_logbook_relationships to prevent redundant queries. Optimize Oqrs_model queries to select only needed columns for several methods. Add Stats::getUniqueCallsignsConsolidated to combine multiple unique-callsign groupings into a single set of queries for better performance. Database debug toggles added where appropriate.
2026-02-11 11:09:39 +00:00
Peter Goodhall
f01599e6a5 Add indexes and batch processing for uploads
Improve query performance and memory usage by adding a migration to create several indexes and converting various upload/reporting flows to batched processing. Changes include:

- Add migration 245 to create indexes: idx_mode, idx_sat_name, idx_continent, idx_qsl_stats (composite), idx_hrdlog_upload, idx_qrz_upload to speed common queries.
- Bump migration version to 245 in config.
- Hrdlog and Qrz controllers: switch to fetching QSOs in LIMIT/OFFSET batches, process updates in chunks, add logging for batch progress, and use break 2 to stop outer loops on invalid API keys to avoid continuing work.
- Logbook_model:
  - get_hrdlog_qsos and get_qrz_qsos now accept limit/offset and use ORDER BY/LIMIT/OFFSET for batching.
  - Replaced a subquery with a JOIN for grid-based filtering to improve performance.
  - get_modes rewritten to use query builder (distinct/select/order_by).
  - Bulk DXCC updates use update_batch instead of per-row queries.
  - calls_without_station_id limited to 500 results to avoid UI hangs.

Overall goal: prevent memory exhaustion with large datasets and improve database query performance.
2026-02-11 10:59:24 +00:00
Peter Goodhall
1d51b608ae Use direct lotw_users joins instead of subqueries
Replace repeated LEFT OUTER JOIN (SELECT callsign, MAX(lastupload) ...) derived-table joins with simpler LEFT JOIN lotw_users lotw across Distances_model, Logbook_model, Logbookadvanced_model, and Worked_all_britain_model. Also remove an unnecessary DISTINCT/inner station_profile join from an optimized Logbook_model subquery. These changes simplify SQL emitted by the CI query builder, improve compatibility and readability, and may improve performance; note that using direct joins can change which lastupload row is returned if multiple lotw_users rows exist for a callsign.
2026-02-11 10:50:22 +00:00