From d8706cad5e13b5bd92e91cb8d014ed3807d50a62 Mon Sep 17 00:00:00 2001 From: Antoine Popineau Date: Fri, 17 Jan 2025 17:04:38 +0100 Subject: [PATCH] Continue implementing API for scenario config around Sanction Check. --- dto/scenario_iterations.go | 28 ++++++++-------- models/scenario_iterations.go | 12 ++++++- .../sanction_check_config_repository.go | 33 +++++++++++++------ usecases/sanction_check_config_usecase.go | 2 +- usecases/scenario_iterations_usecase.go | 12 +++++-- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/dto/scenario_iterations.go b/dto/scenario_iterations.go index 8b31727c..dd70cd0d 100644 --- a/dto/scenario_iterations.go +++ b/dto/scenario_iterations.go @@ -7,6 +7,7 @@ import ( "github.com/cockroachdb/errors" "github.com/checkmarble/marble-backend/models" + "github.com/checkmarble/marble-backend/utils" ) // Read DTO @@ -35,7 +36,7 @@ type ScenarioIterationBodyDto struct { } type SanctionCheckConfig struct { - Enabled bool `json:"enabled"` + Enabled *bool `json:"enabled"` ForceOutcome *string `json:"force_outcome,omitempty"` ScoreModifier *int `json:"score_modifier,omitempty"` } @@ -60,7 +61,7 @@ func AdaptScenarioIterationWithBodyDto(si models.ScenarioIteration) (ScenarioIte } if si.SanctionCheckConfig != nil { body.SanctionCheckConfig = &SanctionCheckConfig{ - Enabled: si.SanctionCheckConfig.Enabled, + Enabled: &si.SanctionCheckConfig.Enabled, ForceOutcome: nil, ScoreModifier: &si.SanctionCheckConfig.Outcome.ScoreModifier, } @@ -118,22 +119,21 @@ func AdaptUpdateScenarioIterationInput(input UpdateScenarioIterationBody, iterat } if input.Body.SanctionCheckConfig != nil { - var forcedOutcome models.Outcome - var scoreModifier int + updateScenarioIterationInput.Body.SanctionCheckConfig = &models.UpdateSanctionCheckConfigInput{ + Enabled: input.Body.SanctionCheckConfig.Enabled, + Outcome: models.UpdateSanctionCheckOutcomeInput{ + ForceOutcome: nil, + ScoreModifier: nil, + }, + } if input.Body.SanctionCheckConfig.ForceOutcome != nil { - forcedOutcome = models.OutcomeFrom(*input.Body.SanctionCheckConfig.ForceOutcome) + updateScenarioIterationInput.Body.SanctionCheckConfig.Outcome.ForceOutcome = utils.Ptr(models.OutcomeFrom( + *input.Body.SanctionCheckConfig.ForceOutcome)) } if input.Body.SanctionCheckConfig.ScoreModifier != nil { - scoreModifier = *input.Body.SanctionCheckConfig.ScoreModifier - } - - updateScenarioIterationInput.Body.SanctionCheckConfig = &models.SanctionCheckConfig{ - Enabled: input.Body.SanctionCheckConfig.Enabled, - Outcome: models.SanctionCheckOutcome{ - ForceOutcome: forcedOutcome, - ScoreModifier: scoreModifier, - }, + updateScenarioIterationInput.Body.SanctionCheckConfig.Outcome.ScoreModifier = + input.Body.SanctionCheckConfig.ScoreModifier } } diff --git a/models/scenario_iterations.go b/models/scenario_iterations.go index 13120429..1b0b32bb 100644 --- a/models/scenario_iterations.go +++ b/models/scenario_iterations.go @@ -47,7 +47,7 @@ type UpdateScenarioIterationInput struct { type UpdateScenarioIterationBody struct { TriggerConditionAstExpression *ast.Node - SanctionCheckConfig *SanctionCheckConfig + SanctionCheckConfig *UpdateSanctionCheckConfigInput ScoreReviewThreshold *int ScoreBlockAndReviewThreshold *int ScoreDeclineThreshold *int @@ -63,3 +63,13 @@ type SanctionCheckOutcome struct { ForceOutcome Outcome ScoreModifier int } + +type UpdateSanctionCheckConfigInput struct { + Enabled *bool + Outcome UpdateSanctionCheckOutcomeInput +} + +type UpdateSanctionCheckOutcomeInput struct { + ForceOutcome *Outcome + ScoreModifier *int +} diff --git a/repositories/sanction_check_config_repository.go b/repositories/sanction_check_config_repository.go index 61a73ca8..a5e0882b 100644 --- a/repositories/sanction_check_config_repository.go +++ b/repositories/sanction_check_config_repository.go @@ -22,11 +22,12 @@ func (repo *MarbleDbRepository) GetSanctionCheckConfig(ctx context.Context, exec } func (repo *MarbleDbRepository) UpdateSanctionCheckConfig(ctx context.Context, exec Executor, - scenarioIterationId string, sanctionCheckConfig models.SanctionCheckConfig, + scenarioIterationId string, sanctionCheckConfig models.UpdateSanctionCheckConfigInput, ) (models.SanctionCheckConfig, error) { var outcome *string - if sanctionCheckConfig.Outcome.ForceOutcome != models.Approve { + if sanctionCheckConfig.Outcome.ForceOutcome != nil && + *sanctionCheckConfig.Outcome.ForceOutcome != models.Approve { outcome = utils.Ptr(sanctionCheckConfig.Outcome.ForceOutcome.String()) } @@ -36,14 +37,26 @@ func (repo *MarbleDbRepository) UpdateSanctionCheckConfig(ctx context.Context, e Values(scenarioIterationId, sanctionCheckConfig.Enabled, outcome, sanctionCheckConfig.Outcome.ScoreModifier). - Suffix("ON CONFLICT (scenario_iteration_id) DO UPDATE"). - Suffix(`SET - enabled = EXCLUDED.enabled, - forced_outcome = EXCLUDED.forced_outcome, - score_modifier = EXCLUDED.score_modifier, - updated_at = NOW() - `). - Suffix(fmt.Sprintf("RETURNING %s", strings.Join(dbmodels.SanctionCheckConfigColumnList, ","))) + Suffix("ON CONFLICT (scenario_iteration_id) DO UPDATE SET") + + updateFields := make([]string, 0, 4) + + if sanctionCheckConfig.Enabled != nil { + updateFields = append(updateFields, "enabled = EXCLUDED.enabled") + } + if sanctionCheckConfig.Outcome.ForceOutcome != nil { + updateFields = append(updateFields, "forced_outcome = EXCLUDED.forced_outcome") + } + if sanctionCheckConfig.Outcome.ScoreModifier != nil { + updateFields = append(updateFields, "score_modifier = EXCLUDED.score_modifier") + } + + updateFields = append(updateFields, "updated_at = NOW()") + + sql = sql.Suffix(strings.Join(updateFields, ",")) + + sql = sql.Suffix(fmt.Sprintf("RETURNING %s", + strings.Join(dbmodels.SanctionCheckConfigColumnList, ","))) return SqlToModel(ctx, exec, sql, dbmodels.AdaptSanctionCheckConfig) } diff --git a/usecases/sanction_check_config_usecase.go b/usecases/sanction_check_config_usecase.go index a63fed63..ef6dcb94 100644 --- a/usecases/sanction_check_config_usecase.go +++ b/usecases/sanction_check_config_usecase.go @@ -10,7 +10,7 @@ import ( type SanctionCheckConfigRepository interface { GetSanctionCheckConfig(ctx context.Context, exec repositories.Executor, scenarioIterationId string) (models.SanctionCheckConfig, error) UpdateSanctionCheckConfig(ctx context.Context, exec repositories.Executor, - scenarioIterationId string, sanctionCheckConfig models.SanctionCheckConfig) (models.SanctionCheckConfig, error) + scenarioIterationId string, sanctionCheckConfig models.UpdateSanctionCheckConfigInput) (models.SanctionCheckConfig, error) } // TODO: Will we have a usecase for sanction checks? diff --git a/usecases/scenario_iterations_usecase.go b/usecases/scenario_iterations_usecase.go index 773b8321..44fc97bd 100644 --- a/usecases/scenario_iterations_usecase.go +++ b/usecases/scenario_iterations_usecase.go @@ -303,8 +303,16 @@ func (usecase *ScenarioIterationUsecase) CreateDraftFromScenarioIteration( ctx, tx, organizationId, createScenarioIterationInput) if sanctionCheckConfig != nil { - if _, err := usecase.sanctionCheckConfigRepository.UpdateSanctionCheckConfig(ctx, tx, - newScenarioIteration.Id, *sanctionCheckConfig); err != nil { + newSanctionCheckConfig := models.UpdateSanctionCheckConfigInput{ + Enabled: &sanctionCheckConfig.Enabled, + Outcome: models.UpdateSanctionCheckOutcomeInput{ + ForceOutcome: &sanctionCheckConfig.Outcome.ForceOutcome, + ScoreModifier: &sanctionCheckConfig.Outcome.ScoreModifier, + }, + } + + if _, err := usecase.sanctionCheckConfigRepository.UpdateSanctionCheckConfig( + ctx, tx, scenarioIterationId, newSanctionCheckConfig); err != nil { return models.ScenarioIteration{}, errors.Wrap(err, "could not duplicate sanction check config for new iteration") }