displays: single display type with IP-driven role (dashboard/lobby/kiosk)
One 'display' image resolves what it shows from its own IP, like the existing
visitor-location BU mapping. Extend DashboardDefault with displayrole
(dashboard|lobby|partskiosk; migration 7d28, businessunitid now nullable since
only the dashboard role needs one) + a role->path map. New unauthenticated
GET /api/dashboarddefaults/display-role returns {role, path, businessunitid}
for the caller IP. Settings UI gains a Display selector, showing the business
unit only for the dashboard role.
This commit is contained in:
63
migrations/versions/7d28_dashboarddefault_displayrole.py
Normal file
63
migrations/versions/7d28_dashboarddefault_displayrole.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""Add dashboarddefaults.displayrole; make businessunitid nullable
|
||||
|
||||
One "display" PC image resolves its role (dashboard / lobby / partskiosk) from
|
||||
its IP. Existing rows are dashboard mappings, so displayrole defaults to
|
||||
'dashboard'. Lobby / kiosk roles need no business unit, so businessunitid
|
||||
becomes nullable.
|
||||
|
||||
Idempotent guards on column presence / nullability.
|
||||
|
||||
Revision ID: 7d28_dashboarddefault_displayrole
|
||||
Revises: 7d27_roles_color
|
||||
Create Date: 2026-07-21
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = '7d28_dashboarddefault_displayrole'
|
||||
down_revision = '7d27_roles_color'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def _cols(insp):
|
||||
return {c['name']: c for c in insp.get_columns('dashboarddefaults')}
|
||||
|
||||
|
||||
def upgrade():
|
||||
bind = op.get_bind()
|
||||
insp = sa.inspect(bind)
|
||||
if 'dashboarddefaults' not in insp.get_table_names():
|
||||
return
|
||||
cols = _cols(insp)
|
||||
|
||||
if 'displayrole' not in cols:
|
||||
op.add_column('dashboarddefaults', sa.Column(
|
||||
'displayrole', sa.String(length=20),
|
||||
nullable=False, server_default='dashboard'))
|
||||
|
||||
if 'businessunitid' in cols and not cols['businessunitid']['nullable']:
|
||||
op.alter_column('dashboarddefaults', 'businessunitid',
|
||||
existing_type=sa.Integer(), nullable=True)
|
||||
|
||||
|
||||
def downgrade():
|
||||
bind = op.get_bind()
|
||||
insp = sa.inspect(bind)
|
||||
if 'dashboarddefaults' not in insp.get_table_names():
|
||||
return
|
||||
cols = _cols(insp)
|
||||
|
||||
# Only restore NOT NULL if no rows would violate it.
|
||||
if 'businessunitid' in cols and cols['businessunitid']['nullable']:
|
||||
nulls = bind.execute(sa.text(
|
||||
'SELECT COUNT(*) FROM dashboarddefaults '
|
||||
'WHERE businessunitid IS NULL')).scalar()
|
||||
if not nulls:
|
||||
op.alter_column('dashboarddefaults', 'businessunitid',
|
||||
existing_type=sa.Integer(), nullable=False)
|
||||
|
||||
if 'displayrole' in cols:
|
||||
op.drop_column('dashboarddefaults', 'displayrole')
|
||||
Reference in New Issue
Block a user