def test_tags_hidden_from_overview(self, shipment_alice, client_bob, new_rw_access_request_bob, devices, overview_tracking_data): new_rw_access_request_bob.tags_permission = PermissionLevel.NONE new_rw_access_request_bob.approved = True new_rw_access_request_bob.save() self.setup_devices_and_tracking(shipment_alice, devices[0], overview_tracking_data[0]) response = client_bob.get(self.shipment_overview) AssertionHelper.HTTP_200(response, is_list=True, entity_refs=[ AssertionHelper.EntityRef( resource='TrackingData', relationships=[{ 'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment_alice.id) }]), ]) response_json = response.json() for included in response_json['included']: assert included['type'] != 'ShipmentTag'
def test_create_multiple_access_requests(self, shipment_alice, client_bob, access_request_ro_attributes, access_request_rw_attributes, user_bob_id): response = client_bob.post(self.list_url, access_request_ro_attributes) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='AccessRequest', attributes={ **{ 'requester_id': user_bob_id }, **access_request_ro_attributes })) response = client_bob.post(self.list_url, access_request_rw_attributes) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='AccessRequest', attributes={ **{ 'requester_id': user_bob_id }, **access_request_rw_attributes }))
def test_includes_legs(self, client_alice, new_route, shipment_alice_with_device, shipment): leg1 = new_route.routeleg_set.create(shipment=shipment) leg2 = new_route.routeleg_set.create(shipment=shipment_alice_with_device) leg1_entity = AssertionHelper.EntityRef(resource='RouteLeg', pk=leg1.pk, attributes={'shipment_id': shipment.pk}) leg2_entity = AssertionHelper.EntityRef(resource='RouteLeg', pk=leg2.pk, attributes={'shipment_id': shipment_alice_with_device.pk}) response = client_alice.get(self.url_route) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Route', pk=new_route.id, attributes={ 'name': new_route.name, 'driver_id': new_route.driver_id, }, relationships={ 'legs': [leg1_entity, leg2_entity] }, ), included=[leg1_entity, leg2_entity] )
def test_with_unassociated_device(self, client_alice, route_attributes, device): route_attributes['device_id'] = device.id with mock.patch('apps.shipments.models.Device.get_or_create_with_permission') as mock_device: mock_device.return_value = device response = client_alice.post(self.url, route_attributes) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='Route', attributes={ 'name': route_attributes['name'], 'driver_id': route_attributes['driver_id'], }, relationships={ 'device': AssertionHelper.EntityRef( resource='Device', pk=route_attributes['device_id'] ), } ), included=AssertionHelper.EntityRef( resource='Device', pk=route_attributes['device_id'] ), )
def test_create_shipment_note(user_alice, shipper_user, api_client, shipper_api_client, client_alice, shipment, mocked_is_shipper, successful_wallet_owner_calls_assertions): url = reverse('shipment-notes-list', kwargs={'version': 'v1', 'shipment_pk': shipment.id}) create_note_data, content_type = create_form_content({'message': MESSAGE_1}) # An unauthenticated user cannot create a shipment note response = api_client.post(url, {'message': MESSAGE_1}) AssertionHelper.HTTP_403(response, error='You do not have permission to perform this action.') # An authenticated request with a empty message should fail response = client_alice.post(url, {'message': ''}) AssertionHelper.HTTP_400(response, error='This field may not be blank.', pointer='message') # An authenticated request with a message with more than 500 characters should fail response = client_alice.post(url, {'message': MESSAGE_2}) AssertionHelper.HTTP_400(response, error='Ensure this value has at most 500 characters (it has 632).', pointer='message') # An authenticated user can create a shipment note response = client_alice.post(url, create_note_data, content_type=content_type) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef(resource='ShipmentNote', attributes={ 'message': MESSAGE_1, 'user_id': user_alice.id, 'username': get_username(user_alice), 'organization_name': get_user_org_name( user_alice)}, relationships={'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id)}) ) # A shipper also valid for moderator and carrier can add a shipment note response = shipper_api_client.post(url, {'message': MESSAGE_1}) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef(resource='ShipmentNote', attributes={ 'message': MESSAGE_1, 'user_id': shipper_user.id, 'username': get_username(shipper_user)}, relationships={ 'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id)}) ) mocked_is_shipper.assert_calls(successful_wallet_owner_calls_assertions)
def test_cannot_update_tag_type(self, client_alice, org_id_alice): response = client_alice.patch(getattr(self, f'url_{self.shipment_tags[0].tag_type}'), { 'tag_type': 'new_tag_type' }) AssertionHelper.HTTP_200(response, entity_refs=AssertionHelper.EntityRef( resource='ShipmentTag', attributes={'tag_type': self.shipment_tags[0].tag_type, 'tag_value': self.shipment_tags[0].tag_value, 'owner_id': org_id_alice}, relationships={ 'shipment': AssertionHelper.EntityRef(resource='Shipment', pk=self.shipment_tags[0].shipment.id) }) )
def test_with_permission_links(self, shipment_alice, client_bob, new_rw_access_request_bob, permission_link_shipment_alice): shipment_data = {'carriers_scac': 'h4x3d'} tag_data = { 'tag_type': 'foo', 'tag_value': 'bar', 'owner_id': client_bob.handler._force_user.id, } # Documents/notes are not accessible via permission link, tracking/telemetry is RO response = client_bob.get( f'{self.endpoint_urls["shipment"]}?permission_link={permission_link_shipment_alice.id}' ) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', relationships={ 'tags': AssertionHelper.EntityRef(resource='ShipmentTag', pk=self.tag.id) }), included=AssertionHelper.EntityRef(resource='ShipmentTag'), ) response = client_bob.patch( f'{self.endpoint_urls["shipment"]}?permission_link={permission_link_shipment_alice.id}', shipment_data) AssertionHelper.HTTP_403(response) response = client_bob.post( f'{self.endpoint_urls["tags"]}?permission_link={permission_link_shipment_alice.id}', tag_data) AssertionHelper.HTTP_403(response) new_rw_access_request_bob.approved = True new_rw_access_request_bob.save() response = client_bob.patch( f'{self.endpoint_urls["shipment"]}?permission_link={permission_link_shipment_alice.id}', shipment_data) AssertionHelper.HTTP_202(response) response = client_bob.post( f'{self.endpoint_urls["tags"]}?permission_link={permission_link_shipment_alice.id}', tag_data) AssertionHelper.HTTP_201(response)
def test_list_search_filter(client_alice, shipper_api_client, api_client, shipment, mocked_is_shipper, shipment_notes, successful_wallet_owner_calls_assertions, shipper_user): url = reverse('shipment-notes-list', kwargs={'version': 'v1', 'shipment_pk': shipment.id}) # An unauthenticated user cannot list a shipment notes response = api_client.get(url) AssertionHelper.HTTP_403(response) # A shipment owner can list all notes associated response = client_alice.get(url) AssertionHelper.HTTP_200(response, is_list=True, count=len(shipment_notes) - 1) # A shipper can list only the notes associated to the relative shipment response = shipper_api_client.get(url) AssertionHelper.HTTP_200(response, is_list=True, count=len(shipment_notes) - 1) mocked_is_shipper.assert_calls(successful_wallet_owner_calls_assertions) # There is only one note authored by the shipper response = client_alice.get(f'{url}?user_id={shipper_user.id}') AssertionHelper.HTTP_200(response, is_list=True, entity_refs=[AssertionHelper.EntityRef(resource='ShipmentNote', attributes={ 'message': shipment_notes[2].message, 'user_id': shipment_notes[2].user_id, 'username': shipment_notes[2].username}, relationships={ 'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id)})], count=1 ) # There is only one note containing the word "ShipChain" response = client_alice.get(f'{url}?search=shipchain') AssertionHelper.HTTP_200(response, is_list=True, entity_refs=[AssertionHelper.EntityRef(resource='ShipmentNote', attributes={ 'message': shipment_notes[1].message, 'user_id': shipment_notes[1].user_id, 'username': shipment_notes[1].username}, relationships={ 'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id)})], count=1 )
def test_pickup(client_alice, shipment): assert shipment.pickup_act is None url = reverse('shipment-actions', kwargs={ 'version': 'v1', 'shipment_pk': shipment.id }) action = {'action_type': ActionType.PICK_UP.name} response = client_alice.post(url, data=action) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes={'state': TransitState.IN_TRANSIT.name})) updated_parameters = response.json()['data']['attributes'] assert datetimeAlmostEqual(dt_parse(updated_parameters['pickup_act'])) # Can't pickup when IN_TRANSIT response = client_alice.post(url, data=action) AssertionHelper.HTTP_400( response, error= 'Action PICK_UP not available while Shipment is in state IN_TRANSIT', pointer='action_type')
def test_shipment_update_with_assignee(client_alice, shipment): url = reverse('shipment-detail', kwargs={ 'version': 'v1', 'pk': shipment.id }) valid_uuid4_data = { 'assignee_id': VALID_UUID4, } invalid_uuid4_data = { 'assignee_id': VALID_UUID4 + '12', } # A shipment cannot be updated with an invalid assignee ID response = client_alice.patch(url, data=invalid_uuid4_data) AssertionHelper.HTTP_400(response, error='Must be a valid UUID.', pointer='assignee_id') # With a valid assignee ID the request should succeed response = client_alice.patch(url, data=valid_uuid4_data) AssertionHelper.HTTP_202(response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes={'assignee_id': VALID_UUID4}))
def test_pickup_with_gtx_required(client_alice, shipment): assert shipment.pickup_act is None shipment.gtx_required = True shipment.save() url = reverse('shipment-actions', kwargs={ 'version': 'v1', 'shipment_pk': shipment.id }) action = {'action_type': ActionType.PICK_UP.name} # If gtx_required, pickup requires an asset_physical_id response = client_alice.post(url, data=action) AssertionHelper.HTTP_403( response, error= 'In order to proceed with this shipment pick up, you need to provide a ' 'value for the field [Shipment.asset_physical_id]') action['asset_physical_id'] = 'nfc_tag' response = client_alice.post(url, data=action) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes={'state': TransitState.IN_TRANSIT.name}))
def test_profiles_disabled_shipment_tag_creation( api_client, shipment, shipment_tag_creation_data, shipment_tag_creation_missing_owner_id, entity_shipment_relationship): url = reverse('shipment-tags-list', kwargs={ 'version': 'v1', 'shipment_pk': shipment.id }) # A request without user_id should fail response = api_client.post(url, shipment_tag_creation_missing_owner_id) AssertionHelper.HTTP_400(response, error='This field is required.') response = api_client.post(url, shipment_tag_creation_data) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='ShipmentTag', attributes={ 'tag_type': shipment_tag_creation_data['tag_type'], 'tag_value': shipment_tag_creation_data['tag_value'], 'owner_id': USER_ID }, relationships={'shipment': entity_shipment_relationship}))
def test_shipment_creation_with_assignee(client_alice, mocked_is_shipper, mocked_storage_credential, shipment): url = reverse('shipment-list', kwargs={'version': 'v1'}) valid_uuid4_data = { 'storage_credentials_id': shipment.storage_credentials_id, 'shipper_wallet_id': shipment.shipper_wallet_id, 'carrier_wallet_id': shipment.carrier_wallet_id, 'assignee_id': VALID_UUID4, } invalid_uuid4_data = { 'storage_credentials_id': shipment.storage_credentials_id, 'shipper_wallet_id': shipment.shipper_wallet_id, 'carrier_wallet_id': shipment.carrier_wallet_id, 'assignee_id': VALID_UUID4[:-1], } # A shipment cannot be created with an invalid assignee ID response = client_alice.post(url, data=invalid_uuid4_data) AssertionHelper.HTTP_400(response, error='Must be a valid UUID.', pointer='assignee_id') # With a valid assignee ID the request should succeed response = client_alice.post(url, data=valid_uuid4_data) AssertionHelper.HTTP_202(response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', attributes={'assignee_id': VALID_UUID4}))
def test_permission_link_email_send_multiform(self, client_alice, mock_aws_success, user_alice): multi_form_data, content_type = create_form_content({ 'name': 'Permission Link Name', 'emails': ['*****@*****.**', '*****@*****.**'] }) response = client_alice.post(self.url_permission_link_create, multi_form_data, content_type=content_type) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={'name': 'Permission Link Name'}, relationships=self.shipment_alice_relationships)) assert len(mail.outbox) == 1 assert 'The ShipChain team' in str(mail.outbox[0].body) assert user_alice.username in str(mail.outbox[0].body) assert user_alice.username in str(mail.outbox[0].subject) pm_id = response.json()['data']['id'] mock_aws_success.assert_calls([{ 'path': '/test/', 'query': None, 'body': { 'long_url': f'http://localhost:3000/shipments/{self.shipment_alice.id}/?permission_link={pm_id}', 'expiration_date': None }, 'host': settings.URL_SHORTENER_HOST }])
def test_file_types(self, client_alice, entity_ref_shipment_alice): attributes = { 'name': 'Test BOL', 'file_type': 'NOT A FILE TYPE', 'document_type': 'BOL', } response = client_alice.post(self.shipment_alice_url, attributes) AssertionHelper.HTTP_400(response, error=f'"{attributes["file_type"]}" is not a valid choice.', pointer='file_type') attributes['file_type'] = FileType.PDF.name response = client_alice.post(self.shipment_alice_url, attributes) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='Document', attributes={ 'upload_status': UploadStatus.PENDING.name, **attributes }, relationships=[{ 'shipment': entity_ref_shipment_alice }], meta={ 'presigned_s3_thumbnail': None } )) assert isinstance(response.json()['data']['meta']['presigned_s3'], dict)
def test_create_shipment_note(api_client, shipment): url = reverse('shipment-notes-list', kwargs={ 'version': 'v1', 'shipment_pk': shipment.id }) bad_shipment_url = reverse('shipment-notes-list', kwargs={ 'version': 'v1', 'shipment_pk': random_id() }) create_note_data, content_type = create_form_content({ 'message': MESSAGE, 'user_id': USER_ID }) # An unauthenticated user cannot create a shipment note without specifying the user response = api_client.post(url, {'message': MESSAGE}) AssertionHelper.HTTP_400(response, error='This field is required.', pointer='user_id') # A shipment note cannot be created for a non existing shipment response = api_client.post(bad_shipment_url, create_note_data, content_type=content_type) AssertionHelper.HTTP_403( response, error='You do not have permission to perform this action.') # An authenticated user with a specified user can create a shipment note response = api_client.post(url, create_note_data, content_type=content_type) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='ShipmentNote', attributes={ 'message': MESSAGE, 'user_id': USER_ID, 'username': None }, relationships={ 'shipment': AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id) }))
def test_owner_can_create(self, client_alice): response = client_alice.post(self.url_permission_link_create, {'name': 'Permission Link Name'}) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={'name': 'Permission Link Name'}, relationships=self.shipment_alice_relationships))
def entity_ref_permission_link(permission_link_shipment_alice, entity_ref_shipment_alice): return AssertionHelper.EntityRef( resource='PermissionLink', pk=permission_link_shipment_alice.id, attributes={'name': permission_link_shipment_alice.name}, relationships=[{ 'shipment': entity_ref_shipment_alice }])
def test_meta_field_presence(self, shipment_alice, client_bob, approved_access_request_bob): response = client_bob.get(self.shipment_detail) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment_alice.id, meta={'permission_derivation': 'AccessRequest'}))
def entity_ref_access_request_bob(new_access_request_bob, user_bob_id, entity_ref_shipment_alice): return AssertionHelper.EntityRef(resource='AccessRequest', pk=new_access_request_bob.id, attributes={'requester_id': user_bob_id}, relationships=[{ 'shipment': entity_ref_shipment_alice }])
def test_org_user_shipment_tag(org_id_alice, api_client, client_alice, shipment, shipment_tag_creation_data, missing_tag_type_creation_data, missing_tag_value_creation_data, space_in_tag_type_creation_data, space_in_tag_value_creation_data): url = reverse('shipment-tags-list', kwargs={'version': 'v1', 'shipment_pk': shipment.id}) # An unauthenticated user cannot tag a shipment response = api_client.post(url, shipment_tag_creation_data) AssertionHelper.HTTP_403(response, error='You do not have permission to perform this action.') # An org user cannot tag a shipment with missing tag_type in creation data response = client_alice.post(url, missing_tag_type_creation_data) AssertionHelper.HTTP_400(response, error='This field is required.') # An org user cannot tag a shipment with missing tag_value in creation data response = client_alice.post(url, missing_tag_value_creation_data) AssertionHelper.HTTP_400(response, error='This field is required.') # An org user cannot tag a shipment with space in tag_value field creation data response = client_alice.post(url, space_in_tag_value_creation_data) AssertionHelper.HTTP_400(response, error='Space(s) not allowed in this field') # An org user cannot tag a shipment with space in tag_type field creation data response = client_alice.post(url, space_in_tag_type_creation_data) AssertionHelper.HTTP_400(response, error='Space(s) not allowed in this field') # An org user with proper tag data definition, should tag a shipment response = client_alice.post(url, shipment_tag_creation_data) AssertionHelper.HTTP_201(response, entity_refs=AssertionHelper.EntityRef( resource='ShipmentTag', attributes={'tag_type': shipment_tag_creation_data['tag_type'], 'tag_value': shipment_tag_creation_data['tag_value'], 'owner_id': org_id_alice}, relationships={ 'shipment': AssertionHelper.EntityRef(resource='Shipment', pk=shipment.id) }) ) # Trying to tag a shipment with an existing (tag_type, tag_value) pair should fail response = client_alice.post(url, shipment_tag_creation_data) AssertionHelper.HTTP_400(response, error='This shipment already has a tag with the provided [tag_type] and [tag_value].')
def test_can_create_with_permission(self, client_bob, mock_successful_wallet_owner_calls): response = client_bob.post(self.url_permission_link_create, {'name': 'Permission Link Name'}) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='PermissionLink', attributes={'name': 'Permission Link Name'}, relationships=self.shipment_alice_relationships)) mock_successful_wallet_owner_calls.assert_calls( self.successful_wallet_owner_calls_assertions)
def test_with_attributes(self, client_alice, route_attributes): response = client_alice.post(self.url, route_attributes) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='Route', attributes={ 'name': route_attributes['name'], 'driver_id': route_attributes['driver_id'], }, ), )
def setup_url(self, new_route, new_route_bob, shipment, second_shipment, third_shipment): leg1 = new_route.routeleg_set.create(shipment=shipment) leg2 = new_route.routeleg_set.create(shipment=second_shipment) leg3 = new_route.routeleg_set.create(shipment=third_shipment) self.url_random = reverse('route-reorder', kwargs={'version': 'v1', 'pk': random_id()}) self.url_route = reverse('route-reorder', kwargs={'version': 'v1', 'pk': new_route.id}) self.url_route_bob = reverse('route-reorder', kwargs={'version': 'v1', 'pk': new_route_bob.id}) self.insert_order = [leg1.pk, leg2.pk, leg3.pk] self.reverse_order = [leg3.pk, leg2.pk, leg1.pk] self.short_order = [leg1.pk, leg3.pk] self.long_order = [leg1.pk, leg3.pk] self.bad_order = [leg1.pk, random_id(), leg3.pk] self.leg1_entity = AssertionHelper.EntityRef(resource='RouteLeg', pk=leg1.pk, attributes={'shipment_id': shipment.pk}) self.leg2_entity = AssertionHelper.EntityRef(resource='RouteLeg', pk=leg2.pk, attributes={'shipment_id': second_shipment.pk}) self.leg3_entity = AssertionHelper.EntityRef(resource='RouteLeg', pk=leg3.pk, attributes={'shipment_id': third_shipment.pk})
def test_geofence_creates(client_alice, mocked_iot_api, mocked_profiles, mocked_engine_rpc, profiles_ids, successful_shipment_create_profiles_assertions): url = reverse('shipment-list', kwargs={'version': 'v1'}) shipment_create_request = {"geofences": [GEOFENCE_3], **profiles_ids} response = client_alice.post(url, data=shipment_create_request) AssertionHelper.HTTP_202(response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', attributes=shipment_create_request)) mocked_profiles.assert_calls( successful_shipment_create_profiles_assertions)
def test_geofence_updates(client_alice, shipment_with_device, shipment): url = reverse('shipment-detail', kwargs={ 'version': 'v1', 'pk': shipment_with_device.id }) shipment_update_request = {'geofences': [GEOFENCE_1]} response = client_alice.patch(url, data=shipment_update_request) AssertionHelper.HTTP_202(response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes=shipment_update_request)) shipment_update_request_formdata, content_type = create_form_content({ "geofences": json.dumps([GEOFENCE_2]), }) response = client_alice.patch(url, data=shipment_update_request_formdata, content_type=content_type) AssertionHelper.HTTP_202(response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes={'geofences': [GEOFENCE_2]})) # Test shipment without a device url = reverse('shipment-detail', kwargs={ 'version': 'v1', 'pk': shipment.id }) shipment_update_request = {'geofences': [GEOFENCE_3]} response = client_alice.patch(url, data=shipment_update_request) AssertionHelper.HTTP_202(response, entity_refs=AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes=shipment_update_request))
def test_creator_update(self, client_alice, route_attributes, new_route): response = client_alice.patch(self.url_route, data=route_attributes) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Route', pk=new_route.id, attributes={ 'name': route_attributes['name'], 'driver_id': route_attributes['driver_id'], } ) )
def test_creator_get(self, client_alice, new_route): response = client_alice.get(self.url_route) AssertionHelper.HTTP_200( response, entity_refs=AssertionHelper.EntityRef( resource='Route', pk=new_route.id, attributes={ 'name': new_route.name, 'driver_id': new_route.driver_id, } ) )
def test_org_shipment(self, client_alice, leg_attributes, second_shipment): leg_attributes['shipment_id'] = second_shipment.pk response = client_alice.post(self.url_route, data=leg_attributes) AssertionHelper.HTTP_201( response, entity_refs=AssertionHelper.EntityRef( resource='RouteLeg', attributes={ 'shipment_id': second_shipment.pk, }, ) )
def alice_organization_shipment_fixtures(alice_organization_shipments, profiles_ids): return [ AssertionHelper.EntityRef( resource='Shipment', pk=shipment.id, attributes={ 'vault_id': shipment.vault_id, 'owner_id': shipment.owner_id, **profiles_ids }, ) for shipment in alice_organization_shipments ]