using FMDAL.CustomCode.Device; using FMDAL.DTO.Device; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using static GB5Shared.GB5Constant.Constant; namespace FMBLL.Device { public class FMDeviceBLL : IFMDeviceBLL { private readonly IFMDeviceDAL _dal; private readonly IQueryExecutor _queryExecutor; private readonly KeyInvalidate _keyInvalidate; private readonly ILogger _logger; public FMDeviceBLL( IFMDeviceDAL dal, IQueryExecutor queryExecutor, KeyInvalidate keyInvalidate, ILogger logger) { _dal = dal; _queryExecutor = queryExecutor; _keyInvalidate = keyInvalidate; _logger = logger; } public async Task GetDevice(int deviceId, LoginDTO login, CancellationToken ct) { var dto = await _dal.GetDevice(deviceId, login, ct).ConfigureAwait(false); return JsonConvert.SerializeObject(dto); } public async Task GetDeviceList(int firstNumber, int maxResult, LoginDTO login, CancellationToken ct) { var (items, count) = await _dal.GetDeviceList(firstNumber, maxResult, login, ct).ConfigureAwait(false); return JsonConvert.SerializeObject(new { Items = items, TotalCount = count }); } public async Task SaveDevice(DeviceSaveDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-fmdevice", new { dto.DeviceId }); if (string.IsNullOrWhiteSpace(dto.DeviceCode)) throw new ArgumentException("DeviceCode is required"); if (string.IsNullOrWhiteSpace(dto.DeviceName)) throw new ArgumentException("DeviceName is required"); bool isNew = dto.DeviceId == 0; dto.TenantId = login.ClientId; dto.ModifiedById = login.UserId; if (isNew) dto.CreatedById = login.UserId; GB5Trace.Step("save-fmdevice", new { dto.DeviceId, isNew }); await using var tx = await _queryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { int deviceId; if (isNew) { deviceId = await _dal.SaveDevice(dto, login, tx, ct).ConfigureAwait(false); dto.DeviceId = deviceId; } else { deviceId = dto.DeviceId; await _dal.UpdateDevice(dto, login, tx, ct).ConfigureAwait(false); } await tx.CommitAsync(ct).ConfigureAwait(false); } catch { await tx.RollbackAsync(ct).ConfigureAwait(false); throw; } var cacheKey = new CacheKeyGeneration().KeyGeneration(dto.DeviceId, EntityConstant.OBJECTFMDEVICE, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.DeviceId}" : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-fmdevice-failed", ex); _logger.LogError(ex, "SaveDevice failed for DeviceId {Id}", dto.DeviceId); throw; } } public async Task DeleteDevice(int deviceId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("delete-fmdevice", new { deviceId }); await using var tx = await _queryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { await _dal.SoftDeleteDevice(deviceId, login.UserId, login, tx, ct).ConfigureAwait(false); await tx.CommitAsync(ct).ConfigureAwait(false); } catch { await tx.RollbackAsync(ct).ConfigureAwait(false); throw; } var cacheKey = new CacheKeyGeneration().KeyGeneration(deviceId, EntityConstant.OBJECTFMDEVICE, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { GB5Trace.MarkFailed("delete-fmdevice-failed", ex); _logger.LogError(ex, "DeleteDevice failed for DeviceId {Id}", deviceId); throw; } } public async Task UpdateLastSeen(int deviceId, LoginDTO login, CancellationToken ct) { await _dal.UpdateLastSeen(deviceId, login, ct).ConfigureAwait(false); } public async Task ValidateDevice(int deviceId, LoginDTO login, CancellationToken ct) { var result = await _dal.ValidateDevice(deviceId, login, ct).ConfigureAwait(false); return result ?? new DeviceValidationResultDTO { IsValid = false, DeviceId = deviceId, Message = "Device not found or not verified." }; } public async Task GetSelectListDeviceType(CriteriaDTO CriteriaDTO,LoginDTO LoginDTO) { try { return await _dal.GetSelectListDeviceType( CriteriaDTO, LoginDTO); } catch (Exception) { throw; } } public async Task GetSelectListDevice(CriteriaDTO CriteriaDTO,LoginDTO LoginDTO) { try { return await _dal.GetSelectListDevice( CriteriaDTO, LoginDTO); } catch (Exception) { throw; } } public async Task GetDeviceType(int deviceTypeId, LoginDTO login, CancellationToken ct) { var dto = await _dal.GetDeviceType(deviceTypeId, login, ct).ConfigureAwait(false); return JsonConvert.SerializeObject(dto); } public async Task SaveDeviceType(DeviceTypeDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-devicetype", new { dto.DeviceTypeId }); if (string.IsNullOrWhiteSpace(dto.DeviceTypeCode)) throw new ArgumentException("DeviceTypeCode is required"); if (string.IsNullOrWhiteSpace(dto.DeviceTypeName)) throw new ArgumentException("DeviceTypeName is required"); bool isNew = dto.DeviceTypeId == 0; dto.DeviceTypeTenantId = login.ClientId; dto.DeviceTypeModifiedById = login.UserId; if (isNew) dto.DeviceTypeCreatedById = login.UserId; GB5Trace.Step("save-devicetype", new { dto.DeviceTypeId, isNew }); await using var tx = await _queryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { if (isNew) { var deviceTypeId = await _dal.SaveDeviceType(dto, login, tx, ct).ConfigureAwait(false); dto.DeviceTypeId = deviceTypeId; } else { await _dal.UpdateDeviceType(dto, login, tx, ct).ConfigureAwait(false); } await tx.CommitAsync(ct).ConfigureAwait(false); } catch { await tx.RollbackAsync(ct).ConfigureAwait(false); throw; } var cacheKey = new CacheKeyGeneration().KeyGeneration(dto.DeviceTypeId, EntityConstant.OBJECTDEVICETYPE, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.DeviceTypeId}" : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-devicetype-failed", ex); _logger.LogError(ex, "SaveDeviceType failed for DeviceTypeId {Id}", dto.DeviceTypeId); throw; } } public async Task DeleteDeviceType(int deviceTypeId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("delete-devicetype", new { deviceTypeId }); await using var tx = await _queryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { await _dal.SoftDeleteDeviceType(deviceTypeId, login.UserId, login, tx, ct).ConfigureAwait(false); await tx.CommitAsync(ct).ConfigureAwait(false); } catch { await tx.RollbackAsync(ct).ConfigureAwait(false); throw; } var cacheKey = new CacheKeyGeneration().KeyGeneration(deviceTypeId, EntityConstant.OBJECTDEVICETYPE, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { GB5Trace.MarkFailed("delete-devicetype-failed", ex); _logger.LogError(ex, "DeleteDeviceType failed for DeviceTypeId {Id}", deviceTypeId); throw; } } } }