Esempio n. 1
0
 class Arguments:
     title = graphene.String()
     body = graphene.String()
     publish_date = graphene.types.datetime.Date()
     public = graphene.Boolean()
     slug = graphene.String()
Esempio n. 2
0
class ProductVariant(CountableDjangoObjectType):
    quantity = graphene.Int(
        required=True,
        description="Quantity of a product available for sale.",
        deprecation_reason=
        ("Use the stock field instead. This field will be removed after 2020-07-31."
         ),
    )
    quantity_allocated = graphene.Int(
        required=False,
        description="Quantity allocated for orders.",
        deprecation_reason=
        ("Use the stock field instead. This field will be removed after 2020-07-31."
         ),
    )
    stock_quantity = graphene.Int(
        required=True,
        description="Quantity of a product available for sale.",
        deprecation_reason=("Use the quantityAvailable field instead. "
                            "This field will be removed after 2020-07-31."),
    )
    price_override = graphene.Field(
        Money,
        description=
        ("Override the base price of a product if necessary. A value of `null` "
         "indicates that the default product price is used."),
    )
    pricing = graphene.Field(
        VariantPricingInfo,
        description=
        ("Lists the storefront variant's pricing, the current price and discounts, "
         "only meant for displaying."),
    )
    is_available = graphene.Boolean(
        description="Whether the variant is in stock and visible or not.",
        deprecation_reason=
        ("Use the stock field instead. This field will be removed after 2020-07-31."
         ),
    )

    attributes = graphene.List(
        graphene.NonNull(SelectedAttribute),
        required=True,
        description="List of attributes assigned to this variant.",
    )
    cost_price = graphene.Field(Money,
                                description="Cost price of the variant.")
    margin = graphene.Int(description="Gross margin percentage value.")
    quantity_ordered = graphene.Int(description="Total quantity ordered.")
    revenue = graphene.Field(
        TaxedMoney,
        period=graphene.Argument(ReportingPeriod),
        description=
        ("Total revenue generated by a variant in given period of time. Note: this "
         "field should be queried using `reportProductSales` query as it uses "
         "optimizations suitable for such calculations."),
    )
    images = graphene.List(
        lambda: ProductImage,
        description="List of images for the product variant.")
    translation = TranslationField(ProductVariantTranslation,
                                   type_name="product variant")
    digital_content = graphene.Field(
        DigitalContent, description="Digital content for the product variant.")
    stocks = graphene.Field(
        graphene.List(Stock),
        description="Stocks for the product variant.",
        country_code=graphene.Argument(
            CountryCodeEnum,
            description="Two-letter ISO 3166-1 country code.",
            required=False,
        ),
    )
    quantity_available = graphene.Int(
        required=True,
        description="Quantity of a product available for sale in one checkout.",
        country_code=graphene.Argument(
            CountryCodeEnum,
            description=
            ("Two-letter ISO 3166-1 country code. When provided, the exact quantity "
             "from a warehouse operating in shipping zones that contain this "
             "country will be returned. Otherwise, it will return the maximum "
             "quantity from all shipping zones."),
        ),
    )

    class Meta:
        description = (
            "Represents a version of a product such as different size or color."
        )
        only_fields = [
            "id", "name", "product", "sku", "track_inventory", "weight"
        ]
        interfaces = [relay.Node, ObjectWithMetadata]
        model = models.ProductVariant

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_stocks(root: models.ProductVariant, info, country_code=None):
        if not country_code:
            return root.stocks.annotate_available_quantity()
        return root.stocks.for_country(
            country_code).annotate_available_quantity()

    @staticmethod
    def resolve_quantity_available(root: models.ProductVariant,
                                   info,
                                   country_code=None):
        if not root.track_inventory:
            return settings.MAX_CHECKOUT_LINE_QUANTITY

        return AvailableQuantityByProductVariantIdAndCountryCodeLoader(
            info.context).load((root.id, country_code))

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_digital_content(root: models.ProductVariant, *_args):
        return getattr(root, "digital_content", None)

    @staticmethod
    def resolve_stock_quantity(root: models.ProductVariant, info):
        if not root.track_inventory:
            return settings.MAX_CHECKOUT_LINE_QUANTITY

        return AvailableQuantityByProductVariantIdAndCountryCodeLoader(
            info.context).load((root.id, info.context.country))

    @staticmethod
    def resolve_attributes(root: models.ProductVariant, info):
        return SelectedAttributesByProductVariantIdLoader(info.context).load(
            root.id)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_margin(root: models.ProductVariant, *_args):
        return get_margin_for_variant(root)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_cost_price(root: models.ProductVariant, *_args):
        return root.cost_price

    @staticmethod
    def resolve_price(root: models.ProductVariant, *_args):
        return root.base_price

    @staticmethod
    def resolve_pricing(root: models.ProductVariant, info):
        context = info.context
        product = ProductByIdLoader(context).load(root.product_id)
        collections = CollectionsByProductIdLoader(context).load(
            root.product_id)

        def calculate_pricing_info(discounts):
            def calculate_pricing_with_product(product):
                def calculate_pricing_with_collections(collections):
                    availability = get_variant_availability(
                        variant=root,
                        product=product,
                        collections=collections,
                        discounts=discounts,
                        country=context.country,
                        local_currency=context.currency,
                        plugins=context.plugins,
                    )
                    return VariantPricingInfo(**asdict(availability))

                return collections.then(calculate_pricing_with_collections)

            return product.then(calculate_pricing_with_product)

        return (DiscountsByDateTimeLoader(context).load(
            info.context.request_time).then(calculate_pricing_info))

    @staticmethod
    def resolve_product(root: models.ProductVariant, info):
        return ProductByIdLoader(info.context).load(root.product_id)

    @staticmethod
    def resolve_is_available(root: models.ProductVariant, info):
        if not root.track_inventory:
            return True

        def is_variant_in_stock(available_quantity):
            return available_quantity > 0

        return (AvailableQuantityByProductVariantIdAndCountryCodeLoader(
            info.context).load(
                (root.id, info.context.country)).then(is_variant_in_stock))

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_price_override(root: models.ProductVariant, *_args):
        return root.price_override

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_quantity(root: models.ProductVariant, info):
        return get_available_quantity(root, info.context.country)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_quantity_ordered(root: models.ProductVariant, *_args):
        # This field is added through annotation when using the
        # `resolve_report_product_sales` resolver.
        return getattr(root, "quantity_ordered", None)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_quantity_allocated(root: models.ProductVariant, info):
        country = info.context.country
        return get_quantity_allocated(root, country)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_revenue(root: models.ProductVariant, *_args, period):
        start_date = reporting_period_to_date(period)
        return calculate_revenue_for_variant(root, start_date)

    @staticmethod
    def resolve_images(root: models.ProductVariant, *_args):
        return root.images.all()

    @classmethod
    def get_node(cls, info, pk):
        user = info.context.user
        visible_products = models.Product.objects.visible_to_user(
            user).values_list("pk", flat=True)
        qs = cls._meta.model.objects.filter(product__id__in=visible_products)
        return qs.filter(pk=pk).first()

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_private_meta(root: models.ProductVariant, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root: models.ProductVariant, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
Esempio n. 3
0
class PageInterface(graphene.Interface):
    """
    Set basic fields exposed on every page object.
    """

    id = graphene.ID()
    url = graphene.String()
    depth = graphene.Int()
    page_type = graphene.String()
    title = graphene.String()
    seo_title = graphene.String()
    search_description = graphene.String()
    show_in_menus = graphene.Boolean()
    specific = graphene.Field(lambda: PageInterface)
    children = QuerySetList(lambda: PageInterface, enable_search=True)
    siblings = QuerySetList(lambda: PageInterface, enable_search=True)
    parent = graphene.Field(lambda: PageInterface)
    next_siblings = QuerySetList(lambda: PageInterface, enable_search=True)
    previous_siblings = QuerySetList(lambda: PageInterface, enable_search=True)
    descendants = QuerySetList(lambda: PageInterface, enable_search=True)
    ancestors = QuerySetList(lambda: PageInterface, enable_search=True)

    class Meta:
        description = _(
            'Interface used by every GraphQL Wagtail page object type.')

    def resolve_url(self, info):
        """
        Resolve a path to a page.
        """
        request = info.context
        return self.get_url(request=request, current_site=request.site)

    def resolve_page_type(self, info):
        """
        Resolve a page type in a form of ``app.ModelName``.
        """
        return '.'.join([
            self.content_type.app_label,
            self.content_type.model_class().__name__
        ])

    def resolve_children(self, info, **kwargs):
        return get_base_queryset_for_page_model_or_qs(self.get_children(),
                                                      info, **kwargs)

    def resolve_descendants(self, info, **kwargs):
        return get_base_queryset_for_page_model_or_qs(self.get_descendants(),
                                                      info, **kwargs)

    def resolve_ancestors(self, info, **kwargs):
        return get_base_queryset_for_page_model_or_qs(self.get_ancestors(),
                                                      info, **kwargs)

    def resolve_siblings(self, info, **kwargs):
        return get_base_queryset_for_page_model_or_qs(
            self.get_siblings().exclude(pk=self.pk), info, **kwargs)

    def resolve_next_siblings(self, info, **kwargs):
        return get_base_queryset_for_page_model_or_qs(
            self.get_next_siblings().exclude(pk=self.pk), info, **kwargs)

    def resolve_previous_siblings(self, info, **kwargs):
        return get_base_queryset_for_page_model_or_qs(
            self.get_prev_siblings().exclude(pk=self.pk), info, **kwargs)

    def resolve_parent(self, info, **kwargs):
        parent = self.get_parent()
        if parent is None:
            return
        qs = get_base_queryset_for_page_model_or_qs(Page, info, **kwargs)
        try:
            return qs.get(pk=parent.pk).specific
        except Page.DoesNotExist:
            return

    def resolve_specific(self, info, **kwargs):
        return self.specific

    def resolve_seo_title(self, info):
        """
        Get page's SEO title. Fallback to a normal page's title if absent.
        """
        return self.seo_title or self.title
Esempio n. 4
0
    class Arguments:
	    user_type = graphene.String(required=True)
	    name = graphene.String(required=True)
	    is_employed = graphene.Boolean(required=True)
	    occupation = graphene.String(required=True)
class LabbookFavorite(graphene.ObjectType,
                      interfaces=(graphene.relay.Node, GitRepository)):
    """A type representing a file or directory that has been favorited in the labbook file system."""
    # An instance of loaded favorite data
    _favorite_data = None

    # Section in the LabBook (code, input, output)
    section = graphene.String(required=True)

    # Relative path from labbook root directory.
    key = graphene.String(required=True)

    # Index value indicating the order of the favorite
    index = graphene.Int()

    # Short description about the favorite
    description = graphene.String()

    # The graphene type id for the associated file
    associated_labbook_file_id = graphene.String()

    # True indicates that the favorite is a directory
    is_dir = graphene.Boolean()

    def _load_favorite_info(self, dataloader):
        """Private method to retrieve file info for a given key"""
        if not self._favorite_data:
            # Load file info from LabBook
            if not self.section or self.key is None:
                raise ValueError(
                    "Must set `section` and `key` on object creation to resolve favorite info"
                )

            # Load labbook instance
            lb = dataloader.load(
                f"{get_logged_in_username()}&{self.owner}&{self.name}").get()

            data = lb.get_favorites(self.section)

            # Pull out single entry
            self._favorite_data = data[self.key]

        # Set class properties
        self.description = self._favorite_data['description']
        self.index = self._favorite_data['index']
        self.is_dir = self._favorite_data['is_dir']

    @classmethod
    def get_node(cls, info, id):
        """Method to resolve the object based on it's Node ID"""
        # Parse the key
        owner, name, section, key = id.split("&")

        return LabbookFavorite(id=f"{owner}&{name}&{section}&{key}",
                               name=name,
                               owner=owner,
                               section=section,
                               key=key)

    def resolve_id(self, info):
        """Resolve the unique Node id for this object"""
        if not self.id:
            if not self.owner or not self.name or not self.section or self.key is None:
                raise ValueError(
                    "Resolving a LabbookFavorite Node ID requires owner,name,section, and key to be set"
                )

            self.id = f"{self.owner}&{self.name}&{self.section}&{self.key}"

        return self.id

    def resolve_is_dir(self, info):
        """Resolve the is_dir field"""
        if self.is_dir is None:
            self._load_favorite_info(info.context.labbook_loader)
        return self.is_dir

    def resolve_key(self, info):
        """Resolve the is_dir field"""
        if self.key is None:
            self._load_favorite_info(info.context.labbook_loader)
        return self.key

    def resolve_index(self, info):
        """Resolve the index field"""
        if self.index is None:
            self._load_favorite_info(info.context.labbook_loader)
        return self.index

    def resolve_description(self, info):
        """Resolve the is_dir field"""
        if self.description is None:
            self._load_favorite_info(info.context.labbook_loader)
        return self.description

    def resolve_associated_labbook_file_id(self, info):
        """Resolve the associated_labbook_file_id field"""
        return base64.b64encode(
            f"LabbookFile:{self.owner}&{self.name}&{self.section}&{self.key}".
            encode()).decode()
Esempio n. 6
0
class Collection(CountableDjangoObjectType):
    products = FilterInputConnectionField(
        Product,
        filter=ProductFilterInput(description="Filtering options for products."),
        sort_by=ProductOrder(description="Sort products."),
        description="List of products in this collection.",
    )
    background_image = graphene.Field(
        Image, size=graphene.Int(description="Size of the image.")
    )
    description = graphene.String(
        description="Description of the collection.",
        deprecation_reason="Use the `descriptionJson` field instead.",
        required=True,
    )
    translation = TranslationField(CollectionTranslation, type_name="collection")
    is_published = graphene.Boolean(
        required=True, description="Whether the collection is published."
    )

    class Meta:
        description = "Represents a collection of products."
        only_fields = [
            "description_json",
            "id",
            "name",
            "publication_date",
            "seo_description",
            "seo_title",
            "slug",
        ]
        interfaces = [relay.Node, ObjectWithMetadata]
        model = models.Collection

    @staticmethod
    def resolve_background_image(root: models.Collection, info, size=None, **_kwargs):
        if root.background_image:
            return Image.get_adjusted(
                image=root.background_image,
                alt=root.background_image_alt,
                size=size,
                rendition_key_set="background_images",
                info=info,
            )

    @staticmethod
    def resolve_products(root: models.Collection, info, first=None, **kwargs):
        return root.products.visible_to_user(info.context.user)

    @classmethod
    def get_node(cls, info, id):
        if info.context:
            requestor = get_user_or_app_from_context(info.context)
            qs = cls._meta.model.objects.visible_to_user(requestor)
            return qs.filter(id=id).first()
        return None

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_private_meta(root: models.Collection, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root: models.Collection, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)

    @staticmethod
    def resolve_is_published(root: models.Collection, _info):
        return root.is_visible
Esempio n. 7
0
class DeleteMutation(graphene.Mutation):
    class Meta:
        abstract = True

    id = graphene.ID()
    ok = graphene.Boolean(
        description="Boolean field that return mutation result request.")
    errors = graphene.List(ErrorType, description="Errors list for the field")

    class Arguments:
        id = graphene.ID(required=True)

    @classmethod
    def __init_subclass_with_meta__(cls,
                                    model=None,
                                    interfaces=(),
                                    resolver=None,
                                    output=None,
                                    arguments=None,
                                    _meta=None,
                                    **options):
        if not _meta:
            _meta = DeleteMutationOptions(cls)

        assert model is not None, ("Model class in {} must be need.").format(
            cls.__name__)
        _meta.model = model
        super(DeleteMutation,
              cls).__init_subclass_with_meta__(interfaces=interfaces,
                                               resolver=resolver,
                                               output=output,
                                               arguments=arguments,
                                               _meta=_meta,
                                               **options)

    @classmethod
    def get_errors(cls, errors):
        errors_dict = {"ok": False, "errors": errors, "id": None}

        return cls(**errors_dict)

    @classmethod
    def perform_mutate(cls, obj, info):
        resp = {"ok": True, "errors": None, "id": obj.id}

        return cls(**resp)

    @classmethod
    def mutate(cls, root, info, id):
        try:
            obj = cls._meta.model.objects.get(id=id)
            obj.delete()
            obj.id = id
            return cls.perform_mutate(obj, info)
        except ObjectDoesNotExist:
            return cls.get_errors([
                ErrorType(
                    field="id",
                    messages=[
                        "A {} obj with id {} do not exist".format(
                            cls._meta.model.__name__, id)
                    ],
                )
            ])

    @classmethod
    def Field(cls,
              name=None,
              description=None,
              deprecation_reason=None,
              required=False):
        """ Mount instance of mutation Field. """
        return Field(
            cls._meta.output,
            args=cls._meta.arguments,
            resolver=cls._meta.resolver,
            name=name,
            description=description or cls._meta.description,
            deprecation_reason=deprecation_reason,
            required=required,
        )
Esempio n. 8
0
class AccountRegister(ModelMutation):
    class Arguments:
        input = AccountRegisterInput(
            description="Fields required to create a user.", required=True)

    requires_confirmation = graphene.Boolean(
        description="Informs whether users need to confirm their email address."
    )

    class Meta:
        description = "Register a new user."
        exclude = ["password"]
        model = models.User
        object_type = User
        error_type_class = AccountError
        error_type_field = "account_errors"

    @classmethod
    def mutate(cls, root, info, **data):
        response = super().mutate(root, info, **data)
        response.requires_confirmation = settings.ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL
        return response

    @classmethod
    def clean_input(cls, info, instance, data, input_cls=None):
        data["metadata"] = {
            item["key"]: item["value"]
            for item in data.get("metadata") or []
        }
        if not settings.ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL:
            return super().clean_input(info, instance, data, input_cls=None)
        elif not data.get("redirect_url"):
            raise ValidationError({
                "redirect_url":
                ValidationError("This field is required.",
                                code=AccountErrorCode.REQUIRED)
            })

        try:
            validate_storefront_url(data["redirect_url"])
        except ValidationError as error:
            raise ValidationError({
                "redirect_url":
                ValidationError(error.message, code=AccountErrorCode.INVALID)
            })

        data["channel"] = clean_channel(data.get("channel"),
                                        error_class=AccountErrorCode).slug

        password = data["password"]
        try:
            password_validation.validate_password(password, instance)
        except ValidationError as error:
            raise ValidationError({"password": error})

        data["language_code"] = data.get("language_code",
                                         settings.LANGUAGE_CODE)
        return super().clean_input(info, instance, data, input_cls=None)

    @classmethod
    @traced_atomic_transaction()
    def save(cls, info, user, cleaned_input):
        password = cleaned_input["password"]
        user.set_password(password)
        user.search_document = search.prepare_user_search_document_value(
            user, attach_addresses_data=False)
        if settings.ENABLE_ACCOUNT_CONFIRMATION_BY_EMAIL:
            user.is_active = False
            user.save()
            notifications.send_account_confirmation(
                user,
                cleaned_input["redirect_url"],
                info.context.plugins,
                channel_slug=cleaned_input["channel"],
            )
        else:
            user.save()

        account_events.customer_account_created_event(user=user)
        info.context.plugins.customer_created(customer=user)
Esempio n. 9
0
class Query(graphene.ObjectType):
    plan = gql_optimizer.field(
        graphene.Field(PlanNode, id=graphene.ID(required=True)))
    all_plans = graphene.List(PlanNode)

    action = graphene.Field(ActionNode,
                            id=graphene.ID(),
                            identifier=graphene.ID(),
                            plan=graphene.ID())
    indicator = graphene.Field(IndicatorNode,
                               id=graphene.ID(),
                               identifier=graphene.ID(),
                               plan=graphene.ID())
    person = graphene.Field(PersonNode, id=graphene.ID(required=True))
    static_page = graphene.Field(StaticPageNode,
                                 plan=graphene.ID(),
                                 slug=graphene.ID())

    plan_actions = graphene.List(ActionNode,
                                 plan=graphene.ID(required=True),
                                 first=graphene.Int(),
                                 order_by=graphene.String())
    plan_categories = graphene.List(CategoryNode,
                                    plan=graphene.ID(required=True))
    plan_organizations = graphene.List(OrganizationNode,
                                       plan=graphene.ID(required=True))
    plan_indicators = graphene.List(
        IndicatorNode,
        plan=graphene.ID(required=True),
        first=graphene.Int(),
        order_by=graphene.String(),
        has_data=graphene.Boolean(),
        has_goals=graphene.Boolean(),
    )

    def resolve_plan(self, info, **kwargs):
        qs = Plan.objects.all()
        try:
            plan = gql_optimizer.query(qs, info).get(identifier=kwargs['id'])
        except Plan.DoesNotExist:
            return None
        return plan

    def resolve_all_plans(self, info):
        return Plan.objects.all()

    def resolve_plan_actions(self,
                             info,
                             plan,
                             first=None,
                             order_by=None,
                             **kwargs):
        qs = Action.objects.all()
        qs = qs.filter(plan__identifier=plan)
        qs = order_queryset(qs, ActionNode, order_by)
        if first is not None:
            qs = qs[0:first]

        return gql_optimizer.query(qs, info)

    def resolve_plan_categories(self, info, **kwargs):
        qs = Category.objects.all()
        plan = kwargs.get('plan')
        if plan is not None:
            qs = qs.filter(type__plan__identifier=plan)
        return gql_optimizer.query(qs, info)

    def resolve_plan_organizations(self, info, **kwargs):
        qs = Organization.objects.all()
        plan = kwargs.get('plan')
        if plan is not None:
            qs = qs.filter(
                responsible_actions__action__plan__identifier=plan).distinct()
        return gql_optimizer.query(qs, info)

    def resolve_plan_indicators(self,
                                info,
                                plan,
                                first=None,
                                order_by=None,
                                has_data=None,
                                has_goals=None,
                                **kwargs):
        qs = Indicator.objects.all()
        qs = qs.filter(levels__plan__identifier=plan).distinct()

        if has_data is not None:
            qs = qs.filter(latest_value__isnull=not has_data)

        if has_goals is not None:
            qs = qs.filter(goals__plan__identifier=plan).distinct()

        qs = order_queryset(qs, IndicatorNode, order_by)
        if first is not None:
            qs = qs[0:first]

        return gql_optimizer.query(qs, info)

    def resolve_action(self, info, **kwargs):
        obj_id = kwargs.get('id')
        identifier = kwargs.get('identifier')
        plan = kwargs.get('plan')
        if identifier and not plan:
            raise Exception(
                "You must supply the 'plan' argument when using 'identifier'")
        qs = Action.objects.all()
        if obj_id:
            qs = qs.filter(id=obj_id)
        if identifier:
            qs = qs.filter(identifier=identifier, plan__identifier=plan)

        qs = gql_optimizer.query(qs, info)

        try:
            obj = qs.get()
        except Action.DoesNotExist:
            return None

        return obj

    def resolve_person(self, info, **kwargs):
        qs = Person.objects.all()
        obj_id = kwargs.get('id')
        qs = qs.filter(id=obj_id)
        try:
            obj = qs.get()
        except Person.DoesNotExist:
            return None

        return obj

    def resolve_indicator(self, info, **kwargs):
        obj_id = kwargs.get('id')
        identifier = kwargs.get('identifier')
        plan = kwargs.get('plan')

        if not identifier and not obj_id:
            raise Exception("You must supply either 'id' or 'identifier'")

        qs = Indicator.objects.all()
        if obj_id:
            qs = qs.filter(id=obj_id)
        if plan:
            qs = qs.filter(levels__plan__identifier=plan).distinct()
        if identifier:
            qs = qs.filter(identifier=identifier)

        qs = gql_optimizer.query(qs, info)

        try:
            obj = qs.get()
        except Indicator.DoesNotExist:
            return None

        return obj

    def resolve_static_page(self, info, **kwargs):
        slug = kwargs.get('slug')
        plan = kwargs.get('plan')

        if not slug or not plan:
            raise Exception("You must supply both 'slug' and 'plan'")

        qs = StaticPage.objects.all()
        qs = qs.filter(slug=slug, plan__identifier=plan)
        qs = gql_optimizer.query(qs, info)

        try:
            obj = qs.get()
        except StaticPage.DoesNotExist:
            return None

        return obj
Esempio n. 10
0
class StaffCreateInput(StaffInput):
    send_password_email = graphene.Boolean(
        description="Send an email with a link to set a password")
Esempio n. 11
0
class BooleanBlock(graphene.ObjectType):
    value = graphene.Boolean(required=True)

    class Meta:
        interfaces = (StreamFieldInterface, )
Esempio n. 12
0
class UserCreateInput(CustomerInput):
    send_password_email = graphene.Boolean(
        description="Send an email with a link to set a password")
Esempio n. 13
0
class Query(graphene.ObjectType):
    # pyre-fixme[4]: Attribute must be annotated.
    node = relay.Node.Field()

    runs = relay.ConnectionField(RunConnection, )

    issues = relay.ConnectionField(
        IssueConnection,
        run_id=graphene.Int(required=True),
        codes=graphene.List(graphene.Int, default_value=["%"]),
        paths=graphene.List(graphene.String, default_value=["%"]),
        callables=MatchesIsField(),
        source_names=MatchesIsField(),
        source_kinds=MatchesIsField(),
        sink_names=MatchesIsField(),
        sink_kinds=MatchesIsField(),
        statuses=graphene.List(graphene.String, default_value=["%"]),
        features=graphene.List(FeatureCondition),
        min_trace_length_to_sinks=graphene.Int(),
        max_trace_length_to_sinks=graphene.Int(),
        min_trace_length_to_sources=graphene.Int(),
        max_trace_length_to_sources=graphene.Int(),
        issue_instance_id=graphene.Int(),
        is_new_issue=graphene.Boolean(),
    )

    trace = relay.ConnectionField(TraceFrameConnection,
                                  issue_instance_id=graphene.ID())
    initial_trace_frames = relay.ConnectionField(
        TraceFrameConnection,
        issue_instance_id=graphene.Int(),
        kind=graphene.String())
    next_trace_frames = relay.ConnectionField(
        TraceFrameConnection,
        issue_instance_id=graphene.Int(),
        frame_id=graphene.Int(),
        kind=graphene.String(),
    )

    # Typeahead data.
    codes = relay.ConnectionField(CodeConnection)
    paths = relay.ConnectionField(PathConnection)
    callables = relay.ConnectionField(CallableConnection)
    features = relay.ConnectionField(FeatureConnection)
    source_names = relay.ConnectionField(SourceNameConnection)
    source_kinds = relay.ConnectionField(SourceKindConnection)
    sink_names = relay.ConnectionField(SinkNameConnection)
    sink_kinds = relay.ConnectionField(SinkKindConnection)
    statuses = relay.ConnectionField(StatusConnection)

    file = relay.ConnectionField(FileConnection, path=graphene.String())

    filters = relay.ConnectionField(FilterConnection)

    def resolve_runs(self, info: ResolveInfo) -> List[run.Run]:
        session = get_session(info.context)
        return run.runs(session)

    def resolve_issues(
        self,
        info: ResolveInfo,
        run_id: int,
        codes: List[int],
        paths: List[str],
        statuses: List[str],
        callables: Optional[MatchesIsField] = None,
        features: Optional[List[FeatureCondition]] = None,
        min_trace_length_to_sinks: Optional[int] = None,
        max_trace_length_to_sinks: Optional[int] = None,
        min_trace_length_to_sources: Optional[int] = None,
        max_trace_length_to_sources: Optional[int] = None,
        issue_instance_id: Optional[int] = None,
        is_new_issue: Optional[bool] = None,
        source_names: Optional[MatchesIsField] = None,
        source_kinds: Optional[MatchesIsField] = None,
        sink_names: Optional[MatchesIsField] = None,
        sink_kinds: Optional[MatchesIsField] = None,
        **kwargs: Any,
    ) -> List[IssueQueryResult]:
        session = get_session(info.context)

        filter_instance = Filter.from_query(
            codes,
            paths,
            callables,
            statuses,
            source_names,
            source_kinds,
            sink_names,
            sink_kinds,
            features,
            min_trace_length_to_sinks,
            max_trace_length_to_sinks,
            min_trace_length_to_sources,
            max_trace_length_to_sources,
            is_new_issue,
        )

        issues = (Instance(session,
                           DBID(run_id)).where_filter(filter_instance).
                  where_issue_instance_id_is(issue_instance_id).get())

        return issues

    def resolve_initial_trace_frames(self, info: ResolveInfo,
                                     issue_instance_id: int,
                                     kind: str) -> List[TraceFrameQueryResult]:
        session = info.context.get("session")
        return trace.initial_frames(session, DBID(issue_instance_id),
                                    TraceKind.create_from_string(kind))

    def resolve_next_trace_frames(self, info: ResolveInfo,
                                  issue_instance_id: int, frame_id: int,
                                  kind: str) -> List[TraceFrameQueryResult]:
        session = info.context.get("session")

        trace_kind = TraceKind.create_from_string(kind)
        if trace_kind == TraceKind.POSTCONDITION:
            leaf_kind = issues.sources(session, DBID(issue_instance_id))
        elif trace_kind == TraceKind.PRECONDITION:
            leaf_kind = issues.sinks(session, DBID(issue_instance_id))

        trace_frame = session.query(TraceFrame).get(frame_id)
        if trace_frame is None:
            raise ValueError(f"`{frame_id}` is not a valid trace frame id")

        return trace.next_frames(
            session,
            trace_frame,
            # pyre-fixme[61]: `leaf_kind` may not be initialized here.
            leaf_kind,
            visited_ids=set(),
        )

    def resolve_codes(self, info: ResolveInfo) -> List[typeahead.Code]:
        session = info.context["session"]
        return typeahead.all_codes(session)

    def resolve_paths(self, info: ResolveInfo) -> List[typeahead.Path]:
        session = info.context["session"]
        return typeahead.all_paths(session)

    def resolve_callables(self, info: ResolveInfo) -> List[typeahead.Callable]:
        session = info.context["session"]
        return typeahead.all_callables(session)

    def resolve_source_names(self,
                             info: ResolveInfo) -> List[typeahead.SourceName]:
        session = info.context["session"]
        return typeahead.all_source_names(session)

    def resolve_source_kinds(self,
                             info: ResolveInfo) -> List[typeahead.SourceName]:
        session = info.context["session"]
        return typeahead.all_source_kinds(session)

    def resolve_sink_names(self,
                           info: ResolveInfo) -> List[typeahead.SourceName]:
        session = info.context["session"]
        return typeahead.all_sink_names(session)

    def resolve_sink_kinds(self,
                           info: ResolveInfo) -> List[typeahead.SourceName]:
        session = info.context["session"]
        return typeahead.all_sink_kinds(session)

    def resolve_statuses(self, info: ResolveInfo) -> List[typeahead.Status]:
        session = info.context["session"]
        return typeahead.all_statuses(session)

    def resolve_features(self, info: ResolveInfo) -> List[typeahead.Feature]:
        session = info.context["session"]
        return typeahead.all_features(session)

    def resolve_file(self, info: ResolveInfo, path: str,
                     **kwargs: Any) -> List[File]:
        if ".." in path:
            raise FileNotFoundError("Attempted directory traversal")

        source_directory = Path(
            info.context.get("source_directory") or os.getcwd())
        full_path = source_directory / path
        contents = full_path.read_text()

        editor_link = None
        editor_schema = info.context.get("editor_schema")
        if editor_schema is not None:
            editor_link = f"{editor_schema}//file/{str(full_path)}"

        return [File(path=path, contents=contents, editor_link=editor_link)]

    def resolve_filters(self,
                        info: ResolveInfo) -> List[filters_module.Filter]:
        session = info.context["session"]
        return filters_module.all_filters(session)
Esempio n. 14
0
class Order(MetadataObjectType, CountableDjangoObjectType):
    fulfillments = gql_optimizer.field(
        graphene.List(Fulfillment,
                      required=True,
                      description="List of shipments for the order."),
        model_field="fulfillments",
    )
    lines = gql_optimizer.field(
        graphene.List(lambda: OrderLine,
                      required=True,
                      description="List of order lines."),
        model_field="lines",
    )
    actions = graphene.List(
        OrderAction,
        description=
        ("List of actions that can be performed in the current state of an order."
         ),
        required=True,
    )
    available_shipping_methods = graphene.List(
        ShippingMethod,
        required=False,
        description="Shipping methods that can be used with this order.",
    )
    number = graphene.String(description="User-friendly number of an order.")
    is_paid = graphene.Boolean(
        description="Informs if an order is fully paid.")
    payment_status = PaymentChargeStatusEnum(
        description="Internal payment status.")
    payment_status_display = graphene.String(
        description="User-friendly payment status.")
    payments = gql_optimizer.field(
        graphene.List(Payment, description="List of payments for the order."),
        model_field="payments",
    )
    total = graphene.Field(TaxedMoney,
                           description="Total amount of the order.")
    shipping_price = graphene.Field(TaxedMoney,
                                    description="Total price of shipping.")
    subtotal = graphene.Field(
        TaxedMoney,
        description="The sum of line prices not including shipping.")
    gift_cards = gql_optimizer.field(
        graphene.List(GiftCard, description="List of user gift cards."),
        model_field="gift_cards",
    )
    status_display = graphene.String(description="User-friendly order status.")
    can_finalize = graphene.Boolean(
        description=("Informs whether a draft order can be finalized"
                     "(turned into a regular order)."),
        required=True,
    )
    total_authorized = graphene.Field(
        Money, description="Amount authorized for the order.")
    total_captured = graphene.Field(Money,
                                    description="Amount captured by payment.")
    events = gql_optimizer.field(
        graphene.List(OrderEvent,
                      description="List of events associated with the order."),
        model_field="events",
    )
    total_balance = graphene.Field(
        Money,
        description=
        "The difference between the paid and the order total amount.",
        required=True,
    )
    user_email = graphene.String(required=False,
                                 description="Email address of the customer.")
    is_shipping_required = graphene.Boolean(
        description="Returns True, if order requires shipping.", required=True)

    class Meta:
        description = "Represents an order in the shop."
        interfaces = [relay.Node]
        model = models.Order
        only_fields = [
            "billing_address",
            "created",
            "customer_note",
            "discount",
            "discount_name",
            "display_gross_prices",
            "gift_cards",
            "id",
            "language_code",
            "shipping_address",
            "shipping_method",
            "shipping_method_name",
            "shipping_price",
            "status",
            "token",
            "tracking_client_id",
            "translated_discount_name",
            "user",
            "voucher",
            "weight",
        ]

    @staticmethod
    def resolve_shipping_price(root: models.Order, _info):
        return root.shipping_price

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="payments__transactions")
    def resolve_actions(root: models.Order, _info):
        actions = []
        payment = root.get_last_payment()
        if root.can_capture(payment):
            actions.append(OrderAction.CAPTURE)
        if root.can_mark_as_paid():
            actions.append(OrderAction.MARK_AS_PAID)
        if root.can_refund(payment):
            actions.append(OrderAction.REFUND)
        if root.can_void(payment):
            actions.append(OrderAction.VOID)
        return actions

    @staticmethod
    def resolve_subtotal(root: models.Order, _info):
        return root.get_subtotal()

    @staticmethod
    def resolve_total(root: models.Order, _info):
        return root.total

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="payments__transactions")
    def resolve_total_authorized(root: models.Order, _info):
        # FIXME adjust to multiple payments in the future
        return root.total_authorized

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="payments")
    def resolve_total_captured(root: models.Order, _info):
        # FIXME adjust to multiple payments in the future
        return root.total_captured

    @staticmethod
    def resolve_total_balance(root: models.Order, _info):
        return root.total_balance

    @staticmethod
    def resolve_fulfillments(root: models.Order, info):
        user = info.context.user
        if user.is_staff:
            qs = root.fulfillments.all()
        else:
            qs = root.fulfillments.exclude(status=FulfillmentStatus.CANCELED)
        return qs.order_by("pk")

    @staticmethod
    def resolve_lines(root: models.Order, _info):
        return root.lines.all().order_by("pk")

    @staticmethod
    def resolve_events(root: models.Order, _info):
        return root.events.all().order_by("pk")

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="payments")
    def resolve_is_paid(root: models.Order, _info):
        return root.is_fully_paid()

    @staticmethod
    def resolve_number(root: models.Order, _info):
        return str(root.pk)

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="payments")
    def resolve_payment_status(root: models.Order, _info):
        return root.get_payment_status()

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="payments")
    def resolve_payment_status_display(root: models.Order, _info):
        return root.get_payment_status_display()

    @staticmethod
    def resolve_payments(root: models.Order, _info):
        return root.payments.all()

    @staticmethod
    def resolve_status_display(root: models.Order, _info):
        return root.get_status_display()

    @staticmethod
    def resolve_can_finalize(root: models.Order, _info):
        try:
            validate_draft_order(root)
        except ValidationError:
            return False
        return True

    @staticmethod
    @gql_optimizer.resolver_hints(select_related="user")
    def resolve_user_email(root: models.Order, _info):
        return root.get_customer_email()

    @staticmethod
    def resolve_available_shipping_methods(root: models.Order, _info):
        available = get_valid_shipping_methods_for_order(root)
        if available is None:
            return []

        manager = get_extensions_manager()
        display_gross = display_gross_prices()
        for shipping_method in available:
            # Ignore typing check because it is checked in
            # get_valid_shipping_methods_for_order
            taxed_price = manager.apply_taxes_to_shipping(
                shipping_method.price,
                root.shipping_address  # type: ignore
            )
            if display_gross:
                shipping_method.price = taxed_price.gross
            else:
                shipping_method.price = taxed_price.net
        return available

    @staticmethod
    def resolve_is_shipping_required(root: models.Order, _info):
        return root.is_shipping_required()

    @staticmethod
    def resolve_gift_cards(root: models.Order, _info):
        return root.gift_cards.all()

    @staticmethod
    @permission_required(OrderPermissions.MANAGE_ORDERS)
    def resolve_private_meta(root: models.Order, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root: models.Order, _info):
        return resolve_meta(root, _info)
