Let a PC be assigned a business unit, and a retired asset be found
Some checks failed
CI / naming (push) Successful in 3s
CI / frontend (push) Successful in 13s
CI / migrations-mysql (push) Successful in 42s
CI / backend (push) Failing after 4m47s

The last two items from the run.

The PC detail page has always rendered a Business Unit row, and the API has
always accepted the field. Only the form had no control, so it could be read and
never set from the UI - a value that appeared the moment somebody set it through
the API and could not be reached otherwise. The form has the picker now, loaded
with listAll() rather than a capped page.

Global search excluded inactive assets, so a retired record existed, was
reachable by URL, and could not be found by anybody who did not already know
where it was - including whoever wanted to restore it, which the retire dialog
promises they can. Retired assets are searchable now.

That is only safe with the ordering, so it is part of the change rather than a
follow-up: somebody searching a machine number almost always wants the machine
still on the floor, so a retired match drops 60 points of relevance, sorts below
every live one, and carries a 'retired' flag the results page renders as a
badge. Indistinguishable retired results would be worse than none.

Four tests, verified by planting the isactive filter back: three fail.

Scope: product
This commit is contained in:
cproudlock
2026-09-03 17:08:03 -04:00
parent a1802a2bf5
commit c1a4c9eba6
4 changed files with 127 additions and 6 deletions

View File

@@ -0,0 +1,69 @@
"""A retired asset has to be findable, and must never outrank a live one.
Retire is a soft delete: the confirm dialog promises history is kept and the
record can be restored. Global search excluded inactive assets, so the record
existed, was reachable by URL, and could not be found by anybody who did not
already know where it was - including whoever wanted to restore it.
Including them is only safe with the ordering: somebody searching a machine
number almost always wants the machine still on the floor, so a retired match
is pushed below every live one and flagged, rather than being mixed in
indistinguishably.
"""
import pytest
@pytest.fixture
def assets(db):
from shopdb.core.models import Asset, AssetType
assettype = AssetType(assettype='machine')
db.session.add(assettype)
db.session.flush()
live = Asset(assetnumber='SR-1000', name='Live grinder',
assettypeid=assettype.assettypeid)
gone = Asset(assetnumber='SR-1001', name='Retired grinder',
assettypeid=assettype.assettypeid, isactive=False)
db.session.add_all([live, gone])
db.session.commit()
return live, gone
def _search(client, headers, term):
response = client.get('/api/search?q=%s' % term, headers=headers)
assert response.status_code == 200, response.get_json()
payload = response.get_json()['data']
return payload.get('results', payload if isinstance(payload, list) else [])
def test_a_retired_asset_can_be_found(client, db, auth_headers, assets):
_live, gone = assets
titles = [r['title'] for r in _search(client, auth_headers, 'SR-1001')]
assert any('Retired grinder' in title or 'SR-1001' in title
for title in titles), titles
def test_a_retired_result_says_it_is_retired(client, db, auth_headers, assets):
results = _search(client, auth_headers, 'SR-1001')
match = next(r for r in results
if 'SR-1001' in (r['title'] + (r.get('subtitle') or '')))
assert match['retired'] is True
def test_a_live_asset_outranks_a_retired_one(client, db, auth_headers, assets):
"""Both match 'grinder'; the one still on the floor comes first."""
results = [r for r in _search(client, auth_headers, 'grinder')
if r.get('retired') is not None]
assert len(results) >= 2, results
live = next(r for r in results if not r['retired'])
retired = next(r for r in results if r['retired'])
assert live['relevance'] > retired['relevance'], (live, retired)
def test_a_live_asset_is_not_flagged(client, db, auth_headers, assets):
results = _search(client, auth_headers, 'SR-1000')
match = next(r for r in results if 'SR-1000' in (r['title'] + (r.get('subtitle') or '')))
assert match['retired'] is False