printers: add format=text to install-list + pc-default; vendor via model

The Inno printer installers hand-parsed JSON in Pascal (brittle brace-counting).
Add ?format=text to install-list (one printer per line, pipe-delimited:
printerid|windowsname|vendorname|modelnumber|hostname|ipaddress|mapx|mapy) and
to pc-default (printerid|windowsname), so the installer side is a split() with
no JSON parser. The web map keeps the default JSON.

Also resolve install-list's vendorname via the model (as the batch already does),
since the import sets the model, not the printer's direct vendorid - otherwise
the installers' HP/Xerox/Brother filter drops every prod printer.
This commit is contained in:
cproudlock
2026-07-29 13:51:01 -04:00
parent cb075a278f
commit ad84c9060a
2 changed files with 87 additions and 5 deletions

View File

@@ -38,6 +38,54 @@ def test_install_list_returns_network_printer_with_map(client, db, auth_headers,
assert row['mapx'] == 120 and row['mapy'] == 240
def test_install_list_vendorname_resolves_via_model(client, db, auth_headers,
printer_assettype):
"""vendorname falls back to the model's vendor when the printer has no
direct vendorid (the import sets the model, not the printer's vendor). The
Inno installer filters on this, so it must not be null on real data."""
from shopdb.core.models import Vendor, Model
hp = Vendor(vendor='HP')
db.session.add(hp)
db.session.commit()
model = Model(modelnumber='LaserJet M607', vendorid=hp.vendorid)
db.session.add(model)
db.session.commit()
client.post('/api/printers', json={
'assetnumber': 'CSF09-2022-HP', 'hostname': 'wjprn09',
'modelnumberid': model.modelnumberid,
}, headers=auth_headers)
resp = client.get('/api/printers/install-list', headers=auth_headers)
row = next((r for r in resp.get_json()['data']
if r['machinenumber'] == 'CSF09-2022-HP'), None)
assert row is not None
assert row['vendorname'] == 'HP'
def test_install_list_text_format(client, db, auth_headers, printer_assettype):
"""format=text returns one pipe-delimited line per printer (fixed field
order) so the Inno installers split() instead of parsing JSON."""
client.post('/api/printers', json={
'assetnumber': 'CSF01-HP', 'windowsname': 'CSF01-HP', 'hostname': 'wjprn01',
'mapx': 120, 'mapy': 240,
}, headers=auth_headers)
resp = client.get('/api/printers/install-list?format=text', headers=auth_headers)
assert resp.status_code == 200
assert resp.mimetype == 'text/plain'
line = next((l for l in resp.get_data(as_text=True).splitlines()
if 'CSF01-HP' in l), None)
assert line is not None
cols = line.split('|')
# printerid|windowsname|vendorname|modelnumber|hostname|ipaddress|mapx|mapy
assert len(cols) == 8
assert cols[1] == 'CSF01-HP' # windowsname (falls back to assetnumber name)
assert cols[4] == 'wjprn01' # hostname
assert cols[6] == '120' and cols[7] == '240'
def test_install_list_excludes_usb_only_printer(client, db, auth_headers,
printer_assettype):
"""A printer with no hostname and no network IP is excluded."""