def save(self, *args, **kwargs): experiment = super().save(*args, **kwargs) old_values = {} new_values = {} old_status = None self.new_serialized_vals = ChangeLogSerializer(self.instance).data latest_change = experiment.changes.latest() # account for changes in variant values if latest_change: old_status = latest_change.new_status if (self.old_serialized_vals["variants"] != self.new_serialized_vals["variants"]): old_values["variants"] = self.old_serialized_vals["variants"] new_values["variants"] = self.new_serialized_vals["variants"] elif self.new_serialized_vals.get("variants"): old_values["variants"] = None new_values["variants"] = self.new_serialized_vals["variants"] if self.changed_data: if latest_change: old_status = latest_change.new_status for field in self.changed_data: if field in self.old_serialized_vals: old_values[field] = self.old_serialized_vals[field] else: prev_values = {field: None for field in self.changed_data} old_values.update(prev_values) for field in self.changed_data: if field in self.new_serialized_vals: new_values[field] = self.new_serialized_vals[field] ExperimentChangeLog.objects.create( experiment=experiment, changed_by=self.request.user, old_status=old_status, new_status=experiment.status, old_values=old_values, new_values=new_values, message=self.get_changelog_message(), ) return experiment
def __init__(self, request, *args, **kwargs): self.request = request super().__init__(*args, **kwargs) if self.instance.id: self.old_serialized_vals = ChangeLogSerializer(self.instance).data
class ChangeLogMixin(object): def __init__(self, request, *args, **kwargs): self.request = request super().__init__(*args, **kwargs) if self.instance.id: self.old_serialized_vals = ChangeLogSerializer(self.instance).data def get_changelog_message(self): return "" def save(self, *args, **kwargs): experiment = super().save(*args, **kwargs) changed_values = {} old_status = None self.new_serialized_vals = ChangeLogSerializer(self.instance).data latest_change = experiment.changes.latest() # account for changes in variant values if latest_change: old_status = latest_change.new_status if (self.old_serialized_vals["variants"] != self.new_serialized_vals["variants"]): old_value = self.old_serialized_vals["variants"] new_value = self.new_serialized_vals["variants"] display_name = "Branches" changed_values["variants"] = { "old_value": old_value, "new_value": new_value, "display_name": display_name, } elif self.new_serialized_vals.get("variants"): old_value = None new_value = self.new_serialized_vals["variants"] display_name = "Branches" changed_values["variants"] = { "old_value": old_value, "new_value": new_value, "display_name": display_name, } if self.changed_data: if latest_change: old_status = latest_change.new_status for field in self.changed_data: old_val = None new_val = None if field in self.old_serialized_vals: if field in ("countries", "locales"): old_field_values = self.old_serialized_vals[field] codes = [obj["code"] for obj in old_field_values] old_val = codes else: old_val = self.old_serialized_vals[field] if field in self.new_serialized_vals: if field in ("countries", "locales"): new_field_values = self.new_serialized_vals[field] codes = [obj["code"] for obj in new_field_values] new_val = codes else: new_val = self.new_serialized_vals[field] display_name = self._get_display_name(field) if new_val or old_val: changed_values[field] = { "old_value": old_val, "new_value": new_val, "display_name": display_name, } else: for field in self.changed_data: old_val = None new_val = None if field in self.new_serialized_vals: if field in ("countries", "locales"): new_field_values = self.new_serialized_vals[field] codes = [obj["code"] for obj in new_field_values] new_val = codes else: new_val = self.new_serialized_vals[field] display_name = self._get_display_name(field) changed_values[field] = { "old_value": old_val, "new_value": new_val, "display_name": display_name, } if self._has_changed(old_status, changed_values, experiment): ExperimentChangeLog.objects.create( experiment=experiment, changed_by=self.request.user, old_status=old_status, new_status=experiment.status, changed_values=changed_values, message=self.get_changelog_message(), ) return experiment def _get_display_name(self, field): if self.fields[field].label: return self.fields[field].label return field.replace("_", " ").title() def _has_changed(self, old_status, changed_values, experiment): return (changed_values or self.get_changelog_message() or old_status != experiment.status)
def save(self, *args, **kwargs): experiment = super().save(*args, **kwargs) changed_values = {} old_status = None self.new_serialized_vals = ChangeLogSerializer(self.instance).data latest_change = experiment.changes.latest() # account for changes in variant values if latest_change: old_status = latest_change.new_status if (self.old_serialized_vals["variants"] != self.new_serialized_vals["variants"]): old_value = self.old_serialized_vals["variants"] new_value = self.new_serialized_vals["variants"] display_name = "Branches" changed_values["variants"] = { "old_value": old_value, "new_value": new_value, "display_name": display_name, } elif self.new_serialized_vals.get("variants"): old_value = None new_value = self.new_serialized_vals["variants"] display_name = "Branches" changed_values["variants"] = { "old_value": old_value, "new_value": new_value, "display_name": display_name, } if self.changed_data: if latest_change: old_status = latest_change.new_status for field in self.changed_data: old_val = None new_val = None if field in self.old_serialized_vals: if field in ("countries", "locales"): old_field_values = self.old_serialized_vals[field] codes = [obj["code"] for obj in old_field_values] old_val = codes else: old_val = self.old_serialized_vals[field] if field in self.new_serialized_vals: if field in ("countries", "locales"): new_field_values = self.new_serialized_vals[field] codes = [obj["code"] for obj in new_field_values] new_val = codes else: new_val = self.new_serialized_vals[field] display_name = self._get_display_name(field) if new_val or old_val: changed_values[field] = { "old_value": old_val, "new_value": new_val, "display_name": display_name, } else: for field in self.changed_data: old_val = None new_val = None if field in self.new_serialized_vals: if field in ("countries", "locales"): new_field_values = self.new_serialized_vals[field] codes = [obj["code"] for obj in new_field_values] new_val = codes else: new_val = self.new_serialized_vals[field] display_name = self._get_display_name(field) changed_values[field] = { "old_value": old_val, "new_value": new_val, "display_name": display_name, } ExperimentChangeLog.objects.create( experiment=experiment, changed_by=self.request.user, old_status=old_status, new_status=experiment.status, changed_values=changed_values, message=self.get_changelog_message(), ) return experiment
def test_serializer_outputs_expected_schema(self): country1 = CountryFactory(code="CA", name="Canada") locale1 = LocaleFactory(code="da", name="Danish") experiment = ExperimentFactory.create(locales=[locale1], countries=[country1]) serializer = ChangeLogSerializer(experiment) risk_tech_description = experiment.risk_technical_description # ensure expected_data has "string" if pref_type is json string pref_type = PrefTypeField().to_representation(experiment.pref_type) expected_data = { "type": experiment.type, "status": experiment.status, "owner": experiment.owner.id, "name": experiment.name, "short_description": experiment.short_description, "related_work": experiment.related_work, "proposed_start_date": str(experiment.proposed_start_date), "proposed_duration": experiment.proposed_duration, "proposed_enrollment": experiment.proposed_enrollment, "addon_experiment_id": experiment.addon_experiment_id, "addon_release_url": experiment.addon_release_url, "pref_key": experiment.pref_key, "pref_type": pref_type, "pref_branch": experiment.pref_branch, "public_name": experiment.public_name, "public_description": experiment.public_description, "population_percent": "{0:.4f}".format(experiment.population_percent), "firefox_min_version": experiment.firefox_min_version, "firefox_max_version": experiment.firefox_max_version, "firefox_channel": experiment.firefox_channel, "client_matching": experiment.client_matching, "locales": [{ "code": "da", "name": "Danish" }], "countries": [{ "code": "CA", "name": "Canada" }], "platform": experiment.platform, "objectives": experiment.objectives, "analysis": experiment.analysis, "analysis_owner": experiment.analysis_owner, "survey_required": experiment.survey_required, "survey_urls": experiment.survey_urls, "survey_instructions": experiment.survey_instructions, "engineering_owner": experiment.engineering_owner, "bugzilla_id": experiment.bugzilla_id, "normandy_slug": experiment.normandy_slug, "normandy_id": experiment.normandy_id, "data_science_bugzilla_url": experiment.data_science_bugzilla_url, "feature_bugzilla_url": experiment.feature_bugzilla_url, "risk_internal_only": experiment.risk_internal_only, "risk_partner_related": experiment.risk_partner_related, "risk_brand": experiment.risk_brand, "risk_fast_shipped": experiment.risk_fast_shipped, "risk_confidential": experiment.risk_confidential, "risk_release_population": experiment.risk_release_population, "risk_revenue": experiment.risk_revenue, "risk_data_category": experiment.risk_data_category, "risk_external_team_impact": experiment.risk_external_team_impact, "risk_telemetry_data": experiment.risk_telemetry_data, "risk_ux": experiment.risk_ux, "risk_security": experiment.risk_security, "risk_revision": experiment.risk_revision, "risk_technical": experiment.risk_technical, "risk_technical_description": risk_tech_description, "risks": experiment.risks, "testing": experiment.testing, "test_builds": experiment.test_builds, "qa_status": experiment.qa_status, "review_science": experiment.review_science, "review_engineering": experiment.review_engineering, "review_qa_requested": experiment.review_qa_requested, "review_intent_to_ship": experiment.review_intent_to_ship, "review_bugzilla": experiment.review_bugzilla, "review_qa": experiment.review_qa, "review_relman": experiment.review_relman, "review_advisory": experiment.review_advisory, "review_legal": experiment.review_legal, "review_ux": experiment.review_ux, "review_security": experiment.review_security, "review_vp": experiment.review_vp, "review_data_steward": experiment.review_data_steward, "review_comms": experiment.review_comms, "review_impacted_teams": experiment.review_impacted_teams, "variants": [ ExperimentVariantSerializer(variant).data for variant in experiment.variants.all() ], } self.assertEqual(set(serializer.data.keys()), set(expected_data.keys())) self.assertEqual(serializer.data, expected_data)