using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using GB5Shared.GB5Constant; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GoodBooks.PAY.PAYDAL.CustomCode.Gateway; using GoodBooks.PAY.PAYDAL.DTO.Gateway; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using static GB5Shared.GB5Constant.Constant; namespace GoodBooks.PAY.PAYBLL.Gateway { // ───────────────────────────────────────────────────────────────────────── // PayGatewayBLL // // MPAYGATEWAY is a DevAdmin platform catalogue — no TENANTID on the table. // Cache level: USER_LEVEL (shared across tenants; keyed on gateway Id). // EntityConstant.OBJECTPAYGATEWAY = -1382000001 // ───────────────────────────────────────────────────────────────────────── public class PayGatewayBLL : IPayGatewayBLL { private readonly IPayGatewayDAL _dal; private readonly AutoNumber _autoNumber; private readonly KeyInvalidate _keyInvalidate; private readonly EventLogPublish _eventLogPublish; private readonly ILogger _logger; public PayGatewayBLL( IPayGatewayDAL dal, AutoNumber autoNumber, KeyInvalidate keyInvalidate, EventLogPublish eventLogPublish, ILogger logger) { _dal = dal; _autoNumber = autoNumber; _keyInvalidate = keyInvalidate; _eventLogPublish = eventLogPublish; _logger = logger; } // ── Get single gateway ──────────────────────────────────────────────── // DAL returns pre-serialized JSON; BLL passes it through. public async Task GetPayGateway(int payGatewayId, LoginDTO login, CancellationToken ct) { try { return await _dal.GetPayGateway(payGatewayId, login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "GetPayGateway failed for PayGatewayId {PayGatewayId}", payGatewayId); throw; } } // ── Select-list / dropdown ──────────────────────────────────────────── // Small platform catalogue — no cache needed (changes rarely, list is tiny). public async Task GetSelectListPayGateway(LoginDTO login, CancellationToken ct) { try { return await _dal.GetSelectListGateway(login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "GetSelectListPayGateway failed for UserId {UserId}", login.UserId); throw; } } // ── Save (insert or update) ─────────────────────────────────────────── public async Task SavePayGateway(PayGatewayDTO dto, LoginDTO login, CancellationToken ct) { if (dto is null) throw new ArgumentNullException(nameof(dto)); try { bool isNew = dto.PayGatewayId == 0; if (isNew) { var autoNum = await _autoNumber.GetAutoNumber(1, "PAYGATEWAY", login) .ConfigureAwait(false); dto.PayGatewayId = autoNum.StartNumber; dto.CreatedById = login.UserId; dto.CreatedOn = DateTime.UtcNow; } dto.ModifiedById = login.UserId; dto.ModifiedOn = DateTime.UtcNow; if (isNew) await _dal.SavePayGateway(dto, login).ConfigureAwait(false); else await _dal.UpdatePayGateway(dto, login).ConfigureAwait(false); // Invalidate platform catalogue cache at USER_LEVEL var cacheKey = new CacheKeyGeneration().KeyGeneration( dto.PayGatewayId.ToString(), EntityConstant.OBJECTPAYGATEWAY, CacheKeyLevel.USER_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); // Audit trail try { await _eventLogPublish.PublishEventLogAsync( isNew ? "Pay Gateway Created" : "Pay Gateway Updated", new { dto.PayGatewayId, dto.PayGatewayCode, dto.PayGatewayName }, Constant.EventTypeConstant.SAVEDOCUMENTSET, 0, login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogWarning(ex, "Event log publish failed for PayGateway {PayGatewayId}", dto.PayGatewayId); } return isNew ? $"{SuccessResponse.SaveSuccessMessage} {dto.PayGatewayId}" : $"{SuccessResponse.UpdateSuccessMessage} {dto.PayGatewayId}"; } catch (Exception ex) { _logger.LogError(ex, "SavePayGateway failed for PayGatewayCode {PayGatewayCode}", dto.PayGatewayCode); throw; } } // ── Delete ──────────────────────────────────────────────────────────── public async Task DeletePayGateway(int payGatewayId, LoginDTO login, CancellationToken ct) { try { // DAL interface does not expose DeletePayGateway directly; // a soft-delete is handled by setting Status = 0 via UpdatePayGateway. // Build a minimal DTO representing the soft-delete state. var dto = new PayGatewayDTO { PayGatewayId = payGatewayId, Status = 0, ModifiedById = login.UserId, ModifiedOn = DateTime.UtcNow }; await _dal.UpdatePayGateway(dto, login).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration( payGatewayId.ToString(), EntityConstant.OBJECTPAYGATEWAY, CacheKeyLevel.USER_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); try { await _eventLogPublish.PublishEventLogAsync( "Pay Gateway Deleted", new { PayGatewayId = payGatewayId }, Constant.EventTypeConstant.SAVEDOCUMENTSET, 0, login).ConfigureAwait(false); } catch (Exception ex) { _logger.LogWarning(ex, "Event log publish failed for deleted PayGateway {PayGatewayId}", payGatewayId); } return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { _logger.LogError(ex, "DeletePayGateway failed for PayGatewayId {PayGatewayId}", payGatewayId); throw; } } } }