Populate machine-user assignments and template sync metadata from device discovery.
Upserts discovered users into attendance_machine_user Updates attendance_machine.total_usersmain
parent
33c2dfabb3
commit
a5d0bc04c1
|
|
@ -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 +
|
||||
|
|
|
|||
Loading…
Reference in New Issue