Properties tab: proximity-based default sort order #205

Closed
opened 2026-06-13 21:26:57 +00:00 by ldraney · 3 comments
Owner

Type

Feature

Lineage

Discovered during schedule digestion discussion -- the boss already groups properties by geographic proximity on his paper schedule, so the digital property list should mirror that mental model.

Repo

ldraney/landscaping-assistant

User Story

As a crew lead
I want properties sorted by geographic proximity by default (not alphabetical)
So that nearby properties are grouped together, matching how I think about my route

Context

The boss's paper schedule groups properties by proximity -- he keeps geographically close properties together even across day boundaries. The current Properties tab sorts alphabetically by client_name, which scatters nearby properties throughout the list.

The Property model already has latitude and longitude fields. Many properties likely have coordinates populated (via the Add Location feature). For properties without coordinates, they fall to the end of the list.

The sort should use a nearest-neighbor chain starting from a configurable base point (e.g., the shop/office location, or the first property). This isn't a full traveling-salesman optimization -- just a simple greedy nearest-neighbor traversal that creates natural geographic clusters.

File Targets

Files the agent should modify:

  • app/controllers/properties_controller.rb -- change default sort from alphabetical to proximity
  • app/controllers/weeks_controller.rb -- same sort change for week view's property lists
  • app/models/property.rb -- add scope :by_proximity that orders by nearest-neighbor chain

Files the agent should NOT touch:

  • db/schema.rb -- no migration needed, using existing lat/lng fields
  • app/models/work_queue_item.rb -- queue ordering is separate (user-defined via drag)
  • app/controllers/work_queue_items_controller.rb -- sorts by updated_at for the add-to-queue dropdown; intentionally different from property browsing sort

Feature Flag

Flag: none
This changes the default sort order. If users prefer alphabetical, we can add a toggle later, but the proximity default is the right starting point.

Acceptance Criteria

  • Properties tab lists properties grouped by geographic proximity instead of alphabetically
  • Properties without lat/lng coordinates appear at the end of the list
  • Week view's unassigned properties section uses the same proximity sort
  • Sort is deterministic (same input always produces same order)
  • Performance: acceptable for up to 200 properties (no N+1, computed in a single query or efficient Ruby sort)

Test Expectations

  • Unit test: Property.by_proximity returns properties in nearest-neighbor order given known coordinates
  • Unit test: properties without coordinates sort to the end
  • Request spec: properties index returns proximity-sorted results
  • Run command: bundle exec rspec spec/models/property_spec.rb spec/requests/properties_spec.rb

Constraints

  • Use Haversine formula or simple Euclidean distance on lat/lng (properties are all in the same metro area, so curvature is negligible)
  • No external geocoding gems -- work with existing lat/lng data
  • Nearest-neighbor greedy algorithm, not TSP optimization
  • Base point: hardcode a sensible default (e.g., centroid of all properties, or a configurable ENV var for shop location) -- can make configurable later

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • landscaping-assistant -- project this affects
### Type Feature ### Lineage Discovered during schedule digestion discussion -- the boss already groups properties by geographic proximity on his paper schedule, so the digital property list should mirror that mental model. ### Repo `ldraney/landscaping-assistant` ### User Story As a crew lead I want properties sorted by geographic proximity by default (not alphabetical) So that nearby properties are grouped together, matching how I think about my route ### Context The boss's paper schedule groups properties by proximity -- he keeps geographically close properties together even across day boundaries. The current Properties tab sorts alphabetically by `client_name`, which scatters nearby properties throughout the list. The Property model already has `latitude` and `longitude` fields. Many properties likely have coordinates populated (via the Add Location feature). For properties without coordinates, they fall to the end of the list. The sort should use a nearest-neighbor chain starting from a configurable base point (e.g., the shop/office location, or the first property). This isn't a full traveling-salesman optimization -- just a simple greedy nearest-neighbor traversal that creates natural geographic clusters. ### File Targets Files the agent should modify: - `app/controllers/properties_controller.rb` -- change default sort from alphabetical to proximity - `app/controllers/weeks_controller.rb` -- same sort change for week view's property lists - `app/models/property.rb` -- add `scope :by_proximity` that orders by nearest-neighbor chain Files the agent should NOT touch: - `db/schema.rb` -- no migration needed, using existing lat/lng fields - `app/models/work_queue_item.rb` -- queue ordering is separate (user-defined via drag) - `app/controllers/work_queue_items_controller.rb` -- sorts by `updated_at` for the add-to-queue dropdown; intentionally different from property browsing sort ### Feature Flag Flag: none This changes the default sort order. If users prefer alphabetical, we can add a toggle later, but the proximity default is the right starting point. ### Acceptance Criteria - [ ] Properties tab lists properties grouped by geographic proximity instead of alphabetically - [ ] Properties without lat/lng coordinates appear at the end of the list - [ ] Week view's unassigned properties section uses the same proximity sort - [ ] Sort is deterministic (same input always produces same order) - [ ] Performance: acceptable for up to 200 properties (no N+1, computed in a single query or efficient Ruby sort) ### Test Expectations - [ ] Unit test: `Property.by_proximity` returns properties in nearest-neighbor order given known coordinates - [ ] Unit test: properties without coordinates sort to the end - [ ] Request spec: properties index returns proximity-sorted results - Run command: `bundle exec rspec spec/models/property_spec.rb spec/requests/properties_spec.rb` ### Constraints - Use Haversine formula or simple Euclidean distance on lat/lng (properties are all in the same metro area, so curvature is negligible) - No external geocoding gems -- work with existing lat/lng data - Nearest-neighbor greedy algorithm, not TSP optimization - Base point: hardcode a sensible default (e.g., centroid of all properties, or a configurable ENV var for shop location) -- can make configurable later ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `landscaping-assistant` -- project this affects
Author
Owner

