Commit 5ce4ec59 authored by Mickaël Desfrênes's avatar Mickaël Desfrênes
Browse files

add and remove metas to/from items

parent 7c030580
Loading
Loading
Loading
Loading
+134 −54
Original line number Diff line number Diff line
@@ -1569,7 +1569,7 @@ def add_meta_to_resource(
@_log_call
@_rpc_groups(["Metadatas", "Collections"])
def remove_meta_value_from_collection(
    user: User, collection_id: int, meta_value_id: int
    user: User, collection_id: int, meta_value_id: int, cascade: bool = False
) -> bool:
    """
    Remove a meta value from a collection given their ids.
@@ -1584,8 +1584,16 @@ def remove_meta_value_from_collection(
    for meta_value in collection_instance.metadatacollectionvalue_set.all():
        if meta_value.id == meta_value_id:
            meta_value.delete()
    if cascade:
        for descendant_collection_instance in collection_instance.descendants():
            remove_meta_value_from_collection(
                user, descendant_collection_instance.pk, meta_value_id
            )
        for descendant_resource_instance in collection_instance.descendants_resources():
            remove_meta_value_from_resource(
                user, descendant_resource_instance.pk, meta_value_id
            )
    return True
    return False


@_log_call
@@ -2841,13 +2849,12 @@ def picture_rotate_crop(
        raise ServiceException(CANT_CREATE_IMAGE)


@_log_call
@_rpc_groups(["Resources", "Collections"])
def remove_selection(user: User, parent_collection_id: int, selection: dict) -> bool:
def _find_items_sets_from_selection_dict(
    from_collection_id: int, selection: dict
) -> Tuple[QuerySet[Resource], QuerySet[Collection]]:
    """
    Will mass remove items (resources AND collections) based on parent collection

    Use such an object for inclusion/exclusion:
    Will find child items of parent collection based on criterias given in selection,
    such as these:

    ```
    {
@@ -2861,21 +2868,15 @@ def remove_selection(user: User, parent_collection_id: int, selection: dict) ->
        }
    }
    ```

    deleteCollection (with recursion) and deleteResource are used under the hood.

    The parent collection is left as-is.
    """
    if not selection:
        selection = {}
    if not parent_collection_id:
    if not from_collection_id:
        raise ServiceException(NO_SUCH_COLLECTION)
    parent_collection = Collection.objects.filter(pk=parent_collection_id).first()
    parent_collection = Collection.objects.filter(pk=from_collection_id).first()
    if not parent_collection:
        raise ServiceException(NO_SUCH_COLLECTION)

    children_collections_set = parent_collection.children()

    if selection.get("include"):
        if selection["include"].get("collections_ids"):
            children_collections_set = children_collections_set.filter(
@@ -2886,23 +2887,60 @@ def remove_selection(user: User, parent_collection_id: int, selection: dict) ->
            children_collections_set = children_collections_set.exclude(
                id__in=selection["exclude"].get("collections_ids")
            )
    for collection_instance in children_collections_set.all():
        delete_collection(user, collection_instance.id, True)

    res_set = parent_collection.resources.all()
    resources_set = parent_collection.resources.all()
    if selection.get("include"):
        if selection["include"].get("resources_ids"):
            res_set = res_set.filter(id__in=selection["include"].get("resources_ids"))
            resources_set = resources_set.filter(
                id__in=selection["include"].get("resources_ids")
            )
    if selection.get("exclude"):
        if selection["exclude"].get("resources_ids"):
            res_set = res_set.exclude(id__in=selection["exclude"].get("resources_ids"))
            resources_set = resources_set.exclude(
                id__in=selection["exclude"].get("resources_ids")
            )
    return resources_set, children_collections_set


@_log_call
@_rpc_groups(["Resources", "Collections"])
def remove_selection(user: User, parent_collection_id: int, selection: dict) -> bool:
    """
    Will mass remove items (resources AND collections) based on parent collection

    Use such an object for inclusion/exclusion:

    ```
    {
        "include": {
            "resources_ids": [3493, 159]
            "collections_ids:" [20, 31]
        },
        "exclude": {
            "resources_ids": [12, 10, 15]
            "collections_ids:" [4, 254, 17]
        }
    }
    ```

    deleteCollection (with recursion) and deleteResource are used under the hood.

    The parent collection is left as-is.
    """

    res_set, children_collections_set = _find_items_sets_from_selection_dict(
        parent_collection_id, selection
    )

    for collection_instance in children_collections_set.all():
        delete_collection(user, collection_instance.id, True)

    for resource_instance in res_set.all():
        # is resource anywhere else ?
        if resource_instance.collections.filter(deleted_at__isnull=True).count() < 2:
            delete_resource(user, resource_instance.id)
        else:
            remove_resource_from_collection(
                user, resource_instance.id, parent_collection.id
                user, resource_instance.id, parent_collection_id
            )
    return True

@@ -2930,49 +2968,91 @@ def move_selection(
    }
    ```
    """
    if not selection:
        selection = {}
    if not from_collection_id:
        raise ServiceException(NO_SUCH_COLLECTION)
    parent_collection = Collection.objects.filter(pk=from_collection_id).first()
    if not parent_collection:
        raise ServiceException(NO_SUCH_COLLECTION)
    if not to_collection_id:
        raise ServiceException(NO_SUCH_COLLECTION)

    resources_set, children_collections_set = _find_items_sets_from_selection_dict(
        from_collection_id, selection
    )

    recipient_collection = Collection.objects.filter(pk=to_collection_id).first()
    if not recipient_collection:
        raise ServiceException(NO_SUCH_COLLECTION)

    children_collections_set = parent_collection.children()
    if selection.get("include"):
        if selection["include"].get("collections_ids"):
            children_collections_set = children_collections_set.filter(
                id__in=selection["include"].get("collections_ids")
            )
    if selection.get("exclude"):
        if selection["exclude"].get("collections_ids"):
            children_collections_set = children_collections_set.exclude(
                id__in=selection["exclude"].get("collections_ids")
            )
    # we only need ids to use move_items
    collections_ids = []
    for collection_instance in children_collections_set.all():
        collections_ids.append(collection_instance.id)

    res_set = parent_collection.resources.all()
    if selection.get("include"):
        if selection["include"].get("resources_ids"):
            res_set = res_set.filter(id__in=selection["include"].get("resources_ids"))
    if selection.get("exclude"):
        if selection["exclude"].get("resources_ids"):
            res_set = res_set.exclude(id__in=selection["exclude"].get("resources_ids"))
    resources_ids = []
    for resource_instance in res_set.all():
    for resource_instance in resources_set.all():
        resources_ids.append(resource_instance.id)

    return move_items(
        user,
        parent_collection.id,
        from_collection_id,
        recipient_collection.id,
        collections_ids,
        resources_ids,
    )


@_log_call
@_rpc_groups(["Resources", "Collections"])
def add_meta_to_selection(
    user: User, from_collection_id: int, selection: dict, meta_id: int, meta_value: str
) -> bool:
    """
    Use such a dict for selection:
    ```
    {
        "include": {
            "resources_ids": [3493, 159]
            "collections_ids:" [20, 31]
        },
        "exclude": {
            "resources_ids": [12, 10, 15]
            "collections_ids:" [4, 254, 17]
        }
    }
    ```
    """
    resources_set, collections_set = _find_items_sets_from_selection_dict(
        from_collection_id, selection
    )
    for resource_instance in resources_set.all():
        add_meta_to_resource(user, resource_instance.pk, meta_id, meta_value)
    for collection_instance in collections_set.all():
        add_meta_to_collection(
            user, collection_instance.pk, meta_id, meta_value, True
        )  # cascading
    return True


@_log_call
@_rpc_groups(["Resources", "Collections"])
def remove_meta_value_from_selection(
    user: User, from_collection_id: int, selection: dict, meta_value_id: int
) -> bool:
    """
    Use such a dict for selection:
    ```
    {
        "include": {
            "resources_ids": [3493, 159]
            "collections_ids:" [20, 31]
        },
        "exclude": {
            "resources_ids": [12, 10, 15]
            "collections_ids:" [4, 254, 17]
        }
    }
    ```
    """
    resources_set, collections_set = _find_items_sets_from_selection_dict(
        from_collection_id, selection
    )
    for resource_instance in resources_set.all():
        remove_meta_value_from_resource(user, resource_instance.pk, meta_value_id)
    for collection_instance in collections_set.all():
        remove_meta_value_from_collection(
            user, collection_instance.pk, meta_value_id, True
        )
    return True