Add kitchen (10 caps) + kds (3 caps) — Phase 4 stack registration

- Update kitchen app row: teal theme, broader description (invoicing/GP/recipes/menus)
- Add kds app row: LXC 125 @ 10.10.10.125
- Seed kitchen capabilities: view, invoices, invoices_manage, disputes, logbook,
  orders, recipes, menus, manage_flags, settings
- Seed KDS capabilities: view, manage, settings
- Grant Staff role KDS view + manage (needed during live service)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-11 11:26:06 +00:00
parent d576f103c5
commit af94b72b02

View file

@ -120,7 +120,7 @@ export async function initDb() {
INSERT INTO apps (slug, name, description, base_path, icon, theme_color, category, internal_host, internal_port)
VALUES
('noticeboard', 'Noticeboard', 'Staff notices and announcements', '/notices', 'ClipboardList', '#1e3a5f', NULL, '10.10.10.112', 3080),
('kitchen', 'Kitchen Flash','Invoice processing and GP tracking', '/kitchen', 'ChefHat', '#e85d04', 'Kitchen', '10.10.10.110', 3080),
('kitchen', 'Kitchen', 'Invoice/GP, recipes, menus and kitchen management', '/kitchen', 'ChefHat', '#0d9488', 'Kitchen', '10.10.10.110', 3080),
('cashup', 'Cash Up', 'Hotel daily cashing up', '/cashup', 'Banknote', '#6b2d8b', 'Finance', '10.10.10.117', 3083),
('housekeeping','Housekeeping', 'Room status and task management', '/hk', 'BedDouble', '#2d6a4f', 'Hotel', '10.10.10.114', 3080),
('hk-planner', 'Rota Check', 'Housekeeping workload and hours planning', '/hk-planner', 'CalendarClock', '#2d6a4f', 'Housekeeping', '10.10.10.118', 3080),
@ -128,7 +128,8 @@ export async function initDb() {
('forecasting', 'Forecasting', 'Revenue forecasting and reporting', '/forecasting', 'TrendingUp', '#0077b6', 'Finance', '10.10.10.113', 3080),
('rates', 'Rate Monitor', 'Competitor rate monitoring and direct booking engine rates', '/rates', 'Tag', '#7b4f00', 'Finance', '10.10.10.115', 3080),
('maintenance', 'Maintenance', 'Maintenance log book — faults, recurring tasks, assets and contractors', '/maintenance', 'Wrench', '#b45309', 'Operations', '10.10.10.121', 3080),
('reports', 'Reports', 'Custom reports for NewBook, ResOS, SambaPOS and internal data', '/reports', 'BarChart2', '#1d4ed8', 'Management', '10.10.10.122', 3080)
('reports', 'Reports', 'Custom reports for NewBook, ResOS, SambaPOS and internal data', '/reports', 'BarChart2', '#1d4ed8', 'Management', '10.10.10.122', 3080),
('kds', 'Kitchen Display', 'SambaPOS ticket feed and course flow display', '/kds', 'Monitor', '#0d9488', 'Kitchen', '10.10.10.125', 3080)
ON CONFLICT (slug) DO UPDATE SET
name = EXCLUDED.name,
icon = EXCLUDED.icon,
@ -287,6 +288,61 @@ export async function initDb() {
sort_order = EXCLUDED.sort_order
`)
// Seed kitchen capabilities
await pool.query(`
INSERT INTO app_capabilities (app_id, slug, name, description, sort_order)
SELECT a.id, c.slug, c.name, c.description, c.sort_order
FROM apps a
CROSS JOIN (VALUES
('view', 'View app', 'Access the kitchen app and dashboard', 1),
('invoices', 'View invoices', 'View invoice list, details and search', 2),
('invoices_manage', 'Manage invoices', 'Upload, edit, approve and delete invoices', 3),
('disputes', 'Disputes', 'Open, manage and resolve invoice disputes', 4),
('logbook', 'Wastage logbook', 'Record and view wastage logbook entries', 5),
('orders', 'Purchase orders', 'Create and manage purchase orders', 6),
('recipes', 'Recipes', 'View and edit recipes, ingredients and allergens', 7),
('menus', 'Menus', 'Build, edit and publish menus and dishes', 8),
('manage_flags', 'Manage flags', 'Review and dismiss food compliance and allergen flags', 9),
('settings', 'Manage settings', 'App settings: integrations, API keys, SambaPOS config', 10)
) AS c(slug, name, description, sort_order)
WHERE a.slug = 'kitchen'
ON CONFLICT (app_id, slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
sort_order = EXCLUDED.sort_order
`)
// Seed KDS capabilities
await pool.query(`
INSERT INTO app_capabilities (app_id, slug, name, description, sort_order)
SELECT a.id, c.slug, c.name, c.description, c.sort_order
FROM apps a
CROSS JOIN (VALUES
('view', 'View board', 'View the KDS ticket board', 1),
('manage', 'Manage courses', 'Call away, mark sent and clear courses on live tickets', 2),
('settings', 'Manage settings', 'KDS timer thresholds, SambaPOS GraphQL config', 3)
) AS c(slug, name, description, sort_order)
WHERE a.slug = 'kds'
ON CONFLICT (app_id, slug) DO UPDATE SET
name = EXCLUDED.name,
description = EXCLUDED.description,
sort_order = EXCLUDED.sort_order
`)
// Grant Staff role KDS view + manage (needed during service; settings stays admin-only)
await pool.query(`
INSERT INTO role_capabilities (role_id, capability_id)
SELECT r.id, ac.id
FROM roles r
JOIN app_capabilities ac ON ac.app_id = (SELECT id FROM apps WHERE slug = 'kds')
WHERE r.slug = 'staff'
AND ac.slug IN ('view', 'manage')
AND NOT EXISTS (
SELECT 1 FROM role_capabilities rc WHERE rc.role_id = r.id AND rc.capability_id = ac.id
)
ON CONFLICT DO NOTHING
`)
// Seed first admin user if table is empty
const { rows } = await pool.query('SELECT COUNT(*) FROM users')
if (parseInt(rows[0].count) === 0) {