| 113 | |
| 114 | |
| 115 | class MultivariateFeatureStateValue( |
| 116 | LifecycleModelMixin, # type: ignore[misc] |
| 117 | AbstractBaseExportableModel, |
| 118 | abstract_base_auditable_model_factory(["uuid"]), # type: ignore[misc] |
| 119 | ): |
| 120 | history_record_class_path = ( |
| 121 | "features.multivariate.models.HistoricalMultivariateFeatureStateValue" |
| 122 | ) |
| 123 | related_object_type = RelatedObjectType.FEATURE_STATE |
| 124 | |
| 125 | feature_state = models.ForeignKey( |
| 126 | "features.FeatureState", |
| 127 | on_delete=models.CASCADE, |
| 128 | related_name="multivariate_feature_state_values", |
| 129 | ) |
| 130 | multivariate_feature_option = models.ForeignKey( |
| 131 | MultivariateFeatureOption, on_delete=models.CASCADE |
| 132 | ) |
| 133 | |
| 134 | percentage_allocation = models.FloatField( |
| 135 | validators=[MinValueValidator(0), MaxValueValidator(100)], |
| 136 | ) |
| 137 | |
| 138 | class Meta: |
| 139 | unique_together = ("feature_state", "multivariate_feature_option") |
| 140 | |
| 141 | @hook(BEFORE_SAVE) |
| 142 | def validate_unique(self, exclude=None): # type: ignore[no-untyped-def] |
| 143 | """ |
| 144 | Override validate_unique method, so we can add the BEFORE_SAVE hook. |
| 145 | """ |
| 146 | super(MultivariateFeatureStateValue, self).validate_unique(exclude=exclude) |
| 147 | |
| 148 | def clone(self, feature_state: "FeatureState", persist: bool = True): # type: ignore[no-untyped-def] |
| 149 | clone = MultivariateFeatureStateValue( |
| 150 | feature_state=feature_state, |
| 151 | multivariate_feature_option=self.multivariate_feature_option, |
| 152 | percentage_allocation=self.percentage_allocation, |
| 153 | uuid=uuid.uuid4(), |
| 154 | ) |
| 155 | |
| 156 | if persist: |
| 157 | clone.save() |
| 158 | |
| 159 | return clone |
| 160 | |
| 161 | def get_skip_create_audit_log(self) -> bool: |
| 162 | try: |
| 163 | if self.feature_state.deleted_at: |
| 164 | return True |
| 165 | return self.feature_state.get_skip_create_audit_log() |
| 166 | except ObjectDoesNotExist: |
| 167 | return True |
| 168 | |
| 169 | def get_update_log_message(self, history_instance) -> typing.Optional[str]: # type: ignore[no-untyped-def] |
| 170 | feature_state = self.feature_state |
| 171 | feature = feature_state.feature |
| 172 |
no test coverage detected
searching dependent graphs…