Scope Review: NEEDS_REFINEMENT

Review note: review-1451-2026-06-13
Template complete, file targets verified, story traceability confirmed. Two minor items before READY:

  • [BODY] Add app/controllers/work_queue_items_controller.rb to the "Files the agent should NOT touch" list -- the Today view dropdown sorts by recency intentionally, and an agent could mistakenly apply proximity sort there
  • [SCOPE] arch-rails-app architecture note does not exist in pal-e-docs (shared gap across many board items, not blocking for this ticket)
## Scope Review: NEEDS_REFINEMENT Review note: `review-1451-2026-06-13` Template complete, file targets verified, story traceability confirmed. Two minor items before READY: - **[BODY]** Add `app/controllers/work_queue_items_controller.rb` to the "Files the agent should NOT touch" list -- the Today view dropdown sorts by recency intentionally, and an agent could mistakenly apply proximity sort there - **[SCOPE]** `arch-rails-app` architecture note does not exist in pal-e-docs (shared gap across many board items, not blocking for this ticket)
Author
Owner

Scope Review: READY (re-review)

Review note: review-1451-2026-06-13-r2

Previous [BODY] finding resolved: app/controllers/work_queue_items_controller.rb now correctly listed in the do-not-touch section.

All file targets verified, template complete, traceability confirmed (story note present, arch note still missing but non-blocking). 3 files in 1 repo, 5 AC, well under the 5-minute decomposition threshold. Ticket is ready for implementation.

## Scope Review: READY (re-review) Review note: `review-1451-2026-06-13-r2` Previous `[BODY]` finding resolved: `app/controllers/work_queue_items_controller.rb` now correctly listed in the do-not-touch section. All file targets verified, template complete, traceability confirmed (story note present, arch note still missing but non-blocking). 3 files in 1 repo, 5 AC, well under the 5-minute decomposition threshold. Ticket is ready for implementation.
Author
Owner

Validation: PASS

Tiers executed: Tier 1 (local tests), Tier 3 (CI pipeline + route checks)
Validation note: validation-205-2026-06-13
5 checks: 5 PASS, 0 FAIL

Evidence summary:

  • Local tests: 50 examples, 0 failures (spec/models/property_spec.rb, spec/requests/properties_spec.rb)
  • CI pipeline #512 test step: 337 examples, 0 failures
  • CI pipeline #511 (PR): all steps green
  • Dev server routes (/properties, /properties/manage, /weeks, /today, /profile): all return HTTP 302 (expected auth redirect), no 500s
  • Code review confirms all 5 acceptance criteria met at commit ae62821
## Validation: PASS Tiers executed: Tier 1 (local tests), Tier 3 (CI pipeline + route checks) Validation note: `validation-205-2026-06-13` 5 checks: 5 PASS, 0 FAIL **Evidence summary:** - Local tests: 50 examples, 0 failures (`spec/models/property_spec.rb`, `spec/requests/properties_spec.rb`) - CI pipeline #512 test step: 337 examples, 0 failures - CI pipeline #511 (PR): all steps green - Dev server routes (`/properties`, `/properties/manage`, `/weeks`, `/today`, `/profile`): all return HTTP 302 (expected auth redirect), no 500s - Code review confirms all 5 acceptance criteria met at commit ae62821
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/landscaping-assistant#205
No description provided.