Assign printers to a MACHINE and let whichever PC controls it install them, with the observed half kept strictly apart from the assigned half: a collector report can never write an assignment row. Adoption is explicit. Adds a singular relationship type so defaultprinter can mean exactly one, client scripts that converge a bay's queues and correct a drifted one in place, and a wave gate so a fleet-wide driver rollout cannot stampede its own share. On the container side: the compose stack never persisted the instance directory, so a rebuild discarded plugins.json and every upload. It is a volume now, the image ships instance/ owned by the app user so the mountpoint is writable, and the database moves to MySQL 8.4 LTS, which the Windows runbook has recommended since 8.0 went end of life. The image also could not build at all: the frontend stage never copied the plugin staging script it runs. Adds a topology migration guide covering IIS to Docker and back.
45 lines
1.8 KiB
Python
45 lines
1.8 KiB
Python
"""Give a printer driver a vendor, so one row can serve a whole make.
|
|
|
|
HP's and Xerox's universal drivers cover 41 of the reference site's 44 printers
|
|
between them, but a driver could only be bound to ONE modelnumberid - so covering
|
|
them meant 21 near-duplicate rows all pointing at the same package, a table
|
|
nobody would keep true. A driver with no model and a vendor now serves every
|
|
printer of that make, and a per-model row still wins where one genuinely differs
|
|
(a plotter, a card printer, a label printer).
|
|
|
|
Nullable and guarded: a re-run is a no-op, and existing rows keep working
|
|
unchanged because model matching is still tried first.
|
|
|
|
Revision ID: printers0004drivervendor
|
|
Revises: printers0003drivername
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
revision = 'printers0004drivervendor'
|
|
down_revision = 'printers0003drivername'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade():
|
|
bind = op.get_bind()
|
|
inspector = sa.inspect(bind)
|
|
columns = {column['name'] for column in inspector.get_columns('printerdrivers')}
|
|
if 'vendorid' not in columns:
|
|
op.add_column('printerdrivers', sa.Column('vendorid', sa.Integer(), nullable=True))
|
|
# No FK constraint: printerdrivers is a plugin table and vendors is core.
|
|
# ADR-008 keeps plugin chains from writing constraints across that line,
|
|
# and the resolver treats a vendor that no longer exists as no match.
|
|
op.create_index('idx_printerdriver_vendor', 'printerdrivers', ['vendorid'])
|
|
|
|
|
|
def downgrade():
|
|
bind = op.get_bind()
|
|
inspector = sa.inspect(bind)
|
|
columns = {column['name'] for column in inspector.get_columns('printerdrivers')}
|
|
if 'vendorid' in columns:
|
|
op.drop_index('idx_printerdriver_vendor', table_name='printerdrivers')
|
|
op.drop_column('printerdrivers', 'vendorid')
|