Skip to content

Commit

Permalink
Primary rating
Browse files Browse the repository at this point in the history
  • Loading branch information
davidwatkins73 committed Jun 9, 2023
1 parent 772bbb3 commit dc5719d
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ public class MeasurableIdSelectorFactory implements IdSelectorFactory {
private final OrganisationalUnitIdSelectorFactory orgUnitIdSelectorFactory = new OrganisationalUnitIdSelectorFactory();


public static SelectConditionStep<Record1<Long>> allMeasurablesIdsInSameCategory(Long measurableId) {
return DSL
.select(MEASURABLE.ID)
.from(MEASURABLE)
.where(MEASURABLE.MEASURABLE_CATEGORY_ID.eq(DSL
.select(MEASURABLE.MEASURABLE_CATEGORY_ID)
.from(MEASURABLE)
.where(MEASURABLE.ID.eq(measurableId))));
}

@Override
public Select<Record1<Long>> apply(IdSelectionOptions options) {
switch (options.entityReference().kind()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import static org.finos.waltz.common.SetUtilities.union;
import static org.finos.waltz.common.StringUtilities.firstChar;
import static org.finos.waltz.common.StringUtilities.notEmpty;
import static org.finos.waltz.data.measurable.MeasurableIdSelectorFactory.allMeasurablesIdsInSameCategory;
import static org.finos.waltz.schema.Tables.*;
import static org.finos.waltz.schema.tables.Application.APPLICATION;
import static org.finos.waltz.schema.tables.Measurable.MEASURABLE;
Expand Down Expand Up @@ -103,6 +104,7 @@ public class MeasurableRatingDao {
.lastUpdatedAt(toLocalDateTime(r.getLastUpdatedAt()))
.lastUpdatedBy(r.getLastUpdatedBy())
.isReadOnly(r.getIsReadonly())
.isPrimary(r.getIsPrimary())
.build();
};

Expand All @@ -129,6 +131,7 @@ public class MeasurableRatingDao {
record.setLastUpdatedAt(Timestamp.valueOf(command.lastUpdate().at()));
record.setLastUpdatedBy(command.lastUpdate().by());
record.setProvenance(command.provenance());
record.setIsPrimary(command.isPrimary());
return record;
};

Expand Down Expand Up @@ -157,6 +160,7 @@ public Operation save(SaveMeasurableRatingCommand command, boolean ignoreReadOnl
.set(MEASURABLE_RATING.LAST_UPDATED_BY, command.lastUpdate().by())
.set(MEASURABLE_RATING.LAST_UPDATED_AT, command.lastUpdate().atTimestamp())
.set(MEASURABLE_RATING.PROVENANCE, command.provenance())
.set(MEASURABLE_RATING.IS_PRIMARY, command.isPrimary())
.where(MEASURABLE_RATING.ENTITY_ID.eq(command.entityReference().id()))
.and(MEASURABLE_RATING.ENTITY_KIND.eq(command.entityReference().kind().name()))
.and(MEASURABLE_RATING.MEASURABLE_ID.eq(command.measurableId()))
Expand All @@ -169,15 +173,15 @@ public Operation save(SaveMeasurableRatingCommand command, boolean ignoreReadOnl
throw new NotFoundException(
"MR_SAVE_UPDATE_FAILED",
format("Could find writable associated record to update for rating: %s", command));
};
}
return Operation.UPDATE;
} else {
if (dsl.executeInsert(record) != 1) {
throw new NotFoundException(
"MR_SAVE_INSERT_FAILED",
format("Creation of record failed: %s", command));
}
;

return Operation.ADD;
}
}
Expand Down Expand Up @@ -334,6 +338,7 @@ private SelectJoinStep<Record> mkBaseQuery() {
.from(MEASURABLE_RATING);
}


public Set<Operation> calculateAmendedRatingOperations(Set<Operation> operationsForEntityAssessment,
EntityReference entityReference,
long measurableId,
Expand Down Expand Up @@ -367,6 +372,7 @@ public Set<Operation> calculateAmendedRatingOperations(Set<Operation> operations
}
}


public Set<Operation> calculateAmendedAllocationOperations(Set<Operation> operationsForAllocation,
long categoryId,
String username) {
Expand All @@ -384,9 +390,9 @@ public Set<Operation> calculateAmendedAllocationOperations(Set<Operation> operat
} else {
return operationsForAllocation;
}

}


/**
* Takes a source measurable and will move all ratings, decommission dates, replacement applications and allocations to the target measurable where possible.
* If a value already exists on the target the migration is ignored, or in the case of allocations, aggregated.
Expand Down Expand Up @@ -564,7 +570,10 @@ public void migrateRatings(Long measurableId, Long targetId, String userId) {
targetId,
EntityKind.ALLOCATION,
Operation.UPDATE,
format("Removed %d ratings from measurable: %d where they could not be migrated due to an existing rating on the target", removedRatings, measurableId, targetId),
format("Removed %d ratings from measurable: %d where they could not be migrated due to an existing rating on the target (%d)",
removedRatings,
measurableId,
targetId),
userId);
}

Expand Down Expand Up @@ -605,13 +614,15 @@ private SelectOrderByStep<Record2<Long, String>> selectRatingsThatCanBeModified(
return migrations.except(targets);
}


private SelectConditionStep<Record2<Long, String>> mkEntitySelectForMeasurable(Long measurableId) {
return DSL
.select(Tables.MEASURABLE_RATING.ENTITY_ID, Tables.MEASURABLE_RATING.ENTITY_KIND)
.from(Tables.MEASURABLE_RATING)
.where(Tables.MEASURABLE_RATING.MEASURABLE_ID.eq(measurableId));
}


public int getSharedRatingsCount(Long measurableId, Long targetId) {

SelectConditionStep<Record2<Long, String>> targets = mkEntitySelectForMeasurable(targetId);
Expand All @@ -622,6 +633,7 @@ public int getSharedRatingsCount(Long measurableId, Long targetId) {
return dsl.fetchCount(sharedRatings);
}


public int getSharedDecommsCount(Long measurableId, Long targetId) {

SelectConditionStep<Record2<Long, String>> targets = mkEntitySelectForDecomm(targetId);
Expand Down Expand Up @@ -679,6 +691,7 @@ private SelectOrderByStep<Record3<Long, Long, String>> selectAllocsToBeSummed(Lo
return migrations.intersect(targets);
}


private SelectHavingStep<Record4<Long, Long, String, Integer>> selectAllocsToBeUpdated(Long measurableId, Long targetId) {

SelectOrderByStep<Record3<Long, Long, String>> valuesToBeSummed = selectAllocsToBeSummed(measurableId, targetId);
Expand All @@ -696,4 +709,26 @@ private SelectHavingStep<Record4<Long, Long, String, Integer>> selectAllocsToBeU
.groupBy(ALLOCATION.ALLOCATION_SCHEME_ID, ALLOCATION.ENTITY_ID, ALLOCATION.ENTITY_KIND);
}

/**
* Updates the given measurable rating to be set as primary.
* All other ratings for the same entity/category will be set to non-primary.
*
* @param tx the dsl connection to use
* @param entityId the entity id
* @param measurableId the measurbable id
*/
private void updateToPrimary(DSLContext tx, Long entityId, Long measurableId) {
tx.update(MEASURABLE_RATING)
.set(MEASURABLE_RATING.IS_PRIMARY, false)
.where(MEASURABLE_RATING.ENTITY_ID.eq(entityId))
.and(MEASURABLE_RATING.MEASURABLE_ID.eq(allMeasurablesIdsInSameCategory(measurableId)))
.execute();

tx.update(MEASURABLE_RATING)
.set(MEASURABLE_RATING.IS_PRIMARY, true)
.where(MEASURABLE_RATING.ENTITY_ID.eq(entityId))
.and(MEASURABLE_RATING.MEASURABLE_ID.eq(measurableId))
.execute();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.finos.waltz.model.DescriptionProvider;
import org.finos.waltz.model.EntityReference;
import org.finos.waltz.model.LastUpdatedProvider;
import org.finos.waltz.model.Nullable;
import org.finos.waltz.model.ProvenanceProvider;
import org.immutables.value.Value;

Expand All @@ -41,4 +42,7 @@ public abstract class MeasurableRating implements

@Value.Default
public boolean isReadOnly() { return false; }

@Nullable
public abstract Boolean isPrimary();
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.finos.waltz.model.DescriptionProvider;
import org.finos.waltz.model.Nullable;
import org.finos.waltz.model.ProvenanceProvider;
import org.immutables.value.Value;

Expand All @@ -34,5 +35,8 @@ public abstract class SaveMeasurableRatingCommand extends MeasurableRatingComman
public abstract char rating();
public abstract Optional<Character> previousRating();

@Nullable
public abstract Boolean isPrimary();

}

Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,14 @@
<!-- EDIT SECTION -->
<div ng-if="$ctrl.visibility.ratingEditor">

<span ng-if="$ctrl.selected.rating.isReadOnly">
<div>
<b style="font-weight: bolder">
<waltz-icon name="lock"></waltz-icon> Locked
</b>
<p style="padding-top: 1em;">
This rating has been marked as read only and cannot be edited
</p>
</div>
</span>
<div ng-if="$ctrl.selected.rating.isReadOnly">
<b style="font-weight: bolder">
<waltz-icon name="lock"></waltz-icon> Locked
</b>
<p style="padding-top: 1em;">
This rating has been marked as read only and cannot be edited
</p>
</div>

<span ng-if="!$ctrl.selected.rating.isReadOnly"
ng-include="'wmrep-rating-editor'">
Expand Down Expand Up @@ -244,6 +242,28 @@
</div>
</div>

<div class="row">
<div class="col-sm-3">
Primary:
</div>
<div class="col-sm-9">
<waltz-toggle icon-on="star"
state="$ctrl.selected.rating.isPrimary"
icon-off="star-o"
label-on="Primary"
label-off="Not Primary"
on-toggle="$ctrl.onPrimaryToggle()">
</waltz-toggle>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<p class="help-block small">
Only one primary rating is allowed per category, selecting this will deselect any other primary ratings for this entity
</p>
</div>
</div>

<!-- COMMENT -->
<div class="row"
style="padding-top: 8px;">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,16 @@ function controller($q,
};

const getDescription = () => _.get(vm.selected, ["rating", "description"], "");
const getIsPrimary = () => _.get(vm.selected, ["rating", "isPrimary"], "");

const getRating = () => _.get(vm.selected, ["rating", "rating"]);

const doRatingSave = (rating, description) => {
const doRatingSave = (rating, description, isPrimary) => {
const currentRating = !_.isEmpty(vm.selected.rating) ? vm.selected.rating.rating : null;
return serviceBroker
.execute(
CORE_API.MeasurableRatingStore.save,
[vm.parentEntityRef, vm.selected.measurable.id, rating, currentRating, description])
[vm.parentEntityRef, vm.selected.measurable.id, rating, currentRating, description, isPrimary])
.then(r => { vm.ratings = r.data })
.then(() => recalcTabs())
.then(() => {
Expand Down Expand Up @@ -318,7 +319,7 @@ function controller($q,
vm.saveInProgress = false;
displayError("Could not remove measurable rating.", e);
})
: doRatingSave(r, getDescription())
: doRatingSave(r, getDescription(), getIsPrimary())
.then(() => toasts.success(`Saved: ${vm.selected.measurable.name}`))
.catch(e => {
deselectMeasurable();
Expand Down Expand Up @@ -358,6 +359,10 @@ function controller($q,
}
};

vm.onPrimaryToggle = (d) => {
console.log("Toggling primary", d);
};


vm.onTabChange = () => {
deselectMeasurable();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@
</waltz-icon>
<span style="position: relative; top: -1px"
class="waltz-visibility-child-30">
<waltz-icon name="star"
ng-if="node.rating.isPrimary">
</waltz-icon>
<waltz-icon name="lock"
ng-if="node.rating.isReadOnly">
</waltz-icon>
Expand Down Expand Up @@ -128,6 +131,14 @@
<waltz-markdown text="node.rating.description"></waltz-markdown>
</div>

<div ng-if="node.rating.isPrimary"
style="border-top: 1px solid #eee; margin-top: 12px; padding-top: 4px"
class="text-muted">
<waltz-icon name="star">
</waltz-icon>
This feature has been marked as primary
</div>

<div ng-if="node.allocations.length > 0"
style="border-top: 1px solid #eee; margin-top: 12px; padding-top: 4px"
class="text-muted">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ function store($http, baseApiUrl) {
.then(d => d.data);
};

const save = (ref, measurableId, rating = "Z", previousRating, description = "") => {
const save = (ref, measurableId, rating = "Z", previousRating, description = "", isPrimary = false) => {
checkIsEntityRef(ref);
return $http
.post(`${baseUrl}/entity/${ref.kind}/${ref.id}/measurable/${measurableId}`, { rating, previousRating, description })
.post(`${baseUrl}/entity/${ref.kind}/${ref.id}/measurable/${measurableId}`, { rating, previousRating, description, isPrimary })
.then(d => d.data);
};

Expand Down
25 changes: 25 additions & 0 deletions waltz-schema/src/main/resources/liquibase/db.changelog-1.51.xml
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,29 @@
columnName="involvement_kind_ids"/>
</changeSet>

<changeSet id="20230601-6635-1"
author="davidwatkins73">
<addColumn tableName="measurable_rating">
<column name="is_primary"
type="boolean">
<constraints nullable="true"/>
</column>
</addColumn>
</changeSet>

<changeSet id="20230601-6635-2"
author="davidwatkins73">
<setColumnRemarks tableName="measurable_rating" columnName="measurable_id" remarks="reference to the measurable being rated against the entity" />
<setColumnRemarks tableName="measurable_rating" columnName="entity_id" remarks="reference to the entity identifier being rated against the measurable" />
<setColumnRemarks tableName="measurable_rating" columnName="entity_kind" remarks="reference to the entity_kind (typically APPLICATION) being rated against the measurable" />
<setColumnRemarks tableName="measurable_rating" columnName="description" remarks="optional comment" />
<setColumnRemarks tableName="measurable_rating" columnName="last_updated_by" remarks="user that last updated the rating" />
<setColumnRemarks tableName="measurable_rating" columnName="provenance" remarks="where the rating came from, 'waltz' if via the ui" />
<setColumnRemarks tableName="measurable_rating" columnName="last_updated_at" remarks="when the rating was last updated" />
<setColumnRemarks tableName="measurable_rating" columnName="rating" remarks="the rating code which identifies the rating scheme item used in the rating. This needs the measurable category to determine which scheme the code belongs to" />
<setColumnRemarks tableName="measurable_rating" columnName="is_readonly" remarks="flag to prevent updates via the UI" />
<setColumnRemarks tableName="measurable_rating" columnName="is_primary" remarks="optional flag to indicate the measurable is the primary one for the entity in it's category" />
</changeSet>


</databaseChangeLog>
Loading

0 comments on commit dc5719d

Please sign in to comment.