Esempio n. 15
0
class LegalContents(graphene.ObjectType):
    __doc__ = docs.LegalContents.__doc__
    legal_notice = graphene.String(lang=graphene.String(),
                                   description=docs.LegalContents.legal_notice)
    terms_and_conditions = graphene.String(
        lang=graphene.String(),
        description=docs.LegalContents.terms_and_conditions)
    legal_notice_entries = graphene.List(
        LangStringEntry, description=docs.LegalContents.legal_notice_entries)
    terms_and_conditions_entries = graphene.List(
        LangStringEntry,
        description=docs.LegalContents.terms_and_conditions_entries)
    cookies_policy = graphene.String(
        lang=graphene.String(), description=docs.LegalContents.cookies_policy)
    privacy_policy = graphene.String(
        lang=graphene.String(), description=docs.LegalContents.privacy_policy)
    cookies_policy_entries = graphene.List(
        LangStringEntry, description=docs.LegalContents.cookies_policy_entries)
    privacy_policy_entries = graphene.List(
        LangStringEntry, description=docs.LegalContents.privacy_policy_entries)
    user_guidelines = graphene.String(
        lang=graphene.String(), description=docs.LegalContents.user_guidelines)
    user_guidelines_entries = graphene.List(
        LangStringEntry,
        description=docs.LegalContents.user_guidelines_entries)
    legal_notice_attachments = graphene.List(
        Attachment, description=docs.LegalContents.legal_notice_attachments)
    terms_and_conditions_attachments = graphene.List(
        Attachment,
        description=docs.LegalContents.terms_and_conditions_attachments)
    cookies_policy_attachments = graphene.List(
        Attachment, description=docs.LegalContents.cookies_policy_attachments)
    privacy_policy_attachments = graphene.List(
        Attachment, description=docs.LegalContents.privacy_policy_attachments)
    user_guidelines_attachments = graphene.List(
        Attachment, description=docs.LegalContents.user_guidelines_attachments)
    mandatory_legal_contents_validation = graphene.Boolean(
        required=True,
        description=docs.LegalContents.mandatory_legal_contents_validation)

    def resolve_legal_notice(self, args, context, info):
        """Legal notice value in given locale."""
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return resolve_langstring(discussion.legal_notice, args.get('lang'))

    def resolve_terms_and_conditions(self, args, context, info):
        """Terms and conditions value in given locale."""
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return resolve_langstring(discussion.terms_and_conditions,
                                  args.get('lang'))

    def resolve_legal_notice_entries(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        if discussion.legal_notice:
            return resolve_langstring_entries(discussion, 'legal_notice')

        return []

    def resolve_terms_and_conditions_entries(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        if discussion.terms_and_conditions:
            return resolve_langstring_entries(discussion,
                                              'terms_and_conditions')

        return []

    def resolve_cookies_policy(self, args, context, info):
        """Cookies policy value in given locale."""
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return resolve_langstring(discussion.cookies_policy, args.get('lang'))

    def resolve_privacy_policy(self, args, context, info):
        """Privacy policy value in given locale."""
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return resolve_langstring(discussion.privacy_policy, args.get('lang'))

    def resolve_cookies_policy_entries(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        if discussion.cookies_policy:
            return resolve_langstring_entries(discussion, 'cookies_policy')

        return []

    def resolve_privacy_policy_entries(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        if discussion.privacy_policy:
            return resolve_langstring_entries(discussion, 'privacy_policy')

        return []

    def resolve_user_guidelines(self, args, context, info):
        """User guidelines value in given locale."""
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return resolve_langstring(discussion.user_guidelines, args.get('lang'))

    def resolve_user_guidelines_entries(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        if discussion.user_guidelines:
            return resolve_langstring_entries(discussion, 'user_guidelines')

        return []

    def resolve_legal_notice_attachments(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return get_attachments_with_purpose(
            discussion.attachments,
            models.AttachmentPurpose.LEGAL_NOTICE_ATTACHMENT.value)

    def resolve_terms_and_conditions_attachments(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return get_attachments_with_purpose(
            discussion.attachments,
            models.AttachmentPurpose.TERMS_AND_CONDITIONS_ATTACHMENT.value)

    def resolve_cookies_policy_attachments(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return get_attachments_with_purpose(
            discussion.attachments,
            models.AttachmentPurpose.COOKIES_POLICY_ATTACHMENT.value)

    def resolve_privacy_policy_attachments(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return get_attachments_with_purpose(
            discussion.attachments,
            models.AttachmentPurpose.PRIVACY_POLICY_ATTACHMENT.value)

    def resolve_user_guidelines_attachments(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return get_attachments_with_purpose(
            discussion.attachments,
            models.AttachmentPurpose.USER_GUIDELINES_ATTACHMENT.value)

    def resolve_mandatory_legal_contents_validation(self, args, context, info):
        discussion_id = context.matchdict['discussion_id']
        discussion = models.Discussion.get(discussion_id)
        return discussion.preferences['mandatory_legal_contents_validation']
Esempio n. 16
0
 class Arguments:
     note_id = graphene.UUID(required=True, name='id')
     ultimate = graphene.Boolean(name='ultimate')
Esempio n. 17
0
 class Arguments:
     follow_request_id = graphene.String(
         required=True, description="Follow request identifier")
     approved = graphene.Boolean(description="Approve or reject follow")
Esempio n. 18
0
class Product(CountableDjangoObjectType):
    url = graphene.String(
        description="The storefront URL for the product.", required=True
    )
    thumbnail_url = graphene.String(
        description="The URL of a main thumbnail for a product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail"),
        deprecation_reason=(
            """thumbnailUrl is deprecated, use
         thumbnail instead"""
        ),
    )
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for a product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail"),
    )
    availability = graphene.Field(
        ProductPricingInfo,
        description="""Informs about product's availability in the
               storefront, current price and discounts.""",
        deprecation_reason="Has been renamed to 'pricing'.",
    )
    pricing = graphene.Field(
        ProductPricingInfo,
        description="""Lists the storefront product's pricing,
            the current price and discounts, only meant for displaying.""",
    )
    is_available = graphene.Boolean(
        description="Whether the product is in stock and visible or not."
    )
    base_price = graphene.Field(Money, description="The product's default base price.")
    price = graphene.Field(
        Money,
        description="The product's default base price.",
        deprecation_reason=("Has been replaced by 'basePrice'"),
    )
    tax_rate = TaxRateType(
        description="A type of tax rate.",
        deprecation_reason=(
            "taxRate is deprecated. Use taxType to obtain taxCode for given tax gateway"
        ),
    )

    tax_type = graphene.Field(
        TaxType, description="A type of tax. Assigned by enabled tax gateway"
    )
    attributes = graphene.List(
        graphene.NonNull(SelectedAttribute),
        required=True,
        description="List of attributes assigned to this product.",
    )
    purchase_cost = graphene.Field(MoneyRange)
    margin = graphene.Field(Margin)
    image_by_id = graphene.Field(
        lambda: ProductImage,
        id=graphene.Argument(graphene.ID, description="ID of a product image."),
        description="Get a single product image by ID",
    )
    variants = gql_optimizer.field(
        graphene.List(ProductVariant, description="List of variants for the product"),
        model_field="variants",
    )
    images = gql_optimizer.field(
        graphene.List(
            lambda: ProductImage, description="List of images for the product"
        ),
        model_field="images",
    )
    collections = gql_optimizer.field(
        graphene.List(
            lambda: Collection, description="List of collections for the product"
        ),
        model_field="collections",
    )
    available_on = graphene.Date(
        deprecation_reason=("availableOn is deprecated, use publicationDate instead")
    )
    translation = graphene.Field(
        ProductTranslation,
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
            required=True,
        ),
        description=("Returns translated Product fields for the given language code."),
        resolver=resolve_translation,
    )

    class Meta:
        description = """Represents an individual item for sale in the
        storefront."""
        interfaces = [relay.Node]
        model = models.Product
        only_fields = [
            "category",
            "charge_taxes",
            "description",
            "description_json",
            "id",
            "is_published",
            "name",
            "product_type",
            "publication_date",
            "seo_description",
            "seo_title",
            "updated_at",
            "weight",
        ]

    @staticmethod
    def resolve_tax_rate(root: models.Product, _info, **_kwargs):
        # FIXME this resolver should be dropped after we drop tax_rate from API
        tax_rate = vatlayer_interface.get_tax_from_object_meta(root).code
        return tax_rate or None

    @staticmethod
    def resolve_tax_type(root: models.Product, _info):
        tax_data = tax_interface.get_tax_from_object_meta(root)
        return TaxType(tax_code=tax_data.code, description=tax_data.description)

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="images")
    def resolve_thumbnail_url(root: models.Product, info, *, size=None):
        if not size:
            size = 255
        url = get_product_image_thumbnail(
            root.get_first_image(), size, method="thumbnail"
        )
        return info.context.build_absolute_uri(url)

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="images")
    def resolve_thumbnail(root: models.Product, info, *, size=None):
        image = root.get_first_image()
        if not size:
            size = 255
        url = get_product_image_thumbnail(image, size, method="thumbnail")
        url = info.context.build_absolute_uri(url)
        alt = image.alt if image else None
        return Image(alt=alt, url=url)

    @staticmethod
    def resolve_url(root: models.Product, *_args):
        return root.get_absolute_url()

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("variants", "collections"),
        only=["publication_date", "charge_taxes", "price", "meta"],
    )
    def resolve_pricing(root: models.Product, info):
        context = info.context
        availability = get_product_availability(
            root, context.discounts, context.country, context.currency, context.taxes
        )
        return ProductPricingInfo(**availability._asdict())

    resolve_availability = resolve_pricing

    @staticmethod
    def resolve_is_available(root: models.Product, _info):
        return root.is_available

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_base_price(root: models.Product, _info):
        return root.price

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("variants", "collections"),
        only=["publication_date", "charge_taxes", "price", "meta"],
    )
    def resolve_price(root: models.Product, info):
        price_range = root.get_price_range(info.context.discounts)
        price = tax_interface.apply_taxes_to_product(
            root, price_range.start, info.context.country, taxes=info.context.taxes
        )
        return price.net

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related="product_type__product_attributes__values"
    )
    def resolve_attributes(root: models.Product, *_args):
        attributes_qs = root.product_type.product_attributes.all()
        return resolve_attribute_list(root.attributes, attributes_qs)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_purchase_cost(root: models.Product, *_args):
        purchase_cost, _ = get_product_costs_data(root)
        return purchase_cost

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_margin(root: models.Product, *_args):
        _, margin = get_product_costs_data(root)
        return Margin(margin[0], margin[1])

    @staticmethod
    def resolve_image_by_id(root: models.Product, info, id):
        pk = get_database_id(info, id, ProductImage)
        try:
            return root.images.get(pk=pk)
        except models.ProductImage.DoesNotExist:
            raise GraphQLError("Product image not found.")

    @staticmethod
    @gql_optimizer.resolver_hints(model_field="images")
    def resolve_images(root: models.Product, *_args, **_kwargs):
        return root.images.all()

    @staticmethod
    def resolve_variants(root: models.Product, *_args, **_kwargs):
        return root.variants.all()

    @staticmethod
    def resolve_collections(root: models.Product, *_args):
        return root.collections.all()

    @staticmethod
    def resolve_available_on(root: models.Product, *_args):
        return root.publication_date

    @classmethod
    def get_node(cls, info, pk):
        if info.context:
            qs = cls._meta.model.objects.visible_to_user(info.context.user)
            return cls.maybe_optimize(info, qs, pk)
        return None
Esempio n. 19
0
 class Arguments:
     identifier = graphene.String(required=False)
     service = graphene.String(required=True)
     spf_identifier = graphene.String(required=False)
     share_spf = graphene.Boolean(required=True)
Esempio n. 20
0
class Query(graphene.ObjectType):
    offers = graphene.List(of_type=GraphQL_offer)

    users = graphene.List(of_type=GraphQL_user)

    # API rewrite methods
    user = graphene.Field(GraphQL_user,
                          userID=graphene.String(default_value="none"))

    offer = graphene.Field(GraphQL_offer,
                           offerID=graphene.Int(default_value=-1))

    mineCoinCoins = graphene.Field(
        GraphQL_user, userID=graphene.String(default_value="none"))

    transaction = graphene.Boolean(offerID=graphene.Int(),
                                   userID=graphene.String())

    cancelOffer = graphene.Boolean(offerID=graphene.Int())

    # API Rewrite Methods

    def resolve_mineCoinCoins(self, info, userID):
        user = User.query.filter_by(userID=userID).first()
        newCoinVal = user.coin_val + 1
        user.coin_val = newCoinVal
        db.session.commit()
        return GraphQL_user(userID=user.userID,
                            displayName=user.display_name,
                            email=user.email,
                            coinVal=user.coin_val)

    def resolve_transaction(self, info, offerID, userID):
        offer = Offer.query.filter_by(offerID=offerID).first()
        user = User.query.filter_by(userID=userID).first()
        coinCoins = offer.coinCoinOffer
        currentCoinVal = user.coin_val
        user.coin_val = currentCoinVal + coinCoins
        db.session.delete(offer)
        db.session.commit()
        return True

    def resolve_cancelOffer(self, info, offerID):
        offer = Offer.query.filter_by(offerID=offerID).first()
        db.session.delete(offer)
        db.session.commit()
        return True

    def resolve_offer(self, info, offerID):
        offer = Offer.query.filter_by(offerID=offerID).first()
        return GraphQL_offer(offerID=offer.offerID,
                             USD_Offer=offer.USDOffer,
                             coin_Offer=offer.coinCoinOffer,
                             userID=offer.userID,
                             displayName=offer.display_name)

    def resolve_offers(self, info):
        offers_query = Offer.query.all()
        if offers_query is not None:
            offers = [
                GraphQL_offer(offerID=offer.offerID,
                              USD_Offer=offer.USDOffer,
                              coin_Offer=offer.coinCoinOffer,
                              userID=offer.userID,
                              displayName=offer.display_name)
                for offer in offers_query
            ]
        else:
            offers = []
        return offers

    def resolve_user(self, info, userID):
        user = User.query.filter_by(userID=userID).first()
        if user is not None:
            offers_query = Offer.query.filter_by(userID=userID).all()
            if offers_query is not None:
                offers = [
                    GraphQL_offer(offerID=offer.offerID,
                                  USD_Offer=offer.USDOffer,
                                  coin_Offer=offer.coinCoinOffer,
                                  userID=offer.userID,
                                  displayName=offer.display_name)
                    for offer in offers_query
                ]
            else:
                offers = []
            return GraphQL_user(userID=user.userID,
                                displayName=user.display_name,
                                email=user.email,
                                coinVal=user.coin_val,
                                offers=offers)
        else:
            return {}

    # i am so proud of this function like im a genius
    def resolve_users(self, info):
        users_query = db.session.query(User, Offer).outerjoin(Offer).all()
        if users_query is not None:
            users = [
                GraphQL_user(userID=join[0].userID,
                             displayName=join[0].display_name,
                             email=join[0].email,
                             coinVal=join[0].coin_val,
                             offers=[
                                 GraphQL_offer(offerID=offer.offerID,
                                               USD_Offer=offer.USDOffer,
                                               coin_Offer=offer.coinCoinOffer,
                                               userID=offer.userID,
                                               displayName=offer.display_name)
                                 for offer in join if type(offer) is Offer
                             ]) for join in users_query
            ]
        else:
            users = []
        return users
class FoodType(DjangoObjectType):
    total_products = graphene.Int()
    url = graphene.String()
    in_used_by_store = graphene.Boolean()
    class Meta:
        model = Type
Esempio n. 22
0
class Checkout(MetadataObjectType, CountableDjangoObjectType):
    available_shipping_methods = graphene.List(
        ShippingMethod,
        required=True,
        description="Shipping methods that can be used with this order.",
    )
    available_payment_gateways = graphene.List(
        PaymentGateway,
        description="List of available payment gateways.",
        required=True)
    email = graphene.String(description="Email of a customer.", required=True)
    gift_cards = gql_optimizer.field(
        graphene.List(
            GiftCard,
            description="List of gift cards associated with this checkout."),
        model_field="gift_cards",
    )
    is_shipping_required = graphene.Boolean(
        description="Returns True, if checkout requires shipping.",
        required=True)
    lines = gql_optimizer.field(
        graphene.List(
            CheckoutLine,
            description=(
                "A list of checkout lines, each containing information about "
                "an item in the checkout."),
        ),
        model_field="lines",
    )
    shipping_price = graphene.Field(
        TaxedMoney,
        description="The price of the shipping, with all the taxes included.",
    )
    subtotal_price = graphene.Field(
        TaxedMoney,
        description=
        "The price of the checkout before shipping, with taxes included.",
    )
    total_price = graphene.Field(
        TaxedMoney,
        description=(
            "The sum of the the checkout line prices, with all the taxes,"
            "shipping costs, and discounts included."),
    )

    class Meta:
        only_fields = [
            "billing_address",
            "created",
            "discount_name",
            "gift_cards",
            "is_shipping_required",
            "last_change",
            "note",
            "quantity",
            "shipping_address",
            "shipping_method",
            "token",
            "translated_discount_name",
            "user",
            "voucher_code",
            "discount",
        ]
        description = "Checkout object."
        model = models.Checkout
        interfaces = [graphene.relay.Node]
        filter_fields = ["token"]

    @staticmethod
    def resolve_email(root: models.Checkout, info):
        return root.get_customer_email()

    @staticmethod
    def resolve_total_price(root: models.Checkout, info):
        taxed_total = (calculations.checkout_total(
            checkout=root, discounts=info.context.discounts) -
                       root.get_total_gift_cards_balance())
        return max(taxed_total, zero_taxed_money())

    @staticmethod
    def resolve_subtotal_price(root: models.Checkout, info):
        return calculations.checkout_subtotal(checkout=root,
                                              discounts=info.context.discounts)

    @staticmethod
    def resolve_shipping_price(root: models.Checkout, info):
        return calculations.checkout_shipping_price(
            checkout=root, discounts=info.context.discounts)

    @staticmethod
    def resolve_lines(root: models.Checkout, *_args):
        return root.lines.prefetch_related("variant")

    @staticmethod
    def resolve_available_shipping_methods(root: models.Checkout, info):
        available = get_valid_shipping_methods_for_checkout(
            root, info.context.discounts)
        if available is None:
            return []

        manager = get_extensions_manager()
        display_gross = display_gross_prices()
        for shipping_method in available:
            # ignore mypy checking because it is checked in
            # get_valid_shipping_methods_for_checkout
            taxed_price = manager.apply_taxes_to_shipping(
                shipping_method.price,
                root.shipping_address  # type: ignore
            )
            if display_gross:
                shipping_method.price = taxed_price.gross
            else:
                shipping_method.price = taxed_price.net
        return available

    @staticmethod
    def resolve_available_payment_gateways(_: models.Checkout, _info):
        return [
            gtw for gtw in get_extensions_manager().list_payment_gateways()
        ]

    @staticmethod
    def resolve_gift_cards(root: models.Checkout, _info):
        return root.gift_cards.all()

    @staticmethod
    def resolve_is_shipping_required(root: models.Checkout, _info):
        return root.is_shipping_required()

    @staticmethod
    @permission_required(OrderPermissions.MANAGE_ORDERS)
    def resolve_private_meta(root: models.Checkout, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root: models.Checkout, _info):
        return resolve_meta(root, _info)
class SpaceContract(graphene.Mutation):
    """
    Mutation to Space Contract
    """
    class Arguments:
        startDate = graphene.String(required=True)
        endDate = graphene.String(required=True)
        spaceId = graphene.String(required=True)
        order = graphene.List(graphene.String)

    success = graphene.Boolean()
    errors = graphene.List(ErrorsType)
    space = graphene.Field(SpaceType)
    contract_spaces = DjangoFilterConnectionField(SpaceType, )

    @staticmethod
    def mutate(_, info, **kwargs):
        try:
            start_date = string_to_date(kwargs.get('startDate'))
            end_date = string_to_date(kwargs.get('endDate'))
            space_id = kwargs.get('spaceId')
            token = get_auth_token(info.context)

            account_token = AccountToken.get_account({'token': token})
            if account_token is None:
                return SpaceContract(
                    success=False,
                    errors=[ErrorsType(field='token', message='トークンが無効です。')])

            if account_token.expire < datetime.now():
                account_token.delete()
                return SpaceContract(
                    success=False,
                    errors=[ErrorsType(field='expired', message='期限切れです。')])

            space = Space.get_empty_space_by_id(space_id)
            if space is None:
                return SpaceContract(
                    success=False,
                    errors=[ErrorsType(field='space', message='既に契約してます。')])

            space.contract_status = True
            space.contract_start = start_date
            space.contract_end = end_date
            space.account = account_token.account
            space.save()

            order = kwargs.get('order')

            if order is None:
                order = ['-created_date']

            contract_spaces = Space.get_spaces({
                'account':
                account_token.account,
                'contract_end__gte':
                datetime.now(),
            }).order_by(*order)

            return SpaceContract(
                success=True,
                space=space,
                contract_spaces=contract_spaces,
            )

        except Exception as e:

            return SpaceContract(
                success=False,
                errors=[ErrorsType(field='exception', message=str(e))])
Esempio n. 24
0
class ProductVariant(CountableDjangoObjectType, MetadataObjectType):
    stock_quantity = graphene.Int(
        required=True, description="Quantity of a product available for sale.")
    price_override = graphene.Field(
        Money,
        description=
        ("Override the base price of a product if necessary. A value of `null` "
         "indicates that the default product price is used."),
    )
    price = graphene.Field(
        Money,
        description="Price of the product variant.",
        deprecation_reason=(
            "DEPRECATED: Will be removed in Saleor 2.10, "
            "has been replaced by 'pricing.priceUndiscounted'"),
    )
    availability = graphene.Field(
        VariantPricingInfo,
        description=
        ("Informs about variant's availability in the storefront, current price and "
         "discounted price."),
        deprecation_reason=
        ("DEPRECATED: Will be removed in Saleor 2.10, has been renamed to `pricing`."
         ),
    )
    pricing = graphene.Field(
        VariantPricingInfo,
        description=
        ("Lists the storefront variant's pricing, the current price and discounts, "
         "only meant for displaying."),
    )
    is_available = graphene.Boolean(
        description="Whether the variant is in stock and visible or not.")
    attributes = gql_optimizer.field(
        graphene.List(
            graphene.NonNull(SelectedAttribute),
            required=True,
            description="List of attributes assigned to this variant.",
        ))
    cost_price = graphene.Field(Money,
                                description="Cost price of the variant.")
    margin = graphene.Int(description="Gross margin percentage value.")
    quantity_ordered = graphene.Int(description="Total quantity ordered.")
    revenue = graphene.Field(
        TaxedMoney,
        period=graphene.Argument(ReportingPeriod),
        description=
        ("Total revenue generated by a variant in given period of time. Note: this "
         "field should be queried using `reportProductSales` query as it uses "
         "optimizations suitable for such calculations."),
    )
    images = gql_optimizer.field(
        graphene.List(lambda: ProductImage,
                      description="List of images for the product variant."),
        model_field="images",
    )
    translation = graphene.Field(
        ProductVariantTranslation,
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
            required=True,
        ),
        description=("Returns translated Product Variant fields "
                     "for the given language code."),
        resolver=resolve_translation,
    )
    digital_content = gql_optimizer.field(
        graphene.Field(DigitalContent,
                       description="Digital content for the product variant."),
        model_field="digital_content",
    )

    class Meta:
        description = (
            "Represents a version of a product such as different size or color."
        )
        only_fields = [
            "id",
            "name",
            "product",
            "quantity",
            "quantity_allocated",
            "sku",
            "track_inventory",
            "weight",
        ]
        interfaces = [relay.Node]
        model = models.ProductVariant

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_digital_content(root: models.ProductVariant, *_args):
        return getattr(root, "digital_content", None)

    @staticmethod
    def resolve_stock_quantity(root: models.ProductVariant, *_args):
        return root.quantity_available

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related=[
        "attributes__values", "attributes__assignment__attribute"
    ])
    def resolve_attributes(root: models.ProductVariant, info):
        return resolve_attribute_list(root, user=info.context.user)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_margin(root: models.ProductVariant, *_args):
        return get_margin_for_variant(root)

    @staticmethod
    def resolve_price(root: models.ProductVariant, *_args):
        return (root.price_override
                if root.price_override is not None else root.product.price)

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related=("product", ),
                                  only=["price_override_amount", "currency"])
    def resolve_pricing(root: models.ProductVariant, info):
        context = info.context
        availability = get_variant_availability(
            root,
            context.discounts,
            context.country,
            context.currency,
            extensions=context.extensions,
        )
        return VariantPricingInfo(**availability._asdict())

    resolve_availability = resolve_pricing

    @staticmethod
    def resolve_is_available(root: models.ProductVariant, _info):
        return root.is_available

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_price_override(root: models.ProductVariant, *_args):
        return root.price_override

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_quantity(root: models.ProductVariant, *_args):
        return root.quantity

    @staticmethod
    @permission_required(["order.manage_orders", "product.manage_products"])
    def resolve_quantity_ordered(root: models.ProductVariant, *_args):
        # This field is added through annotation when using the
        # `resolve_report_product_sales` resolver.
        return getattr(root, "quantity_ordered", None)

    @staticmethod
    @permission_required(["order.manage_orders", "product.manage_products"])
    def resolve_quantity_allocated(root: models.ProductVariant, *_args):
        return root.quantity_allocated

    @staticmethod
    @permission_required(["order.manage_orders", "product.manage_products"])
    def resolve_revenue(root: models.ProductVariant, *_args, period):
        start_date = reporting_period_to_date(period)
        return calculate_revenue_for_variant(root, start_date)

    @staticmethod
    def resolve_images(root: models.ProductVariant, *_args):
        return root.images.all()

    @classmethod
    def get_node(cls, info, id):
        user = info.context.user
        visible_products = models.Product.objects.visible_to_user(
            user).values_list("pk", flat=True)
        qs = cls._meta.model.objects.filter(product__id__in=visible_products)
        return cls.maybe_optimize(info, qs, id)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_private_meta(root, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root, _info):
        return resolve_meta(root, _info)
