feat: add app_config table with runtime log level control and POS structured logging
All checks were successful
CI / ci (pull_request) Successful in 20s
CI / e2e (pull_request) Successful in 56s

- New app_config key-value table for system settings, with in-memory cache (mirrors ModuleService pattern)
- GET/PATCH /v1/config endpoints for reading and updating config (settings.view/settings.edit permissions)
- Runtime log level: PATCH /v1/config/log_level applies immediately, persists across restarts
- Startup loads log level from DB in onReady hook (env var is default, DB overrides)
- Add structured request.log.info() to POS routes: transaction create/complete/void, drawer open/close, discount create/update/delete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
ryan
2026-04-04 18:56:21 +00:00
parent 51e7902ee2
commit 772d5578ad
11 changed files with 154 additions and 0 deletions

View File

@@ -15,6 +15,7 @@ export const transactionRoutes: FastifyPluginAsync = async (app) => {
return reply.status(400).send({ error: { message: 'Validation failed', details: parsed.error.flatten(), statusCode: 400 } })
}
const txn = await TransactionService.create(app.db, parsed.data, request.user.id)
request.log.info({ transactionId: txn.id, type: parsed.data.transactionType, userId: request.user.id }, 'Transaction created')
return reply.status(201).send(txn)
})
@@ -80,6 +81,7 @@ export const transactionRoutes: FastifyPluginAsync = async (app) => {
}
await TransactionService.complete(app.db, id, parsed.data)
const txn = await TransactionService.getById(app.db, id)
request.log.info({ transactionId: id, paymentMethod: parsed.data.paymentMethod, userId: request.user.id }, 'Transaction completed')
return reply.send(txn)
})
@@ -87,6 +89,7 @@ export const transactionRoutes: FastifyPluginAsync = async (app) => {
const { id } = request.params as { id: string }
await TransactionService.void(app.db, id, request.user.id)
const txn = await TransactionService.getById(app.db, id)
request.log.info({ transactionId: id, voidedBy: request.user.id }, 'Transaction voided')
return reply.send(txn)
})
}