def resolve_berths(self, info, harbor: GlobalID = None, pier: GlobalID = None, min_width: Decimal = 0, min_length: Decimal = 0, **kwargs): if pier and harbor: raise VenepaikkaGraphQLError( _("Cannot pass both pier and harbor filters")) filters = Q() if harbor: filters &= Q(pier__harbor_id=from_global_id(harbor, HarborNode)) if pier: filters &= Q(pier_id=from_global_id(pier, PierNode)) if min_width: filters &= Q(berth_type__width__gte=min_width) if min_length: filters &= Q(berth_type__length__gte=min_length) if "is_available" in kwargs: filters &= Q(is_available=kwargs.get("is_available")) if "is_invoiceable" in kwargs: filters &= Q(is_invoiceable=kwargs.get("is_invoiceable")) return info.context.berth_loader.load_many( keys=Berth.objects.filter(filters).values_list("id", flat=True))
def parse_user(self, profile: Dict[str, dict]) -> HelsinkiProfileUser: user_id = from_global_id(profile.pop("id")) email = None phone = None if "primary_email" in profile: primary_email = profile.pop("primary_email") email = (primary_email is not None and primary_email.get("email")) or None if "primary_phone" in profile: primary_phone = profile.pop("primary_phone") phone = (primary_phone is not None and primary_phone.get("phone")) or None primary_address = profile.pop("primary_address", {}) or {} address = primary_address.get("address") postal_code = primary_address.get("postal_code") city = primary_address.get("city") return HelsinkiProfileUser( UUID(user_id), email=email, phone=phone, address=address, postal_code=postal_code, city=city, **profile, )
def remove_boat_certificates(certificates, boat): try: for cert_id in certificates: cert_id = from_global_id(cert_id) BoatCertificate.objects.get(pk=cert_id, boat=boat).delete() except BoatCertificate.DoesNotExist as e: raise VenepaikkaGraphQLError(e)
def mutate_and_get_payload(cls, root, info, **input): from customers.schema import ProfileNode application = get_node_from_global_id( info, input.pop("id"), only_type=WinterStorageApplicationNode) cls.validate_application_status(application, info, input) # This allows for getting explicit None values if "customer_id" in input: customer_id = input.pop("customer_id", None) if is_customer(info.context.user): raise VenepaikkaGraphQLError( _("A customer cannot modify the customer connected to the application" )) input["customer"] = get_node_from_global_id(info, customer_id, only_type=ProfileNode, nullable=True) if remove_choices := input.pop("remove_choices", []): for choice_id in remove_choices: try: choice = WinterStorageAreaChoice.objects.get( id=from_global_id( choice_id, node_type=WinterStorageAreaChoiceType)) choice.delete() except WinterStorageAreaChoice.DoesNotExist: pass
def create_profile(self, first_name: str, last_name: str, email: str = None, phone: str = None): from ..models import CustomerProfile variables = { "input": { "profile": { "firstName": first_name, "lastName": last_name } } } if email: variables["input"]["profile"]["addEmails"] = [{ "primary": True, "email": email, "emailType": "NONE" }] if phone: variables["input"]["profile"]["addPhones"] = [{ "primary": True, "phone": phone, "phoneType": "NONE" }] mutation = """ mutation CreateProfile($input: CreateProfileMutationInput!) { createProfile(input: $input) { profile { id } } } """ response = self.query(query=mutation, variables=variables) global_id = response.get("createProfile", {}).get("profile", {}).get("id") profile_id = UUID(from_global_id(global_id)) profile = CustomerProfile.objects.create(id=profile_id) return profile
def mutate_and_get_payload(cls, root, info, **input): input["id"] = from_global_id(global_id=input.pop("id"), node_type=ProfileNode) organization_input = None if "organization" in input: organization_input = input.pop("organization") try: profile = CustomerProfile.objects.create(**input) if organization_input: Organization.objects.create(customer=profile, **organization_input) except ValidationError as e: # Flatten all the error messages on a single list errors = sum(e.message_dict.values(), []) raise VenepaikkaGraphQLError(errors) return CreateBerthServicesProfileMutation(profile=profile)
def test_create_boat(api_client, customer_profile, boat_type): check_date = today().date() file_name = "certificate.pdf" owner_id = to_global_id(ProfileNode, customer_profile.id) boat_type_id = str(boat_type.id) variables = { "ownerId": owner_id, "boatTypeId": boat_type_id, "name": "Flying Dutchman", "length": random_decimal(as_string=True), "width": random_decimal(as_string=True), "addBoatCertificates": [ { "file": SimpleUploadedFile( name=file_name, content=None, content_type="application/pdf" ), "certificateType": random.choice(list(BoatCertificateType)).name, "validUntil": str(check_date), "checkedAt": str(check_date), "checkedBy": "John Wick", } ], } assert Boat.objects.count() == 0 assert BoatCertificate.objects.count() == 0 executed = api_client.execute(CREATE_BOAT_MUTATION, input=variables) certificates = executed["data"]["createBoat"]["boat"].pop("certificates") assert Boat.objects.count() == 1 assert BoatCertificate.objects.count() == 1 assert len(certificates) == 1 # Test that all the expected files are in the instance certificates cert = certificates[0] cert_id = cert.pop("id") assert cert_id is not None cert_id = from_global_id(cert_id, BoatCertificateNode) assert get_boat_certificate_media_folder( BoatCertificate.objects.get(id=cert_id), "certificate.pdf" ) in cert.pop("file") assert cert == { "certificateType": variables["addBoatCertificates"][0]["certificateType"], "validUntil": str(check_date), "checkedAt": str(check_date), "checkedBy": "John Wick", } assert executed["data"]["createBoat"]["boat"] == { "owner": {"id": owner_id}, "boatType": {"id": boat_type_id}, "name": variables["name"], "length": variables["length"], "width": variables["width"], }
def test_update_boat(api_client, boat): boat_id = to_global_id(BoatNode, boat.id) owner_id = to_global_id(ProfileNode, boat.owner.id) boat_type_id = str(boat.boat_type.id) file_name_keep = "certificate-keep.pdf" file_name_delete = "certificate-delete.pdf" certificate_delete = BoatCertificateFactory( boat=boat, file=SimpleUploadedFile(name=file_name_delete, content=None) ) variables = { "id": boat_id, "name": "Flying Dutchman", "length": random_decimal(as_string=True), "width": random_decimal(as_string=True), "addBoatCertificates": [ { "file": SimpleUploadedFile( name=file_name_keep, content=None, content_type="application/pdf" ), "certificateType": random.choice(list(BoatCertificateType)).name, "checkedBy": "John Wick", } ], "removeBoatCertificates": [ to_global_id(BoatCertificateNode, certificate_delete.id) ], } assert Boat.objects.count() == 1 assert BoatCertificate.objects.count() == 1 executed = api_client.execute(UPDATE_BOAT_MUTATION, input=variables) certificates = executed["data"]["updateBoat"]["boat"].pop("certificates") assert Boat.objects.count() == 1 assert BoatCertificate.objects.count() == 1 assert len(certificates) == 1 # Test that all the expected files are in the instance certificates cert = certificates[0] cert_id = cert.pop("id") assert cert_id is not None cert_id = from_global_id(cert_id) # Check that the old file was removed assert get_boat_certificate_media_folder( BoatCertificate.objects.get(id=cert_id), file_name_delete ) not in cert.get("file") # Check that the new file has a valid url assert get_boat_certificate_media_folder( BoatCertificate.objects.get(id=cert_id), file_name_keep ) in cert.pop("file") assert cert == { "certificateType": variables["addBoatCertificates"][0]["certificateType"], "checkedBy": variables["addBoatCertificates"][0]["checkedBy"], } assert executed["data"]["updateBoat"]["boat"] == { "owner": {"id": owner_id}, "boatType": {"id": boat_type_id}, "name": variables["name"], "length": variables["length"], "width": variables["width"], }
def find_profile( self, first_name: str = "", last_name: str = "", email: str = "", phone: str = "", force_only_one: bool = True, ) -> Union[List[HelsinkiProfileUser], HelsinkiProfileUser]: """ Find the profile based on the passed criteria, the missing parameters are replaced by empty values. force_only_one: bool -> If more than one profile is found, it will raise an error """ query = f""" query FindProfile {{ profiles( serviceType: BERTH, firstName: "{first_name}", lastName: "{last_name}", emails_Email: "{email}", phones_Phone: "{phone}" ) {{ edges {{ node {{ id first_name: firstName last_name: lastName primary_email: primaryEmail {{ email }} primary_phone: primaryPhone {{ phone }} }} }} }} }} """ response = self.query(query) profiles = (response.get("profiles", {}).get("edges", []) if response and response.get("profiles", {}) and response.get("profiles", {}).get("edges") else []) if force_only_one: if len(profiles) > 1: ids = [ from_global_id(profile_node.get("node", {}).get("id")) for profile_node in profiles ] raise MultipleProfilesException(ids=ids) elif len(profiles) == 0: raise NoProfilesException users = [] for profile_edge in profiles: users.append(self.parse_user_edge(profile_edge)) if force_only_one: return users[0] return users
def resolve_order_refunds(self, info, order_id, **kwargs): return OrderRefund.objects.filter( order_id=from_global_id(order_id, OrderNode))
class UpdateBerthApplication(graphene.ClientIDMutation): class Input(UpdateBerthApplicationInput): pass berth_application = graphene.Field(BerthApplicationNode) @classmethod def validate_application_status(cls, application, info, input): if application.status != ApplicationStatus.PENDING: if is_customer(info.context.user): raise VenepaikkaGraphQLError( _("Cannot modify the application once it has been processed" )) # If the input receives explicitly customerId: None if "customer_id" in input and input.get("customer_id") is None: raise VenepaikkaGraphQLError( _("Customer cannot be disconnected from processed applications" )) def get_nodes_to_check(info, **input): application = get_node_from_global_id(info, input.get("id"), only_type=BerthApplicationNode, nullable=True) return [application] @classmethod @check_user_is_authorised( get_nodes_to_check=get_nodes_to_check, model_checks=[ user_has_view_permission(CustomerProfile, BerthLease), user_has_change_permission(BerthApplication), ], ) @transaction.atomic def mutate_and_get_payload(cls, root, info, **input): from customers.schema import ProfileNode application = get_node_from_global_id(info, input.pop("id"), only_type=BerthApplicationNode) cls.validate_application_status(application, info, input) # This allows for getting explicit None values if "customer_id" in input: customer_id = input.pop("customer_id", None) if is_customer(info.context.user): raise VenepaikkaGraphQLError( _("A customer cannot modify the customer connected to the application" )) input["customer"] = get_node_from_global_id(info, customer_id, only_type=ProfileNode, nullable=True) if remove_choices := input.pop("remove_choices", []): for choice_id in remove_choices: try: choice = HarborChoice.objects.get(id=from_global_id( choice_id, node_type=HarborChoiceType)) choice.delete() except HarborChoice.DoesNotExist: pass if add_choices := input.pop("add_choices", []): for choice in add_choices: HarborChoice.objects.get_or_create( harbor_id=from_global_id(choice.get("harbor_id")), priority=choice.get("priority"), application=application, )