From 58d0c37d997f01cd6834983a184422a0c9e84f20 Mon Sep 17 00:00:00 2001 From: Philipp Metzner Date: Fri, 3 Jan 2025 11:44:47 +0100 Subject: [PATCH] wip --- back/boxtribute_server/authz.py | 2 +- .../business_logic/warehouse/box/crud.py | 7 ++- .../business_logic/warehouse/box/mutations.py | 59 +++++++++++++++---- back/boxtribute_server/graph_ql/bindables.py | 1 + .../definitions/protected/inputs.graphql | 2 +- .../definitions/protected/mutations.graphql | 2 +- .../definitions/protected/types.graphql | 17 ++++++ back/test/endpoint_tests/test_app.py | 2 +- back/test/endpoint_tests/test_box.py | 14 ++--- back/test/endpoint_tests/test_permissions.py | 6 +- graphql/generated/graphql-env.d.ts | 7 ++- graphql/generated/schema.graphql | 21 ++++++- 12 files changed, 106 insertions(+), 34 deletions(-) diff --git a/back/boxtribute_server/authz.py b/back/boxtribute_server/authz.py index 1ad8d09f1..f172832cb 100644 --- a/back/boxtribute_server/authz.py +++ b/back/boxtribute_server/authz.py @@ -335,7 +335,7 @@ def authorize_cross_organisation_access( MUTATIONS_FOR_BETA_LEVEL[3] = MUTATIONS_FOR_BETA_LEVEL[2] + ("deleteBoxes",) MUTATIONS_FOR_BETA_LEVEL[4] = MUTATIONS_FOR_BETA_LEVEL[3] + ( "moveBoxesToLocation", - "assignTagToBoxes", + "assignTagsToBoxes", "unassignTagFromBoxes", ) MUTATIONS_FOR_BETA_LEVEL[5] = MUTATIONS_FOR_BETA_LEVEL[4] + ( diff --git a/back/boxtribute_server/business_logic/warehouse/box/crud.py b/back/boxtribute_server/business_logic/warehouse/box/crud.py index 43a09a86e..5d707f63c 100644 --- a/back/boxtribute_server/business_logic/warehouse/box/crud.py +++ b/back/boxtribute_server/business_logic/warehouse/box/crud.py @@ -440,8 +440,8 @@ def move_boxes_to_location(*, user_id, boxes, location): return list(Box.select().where(Box.id << box_ids)) -def assign_tag_to_boxes(*, user_id, boxes, tag): - """Add TagsRelation entries for given boxes and tag. Update last_modified_* fields +def assign_tags_to_boxes(*, user_id, boxes, tag_ids): + """Add TagsRelation entries for given boxes and tags. Update last_modified_* fields of the affected boxes. Return the list of updated boxes. """ @@ -453,11 +453,12 @@ def assign_tag_to_boxes(*, user_id, boxes, tag): TagsRelation( object_id=box.id, object_type=TaggableObjectType.Box, - tag=tag.id, + tag=tag_id, created_on=now, created_by=user_id, ) for box in boxes + for tag_id in tag_ids ] box_ids = [box.id for box in boxes] diff --git a/back/boxtribute_server/business_logic/warehouse/box/mutations.py b/back/boxtribute_server/business_logic/warehouse/box/mutations.py index aa87e8c8f..2a7961636 100644 --- a/back/boxtribute_server/business_logic/warehouse/box/mutations.py +++ b/back/boxtribute_server/business_logic/warehouse/box/mutations.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import Any from ariadne import MutationType from flask import g @@ -19,7 +20,7 @@ from ....models.definitions.tag import Tag from ....models.definitions.tags_relation import TagsRelation from .crud import ( - assign_tag_to_boxes, + assign_tags_to_boxes, create_box, delete_boxes, move_boxes_to_location, @@ -36,6 +37,11 @@ class BoxesResult: invalid_box_label_identifiers: list[str] +@dataclass(kw_only=True) +class AssignTagsToBoxesResult(BoxesResult): + tag_error_info: list[dict[str, Any]] + + @mutation.field("createBox") def resolve_create_box(*_, creation_input): requested_location = Location.get_by_id(creation_input["location_id"]) @@ -156,18 +162,40 @@ def resolve_move_boxes_to_location(*_, update_input): ) -@mutation.field("assignTagToBoxes") @handle_unauthorized -def resolve_assign_tag_to_boxes(*_, update_input): - tag_id = update_input["tag_id"] - if (tag := Tag.get_or_none(tag_id)) is None: - return ResourceDoesNotExist(name="Tag", id=tag_id) +def authorize_tag(tag): authorize(permission="tag_relation:assign") authorize(permission="tag:read", base_id=tag.base_id) - if tag.deleted_on is not None: - return DeletedTag(name=tag.name) - if tag.type == TagType.Beneficiary: - return TagTypeMismatch(expected_type=TagType.Box) + + +def _validate_tags(tag_ids): + tag_errors = [] + valid_tag_ids = [] + for tag_id in tag_ids: + if (tag := Tag.get_or_none(tag_id)) is None: + tag_errors.append( + {"id": tag_id, "error": ResourceDoesNotExist(name="Tag", id=tag_id)} + ) + continue + if (error := authorize_tag(tag)) is not None: + tag_errors.append({"id": tag_id, "error": error}) + continue + if tag.deleted_on is not None: + tag_errors.append({"id": tag_id, "error": DeletedTag(name=tag.name)}) + continue + if tag.type == TagType.Beneficiary: + tag_errors.append( + {"id": tag_id, "error": TagTypeMismatch(expected_type=TagType.Box)} + ) + continue + valid_tag_ids.append(tag_id) + return valid_tag_ids, tag_errors + + +@mutation.field("assignTagsToBoxes") +def resolve_assign_tags_to_boxes(*_, update_input): + tag_ids = set(update_input["tag_ids"]) + valid_tag_ids, tag_errors = _validate_tags(tag_ids) label_identifiers = set(update_input["label_identifiers"]) boxes = ( @@ -179,7 +207,9 @@ def resolve_assign_tag_to_boxes(*_, update_input): on=( (TagsRelation.object_id == Box.id) & (TagsRelation.object_type == TaggableObjectType.Box) - & (TagsRelation.tag == tag.id) + # TODO: this is not correct because it filters out a box if it has only + # one of the requested tags already + & (TagsRelation.tag << valid_tag_ids) & TagsRelation.deleted_on.is_null() ), ) @@ -194,11 +224,14 @@ def resolve_assign_tag_to_boxes(*_, update_input): ) valid_box_label_identifiers = {box.label_identifier for box in boxes} - return BoxesResult( - updated_boxes=assign_tag_to_boxes(user_id=g.user.id, boxes=boxes, tag=tag), + return AssignTagsToBoxesResult( + updated_boxes=assign_tags_to_boxes( + user_id=g.user.id, boxes=boxes, tag_ids=valid_tag_ids + ), invalid_box_label_identifiers=sorted( label_identifiers.difference(valid_box_label_identifiers) ), + tag_error_info=tag_errors, ) diff --git a/back/boxtribute_server/graph_ql/bindables.py b/back/boxtribute_server/graph_ql/bindables.py index 3484f265f..5752f4c35 100644 --- a/back/boxtribute_server/graph_ql/bindables.py +++ b/back/boxtribute_server/graph_ql/bindables.py @@ -182,6 +182,7 @@ def resolve_location_type(obj, *_): UnionType("UnassignTagFromBoxesResult", resolve_type_by_class_name), UnionType("QrCodeResult", resolve_type_by_class_name), UnionType("BoxResult", resolve_type_by_class_name), + UnionType("TagError", resolve_type_by_class_name), ) interface_types = ( InterfaceType("Location", resolve_location_type), diff --git a/back/boxtribute_server/graph_ql/definitions/protected/inputs.graphql b/back/boxtribute_server/graph_ql/definitions/protected/inputs.graphql index a8b4744ae..4cb52b9d5 100644 --- a/back/boxtribute_server/graph_ql/definitions/protected/inputs.graphql +++ b/back/boxtribute_server/graph_ql/definitions/protected/inputs.graphql @@ -34,7 +34,7 @@ input BoxMoveInput { input BoxAssignTagInput { labelIdentifiers: [String!]! - tagId: Int! + tagIds: [Int!]! } input CustomProductCreationInput { diff --git a/back/boxtribute_server/graph_ql/definitions/protected/mutations.graphql b/back/boxtribute_server/graph_ql/definitions/protected/mutations.graphql index 5a9534550..8e991e407 100644 --- a/back/boxtribute_server/graph_ql/definitions/protected/mutations.graphql +++ b/back/boxtribute_server/graph_ql/definitions/protected/mutations.graphql @@ -12,7 +12,7 @@ type Mutation { " Any boxes that are non-existing, already inside the requested location, inside a different base other than the one of the requested location, and/or in a base that the user must not access are returned in the `BoxesResult.invalidBoxLabelIdentifiers` list. " moveBoxesToLocation(updateInput: BoxMoveInput): MoveBoxesResult " Any boxes that are non-existing, already assigned to the requested tag, and/or in a base that the user must not access are returned in the `BoxesResult.invalidBoxLabelIdentifiers` list. " - assignTagToBoxes(updateInput: BoxAssignTagInput): AssignTagToBoxesResult + assignTagsToBoxes(updateInput: BoxAssignTagInput): AssignTagsToBoxesResult " Any boxes that are non-existing, don't have the requested tag assigned, and/or in a base that the user must not access are returned in the `BoxesResult.invalidBoxLabelIdentifiers` list. " unassignTagFromBoxes(updateInput: BoxAssignTagInput): UnassignTagFromBoxesResult diff --git a/back/boxtribute_server/graph_ql/definitions/protected/types.graphql b/back/boxtribute_server/graph_ql/definitions/protected/types.graphql index 48d8c0a4e..03776022f 100644 --- a/back/boxtribute_server/graph_ql/definitions/protected/types.graphql +++ b/back/boxtribute_server/graph_ql/definitions/protected/types.graphql @@ -588,6 +588,23 @@ type ShipmentDetail { receivedOn: Datetime } +""" +Utility response type for box bulk tag-mutations, containing both updated boxes and invalid boxes (ignored due to e.g. being deleted, in prohibited base, and/or non-existing) as well as optional info about erroneous tags. +""" +type AssignTagsToBoxesResult { + updatedBoxes: [Box!]! + invalidBoxLabelIdentifiers: [String!]! + tagErrorInfo: [TagErrorInfo!] +} + +""" Error info about tag with specified ID. """ +type TagErrorInfo { + id: ID! + error: TagError! +} + +union TagError = InsufficientPermissionError | ResourceDoesNotExistError | UnauthorizedForBaseError | TagTypeMismatchError | DeletedTagError + type InsufficientPermissionError { " e.g. 'product:write' missing " name: String! diff --git a/back/test/endpoint_tests/test_app.py b/back/test/endpoint_tests/test_app.py index bb419c3db..2f0cac963 100644 --- a/back/test/endpoint_tests/test_app.py +++ b/back/test/endpoint_tests/test_app.py @@ -321,7 +321,7 @@ def test_update_non_existent_resource( ], # Test case 8.2.23g [ - "assignTagToBoxes", + "assignTagsToBoxes", 'updateInput: { labelIdentifiers: ["12345678"], tagId: 0 }', "...on ResourceDoesNotExistError { id name }", {"id": "0", "name": "Tag"}, diff --git a/back/test/endpoint_tests/test_box.py b/back/test/endpoint_tests/test_box.py index 5cad12bbf..3c411fca5 100644 --- a/back/test/endpoint_tests/test_box.py +++ b/back/test/endpoint_tests/test_box.py @@ -567,7 +567,7 @@ def test_box_mutations( assert response == {"name": f"{deleted_location['name']}"} # Test case 8.2.23a, 8.2.23c - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {tag_id} }} ) {{ ...on BoxesResult {{ updatedBoxes {{ tags {{ id }} }} @@ -579,7 +579,7 @@ def test_box_mutations( "invalidBoxLabelIdentifiers": [another_created_box_label_identifier], } - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {tag_id} }} ) {{ ...on BoxesResult {{ updatedBoxes {{ tags {{ id }} }} @@ -592,7 +592,7 @@ def test_box_mutations( } generic_tag_id = str(tags[2]["id"]) - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {generic_tag_id} }} ) {{ ...on BoxesResult {{ updatedBoxes {{ tags {{ id }} }} @@ -607,7 +607,7 @@ def test_box_mutations( } another_generic_tag_id = str(tags[5]["id"]) - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {another_generic_tag_id} }} ) {{ ...on BoxesResult {{ @@ -672,7 +672,7 @@ def test_box_mutations( # Test case 8.2.23h beneficiary_tag_id = str(tags[0]["id"]) - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {beneficiary_tag_id} }} ) {{ ...on TagTypeMismatchError {{ expectedType }} }} }}""" response = assert_successful_request(client, mutation) @@ -694,7 +694,7 @@ def test_box_mutations( # Test case 8.2.23i deleted_tag_id = str(tags[4]["id"]) tag_name = tags[4]["name"] - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {deleted_tag_id} }} ) {{ ...on DeletedTagError {{ name }} }} }}""" response = assert_successful_request(client, mutation) @@ -750,7 +750,7 @@ def test_box_mutations( } # Test case 8.2.23b, 8.2.23d, 8.2.23j - mutation = f"""mutation {{ assignTagToBoxes( updateInput: {{ + mutation = f"""mutation {{ assignTagsToBoxes( updateInput: {{ labelIdentifiers: [{label_identifiers}], tagId: {tag_id} }} ) {{ ...on BoxesResult {{ updatedBoxes {{ tags {{ id }} }} diff --git a/back/test/endpoint_tests/test_permissions.py b/back/test/endpoint_tests/test_permissions.py index ad23dda88..7670843f6 100644 --- a/back/test/endpoint_tests/test_permissions.py +++ b/back/test/endpoint_tests/test_permissions.py @@ -576,7 +576,7 @@ def test_invalid_permission_for_user_read( ], # Test case 8.2.23e [ - "assignTagToBoxes", + "assignTagsToBoxes", 'updateInput: { labelIdentifiers: ["12345678"], tagId: 2 }', "...on InsufficientPermissionError { name }", {"name": "tag_relation:assign"}, @@ -653,8 +653,8 @@ def test_mutate_insufficient_permission( ], # Test case 8.2.23f [ - "assignTagToBoxes", - 'updateInput: { labelIdentifiers: ["12345678"], tagId: 4 }', + "assignTagsToBoxes", + 'updateInput: { labelIdentifiers: ["12345678"], tagIds: [4] }', "...on UnauthorizedForBaseError { id }", {"id": "2"}, ], diff --git a/graphql/generated/graphql-env.d.ts b/graphql/generated/graphql-env.d.ts index 3b88e6466..1e8ff366e 100644 --- a/graphql/generated/graphql-env.d.ts +++ b/graphql/generated/graphql-env.d.ts @@ -3,6 +3,7 @@ export type introspection_types = { 'AssignTagToBoxesResult': { kind: 'UNION'; name: 'AssignTagToBoxesResult'; fields: {}; possibleTypes: 'BoxesResult' | 'DeletedTagError' | 'InsufficientPermissionError' | 'ResourceDoesNotExistError' | 'TagTypeMismatchError' | 'UnauthorizedForBaseError'; }; + 'AssignTagsToBoxesResult': { kind: 'OBJECT'; name: 'AssignTagsToBoxesResult'; fields: { 'invalidBoxLabelIdentifiers': { name: 'invalidBoxLabelIdentifiers'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; }; } }; 'tagErrorInfo': { name: 'tagErrorInfo'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'TagErrorInfo'; ofType: null; }; }; } }; 'updatedBoxes': { name: 'updatedBoxes'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Box'; ofType: null; }; }; }; } }; }; }; 'Base': { kind: 'OBJECT'; name: 'Base'; fields: { 'beneficiaries': { name: 'beneficiaries'; type: { kind: 'OBJECT'; name: 'BeneficiaryPage'; ofType: null; } }; 'currencyName': { name: 'currencyName'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'deletedOn': { name: 'deletedOn'; type: { kind: 'SCALAR'; name: 'Datetime'; ofType: null; } }; 'distributionEvents': { name: 'distributionEvents'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; }; }; }; } }; 'distributionEventsBeforeReturnedFromDistributionState': { name: 'distributionEventsBeforeReturnedFromDistributionState'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; }; }; }; } }; 'distributionEventsInReturnedFromDistributionState': { name: 'distributionEventsInReturnedFromDistributionState'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; }; }; }; } }; 'distributionEventsStatistics': { name: 'distributionEventsStatistics'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DistributionEventsStatistics'; ofType: null; }; }; }; } }; 'distributionEventsTrackingGroups': { name: 'distributionEventsTrackingGroups'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DistributionEventsTrackingGroup'; ofType: null; }; }; }; } }; 'distributionSpots': { name: 'distributionSpots'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DistributionSpot'; ofType: null; }; }; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'locations': { name: 'locations'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'ClassicLocation'; ofType: null; }; }; }; } }; 'name': { name: 'name'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'organisation': { name: 'organisation'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Organisation'; ofType: null; }; } }; 'products': { name: 'products'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Product'; ofType: null; }; }; }; } }; 'tags': { name: 'tags'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Tag'; ofType: null; }; }; } }; }; }; 'BasicDimensionInfo': { kind: 'INTERFACE'; name: 'BasicDimensionInfo'; fields: { 'id': { name: 'id'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; }; possibleTypes: 'DimensionInfo' | 'ProductDimensionInfo' | 'TagDimensionInfo'; }; 'Beneficiary': { kind: 'OBJECT'; name: 'Beneficiary'; fields: { 'active': { name: 'active'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'age': { name: 'age'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'base': { name: 'base'; type: { kind: 'OBJECT'; name: 'Base'; ofType: null; } }; 'comment': { name: 'comment'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'createdBy': { name: 'createdBy'; type: { kind: 'OBJECT'; name: 'User'; ofType: null; } }; 'createdOn': { name: 'createdOn'; type: { kind: 'SCALAR'; name: 'Datetime'; ofType: null; } }; 'dateOfBirth': { name: 'dateOfBirth'; type: { kind: 'SCALAR'; name: 'Date'; ofType: null; } }; 'dateOfSignature': { name: 'dateOfSignature'; type: { kind: 'SCALAR'; name: 'Date'; ofType: null; } }; 'familyHead': { name: 'familyHead'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'firstName': { name: 'firstName'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'gender': { name: 'gender'; type: { kind: 'ENUM'; name: 'HumanGender'; ofType: null; } }; 'groupIdentifier': { name: 'groupIdentifier'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'isVolunteer': { name: 'isVolunteer'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'languages': { name: 'languages'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'Language'; ofType: null; }; }; } }; 'lastModifiedBy': { name: 'lastModifiedBy'; type: { kind: 'OBJECT'; name: 'User'; ofType: null; } }; 'lastModifiedOn': { name: 'lastModifiedOn'; type: { kind: 'SCALAR'; name: 'Datetime'; ofType: null; } }; 'lastName': { name: 'lastName'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'registered': { name: 'registered'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'signature': { name: 'signature'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'signed': { name: 'signed'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'tags': { name: 'tags'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Tag'; ofType: null; }; }; } }; 'tokens': { name: 'tokens'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'transactions': { name: 'transactions'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Transaction'; ofType: null; }; }; } }; }; }; @@ -14,7 +15,7 @@ export type introspection_types = { 'BeneficiaryUpdateInput': { kind: 'INPUT_OBJECT'; name: 'BeneficiaryUpdateInput'; isOneOf: false; inputFields: [{ name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; }; defaultValue: null }, { name: 'firstName'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'lastName'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'groupIdentifier'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'dateOfBirth'; type: { kind: 'SCALAR'; name: 'Date'; ofType: null; }; defaultValue: null }, { name: 'comment'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'gender'; type: { kind: 'ENUM'; name: 'HumanGender'; ofType: null; }; defaultValue: null }, { name: 'languages'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'Language'; ofType: null; }; }; }; defaultValue: null }, { name: 'familyHeadId'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; defaultValue: null }, { name: 'isVolunteer'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; defaultValue: null }, { name: 'registered'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; defaultValue: null }, { name: 'signature'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'dateOfSignature'; type: { kind: 'SCALAR'; name: 'Date'; ofType: null; }; defaultValue: null }]; }; 'Boolean': unknown; 'Box': { kind: 'OBJECT'; name: 'Box'; fields: { 'comment': { name: 'comment'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'createdBy': { name: 'createdBy'; type: { kind: 'OBJECT'; name: 'User'; ofType: null; } }; 'createdOn': { name: 'createdOn'; type: { kind: 'SCALAR'; name: 'Datetime'; ofType: null; } }; 'deletedOn': { name: 'deletedOn'; type: { kind: 'SCALAR'; name: 'Datetime'; ofType: null; } }; 'displayUnit': { name: 'displayUnit'; type: { kind: 'OBJECT'; name: 'Unit'; ofType: null; } }; 'distributionEvent': { name: 'distributionEvent'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'history': { name: 'history'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'HistoryEntry'; ofType: null; }; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'labelIdentifier': { name: 'labelIdentifier'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'lastModifiedBy': { name: 'lastModifiedBy'; type: { kind: 'OBJECT'; name: 'User'; ofType: null; } }; 'lastModifiedOn': { name: 'lastModifiedOn'; type: { kind: 'SCALAR'; name: 'Datetime'; ofType: null; } }; 'location': { name: 'location'; type: { kind: 'INTERFACE'; name: 'Location'; ofType: null; } }; 'measureValue': { name: 'measureValue'; type: { kind: 'SCALAR'; name: 'Float'; ofType: null; } }; 'numberOfItems': { name: 'numberOfItems'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'product': { name: 'product'; type: { kind: 'OBJECT'; name: 'Product'; ofType: null; } }; 'qrCode': { name: 'qrCode'; type: { kind: 'OBJECT'; name: 'QrCode'; ofType: null; } }; 'shipmentDetail': { name: 'shipmentDetail'; type: { kind: 'OBJECT'; name: 'ShipmentDetail'; ofType: null; } }; 'size': { name: 'size'; type: { kind: 'OBJECT'; name: 'Size'; ofType: null; } }; 'state': { name: 'state'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'BoxState'; ofType: null; }; } }; 'tags': { name: 'tags'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Tag'; ofType: null; }; }; } }; }; }; - 'BoxAssignTagInput': { kind: 'INPUT_OBJECT'; name: 'BoxAssignTagInput'; isOneOf: false; inputFields: [{ name: 'labelIdentifiers'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; }; }; defaultValue: null }, { name: 'tagId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }]; }; + 'BoxAssignTagInput': { kind: 'INPUT_OBJECT'; name: 'BoxAssignTagInput'; isOneOf: false; inputFields: [{ name: 'labelIdentifiers'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; }; }; defaultValue: null }, { name: 'tagIds'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; }; }; defaultValue: null }]; }; 'BoxCreationInput': { kind: 'INPUT_OBJECT'; name: 'BoxCreationInput'; isOneOf: false; inputFields: [{ name: 'productId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }, { name: 'sizeId'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; defaultValue: null }, { name: 'displayUnitId'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; defaultValue: null }, { name: 'measureValue'; type: { kind: 'SCALAR'; name: 'Float'; ofType: null; }; defaultValue: null }, { name: 'numberOfItems'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; defaultValue: null }, { name: 'locationId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }, { name: 'comment'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'qrCode'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'tagIds'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; }; defaultValue: null }]; }; 'BoxMoveInput': { kind: 'INPUT_OBJECT'; name: 'BoxMoveInput'; isOneOf: false; inputFields: [{ name: 'labelIdentifiers'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; }; }; defaultValue: null }, { name: 'locationId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }]; }; 'BoxPage': { kind: 'OBJECT'; name: 'BoxPage'; fields: { 'elements': { name: 'elements'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Box'; ofType: null; }; }; }; } }; 'pageInfo': { name: 'pageInfo'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'PageInfo'; ofType: null; }; } }; 'totalCount': { name: 'totalCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; }; }; @@ -73,7 +74,7 @@ export type introspection_types = { 'MovedBoxDataDimensions': { kind: 'OBJECT'; name: 'MovedBoxDataDimensions'; fields: { 'category': { name: 'category'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'DimensionInfo'; ofType: null; }; } }; 'dimension': { name: 'dimension'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'DimensionInfo'; ofType: null; }; }; }; } }; 'size': { name: 'size'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'DimensionInfo'; ofType: null; }; } }; 'tag': { name: 'tag'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'TagDimensionInfo'; ofType: null; }; }; }; } }; 'target': { name: 'target'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'TargetDimensionInfo'; ofType: null; }; } }; }; }; 'MovedBoxesData': { kind: 'OBJECT'; name: 'MovedBoxesData'; fields: { 'dimensions': { name: 'dimensions'; type: { kind: 'OBJECT'; name: 'MovedBoxDataDimensions'; ofType: null; } }; 'facts': { name: 'facts'; type: { kind: 'LIST'; name: never; ofType: { kind: 'OBJECT'; name: 'MovedBoxesResult'; ofType: null; }; } }; }; }; 'MovedBoxesResult': { kind: 'OBJECT'; name: 'MovedBoxesResult'; fields: { 'absoluteMeasureValue': { name: 'absoluteMeasureValue'; type: { kind: 'SCALAR'; name: 'Float'; ofType: null; } }; 'boxesCount': { name: 'boxesCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'categoryId': { name: 'categoryId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'dimensionId': { name: 'dimensionId'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'gender': { name: 'gender'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'ProductGender'; ofType: null; }; } }; 'itemsCount': { name: 'itemsCount'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'movedOn': { name: 'movedOn'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Date'; ofType: null; }; } }; 'organisationName': { name: 'organisationName'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'productName': { name: 'productName'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'sizeId': { name: 'sizeId'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'tagIds': { name: 'tagIds'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; } }; 'targetId': { name: 'targetId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; }; }; - 'Mutation': { kind: 'OBJECT'; name: 'Mutation'; fields: { 'acceptTransferAgreement': { name: 'acceptTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'addPackingListEntryToDistributionEvent': { name: 'addPackingListEntryToDistributionEvent'; type: { kind: 'OBJECT'; name: 'PackingListEntry'; ofType: null; } }; 'assignBoxToDistributionEvent': { name: 'assignBoxToDistributionEvent'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'assignTag': { name: 'assignTag'; type: { kind: 'UNION'; name: 'TaggableResource'; ofType: null; } }; 'assignTagToBoxes': { name: 'assignTagToBoxes'; type: { kind: 'UNION'; name: 'AssignTagToBoxesResult'; ofType: null; } }; 'cancelShipment': { name: 'cancelShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'cancelTransferAgreement': { name: 'cancelTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'changeDistributionEventState': { name: 'changeDistributionEventState'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'completeDistributionEventsTrackingGroup': { name: 'completeDistributionEventsTrackingGroup'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingGroup'; ofType: null; } }; 'createBeneficiary': { name: 'createBeneficiary'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'createBox': { name: 'createBox'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'createCustomProduct': { name: 'createCustomProduct'; type: { kind: 'UNION'; name: 'CreateCustomProductResult'; ofType: null; } }; 'createDistributionEvent': { name: 'createDistributionEvent'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'createDistributionSpot': { name: 'createDistributionSpot'; type: { kind: 'OBJECT'; name: 'DistributionSpot'; ofType: null; } }; 'createQrCode': { name: 'createQrCode'; type: { kind: 'OBJECT'; name: 'QrCode'; ofType: null; } }; 'createShipment': { name: 'createShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'createTag': { name: 'createTag'; type: { kind: 'OBJECT'; name: 'Tag'; ofType: null; } }; 'createTransferAgreement': { name: 'createTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'deactivateBeneficiary': { name: 'deactivateBeneficiary'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'deleteBoxes': { name: 'deleteBoxes'; type: { kind: 'UNION'; name: 'DeleteBoxesResult'; ofType: null; } }; 'deleteProduct': { name: 'deleteProduct'; type: { kind: 'UNION'; name: 'DeleteProductResult'; ofType: null; } }; 'deleteTag': { name: 'deleteTag'; type: { kind: 'OBJECT'; name: 'Tag'; ofType: null; } }; 'disableStandardProduct': { name: 'disableStandardProduct'; type: { kind: 'UNION'; name: 'DisableStandardProductResult'; ofType: null; } }; 'editCustomProduct': { name: 'editCustomProduct'; type: { kind: 'UNION'; name: 'EditCustomProductResult'; ofType: null; } }; 'editStandardProductInstantiation': { name: 'editStandardProductInstantiation'; type: { kind: 'UNION'; name: 'EditStandardProductInstantiationResult'; ofType: null; } }; 'enableStandardProduct': { name: 'enableStandardProduct'; type: { kind: 'UNION'; name: 'EnableStandardProductResult'; ofType: null; } }; 'markShipmentAsLost': { name: 'markShipmentAsLost'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'moveBoxesToLocation': { name: 'moveBoxesToLocation'; type: { kind: 'UNION'; name: 'MoveBoxesResult'; ofType: null; } }; 'moveItemsFromBoxToDistributionEvent': { name: 'moveItemsFromBoxToDistributionEvent'; type: { kind: 'OBJECT'; name: 'UnboxedItemsCollection'; ofType: null; } }; 'moveItemsFromReturnTrackingGroupToBox': { name: 'moveItemsFromReturnTrackingGroupToBox'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingEntry'; ofType: null; } }; 'moveNotDeliveredBoxesInStock': { name: 'moveNotDeliveredBoxesInStock'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'rejectTransferAgreement': { name: 'rejectTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'removeAllPackingListEntriesFromDistributionEventForProduct': { name: 'removeAllPackingListEntriesFromDistributionEventForProduct'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; } }; 'removeItemsFromUnboxedItemsCollection': { name: 'removeItemsFromUnboxedItemsCollection'; type: { kind: 'OBJECT'; name: 'UnboxedItemsCollection'; ofType: null; } }; 'removePackingListEntryFromDistributionEvent': { name: 'removePackingListEntryFromDistributionEvent'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'sendShipment': { name: 'sendShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'setReturnedNumberOfItemsForDistributionEventsTrackingGroup': { name: 'setReturnedNumberOfItemsForDistributionEventsTrackingGroup'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingEntry'; ofType: null; } }; 'startDistributionEventsTrackingGroup': { name: 'startDistributionEventsTrackingGroup'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingGroup'; ofType: null; } }; 'startReceivingShipment': { name: 'startReceivingShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'unassignBoxFromDistributionEvent': { name: 'unassignBoxFromDistributionEvent'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'unassignTag': { name: 'unassignTag'; type: { kind: 'UNION'; name: 'TaggableResource'; ofType: null; } }; 'unassignTagFromBoxes': { name: 'unassignTagFromBoxes'; type: { kind: 'UNION'; name: 'UnassignTagFromBoxesResult'; ofType: null; } }; 'updateBeneficiary': { name: 'updateBeneficiary'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'updateBox': { name: 'updateBox'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'updatePackingListEntry': { name: 'updatePackingListEntry'; type: { kind: 'OBJECT'; name: 'PackingListEntry'; ofType: null; } }; 'updateSelectedProductsForDistributionEventPackingList': { name: 'updateSelectedProductsForDistributionEventPackingList'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'updateShipmentWhenPreparing': { name: 'updateShipmentWhenPreparing'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'updateShipmentWhenReceiving': { name: 'updateShipmentWhenReceiving'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'updateTag': { name: 'updateTag'; type: { kind: 'OBJECT'; name: 'Tag'; ofType: null; } }; }; }; + 'Mutation': { kind: 'OBJECT'; name: 'Mutation'; fields: { 'acceptTransferAgreement': { name: 'acceptTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'addPackingListEntryToDistributionEvent': { name: 'addPackingListEntryToDistributionEvent'; type: { kind: 'OBJECT'; name: 'PackingListEntry'; ofType: null; } }; 'assignBoxToDistributionEvent': { name: 'assignBoxToDistributionEvent'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'assignTag': { name: 'assignTag'; type: { kind: 'UNION'; name: 'TaggableResource'; ofType: null; } }; 'assignTagsToBoxes': { name: 'assignTagsToBoxes'; type: { kind: 'OBJECT'; name: 'AssignTagsToBoxesResult'; ofType: null; } }; 'cancelShipment': { name: 'cancelShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'cancelTransferAgreement': { name: 'cancelTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'changeDistributionEventState': { name: 'changeDistributionEventState'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'completeDistributionEventsTrackingGroup': { name: 'completeDistributionEventsTrackingGroup'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingGroup'; ofType: null; } }; 'createBeneficiary': { name: 'createBeneficiary'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'createBox': { name: 'createBox'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'createCustomProduct': { name: 'createCustomProduct'; type: { kind: 'UNION'; name: 'CreateCustomProductResult'; ofType: null; } }; 'createDistributionEvent': { name: 'createDistributionEvent'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'createDistributionSpot': { name: 'createDistributionSpot'; type: { kind: 'OBJECT'; name: 'DistributionSpot'; ofType: null; } }; 'createQrCode': { name: 'createQrCode'; type: { kind: 'OBJECT'; name: 'QrCode'; ofType: null; } }; 'createShipment': { name: 'createShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'createTag': { name: 'createTag'; type: { kind: 'OBJECT'; name: 'Tag'; ofType: null; } }; 'createTransferAgreement': { name: 'createTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'deactivateBeneficiary': { name: 'deactivateBeneficiary'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'deleteBoxes': { name: 'deleteBoxes'; type: { kind: 'UNION'; name: 'DeleteBoxesResult'; ofType: null; } }; 'deleteProduct': { name: 'deleteProduct'; type: { kind: 'UNION'; name: 'DeleteProductResult'; ofType: null; } }; 'deleteTag': { name: 'deleteTag'; type: { kind: 'OBJECT'; name: 'Tag'; ofType: null; } }; 'disableStandardProduct': { name: 'disableStandardProduct'; type: { kind: 'UNION'; name: 'DisableStandardProductResult'; ofType: null; } }; 'editCustomProduct': { name: 'editCustomProduct'; type: { kind: 'UNION'; name: 'EditCustomProductResult'; ofType: null; } }; 'editStandardProductInstantiation': { name: 'editStandardProductInstantiation'; type: { kind: 'UNION'; name: 'EditStandardProductInstantiationResult'; ofType: null; } }; 'enableStandardProduct': { name: 'enableStandardProduct'; type: { kind: 'UNION'; name: 'EnableStandardProductResult'; ofType: null; } }; 'markShipmentAsLost': { name: 'markShipmentAsLost'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'moveBoxesToLocation': { name: 'moveBoxesToLocation'; type: { kind: 'UNION'; name: 'MoveBoxesResult'; ofType: null; } }; 'moveItemsFromBoxToDistributionEvent': { name: 'moveItemsFromBoxToDistributionEvent'; type: { kind: 'OBJECT'; name: 'UnboxedItemsCollection'; ofType: null; } }; 'moveItemsFromReturnTrackingGroupToBox': { name: 'moveItemsFromReturnTrackingGroupToBox'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingEntry'; ofType: null; } }; 'moveNotDeliveredBoxesInStock': { name: 'moveNotDeliveredBoxesInStock'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'rejectTransferAgreement': { name: 'rejectTransferAgreement'; type: { kind: 'OBJECT'; name: 'TransferAgreement'; ofType: null; } }; 'removeAllPackingListEntriesFromDistributionEventForProduct': { name: 'removeAllPackingListEntriesFromDistributionEventForProduct'; type: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; } }; 'removeItemsFromUnboxedItemsCollection': { name: 'removeItemsFromUnboxedItemsCollection'; type: { kind: 'OBJECT'; name: 'UnboxedItemsCollection'; ofType: null; } }; 'removePackingListEntryFromDistributionEvent': { name: 'removePackingListEntryFromDistributionEvent'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'sendShipment': { name: 'sendShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'setReturnedNumberOfItemsForDistributionEventsTrackingGroup': { name: 'setReturnedNumberOfItemsForDistributionEventsTrackingGroup'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingEntry'; ofType: null; } }; 'startDistributionEventsTrackingGroup': { name: 'startDistributionEventsTrackingGroup'; type: { kind: 'OBJECT'; name: 'DistributionEventsTrackingGroup'; ofType: null; } }; 'startReceivingShipment': { name: 'startReceivingShipment'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'unassignBoxFromDistributionEvent': { name: 'unassignBoxFromDistributionEvent'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'unassignTag': { name: 'unassignTag'; type: { kind: 'UNION'; name: 'TaggableResource'; ofType: null; } }; 'unassignTagFromBoxes': { name: 'unassignTagFromBoxes'; type: { kind: 'UNION'; name: 'UnassignTagFromBoxesResult'; ofType: null; } }; 'updateBeneficiary': { name: 'updateBeneficiary'; type: { kind: 'OBJECT'; name: 'Beneficiary'; ofType: null; } }; 'updateBox': { name: 'updateBox'; type: { kind: 'OBJECT'; name: 'Box'; ofType: null; } }; 'updatePackingListEntry': { name: 'updatePackingListEntry'; type: { kind: 'OBJECT'; name: 'PackingListEntry'; ofType: null; } }; 'updateSelectedProductsForDistributionEventPackingList': { name: 'updateSelectedProductsForDistributionEventPackingList'; type: { kind: 'OBJECT'; name: 'DistributionEvent'; ofType: null; } }; 'updateShipmentWhenPreparing': { name: 'updateShipmentWhenPreparing'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'updateShipmentWhenReceiving': { name: 'updateShipmentWhenReceiving'; type: { kind: 'OBJECT'; name: 'Shipment'; ofType: null; } }; 'updateTag': { name: 'updateTag'; type: { kind: 'OBJECT'; name: 'Tag'; ofType: null; } }; }; }; 'Organisation': { kind: 'OBJECT'; name: 'Organisation'; fields: { 'bases': { name: 'bases'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Base'; ofType: null; }; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; }; }; 'PackingListEntry': { kind: 'OBJECT'; name: 'PackingListEntry'; fields: { 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'matchingPackedItemsCollections': { name: 'matchingPackedItemsCollections'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'INTERFACE'; name: 'ItemsCollection'; ofType: null; }; }; }; } }; 'numberOfItems': { name: 'numberOfItems'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; } }; 'product': { name: 'product'; type: { kind: 'OBJECT'; name: 'Product'; ofType: null; } }; 'size': { name: 'size'; type: { kind: 'OBJECT'; name: 'Size'; ofType: null; } }; 'state': { name: 'state'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'PackingListEntryState'; ofType: null; }; } }; }; }; 'PackingListEntryInput': { kind: 'INPUT_OBJECT'; name: 'PackingListEntryInput'; isOneOf: false; inputFields: [{ name: 'distributionEventId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; }; defaultValue: null }, { name: 'productId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }, { name: 'sizeId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }, { name: 'numberOfItems'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }]; }; @@ -117,6 +118,8 @@ export type introspection_types = { 'Tag': { kind: 'OBJECT'; name: 'Tag'; fields: { 'base': { name: 'base'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'Base'; ofType: null; }; } }; 'color': { name: 'color'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'description': { name: 'description'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; 'name': { name: 'name'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'taggedResources': { name: 'taggedResources'; type: { kind: 'LIST'; name: never; ofType: { kind: 'NON_NULL'; name: never; ofType: { kind: 'UNION'; name: 'TaggableResource'; ofType: null; }; }; } }; 'type': { name: 'type'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'TagType'; ofType: null; }; } }; }; }; 'TagCreationInput': { kind: 'INPUT_OBJECT'; name: 'TagCreationInput'; isOneOf: false; inputFields: [{ name: 'name'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; defaultValue: null }, { name: 'description'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }, { name: 'color'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; }; defaultValue: null }, { name: 'type'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'TagType'; ofType: null; }; }; defaultValue: null }, { name: 'baseId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Int'; ofType: null; }; }; defaultValue: null }]; }; 'TagDimensionInfo': { kind: 'OBJECT'; name: 'TagDimensionInfo'; fields: { 'color': { name: 'color'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'id': { name: 'id'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'name': { name: 'name'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; }; }; + 'TagError': { kind: 'UNION'; name: 'TagError'; fields: {}; possibleTypes: 'DeletedTagError' | 'InsufficientPermissionError' | 'ResourceDoesNotExistError' | 'TagTypeMismatchError' | 'UnauthorizedForBaseError'; }; + 'TagErrorInfo': { kind: 'OBJECT'; name: 'TagErrorInfo'; fields: { 'error': { name: 'error'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'UNION'; name: 'TagError'; ofType: null; }; } }; 'id': { name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; } }; }; }; 'TagOperationInput': { kind: 'INPUT_OBJECT'; name: 'TagOperationInput'; isOneOf: false; inputFields: [{ name: 'id'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; }; defaultValue: null }, { name: 'resourceId'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'ID'; ofType: null; }; }; defaultValue: null }, { name: 'resourceType'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'TaggableResourceType'; ofType: null; }; }; defaultValue: null }]; }; 'TagType': { name: 'TagType'; enumValues: 'Box' | 'Beneficiary' | 'All'; }; 'TagTypeMismatchError': { kind: 'OBJECT'; name: 'TagTypeMismatchError'; fields: { 'expectedType': { name: 'expectedType'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'ENUM'; name: 'TagType'; ofType: null; }; } }; }; }; diff --git a/graphql/generated/schema.graphql b/graphql/generated/schema.graphql index cd8fc8426..1220a13b1 100644 --- a/graphql/generated/schema.graphql +++ b/graphql/generated/schema.graphql @@ -173,7 +173,7 @@ input BoxMoveInput { input BoxAssignTagInput { labelIdentifiers: [String!]! - tagId: Int! + tagIds: [Int!]! } input CustomProductCreationInput { @@ -349,7 +349,7 @@ type Mutation { " Any boxes that are non-existing, already inside the requested location, inside a different base other than the one of the requested location, and/or in a base that the user must not access are returned in the `BoxesResult.invalidBoxLabelIdentifiers` list. " moveBoxesToLocation(updateInput: BoxMoveInput): MoveBoxesResult " Any boxes that are non-existing, already assigned to the requested tag, and/or in a base that the user must not access are returned in the `BoxesResult.invalidBoxLabelIdentifiers` list. " - assignTagToBoxes(updateInput: BoxAssignTagInput): AssignTagToBoxesResult + assignTagsToBoxes(updateInput: BoxAssignTagInput): AssignTagsToBoxesResult " Any boxes that are non-existing, don't have the requested tag assigned, and/or in a base that the user must not access are returned in the `BoxesResult.invalidBoxLabelIdentifiers` list. " unassignTagFromBoxes(updateInput: BoxAssignTagInput): UnassignTagFromBoxesResult @@ -1136,6 +1136,23 @@ type ShipmentDetail { receivedOn: Datetime } +""" +Utility response type for box bulk tag-mutations, containing both updated boxes and invalid boxes (ignored due to e.g. being deleted, in prohibited base, and/or non-existing) as well as optional info about erroneous tags. +""" +type AssignTagsToBoxesResult { + updatedBoxes: [Box!]! + invalidBoxLabelIdentifiers: [String!]! + tagErrorInfo: [TagErrorInfo!] +} + +""" Error info about tag with specified ID. """ +type TagErrorInfo { + id: ID! + error: TagError! +} + +union TagError = InsufficientPermissionError | ResourceDoesNotExistError | UnauthorizedForBaseError | TagTypeMismatchError | DeletedTagError + type InsufficientPermissionError { " e.g. 'product:write' missing " name: String!