Exemple #1
0
    def use(object: TrackedModel, new_data: Callable[[TrackedModel], dict[str, Any]]):
        model = type(object)
        versions = set(
            model.objects.filter(**object.get_identifying_fields()).values_list(
                "pk",
                flat=True,
            ),
        )

        # Visit the edit page and ensure it is a success
        edit_url = object.get_url("edit")
        assert edit_url, f"No edit page found for {object}"
        response = valid_user_api_client.get(edit_url)
        assert response.status_code == 200

        # Get the data out of the edit page
        # and override it with any data that has been passed in
        data = get_form_data(response.context_data["form"])

        # Submit the edited data and if we expect success ensure we are redirected
        realised_data = new_data(object)
        assert set(realised_data.keys()).issubset(data.keys())
        data.update(realised_data)
        response = valid_user_api_client.post(edit_url, data)

        # Check that if we expect failure that the new data was not persisted
        if response.status_code not in (301, 302):
            assert (
                set(
                    model.objects.filter(**object.get_identifying_fields()).values_list(
                        "pk",
                        flat=True,
                    ),
                )
                == versions
            )
            raise ValidationError(
                f"Update form contained errors: {response.context_data['form'].errors}",
            )

        # Check that what we asked to be changed has been persisted
        response = valid_user_api_client.get(edit_url)
        assert response.status_code == 200
        data = get_form_data(response.context_data["form"])
        for key in realised_data:
            assert data[key] == realised_data[key]

        # Check that if success was expected that the new version was persisted
        new_version = model.objects.exclude(pk=object.pk).get(
            version_group=object.version_group,
        )
        assert new_version != object

        # Check that the new version is an update and is not approved yet
        assert new_version.update_type == UpdateType.UPDATE
        assert new_version.transaction != object.transaction
        assert not new_version.transaction.workbasket.approved
        return new_version
Exemple #2
0
    def use(object: TrackedModel):
        model = type(object)
        versions = set(
            model.objects.filter(**object.get_identifying_fields()).values_list(
                "pk",
                flat=True,
            ),
        )

        # Visit the delete page and ensure it is a success
        delete_url = object.get_url("delete")
        assert delete_url, f"No delete page found for {object}"
        response = valid_user_api_client.get(delete_url)
        assert response.status_code == 200

        # Get the data out of the delete page
        data = get_form_data(response.context_data["form"])
        response = valid_user_api_client.post(delete_url, data)

        # Check that if we expect failure that the new data was not persisted
        if response.status_code not in (301, 302):
            assert (
                set(
                    model.objects.filter(**object.get_identifying_fields()).values_list(
                        "pk",
                        flat=True,
                    ),
                )
                == versions
            )
            raise ValidationError(
                f"Delete form contained errors: {response.context_data['form'].errors}",
            )

        # Check that the delete persisted and we can't delete again
        response = valid_user_api_client.get(delete_url)
        assert response.status_code == 404

        # Check that if success was expected that the new version was persisted
        new_version = model.objects.exclude(pk=object.pk).get(
            version_group=object.version_group,
        )
        assert new_version != object

        # Check that the new version is a delete and is not approved yet
        assert new_version.update_type == UpdateType.DELETE
        assert new_version.transaction != object.transaction
        assert not new_version.transaction.workbasket.approved
        return new_version
Exemple #3
0
    def cache_object(self, obj: TrackedModel):
        """
        Caches an objects primary key and model name in the cache.

        Key is generated based on the model name and the identifying fields used
        to find it.
        """
        model = obj.__class__
        link_fields = self.get_handler_link_fields(model)

        for identifying_fields in link_fields:
            cache_key = self.generate_cache_key(
                model,
                identifying_fields,
                obj.get_identifying_fields(identifying_fields),
            )
            cache.set(cache_key, (obj.pk, model.__name__), timeout=None)
Exemple #4
0
    def remove_object_from_cache(self, obj: TrackedModel):
        """
        Removes an object from the importer cache. If an object has to be
        deleted (generally done in dev only) then it is problematic to keep the
        ID in the cache as well.

        Key is generated based on the model name and the identifying fields used
        to find it.
        """
        model = obj.__class__
        link_fields = self.get_handler_link_fields(model)

        for identifying_fields in link_fields:
            cache_key = self.generate_cache_key(
                model,
                identifying_fields,
                obj.get_identifying_fields(identifying_fields),
            )
            cache.delete(cache_key)
Exemple #5
0
    def check(
        model: Union[TrackedModel, Type[DjangoModelFactory]],
        serializer: Type[TrackedModelSerializer],
        parent_model: TrackedModel = None,
        dependencies: Dict[str, Union[TrackedModel, Type[DjangoModelFactory]]] = None,
        kwargs: Dict[str, Any] = None,
        validity=(date_ranges.normal, date_ranges.adjacent_no_end),
    ):
        update_type = request.param
        if isinstance(model, type) and issubclass(model, DjangoModelFactory):
            if parent_model:
                raise ValueError("Can't have parent_model and a factory defined")

            # Build kwargs and dependencies needed to make a complete model.
            # This can't rely on the factory itself as the dependencies need
            # to be in the database and .build does not save anything.
            kwargs = kwargs or {}
            for name, dependency_model in (dependencies or {}).items():
                if isinstance(dependency_model, type) and issubclass(
                    dependency_model,
                    DjangoModelFactory,
                ):
                    kwargs[name] = dependency_model.create()
                else:
                    kwargs[name] = dependency_model

            if validity:
                kwargs["valid_between"] = validity[0]

            parent_model = model.create(**kwargs)

            kwargs.update(parent_model.get_identifying_fields())
            if validity:
                kwargs["valid_between"] = validity[1]

            model = model.build(
                update_type=update_type,
                **kwargs,
            )
        elif not parent_model:
            raise ValueError("parent_model must be defined if an instance is provided")

        try:
            updated_model = imported_fields_match(
                model,
                serializer,
            )
        except model.__class__.DoesNotExist:
            if update_type == UpdateType.UPDATE:
                raise
            updated_model = model.__class__.objects.get(
                update_type=UpdateType.DELETE, **model.get_identifying_fields()
            )

        version_group = parent_model.version_group
        version_group.refresh_from_db()
        assert version_group.versions.count() == 2
        assert version_group == updated_model.version_group
        assert version_group.current_version == updated_model
        assert version_group.current_version.update_type == update_type
        return updated_model