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