Skip to content

feat: add postcode lookup for lincoln council#2068

Open
InertiaUK wants to merge 1 commit into
robbrad:masterfrom
InertiaUK:feat/lincoln-postcode-lookup
Open

feat: add postcode lookup for lincoln council#2068
InertiaUK wants to merge 1 commit into
robbrad:masterfrom
InertiaUK:feat/lincoln-postcode-lookup

Conversation

@InertiaUK
Copy link
Copy Markdown
Contributor

@InertiaUK InertiaUK commented May 12, 2026

Summary

  • Users can provide either UPRN or postcode + house number
  • UPRN takes priority when provided (backward compatible)
  • When no UPRN provided, sends empty chooseaddress to AchieveForms API - returns all addresses for the postcode along with bin data in one call
  • Matches by house number in the display field
  • Falls back to first result if no match found

Testing

  • UPRN path (backward compat): LN1 3AE + UPRN 000235056871
  • Postcode + house number: LN1 3AE + paon 2
  • Tested via API end-to-end ✅

Summary by CodeRabbit

  • New Features
    • Enhanced address lookup for Lincoln Council: users can now identify their address using house number instead of UPRN, which is now optional. This provides greater flexibility when retrieving bin collection schedules.

Review Change Stack

Users can provide either UPRN or postcode + house number.
UPRN takes priority when provided (backward compatible).
When no UPRN given, sends empty chooseaddress to AchieveForms
API which returns all addresses for the postcode with bin data.
Matches address by house number in the display field.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

LincolnCouncil address lookup is enhanced to support PAON (house_number) as a fallback when UPRN is unavailable. A new PAON-matching helper method is introduced, parse_data is refactored to zero-pad UPRN values and conditionally populate API requests, and bin results are filtered to the resolved target address. Test configuration is updated to reflect the optional UPRN requirement.

Changes

Lincoln Council address lookup with PAON fallback

Layer / File(s) Summary
PAON matching helper
uk_bin_collection/uk_bin_collection/councils/LincolnCouncil.py
New _match_by_paon static method normalizes house_number and matches against API response row display fields using multiple strategies (prefix with separators, exact match, substring match), falling back to the first available UPRN.
Parse method refactor for UPRN and PAON support
uk_bin_collection/uk_bin_collection/councils/LincolnCouncil.py
Input handling extended to read PAON from kwargs and zero-pad UPRN to 12 digits. API request payload conditionally supplies user_uprn or empty string. After response, target_uprn is resolved directly from user_uprn or via PAON matching when multiple rows exist. Bin-generation loop filters to target_uprn. Minor comment cleanup.
Test configuration update
uk_bin_collection/tests/input.json
LincolnCouncil entry now includes house_number field, updated sample postcode and uprn values, and revised wiki_note indicating UPRN is optional with postcode and house_number for lookup.

Sequence Diagram(s)

sequenceDiagram
  participant Input as Input: UPRN or PAON
  participant ParseData as parse_data
  participant API as API Request
  participant Match as _match_by_paon
  participant Filter as Bin Filter

  Input ->> ParseData: user_uprn or paon
  ParseData ->> ParseData: Zero-pad user_uprn if present
  ParseData ->> API: chooseaddress: user_uprn or ''
  API -->> ParseData: rows_data
  
  alt user_uprn provided
    ParseData ->> Filter: target_uprn = user_uprn
  else multiple rows and paon provided
    ParseData ->> Match: Match paon against display fields
    Match -->> ParseData: matched UPRN
    ParseData ->> Filter: target_uprn = matched UPRN
  end
  
  Filter ->> Filter: Generate bins only for target_uprn rows
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • robbrad/UKBinCollectionData#1996: Both PRs modify council address-selection logic to prefer UPRN when present and fall back to matching by house number/PAON (adding PAON-matching helpers).

Poem

