true,
'brands' => []
]);
}
$stmt = $db->prepare("
SELECT idbrand, brand_name, status
FROM brands
WHERE idcompany = :idcompany
ORDER BY brand_name ASC
");
$stmt->execute([':idcompany' => $idcompany]);
jsonResponse([
'success' => true,
'brands' => $stmt->fetchAll(PDO::FETCH_ASSOC)
]);
}
if ($action === 'get_departments_by_company_brand') {
$idcompany = isset($_POST['idcompany']) ? (int) $_POST['idcompany'] : 0;
$idbrand = !empty($_POST['idbrand']) ? (int) $_POST['idbrand'] : null;
if ($idcompany <= 0) {
jsonResponse([
'success' => true,
'departments' => []
]);
}
if ($idbrand !== null) {
$stmt = $db->prepare("
SELECT iddepartment, department_name, status
FROM departments
WHERE idcompany = :idcompany
AND (idbrand = :idbrand OR idbrand IS NULL)
ORDER BY department_name ASC
");
$stmt->execute([
':idcompany' => $idcompany,
':idbrand' => $idbrand,
]);
} else {
$stmt = $db->prepare("
SELECT iddepartment, department_name, status
FROM departments
WHERE idcompany = :idcompany
ORDER BY department_name ASC
");
$stmt->execute([':idcompany' => $idcompany]);
}
jsonResponse([
'success' => true,
'departments' => $stmt->fetchAll(PDO::FETCH_ASSOC)
]);
}
if ($action === 'save_company_user') {
$idcompanyuser = isset($_POST['idcompanyuser']) ? (int) $_POST['idcompanyuser'] : 0;
$iduser = isset($_POST['iduser']) ? (int) $_POST['iduser'] : 0;
$idcompany = isset($_POST['idcompany']) ? (int) $_POST['idcompany'] : 0;
$idbrand = !empty($_POST['idbrand']) ? (int) $_POST['idbrand'] : null;
$iddepartment = !empty($_POST['iddepartment']) ? (int) $_POST['iddepartment'] : null;
$userScope = $_POST['user_scope'] ?? 'company';
$companyRole = $_POST['company_role'] ?? 'viewer';
$status = $_POST['status'] ?? 'active';
$allowedScopes = ['company', 'brand', 'department'];
$allowedRoles = ['owner', 'admin', 'manager', 'operator', 'viewer', 'api_user', 'lab_user'];
$allowedStatuses = ['active', 'inactive'];
if ($iduser <= 0) {
jsonResponse([
'success' => false,
'message' => 'User is required.'
]);
}
if ($idcompany <= 0) {
jsonResponse([
'success' => false,
'message' => 'Company is required.'
]);
}
if (!in_array($userScope, $allowedScopes, true)) {
$userScope = 'company';
}
if (!in_array($companyRole, $allowedRoles, true)) {
$companyRole = 'viewer';
}
if (!in_array($status, $allowedStatuses, true)) {
$status = 'active';
}
/*
* Scope consistency.
*/
if ($userScope === 'company') {
$idbrand = null;
$iddepartment = null;
}
if ($userScope === 'brand') {
if ($idbrand === null) {
jsonResponse([
'success' => false,
'message' => 'Brand is required for brand scope.'
]);
}
$iddepartment = null;
}
if ($userScope === 'department') {
if ($iddepartment === null) {
jsonResponse([
'success' => false,
'message' => 'Department is required for department scope.'
]);
}
}
/*
* Check Vanguard user exists.
*/
$stmt = $db->prepare("
SELECT COUNT(*)
FROM auth_users
WHERE id = :iduser
");
$stmt->execute([':iduser' => $iduser]);
if ((int) $stmt->fetchColumn() === 0) {
jsonResponse([
'success' => false,
'message' => 'Selected Vanguard user does not exist.'
]);
}
/*
* Check company exists.
*/
$stmt = $db->prepare("
SELECT COUNT(*)
FROM companies
WHERE idcompany = :idcompany
");
$stmt->execute([':idcompany' => $idcompany]);
if ((int) $stmt->fetchColumn() === 0) {
jsonResponse([
'success' => false,
'message' => 'Selected company does not exist.'
]);
}
/*
* Check brand belongs to company.
*/
if ($idbrand !== null) {
$stmt = $db->prepare("
SELECT COUNT(*)
FROM brands
WHERE idbrand = :idbrand
AND idcompany = :idcompany
");
$stmt->execute([
':idbrand' => $idbrand,
':idcompany' => $idcompany,
]);
if ((int) $stmt->fetchColumn() === 0) {
jsonResponse([
'success' => false,
'message' => 'Selected brand does not belong to the selected company.'
]);
}
}
/*
* Check department belongs to company and, if brand is selected, is compatible.
*/
if ($iddepartment !== null) {
if ($idbrand !== null) {
$stmt = $db->prepare("
SELECT COUNT(*)
FROM departments
WHERE iddepartment = :iddepartment
AND idcompany = :idcompany
AND (idbrand = :idbrand OR idbrand IS NULL)
");
$stmt->execute([
':iddepartment' => $iddepartment,
':idcompany' => $idcompany,
':idbrand' => $idbrand,
]);
} else {
$stmt = $db->prepare("
SELECT COUNT(*)
FROM departments
WHERE iddepartment = :iddepartment
AND idcompany = :idcompany
");
$stmt->execute([
':iddepartment' => $iddepartment,
':idcompany' => $idcompany,
]);
}
if ((int) $stmt->fetchColumn() === 0) {
jsonResponse([
'success' => false,
'message' => 'Selected department is not compatible with the selected company/brand.'
]);
}
}
/*
* Check duplicate assignment.
*/
if ($idcompanyuser > 0) {
$stmt = $db->prepare("
SELECT COUNT(*)
FROM company_users
WHERE iduser = :iduser
AND idcompany = :idcompany
AND (
(idbrand IS NULL AND :idbrand_null = 1)
OR idbrand = :idbrand
)
AND (
(iddepartment IS NULL AND :iddepartment_null = 1)
OR iddepartment = :iddepartment
)
AND idcompanyuser <> :idcompanyuser
");
$stmt->execute([
':iduser' => $iduser,
':idcompany' => $idcompany,
':idbrand' => $idbrand,
':idbrand_null' => $idbrand === null ? 1 : 0,
':iddepartment' => $iddepartment,
':iddepartment_null' => $iddepartment === null ? 1 : 0,
':idcompanyuser' => $idcompanyuser,
]);
} else {
$stmt = $db->prepare("
SELECT COUNT(*)
FROM company_users
WHERE iduser = :iduser
AND idcompany = :idcompany
AND (
(idbrand IS NULL AND :idbrand_null = 1)
OR idbrand = :idbrand
)
AND (
(iddepartment IS NULL AND :iddepartment_null = 1)
OR iddepartment = :iddepartment
)
");
$stmt->execute([
':iduser' => $iduser,
':idcompany' => $idcompany,
':idbrand' => $idbrand,
':idbrand_null' => $idbrand === null ? 1 : 0,
':iddepartment' => $iddepartment,
':iddepartment_null' => $iddepartment === null ? 1 : 0,
]);
}
if ((int) $stmt->fetchColumn() > 0) {
jsonResponse([
'success' => false,
'message' => 'This user already has the same assignment.'
]);
}
if ($idcompanyuser > 0) {
$sql = "
UPDATE company_users
SET
iduser = :iduser,
idcompany = :idcompany,
idbrand = :idbrand,
iddepartment = :iddepartment,
user_scope = :user_scope,
company_role = :company_role,
status = :status,
updated_at = NOW()
WHERE idcompanyuser = :idcompanyuser
";
$stmt = $db->prepare($sql);
$stmt->execute([
':iduser' => $iduser,
':idcompany' => $idcompany,
':idbrand' => $idbrand,
':iddepartment' => $iddepartment,
':user_scope' => $userScope,
':company_role' => $companyRole,
':status' => $status,
':idcompanyuser' => $idcompanyuser,
]);
jsonResponse([
'success' => true,
'message' => 'User assignment updated successfully.'
]);
}
$sql = "
INSERT INTO company_users (
iduser,
idcompany,
idbrand,
iddepartment,
user_scope,
company_role,
status,
created_at,
updated_at
) VALUES (
:iduser,
:idcompany,
:idbrand,
:iddepartment,
:user_scope,
:company_role,
:status,
NOW(),
NOW()
)
";
$stmt = $db->prepare($sql);
$stmt->execute([
':iduser' => $iduser,
':idcompany' => $idcompany,
':idbrand' => $idbrand,
':iddepartment' => $iddepartment,
':user_scope' => $userScope,
':company_role' => $companyRole,
':status' => $status,
]);
jsonResponse([
'success' => true,
'message' => 'User assigned successfully.'
]);
}
if ($action === 'get_company_user') {
$idcompanyuser = isset($_POST['idcompanyuser']) ? (int) $_POST['idcompanyuser'] : 0;
if ($idcompanyuser <= 0) {
jsonResponse([
'success' => false,
'message' => 'Invalid assignment id.'
]);
}
$stmt = $db->prepare("
SELECT *
FROM company_users
WHERE idcompanyuser = :idcompanyuser
LIMIT 1
");
$stmt->execute([':idcompanyuser' => $idcompanyuser]);
$companyUser = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$companyUser) {
jsonResponse([
'success' => false,
'message' => 'Assignment not found.'
]);
}
jsonResponse([
'success' => true,
'company_user' => $companyUser
]);
}
if ($action === 'change_status') {
$idcompanyuser = isset($_POST['idcompanyuser']) ? (int) $_POST['idcompanyuser'] : 0;
$status = $_POST['status'] ?? 'inactive';
$allowedStatuses = ['active', 'inactive'];
if ($idcompanyuser <= 0 || !in_array($status, $allowedStatuses, true)) {
jsonResponse([
'success' => false,
'message' => 'Invalid request.'
]);
}
$stmt = $db->prepare("
UPDATE company_users
SET status = :status, updated_at = NOW()
WHERE idcompanyuser = :idcompanyuser
");
$stmt->execute([
':status' => $status,
':idcompanyuser' => $idcompanyuser,
]);
jsonResponse([
'success' => true,
'message' => 'Assignment status updated successfully.'
]);
}
if ($action === 'delete_company_user') {
$idcompanyuser = isset($_POST['idcompanyuser']) ? (int) $_POST['idcompanyuser'] : 0;
if ($idcompanyuser <= 0) {
jsonResponse([
'success' => false,
'message' => 'Invalid assignment id.'
]);
}
$stmt = $db->prepare("
DELETE FROM company_users
WHERE idcompanyuser = :idcompanyuser
");
$stmt->execute([':idcompanyuser' => $idcompanyuser]);
jsonResponse([
'success' => true,
'message' => 'User assignment deleted successfully.'
]);
}
jsonResponse([
'success' => false,
'message' => 'Unknown action.'
]);
} catch (Throwable $e) {
jsonResponse([
'success' => false,
'message' => $e->getMessage()
]);
}
}
/*
* Page data
*/
$users = [];
try {
$stmt = $db->query("
SELECT
u.id,
u.email,
u.first_name,
u.last_name,
u.username,
u.status,
r.display_name AS role_display_name,
r.name AS role_name
FROM auth_users u
LEFT JOIN auth_roles r ON r.id = u.role_id
ORDER BY u.first_name ASC, u.last_name ASC, u.email ASC
");
$users = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
$users = [];
}
$companies = [];
try {
$stmt = $db->query("
SELECT idcompany, company_name, status
FROM companies
ORDER BY company_name ASC
");
$companies = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
$companies = [];
}
$brands = [];
try {
$stmt = $db->query("
SELECT idbrand, idcompany, brand_name, status
FROM brands
ORDER BY brand_name ASC
");
$brands = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
$brands = [];
}
$departments = [];
try {
$stmt = $db->query("
SELECT iddepartment, idcompany, idbrand, department_name, status
FROM departments
ORDER BY department_name ASC
");
$departments = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
$departments = [];
}
$assignments = [];
try {
$stmt = $db->query("
SELECT
cu.idcompanyuser,
cu.iduser,
cu.idcompany,
cu.idbrand,
cu.iddepartment,
cu.user_scope,
cu.company_role,
cu.status,
cu.created_at,
u.email,
u.first_name,
u.last_name,
u.username,
u.status AS user_status,
r.display_name AS vanguard_role,
c.company_name,
c.status AS company_status,
b.brand_name,
b.status AS brand_status,
d.department_name,
d.status AS department_status
FROM company_users cu
INNER JOIN auth_users u ON u.id = cu.iduser
LEFT JOIN auth_roles r ON r.id = u.role_id
INNER JOIN companies c ON c.idcompany = cu.idcompany
LEFT JOIN brands b ON b.idbrand = cu.idbrand
LEFT JOIN departments d ON d.iddepartment = cu.iddepartment
ORDER BY c.company_name ASC, u.first_name ASC, u.last_name ASC, u.email ASC
");
$assignments = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {
$assignments = [];
}
$pageTitle = 'Company Users';
?>
= e($pageTitle); ?> - = isset($titlewebsite) ? e($titlewebsite) : 'TRFgo'; ?>
TRFgo Access Control
Company Users
Link Vanguard users to TRFgo companies, brands and departments.
Vanguard remains responsible for authentication; this page defines operational access and data visibility.
Assign User
$row['status'] === 'active'));
$companyScopeCount = count(array_filter($assignments, fn($row) => $row['user_scope'] === 'company'));
$departmentScopeCount = count(array_filter($assignments, fn($row) => $row['user_scope'] === 'department'));
?>
Assignments
= e($totalAssignments); ?>
Active
= e($activeAssignments); ?>
Company Scope
= e($companyScopeCount); ?>
Department Scope
= e($departmentScopeCount); ?>
No companies available.
Create at least one company before assigning users.
No Vanguard users available.
Create users in Vanguard before assigning TRFgo access.
User
Company
Scope
Role
Vanguard Role
Status
Created
Actions
= e($fullName); ?>
= e($assignment['email']); ?>
= e($assignment['company_name']); ?>
Company status: = e($assignment['company_status']); ?>
Company
Full company visibility
Brand
= e($assignment['brand_name'] ?: '-'); ?>
Department
= e($assignment['department_name'] ?: '-'); ?>
/ = e($assignment['brand_name']); ?>
= e($roleLabel); ?>
= !empty($assignment['vanguard_role']) ? e($assignment['vanguard_role']) : '- '; ?>
Active
Inactive
= !empty($assignment['created_at']) ? e(date('d/m/Y', strtotime($assignment['created_at']))) : '-'; ?>