Workforce: add location_id config field + locations fetch endpoint

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-07 12:52:35 +00:00
parent 24f3fcdc7b
commit db1b168300
2 changed files with 26 additions and 1 deletions

View file

@ -112,6 +112,31 @@ export async function integrationRoutes(app) {
})
// POST /settings/api/integrations/newbook/sync-rooms
// GET /settings/api/integrations/workforce/locations — fetch location list from Tanda for the picker
app.get('/integrations/workforce/locations', { preHandler: requireAdmin }, async (req, reply) => {
const { rows: [row] } = await pool.query(`SELECT * FROM integrations WHERE slug = 'workforce'`)
if (!row?.enabled) return reply.status(400).send({ error: 'Workforce integration not enabled' })
const creds = { ...row.config, ...decryptSecrets(row) }
if (!creds.bearer_token) return reply.status(400).send({ error: 'Workforce bearer token not configured' })
const baseUrl = creds.base_url || 'https://my.tanda.co'
const locations = []
let page = 1
while (true) {
const res = await fetch(`${baseUrl}/api/v2/locations?page=${page}&page_size=100`, {
headers: { Authorization: `Bearer ${creds.bearer_token}` },
signal: AbortSignal.timeout(8000),
})
if (!res.ok) return reply.status(502).send({ error: `Workforce API error (${res.status})` })
const data = await res.json()
const items = Array.isArray(data) ? data : (data.locations ?? [])
locations.push(...items.map(l => ({ id: String(l.id), name: l.name, short_name: l.short_name ?? null })))
if (items.length < 100) break
page++
}
return locations
})
app.post('/integrations/newbook/sync-rooms', { preHandler: requireAdmin }, async (req, reply) => {
const { rows: [row] } = await pool.query(`SELECT * FROM integrations WHERE slug = 'newbook'`)
if (!row?.enabled) return reply.status(400).send({ error: 'Newbook integration not enabled' })