feat(rda): measure the two district sources before arbitrating between them
A log imported from HAMLOG.online carries the Russian district in CNTY, and the offline RDA database has its own answer for the same contact. Which wins is a real question — but only if the two are independent. If HAMLOG's value is itself a lookup in the same kind of database, there is nothing to arbitrate and a precedence rule would be ceremony around a redundancy. So this measures instead of deciding: Settings → RDA gains a read-only compare that reports agreements, disagreements, and the contacts where only one side knows, then lists the disagreements — callsign, date, both districts, whether the database answer was a DATED record (the award administrators' own fact) or the callsign's current district (an assumption), and whether the QSO is confirmed on HAMLOG (their value has then been through a match of two logs). It changes nothing in the log. What to do about a conflict is the next decision, and it should be taken with the operator's own numbers in hand. Also: the four HAMLOG fields become filterable, so 'never sent there' is a filter rather than a guess. A field that can be written and not read back is half a feature — pinned by a test against the bulk-editable list.
This commit is contained in:
@@ -55,3 +55,24 @@ func TestNotInKeepsNulls(t *testing.T) {
|
||||
t.Errorf("sql = %q, want the column wrapped in IFNULL", sql)
|
||||
}
|
||||
}
|
||||
|
||||
// Every HAMLOG field an operator can bulk-edit must also be filterable: the
|
||||
// question "which contacts have never gone to HAMLOG" is what you ask BEFORE
|
||||
// uploading a backlog, and a field that can be written but not read back is
|
||||
// half a feature.
|
||||
func TestHamlogFieldsAreFilterable(t *testing.T) {
|
||||
filterable := map[string]bool{}
|
||||
for _, f := range FilterableFields() {
|
||||
filterable[f] = true
|
||||
}
|
||||
for _, f := range []string{"hamlog_sent", "hamlog_sent_date", "hamlog_rcvd", "hamlog_rcvd_date"} {
|
||||
if !filterable[f] {
|
||||
t.Errorf("%s is bulk-editable but not filterable", f)
|
||||
}
|
||||
}
|
||||
// The received key must be THEIR name, or an imported log filters differently
|
||||
// from a stamped one — the exact split the confirmation source exists to avoid.
|
||||
if got := filterableExtras["hamlog_rcvd"]; got != "APP_HAMLOG_QSO_CFM" {
|
||||
t.Errorf("hamlog_rcvd filters on %q, want APP_HAMLOG_QSO_CFM", got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1316,6 +1316,15 @@ var bareDateRe = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`)
|
||||
// ADIF/Extras key; the SQL expression uses json_extract.
|
||||
var filterableExtras = map[string]string{
|
||||
"owner_callsign": "OWNER_CALLSIGN",
|
||||
// HAMLOG.online, in both directions and with its dates. Filterable for the
|
||||
// same reason it is bulk-editable: without it there is no way to ask "which
|
||||
// contacts have never gone there", which is the question an operator asks
|
||||
// before uploading a backlog. The received key is THEIR field name — see
|
||||
// award.HamlogQSLKey — so an imported log filters the same as a stamped one.
|
||||
"hamlog_sent": "APP_OPSLOG_HAMLOG_SENT",
|
||||
"hamlog_sent_date": "APP_OPSLOG_HAMLOG_SENT_DATE",
|
||||
"hamlog_rcvd": "APP_HAMLOG_QSO_CFM",
|
||||
"hamlog_rcvd_date": "APP_OPSLOG_HAMLOG_QSL_DATE",
|
||||
}
|
||||
|
||||
// FilterableFields returns the whitelist (for the frontend to build its field
|
||||
|
||||
Reference in New Issue
Block a user