add editable menu items for companies

This commit is contained in:
root
2026-06-03 20:06:41 -04:00
parent e6110d7faa
commit e0b2239f66
13 changed files with 2881 additions and 5 deletions
@@ -4,6 +4,7 @@ import { parseBody, parseQuery, parseParams } from '../../http/validate'
import { ok, created } from '../../http/respond'
import * as service from './admin.service'
import * as subService from '../subscriptions/subscription.service'
import * as menuService from '../menu/menu.service'
import { presentAdminUser } from './admin.presenter'
import {
loginSchema, forgotPasswordSchema, resetPasswordSchema, totpVerifySchema,
@@ -16,6 +17,8 @@ import {
promotionCreateSchema, promotionUpdateSchema, promotionIdParamSchema,
billingAccountUpdateSchema, createBillingInvoiceSchema, payBillingInvoiceSchema,
retryBillingInvoiceSchema, billingReasonSchema, billingCreditNoteSchema, billingRefundSchema,
menuItemSchema, menuItemStatusSchema, menuPlanAssignmentsSchema, menuCompanyAssignmentsSchema,
menuPreviewSchema, menuAuditLogQuerySchema, menuPlanParamSchema, menuCompanyParamSchema,
} from './admin.schemas'
import { z } from 'zod'
@@ -127,6 +130,92 @@ router.post('/companies/:id/impersonate', requireAdminAuth, requireAdminRole('AD
} catch (err) { next(err) }
})
// ─── Menu management ──────────────────────────────────────────
router.get('/menu-items', requireAdminAuth, requireAdminRole('SUPPORT'), async (_req, res, next) => {
try {
ok(res, await menuService.listMenuItems())
} catch (err) { next(err) }
})
router.post('/menu-items', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
created(res, { data: await menuService.createMenuItem(parseBody(menuItemSchema, req), req.admin) })
} catch (err) { next(err) }
})
router.get('/menu-items/:id', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
try {
const { id } = parseParams(idParamSchema, req)
ok(res, await menuService.getMenuItem(id))
} catch (err) { next(err) }
})
router.put('/menu-items/:id', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id } = parseParams(idParamSchema, req)
ok(res, await menuService.updateMenuItem(id, parseBody(menuItemSchema, req), req.admin))
} catch (err) { next(err) }
})
router.patch('/menu-items/:id/status', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id } = parseParams(idParamSchema, req)
const { isActive } = parseBody(menuItemStatusSchema, req)
ok(res, await menuService.setMenuItemStatus(id, isActive, req.admin))
} catch (err) { next(err) }
})
router.delete('/menu-items/:id', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id } = parseParams(idParamSchema, req)
await menuService.deleteMenuItem(id, req.admin)
ok(res, { success: true })
} catch (err) { next(err) }
})
router.post('/menu-items/:id/subscriptions', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id } = parseParams(idParamSchema, req)
const { assignments } = parseBody(menuPlanAssignmentsSchema, req)
ok(res, await menuService.assignMenuItemToPlans(id, assignments, req.admin))
} catch (err) { next(err) }
})
router.delete('/menu-items/:id/subscriptions/:plan', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id, plan } = parseParams(menuPlanParamSchema, req)
ok(res, await menuService.removeMenuItemFromPlan(id, plan, req.admin))
} catch (err) { next(err) }
})
router.post('/menu-items/:id/companies', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id } = parseParams(idParamSchema, req)
const { assignments } = parseBody(menuCompanyAssignmentsSchema, req)
ok(res, await menuService.assignMenuItemToCompanies(id, assignments, req.admin))
} catch (err) { next(err) }
})
router.delete('/menu-items/:id/companies/:companyId', requireAdminAuth, requireAdminRole('ADMIN'), async (req, res, next) => {
try {
const { id, companyId } = parseParams(menuCompanyParamSchema, req)
ok(res, await menuService.removeMenuItemFromCompany(id, companyId, req.admin))
} catch (err) { next(err) }
})
router.post('/menu-preview', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
try {
ok(res, await menuService.previewCompanyMenu(parseBody(menuPreviewSchema, req)))
} catch (err) { next(err) }
})
router.get('/menu-audit-logs', requireAdminAuth, requireAdminRole('SUPPORT'), async (req, res, next) => {
try {
ok(res, await menuService.listMenuAuditLogs(parseQuery(menuAuditLogQuerySchema, req)))
} catch (err) { next(err) }
})
// ─── Renters ───────────────────────────────────────────────────
router.get('/renters', requireAdminAuth, async (req, res, next) => {