Log face-template saves only for new inserts and pass updatedBy

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.
main
SYED MUSTUFA AHMED NAQVI 2026-08-05 15:39:34 +05:00
parent e5a3689434
commit 7b66f9319a
2 changed files with 70 additions and 17 deletions

View File

@ -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
{

View File

@ -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
{