diff --git a/Data/MySqlRepositories.cs b/Data/MySqlRepositories.cs index 1bebc4e..8555d8b 100644 --- a/Data/MySqlRepositories.cs +++ b/Data/MySqlRepositories.cs @@ -261,7 +261,7 @@ internal sealed class MySqlAttendanceMachineUserRepository : IAttendanceMachineU return rows; } - public bool UpsertMachineUser(string machineId, string serialNumber, string employeeName, out string error) + public bool UpsertMachineUser(string machineId, string serialNumber, string employeeName, string updatedBy, out string error) { error = ""; if (!_factory.TryBuildConnectionString(out var cs, out error)) @@ -271,11 +271,12 @@ internal sealed class MySqlAttendanceMachineUserRepository : IAttendanceMachineU using var conn = new MySqlConnection(cs); conn.Open(); using var cmd = new MySqlCommand( - "REPLACE INTO attendance_machine_user (machine_id,serial_number,employee_name,is_deleted,is_deletion_requested,updated_at) " + - "VALUES (@machine_id,@serial_number,@employee_name,0,0,NOW())", conn); + "REPLACE INTO attendance_machine_user (machine_id,serial_number,employee_name,is_deleted,is_deletion_requested,updated_by,updated_at) " + + "VALUES (@machine_id,@serial_number,@employee_name,0,0,@updated_by,NOW())", conn); cmd.Parameters.AddWithValue("@machine_id", machineId ?? ""); cmd.Parameters.AddWithValue("@serial_number", serialNumber ?? ""); cmd.Parameters.AddWithValue("@employee_name", employeeName ?? ""); + cmd.Parameters.AddWithValue("@updated_by", string.IsNullOrWhiteSpace(updatedBy) ? "hikvision-service" : updatedBy.Trim()); cmd.ExecuteNonQuery(); return true; } @@ -320,11 +321,26 @@ internal sealed class MySqlAttendanceMachineFaceTemplateRepository : IAttendance using var conn = new MySqlConnection(cs); conn.Open(); + // Skip rewrite when an active non-empty template is already stored for this employee. using (var existsCmd = new MySqlCommand( - "SELECT 1 FROM attendance_machine_face_templates WHERE serial_no=@serial_no LIMIT 1", conn)) + "SELECT 1 FROM attendance_machine_face_templates " + + "WHERE serial_no=@serial_no AND is_active=1 AND template IS NOT NULL AND LENGTH(template)>0 " + + "LIMIT 1", conn)) { existsCmd.Parameters.AddWithValue("@serial_no", serialNo ?? ""); - createdNew = existsCmd.ExecuteScalar() == null; + if (existsCmd.ExecuteScalar() != null) + { + createdNew = false; + return true; // already present — do not UPDATE / re-INSERT + } + } + + // Insert new, or fill/replace an empty/inactive row for the same serial. + using (var existsAnyCmd = new MySqlCommand( + "SELECT 1 FROM attendance_machine_face_templates WHERE serial_no=@serial_no LIMIT 1", conn)) + { + existsAnyCmd.Parameters.AddWithValue("@serial_no", serialNo ?? ""); + createdNew = existsAnyCmd.ExecuteScalar() == null; } if (createdNew) @@ -348,6 +364,7 @@ internal sealed class MySqlAttendanceMachineFaceTemplateRepository : IAttendance update.Parameters.AddWithValue("@created_date", createdDate); update.Parameters.AddWithValue("@is_active", isActive ? 1 : 0); update.ExecuteNonQuery(); + createdNew = true; // treat fill of empty row as a new save for caller logging } // Best-effort source metadata update for schemas that include these columns.