using MySql.Data.MySqlClient;
using System;
namespace HanvonF710XAttendanceService
{
///
/// HRMS employee row used for Hanvon display name and portal photo URL.
/// Device enroll/serial must NOT be treated as employee.id.
///
internal sealed class HrmsEmployeeInfo
{
public HrmsEmployeeInfo(string employeeId, string serialNumberInt, string concatenatedName, string department = "")
{
EmployeeId = employeeId ?? "";
SerialNumberInt = serialNumberInt ?? "";
ConcatenatedName = concatenatedName ?? "";
Department = department ?? "";
}
/// employee.id — used for portal photo URL only.
public string EmployeeId { get; }
/// employee.serial_number_int — matches device / attendance_machine_user.serial_number.
public string SerialNumberInt { get; }
/// employee.concatenated_name — Hanvon user display name.
public string ConcatenatedName { get; }
/// Department display name when available; otherwise department_id.
public string Department { get; }
}
internal sealed class HrmsEmployeeDAO
{
///
/// Match device serial (attendance_machine_user.serial_number) to employee.serial_number_int.
///
public bool TryGetByDeviceSerial(MySqlConnection connection, string deviceSerial, out HrmsEmployeeInfo employee)
{
employee = null;
if (connection == null || string.IsNullOrWhiteSpace(deviceSerial))
{
return false;
}
string serial = deviceSerial.Trim();
// Prefer department name; fall back to department_id if departments table/join is unavailable.
const string queryWithDeptName =
"SELECT e.id, e.serial_number_int, e.concatenated_name, " +
"COALESCE(NULLIF(TRIM(d.name), ''), CAST(e.department_id AS CHAR), '') AS department " +
"FROM hrms.employee e " +
"LEFT JOIN hrms.departments d ON d.id = e.department_id " +
"WHERE CAST(e.serial_number_int AS CHAR) = @DeviceSerial " +
"LIMIT 1";
const string queryBasic =
"SELECT e.id, e.serial_number_int, e.concatenated_name, " +
"CAST(e.department_id AS CHAR) AS department " +
"FROM hrms.employee e " +
"WHERE CAST(e.serial_number_int AS CHAR) = @DeviceSerial " +
"LIMIT 1";
try
{
if (TryReadEmployee(connection, queryWithDeptName, serial, out employee))
{
return true;
}
}
catch
{
// departments table/column may differ; fall back.
}
return TryReadEmployee(connection, queryBasic, serial, out employee);
}
private static bool TryReadEmployee(MySqlConnection connection, string query, string serial, out HrmsEmployeeInfo employee)
{
employee = null;
using (var cmd = new MySqlCommand(query, connection))
{
cmd.CommandTimeout = 60;
cmd.Parameters.AddWithValue("@DeviceSerial", serial);
using (var reader = cmd.ExecuteReader())
{
if (!reader.Read())
{
return false;
}
string id = reader.IsDBNull(0) ? "" : Convert.ToString(reader.GetValue(0))?.Trim();
string serialInt = reader.IsDBNull(1) ? "" : Convert.ToString(reader.GetValue(1))?.Trim();
string name = reader.IsDBNull(2) ? "" : Convert.ToString(reader.GetValue(2))?.Trim();
string department = reader.FieldCount > 3 && !reader.IsDBNull(3)
? Convert.ToString(reader.GetValue(3))?.Trim()
: "";
if (string.IsNullOrWhiteSpace(id))
{
return false;
}
employee = new HrmsEmployeeInfo(id, serialInt, name, department);
return true;
}
}
}
public string ResolveDisplayName(
MySqlConnection connection,
string deviceSerial,
string fallbackName = null)
{
if (TryGetByDeviceSerial(connection, deviceSerial, out HrmsEmployeeInfo employee)
&& !string.IsNullOrWhiteSpace(employee.ConcatenatedName))
{
return employee.ConcatenatedName;
}
if (!string.IsNullOrWhiteSpace(fallbackName))
{
return fallbackName.Trim();
}
return string.IsNullOrWhiteSpace(deviceSerial) ? "" : deviceSerial.Trim();
}
}
}