class LabbookFile(graphene.ObjectType,
                  interfaces=(graphene.relay.Node, GitRepository)):
    """A type representing a file or directory inside the labbook file system."""
    # Loaded file info
    _file_info = None

    # Section in the LabBook (code, input, output)
    section = graphene.String(required=True)

    # Relative path from labbook section.
    key = graphene.String(required=True)

    # True indicates that path points to a directory
    is_dir = graphene.Boolean()

    # True indicates that path points to a favorite
    is_favorite = graphene.Boolean()

    # Modified at contains timestamp of last modified - NOT creation - in epoch time.
    modified_at = graphene.Int()

    # Size in bytes encoded as a string.
    size = graphene.String()

    def _load_file_info(self, dataloader):
        """Private method to retrieve file info for a given key"""
        if not self._file_info:
            # Load file info from LabBook
            if not self.section or not self.key:
                raise ValueError(
                    "Must set `section` and `key` on object creation to resolve file info"
                )

            # Load labbook instance
            lb = dataloader.load(
                f"{get_logged_in_username()}&{self.owner}&{self.name}").get()

            # Retrieve file info
            self._file_info = lb.get_file_info(self.section, self.key)

        # Set class properties
        self.is_dir = self._file_info['is_dir']
        self.modified_at = round(self._file_info['modified_at'])
        self.size = f"{self._file_info['size']}"
        self.is_favorite = self._file_info['is_favorite']

    @classmethod
    def get_node(cls, info, id):
        """Method to resolve the object based on it's Node ID"""
        # Parse the key
        owner, name, section, key = id.split("&")

        return LabbookFile(id=f"{owner}&{name}&{section}&{key}",
                           name=name,
                           owner=owner,
                           section=section,
                           key=key)

    def resolve_id(self, info):
        """Resolve the unique Node id for this object"""
        if not self.id:
            if not self.owner or not self.name or not self.section or not self.key:
                raise ValueError(
                    "Resolving a LabbookFile Node ID requires owner, name, section, and key to be set"
                )
            self.id = f"{self.owner}&{self.name}&{self.section}&{self.key}"

        return self.id

    def resolve_is_dir(self, info):
        """Resolve the is_dir field"""
        if self.is_dir is None:
            self._load_file_info(info.context.labbook_loader)
        return self.is_dir

    def resolve_modified_at(self, info):
        """Resolve the modified_at field"""
        if self.modified_at is None:
            self._load_file_info(info.context.labbook_loader)
        return self.modified_at

    def resolve_size(self, info):
        """Resolve the size field"""
        if self.size is None:
            self._load_file_info(info.context.labbook_loader)
        return self.size

    def resolve_is_favorite(self, info):
        """Resolve the is_favorite field"""
        if self.is_favorite is None:
            self._load_file_info(info.context.labbook_loader)
        return self.is_favorite
