A wrong pin is worse than no pin
The CRM spelled one tower many ways, and some deals sat in the middle of India. Reviewed merges, the pin the data agrees on and four checks before any new pin made the showroom map something a visitor can trust.
The problem
CRM building names were messy, and some deals were pinned in the middle of India.
The fix
Merge spellings by hand, take the pin the data agrees on, and accept new pins only after four checks.
- 507
- buildings on the map
- 27
- spelling merges, each read by a person
- 4
- checks before a new pin is written
On a showroom screen, a visitor’s first move is to look for their own building. If its pin sits on the wrong street, the map stops being proof. So when the deals map became a showroom screen in September, the question wasn’t how to draw 500 pins. It was which pins deserved to be drawn at all. Claude Code wrote most of the SQL; my job was deciding what counted as the same building, and when a location was good enough to show.
One tower, many spellings
The CRM’s building field is typed by hand. The same tower turned up with a wing’s name in front, the neighbourhood tacked on the end, two words swapped or a letter missing. The single most common “building” was NA.
Every raw spelling from the deals and the plan files now goes into an alias table: one row per spelling, pointing at one canonical building. The automatic part is deliberately timid. It folds case, punctuation and spacing, nothing else, which alone collapsed about 30 spellings. Anything cleverer, like dropping “Tower” or a developer’s name, merges real buildings: two towers in one complex can differ by a single word.
Everything beyond that is a decision, stored as a row with its reason:
- 27 merges, each confirmed by reading the pair: misspellings, swapped words, a wing in front, a locality on the end.
- No merge without a reader. Trigram matching (comparing names by shared three-letter chunks) suggested candidates, including two pairs of near-identical names that stand kilometres apart. Those are left out on purpose, and the table can hold a person’s “no” as well as a “yes”.
- 25 entries that aren’t buildings, such as placeholders, bare area names and “somewhere in” notes, stay in the table so their plans still resolve, but never appear on screen.
Even the displayed name is chosen: the canonical spelling, mixed case over shouting capitals, no trailing punctuation, acronyms kept. On a five-foot screen, a title-cased acronym looks like a typo.
A pin the data agrees on
Each building’s pin comes from its own deals, and it’s the mode, not the average: the location the CRM gives most often. Average two bad points on either side of a city and you land in the sea.
Before counting, a point has to be possible: present, inside India, not 0, 0, and not the exact centre of India, which is what a failed lookup returns when all it understood was “India”. 61 deal rows carried that point.
If two or more buildings share exactly the same point, it’s a neighbourhood centre wearing a building’s name, so it’s marked neighbourhood-level. Every pin carries its precision, and the camera respects it: building-level pins can be flown into, neighbourhood pins are shown but never zoomed into, and a building with no trustworthy point never reaches the map.
Four checks before a new pin
For buildings the CRM couldn’t place, or placed only to a neighbourhood, a script asks Google’s Geocoder and Places search, and writes a pin only when a result clears four checks:
accept(result) =
nameMatch(tower, result) >= 0.85 // most of the name’s words agree
&& insideMumbaiRegion(result)
&& isBuildingLevel(result) // not a neighbourhood centre
&& (noRoughPin || movedKm(result) <= 6) // not a different place
// and never a shop, a restaurant or a developer’s head office
The last line earned its place. A one-word tower name is a magnet for businesses: a restaurant and a clothing shop sharing two towers’ names came back a few kilometres from the real buildings. A developer’s name returns its head office, which is a real place and the wrong pin.
Everything else goes to a review file for a person. It held 77 buildings: 52 names didn’t match closely enough, 16 results were businesses, 6 had jumped more than 6 km and 3 were company offices.
Rebuilds that keep the work
The building list is rebuilt after new deals or plans land. A rebuild recomputes names and counts but never overwrites a location the geocoder or a person set, so a pin is reviewed once.
The September check read 533 buildings, 507 of them on the map and 456 placed to the building or its compound. The 26 with no trustworthy point wait for a person rather than a guess.
Rules I’d keep
- A wrong pin is worse than no pin. Leave it off until it’s right.
- Merge by reading, not by score. Fuzzy matching suggests; a person decides.
- Keep decisions as data. A wrong merge is undone by editing a row, not code.
- Take the mode, not the mean. Bad points average into the sea.
- Store the precision. Then the camera knows how close it may go.