Utopia-Canteen-System/Services/EmployeeLookupService.cs

146 lines
5.0 KiB
C#

using Microsoft.EntityFrameworkCore;
using MySqlConnector;
using UtopiaCanteenSystem.Data;
using UtopiaCanteenSystem.Models;
namespace UtopiaCanteenSystem.Services;
/// <summary>
/// Looks up employee by RFID from local SQLite <c>employee_rfid_tag_cache</c> (synced from production HRMS).
/// Menu authorization and admin site lookup still use HRMS when configured.
/// </summary>
public class EmployeeLookupService : IEmployeeLookupService
{
private readonly IDbContextFactory<AppDbContext> _dbFactory;
private readonly IConfigService _configService;
public EmployeeLookupService(IDbContextFactory<AppDbContext> dbFactory, IConfigService configService)
{
_dbFactory = dbFactory;
_configService = configService;
}
/// <inheritdoc />
public async Task<HrmsEmployeeInfo?> GetEmployeeByRfidAsync(string rfid, CancellationToken cancellationToken = default)
{
var cardId = rfid?.Trim() ?? string.Empty;
if (string.IsNullOrEmpty(cardId))
return null;
await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
var tag = await db.EmployeeRfidTagCache
.AsNoTracking()
.Where(x => x.ManufacturerSerial == cardId)
.Where(x => x.ParentDocumentType == "Employee")
.FirstOrDefaultAsync(cancellationToken)
.ConfigureAwait(false);
if (tag == null)
return null;
return MapToHrmsEmployeeInfo(tag);
}
/// <inheritdoc />
public async Task<string?> GetLocationSiteIdByEmployeeSerialAsync(string employeeSerial, CancellationToken cancellationToken = default)
{
var serial = employeeSerial?.Trim() ?? string.Empty;
if (string.IsNullOrEmpty(serial))
return null;
await using var db = await _dbFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false);
var siteId = await db.EmployeeRfidTagCache
.AsNoTracking()
.Where(x => x.ParentDocumentType == "Employee")
.Where(x => x.EmployeeSerialNumber == serial)
.Where(x => !string.IsNullOrEmpty(x.LocationSiteId))
.Select(x => x.LocationSiteId)
.FirstOrDefaultAsync(cancellationToken)
.ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(siteId))
return siteId.Trim();
return await GetLocationSiteIdFromHrmsAsync(serial, cancellationToken).ConfigureAwait(false);
}
/// <inheritdoc />
public async Task<bool> IsMenuItemAuthorizedForRfidAsync(string rfid, int menuItemId, CancellationToken cancellationToken = default)
{
var card = rfid?.Trim() ?? string.Empty;
if (string.IsNullOrEmpty(card) || menuItemId <= 0)
return false;
var connectionString = _configService.GetHrmsLookupConnectionString();
if (string.IsNullOrWhiteSpace(connectionString))
return false;
const string sql = @"
SELECT 1
FROM employee_rfid_tag r
JOIN employee_menu_item_tag em ON em.employee_rfid_tag_id = r.id
WHERE r.manufacturer_serial = @rfid
AND em.item_id = @itemId
LIMIT 1";
await using var conn = new MySqlConnection(connectionString);
await conn.OpenAsync(cancellationToken).ConfigureAwait(false);
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@rfid", card);
cmd.Parameters.AddWithValue("@itemId", menuItemId);
var exists = await cmd.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
return exists != null && exists != DBNull.Value;
}
private static HrmsEmployeeInfo MapToHrmsEmployeeInfo(EmployeeRfidTagCache tag)
{
return new HrmsEmployeeInfo
{
ParentDocumentId = tag.ParentDocumentId,
EmployeeId = tag.EmployeeSerialNumber,
FirstName = tag.EmployeeConcatenatedName,
MiddleName = string.Empty,
UindSerial = tag.UindSerial,
FunctionId = tag.FunctionId,
DepartmentId = tag.DepartmentId,
TagCreatedAtUtc = tag.DateTimeCreated,
TagCreatedBy = tag.CreatedBy,
DepartmentTitle = tag.DepartmentTitle,
DepartmentType = tag.DepartmentType,
LocationSiteId = tag.LocationSiteId,
GradeType = tag.GradeType
};
}
private async Task<string?> GetLocationSiteIdFromHrmsAsync(string serial, CancellationToken cancellationToken)
{
var connectionString = _configService.GetHrmsLookupConnectionString();
if (string.IsNullOrWhiteSpace(connectionString))
return null;
const string sql = @"
SELECT location_site_id
FROM employee
WHERE serial_number = @serial
LIMIT 1";
await using var conn = new MySqlConnection(connectionString);
await conn.OpenAsync(cancellationToken).ConfigureAwait(false);
await using var cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@serial", serial);
await using var reader = await cmd.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false);
if (!await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
return null;
if (reader.IsDBNull(0))
return null;
var raw = reader.GetValue(0)?.ToString()?.Trim();
return string.IsNullOrEmpty(raw) ? null : raw;
}
}