146 lines
5.0 KiB
C#
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;
|
|
}
|
|
}
|