feat: skip already-registered users and emit DB_TO_DEVICE summary
Skip active attendance_machine_user rows; produce per-target summary report.main
parent
c41950a22a
commit
5e80e11b0e
|
|
@ -0,0 +1,133 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace HanvonF710XAttendanceService
|
||||||
|
{
|
||||||
|
internal sealed class DbToDeviceFailedEmployee
|
||||||
|
{
|
||||||
|
public string SerialNumber { get; set; } = "";
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Department { get; set; } = "";
|
||||||
|
public string MachineId { get; set; } = "";
|
||||||
|
public string MachineIp { get; set; } = "";
|
||||||
|
public string MachineType { get; set; } = "";
|
||||||
|
public string Reason { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class DbToDeviceMissingMappingEmployee
|
||||||
|
{
|
||||||
|
public string SerialNumber { get; set; } = "";
|
||||||
|
public string MachineId { get; set; } = "";
|
||||||
|
public string MachineIp { get; set; } = "";
|
||||||
|
public string MachineType { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
internal sealed class DbToDeviceTargetSummary
|
||||||
|
{
|
||||||
|
public string MachineId { get; set; } = "";
|
||||||
|
public string MachineIp { get; set; } = "";
|
||||||
|
public string MachineType { get; set; } = "";
|
||||||
|
public int AlreadyRegistered { get; set; }
|
||||||
|
public int NewlyRegistered { get; set; }
|
||||||
|
public int Failed { get; set; }
|
||||||
|
public List<DbToDeviceFailedEmployee> FailedEmployees { get; } = new List<DbToDeviceFailedEmployee>();
|
||||||
|
public List<DbToDeviceMissingMappingEmployee> MissingMappings { get; } = new List<DbToDeviceMissingMappingEmployee>();
|
||||||
|
|
||||||
|
public void AddFailure(string serial, string name, string department, string reason)
|
||||||
|
{
|
||||||
|
Failed++;
|
||||||
|
FailedEmployees.Add(new DbToDeviceFailedEmployee
|
||||||
|
{
|
||||||
|
SerialNumber = serial ?? "",
|
||||||
|
Name = name ?? "",
|
||||||
|
Department = department ?? "",
|
||||||
|
MachineId = MachineId,
|
||||||
|
MachineIp = MachineIp,
|
||||||
|
MachineType = MachineType,
|
||||||
|
Reason = reason ?? ""
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMissingMapping(string serial)
|
||||||
|
{
|
||||||
|
MissingMappings.Add(new DbToDeviceMissingMappingEmployee
|
||||||
|
{
|
||||||
|
SerialNumber = serial ?? "",
|
||||||
|
MachineId = MachineId,
|
||||||
|
MachineIp = MachineIp,
|
||||||
|
MachineType = MachineType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatReport()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("=================================");
|
||||||
|
sb.AppendLine("DB_TO_DEVICE SUMMARY");
|
||||||
|
sb.AppendLine("=================================");
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine("Target:");
|
||||||
|
sb.AppendLine("Machine ID: " + MachineId);
|
||||||
|
sb.AppendLine("IP: " + MachineIp);
|
||||||
|
sb.AppendLine("Type: " + MachineType);
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine("Already Registered: " + AlreadyRegistered);
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine("Newly Registered: " + NewlyRegistered);
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine("Failed: " + Failed);
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.AppendLine("Missing Employee Mapping: " + MissingMappings.Count);
|
||||||
|
if (MissingMappings.Count > 0)
|
||||||
|
{
|
||||||
|
sb.AppendLine();
|
||||||
|
foreach (var miss in MissingMappings)
|
||||||
|
{
|
||||||
|
sb.AppendLine("Serial: " + miss.SerialNumber);
|
||||||
|
sb.AppendLine("Machine ID: " + miss.MachineId);
|
||||||
|
sb.AppendLine("Machine IP: " + miss.MachineIp);
|
||||||
|
sb.AppendLine("Machine Type: " + miss.MachineType);
|
||||||
|
sb.AppendLine("Reason: No employee row for serial_number_int");
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FailedEmployees.Count > 0)
|
||||||
|
{
|
||||||
|
sb.AppendLine("Failed Employees:");
|
||||||
|
sb.AppendLine();
|
||||||
|
foreach (var fail in FailedEmployees)
|
||||||
|
{
|
||||||
|
sb.AppendLine("Serial: " + fail.SerialNumber);
|
||||||
|
sb.AppendLine("Name: " + fail.Name);
|
||||||
|
sb.AppendLine("Department: " + fail.Department);
|
||||||
|
sb.AppendLine("Machine ID: " + fail.MachineId);
|
||||||
|
sb.AppendLine("Machine IP: " + fail.MachineIp);
|
||||||
|
sb.AppendLine("Machine Type: " + fail.MachineType);
|
||||||
|
sb.AppendLine("Reason: " + fail.Reason);
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString().TrimEnd() + Environment.NewLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class DbToDeviceSkipLogic
|
||||||
|
{
|
||||||
|
public static bool ShouldSkipAlreadyRegistered(ISet<string> registeredSerials, string employeeSerial)
|
||||||
|
{
|
||||||
|
if (registeredSerials == null || string.IsNullOrWhiteSpace(employeeSerial))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return registeredSerials.Contains(employeeSerial.Trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace HanvonF710XAttendanceService
|
||||||
|
{
|
||||||
|
internal static class DbToDeviceSummaryTests
|
||||||
|
{
|
||||||
|
public static int RunAll()
|
||||||
|
{
|
||||||
|
int failed = 0;
|
||||||
|
failed += Run("existing user is skipped", TestExistingUserSkipped);
|
||||||
|
failed += Run("missing user is enrolled", TestMissingUserEnrolled);
|
||||||
|
failed += Run("summary contains required fields", TestSummaryContainsRequiredFields);
|
||||||
|
failed += Run("multiple machines produce separate summaries", TestMultipleMachineSummaries);
|
||||||
|
return failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Run(string name, Func<bool> test)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!test())
|
||||||
|
{
|
||||||
|
Console.WriteLine("FAIL: " + name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("PASS: " + name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("FAIL: " + name + " err=" + ex.Message);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TestExistingUserSkipped()
|
||||||
|
{
|
||||||
|
var registered = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "15057", "6401" };
|
||||||
|
return DbToDeviceSkipLogic.ShouldSkipAlreadyRegistered(registered, "15057")
|
||||||
|
&& DbToDeviceSkipLogic.ShouldSkipAlreadyRegistered(registered, " 6401 ")
|
||||||
|
&& !DbToDeviceSkipLogic.ShouldSkipAlreadyRegistered(registered, "99999");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TestMissingUserEnrolled()
|
||||||
|
{
|
||||||
|
var registered = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "15057" };
|
||||||
|
var summary = new DbToDeviceTargetSummary
|
||||||
|
{
|
||||||
|
MachineId = "105",
|
||||||
|
MachineIp = "192.168.90.223",
|
||||||
|
MachineType = "HANVON"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Existing -> skip
|
||||||
|
if (DbToDeviceSkipLogic.ShouldSkipAlreadyRegistered(registered, "15057"))
|
||||||
|
{
|
||||||
|
summary.AlreadyRegistered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Missing -> enroll
|
||||||
|
if (!DbToDeviceSkipLogic.ShouldSkipAlreadyRegistered(registered, "99999"))
|
||||||
|
{
|
||||||
|
summary.NewlyRegistered++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return summary.AlreadyRegistered == 1 && summary.NewlyRegistered == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TestSummaryContainsRequiredFields()
|
||||||
|
{
|
||||||
|
var summary = new DbToDeviceTargetSummary
|
||||||
|
{
|
||||||
|
MachineId = "105",
|
||||||
|
MachineIp = "192.168.90.223",
|
||||||
|
MachineType = "HANVON",
|
||||||
|
AlreadyRegistered = 620,
|
||||||
|
NewlyRegistered = 30
|
||||||
|
};
|
||||||
|
summary.AddMissingMapping("88888");
|
||||||
|
summary.AddFailure("15057", "John Smith", "Production", "Employee photo not found");
|
||||||
|
summary.AddFailure("6401", "ABC XYZ", "Quality", "DUPLICATE_FACE existing_device_id=6400");
|
||||||
|
|
||||||
|
string report = summary.FormatReport();
|
||||||
|
return report.Contains("DB_TO_DEVICE SUMMARY")
|
||||||
|
&& report.Contains("Machine ID: 105")
|
||||||
|
&& report.Contains("IP: 192.168.90.223")
|
||||||
|
&& report.Contains("Type: HANVON")
|
||||||
|
&& report.Contains("Already Registered: 620")
|
||||||
|
&& report.Contains("Newly Registered: 30")
|
||||||
|
&& report.Contains("Failed: 2")
|
||||||
|
&& report.Contains("Missing Employee Mapping: 1")
|
||||||
|
&& report.Contains("Serial: 15057")
|
||||||
|
&& report.Contains("Name: John Smith")
|
||||||
|
&& report.Contains("Department: Production")
|
||||||
|
&& report.Contains("Reason: Employee photo not found")
|
||||||
|
&& report.Contains("DUPLICATE_FACE existing_device_id=6400");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TestMultipleMachineSummaries()
|
||||||
|
{
|
||||||
|
var a = new DbToDeviceTargetSummary
|
||||||
|
{
|
||||||
|
MachineId = "105",
|
||||||
|
MachineIp = "192.168.90.223",
|
||||||
|
MachineType = "HANVON",
|
||||||
|
AlreadyRegistered = 10,
|
||||||
|
NewlyRegistered = 2
|
||||||
|
};
|
||||||
|
var b = new DbToDeviceTargetSummary
|
||||||
|
{
|
||||||
|
MachineId = "106",
|
||||||
|
MachineIp = "10.0.1.7",
|
||||||
|
MachineType = "HANVON",
|
||||||
|
AlreadyRegistered = 5,
|
||||||
|
NewlyRegistered = 7
|
||||||
|
};
|
||||||
|
b.AddFailure("6401", "ABC XYZ", "Quality", "DUPLICATE_FACE existing_device_id=6400");
|
||||||
|
|
||||||
|
string reportA = a.FormatReport();
|
||||||
|
string reportB = b.FormatReport();
|
||||||
|
|
||||||
|
return reportA.Contains("Machine ID: 105")
|
||||||
|
&& reportA.Contains("IP: 192.168.90.223")
|
||||||
|
&& reportA.Contains("Already Registered: 10")
|
||||||
|
&& reportA.Contains("Newly Registered: 2")
|
||||||
|
&& !reportA.Contains("10.0.1.7")
|
||||||
|
&& reportB.Contains("Machine ID: 106")
|
||||||
|
&& reportB.Contains("IP: 10.0.1.7")
|
||||||
|
&& reportB.Contains("Already Registered: 5")
|
||||||
|
&& reportB.Contains("Newly Registered: 7")
|
||||||
|
&& reportB.Contains("Failed: 1")
|
||||||
|
&& !reportB.Contains("192.168.90.223");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue