Place a company on the map from its Wikidata coordinates #701

Closed
opened 2026-10-03 01:59:11 +00:00 by tiagoagueda · 0 comments
Owner

From the list: “Companies with Wikidata might have location data available = coordinates = pin on a map.” A company is placed today from the text of its location against an offline city table; the coordinate Wikidata holds for the organisation is never read. The engine, the precision and the tile questions are decided in #700; this issue is only the Wikidata source.

What exists today

  • A company's coordinates and where they came from. Company.location_lat and location_lon are floats, with location_resolved_from, location_resolved_at and location_resolved_by, whose values are LocationSource.GUESSED (the city dataset), MANUAL and UNPLACED (src/postulo/jobs/models.py:224-235, :273-287). There is no Wikidata value. Company.save() guesses again whenever the location text differs from the text the last resolution was made from, unless the source is MANUAL (:322-331); a source of any other kind is therefore overwritten by the next edit of the text.
  • Wikidata is an identifier and nothing more. A company can carry a Wikidata item (#42) and nothing reads it; the read is proposed in #673 through the guarded client, by a press.
  • What Wikidata holds, verified on 2026-10-02 (one read-only request to Special:EntityData/Q29671.json): the University of Aveiro item has a coordinate location (P625: latitude 40.63027778, longitude -8.6575, precision 0.000001 degrees) alongside its labels, website and ISNI. That is a building, not a city. An item can also have no P625, or several; an organisation with many offices is usually given its headquarters, and the headquarters location is a statement (P159) pointing at another item.
  • The map groups by the location text. CompanyMapView keys a place by the text and uses the first coordinate found for it (src/postulo/jobs/views.py:175-184); a precise point under a city's text would become that city's dot.
  • Coordinates do not travel. COMPANY_FIELDS carries location but none of the coordinate columns (src/postulo/core/export.py:164-176), so after a restore every company is guessed again and a person's correction is lost; a merge does move all six location fields (src/postulo/jobs/merging.py:478-491). Found while drafting; not filed separately.

Checked against main at f09b6010b.

Proposal

  1. A source called Wikidata: LocationSource.WIKIDATA, fitting the 20-character column.
  2. Read the coordinate in the same request as the names that #673 fetches (one document, no second request): the preferred-rank P625 statement, or the only one; none or several without a preferred one means nothing is proposed. The preview shows the point and its source beside the names, and nothing is stored until the person confirms.
  3. A rule of precedence written down and tested: a point the person set (MANUAL) beats Wikidata's, which beats the city guess; a Wikidata point is not derived from the text, so editing the text does not replace it, and it can be taken off (the place then falls back to the guess) or replaced by fetching again.
  4. Carry the coordinates in the archive and the importer, with their source, time and the text they were made from, so a restore keeps what a person corrected or fetched.
  5. Draw it as #700 decides: a Wikidata point is a precise point, and the overview keeps one dot per place; the point is used by a per-company map where one exists and otherwise only sets the place's dot.

Decisions

  • Precision. Store what Wikidata gives (here a precision of 0.000001 degrees, about ten centimetres, in practice a building), or round. Recommended: store it as given: the organisation's own coordinate is a public fact and no more sensitive than the address text already on the record; what must not leak is the viewing of it, which is #700's tile decision.
  • Several or indirect locations. Take the headquarters (P159) when P625 is missing. Recommended: no, not in this issue: it is a second request to another item and an arbitrary choice for a group.
  • A precise point and the city dot at one place. Recommended: the overview keeps counting by the place's text and its city coordinate; the Wikidata point is not allowed to move another company's dot, which the first-coordinate-wins rule would do.

Builds on

Issues #42 (Wikidata as an identifier), #108 (the map), #366 (the outbound inventory), #534 and #399 (open map defects). Related: #700 (the decisions), #673 (the Wikidata read).

Needed by

#702 (a precise point is the model for an address's pin).

Done when

  • In tests/test_company_map.py: a company with a fetched Wikidata point is drawn at it; editing its location text does not move it; a manual correction beats it; taking it off falls back to the city guess; another company's dot does not move.
  • A test with a mocked transport (as #673's) shows the coordinate comes from the same single request and nothing is stored before confirming.
  • tests/test_export.py: coordinates, source and time survive the archive round trip; the archive format goes up by one (src/postulo/core/export.py FORMAT_VERSION: one more than whatever FORMAT_VERSION is when the commit lands (29 at f09b6010b); tests/test_export.py:96 follows it), and #673 bumps it too if it lands first. The candidate format (4) does not change; the processing record concerns contacts and is unchanged for a company.
  • No new page: tests/test_page_coverage.py and the isolation sweep stand. New strings are in the working catalogues (en-GB, fr-FR, pt-PT as drafts) and Weblate (#349).

From the list of improvements of 2026-10-02.

From the list: “Companies with Wikidata might have location data available = coordinates = pin on a map.” A company is placed today from the text of its location against an offline city table; the coordinate Wikidata holds for the organisation is never read. The engine, the precision and the tile questions are decided in #700; this issue is only the Wikidata source. ## What exists today - **A company's coordinates and where they came from.** `Company.location_lat` and `location_lon` are floats, with `location_resolved_from`, `location_resolved_at` and `location_resolved_by`, whose values are `LocationSource.GUESSED` (the city dataset), `MANUAL` and `UNPLACED` (`src/postulo/jobs/models.py:224-235`, `:273-287`). There is no Wikidata value. `Company.save()` guesses again whenever the location text differs from the text the last resolution was made from, unless the source is `MANUAL` (`:322-331`); a source of any other kind is therefore overwritten by the next edit of the text. - **Wikidata is an identifier and nothing more.** A company can carry a Wikidata item (#42) and nothing reads it; the read is proposed in #673 through the guarded client, by a press. - **What Wikidata holds, verified on 2026-10-02** (one read-only request to `Special:EntityData/Q29671.json`): the University of Aveiro item has a coordinate location (P625: latitude 40.63027778, longitude -8.6575, precision 0.000001 degrees) alongside its labels, website and ISNI. That is a building, not a city. An item can also have no P625, or several; an organisation with many offices is usually given its headquarters, and the headquarters location is a statement (P159) pointing at another item. - **The map groups by the location text.** `CompanyMapView` keys a place by the text and uses the first coordinate found for it (`src/postulo/jobs/views.py:175-184`); a precise point under a city's text would become that city's dot. - **Coordinates do not travel.** `COMPANY_FIELDS` carries `location` but none of the coordinate columns (`src/postulo/core/export.py:164-176`), so after a restore every company is guessed again and a person's correction is lost; a merge does move all six location fields (`src/postulo/jobs/merging.py:478-491`). Found while drafting; not filed separately. Checked against `main` at `f09b6010b`. ## Proposal 1. **A source called Wikidata**: `LocationSource.WIKIDATA`, fitting the 20-character column. 2. **Read the coordinate in the same request as the names** that #673 fetches (one document, no second request): the preferred-rank P625 statement, or the only one; none or several without a preferred one means nothing is proposed. The preview shows the point and its source beside the names, and nothing is stored until the person confirms. 3. **A rule of precedence** written down and tested: a point the person set (`MANUAL`) beats Wikidata's, which beats the city guess; a Wikidata point is not derived from the text, so editing the text does not replace it, and it can be taken off (the place then falls back to the guess) or replaced by fetching again. 4. **Carry the coordinates in the archive and the importer**, with their source, time and the text they were made from, so a restore keeps what a person corrected or fetched. 5. **Draw it as #700 decides**: a Wikidata point is a precise point, and the overview keeps one dot per place; the point is used by a per-company map where one exists and otherwise only sets the place's dot. ## Decisions - **Precision.** Store what Wikidata gives (here a precision of 0.000001 degrees, about ten centimetres, in practice a building), or round. **Recommended: store it as given**: the organisation's own coordinate is a public fact and no more sensitive than the address text already on the record; what must not leak is the viewing of it, which is #700's tile decision. - **Several or indirect locations.** Take the headquarters (P159) when P625 is missing. **Recommended: no, not in this issue**: it is a second request to another item and an arbitrary choice for a group. - **A precise point and the city dot at one place.** **Recommended: the overview keeps counting by the place's text and its city coordinate**; the Wikidata point is not allowed to move another company's dot, which the first-coordinate-wins rule would do. ## Builds on Issues #42 (Wikidata as an identifier), #108 (the map), #366 (the outbound inventory), #534 and #399 (open map defects). Related: #700 (the decisions), #673 (the Wikidata read). ## Needed by #702 (a precise point is the model for an address's pin). ## Done when - In `tests/test_company_map.py`: a company with a fetched Wikidata point is drawn at it; editing its location text does not move it; a manual correction beats it; taking it off falls back to the city guess; another company's dot does not move. - A test with a mocked transport (as #673's) shows the coordinate comes from the same single request and nothing is stored before confirming. - `tests/test_export.py`: coordinates, source and time survive the archive round trip; **the archive format goes up by one** (`src/postulo/core/export.py` `FORMAT_VERSION`: one more than whatever `FORMAT_VERSION` is when the commit lands (29 at `f09b6010b`); `tests/test_export.py:96` follows it), and #673 bumps it too if it lands first. The candidate format (4) does not change; the processing record concerns contacts and is unchanged for a company. - No new page: `tests/test_page_coverage.py` and the isolation sweep stand. New strings are in the working catalogues (en-GB, fr-FR, pt-PT as drafts) and Weblate (#349). From the list of improvements of 2026-10-02.
tiagoagueda added this to the 1.0.0 milestone 2026-10-03 01:59:11 +00:00
Sign in to join this conversation.
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
Postulo/postulo#701
No description provided.