Populate machine-user assignments and template sync metadata from device discovery.

Upserts discovered users into attendance_machine_user
Updates attendance_machine.total_users
main
SYED MUSTUFA AHMED NAQVI 2026-04-14 17:21:42 +05:00
parent 33c2dfabb3
commit a5d0bc04c1
1 changed files with 57 additions and 1 deletions

View File

@ -9,6 +9,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using HikvisionAttendanceService.Data;
namespace HikvisionAttendanceService;
@ -25,7 +26,7 @@ internal sealed partial class HikvisionAttendanceManager
var key = DeviceIdentity.CanonicalLookupKey(deviceId);
if (key.Length == 0)
return null;
foreach (var d in _config.Devices ?? Enumerable.Empty<HikvisionAttendanceWindowsService.DeviceConfig>())
foreach (var d in ResolveRuntimeDevices() ?? Enumerable.Empty<HikvisionAttendanceWindowsService.DeviceConfig>())
{
if (DeviceIdentity.CanonicalLookupKey(d.DeviceId) == key)
return d;
@ -120,6 +121,18 @@ internal sealed partial class HikvisionAttendanceManager
var targetMap = targetUsers.ToDictionary(x => x.EmployeeNo, x => x, StringComparer.OrdinalIgnoreCase);
var initialTargetEmployeeIds = new HashSet<string>(targetUsers.Select(u => u.EmployeeNo),
StringComparer.OrdinalIgnoreCase);
HashSet<string>? assignedUsers = null;
if (_config.EnableDbIntegration && _attendanceMachineUserRepository != null)
{
var dbAssignments = _attendanceMachineUserRepository.GetActiveUsersByMachine(target.DeviceId ?? "", out var dbAssignErr);
if (!string.IsNullOrWhiteSpace(dbAssignErr))
_logger.Warn("UserSync DB assignment fetch failed target=" + target.DeviceId + " err=" + dbAssignErr);
else if (dbAssignments.Count > 0)
{
assignedUsers = new HashSet<string>(dbAssignments.Select(x => x.SerialNumber), StringComparer.OrdinalIgnoreCase);
_logger.JobInfo("user_sync", "Target " + target.DeviceId + " DB-assigned active users=" + assignedUsers.Count);
}
}
_logger.Info("UserSync: cycle=" + cycleId + " target=" + target.DeviceId + " existingUsers=" + targetUsers.Count);
@ -135,6 +148,8 @@ internal sealed partial class HikvisionAttendanceManager
foreach (var srcUser in sourceUsers)
{
ct.ThrowIfCancellationRequested();
if (assignedUsers != null && !assignedUsers.Contains(srcUser.EmployeeNo))
continue;
targetMap.TryGetValue(srcUser.EmployeeNo, out var tgtRow);
bool createdNew = false;
@ -186,6 +201,23 @@ internal sealed partial class HikvisionAttendanceManager
bool hasFaceBytes = faceBytesByEmployee.TryGetValue(srcUser.EmployeeNo, out var fb) && fb != null &&
fb.Length > 0;
string tplErr = "";
if (!hasFaceBytes &&
_config.EnableDbIntegration &&
_config.EnableTemplateDbToDeviceSync &&
_attendanceMachineFaceTemplateRepository != null &&
_attendanceMachineFaceTemplateRepository.TryGetActiveFaceTemplateBySerial(srcUser.EmployeeNo, out var tplRow, out tplErr) &&
tplRow != null &&
tplRow.Template != null &&
tplRow.Template.Length > 0)
{
fb = tplRow.Template;
hasFaceBytes = true;
}
else if (!hasFaceBytes && !string.IsNullOrWhiteSpace(tplErr))
{
_logger.Warn("UserSync template lookup failed employeeNo=" + srcUser.EmployeeNo + " err=" + tplErr);
}
if (!hasFaceBytes)
{
skipped++;
@ -238,6 +270,30 @@ internal sealed partial class HikvisionAttendanceManager
}
}
if (_config.EnableDbIntegration && _attendanceMachineUserRepository != null)
{
var pendingDeletionUsers = _attendanceMachineUserRepository.GetPendingDeletionUsersByMachine(target.DeviceId ?? "", out var pendingErr);
if (!string.IsNullOrWhiteSpace(pendingErr))
{
_logger.Warn("UserSync pending deletion fetch failed target=" + target.DeviceId + " err=" + pendingErr);
}
else if (pendingDeletionUsers.Count > 0)
{
var toDelete = pendingDeletionUsers.Select(x => x.SerialNumber).Where(x => !string.IsNullOrWhiteSpace(x)).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
string delErr2 = "";
if (toDelete.Count > 0 && TryDeleteUsersOnTarget(target, toDelete, maxRetries, ct, out delErr2))
{
foreach (var serial in toDelete)
_attendanceMachineUserRepository.MarkDeleted(target.DeviceId ?? "", serial, "hikvision-service", out _);
_logger.JobInfo("user_sync", "Target " + target.DeviceId + " DB deletion requests processed=" + toDelete.Count);
}
else if (toDelete.Count > 0)
{
_logger.Warn("UserSync DB-requested deletions failed target=" + target.DeviceId + " err=" + delErr2);
}
}
}
var statusLine = string.Join(", ", statusCounts.OrderBy(kv => kv.Key.ToString())
.Select(kv => kv.Key + "=" + kv.Value));
_logger.Info("UserSync: cycle=" + cycleId + " target=" + target.DeviceId + " summary created=" + created +