🐰 A Lincoln address lookup so fine,
With PAON matching in design,
When UPRN is bare,
House numbers are there—
Bin schedules shall perfectly align! 📦

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding postcode lookup capability as an alternative to UPRN for Lincoln Council.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.67%. Comparing base (8ecf878) to head (96ebb4d).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2068   +/-   ##
=======================================
  Coverage   86.67%   86.67%           
=======================================
  Files           9        9           
  Lines        1141     1141           
=======================================
  Hits          989      989           
  Misses        152      152           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@uk_bin_collection/uk_bin_collection/councils/LincolnCouncil.py`:
- Around line 71-78: The current resolve logic silently falls back to the first
address when PAON resolution is ambiguous or fails; change it to fail explicitly
instead: in the method that sets target_uprn (using variables user_uprn,
user_paon, rows_data and calling _match_by_paon), detect when rows_data has
multiple entries and _match_by_paon returns no unique match (or when user_paon
is provided but ambiguous) and raise a clear exception (e.g., ValueError or a
custom NotFound/AmbiguousMatch error) instead of using next(iter(rows_data));
also update the other occurrences where the code silently picks
next(iter(rows_data)) (including the spots that call the same resolution flow
referenced by _match_by_paon) to follow the same explicit-failure behavior so
callers can handle/return an error rather than returning potentially-wrong bin
data.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7aed1461-28d3-4f47-8f14-49418dcc7d49

📥 Commits

Reviewing files that changed from the base of the PR and between 8ecf878 and 96ebb4d.

📒 Files selected for processing (2)
  • uk_bin_collection/tests/input.json
  • uk_bin_collection/uk_bin_collection/councils/LincolnCouncil.py

Comment on lines +71 to +78
# Resolve which UPRN to use
if user_uprn:
target_uprn = user_uprn
elif user_paon and len(rows_data) > 1:
target_uprn = self._match_by_paon(rows_data, user_paon)
else:
target_uprn = next(iter(rows_data))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid silent first-address fallback for ambiguous/no-match cases.

Lines 74-78 and Line 124 silently select the first address when PAON cannot be deterministically resolved. That can return bin data for the wrong property; fail explicitly instead.

🔧 Safer resolution flow
-        if user_uprn:
-            target_uprn = user_uprn
-        elif user_paon and len(rows_data) > 1:
-            target_uprn = self._match_by_paon(rows_data, user_paon)
-        else:
-            target_uprn = next(iter(rows_data))
+        if not rows_data:
+            raise LookupError("No address rows returned for the provided postcode")
+
+        if user_uprn:
+            target_uprn = user_uprn
+            if target_uprn not in rows_data:
+                raise LookupError(f"UPRN {target_uprn} was not returned by Lincoln API")
+        elif user_paon and len(rows_data) > 1:
+            target_uprn = self._match_by_paon(rows_data, user_paon)
+            if target_uprn is None:
+                raise LookupError(f"No address matched PAON '{user_paon}'")
+        elif len(rows_data) == 1:
+            target_uprn = next(iter(rows_data))
+        else:
+            raise LookupError("Multiple addresses returned; provide UPRN or exact house_number")
@@
-        return next(iter(rows_data))
+        return None

Based on learnings: In uk_bin_collection/**/*.py, prefer explicit failures over silent defaults when formats/matches are unexpected.

Also applies to: 86-87, 124-124

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uk_bin_collection/uk_bin_collection/councils/LincolnCouncil.py` around lines
71 - 78, The current resolve logic silently falls back to the first address when
PAON resolution is ambiguous or fails; change it to fail explicitly instead: in
the method that sets target_uprn (using variables user_uprn, user_paon,
rows_data and calling _match_by_paon), detect when rows_data has multiple
entries and _match_by_paon returns no unique match (or when user_paon is
provided but ambiguous) and raise a clear exception (e.g., ValueError or a
custom NotFound/AmbiguousMatch error) instead of using next(iter(rows_data));
also update the other occurrences where the code silently picks
next(iter(rows_data)) (including the spots that call the same resolution flow
referenced by _match_by_paon) to follow the same explicit-failure behavior so
callers can handle/return an error rather than returning potentially-wrong bin
data.

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.

1 participant