using DigitalData.Core.Abstraction.Application.Repository; using DigitalData.Core.Exceptions; using MediatR; using Microsoft.Data.SqlClient; using Microsoft.Extensions.Options; using ReC.Application.Common.Exceptions; using ReC.Application.Common.Options; using ReC.Application.Common.Procedures.UpdateProcedure.Dto; using System.Data; namespace ReC.Application.Common.Procedures.UpdateProcedure; public record UpdateObjectProcedure : IRequest { /// /// Target entity for the update operation. /// public required EntityType Entity { get; set; } /// /// Target GUID to update (required) /// public long Id { get; set; } //TODO: update to set in authentication middleware or similar, and remove from procedure properties internal string? ChangedWho { get; private set; } = "ReC.API"; public UpdateActionDto Action { get; set; } = new(); public UpdateEndpointDto Endpoint { get; set; } = new(); public UpdateEndpointAuthDto EndpointAuth { get; set; } = new(); public UpdateProfileDto Profile { get; set; } = new(); public UpdateResultDto Result { get; set; } = new(); public UpdateEndpointParamsDto EndpointParams { get; set; } = new(); } public class UpdateObjectProcedureHandler(IRepository repo, IOptionsMonitor sqlExOpt) : IRequestHandler { public async Task Handle(UpdateObjectProcedure request, CancellationToken cancel) { var sp = new StoredProcedureBuilder("[dbo].[PRREC_UPDATE_OBJECT]", "RC") .Add("pENTITY", request.Entity) .Add("pGUID", request.Id) .Add("pCHANGED_WHO", request.ChangedWho) .Add("pCHANGED_WHEN", DateTime.UtcNow) .Add("pACTION_PROFILE_ID", request.Action.ProfileId) .Add("pACTION_ACTIVE", request.Action.Active) .Add("pACTION_SEQUENCE", request.Action.Sequence, SqlDbType.TinyInt) .Add("pACTION_ENDPOINT_ID", request.Action.EndpointId) .Add("pACTION_ENDPOINT_AUTH_ID", request.Action.EndpointAuthId) .Add("pACTION_ENDPOINT_PARAMS_ID", request.Action.EndpointParamsId, SqlDbType.SmallInt) .Add("pACTION_SQL_CONNECTION_ID", request.Action.SqlConnectionId, SqlDbType.SmallInt) .Add("pACTION_TYPE_ID", request.Action.TypeId, SqlDbType.TinyInt) .Add("pACTION_PRE_SQL", request.Action.PreSql) .Add("pACTION_HEADER_SQL", request.Action.HeaderSql) .Add("pACTION_BODY_SQL", request.Action.BodySql) .Add("pACTION_POST_SQL", request.Action.PostSql) .Add("pACTION_ERROR_ACTION_ID", request.Action.ErrorActionId, SqlDbType.TinyInt) .Add("pENDPOINT_ACTIVE", request.Endpoint.Active) .Add("pENDPOINT_DESCRIPTION", request.Endpoint.Description) .Add("pENDPOINT_URI", request.Endpoint.Uri) .Add("pENDPOINT_AUTH_ACTIVE", request.EndpointAuth.Active) .Add("pENDPOINT_AUTH_DESCRIPTION", request.EndpointAuth.Description) .Add("pENDPOINT_AUTH_TYPE_ID", request.EndpointAuth.TypeId, SqlDbType.TinyInt) .Add("pENDPOINT_AUTH_API_KEY", request.EndpointAuth.ApiKey) .Add("pENDPOINT_AUTH_API_VALUE", request.EndpointAuth.ApiValue) .Add("pENDPOINT_AUTH_API_KEY_ADD_TO_ID", request.EndpointAuth.ApiKeyAddToId) .Add("pENDPOINT_AUTH_TOKEN", request.EndpointAuth.Token) .Add("pENDPOINT_AUTH_USERNAME", request.EndpointAuth.Username) .Add("pENDPOINT_AUTH_PASSWORD", request.EndpointAuth.Password) .Add("pENDPOINT_AUTH_DOMAIN", request.EndpointAuth.Domain) .Add("pENDPOINT_AUTH_WORKSTATION", request.EndpointAuth.Workstation) .Add("pENDPOINT_PARAMS_ACTIVE", request.EndpointParams.Active) .Add("pENDPOINT_PARAMS_DESCRIPTION", request.EndpointParams.Description) .Add("pENDPOINT_PARAMS_GROUP_ID", request.EndpointParams.GroupId, SqlDbType.SmallInt) .Add("pENDPOINT_PARAMS_SEQUENCE", request.EndpointParams.Sequence, SqlDbType.TinyInt) .Add("pENDPOINT_PARAMS_KEY", request.EndpointParams.Key) .Add("pENDPOINT_PARAMS_VALUE", request.EndpointParams.Value) .Add("pPROFILE_ACTIVE", request.Profile.Active) .Add("pPROFILE_TYPE_ID", request.Profile.TypeId, SqlDbType.TinyInt) .Add("pPROFILE_MANDANTOR", request.Profile.Mandantor) .Add("pPROFILE_NAME", request.Profile.Name) .Add("pPROFILE_DESCRIPTION", request.Profile.Description) .Add("pPROFILE_LOG_LEVEL_ID", request.Profile.LogLevelId, SqlDbType.TinyInt) .Add("pPROFILE_LANGUAGE_ID", request.Profile.LanguageId, SqlDbType.SmallInt) .Add("pPROFILE_FIRST_RUN", request.Profile.FirstRun) .Add("pPROFILE_LAST_RUN", request.Profile.LastRun) .Add("pPROFILE_LAST_RESULT", request.Profile.LastResult) .Add("pRESULT_ACTION_ID", request.Result.ActionId) .Add("pRESULT_STATUS_ID", request.Result.StatusId, SqlDbType.TinyInt) .Add("pRESULT_HEADER", request.Result.Header) .Add("pRESULT_BODY", request.Result.Body) .Add("pRESULT_INFO_ID", request.Result.Info, SqlDbType.SmallInt) .Add("pRESULT_INFO_DETAIL", request.Result.InfoDetail) .Add("pRESULT_ERROR", request.Result.Error) .Add("pRESULT_BATCH_ID", request.Result.References?.BatchId) .Add("pRESULT_REFERENCE1", request.Result.References?.Reference1) .Add("pRESULT_REFERENCE2", request.Result.References?.Reference2) .Add("pRESULT_REFERENCE3", request.Result.References?.Reference3) .Add("pRESULT_REFERENCE4", request.Result.References?.Reference4) .Add("pRESULT_REFERENCE5", request.Result.References?.Reference5); try { var result = await repo.ExecuteQueryRawAsync(sp.BuildSql(), sp.BuildParameters(), cancel); if (result > 0) { throw new UpdateObjectFailedException(request, $"UpdateObject stored procedure failed with error code: {result}"); } return result; } catch (SqlException ex) { if (sqlExOpt.CurrentValue.BadRequestSqlExceptionNumbers.Contains(ex.Number)) throw new BadRequestException(ex.Message, ex); else throw; } } }