using FMDAL.CustomCode.Asset; using FMDAL.DTO.Asset; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.QueryExecutor; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using static GB5Shared.GB5Constant.Constant; namespace FMBLL.Asset { public class AssetBLL : IAssetBLL { private readonly IAssetDAL _AssetDAL; private readonly IQueryExecutor _queryExecutor; private readonly AutoNumber _autoNumber; private readonly KeyInvalidate _keyInvalidate; private readonly ILogger _logger; public AssetBLL( IAssetDAL IAssetDAL, IQueryExecutor queryExecutor, AutoNumber autoNumber, KeyInvalidate keyInvalidate, ILogger logger) { _AssetDAL = IAssetDAL; _queryExecutor = queryExecutor; _autoNumber = autoNumber; _keyInvalidate = keyInvalidate; _logger = logger; } public async Task GetAsset(int AssetId, LoginDTO LoginDTO) { try { return await _AssetDAL.GetAsset(AssetId, LoginDTO); } catch (Exception) { throw; } } public async Task GetSelectListAsset(CriteriaDTO criteriaDTO, LoginDTO loginDTO) { try { return await _AssetDAL.GetSelectListAsset(criteriaDTO, loginDTO); } catch (Exception) { throw; } } public async Task IsDuplicateAssetBatch(int assetTypeId, string assetBatch, int excludeAssetId, LoginDTO login, CancellationToken ct) { if (string.IsNullOrWhiteSpace(assetBatch)) return false; var count = await _AssetDAL.CheckDuplicateAssetBatch(assetTypeId, assetBatch, excludeAssetId, login, ct).ConfigureAwait(false); return count > 0; } public async Task UpdateAssetSnapshot(AssetSnapshotDTO snapshot, LoginDTO login, System.Data.Common.DbTransaction tx, CancellationToken ct) { GB5Trace.Step("update-asset-snapshot", new { snapshot.AssetId, snapshot.CurrentAssetStateId }); await _AssetDAL.UpdateAssetSnapshot(snapshot, login, tx, ct).ConfigureAwait(false); } public async Task DeleteAsset(int assetId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("delete-asset", new { assetId }); await using var tx = await _queryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { var existingDetails = await _AssetDAL.GetAssetParameterSetDetailListByAsset(assetId, login, ct).ConfigureAwait(false); foreach (var existing in existingDetails) { await _AssetDAL.DeleteAssetParameterSetDetail(existing.AssetParameterSetDetailId, login, tx, ct).ConfigureAwait(false); } await _AssetDAL.DeleteAsset(assetId, login, tx, ct).ConfigureAwait(false); await tx.CommitAsync(ct).ConfigureAwait(false); } catch { await tx.RollbackAsync(ct).ConfigureAwait(false); throw; } var cacheKey = new CacheKeyGeneration().KeyGeneration(assetId, EntityConstant.OBJECTASSET, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { GB5Trace.MarkFailed("delete-asset-failed", ex); _logger.LogError(ex, "DeleteAsset failed for AssetId {AssetId}", assetId); throw; } } public async Task SaveAsset(AssetDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-asset", new { dto.AssetId }); if (string.IsNullOrWhiteSpace(dto.AssetCode)) throw new ArgumentException("AssetCode is required"); if (string.IsNullOrWhiteSpace(dto.AssetName)) throw new ArgumentException("AssetName is required"); bool isNew = dto.AssetId == 0; if (await IsDuplicateAssetBatch(dto.AssetTypeId, dto.AssetBatch, isNew ? 0 : dto.AssetId, login, ct).ConfigureAwait(false)) throw new ArgumentException(SuccessResponse.DuplicateAssetBatch); GB5Trace.Step("save-asset", new { dto.AssetId, isNew }); await using var tx = await _queryExecutor.BeginTransactionAsync(login).ConfigureAwait(false); try { if (isNew) { var auto = await _autoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.ASSET, login).ConfigureAwait(false); dto.AssetId = auto.StartNumber; await _AssetDAL.SaveAsset(dto, login, tx, ct).ConfigureAwait(false); } else { await _AssetDAL.UpdateAsset(dto, login, tx, ct).ConfigureAwait(false); var existingDetails = await _AssetDAL.GetAssetParameterSetDetailListByAsset(dto.AssetId, login, ct).ConfigureAwait(false); var incomingIds = (dto.AssetParameterSetDetailArray ?? new List()) .Select(d => d.AssetParameterSetDetailId) .Where(id => id != 0) .ToHashSet(); foreach (var existing in existingDetails) { if (!incomingIds.Contains(existing.AssetParameterSetDetailId)) { await _AssetDAL.DeleteAssetParameterSetDetail(existing.AssetParameterSetDetailId, login, tx, ct).ConfigureAwait(false); } } } foreach (var detail in dto.AssetParameterSetDetailArray ?? new List()) { detail.AssetId = dto.AssetId; if (detail.AssetParameterSetDetailId == 0) { var auto = await _autoNumber.GetNumberAsync(1, AUTONUMBERCONSTANT.ASSETPARAMETERSETDETAIL, login).ConfigureAwait(false); detail.AssetParameterSetDetailId = auto.StartNumber; await _AssetDAL.SaveAssetParameterSetDetail(detail, login, tx, ct).ConfigureAwait(false); } else { await _AssetDAL.UpdateAssetParameterSetDetail(detail, 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.AssetId, EntityConstant.OBJECTASSET, CacheKeyLevel.CLIENT_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.AssetId}" : SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("save-asset-failed", ex); _logger.LogError(ex, "SaveAsset failed for AssetId {AssetId}", dto.AssetId); throw; } } } }