98 lines
3.2 KiB
JavaScript
98 lines
3.2 KiB
JavaScript
const SETTINGS_URL = process.env.SETTINGS_URL || 'http://10.10.10.106:3080'
|
|
const SETTINGS_SECRET = process.env.SETTINGS_SECRET || ''
|
|
|
|
let _credsCache = null // { creds, expires_at }
|
|
|
|
async function getWorkforceCreds() {
|
|
if (_credsCache && Date.now() < _credsCache.expires_at) return _credsCache.creds
|
|
const res = await fetch(`${SETTINGS_URL}/settings/api/internal/integration/workforce`, {
|
|
headers: { Authorization: `Bearer ${SETTINGS_SECRET}` },
|
|
signal: AbortSignal.timeout(5000),
|
|
})
|
|
if (!res.ok) throw new Error(`Failed to fetch Workforce credentials from settings: ${res.status}`)
|
|
const creds = await res.json()
|
|
if (!creds.bearer_token) throw new Error('Workforce bearer token not configured in settings')
|
|
_credsCache = { creds, expires_at: Date.now() + 5 * 60_000 }
|
|
return creds
|
|
}
|
|
|
|
async function wfFetch(path) {
|
|
const creds = await getWorkforceCreds()
|
|
const baseUrl = creds.base_url || 'https://my.workforce.com'
|
|
const res = await fetch(`${baseUrl}${path}`, {
|
|
headers: { Authorization: `Bearer ${creds.bearer_token}` },
|
|
signal: AbortSignal.timeout(10000),
|
|
})
|
|
if (!res.ok) {
|
|
const body = await res.text().catch(() => '')
|
|
throw new Error(`Workforce API error ${res.status} at ${path}${body ? ': ' + body.slice(0, 200) : ''}`)
|
|
}
|
|
return res.json()
|
|
}
|
|
|
|
async function wfFetchPaged(path) {
|
|
const results = []
|
|
let page = 1
|
|
while (true) {
|
|
const sep = path.includes('?') ? '&' : '?'
|
|
const data = await wfFetch(`${path}${sep}page=${page}&page_size=100`)
|
|
const items = Array.isArray(data) ? data : (data.users ?? data.departments ?? data.teams ?? data.locations ?? [])
|
|
results.push(...items)
|
|
if (items.length < 100) break
|
|
page++
|
|
}
|
|
return results
|
|
}
|
|
|
|
export async function findEmployeeByEmail(email) {
|
|
const data = await wfFetch(`/api/v2/users?email=${encodeURIComponent(email)}`)
|
|
const users = Array.isArray(data) ? data : (data.users ?? [])
|
|
return users.length > 0 ? users[0] : null
|
|
}
|
|
|
|
export async function findEmployeeById(wfUserId) {
|
|
try {
|
|
const data = await wfFetch(`/api/v2/users/${wfUserId}`)
|
|
return data?.id ? data : (data?.user ?? null)
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
export async function getLocationsByIds(ids) {
|
|
const results = await Promise.all(ids.map(async id => {
|
|
try {
|
|
const data = await wfFetch(`/api/v2/locations/${id}`)
|
|
return { id: String(id), name: data.name ?? `Location ${id}`, short_name: data.short_name ?? null }
|
|
} catch {
|
|
return { id: String(id), name: `Location ${id}`, short_name: null }
|
|
}
|
|
}))
|
|
return results
|
|
}
|
|
|
|
export async function getAllDepartments() {
|
|
return wfFetchPaged('/api/v2/departments')
|
|
}
|
|
|
|
export async function getEmployeeDepartments(wfUserId) {
|
|
const depts = await getAllDepartments()
|
|
const id = String(wfUserId)
|
|
return depts.filter(d => {
|
|
const staff = (d.staff ?? []).map(String)
|
|
const managers = (d.managers ?? []).map(String)
|
|
return staff.includes(id) || managers.includes(id)
|
|
})
|
|
}
|
|
|
|
export async function getSyncConfig() {
|
|
const creds = await getWorkforceCreds()
|
|
return {
|
|
syncHours: parseFloat(creds.sync_hours ?? '6'),
|
|
locationId: creds.location_id ? String(creds.location_id) : null,
|
|
}
|
|
}
|
|
|
|
export function invalidateCache() {
|
|
_credsCache = null
|
|
}
|