From 7b66f9319a1f85594434a557e46b7d6a6f134f09 Mon Sep 17 00:00:00 2001 From: "mustafa.ahmed" Date: Wed, 5 Aug 2026 15:39:34 +0500 Subject: [PATCH] Log face-template saves only for new inserts and pass updatedBy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Business-log “Saved successfully” only when a template is newly inserted; skip already-present templates in biz logs. Pass hikvision-service as updatedBy on user upserts. Show machine context in user-sync logs and clear is_deleted after device add Include Machine ID/IP on add/update/remove business logs. After a successful device user create, upsert the DB row so is_deleted returns to 0 with updated_by set. --- HikvisionAttendanceManager.UserSync.cs | 49 +++++++++++++++++++++++--- HikvisionAttendanceManager.cs | 38 +++++++++++++------- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/HikvisionAttendanceManager.UserSync.cs b/HikvisionAttendanceManager.UserSync.cs index f49c704..a792b1d 100644 --- a/HikvisionAttendanceManager.UserSync.cs +++ b/HikvisionAttendanceManager.UserSync.cs @@ -306,7 +306,33 @@ internal sealed partial class HikvisionAttendanceManager created++; _logger.Totals.UsersAdded++; - _logger.Biz(BizChannel.UserSync, srcUser.EmployeeNo + " added successfully.", ""); + _logger.Biz(BizChannel.UserSync, + "Machine ID : " + (target.DeviceId ?? ""), + "Machine IP : " + (target.Ip ?? ""), + "", + srcUser.EmployeeNo + " added successfully.", + ""); + // Clear is_deleted / is_deletion_requested so DB matches the live device user. + if (_config.EnableDbIntegration && _attendanceMachineUserRepository != null) + { + if (!_attendanceMachineUserRepository.UpsertMachineUser( + target.DeviceId ?? "", + srcUser.EmployeeNo, + srcUser.Name ?? "", + "hikvision-service", + out var upsertErr)) + { + _logger.Warn("UserSync: device add OK but DB is_deleted reset failed employeeNo=" + + srcUser.EmployeeNo + " machine_id=" + (target.DeviceId ?? "") + + " err=" + upsertErr); + } + else + { + _logger.Diag("user_sync", + "DB attendance_machine_user reactivated is_deleted=0 employeeNo=" + + srcUser.EmployeeNo + " machine_id=" + (target.DeviceId ?? "")); + } + } createdNew = true; tgtRow = new UserDto { @@ -323,7 +349,12 @@ internal sealed partial class HikvisionAttendanceManager { updated++; _logger.Totals.UsersUpdated++; - _logger.Biz(BizChannel.UserSync, srcUser.EmployeeNo + " updated successfully.", ""); + _logger.Biz(BizChannel.UserSync, + "Machine ID : " + (target.DeviceId ?? ""), + "Machine IP : " + (target.Ip ?? ""), + "", + srcUser.EmployeeNo + " updated successfully.", + ""); Bump(UserSyncStatus.ExistsUserFieldsUpdated); tgtRow.Name = srcUser.Name; tgtRow.ValidBeginTime = srcUser.ValidBeginTime; @@ -475,7 +506,12 @@ internal sealed partial class HikvisionAttendanceManager { _logger.Ops(OpsMarkers.UserDelete, emp + " -> Device " + target.DeviceId + " = DELETED SUCCESSFULLY"); _logger.Totals.UsersRemoved++; - _logger.Biz(BizChannel.UserSync, emp + " removed successfully.", ""); + _logger.Biz(BizChannel.UserSync, + "Machine ID : " + (target.DeviceId ?? ""), + "Machine IP : " + (target.Ip ?? ""), + "", + emp + " removed successfully.", + ""); Bump(UserSyncStatus.DeletedOnTargetNotInSource); } } @@ -592,7 +628,12 @@ internal sealed partial class HikvisionAttendanceManager deletedOk++; _logger.Totals.UsersRemoved++; _logger.Ops(OpsMarkers.UserDelete, employeeNo + " -> Device " + machineId + " = DELETED SUCCESSFULLY"); - _logger.Biz(BizChannel.UserSync, employeeNo + " removed successfully.", ""); + _logger.Biz(BizChannel.UserSync, + "Machine ID : " + machineId, + "Machine IP : " + machineIp, + "", + employeeNo + " removed successfully.", + ""); } else { diff --git a/HikvisionAttendanceManager.cs b/HikvisionAttendanceManager.cs index 0620f20..5cd82af 100644 --- a/HikvisionAttendanceManager.cs +++ b/HikvisionAttendanceManager.cs @@ -4315,7 +4315,7 @@ internal sealed partial class HikvisionAttendanceManager : IDisposable var serial = (eno ?? "").Trim(); if (serial.Length == 0) continue; - if (_attendanceMachineUserRepository.UpsertMachineUser(deviceId.Trim(), serial, "", out var upErr)) + if (_attendanceMachineUserRepository.UpsertMachineUser(deviceId.Trim(), serial, "", "hikvision-service", out var upErr)) upsertedUsers++; else upsertFailed++; @@ -4437,7 +4437,7 @@ internal sealed partial class HikvisionAttendanceManager : IDisposable if (_config.EnableDbIntegration && _attendanceMachineUserRepository != null && TryExtractNameFromUserInfoSearch(userInfoRaw, cardNo.Trim(), out var userName)) { - _attendanceMachineUserRepository.UpsertMachineUser(deviceId.Trim(), cardNo.Trim(), userName ?? "", out _); + _attendanceMachineUserRepository.UpsertMachineUser(deviceId.Trim(), cardNo.Trim(), userName ?? "", "hikvision-service", out _); } var facePath = userFaceUrl; @@ -4502,17 +4502,29 @@ internal sealed partial class HikvisionAttendanceManager : IDisposable var bytes = Convert.FromBase64String(userPayload.face.dataBase64); if (_attendanceMachineFaceTemplateRepository.UpsertFaceTemplate(cardNo.Trim(), bytes, DateTime.UtcNow, true, deviceId.Trim(), session.Device.Ip, out var createdNew, out var dbErr)) { - _logger.Ops(OpsMarkers.TemplateDeviceToDb, - cardNo.Trim() + " -> DB = FACE TEMPLATE " + (createdNew ? "INSERTED" : "UPDATED") + " SUCCESSFULLY"); - _logger.Totals.TemplatesSaved++; - _logger.Biz(BizChannel.Template, - "Employee " + cardNo.Trim(), - "", - "Face Template", - "", - "Saved successfully.", - ""); - _logger.BizSeparator(BizChannel.Template); + if (createdNew) + { + _logger.Ops(OpsMarkers.TemplateDeviceToDb, + cardNo.Trim() + " -> DB = FACE TEMPLATE INSERTED SUCCESSFULLY"); + _logger.Totals.TemplatesSaved++; + _logger.Biz(BizChannel.Template, + "Employee " + cardNo.Trim(), + "", + "Face Template", + "", + "Saved successfully.", + ""); + _logger.BizSeparator(BizChannel.Template); + } + else + { + // Already in DB — do not rewrite and do not spam business logs. + _logger.Diag("template_fetch", + "face template already in DB — skipped employee=" + cardNo.Trim() + + " device=" + deviceId); + _logger.Ops(OpsMarkers.TemplateDeviceToDb, + cardNo.Trim() + " -> DB = FACE TEMPLATE SKIPPED reason=\"already present\""); + } } else {