Skip to content

Commit d72de71

Browse files
Add errors checking on server side
#CTCTOWALTZ-2708 #6612
1 parent 3a824b1 commit d72de71

4 files changed

Lines changed: 125 additions & 60 deletions

File tree

waltz-data/src/main/java/org/finos/waltz/data/measurable_rating/MeasurableRatingDao.java

Lines changed: 64 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -446,22 +446,25 @@ public void migrateRatings(Long measurableId, Long targetId, String userId) {
446446
.select(ratingsToInsert)
447447
.execute();
448448

449-
writeChangeLogForMerge(
450-
tx,
451-
targetId,
452-
EntityKind.MEASURABLE_RATING,
453-
Operation.UPDATE,
454-
format("Migrated %d ratings from measurable: %d to %d", migratedRatings, measurableId, targetId),
455-
userId);
456-
457-
writeChangeLogForMerge(
458-
tx,
459-
targetId,
460-
EntityKind.MEASURABLE_RATING,
461-
Operation.REMOVE,
462-
format("Failed to migrate %d ratings from measurable: %d to %d due to existing ratings on the target", sharedRatingCount, measurableId, targetId),
463-
userId);
449+
if (migratedRatings > 0) {
450+
writeChangeLogForMerge(
451+
tx,
452+
targetId,
453+
EntityKind.MEASURABLE_RATING,
454+
Operation.UPDATE,
455+
format("Migrated %d ratings from measurable: %d to %d", migratedRatings, measurableId, targetId),
456+
userId);
457+
}
464458

459+
if (sharedRatingCount > 0) {
460+
writeChangeLogForMerge(
461+
tx,
462+
targetId,
463+
EntityKind.MEASURABLE_RATING,
464+
Operation.REMOVE,
465+
format("Failed to migrate %d ratings from measurable: %d to %d due to existing ratings on the target", sharedRatingCount, measurableId, targetId),
466+
userId);
467+
}
465468

466469
// DECOMMS
467470

@@ -476,21 +479,25 @@ public void migrateRatings(Long measurableId, Long targetId, String userId) {
476479
.and(MEASURABLE_RATING_PLANNED_DECOMMISSION.MEASURABLE_ID.eq(measurableId))))
477480
.execute();
478481

479-
writeChangeLogForMerge(
480-
tx,
481-
targetId,
482-
EntityKind.MEASURABLE_RATING_PLANNED_DECOMMISSION,
483-
Operation.UPDATE,
484-
format("Migrated %d decomms from measurable: %d to %d", migratedRatings, measurableId, targetId),
485-
userId);
482+
if (migratedDecoms > 0) {
483+
writeChangeLogForMerge(
484+
tx,
485+
targetId,
486+
EntityKind.MEASURABLE_RATING_PLANNED_DECOMMISSION,
487+
Operation.UPDATE,
488+
format("Migrated %d decomms from measurable: %d to %d", migratedDecoms, measurableId, targetId),
489+
userId);
490+
}
486491

487-
writeChangeLogForMerge(
488-
tx,
489-
targetId,
490-
EntityKind.MEASURABLE_RATING_PLANNED_DECOMMISSION,
491-
Operation.REMOVE,
492-
format("Failed to migrate %d decomms from measurable: %d to %d due to existing decomms on the target", sharedDecomCount, measurableId, targetId),
493-
userId);
492+
if (sharedDecomCount > 0) {
493+
writeChangeLogForMerge(
494+
tx,
495+
targetId,
496+
EntityKind.MEASURABLE_RATING_PLANNED_DECOMMISSION,
497+
Operation.REMOVE,
498+
format("Failed to migrate %d decomms from measurable: %d to %d due to existing decomms on the target", sharedDecomCount, measurableId, targetId),
499+
userId);
500+
}
494501

495502

496503
// ALLOCATIONS
@@ -518,22 +525,25 @@ public void migrateRatings(Long measurableId, Long targetId, String userId) {
518525
.and(ALLOCATION.MEASURABLE_ID.eq(targetId)))))
519526
.execute();
520527

521-
writeChangeLogForMerge(
522-
tx,
523-
targetId,
524-
EntityKind.ALLOCATION,
525-
Operation.UPDATE,
526-
format("Migrated %d allocations from measurable: %d to %d", migratedRatings, measurableId, targetId),
527-
userId);
528-
529-
writeChangeLogForMerge(
530-
tx,
531-
targetId,
532-
EntityKind.ALLOCATION,
533-
Operation.REMOVE,
534-
format("Merged %d allocations from measurable: %d to %d due to an existing allocation on the target", sharedDecomCount, measurableId, targetId),
535-
userId);
528+
if (migratedAllocs > 0) {
529+
writeChangeLogForMerge(
530+
tx,
531+
targetId,
532+
EntityKind.ALLOCATION,
533+
Operation.UPDATE,
534+
format("Migrated %d allocations from measurable: %d to %d", migratedAllocs, measurableId, targetId),
535+
userId);
536+
}
536537

