Skip to content

feat(feeds): English feed name unique per country, not library-wide - #123

Merged
satishbagali merged 2 commits into
mainfrom
feat/feed-name-unique-per-country
Nov 4, 2026
Merged

satishbagali merged 2 commits into
mainfrom
feat/feed-name-unique-per-country

Conversation

@satishbagali

Copy link
Copy Markdown
Collaborator

Why

The same forage has the same English name in several countries. The library-wide unique feed name (PR #55) rejected real CLIMDES rows: 13 of 187 in the last Test sync (2026-10-31). Names are now unique within a country; the same name may be used in different countries. Local names already follow this rule (PR #104).

Comparison is unchanged: lowercase, trimmed, whitespace (incl. no-break space) collapsed.

What changes

Area Change
Migration f3a4b5c6d7e8 (after e2f3a4b5c6d7) Creates uq_feeds_country_fd_name_norm on (fd_country_id, normalized fd_name) NULLS NOT DISTINCT, then drops uq_feeds_fd_name_norm, in one transaction. Upgrade can't fail on data (the old rule is stricter). Downgrade refuses while a name is used in more than one country and lists them
models.py, schema_compare.py Follow the new index (drift check = 0)
FeedRepository.get_by_name Takes the country (None = feeds without a country)
Feed sync / run-from-file Name checked in the row's country. A row that would move a feed into a country where its name is taken fails with a clear reason. Messages name the country
POST /v1/admin/add-feed 🆕 Blank fd_country_name → 400 "Country is required" (it used to create a feed with no country). Name checked in that country
PUT /v1/admin/update-feed/{id} Name checked in the feed's own fd_country_id

No request/response schema change.

Frontend impact

  • No PWA change is required for this PR.
  • Two PWA requests make the new rule safe for users once names actually repeat across countries: N8 (reset Feed Selection when the user changes the simulation country) and N7 (show the country in Admin › Feeds). Together with N5 (fix(pwa): Feed Selection uses the simulation country's feeds (N5) #118) they gate production.

Deploy plan

  • Test: deploy normally (deploy_test.sh; index swap only). Until N8 + N5 are live, hold cross-country names on Test: no Sync now, no file upload, no same-name Add Feed in another country. Test's feed-sync scheduler is off.
  • Production / Azure: only after N8 + N5 are live.
  • New migration → the 2026-11-01 Azure master-data export (e2f3a4b5c6d7) is obsolete; re-export before the cut-off.

Tests (local)

Check Result
tests/unit 1709 passed, 0 failed (+18 new: cross-country insert, same-country refusal, country move, admin add/edit, both migrations)
PostgreSQL 15.8: upgrade → downgrade → upgrade ✅; pg_get_indexdef equals schema_compare.py
Real inserts Kenya + India same name ✅ saved; India twice ❌ refused; two with no country ❌ refused
Downgrade with a cross-country pair Refused, pair listed, DB stays at head
schema_drift_check --fresh 0 differences
tests/integration/test_schema_alignment.py 11 passed
File upload (Kenya, India, India) through run_file_upload_import 2 imported; 3rd: "…already used in India by row 3 of this file…"

🤖 Generated with Claude Code

The same forage has the same English name in several countries, so the
library-wide unique name rejected real CLIMDES rows (13 of 187 in the last
Test sync). Names are now unique within a country, compared as before
(lowercase, trimmed, whitespace collapsed); local names already follow
this rule (PR #104).

- Migration f3a4b5c6d7e8: creates uq_feeds_country_fd_name_norm on
  (fd_country_id, normalized fd_name) NULLS NOT DISTINCT, then drops
  uq_feeds_fd_name_norm. Upgrade can't fail on data; downgrade refuses
  while a name is used in more than one country and lists them.
- FeedRepository.get_by_name takes the country.
- Feed sync / file upload: name checked in the row's country; a row that
  would move a feed into a country where its name is taken fails with a
  clear reason; messages name the country.
- Admin Add Feed: country required (a blank one used to create a feed
  with no country), then the name is checked in that country. Edit Feed:
  checked in the feed's own fd_country_id.
- models.py and schema_compare.py follow the new index; drift check = 0.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Important

  • Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@satishbagali
satishbagali merged commit 96a2c41 into main Nov 4, 2026
6 checks passed
@satishbagali
satishbagali deleted the feat/feed-name-unique-per-country branch November 4, 2026 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants