Updated A LOT
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
const { audit, json, now, one, run } = require('../db');
|
||||
const { upsertEmployee } = require('./assignments');
|
||||
const { upsertWorkdayContact } = require('./contacts');
|
||||
|
||||
function publicConnection(row) {
|
||||
if (!row) return null;
|
||||
@@ -12,12 +13,21 @@ function publicConnection(row) {
|
||||
client_id: row.client_id,
|
||||
workers_path: row.workers_path,
|
||||
enabled: Boolean(row.enabled),
|
||||
sync_enabled: Boolean(row.sync_enabled),
|
||||
sync_interval_hours: row.sync_interval_hours || 24,
|
||||
last_sync_at: row.last_sync_at,
|
||||
last_sync_status: row.last_sync_status,
|
||||
configured: Boolean(row.base_url && row.token_url && row.client_id && row.client_secret)
|
||||
};
|
||||
}
|
||||
|
||||
function splitName(full) {
|
||||
const parts = String(full || '').trim().split(/\s+/).filter(Boolean);
|
||||
if (!parts.length) return { first: null, last: null };
|
||||
if (parts.length === 1) return { first: parts[0], last: null };
|
||||
return { first: parts[0], last: parts.slice(1).join(' ') };
|
||||
}
|
||||
|
||||
function getConnection() {
|
||||
return publicConnection(one('SELECT * FROM workday_connections ORDER BY id LIMIT 1'));
|
||||
}
|
||||
@@ -37,23 +47,25 @@ function saveConnection(body, userId) {
|
||||
client_id: body.client_id ?? existing?.client_id ?? '',
|
||||
client_secret: body.client_secret ? body.client_secret : existing?.client_secret ?? '',
|
||||
workers_path: body.workers_path ?? existing?.workers_path ?? '/workers',
|
||||
enabled: body.enabled === undefined ? Number(existing?.enabled || 0) : (body.enabled ? 1 : 0)
|
||||
enabled: body.enabled === undefined ? Number(existing?.enabled || 0) : (body.enabled ? 1 : 0),
|
||||
sync_enabled: body.sync_enabled === undefined ? Number(existing?.sync_enabled || 0) : (body.sync_enabled ? 1 : 0),
|
||||
sync_interval_hours: body.sync_interval_hours === undefined ? (existing?.sync_interval_hours || 24) : Math.max(1, Number(body.sync_interval_hours) || 24)
|
||||
};
|
||||
|
||||
if (existing) {
|
||||
run(
|
||||
`UPDATE workday_connections SET
|
||||
name = ?, tenant = ?, base_url = ?, token_url = ?, client_id = ?, client_secret = ?,
|
||||
workers_path = ?, enabled = ?, updated_at = ?
|
||||
workers_path = ?, enabled = ?, sync_enabled = ?, sync_interval_hours = ?, updated_at = ?
|
||||
WHERE id = ?`,
|
||||
[payload.name, payload.tenant, payload.base_url, payload.token_url, payload.client_id, payload.client_secret, payload.workers_path, payload.enabled, timestamp, existing.id]
|
||||
[payload.name, payload.tenant, payload.base_url, payload.token_url, payload.client_id, payload.client_secret, payload.workers_path, payload.enabled, payload.sync_enabled, payload.sync_interval_hours, timestamp, existing.id]
|
||||
);
|
||||
} else {
|
||||
run(
|
||||
`INSERT INTO workday_connections (
|
||||
name, tenant, base_url, token_url, client_id, client_secret, workers_path, enabled, created_at, updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[payload.name, payload.tenant, payload.base_url, payload.token_url, payload.client_id, payload.client_secret, payload.workers_path, payload.enabled, timestamp, timestamp]
|
||||
name, tenant, base_url, token_url, client_id, client_secret, workers_path, enabled, sync_enabled, sync_interval_hours, created_at, updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[payload.name, payload.tenant, payload.base_url, payload.token_url, payload.client_id, payload.client_secret, payload.workers_path, payload.enabled, payload.sync_enabled, payload.sync_interval_hours, timestamp, timestamp]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -85,19 +97,31 @@ function normalizeWorkers(payload) {
|
||||
? payload
|
||||
: payload.workers || payload.Workers || payload.data || payload.value || [];
|
||||
|
||||
return rows.map((worker) => ({
|
||||
workday_worker_id: worker.id || worker.workerId || worker.worker_id || worker.Worker_ID || worker.workerReference?.id,
|
||||
employee_number: worker.employeeNumber || worker.employee_number || worker.Worker_ID || worker.workerNumber,
|
||||
name: worker.name || worker.fullName || worker.Full_Name || worker.descriptor || [worker.firstName, worker.lastName].filter(Boolean).join(' '),
|
||||
email: worker.email || worker.workEmail || worker.primaryWorkEmail || worker.Email,
|
||||
department: worker.department || worker.organization || worker.Department || worker.supervisoryOrganization?.descriptor,
|
||||
location: worker.location || worker.workLocation || worker.Location || worker.location?.descriptor,
|
||||
manager_name: worker.managerName || worker.manager?.descriptor,
|
||||
status: worker.status || (worker.active === false ? 'inactive' : 'active'),
|
||||
source: 'workday',
|
||||
source_payload: worker,
|
||||
last_synced_at: now()
|
||||
}));
|
||||
return rows.map((worker) => {
|
||||
const name = worker.name || worker.fullName || worker.Full_Name || worker.descriptor || [worker.firstName, worker.lastName].filter(Boolean).join(' ');
|
||||
const fallbackName = splitName(name);
|
||||
const managerName = worker.managerName || worker.manager?.descriptor;
|
||||
const managerSplit = splitName(managerName);
|
||||
return {
|
||||
workday_worker_id: worker.id || worker.workerId || worker.worker_id || worker.Worker_ID || worker.workerReference?.id,
|
||||
employee_number: worker.employeeNumber || worker.employee_number || worker.Worker_ID || worker.workerNumber,
|
||||
name,
|
||||
first_name: worker.firstName || worker.legalFirstName || worker.First_Name || fallbackName.first,
|
||||
last_name: worker.lastName || worker.legalLastName || worker.Last_Name || fallbackName.last,
|
||||
email: worker.email || worker.workEmail || worker.primaryWorkEmail || worker.Email,
|
||||
department: worker.department || worker.organization || worker.Department || worker.supervisoryOrganization?.descriptor,
|
||||
location: worker.location || worker.workLocation || worker.Location || worker.location?.descriptor,
|
||||
manager_name: managerName,
|
||||
manager_first_name: worker.manager?.firstName || managerSplit.first,
|
||||
manager_last_name: worker.manager?.lastName || managerSplit.last,
|
||||
manager_email: worker.managerEmail || worker.manager?.email,
|
||||
start_date: worker.hireDate || worker.startDate || worker.Hire_Date || worker.continuousServiceDate,
|
||||
status: worker.status || (worker.active === false ? 'inactive' : 'active'),
|
||||
source: 'workday',
|
||||
source_payload: worker,
|
||||
last_synced_at: now()
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function syncWorkers(userId) {
|
||||
@@ -120,7 +144,10 @@ async function syncWorkers(userId) {
|
||||
}
|
||||
|
||||
const workers = normalizeWorkers(await response.json());
|
||||
for (const worker of workers) upsertEmployee(worker);
|
||||
for (const worker of workers) {
|
||||
upsertEmployee(worker);
|
||||
upsertWorkdayContact(worker);
|
||||
}
|
||||
|
||||
const timestamp = now();
|
||||
run('UPDATE workday_connections SET last_sync_at = ?, last_sync_status = ?, updated_at = ? WHERE id = ?', [
|
||||
@@ -135,14 +162,30 @@ async function syncWorkers(userId) {
|
||||
|
||||
function importWorkersFromPayload(workers, userId) {
|
||||
const normalized = normalizeWorkers(workers);
|
||||
for (const worker of normalized) upsertEmployee(worker);
|
||||
for (const worker of normalized) {
|
||||
upsertEmployee(worker);
|
||||
upsertWorkdayContact(worker);
|
||||
}
|
||||
audit(userId, 'import', 'workday_workers', null, null, { imported: normalized.length, source: 'payload' });
|
||||
return { imported: normalized.length };
|
||||
}
|
||||
|
||||
// Run an automatic sync if it's enabled, configured, and the interval has elapsed.
|
||||
async function runScheduledSync() {
|
||||
const connection = getPrivateConnection();
|
||||
if (!connection || !connection.sync_enabled || !connection.enabled) return { skipped: true };
|
||||
if (!connection.base_url || !connection.token_url || !connection.client_id || !connection.client_secret) return { skipped: true };
|
||||
const intervalMs = (Number(connection.sync_interval_hours) || 24) * 3600000;
|
||||
if (connection.last_sync_at && Date.now() - new Date(connection.last_sync_at).getTime() < intervalMs) {
|
||||
return { skipped: true };
|
||||
}
|
||||
return syncWorkers(null);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getConnection,
|
||||
importWorkersFromPayload,
|
||||
runScheduledSync,
|
||||
saveConnection,
|
||||
syncWorkers
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user