Esempio n. 26
0
class Product(CountableDjangoObjectType, MetadataObjectType):
    url = graphene.String(description="The storefront URL for the product.",
                          required=True)
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for a product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail."),
    )
    availability = graphene.Field(
        ProductPricingInfo,
        description=
        ("Informs about product's availability in the storefront, current price and "
         "discounts."),
        deprecation_reason=
        ("DEPRECATED: Will be removed in Saleor 2.10, Has been renamed to `pricing`."
         ),
    )
    pricing = graphene.Field(
        ProductPricingInfo,
        description=
        ("Lists the storefront product's pricing, the current price and discounts, "
         "only meant for displaying."),
    )
    is_available = graphene.Boolean(
        description="Whether the product is in stock and visible or not.")
    base_price = graphene.Field(
        Money, description="The product's default base price.")
    price = graphene.Field(
        Money,
        description="The product's default base price.",
        deprecation_reason=(
            "DEPRECATED: Will be removed in Saleor 2.10, has been replaced by "
            "`basePrice`"),
    )
    minimal_variant_price = graphene.Field(
        Money,
        description="The price of the cheapest variant (including discounts).")
    tax_type = graphene.Field(
        TaxType, description="A type of tax. Assigned by enabled tax gateway")
    attributes = graphene.List(
        graphene.NonNull(SelectedAttribute),
        required=True,
        description="List of attributes assigned to this product.",
    )
    purchase_cost = graphene.Field(MoneyRange)
    margin = graphene.Field(Margin)
    image_by_id = graphene.Field(
        lambda: ProductImage,
        id=graphene.Argument(graphene.ID,
                             description="ID of a product image."),
        description="Get a single product image by ID.",
    )
    variants = gql_optimizer.field(
        graphene.List(ProductVariant,
                      description="List of variants for the product."),
        model_field="variants",
    )
    images = gql_optimizer.field(
        graphene.List(lambda: ProductImage,
                      description="List of images for the product."),
        model_field="images",
    )
    collections = gql_optimizer.field(
        graphene.List(lambda: Collection,
                      description="List of collections for the product."),
        model_field="collections",
    )
    translation = graphene.Field(
        ProductTranslation,
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
            required=True,
        ),
        description=(
            "Returns translated Product fields for the given language code."),
        resolver=resolve_translation,
    )

    slug = graphene.String(required=True, description="The slug of a product.")

    class Meta:
        description = "Represents an individual item for sale in the storefront."
        interfaces = [relay.Node]
        model = models.Product
        only_fields = [
            "category",
            "charge_taxes",
            "description",
            "description_json",
            "id",
            "is_published",
            "name",
            "product_type",
            "publication_date",
            "seo_description",
            "seo_title",
            "updated_at",
            "weight",
        ]

    @staticmethod
    def resolve_tax_type(root: models.Product, info):
        tax_data = info.context.extensions.get_tax_code_from_object_meta(root)
        return TaxType(tax_code=tax_data.code,
                       description=tax_data.description)

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related="images")
    def resolve_thumbnail(root: models.Product, info, *, size=255):
        image = root.get_first_image()
        if image:
            url = get_product_image_thumbnail(image, size, method="thumbnail")
            alt = image.alt
            return Image(alt=alt, url=info.context.build_absolute_uri(url))
        return None

    @staticmethod
    def resolve_url(root: models.Product, *_args):
        return root.get_absolute_url()

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("variants", "collections"),
        only=[
            "publication_date", "charge_taxes", "price_amount", "currency",
            "meta"
        ],
    )
    def resolve_pricing(root: models.Product, info):
        context = info.context
        availability = get_product_availability(
            root,
            context.discounts,
            context.country,
            context.currency,
            context.extensions,
        )
        return ProductPricingInfo(**availability._asdict())

    resolve_availability = resolve_pricing

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related=("variants"))
    def resolve_is_available(root: models.Product, _info):
        return root.is_available

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_base_price(root: models.Product, _info):
        return root.price

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=("variants", "collections"),
        only=[
            "publication_date", "charge_taxes", "price_amount", "currency",
            "meta"
        ],
    )
    def resolve_price(root: models.Product, info):
        price_range = root.get_price_range(info.context.discounts)
        price = info.context.extensions.apply_taxes_to_product(
            root, price_range.start, info.context.country)
        return price.net

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related=[
        "product_type__attributeproduct__productassignments__values",
        "product_type__attributeproduct__attribute",
    ])
    def resolve_attributes(root: models.Product, info):
        return resolve_attribute_list(root, user=info.context.user)

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_purchase_cost(root: models.Product, *_args):
        purchase_cost, _ = get_product_costs_data(root)
        return purchase_cost

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_margin(root: models.Product, *_args):
        _, margin = get_product_costs_data(root)
        return Margin(margin[0], margin[1])

    @staticmethod
    def resolve_image_by_id(root: models.Product, info, id):
        pk = get_database_id(info, id, ProductImage)
        try:
            return root.images.get(pk=pk)
        except models.ProductImage.DoesNotExist:
            raise GraphQLError("Product image not found.")

    @staticmethod
    @gql_optimizer.resolver_hints(model_field="images")
    def resolve_images(root: models.Product, *_args, **_kwargs):
        return root.images.all()

    @staticmethod
    def resolve_variants(root: models.Product, *_args, **_kwargs):
        return root.variants.all()

    @staticmethod
    def resolve_collections(root: models.Product, *_args):
        return root.collections.all()

    @classmethod
    def get_node(cls, info, pk):
        if info.context:
            qs = cls._meta.model.objects.visible_to_user(info.context.user)
            return cls.maybe_optimize(info, qs, pk)
        return None

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_private_meta(root, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def resolve_slug(root: models.Product, *_args):
        return root.get_slug()
Esempio n. 27
0
class Product(CountableDjangoObjectType):
    url = graphene.String(
        description="The storefront URL for the product.",
        required=True,
        deprecation_reason="This field will be removed after 2020-07-31.",
    )
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for a product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail."),
    )
    pricing = graphene.Field(
        ProductPricingInfo,
        description=
        ("Lists the storefront product's pricing, the current price and discounts, "
         "only meant for displaying."),
    )
    is_available = graphene.Boolean(
        description="Whether the product is in stock and visible or not.")
    base_price = graphene.Field(
        Money, description="The product's default base price.")
    minimal_variant_price = graphene.Field(
        Money,
        description="The price of the cheapest variant (including discounts).")
    tax_type = graphene.Field(
        TaxType, description="A type of tax. Assigned by enabled tax gateway")
    attributes = graphene.List(
        graphene.NonNull(SelectedAttribute),
        required=True,
        description="List of attributes assigned to this product.",
    )
    purchase_cost = graphene.Field(MoneyRange)
    margin = graphene.Field(Margin)
    image_by_id = graphene.Field(
        lambda: ProductImage,
        id=graphene.Argument(graphene.ID,
                             description="ID of a product image."),
        description="Get a single product image by ID.",
    )
    variants = graphene.List(ProductVariant,
                             description="List of variants for the product.")
    images = graphene.List(lambda: ProductImage,
                           description="List of images for the product.")
    collections = graphene.List(
        lambda: Collection, description="List of collections for the product.")
    translation = TranslationField(ProductTranslation, type_name="product")

    class Meta:
        description = "Represents an individual item for sale in the storefront."
        interfaces = [relay.Node, ObjectWithMetadata]
        model = models.Product
        only_fields = [
            "category",
            "charge_taxes",
            "description",
            "description_json",
            "id",
            "is_published",
            "name",
            "slug",
            "product_type",
            "publication_date",
            "seo_description",
            "seo_title",
            "updated_at",
            "weight",
        ]

    @staticmethod
    def resolve_category(root: models.Product, info):
        category_id = root.category_id
        if category_id is None:
            return None

        return CategoryByIdLoader(info.context).load(category_id)

    @staticmethod
    def resolve_tax_type(root: models.Product, info):
        tax_data = info.context.plugins.get_tax_code_from_object_meta(root)
        return TaxType(tax_code=tax_data.code,
                       description=tax_data.description)

    @staticmethod
    def resolve_thumbnail(root: models.Product, info, *, size=255):
        def return_first_thumbnail(images):
            image = images[0] if images else None
            if image:
                url = get_product_image_thumbnail(image,
                                                  size,
                                                  method="thumbnail")
                alt = image.alt
                return Image(alt=alt, url=info.context.build_absolute_uri(url))
            return None

        return (ImagesByProductIdLoader(info.context).load(
            root.id).then(return_first_thumbnail))

    @staticmethod
    def resolve_url(root: models.Product, *_args):
        return ""

    @staticmethod
    def resolve_pricing(root: models.Product, info):
        context = info.context
        variants = ProductVariantsByProductIdLoader(context).load(root.id)
        collections = CollectionsByProductIdLoader(context).load(root.id)

        def calculate_pricing_info(discounts):
            def calculate_pricing_with_variants(variants):
                def calculate_pricing_with_collections(collections):
                    availability = get_product_availability(
                        product=root,
                        variants=variants,
                        collections=collections,
                        discounts=discounts,
                        country=context.country,
                        local_currency=context.currency,
                        plugins=context.plugins,
                    )
                    return ProductPricingInfo(**asdict(availability))

                return collections.then(calculate_pricing_with_collections)

            return variants.then(calculate_pricing_with_variants)

        return (DiscountsByDateTimeLoader(context).load(
            info.context.request_time).then(calculate_pricing_info))

    @staticmethod
    def resolve_is_available(root: models.Product, info):
        country = info.context.country
        in_stock = is_product_in_stock(root, country)
        return root.is_visible and in_stock

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_base_price(root: models.Product, _info):
        return root.price

    @staticmethod
    def resolve_price(root: models.Product, info):
        context = info.context

        def calculate_price(discounts):
            price_range = root.get_price_range(discounts)
            price = info.context.plugins.apply_taxes_to_product(
                root, price_range.start, info.context.country)
            return price.net

        return (DiscountsByDateTimeLoader(context).load(
            info.context.request_time).then(calculate_price))

    @staticmethod
    def resolve_attributes(root: models.Product, info):
        return SelectedAttributesByProductIdLoader(info.context).load(root.id)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_purchase_cost(root: models.Product, *_args):
        purchase_cost, _ = get_product_costs_data(root)
        return purchase_cost

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_margin(root: models.Product, *_args):
        _, margin = get_product_costs_data(root)
        return Margin(margin[0], margin[1])

    @staticmethod
    def resolve_image_by_id(root: models.Product, info, id):
        pk = get_database_id(info, id, ProductImage)
        try:
            return root.images.get(pk=pk)
        except models.ProductImage.DoesNotExist:
            raise GraphQLError("Product image not found.")

    @staticmethod
    def resolve_images(root: models.Product, info, **_kwargs):
        return ImagesByProductIdLoader(info.context).load(root.id)

    @staticmethod
    def resolve_variants(root: models.Product, info, **_kwargs):
        return ProductVariantsByProductIdLoader(info.context).load(root.id)

    @staticmethod
    def resolve_collections(root: models.Product, *_args):
        return root.collections.all()

    @classmethod
    def get_node(cls, info, pk):
        if info.context:
            qs = cls._meta.model.objects.visible_to_user(info.context.user)
            return qs.filter(pk=pk).first()
        return None

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_private_meta(root: models.Product, _info):
        return resolve_private_meta(root, _info)

    @staticmethod
    def resolve_meta(root: models.Product, _info):
        return resolve_meta(root, _info)

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
Esempio n. 28
0
class URLMeta(graphene.ObjectType):
    local = graphene.Boolean()
    url = graphene.String(required=True)
