def set_entity_attribute(metric_uuid: MetricId, source_uuid: SourceId, entity_key: str, attribute: str, database: Database) -> dict: """Set an entity attribute.""" data = SourceData(latest_datamodel(database), latest_reports(database), source_uuid) old_measurement = latest_measurement(database, metric_uuid) new_measurement = old_measurement.copy() source = [ s for s in new_measurement["sources"] if s["source_uuid"] == source_uuid ][0] entity = [e for e in source["entities"] if e["key"] == entity_key][0] entity_description = "/".join( [entity[key] for key in entity.keys() if key not in ("key", "url")]) old_value = source.get("entity_user_data", {}).get(entity_key, {}).get(attribute) or "" new_value = dict(bottle.request.json)[attribute] source.setdefault("entity_user_data", {}).setdefault(entity_key, {})[attribute] = new_value user = sessions.user(database) new_measurement["delta"] = dict( uuids=[data.report_uuid, data.subject_uuid, metric_uuid, source_uuid], description= f"{user['user']} changed the {attribute} of '{entity_description}' from '{old_value}' to " f"'{new_value}'.", email=user["email"], ) return insert_new_measurement(database, data.datamodel, data.metric, new_measurement, old_measurement)
def post_metric_attribute(metric_uuid: MetricId, metric_attribute: str, database: Database): """Set the metric attribute.""" new_value = dict(bottle.request.json)[metric_attribute] data = MetricData(latest_datamodel(database), latest_reports(database), metric_uuid) if metric_attribute == "comment" and new_value: new_value = sanitize_html(new_value) old_value: Any if metric_attribute == "position": old_value, new_value = move_item(data, new_value, "metric") else: old_value = data.metric.get(metric_attribute) or "" if old_value == new_value: return dict(ok=True) # Nothing to do data.metric[metric_attribute] = new_value if metric_attribute == "type": data.metric.update(default_metric_attributes(database, new_value)) description = ( f"{{user}} changed the {metric_attribute} of metric '{data.metric_name}' of subject " f"'{data.subject_name}' in report '{data.report_name}' from '{old_value}' to '{new_value}'." ) uuids = [data.report_uuid, data.subject_uuid, metric_uuid] insert_new_report(database, description, (data.report, uuids)) if metric_attribute in ATTRIBUTES_IMPACTING_STATUS and ( latest := latest_measurement(database, metric_uuid)): return insert_new_measurement(database, data.datamodel, data.metric, latest.copy(), latest)
def post_metric_attribute(metric_uuid: MetricId, metric_attribute: str, database: Database): """Set the metric attribute.""" value = dict(bottle.request.json)[metric_attribute] data_model = latest_datamodel(database) reports = latest_reports(database) data = MetricData(data_model, reports, metric_uuid) if metric_attribute == "comment" and value: value = sanitize_html(value) old_value: Any if metric_attribute == "position": old_value, value = move_item(data, value, "metric") else: old_value = data.metric.get(metric_attribute) or "" if old_value == value: return dict(ok=True) # Nothing to do data.metric[metric_attribute] = value if metric_attribute == "type": data.metric.update(default_metric_attributes(database, value)) user = sessions.user(database) data.report["delta"] = dict( uuids=[data.report_uuid, data.subject_uuid, metric_uuid], email=user["email"], description= f"{user['user']} changed the {metric_attribute} of metric '{data.metric_name}' " f"of subject '{data.subject_name}' in report '{data.report_name}' from '{old_value}' to '{value}'." ) insert_new_report(database, data.report) attributes_impacting_status = ("accept_debt", "debt_target", "debt_end_date", "direction", "near_target", "target") if metric_attribute in attributes_impacting_status and ( latest := latest_measurement(database, metric_uuid)): return insert_new_measurement(database, data.datamodel, data.metric, latest)
ok=False ) # Metric does not exist, must've been deleted while being measured data_model = latest_datamodel(database) if latest := latest_measurement(database, metric_uuid): latest_successful = latest_successful_measurement( database, metric_uuid) latest_sources = latest_successful[ "sources"] if latest_successful else latest["sources"] copy_entity_user_data(latest_sources, measurement["sources"]) if not debt_target_expired( data_model, metric, latest) and latest["sources"] == measurement["sources"]: # If the new measurement is equal to the previous one, merge them together update_measurement_end(database, latest["_id"]) return dict(ok=True) return insert_new_measurement(database, data_model, metric, measurement, latest) def copy_entity_user_data(old_sources, new_sources) -> None: """Copy the entity user data from the old sources to the new sources.""" for old_source, new_source in zip(old_sources, new_sources): new_entity_keys = { entity["key"] for entity in new_source.get("entities", []) } # Sometimes the key Quality-time generates for entities needs to change, e.g. when it turns out not to be # unique. Create a mapping of old keys to new keys so we can move the entity user data to the new keys changed_entity_keys = { entity["old_key"]: entity["key"] for entity in new_source.get("entities", []) if "old_key" in entity }