538+
if (mergedAllocs > 0) {
539+
writeChangeLogForMerge(
540+
tx,
541+
targetId,
542+
EntityKind.ALLOCATION,
543+
Operation.UPDATE,
544+
format("Merged %d allocations from measurable: %d to %d where there was an existing allocation on the target", mergedAllocs, measurableId, targetId),
545+
userId);
546+
}
537547

538548
LOG.info(format("Migrated %d ratings, %d decomms, %d/%d allocations (migrated/merged) from measurable: %d to %d",
539549
migratedRatings,
@@ -548,6 +558,16 @@ public void migrateRatings(Long measurableId, Long targetId, String userId) {
548558
.where(Tables.MEASURABLE_RATING.MEASURABLE_ID.eq(measurableId))
549559
.execute();
550560

561+
if (removedRatings > 0) {
562+
writeChangeLogForMerge(
563+
tx,
564+
targetId,
565+
EntityKind.ALLOCATION,
566+
Operation.UPDATE,
567+
format("Removed %d ratings from measurable: %d where they could not be migrated due to an existing rating on the target", removedRatings, measurableId, targetId),
568+
userId);
569+
}
570+
551571
// allocations, decomms and replacements are automatically cleared up via cascade delete on fk
552572
LOG.info("Removed {} measurable ratings and any associated allocations, planned decommissions and replacement applications after migration", removedRatings);
553573
});

waltz-ng/client/measurable/components/change-control/measurable-change-control.js

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,15 @@ function controller($scope,
7171
const vm = initialiseData(this, initialState);
7272

7373
function mkCmd(params = {}) {
74+
7475
const paramProcessor = vm.selectedOperation.paramProcessor || _.identity;
76+
const processedParam = paramProcessor(params);
7577

7678
return {
7779
changeType: vm.selectedOperation.code,
7880
changeDomain: toEntityRef(vm.changeDomain),
7981
primaryReference: toEntityRef(vm.measurable),
80-
params: paramProcessor(params),
82+
params: processedParam,
8183
createdBy: vm.userName,
8284
lastUpdatedBy: vm.userName
8385
};
@@ -88,7 +90,7 @@ function controller($scope,
8890
}
8991

9092
function mkPreviewCmd() {
91-
return mkCmd();
93+
return mkCmd(vm.commandParams);
9294
}
9395

9496
function calcPreview() {
@@ -278,26 +280,34 @@ function controller($scope,
278280
onShow: () => {
279281
resetForm();
280282
calcPreview();
281-
vm.submitDisabled = false;
282283
},
283284
paramProcessor: (d) => _.isEmpty(d)
284285
? {}
285286
: ({
286287
targetId: d.target.id,
287288
targetName: d.target.name
288289
}),
290+
onReset: () => {
291+
vm.commandParams.target = null;
292+
vm.submitDisabled = true;
293+
},
289294
onChange: (target) => {
290-
if (target.id === vm.measurable.id) {
295+
if (target === null) {
296+
toasts.warning("Must have selected a arget to merge, ignoring....");
297+
vm.commandParams.target = null;
298+
vm.submitDisabled = true;
299+
} else if (target.id === vm.measurable.id) {
291300
toasts.warning("Cannot merge onto yourself, ignoring....");
292-
vm.commandParams.destination = null;
301+
vm.commandParams.target = null;
293302
vm.submitDisabled = true;
294303
} else if (vm.measurable.concrete && !target.concrete) {
295304
toasts.warning("Cannot migrate to a non-concrete node, ignoring....");
296-
vm.commandParams.destination = null;
305+
vm.commandParams.target = null;
297306
vm.submitDisabled = true;
298307
} else {
299308
vm.commandParams.target = target;
300309
vm.submitDisabled = false;
310+
calcPreview();
301311
}
302312
}
303313
},

waltz-service/src/main/java/org/finos/waltz/service/taxonomy_management/TaxonomyManagementUtilities.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import static java.lang.String.format;
3939
import static org.finos.waltz.common.Checks.*;
40+
import static org.finos.waltz.common.CollectionUtilities.any;
4041
import static org.finos.waltz.common.SetUtilities.fromCollection;
4142
import static org.finos.waltz.common.SetUtilities.minus;
4243
import static org.finos.waltz.model.IdSelectionOptions.mkOpts;
@@ -70,8 +71,8 @@ public static void validateMeasurablesInCategory(MeasurableService measurableSer
7071

7172

7273
public static Measurable validateMeasurableInCategory(MeasurableService measurableService,
73-
long measurableId,
74-
long categoryId) {
74+
long measurableId,
75+
long categoryId) {
7576
Measurable measurable = measurableService.getById(measurableId);
7677

7778
checkNotNull(
@@ -90,6 +91,36 @@ public static Measurable validateMeasurableInCategory(MeasurableService measurab
9091
return measurable;
9192
}
9293

94+
public static void validateTargetNotChild(MeasurableService measurableService,
95+
Measurable measurable,
96+
Measurable targetMeasurable) {
97+
98+
List<Measurable> children = measurableService.findByMeasurableIdSelector(mkOpts(
99+
measurable.entityReference(),
100+
HierarchyQueryScope.CHILDREN));
101+
102+
checkFalse(
103+
any(children, d -> d.equals(targetMeasurable)),
104+
format("Target measurable [%s / %d] is a child of measurable [%s / %d]",
105+
targetMeasurable.name(),
106+
targetMeasurable.id().get(),
107+
measurable.name(),
108+
measurable.id().get()));
109+
}
110+
111+
112+
public static void validateConcreteMergeAllowed(Measurable measurable,
113+
Measurable targetMeasurable) {
114+
115+
checkFalse(
116+
measurable.concrete() && !targetMeasurable.concrete(),
117+
format("Measurable [%s / %d] is concrete but target measurable [%s / %d] is abstract",
118+
measurable.name(),
119+
measurable.id().get(),
120+
targetMeasurable.name(),
121+
targetMeasurable.id().get()));
122+
}
123+
93124

94125
public static Set<EntityReference> findCurrentRatingMappings(MeasurableRatingService measurableRatingService,
95126
TaxonomyChangeCommand cmd) {
@@ -106,10 +137,10 @@ public static Set<EntityReference> findCurrentRatingMappings(MeasurableRatingSer
106137
* Optionally add an impact to the given preview and return it.
107138
* Whether to add the impact is determined by the presence of references.
108139
*
109-
* @param preview The preview builder to update
110-
* @param refs Set of references, if empty no impact will be added to the preview
111-
* @param severity Severity of the impact
112-
* @param msg Description of the impact
140+
* @param preview The preview builder to update
141+
* @param impactCount Count of the records affected by this change
142+
* @param severity Severity of the impact
143+
* @param msg Description of the impact
113144
* @return The preview builder for convenience
114145
*/
115146
public static ImmutableTaxonomyChangePreview.Builder addToPreview(ImmutableTaxonomyChangePreview.Builder preview,

waltz-service/src/main/java/org/finos/waltz/service/taxonomy_management/processors/MergeMeasurableCommandProcessor.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import static java.lang.String.format;
3636
import static org.finos.waltz.common.Checks.checkNotNull;
3737
import static org.finos.waltz.model.IdSelectionOptions.mkOpts;
38-
import static org.finos.waltz.service.taxonomy_management.TaxonomyManagementUtilities.validateMeasurableInCategory;
38+
import static org.finos.waltz.service.taxonomy_management.TaxonomyManagementUtilities.*;
3939

4040
@Service
4141
public class MergeMeasurableCommandProcessor implements TaxonomyCommandProcessor {
@@ -87,6 +87,8 @@ public TaxonomyChangePreview preview(TaxonomyChangeCommand cmd) {
8787
if (target != null) {
8888
taxonomyManagementHelper.previewRatingMigrations(previewBuilder, opts.entityReference().id(), target);
8989
taxonomyManagementHelper.previewDecommMigrations(previewBuilder, opts.entityReference().id(), target);
90+
} else {
91+
previewBuilder.errorMessage("Target is null, cannot merge cannot be performed");
9092
}
9193

9294
ImmutableTaxonomyChangePreview preview = previewBuilder.build();
@@ -138,12 +140,14 @@ public TaxonomyChangeCommand apply(TaxonomyChangeCommand cmd, String userId) {
138140
private Measurable validate(TaxonomyChangeCommand cmd) {
139141
doBasicValidation(cmd);
140142
long categoryId = cmd.changeDomain().id();
141-
Measurable m = validateMeasurableInCategory(measurableService, cmd.primaryReference().id(), categoryId);
143+
Measurable measurable = validateMeasurableInCategory(measurableService, cmd.primaryReference().id(), categoryId);
142144
Long targetId = getTarget(cmd);
143145
if (targetId != null) {
144-
validateMeasurableInCategory(measurableService, targetId, categoryId);
146+
Measurable target = validateMeasurableInCategory(measurableService, targetId, categoryId);
147+
validateTargetNotChild(measurableService, measurable, target);
148+
validateConcreteMergeAllowed(measurable, target);
145149
}
146-
return m;
150+
return measurable;
147151
}
148152

149153

0 commit comments

Comments
 (0)