Esempio n. 29
0
class OrderEvent(CountableDjangoObjectType):
    date = graphene.types.datetime.DateTime(
        description="Date when event happened at in ISO 8601 format."
    )
    type = OrderEventsEnum(description="Order event type.")
    user = graphene.Field(User, description="User who performed the action.")
    message = graphene.String(description="Content of the event.")
    email = graphene.String(description="Email of the customer.")
    email_type = OrderEventsEmailsEnum(
        description="Type of an email sent to the customer."
    )
    amount = graphene.Float(description="Amount of money.")
    payment_id = graphene.String(description="The payment ID from the payment gateway.")
    payment_gateway = graphene.String(description="The payment gateway of the payment.")
    quantity = graphene.Int(description="Number of items.")
    composed_id = graphene.String(description="Composed ID of the Fulfillment.")
    order_number = graphene.String(description="User-friendly number of an order.")
    invoice_number = graphene.String(
        description="Number of an invoice related to the order."
    )
    oversold_items = graphene.List(
        graphene.String, description="List of oversold lines names."
    )
    lines = graphene.List(OrderEventOrderLineObject, description="The concerned lines.")
    fulfilled_items = graphene.List(
        lambda: FulfillmentLine, description="The lines fulfilled."
    )
    warehouse = graphene.Field(
        Warehouse, description="The warehouse were items were restocked."
    )
    transaction_reference = graphene.String(
        description="The transaction reference of captured payment."
    )
    shipping_costs_included = graphene.Boolean(
        description="Define if shipping costs were included to the refund."
    )
    related_order = graphene.Field(
        lambda: Order, description="The order which is related to this order."
    )
    discount = graphene.Field(
        OrderEventDiscountObject, description="The discount applied to the order."
    )

    class Meta:
        description = "History log of the order."
        model = models.OrderEvent
        interfaces = [relay.Node]
        only_fields = ["id"]

    @staticmethod
    def resolve_user(root: models.OrderEvent, info):
        user = info.context.user
        if (
            user == root.user
            or user.has_perm(AccountPermissions.MANAGE_USERS)
            or user.has_perm(AccountPermissions.MANAGE_STAFF)
        ):
            return root.user
        raise PermissionDenied()

    @staticmethod
    def resolve_email(root: models.OrderEvent, _info):
        return root.parameters.get("email", None)

    @staticmethod
    def resolve_email_type(root: models.OrderEvent, _info):
        return root.parameters.get("email_type", None)

    @staticmethod
    def resolve_amount(root: models.OrderEvent, _info):
        amount = root.parameters.get("amount", None)
        return float(amount) if amount else None

    @staticmethod
    def resolve_payment_id(root: models.OrderEvent, _info):
        return root.parameters.get("payment_id", None)

    @staticmethod
    def resolve_payment_gateway(root: models.OrderEvent, _info):
        return root.parameters.get("payment_gateway", None)

    @staticmethod
    def resolve_quantity(root: models.OrderEvent, _info):
        quantity = root.parameters.get("quantity", None)
        return int(quantity) if quantity else None

    @staticmethod
    def resolve_message(root: models.OrderEvent, _info):
        return root.parameters.get("message", None)

    @staticmethod
    def resolve_composed_id(root: models.OrderEvent, _info):
        return root.parameters.get("composed_id", None)

    @staticmethod
    def resolve_oversold_items(root: models.OrderEvent, _info):
        return root.parameters.get("oversold_items", None)

    @staticmethod
    def resolve_order_number(root: models.OrderEvent, _info):
        return root.order_id

    @staticmethod
    def resolve_invoice_number(root: models.OrderEvent, _info):
        return root.parameters.get("invoice_number")

    @staticmethod
    def resolve_lines(root: models.OrderEvent, info):
        raw_lines = root.parameters.get("lines", None)

        if not raw_lines:
            return None

        line_pks = []
        for entry in raw_lines:
            line_pk = entry.get("line_pk", None)
            if line_pk:
                line_pks.append(line_pk)

        def _resolve_lines(lines):
            results = []
            lines_dict = {line.pk: line for line in lines if line}
            for raw_line in raw_lines:
                line_pk = raw_line.get("line_pk")
                line_object = lines_dict.get(line_pk)
                discount = raw_line.get("discount")
                if discount:
                    discount = get_order_discount_event(discount)
                results.append(
                    OrderEventOrderLineObject(
                        quantity=raw_line["quantity"],
                        order_line=line_object,
                        item_name=raw_line["item"],
                        discount=discount,
                    )
                )

            return results

        return (
            OrderLineByIdLoader(info.context).load_many(line_pks).then(_resolve_lines)
        )

    @staticmethod
    def resolve_fulfilled_items(root: models.OrderEvent, _info):
        lines = root.parameters.get("fulfilled_items", [])
        return models.FulfillmentLine.objects.filter(pk__in=lines)

    @staticmethod
    def resolve_warehouse(root: models.OrderEvent, _info):
        warehouse = root.parameters.get("warehouse")
        return warehouse_models.Warehouse.objects.filter(pk=warehouse).first()

    @staticmethod
    def resolve_transaction_reference(root: models.OrderEvent, _info):
        return root.parameters.get("transaction_reference")

    @staticmethod
    def resolve_shipping_costs_included(root: models.OrderEvent, _info):
        return root.parameters.get("shipping_costs_included")

    @staticmethod
    def resolve_related_order(root: models.OrderEvent, info):
        order_pk = root.parameters.get("related_order_pk")
        if not order_pk:
            return None
        return OrderByIdLoader(info.context).load(order_pk)

    @staticmethod
    def resolve_discount(root: models.OrderEvent, info):
        discount_obj = root.parameters.get("discount")
        if not discount_obj:
            return None
        return get_order_discount_event(discount_obj)
Esempio n. 30
0
class NewsGraph(graphene.ObjectType):
    title = graphene.String()
    body = graphene.String()
    publish_date = graphene.types.datetime.Date()
    public = graphene.Boolean()
    slug = graphene.String()