This commit is contained in:
2026-06-03 13:58:12 -05:00
commit 2f13b8c590
54 changed files with 5136 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
const { all, audit, json, now, one, parseJson, run, tx } = require('../db');
function employeeFromRow(row) {
if (!row) return null;
return {
...row,
source_payload: parseJson(row.source_payload, null)
};
}
function assignmentFromRow(row) {
if (!row) return null;
return {
...row,
active: !row.released_at
};
}
function listEmployees(query = {}) {
return all(`
SELECT *
FROM employees
WHERE (? IS NULL OR status = ?)
AND (? IS NULL OR name LIKE '%' || ? || '%' OR email LIKE '%' || ? || '%' OR employee_number LIKE '%' || ? || '%')
ORDER BY name
LIMIT 500
`, [
query.status || null,
query.status || null,
query.search || null,
query.search || null,
query.search || null,
query.search || null
]).map(employeeFromRow);
}
function upsertEmployee(employee) {
const timestamp = now();
const workdayId = employee.workday_worker_id || employee.workdayWorkerId || employee.workerId || null;
const existing = workdayId
? one('SELECT id FROM employees WHERE workday_worker_id = ?', [workdayId])
: one('SELECT id FROM employees WHERE employee_number = ? OR lower(email) = lower(?)', [employee.employee_number || '', employee.email || '']);
const values = [
workdayId,
employee.employee_number || employee.employeeNumber || employee.workerNumber || null,
employee.name || employee.fullName || [employee.firstName, employee.lastName].filter(Boolean).join(' ') || 'Unnamed employee',
employee.email || employee.workEmail || null,
employee.department || employee.organization || null,
employee.location || employee.workLocation || null,
employee.manager_name || employee.managerName || null,
employee.status || 'active',
employee.source || 'manual',
json(employee.source_payload || employee),
employee.last_synced_at || null,
timestamp
];
if (existing) {
run(
`UPDATE employees SET
workday_worker_id = COALESCE(?, workday_worker_id),
employee_number = ?,
name = ?,
email = ?,
department = ?,
location = ?,
manager_name = ?,
status = ?,
source = ?,
source_payload = ?,
last_synced_at = COALESCE(?, last_synced_at),
updated_at = ?
WHERE id = ?`,
[...values, existing.id]
);
return one('SELECT * FROM employees WHERE id = ?', [existing.id]);
}
const result = run(
`INSERT INTO employees (
workday_worker_id, employee_number, name, email, department, location, manager_name,
status, source, source_payload, last_synced_at, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[...values, timestamp]
);
return one('SELECT * FROM employees WHERE id = ?', [result.lastInsertRowid]);
}
function assignmentRows(query = {}) {
return all(`
SELECT aa.*, a.asset_id AS asset_code, a.description AS asset_description,
e.name AS employee_name, e.email AS employee_email, e.employee_number
FROM asset_assignments aa
JOIN assets a ON a.id = aa.asset_id
LEFT JOIN employees e ON e.id = aa.employee_id
WHERE (? IS NULL OR aa.asset_id = ?)
AND (? IS NULL OR aa.employee_id = ?)
AND (? IS NULL OR aa.released_at IS NULL)
ORDER BY aa.assigned_at DESC, aa.id DESC
LIMIT 500
`, [
query.asset_id || null,
query.asset_id || null,
query.employee_id || null,
query.employee_id || null,
query.active ? 1 : null
]).map(assignmentFromRow);
}
function assignAsset(body, userId) {
const timestamp = now();
const asset = one('SELECT * FROM assets WHERE id = ?', [body.asset_id]);
if (!asset) throw Object.assign(new Error('Asset not found'), { status: 404 });
const employee = body.employee_id ? one('SELECT * FROM employees WHERE id = ?', [body.employee_id]) : null;
const department = body.department ?? employee?.department ?? asset.department ?? null;
const location = body.location ?? employee?.location ?? asset.location ?? null;
return tx(() => {
run(
`UPDATE asset_assignments
SET released_at = ?, status = 'released', release_reason = 'Reassigned', updated_at = ?
WHERE asset_id = ? AND released_at IS NULL`,
[timestamp, timestamp, body.asset_id]
);
const result = run(
`INSERT INTO asset_assignments (
asset_id, employee_id, department, location, status, assigned_at, assigned_by, notes, created_at, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
body.asset_id,
body.employee_id || null,
department,
location,
'assigned',
body.assigned_at || timestamp,
userId,
body.notes || null,
timestamp,
timestamp
]
);
run(
`UPDATE assets SET
custodian = ?,
department = ?,
location = ?,
status = 'in_service',
updated_at = ?
WHERE id = ?`,
[employee?.name || asset.custodian || null, department, location, timestamp, body.asset_id]
);
const assignment = assignmentRows({ asset_id: body.asset_id, active: true })[0];
audit(userId, 'assign', 'asset', body.asset_id, null, assignment);
return assignment || one('SELECT * FROM asset_assignments WHERE id = ?', [result.lastInsertRowid]);
});
}
function releaseAssignment(id, body, userId) {
const before = one('SELECT * FROM asset_assignments WHERE id = ?', [id]);
if (!before) return null;
const timestamp = now();
run(
`UPDATE asset_assignments
SET released_at = ?, status = 'released', release_reason = ?, notes = COALESCE(?, notes), updated_at = ?
WHERE id = ?`,
[timestamp, body.release_reason || 'Released', body.notes || null, timestamp, id]
);
audit(userId, 'release_assignment', 'asset_assignment', id, before, { released_at: timestamp, ...body });
return assignmentRows({ asset_id: before.asset_id }).find((assignment) => assignment.id === Number(id));
}
function assignmentSummary() {
const stats = one(`
SELECT
COUNT(*) AS active_assignments,
COUNT(DISTINCT employee_id) AS assigned_employees,
COUNT(DISTINCT location) AS assigned_locations
FROM asset_assignments
WHERE released_at IS NULL
`);
const unassigned = one(`
SELECT COUNT(*) AS count
FROM assets a
WHERE NOT EXISTS (
SELECT 1 FROM asset_assignments aa
WHERE aa.asset_id = a.id AND aa.released_at IS NULL
)
`);
return { ...stats, unassigned_assets: unassigned.count };
}
module.exports = {
assignAsset,
assignmentRows,
assignmentSummary,
employeeFromRow,
listEmployees,
releaseAssignment,
upsertEmployee
};