fix(confirmations): count a LoTW "V" everywhere, not only in the awards
An operator's screenshot had it side by side: the Awards panel showed Morocco validated on five bands, and the band/mode matrix two inches above showed the entity as merely worked. ADIF's QSL_Rcvd enumeration has both Y and V — "received" and "verified" — and V is what a LoTW download writes for a confirmation the ARRL has validated. The award engine's isYes accepted "Y" or "V". Everything else in the app compared against 'Y' alone: the worked-before status grid, the slot statistics, the row colouring by QSL status, the awards QSO list, the call history badges. So the confirmations an operator cares most about were the ones that did not count. Now one definition per side, named so the next reader finds the other: qso.ConfirmedValues on the Go side, used by the queries themselves, and isQSLConfirmed in lib/qsl on the frontend, which rowColors and the panels call instead of testing the letter. The Go test drives the real query shape against a real database with a 'V' row — the constant being right is not the point, the queries using it is.
This commit is contained in:
+18
-3
@@ -1907,9 +1907,9 @@ func (r *Repo) WorkedBefore(ctx context.Context, callsign string, dxccHint int,
|
||||
SELECT band, mode,
|
||||
MAX(CASE WHEN callsign = ? THEN 1 ELSE 0 END),
|
||||
MAX(CASE WHEN callsign = ?
|
||||
AND (lotw_rcvd = 'Y' OR qsl_rcvd = 'Y' OR eqsl_rcvd = 'Y')
|
||||
AND (lotw_rcvd IN `+ConfirmedValues+` OR qsl_rcvd IN `+ConfirmedValues+` OR eqsl_rcvd IN `+ConfirmedValues+`)
|
||||
THEN 1 ELSE 0 END),
|
||||
MAX(CASE WHEN lotw_rcvd = 'Y' OR qsl_rcvd = 'Y' OR eqsl_rcvd = 'Y'
|
||||
MAX(CASE WHEN lotw_rcvd IN `+ConfirmedValues+` OR qsl_rcvd IN `+ConfirmedValues+` OR eqsl_rcvd IN `+ConfirmedValues+`
|
||||
THEN 1 ELSE 0 END)
|
||||
FROM qso
|
||||
WHERE dxcc = ?
|
||||
@@ -2792,12 +2792,27 @@ type SlotStats struct {
|
||||
DIGConfirmed int `json:"dig_confirmed"`
|
||||
}
|
||||
|
||||
// ConfirmedValues is what a QSL-received field holds when the contact IS
|
||||
// confirmed, as an SQL list.
|
||||
//
|
||||
// Y AND V. ADIF's QSL_Rcvd enumeration has both: Y is "received", V is
|
||||
// "verified" — and that is what a LoTW download writes for a confirmation the
|
||||
// ARRL has validated. Testing only = 'Y' therefore misses exactly the
|
||||
// confirmations an operator cares most about.
|
||||
//
|
||||
// This was visible on screen: the Awards panel showed Morocco validated on five
|
||||
// bands while the band/mode matrix beside it showed the entity as merely worked,
|
||||
// because the award engine's isYes accepts "Y" or "V" and every SQL query here
|
||||
// compared against 'Y' alone. One definition of confirmed, in one place, is the
|
||||
// only way those two agree.
|
||||
const ConfirmedValues = "('Y','V')"
|
||||
|
||||
// GetSlotStats computes the worked/confirmed slot and DXCC tallies in one pass.
|
||||
// "Confirmed" = LoTW or paper QSL received (the award-valid sources).
|
||||
func (r *Repo) GetSlotStats(ctx context.Context) (SlotStats, error) {
|
||||
rows, err := r.db.QueryContext(ctx, `
|
||||
SELECT COALESCE(dxcc,0), LOWER(COALESCE(band,'')), UPPER(COALESCE(mode,'')),
|
||||
CASE WHEN lotw_rcvd='Y' OR qsl_rcvd='Y' THEN 1 ELSE 0 END
|
||||
CASE WHEN lotw_rcvd IN `+ConfirmedValues+` OR qsl_rcvd IN `+ConfirmedValues+` THEN 1 ELSE 0 END
|
||||
FROM qso`)
|
||||
if err != nil {
|
||||
return SlotStats{}, err
|
||||
|
||||
Reference in New Issue
Block a user