Example #1
0
class OrderLine(CountableDjangoObjectType):
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for the ordered product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail."),
    )
    unit_price = graphene.Field(
        TaxedMoney,
        description="Price of the single item in the order line.",
        required=True,
    )
    undiscounted_unit_price = graphene.Field(
        TaxedMoney,
        description=(
            "Price of the single item in the order line without applied an order line "
            "discount."
        ),
        required=True,
    )
    unit_discount = graphene.Field(
        Money,
        description="The discount applied to the single order line.",
        required=True,
    )
    unit_discount_value = graphene.Field(
        PositiveDecimal,
        description="Value of the discount. Can store fixed value or percent value",
        required=True,
    )
    total_price = graphene.Field(
        TaxedMoney, description="Price of the order line.", required=True
    )
    variant = graphene.Field(
        ProductVariant,
        required=False,
        description=(
            "A purchased product variant. Note: this field may be null if the variant "
            "has been removed from stock at all."
        ),
    )
    translated_product_name = graphene.String(
        required=True, description="Product name in the customer's language"
    )
    translated_variant_name = graphene.String(
        required=True, description="Variant name in the customer's language"
    )
    allocations = graphene.List(
        graphene.NonNull(Allocation),
        description="List of allocations across warehouses.",
    )
    quantity_to_fulfill = graphene.Int(
        required=True,
        description=f"{ADDED_IN_31} A quantity of items remaining to be fulfilled.",
    )
    unit_discount_type = graphene.Field(
        DiscountValueTypeEnum,
        description="Type of the discount: fixed or percent",
    )

    class Meta:
        description = "Represents order line of particular order."
        model = models.OrderLine
        interfaces = [relay.Node]
        only_fields = [
            "digital_content_url",
            "id",
            "is_shipping_required",
            "product_name",
            "variant_name",
            "product_sku",
            "product_variant_id",
            "quantity",
            "quantity_fulfilled",
            "tax_rate",
            "unit_discount_reason",
        ]

    @staticmethod
    @traced_resolver
    def resolve_thumbnail(root: models.OrderLine, info, *, size=255):
        if not root.variant_id:
            return None

        def _get_image_from_media(image):
            url = get_product_image_thumbnail(image, size, method="thumbnail")
            alt = image.alt
            return Image(alt=alt, url=info.context.build_absolute_uri(url))

        def _get_first_variant_image(all_medias):
            if image := next(
                (
                    media
                    for media in all_medias
                    if media.type == ProductMediaTypes.IMAGE
                ),
                None,
            ):
                return image

        def _get_first_product_image(images):
            return _get_image_from_media(images[0]) if images else None

        def _resolve_thumbnail(result):
            product, variant_medias = result

            if image := _get_first_variant_image(variant_medias):
                return _get_image_from_media(image)

            # we failed to get image from variant, lets use first from product
            return (
                ProductImageByProductIdLoader(info.context)
                .load(product.id)
                .then(_get_first_product_image)
            )
Example #2
0
class Query(graphene.ObjectType):
    hello = graphene.String(
        name=graphene.Argument(graphene.String, default_value="stranger"))

    def resolve_hello(self, args, context, info):
        return 'Hello ' + args['name']
 class Arguments:
     tag_id = graphene.Int(required=True)
     tag_data = graphene.Argument(TagUpdateInput, required=True)
Example #4
0
class Shop(graphene.ObjectType):
    available_payment_gateways = graphene.List(
        graphene.NonNull(PaymentGateway),
        currency=graphene.Argument(
            graphene.String,
            description="A currency for which gateways will be returned.",
            required=False,
        ),
        description="List of available payment gateways.",
        required=True,
    )
    geolocalization = graphene.Field(
        Geolocalization, description="Customer's geolocalization data."
    )
    authorization_keys = graphene.List(
        AuthorizationKey,
        description=(
            "List of configured authorization keys. Authorization keys are used to "
            "enable third-party OAuth authorization (currently Facebook or Google)."
        ),
        required=True,
    )
    countries = graphene.List(
        graphene.NonNull(CountryDisplay),
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
        ),
        description="List of countries available in the shop.",
        required=True,
    )
    currencies = graphene.List(
        graphene.String, description="List of available currencies.", required=True
    )
    default_currency = graphene.String(
        description="Shop's default currency.", required=True
    )
    default_country = graphene.Field(
        CountryDisplay, description="Shop's default country."
    )
    default_mail_sender_name = graphene.String(
        description="Default shop's email sender's name."
    )
    default_mail_sender_address = graphene.String(
        description="Default shop's email sender's address."
    )
    description = graphene.String(description="Shop's description.")
    domain = graphene.Field(Domain, required=True, description="Shop's domain data.")
    homepage_collection = graphene.Field(
        Collection, description="Collection displayed on homepage."
    )
    languages = graphene.List(
        LanguageDisplay,
        description="List of the shops's supported languages.",
        required=True,
    )
    name = graphene.String(description="Shop's name.", required=True)
    navigation = graphene.Field(Navigation, description="Shop's navigation.")
    permissions = graphene.List(
        Permission, description="List of available permissions.", required=True
    )
    phone_prefixes = graphene.List(
        graphene.String, description="List of possible phone prefixes.", required=True
    )
    header_text = graphene.String(description="Header text.")
    include_taxes_in_prices = graphene.Boolean(
        description="Include taxes in prices.", required=True
    )
    display_gross_prices = graphene.Boolean(
        description="Display prices with tax in store.", required=True
    )
    charge_taxes_on_shipping = graphene.Boolean(
        description="Charge taxes on shipping.", required=True
    )
    track_inventory_by_default = graphene.Boolean(
        description="Enable inventory tracking."
    )
    default_weight_unit = WeightUnitsEnum(description="Default weight unit.")
    translation = TranslationField(ShopTranslation, type_name="shop", resolver=None)
    automatic_fulfillment_digital_products = graphene.Boolean(
        description="Enable automatic fulfillment for all digital products."
    )

    default_digital_max_downloads = graphene.Int(
        description="Default number of max downloads per digital content URL."
    )
    default_digital_url_valid_days = graphene.Int(
        description="Default number of days which digital content URL will be valid."
    )
    company_address = graphene.Field(
        Address, description="Company address.", required=False
    )
    customer_set_password_url = graphene.String(
        description="URL of a view where customers can set their password.",
        required=False,
    )
    staff_notification_recipients = graphene.List(
        StaffNotificationRecipient,
        description="List of staff notification recipients.",
        required=False,
    )

    class Meta:
        description = (
            "Represents a shop resource containing general shop data and configuration."
        )

    @staticmethod
    def resolve_available_payment_gateways(_, _info, currency: Optional[str] = None):
        return get_plugins_manager().list_payment_gateways(currency=currency)

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_authorization_keys(_, _info):
        return site_models.AuthorizationKey.objects.all()

    @staticmethod
    def resolve_countries(_, _info, language_code=None):
        taxes = {vat.country_code: vat for vat in VAT.objects.all()}
        with translation.override(language_code):
            return [
                CountryDisplay(
                    code=country[0], country=country[1], vat=taxes.get(country[0])
                )
                for country in filter(lambda c: c[0] == "MN" or c[0] == "GB", countries)
            ]

    @staticmethod
    def resolve_currencies(_, _info):
        return settings.AVAILABLE_CURRENCIES

    @staticmethod
    def resolve_domain(_, info):
        site = info.context.site
        return Domain(
            host=site.domain,
            ssl_enabled=settings.ENABLE_SSL,
            url=info.context.build_absolute_uri("/"),
        )

    @staticmethod
    def resolve_geolocalization(_, info):
        client_ip = get_client_ip(info.context)
        country = get_country_by_ip(client_ip)
        if country:
            return Geolocalization(
                country=CountryDisplay(code=country.code, country=country.name)
            )
        return Geolocalization(country=None)

    @staticmethod
    def resolve_default_currency(_, _info):
        return settings.DEFAULT_CURRENCY

    @staticmethod
    def resolve_description(_, info):
        return info.context.site.settings.description

    @staticmethod
    def resolve_homepage_collection(_, info):
        collection_pk = info.context.site.settings.homepage_collection_id
        qs = product_models.Collection.objects.all()
        return qs.filter(pk=collection_pk).first()

    @staticmethod
    def resolve_languages(_, _info):
        return [
            LanguageDisplay(
                code=LanguageCodeEnum[str_to_enum(language[0])], language=language[1]
            )
            for language in settings.LANGUAGES
        ]

    @staticmethod
    def resolve_name(_, info):
        return info.context.site.name

    @staticmethod
    def resolve_navigation(_, info):
        site_settings = info.context.site.settings
        main = (
            MenuByIdLoader(info.context).load(site_settings.top_menu_id)
            if site_settings.top_menu_id
            else None
        )
        secondary = (
            MenuByIdLoader(info.context).load(site_settings.bottom_menu_id)
            if site_settings.bottom_menu_id
            else None
        )
        return Navigation(main=main, secondary=secondary)

    @staticmethod
    def resolve_permissions(_, _info):
        permissions = get_permissions()
        return format_permissions_for_display(permissions)

    @staticmethod
    def resolve_phone_prefixes(_, _info):
        return list(COUNTRY_CODE_TO_REGION_CODE.keys())

    @staticmethod
    def resolve_header_text(_, info):
        return info.context.site.settings.header_text

    @staticmethod
    def resolve_include_taxes_in_prices(_, info):
        return info.context.site.settings.include_taxes_in_prices

    @staticmethod
    def resolve_display_gross_prices(_, info):
        return info.context.site.settings.display_gross_prices

    @staticmethod
    def resolve_charge_taxes_on_shipping(_, info):
        return info.context.site.settings.charge_taxes_on_shipping

    @staticmethod
    def resolve_track_inventory_by_default(_, info):
        return info.context.site.settings.track_inventory_by_default

    @staticmethod
    def resolve_default_weight_unit(_, info):
        return info.context.site.settings.default_weight_unit

    @staticmethod
    def resolve_default_country(_, _info):
        default_country_code = settings.DEFAULT_COUNTRY
        default_country_name = countries.countries.get(default_country_code)
        if default_country_name:
            vat = VAT.objects.filter(country_code=default_country_code).first()
            default_country = CountryDisplay(
                code=default_country_code, country=default_country_name, vat=vat
            )
        else:
            default_country = None
        return default_country

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_default_mail_sender_name(_, info):
        return info.context.site.settings.default_mail_sender_name

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_default_mail_sender_address(_, info):
        return info.context.site.settings.default_mail_sender_address

    @staticmethod
    def resolve_company_address(_, info):
        return info.context.site.settings.company_address

    @staticmethod
    def resolve_customer_set_password_url(_, info):
        return info.context.site.settings.customer_set_password_url

    @staticmethod
    def resolve_translation(_, info, language_code):
        return resolve_translation(info.context.site.settings, info, language_code)

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_automatic_fulfillment_digital_products(_, info):
        site_settings = info.context.site.settings
        return site_settings.automatic_fulfillment_digital_products

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_default_digital_max_downloads(_, info):
        return info.context.site.settings.default_digital_max_downloads

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_default_digital_url_valid_days(_, info):
        return info.context.site.settings.default_digital_url_valid_days

    @staticmethod
    @permission_required(SitePermissions.MANAGE_SETTINGS)
    def resolve_staff_notification_recipients(_, info):
        return account_models.StaffNotificationRecipient.objects.all()
 def get_all_links_input_fields():
     return {
         # this creates an input field using the LinkOrderBy custom enum
         'order_by': graphene.Argument(LinkOrderBy)
     }
Example #6
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."),
    )
    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 = 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 = TranslationField(ProductTranslation, type_name="product")

    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(**asdict(availability))

    @staticmethod
    @gql_optimizer.resolver_hints(prefetch_related=("variants"))
    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
    @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=[
        Prefetch(
            "product_type__attributeproduct",
            queryset=models.AttributeProduct.objects.filter(
                attribute__visible_in_storefront=True).prefetch_related(
                    "productassignments__values", "attribute"),
            to_attr="storefront_attributes",
        )
    ])
    def resolve_attributes(root: models.Product, info):
        return resolve_attribute_list(root, user=info.context.user)

    @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
    @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(ProductPermissions.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()

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
Example #7
0
class Page(CountableDjangoObjectType):
    content_json = graphene.JSONString(
        description="Content of the page (JSON).",
        deprecation_reason=(
            "Will be removed in Saleor 4.0. Use the `content` field instead."
        ),
        required=True,
    )
    translation = TranslationField(PageTranslation, type_name="page")
    attributes = graphene.List(
        graphene.NonNull(SelectedAttribute),
        required=True,
        description="List of attributes assigned to this product.",
    )
    media = graphene.List(
        graphene.NonNull(lambda: PageMedia),
        description="List of media for the page.",
    )
    store = graphene.Field(
        Store,
        id=graphene.Argument(graphene.ID, description="ID of the store."),
        slug=graphene.Argument(graphene.String, description="Slug of the store"),
        description="Look up a store by ID or slug.",
    )

    class Meta:
        description = (
            "A static page that can be manually added by a shop operator through the "
            "dashboard."
        )
        only_fields = [
            "content",
            "created",
            "id",
            "is_published",
            "page_type",
            "publication_date",
            "seo_description",
            "seo_title",
            "slug",
            "title",
            "store",
        ]
        interfaces = [graphene.relay.Node, ObjectWithMetadata]
        model = models.Page

    @staticmethod
    def resolve_page_type(root: models.Page, info):
        return PageTypeByIdLoader(info.context).load(root.page_type_id)

    @staticmethod
    def resolve_content_json(root: models.Page, info):
        content = root.content
        return content if content is not None else {}

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

    @staticmethod
    def resolve_media(self, info, page=None, slug=None, channel=None, **_kwargs):
        return models.PageMedia.objects.filter(page_id=self.pk, is_active=True)
Example #8
0
class Query(graphene.ObjectType):
    attributes = DjangoFilterConnectionField(
        ProductAttribute,
        filterset_class=DistinctFilterSet,
        query=graphene.String(description=DESCRIPTIONS['attributes']),
        in_category=graphene.Argument(graphene.ID),
        description='List of the shop\'s product attributes.')
    categories = DjangoFilterConnectionField(
        Category,
        filterset_class=DistinctFilterSet,
        query=graphene.String(description=DESCRIPTIONS['category']),
        level=graphene.Argument(graphene.Int),
        description='List of the shop\'s categories.')
    category = graphene.Field(Category,
                              id=graphene.Argument(graphene.ID),
                              description='Lookup a category by ID.')
    collection = graphene.Field(Collection,
                                id=graphene.Argument(graphene.ID),
                                description='Lookup a collection by ID.')
    collections = DjangoFilterConnectionField(
        Collection,
        query=graphene.String(description=DESCRIPTIONS['collection']),
        description='List of the shop\'s collections.')
    menu = graphene.Field(Menu,
                          id=graphene.Argument(graphene.ID),
                          description='Lookup a menu by ID.')
    menus = DjangoFilterConnectionField(
        Menu,
        query=graphene.String(description=DESCRIPTIONS['menu']),
        description="List of the shop\'s menus.")
    menu_item = graphene.Field(MenuItem,
                               id=graphene.Argument(graphene.ID),
                               description='Lookup a menu item by ID.')
    menu_items = DjangoFilterConnectionField(
        MenuItem,
        query=graphene.String(description=DESCRIPTIONS['menu_item']),
        description='List of the shop\'s menu items.')
    order = graphene.Field(Order,
                           description='Lookup an order by ID.',
                           id=graphene.Argument(graphene.ID))
    orders = DjangoFilterConnectionField(
        Order,
        filterset_class=OrderFilter,
        query=graphene.String(description=DESCRIPTIONS['order']),
        description='List of the shop\'s orders.')
    page = graphene.Field(
        Page,
        id=graphene.Argument(graphene.ID),
        slug=graphene.String(description=DESCRIPTIONS['page']),
        description='Lookup a page by ID or by slug.')
    pages = DjangoFilterConnectionField(
        Page,
        filterset_class=DistinctFilterSet,
        query=graphene.String(),
        description='List of the shop\'s pages.')
    product = graphene.Field(Product,
                             id=graphene.Argument(graphene.ID),
                             description='Lookup a product by ID.')
    products = DjangoFilterConnectionField(
        Product,
        filterset_class=ProductFilterSet,
        query=graphene.String(description=DESCRIPTIONS['product']),
        description='List of the shop\'s products.')
    product_type = graphene.Field(ProductType,
                                  id=graphene.Argument(graphene.ID),
                                  description='Lookup a product type by ID.')
    product_types = DjangoFilterConnectionField(
        ProductType,
        filterset_class=DistinctFilterSet,
        description='List of the shop\'s product types.')
    product_variant = graphene.Field(ProductVariant,
                                     id=graphene.Argument(graphene.ID),
                                     description='Lookup a variant by ID.')
    sale = graphene.Field(Sale,
                          id=graphene.Argument(graphene.ID),
                          description='Lookup a sale by ID.')
    sales = DjangoFilterConnectionField(
        Sale,
        query=graphene.String(description=DESCRIPTIONS['sale']),
        description="List of the shop\'s sales.")
    shop = graphene.Field(Shop,
                          description='Represents a shop resources.',
                          resolver=resolve_shop)
    voucher = graphene.Field(Voucher,
                             id=graphene.Argument(graphene.ID),
                             description='Lookup a voucher by ID.')
    vouchers = DjangoFilterConnectionField(
        Voucher,
        query=graphene.String(description=DESCRIPTIONS['product']),
        description="List of the shop\'s vouchers.")
    shipping_method = graphene.Field(
        ShippingMethod,
        id=graphene.Argument(graphene.ID),
        description='Lookup a shipping method by ID.')
    shipping_methods = DjangoFilterConnectionField(
        ShippingMethod, description='List of the shop\'s shipping methods.')
    user = graphene.Field(User,
                          id=graphene.Argument(graphene.ID),
                          description='Lookup an user by ID.')
    users = DjangoFilterConnectionField(
        User,
        description='List of the shop\'s users.',
        query=graphene.String(description=DESCRIPTIONS['user']))
    node = graphene.Node.Field()

    def resolve_attributes(self, info, in_category=None, query=None, **kwargs):
        return resolve_attributes(in_category, info, query)

    def resolve_category(self, info, id):
        return get_node(info, id, only_type=Category)

    def resolve_categories(self, info, level=None, query=None, **kwargs):
        return resolve_categories(info, level=level, query=query)

    def resolve_collection(self, info, id):
        return get_node(info, id, only_type=Collection)

    def resolve_collections(self, info, query=None, **kwargs):
        resolve_collections(info, query)

    def resolve_user(self, info, id):
        return resolve_user(info, id)

    def resolve_users(self, info, query=None, **kwargs):
        return resolve_users(info, query=query)

    def resolve_menu(self, info, id):
        return get_node(info, id, only_type=Menu)

    def resolve_menus(self, info, query=None, **kwargs):
        return resolve_menus(info, query)

    def resolve_menu_item(self, info, id):
        return get_node(info, id, only_type=MenuItem)

    def resolve_menu_items(self, info, query=None, **kwargs):
        return resolve_menu_items(info, query)

    def resolve_page(self, info, id=None, slug=None):
        return resolve_page(info, id, slug)

    def resolve_pages(self, info, query=None, **kwargs):
        return resolve_pages(user=info.context.user, query=query)

    def resolve_order(self, info, id):
        return resolve_order(info, id)

    def resolve_orders(self, info, query=None, **kwargs):
        return resolve_orders(info, query)

    def resolve_product(self, info, id):
        return get_node(info, id, only_type=Product)

    def resolve_products(self, info, category_id=None, query=None, **kwargs):
        return resolve_products(info, category_id, query)

    def resolve_product_type(self, info, id):
        return get_node(info, id, only_type=ProductType)

    def resolve_product_types(self, info, **kwargs):
        return resolve_product_types()

    @permission_required('discount.view_sale')
    def resolve_sale(self, info, id):
        return get_node(info, id, only_type=Sale)

    @permission_required('discount.view_sale')
    def resolve_sales(self, info, query=None, **kwargs):
        return resolve_sales(info, query)

    def resolve_product_variant(self, info, id):
        return get_node(info, id, only_type=ProductVariant)

    @permission_required('discount.view_voucher')
    def resolve_voucher(self, info, id):
        return get_node(info, id, only_type=Voucher)

    @permission_required('discount.view_voucher')
    def resolve_vouchers(self, info, query=None, **kwargs):
        return resolve_vouchers(info, query)

    def resolve_shipping_method(self, info, id):
        return get_node(info, id, only_type=ShippingMethod)

    def resolve_shipping_methods(self, info, **kwargs):
        return resolve_shipping_methods(info)
Example #9
0
    return evalg.proc.pollbook.get_voters_in_election_group(
        session, election_group_id, **kwargs).all()


def resolve_voters_by_person_id(_, info, **kwargs):
    person_id = kwargs['id']
    session = get_session(info)
    person = session.query(evalg.models.person.Person).get(person_id)
    return evalg.proc.pollbook.get_voters_for_person(session, person).all()


search_voters_query = graphene.List(
    Voter,
    resolver=resolve_search_voters,
    election_group_id=graphene.Argument(graphene.UUID, required=True),
    self_added=graphene.Argument(graphene.Boolean, required=False),
    reviewed=graphene.Argument(graphene.Boolean, required=False),
    verified=graphene.Argument(graphene.Boolean, required=False),
    has_voted=graphene.Argument(graphene.Boolean, required=False),
    limit=graphene.Argument(graphene.Int, required=False),
    search=graphene.Argument(graphene.String, required=False),
    pollbook_id=graphene.Argument(graphene.UUID, required=False),
)

# TODO: Re-design person-voter relationship
find_voters_query = graphene.List(Voter,
                                  resolver=resolve_voters_by_person_id,
                                  id=graphene.Argument(graphene.UUID,
                                                       required=True))
Example #10
0
class OrderLine(CountableDjangoObjectType):
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for the ordered product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail."),
    )
    unit_price = graphene.Field(
        TaxedMoney, description="Price of the single item in the order line."
    )
    variant = graphene.Field(
        ProductVariant,
        required=False,
        description=(
            "A purchased product variant. Note: this field may be null if the variant "
            "has been removed from stock at all."
        ),
    )
    translated_product_name = graphene.String(
        required=True, description="Product name in the customer's language"
    )
    translated_variant_name = graphene.String(
        required=True, description="Variant name in the customer's language"
    )

    class Meta:
        description = "Represents order line of particular order."
        model = models.OrderLine
        interfaces = [relay.Node]
        only_fields = [
            "digital_content_url",
            "id",
            "is_shipping_required",
            "product_name",
            "variant_name",
            "product_sku",
            "quantity",
            "quantity_fulfilled",
            "tax_rate",
        ]

    @staticmethod
    @gql_optimizer.resolver_hints(
        prefetch_related=["variant__images", "variant__product__images"]
    )
    def resolve_thumbnail(root: models.OrderLine, info, *, size=255):
        if not root.variant:
            return None
        image = root.variant.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_unit_price(root: models.OrderLine, _info):
        return root.unit_price

    @staticmethod
    def resolve_translated_product_name(root: models.OrderLine, _info):
        return root.translated_product_name

    @staticmethod
    def resolve_translated_variant_name(root: models.OrderLine, _info):
        return root.translated_variant_name
Example #11
0
 class Input:
     availability = graphene.Argument(EditMatchAvailabilityInput)
Example #12
0
class Query(graphene.ObjectType):
    hospitals = relay.ConnectionField(
        HospitalConnection,
        order_by=graphene.Argument(HospitalSortField,
                                   required=False,
                                   default_value="distance"),
        descending=graphene.Boolean(default_value=False, required=False),
        category_filters=graphene.List(graphene.String,
                                       required=False,
                                       default_value=[]),
        search_query=graphene.String(required=False, default_value=''))

    hospital = graphene.Field(HospitalType,
                              id=graphene.NonNull(graphene.ID),
                              lat=graphene.Float(default_value=0),
                              lon=graphene.Float(default_value=0))

    localities = relay.ConnectionField(LocalityConnection)
    locality = graphene.Field(LocalityType, name=graphene.String())

    country = graphene.Field(CountryType)

    def resolve_hospitals(parent, info, order_by, descending, category_filters,
                          lat, lon, search_query, **kwargs):
        info.context.coords = {"lat": lat, "lon": lon}
        coords = Point(lon, lat, srid=4326)

        def get_hospitals(order):
            joins = '''
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available general_available, total general_total, (total - available) general_occupied
          FROM "Equipment" WHERE category = 'gen' ORDER BY branch_id, time DESC
        ) AS eq_gen ON eq_gen.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available icu_available, total icu_total, (total - available) icu_occupied
          FROM "Equipment" WHERE category = 'ICU' ORDER BY branch_id, time DESC
        ) AS eq_ICU ON eq_ICU.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available hdu_available, total hdu_total, (total - available) hdu_occupied
          FROM "Equipment" WHERE category = 'HDU' ORDER BY branch_id, time DESC
        ) AS eq_HDU ON eq_HDU.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available ventilators_available, total ventilators_total, (total - available) ventilators_occupied
          FROM "Equipment" WHERE category = 'vent' ORDER BY branch_id, time DESC
        ) AS eq_vent ON eq_vent.branch_id = hos.id
      '''

            selections = '''
        eq_HDU.hdu_available, eq_HDU.hdu_total, eq_HDU.hdu_occupied,
        eq_gen.general_available, eq_gen.general_total, eq_gen.general_occupied,
        eq_ICU.icu_available, eq_ICU.icu_total, eq_ICU.icu_occupied,
        eq_vent.ventilators_available, eq_vent.ventilators_total, eq_vent.ventilators_occupied,
        hos.name, hos.website, hos.phone, hos.location, hos.city, hos.district, hos.state, hos.country, hos.postal_code, hos.place_id, hos.address, hos.category, hos.locality_id,
        encode(('Hospital:' || hos.id)::bytea, 'base64') id,
        ST_X(hos.location::geometry) as longitude, ST_Y(hos.location::geometry) as latitude,
        ((hos."location" <-> %s::geometry) / 1000) AS distance
      '''

            cursor = connection.cursor()

            if len(category_filters) > 0:
                where_claus = 'WHERE hos.name ILIKE %s AND hos.category IN %s'
                escaped_strings = [
                    str(coords), '%' + search_query + '%',
                    tuple(category_filters)
                ]
            else:
                where_claus = 'WHERE hos.name ILIKE %s'
                escaped_strings = [str(coords), '%' + search_query + '%']

            query = f'''
        SELECT * FROM (
          SELECT 
          {selections}
          FROM "Hospitals" AS hos
          {joins}
          {where_claus}
        ) data
        ORDER BY COALESCE({order}, {"''" if order == 'name' else 0}) {'DESC' if descending else 'ASC'}
      '''

            cursor.execute(query, escaped_strings)
            return namedtuplefetch(cursor, "Hospital")

        o = order_by

        if o not in ("distance", "name"):
            o = o.split("_")[::-1]
            o = '_'.join(o)

        hospitals = get_hospitals(o)

        return hospitals

    def resolve_hospital(parent, info, id, lat, lon, **kwargs):
        coords = Point(lon, lat, srid=4326)

        def namedtuplefetch(cursor):
            desc = cursor.description
            nt_result = namedtuple('Hospital', [col[0] for col in desc])
            return [nt_result(*row) for row in cursor.fetchall()]

        joins = '''
      FULL OUTER JOIN (
        SELECT DISTINCT ON (branch_id)
        branch_id, available general_available, total general_total, (total - available) general_occupied
        FROM "Equipment" WHERE category = 'gen' ORDER BY branch_id, time DESC
      ) AS eq_gen ON eq_gen.branch_id = hos.id
      FULL OUTER JOIN (
        SELECT DISTINCT ON (branch_id)
        branch_id, available icu_available, total icu_total, (total - available) icu_occupied
        FROM "Equipment" WHERE category = 'ICU' ORDER BY branch_id, time DESC
      ) AS eq_ICU ON eq_ICU.branch_id = hos.id
      FULL OUTER JOIN (
        SELECT DISTINCT ON (branch_id)
        branch_id, available hdu_available, total hdu_total, (total - available) hdu_occupied
        FROM "Equipment" WHERE category = 'HDU' ORDER BY branch_id, time DESC
      ) AS eq_HDU ON eq_HDU.branch_id = hos.id
      FULL OUTER JOIN (
        SELECT DISTINCT ON (branch_id)
        branch_id, available ventilators_available, total ventilators_total, (total - available) ventilators_occupied
        FROM "Equipment" WHERE category = 'vent' ORDER BY branch_id, time DESC
      ) AS eq_vent ON eq_vent.branch_id = hos.id
      FULL OUTER JOIN (
        SELECT DISTINCT ON (branch_id)
        branch_id, available oxygen_available, total oxygen_total, (total - available) oxygen_occupied
        FROM "Equipment" WHERE category = 'oxy' ORDER BY branch_id, time DESC
      ) AS eq_oxy ON eq_oxy.branch_id = hos.id
    '''

        selections = '''
      eq_HDU.hdu_available, eq_HDU.hdu_total, eq_HDU.hdu_occupied,
      eq_gen.general_available, eq_gen.general_total, eq_gen.general_occupied,
      eq_oxy.oxygen_available, eq_oxy.oxygen_total, eq_oxy.oxygen_occupied,
      eq_vent.ventilators_available, eq_vent.ventilators_total, eq_vent.ventilators_occupied,
      eq_ICU.icu_available, eq_ICU.icu_total, eq_ICU.icu_occupied,
      hos.name, hos.website, hos.phone, hos.location, hos.city, hos.district, hos.state, hos.country, hos.postal_code, hos.place_id, hos.address, hos.category, hos.locality_id,
      encode(('Hospital:' || hos.id)::bytea, 'base64') id,
      ST_X(hos.location::geometry) as longitude, ST_Y(hos.location::geometry) as latitude,
      ((hos."location" <-> %s::geometry) / 1000) AS distance
    '''

        query = f'''
      SELECT {selections}
      FROM "Hospitals" AS hos
      {joins}
      WHERE id=%s
    '''

        cursor = connection.cursor()

        cursor.execute(query, [str(coords), get_id(id)])
        hospital = namedtuplefetch(cursor)[0]

        return hospital

    def resolve_localities(parent, info, **kwargs):
        localities = Locality.objects.raw("""
        SELECT "Locality".*, MAX(c.time) as last_updated, SUM(c.total) total, SUM(c.available) available, SUM(c.occupied) occupied FROM "Locality"
        INNER JOIN (
          SELECT hos.id, hos.name, hos.locality_id, SUM(available) available, SUM(total) total, SUM(total - available) occupied, a.time
          FROM "Hospitals" as hos
          INNER JOIN (
            SELECT MAX(time) as time, branch_id 
            FROM "Equipment"
            GROUP BY branch_id
          ) AS a ON a.branch_id = hos.id
          INNER JOIN (
            SELECT available, total, category, branch_id, time
            FROM "Equipment"
          ) AS b on b.branch_id = hos.id AND b.time = a.time
          WHERE hos.category != 'pri covid' OR hos.category IS null
          GROUP BY hos.id, a.time
          ORDER BY hos.name
        ) c on "Locality".id = c.locality_id
        GROUP BY "Locality".id
    """)

        return localities

    def resolve_locality(parent, info, name, **kwargs):
        name = ' '.join(name.split('-'))
        locality = Locality.objects.raw(
            """
      SELECT "Locality".*, MAX(c.time) as last_updated, SUM(c.total) total, SUM(c.available) available, SUM(c.occupied) occupied FROM "Locality"
      INNER JOIN (
        SELECT hos.id, hos.name, hos.locality_id, SUM(available) available, SUM(total) total, SUM(total - available) occupied, a.time
        FROM "Hospitals" as hos
        INNER JOIN (
          SELECT MAX(time) as time, branch_id
          FROM "Equipment"
          GROUP BY branch_id
        ) AS a ON a.branch_id = hos.id
        INNER JOIN (
          SELECT available, total, category, branch_id, time
          FROM "Equipment"
        ) AS b on b.branch_id = hos.id AND b.time = a.time
        WHERE hos.category != 'pri covid' OR hos.category IS null
        GROUP BY hos.id, a.time
        ORDER BY hos.name
      ) c on "Locality".id = c.locality_id
      WHERE ("Locality".name || ' ' || "Locality".state ILIKE %s)
      GROUP BY "Locality".id
    """, [name])

        if len(locality) == 0:
            raise KeyError("Invalid locality passed")

        return locality[0]

    def resolve_country(parent, info, **kwargs):
        query = """
        SELECT SUM(total) total, SUM(available) available, SUM(occupied) occupied, MAX(last_updated) last_updated
        FROM (
          SELECT "Locality".*, MAX(c.time) as last_updated, SUM(c.total) total, SUM(c.available) available, SUM(c.occupied) occupied FROM "Locality"
          INNER JOIN (
            SELECT hos.id, hos.name, hos.locality_id, SUM(available) available, SUM(total) total, SUM(total - available) occupied, a.time
            FROM "Hospitals" as hos
            INNER JOIN (
              SELECT MAX(time) as time, branch_id
              FROM "Equipment"
              GROUP BY branch_id
            ) AS a ON a.branch_id = hos.id
            INNER JOIN (
              SELECT available, total, category, branch_id, time
              FROM "Equipment"
            ) AS b on b.branch_id = hos.id AND b.time = a.time
            GROUP BY hos.id, a.time
            ORDER BY hos.name
          ) c on "Locality".id = c.locality_id
          GROUP BY "Locality".id
          ) d
      """
        cursor = connection.cursor()
        cursor.execute(query)

        return namedtuplefetch(cursor, "Country")[0]
Example #13
0
class LocalityType(DjangoObjectType):
    total = graphene.Int()
    available = graphene.Int()
    occupied = graphene.Int()
    last_updated = graphene.Float()
    hospitals = relay.ConnectionField(
        HospitalConnection,
        order_by=graphene.Argument(HospitalSortField,
                                   required=False,
                                   default_value="distance"),
        descending=graphene.Boolean(default_value=False, required=False),
        category_filters=graphene.List(graphene.String,
                                       required=False,
                                       default_value=[]),
        lat=graphene.Float(required=False, default_value=0),
        lon=graphene.Float(required=False, default_value=0),
        search_query=graphene.String(required=False, default_value=''))

    def resolve_hospitals(locality, info, order_by, descending,
                          category_filters, lat, lon, search_query, **kwargs):
        info.context.coords = {"lat": lat, "lon": lon}
        coords = Point(lon, lat, srid=4326)

        def get_hospitals(order):
            joins = '''
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available general_available, total general_total, (total - available) general_occupied
          FROM "Equipment" WHERE category = 'gen' ORDER BY branch_id, time DESC
        ) AS eq_gen ON eq_gen.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available icu_available, total icu_total, (total - available) icu_occupied
          FROM "Equipment" WHERE category = 'ICU' ORDER BY branch_id, time DESC
        ) AS eq_ICU ON eq_ICU.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available hdu_available, total hdu_total, (total - available) hdu_occupied
          FROM "Equipment" WHERE category = 'HDU' ORDER BY branch_id, time DESC
        ) AS eq_HDU ON eq_HDU.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available ventilators_available, total ventilators_total, (total - available) ventilators_occupied
          FROM "Equipment" WHERE category = 'vent' ORDER BY branch_id, time DESC
        ) AS eq_vent ON eq_vent.branch_id = hos.id
        FULL OUTER JOIN (
          SELECT DISTINCT ON (branch_id)
          branch_id, available oxygen_available, total oxygen_total, (total - available) oxygen_occupied
          FROM "Equipment" WHERE category = 'oxy' ORDER BY branch_id, time DESC
        ) AS eq_oxy ON eq_oxy.branch_id = hos.id
      '''

            selections = '''
        eq_HDU.hdu_available, eq_HDU.hdu_total, eq_HDU.hdu_occupied,
        eq_gen.general_available, eq_gen.general_total, eq_gen.general_occupied,
        eq_oxy.oxygen_available, eq_oxy.oxygen_total, eq_oxy.oxygen_occupied,
        eq_ICU.icu_available, eq_ICU.icu_total, eq_ICU.icu_occupied,
        eq_vent.ventilators_available, eq_vent.ventilators_total, eq_vent.ventilators_occupied,
        hos.name, hos.website, hos.phone, hos.location, hos.city, hos.district, hos.state, hos.country, hos.postal_code, hos.place_id, hos.address, hos.category, hos.locality_id,
        encode(('Hospital:' || hos.id)::bytea, 'base64') id,
        ST_X(hos.location::geometry) as longitude, ST_Y(hos.location::geometry) as latitude,
        ((hos."location" <-> %s::geometry) / 1000) AS distance
      '''

            cursor = connection.cursor()

            if len(category_filters) > 0:
                where_claus = 'WHERE hos.name ILIKE %s AND hos.category IN %s'
                escaped_strings = [
                    str(coords), '%' + search_query + '%',
                    tuple(category_filters)
                ]
            else:
                where_claus = 'WHERE hos.name ILIKE %s'
                escaped_strings = [str(coords), '%' + search_query + '%']

            query = f'''
        SELECT * FROM (
          SELECT 
          {selections}
          FROM "Hospitals" AS hos
          {joins}
          {where_claus}
        ) data
        WHERE data.locality_id = {locality.id} AND distance IS NOT NULL AND (data.category != 'pri covid' OR data.category IS null)
        AND (data.hdu_total IS NOT NULL OR data.icu_total IS NOT NULL OR data.ventilators_total IS NOT NULL or general_total IS NOT NULL)
        ORDER BY COALESCE({order}, {"''" if order == 'name' else 0}) {'DESC' if descending else 'ASC'}
      '''

            cursor.execute(query, escaped_strings)
            return namedtuplefetch(cursor, "Hospital")

        o = order_by

        if o not in ("distance", "name"):
            o = o.split("_")[::-1]
            o = '_'.join(o)

        hospitals = get_hospitals(o)

        return hospitals

    class Meta:
        model = Locality
        name = "Locality"
        interfaces = (relay.Node, )
Example #14
0
 class Arguments:
     userInput = graphene.Argument(UserInput)
Example #15
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'))
    availability = graphene.Field(
        ProductAvailability,
        description="""Informs about product's availability in the storefront,
        current price and discounts.""")
    price = graphene.Field(
        Money,
        description="""The product's base price (without any discounts
        applied).""")
    attributes = graphene.List(
        SelectedAttribute,
        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')

    class Meta:
        description = """Represents an individual item for sale in the
        storefront."""
        interfaces = [relay.Node]
        model = models.Product

    def resolve_thumbnail_url(self, info, *, size=None):
        if not size:
            size = 255
        return get_thumbnail(self.get_first_image(), size, method='thumbnail')

    def resolve_url(self, info):
        return self.get_absolute_url()

    def resolve_availability(self, info):
        context = info.context
        availability = get_availability(self, context.discounts, context.taxes,
                                        context.currency)
        return ProductAvailability(**availability._asdict())

    def resolve_attributes(self, info):
        return resolve_attribute_list(self.attributes)

    def resolve_product_type(self, info):
        return self.product_type

    @permission_required('product.manage_products')
    def resolve_purchase_cost(self, info):
        purchase_cost, _ = get_product_costs_data(self)
        return purchase_cost

    @permission_required('product.manage_products')
    def resolve_margin(self, info):
        _, margin = get_product_costs_data(self)
        return Margin(margin[0], margin[1])

    def resolve_image_by_id(self, info, id):
        pk = get_database_id(info, id, ProductImage)
        try:
            return self.images.get(pk=pk)
        except models.ProductImage.DoesNotExist:
            raise GraphQLError('Product image not found.')
Example #16
0
class ProductChannelListing(CountableDjangoObjectType):
    discounted_price = graphene.Field(
        Money,
        description="The price of the cheapest variant (including discounts).")
    purchase_cost = graphene.Field(MoneyRange,
                                   description="Purchase cost of product.")
    margin = graphene.Field(Margin,
                            description="Range of margin percentage value.")
    is_available_for_purchase = graphene.Boolean(
        description="Whether the product is available for purchase.")
    pricing = graphene.Field(
        "saleor.graphql.product.types.products.ProductPricingInfo",
        address=graphene.Argument(
            account_types.AddressInput,
            description=
            ("Destination address used to find warehouses where stock availability "
             "for this product is checked. If address is empty, uses "
             "`Shop.companyAddress` or fallbacks to server's "
             "`settings.DEFAULT_COUNTRY` configuration."),
        ),
        description=
        ("Lists the storefront product's pricing, the current price and discounts, "
         "only meant for displaying."),
    )

    class Meta:
        description = "Represents product channel listing."
        model = models.ProductChannelListing
        interfaces = [graphene.relay.Node]
        only_fields = [
            "id",
            "channel",
            "is_published",
            "publication_date",
            "visible_in_listings",
            "available_for_purchase",
        ]

    @staticmethod
    def resolve_channel(root: models.ProductChannelListing, info, **_kwargs):
        return ChannelByIdLoader(info.context).load(root.channel_id)

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_purchase_cost(root: models.ProductChannelListing, info,
                              *_kwargs):
        channel = ChannelByIdLoader(info.context).load(root.channel_id)

        def calculate_margin_with_variants(variants):
            def calculate_margin_with_channel(channel):
                def calculate_margin_with_channel_listings(
                        variant_channel_listings):
                    variant_channel_listings = list(
                        filter(None, variant_channel_listings))
                    if not variant_channel_listings:
                        return None

                    has_variants = True if len(
                        variant_ids_channel_slug) > 0 else False
                    purchase_cost, _margin = get_product_costs_data(
                        variant_channel_listings, has_variants, root.currency)
                    return purchase_cost

                variant_ids_channel_slug = [(variant.id, channel.slug)
                                            for variant in variants]
                return (VariantChannelListingByVariantIdAndChannelSlugLoader(
                    info.context).load_many(variant_ids_channel_slug).then(
                        calculate_margin_with_channel_listings))

            return channel.then(calculate_margin_with_channel)

        return (ProductVariantsByProductIdLoader(info.context).load(
            root.product_id).then(calculate_margin_with_variants))

    @staticmethod
    @permission_required(ProductPermissions.MANAGE_PRODUCTS)
    def resolve_margin(root: models.ProductChannelListing, info, *_kwargs):
        channel = ChannelByIdLoader(info.context).load(root.channel_id)

        def calculate_margin_with_variants(variants):
            def calculate_margin_with_channel(channel):
                def calculate_margin_with_channel_listings(
                        variant_channel_listings):
                    variant_channel_listings = list(
                        filter(None, variant_channel_listings))
                    if not variant_channel_listings:
                        return None

                    has_variants = True if len(
                        variant_ids_channel_slug) > 0 else False
                    _purchase_cost, margin = get_product_costs_data(
                        variant_channel_listings, has_variants, root.currency)
                    return Margin(margin[0], margin[1])

                variant_ids_channel_slug = [(variant.id, channel.slug)
                                            for variant in variants]
                return (VariantChannelListingByVariantIdAndChannelSlugLoader(
                    info.context).load_many(variant_ids_channel_slug).then(
                        calculate_margin_with_channel_listings))

            return channel.then(calculate_margin_with_channel)

        return (ProductVariantsByProductIdLoader(info.context).load(
            root.product_id).then(calculate_margin_with_variants))

    @staticmethod
    def resolve_is_available_for_purchase(root: models.ProductChannelListing,
                                          _info):
        return root.is_available_for_purchase()

    @staticmethod
    def resolve_pricing(root: models.ProductChannelListing,
                        info,
                        address=None):
        context = info.context
        country_code = get_user_country_context(
            address, info.context.site.settings.company_address)

        def calculate_pricing_info(discounts):
            def calculate_pricing_with_channel(channel):
                def calculate_pricing_with_product(product):
                    def calculate_pricing_with_variants(variants):
                        def calculate_pricing_with_variants_channel_listings(
                            variants_channel_listing, ):
                            def calculate_pricing_with_collections(
                                    collections):
                                if not variants_channel_listing:
                                    return None
                                availability = get_product_availability(
                                    product=product,
                                    product_channel_listing=root,
                                    variants=variants,
                                    variants_channel_listing=
                                    variants_channel_listing,
                                    collections=collections,
                                    discounts=discounts,
                                    channel=channel,
                                    manager=context.plugins,
                                    country=Country(country_code),
                                    local_currency=get_currency_for_country(
                                        country_code),
                                )
                                from .products import ProductPricingInfo

                                return ProductPricingInfo(
                                    **asdict(availability))

                            return (CollectionsByProductIdLoader(context).load(
                                root.product_id).then(
                                    calculate_pricing_with_collections))

                        return (
                            VariantsChannelListingByProductIdAndChanneSlugLoader(
                                context).load((root.product_id, channel.slug)).
                            then(
                                calculate_pricing_with_variants_channel_listings
                            ))

                    return (ProductVariantsByProductIdLoader(context).load(
                        root.product_id).then(calculate_pricing_with_variants))

                return (ProductByIdLoader(context).load(
                    root.product_id).then(calculate_pricing_with_product))

            return (ChannelByIdLoader(context).load(
                root.channel_id).then(calculate_pricing_with_channel))

        return (DiscountsByDateTimeLoader(context).load(
            info.context.request_time).then(calculate_pricing_info))
Example #17
0
class ProductVariant(CountableDjangoObjectType, MetadataObjectType):
    quantity = graphene.Int(
        required=True,
        description="Quantity of a product in the store's possession, "
        "including the allocated stock that is waiting for shipment.",
        deprecation_reason="This field will be removed in Saleor 2.11. "
        "Use the stock field instead.",
    )
    quantity_allocated = graphene.Int(
        required=False,
        description="Quantity allocated for orders",
        deprecation_reason="This field will be removed in Saleor 2.11. "
        "Use the stock field instead.",
    )
    stock_quantity = graphene.Int(
        required=True,
        description="Quantity of a product available for sale.",
        deprecation_reason="This field will be removed in Saleor 2.11. "
        "Use the stock field instead.",
    )
    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="This field will be removed in Saleor 2.11. "
        "Use the stock field instead.",
    )

    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 = TranslationField(ProductVariantTranslation,
                                   type_name="product variant")
    digital_content = gql_optimizer.field(
        graphene.Field(DigitalContent,
                       description="Digital content for the product variant."),
        model_field="digital_content",
    )

    stock = gql_optimizer.field(
        graphene.Field(
            graphene.List(Stock),
            description="Stocks for the product variant.",
            country=graphene.String(required=False),
        ))

    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]
        model = models.ProductVariant

    @staticmethod
    def resolve_stock(root: models.ProductVariant, info, country=None):
        if country is None:
            return gql_optimizer.query(
                root.stock.annotate_available_quantity().all(), info)
        return gql_optimizer.query(
            root.stock.annotate_available_quantity().for_country(
                "country").all(), info)

    @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):
        country = info.context.country
        try:
            stock = stock_models.Stock.objects.get_variant_stock_for_country(
                country, root)
        except stock_models.Stock.DoesNotExist:
            return 0
        return get_available_quantity_for_customer(stock)

    @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(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
    @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(**asdict(availability))

    @staticmethod
    def resolve_is_available(root: models.ProductVariant, info):
        country = info.context.country
        return is_variant_in_stock(root, country)

    @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)

    @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, 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(ProductPermissions.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_reference(root, _info, **_kwargs):
        return graphene.Node.get_node_from_global_id(_info, root.id)
Example #18
0
class OrderLine(CountableDjangoObjectType):
    thumbnail = graphene.Field(
        Image,
        description="The main thumbnail for the ordered product.",
        size=graphene.Argument(graphene.Int, description="Size of thumbnail."),
    )
    unit_price = graphene.Field(
        TaxedMoney, description="Price of the single item in the order line.")
    total_price = graphene.Field(
        TaxedMoney,
        description="Price of the order line.",
    )
    variant = graphene.Field(
        ProductVariant,
        required=False,
        description=
        ("A purchased product variant. Note: this field may be null if the variant "
         "has been removed from stock at all."),
    )
    translated_product_name = graphene.String(
        required=True, description="Product name in the customer's language")
    translated_variant_name = graphene.String(
        required=True, description="Variant name in the customer's language")
    allocations = graphene.List(
        graphene.NonNull(Allocation),
        description="List of allocations across warehouses.",
    )

    class Meta:
        description = "Represents order line of particular order."
        model = models.OrderLine
        interfaces = [relay.Node]
        only_fields = [
            "digital_content_url",
            "id",
            "is_shipping_required",
            "product_name",
            "variant_name",
            "product_sku",
            "quantity",
            "quantity_fulfilled",
            "tax_rate",
        ]

    @staticmethod
    def resolve_thumbnail(root: models.OrderLine, info, *, size=255):
        if not root.variant:
            return None
        image = root.variant.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_unit_price(root: models.OrderLine, _info):
        return root.unit_price

    @staticmethod
    def resolve_total_price(root: models.OrderLine, _info):
        return root.total_price

    @staticmethod
    def resolve_translated_product_name(root: models.OrderLine, _info):
        return root.translated_product_name

    @staticmethod
    def resolve_translated_variant_name(root: models.OrderLine, _info):
        return root.translated_variant_name

    @staticmethod
    def resolve_variant(root: models.OrderLine, info):
        dataloader = ChannelByOrderLineIdLoader(info.context)
        return resolve_variant(info, root, dataloader)

    @staticmethod
    @one_of_permissions_required(
        [ProductPermissions.MANAGE_PRODUCTS, OrderPermissions.MANAGE_ORDERS])
    def resolve_allocations(root: models.OrderLine, info):
        return AllocationsByOrderLineIdLoader(info.context).load(root.id)
Example #19
0
class Attribute(CountableDjangoObjectType, MetadataObjectType):
    input_type = AttributeInputTypeEnum(
        description=AttributeDescriptions.INPUT_TYPE)

    name = graphene.String(description=AttributeDescriptions.NAME)
    slug = graphene.String(description=AttributeDescriptions.SLUG)

    values = gql_optimizer.field(
        graphene.List(AttributeValue,
                      description=AttributeDescriptions.VALUES),
        model_field="values",
    )

    value_required = graphene.Boolean(
        description=AttributeDescriptions.VALUE_REQUIRED, required=True)
    visible_in_storefront = graphene.Boolean(
        description=AttributeDescriptions.VISIBLE_IN_STOREFRONT, required=True)
    filterable_in_storefront = graphene.Boolean(
        description=AttributeDescriptions.FILTERABLE_IN_STOREFRONT,
        required=True)
    filterable_in_dashboard = graphene.Boolean(
        description=AttributeDescriptions.FILTERABLE_IN_DASHBOARD,
        required=True)
    available_in_grid = graphene.Boolean(
        description=AttributeDescriptions.AVAILABLE_IN_GRID, required=True)

    translation = graphene.Field(
        AttributeTranslation,
        language_code=graphene.Argument(
            LanguageCodeEnum,
            description="A language code to return the translation for.",
            required=True,
        ),
        description=("Returns translated Attribute fields "
                     "for the given language code."),
        resolver=resolve_translation,
    )

    storefront_search_position = graphene.Int(
        description=AttributeDescriptions.STOREFRONT_SEARCH_POSITION,
        required=True)

    class Meta:
        description = (
            "Custom attribute of a product. Attributes can be assigned to products and "
            "variants at the product type level.")
        only_fields = ["id", "product_types", "product_variant_types"]
        interfaces = [relay.Node]
        model = models.Attribute

    @staticmethod
    def resolve_values(root: models.Attribute, *_args):
        return root.values.all()

    @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
    @permission_required("product.manage_products")
    def resolve_value_required(root: models.Attribute, *_args):
        return root.value_required

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_visible_in_storefront(root: models.Attribute, *_args):
        return root.visible_in_storefront

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_filterable_in_storefront(root: models.Attribute, *_args):
        return root.filterable_in_storefront

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_filterable_in_dashboard(root: models.Attribute, *_args):
        return root.filterable_in_dashboard

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_storefront_search_position(root: models.Attribute, *_args):
        return root.storefront_search_position

    @staticmethod
    @permission_required("product.manage_products")
    def resolve_available_in_grid(root: models.Attribute, *_args):
        return root.available_in_grid
Example #20
0
class Query:
    workouts = graphene.List(
        WorkoutType,
        status=graphene.Argument(WorkoutStatusesEnum),
        limit=graphene.Int(required=False),
    )

    exercise_types = graphene.List(ExerciseTypeType)

    popular_exercise_types = graphene.List(ExerciseTypeType)

    exercises = graphene.List(ExerciseType,
                              workout_id=graphene.Int(required=True))

    sets = graphene.List(SetType, exercise_id=graphene.Int(required=True))

    workout = graphene.Field(WorkoutType,
                             workout_id=graphene.Int(required=True))

    exercise = graphene.Field(ExerciseType,
                              exercise_id=graphene.Int(required=True))

    muscle_groups = graphene.List(MuscleGroupType)

    @staticmethod
    def resolve_muscle_groups(_, info):
        return MuscleGroup.objects.filter(is_active=True)

    @staticmethod
    def resolve_workouts(_, info, status=None, limit=None):
        user = info.context.user

        filter_args = {"user": user, "is_active": True}

        if status:
            filter_args["status"] = status

        qs = Workout.objects.filter(**filter_args)

        if limit and limit > 0:
            qs = qs[:limit]

        return qs

    @staticmethod
    def resolve_exercise_types(_, info):
        user = info.context.user

        user_types = ExerciseTypeModel.objects.filter(user=user,
                                                      is_active=True)
        all_types = ExerciseTypeModel.objects.filter(is_active=True).exclude(
            user=user)

        return user_types | all_types

    @staticmethod
    def resolve_popular_exercise_types(_, info):
        user = info.context.user

        popular = (ExerciseTypeModel.objects.filter(is_active=True).annotate(
            num_exercises=Count("exercise")).order_by("-num_exercises")[:5])

        return popular

    @staticmethod
    def resolve_exercises(_, info, workout_id):
        user = info.context.user

        return Exercise.objects.filter(is_active=True,
                                       workout_id=workout_id,
                                       user=user)

    @staticmethod
    def resolve_sets(_, info, exercise_id):
        user = info.context.user

        return Set.objects.filter(user=user,
                                  is_active=True,
                                  exercise_id=exercise_id)

    @staticmethod
    def resolve_workout(_, info, workout_id):
        user = info.context.user

        try:
            workout = Workout.objects.get(is_active=True,
                                          id=workout_id,
                                          user=user.id)
        except Workout.DoesNotExist:
            raise GraphQLError("Workout not found.")

        return workout

    @staticmethod
    def resolve_exercise(_, info, exercise_id):
        user = info.context.user

        try:
            exercise = Exercise.objects.get(is_active=True,
                                            id=exercise_id,
                                            user=user.id)
        except Exercise.DoesNotExist:
            raise GraphQLError("Exercise not found.")

        return exercise
Example #21
0
class GraphenePartition(graphene.ObjectType):
    name = graphene.NonNull(graphene.String)
    partition_set_name = graphene.NonNull(graphene.String)
    solid_selection = graphene.List(graphene.NonNull(graphene.String))
    mode = graphene.NonNull(graphene.String)
    runConfigOrError = graphene.NonNull(GraphenePartitionRunConfigOrError)
    tagsOrError = graphene.NonNull(GraphenePartitionTagsOrError)
    runs = graphene.Field(
        non_null_list(GrapheneRun),
        filter=graphene.Argument(GrapheneRunsFilter),
        cursor=graphene.String(),
        limit=graphene.Int(),
    )
    status = graphene.Field(GrapheneRunStatus)

    class Meta:
        name = "Partition"

    def __init__(self, external_repository_handle, external_partition_set, partition_name):
        self._external_repository_handle = check.inst_param(
            external_repository_handle, "external_respository_handle", RepositoryHandle
        )
        self._external_partition_set = check.inst_param(
            external_partition_set, "external_partition_set", ExternalPartitionSet
        )
        self._partition_name = check.str_param(partition_name, "partition_name")

        super().__init__(
            name=partition_name,
            partition_set_name=external_partition_set.name,
            solid_selection=external_partition_set.solid_selection,
            mode=external_partition_set.mode,
        )

    def resolve_runConfigOrError(self, graphene_info):
        return get_partition_config(
            graphene_info,
            self._external_repository_handle,
            self._external_partition_set.name,
            self._partition_name,
        )

    def resolve_tagsOrError(self, graphene_info):
        return get_partition_tags(
            graphene_info,
            self._external_repository_handle,
            self._external_partition_set.name,
            self._partition_name,
        )

    def resolve_runs(self, graphene_info, **kwargs):
        filters = kwargs.get("filter")
        partition_tags = {
            PARTITION_SET_TAG: self._external_partition_set.name,
            PARTITION_NAME_TAG: self._partition_name,
        }
        if filters is not None:
            filters = filters.to_selector()
            runs_filter = RunsFilter(
                run_ids=filters.run_ids,
                pipeline_name=filters.job_name,
                statuses=filters.statuses,
                tags=merge_dicts(filters.tags, partition_tags),
            )
        else:
            runs_filter = RunsFilter(tags=partition_tags)

        return get_runs(
            graphene_info, runs_filter, cursor=kwargs.get("cursor"), limit=kwargs.get("limit")
        )
Example #22
0
 class Arguments:
     runId = graphene.NonNull(graphene.String)
     terminatePolicy = graphene.Argument(GrapheneTerminatePipelinePolicy)
Example #23
0
class User(CountableDjangoObjectType):
    addresses = graphene.List(Address, description="List of all user's addresses.")
    checkout = graphene.Field(
        Checkout,
        description="Returns the last open checkout of this user.",
        deprecation_reason=(
            "Use the `checkout_tokens` field to fetch the user checkouts."
        ),
    )
    checkout_tokens = graphene.List(
        graphene.NonNull(UUID),
        description="Returns the checkout UUID's assigned to this user.",
        channel=graphene.String(
            description="Slug of a channel for which the data should be returned."
        ),
    )
    gift_cards = PrefetchingConnectionField(
        "saleor.graphql.giftcard.types.GiftCard",
        description="List of the user gift cards.",
    )
    note = graphene.String(description="A note about the customer.")
    orders = PrefetchingConnectionField(
        "saleor.graphql.order.types.Order", description="List of user's orders."
    )
    # deprecated, to remove in #5389
    permissions = graphene.List(
        Permission,
        description="List of user's permissions.",
        deprecation_reason=(
            "Will be removed in Saleor 2.11." "Use the `userPermissions` instead."
        ),
    )
    user_permissions = graphene.List(
        UserPermission, description="List of user's permissions."
    )
    permission_groups = graphene.List(
        "saleor.graphql.account.types.Group",
        description="List of user's permission groups.",
    )
    editable_groups = graphene.List(
        "saleor.graphql.account.types.Group",
        description="List of user's permission groups which user can manage.",
    )
    avatar = graphene.Field(Image, size=graphene.Int(description="Size of the avatar."))
    events = graphene.List(
        CustomerEvent, description="List of events associated with the user."
    )
    stored_payment_sources = graphene.List(
        "saleor.graphql.payment.types.PaymentSource",
        description="List of stored payment sources.",
    )
    store = graphene.Field(
        Store,
        id=graphene.Argument(graphene.ID, description="ID of the store."),
        slug=graphene.Argument(graphene.String, description="Slug of the store"),
        description="Look up a category by ID or slug.",
    )

    class Meta:
        description = "Represents user data."
        interfaces = [relay.Node, ObjectWithMetadata]
        model = get_user_model()
        only_fields = [
            "date_joined",
            "default_billing_address",
            "default_shipping_address",
            "email",
            "first_name",
            "id",
            "is_active",
            "is_staff",
            "is_supplier",
            "last_login",
            "last_name",
            "note",
            "store",
        ]

    @staticmethod
    def resolve_addresses(root: models.User, _info, **_kwargs):
        return root.addresses.annotate_default(root).all()

    @staticmethod
    def resolve_checkout(root: models.User, _info, **_kwargs):
        return get_user_checkout(root)

    @staticmethod
    def resolve_checkout_tokens(root: models.User, info, channel=None, **_kwargs):
        def return_checkout_tokens(checkouts):
            if not checkouts:
                return []
            checkout_global_ids = []
            for checkout in checkouts:
                checkout_global_ids.append(checkout.token)
            return checkout_global_ids

        if not channel:
            return (
                CheckoutByUserLoader(info.context)
                .load(root.id)
                .then(return_checkout_tokens)
            )
        return (
            CheckoutByUserAndChannelLoader(info.context)
            .load((root.id, channel))
            .then(return_checkout_tokens)
        )

    @staticmethod
    def resolve_gift_cards(root: models.User, info, **_kwargs):
        return root.gift_cards.all()

    @staticmethod
    def resolve_permissions(root: models.User, _info, **_kwargs):
        # deprecated, to remove in #5389
        from .resolvers import resolve_permissions

        return resolve_permissions(root)

    @staticmethod
    def resolve_user_permissions(root: models.User, _info, **_kwargs):
        from .resolvers import resolve_permissions

        return resolve_permissions(root)

    @staticmethod
    def resolve_permission_groups(root: models.User, _info, **_kwargs):
        return root.groups.all()

    @staticmethod
    def resolve_editable_groups(root: models.User, _info, **_kwargs):
        return get_groups_which_user_can_manage(root)

    @staticmethod
    @one_of_permissions_required(
        [AccountPermissions.MANAGE_USERS, AccountPermissions.MANAGE_STAFF]
    )
    def resolve_note(root: models.User, info):
        return root.note

    @staticmethod
    @one_of_permissions_required(
        [AccountPermissions.MANAGE_USERS, AccountPermissions.MANAGE_STAFF]
    )
    def resolve_events(root: models.User, info):
        return root.events.all()

    @staticmethod
    def resolve_orders(root: models.User, info, **_kwargs):
        viewer = info.context.user
        if viewer.has_perm(OrderPermissions.MANAGE_ORDERS):
            return root.orders.all()  # type: ignore
        return root.orders.confirmed()  # type: ignore

    @staticmethod
    def resolve_avatar(root: models.User, info, size=None, **_kwargs):
        if root.avatar:
            return Image.get_adjusted(
                image=root.avatar,
                alt=None,
                size=size,
                rendition_key_set="user_avatars",
                info=info,
            )

    @staticmethod
    def resolve_stored_payment_sources(root: models.User, info):
        from .resolvers import resolve_payment_sources

        if root == info.context.user:
            return resolve_payment_sources(info, root)
        raise PermissionDenied()

    @staticmethod
    def resolve_wishlist(root: models.User, info, **_kwargs):
        return resolve_wishlist_items_from_user(root)

    @staticmethod
    def __resolve_reference(root, _info, **_kwargs):
        if root.id is not None:
            return graphene.Node.get_node_from_global_id(_info, root.id)
        return get_user_model().objects.get(email=root.email)
Example #24
0
class Token(graphene.ObjectType):
    """ self = CommunityDB Object """
    class Meta:
        description = "Representds an ERC-20 token contract in Band ecosystem, including Band native token and community tokens."

    address = graphene.String(required=True,
                              description="This token's ERC-20 address.")

    community = graphene.Field(
        lambda: community_module.Community,
        description=
        "The community of this token, in the case of community token.",
    )

    balances = graphene.List(
        lambda: graphene.NonNull(user_balance_module.UserBalance),
        filtered_by=graphene.Argument(
            lambda: user_balance_module.UserBalanceFilters),
        required=True,
        description="The list of user balances of this token.",
    )

    transfer_history = graphene.List(
        lambda: transfer_module.Transfer,
        filtered_by=graphene.Argument(lambda: transfer_module.TransferFilters),
        required=True,
        description="The list of transfers of this token.",
    )

    name = graphene.String(required=True,
                           description="The name of this token.")

    symbol = graphene.String(required=True,
                             description="The symbol of this token.")

    def resolve_address(self, info):
        contract = (db.session.query(Contract).filter(
            Contract.contract_type == "TOKEN").filter(
                Contract.community_id == self.id).one())
        return contract.address

    def resolve_community(self, info):
        if self.id == 1:
            return None
        return self

    def resolve_balances(self, info, filtered_by={}):
        if "users" in filtered_by:
            return [(address, self) for address in filtered_by["users"]]
        addresses = (db.session.query(func.distinct(
            TransferDB.receiver)).filter(
                TransferDB.receiver !=
                "0x0000000000000000000000000000000000000000").filter(
                    TransferDB.community_id == self.id).all())
        return [(address[0], self) for address in addresses]

    def resolve_transfer_history(self, info, filtered_by={}):
        return get_transfer_history(**filtered_by, tokens=[self])

    def resolve_name(self, info):
        return self.name

    def resolve_symbol(self, info):
        return self.symbol
 def get_all_votes_input_fields():
     """Return the input fields needed by allVotes."""
     return {
         'filter': graphene.Argument(VoteFilter),
     }
Example #26
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().all()
        return root.stocks.annotate_available_quantity().for_country(country_code).all()

    @staticmethod
    def resolve_quantity_available(
        root: models.ProductVariant, info, country_code=None
    ):
        return get_available_quantity_for_customer(root, 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):
        return get_available_quantity_for_customer(root, 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):
        country = info.context.country
        return is_variant_in_stock(root, country)

    @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)
 class Arguments:
     tag_data = graphene.Argument(TagCreateInput, required=True)
Example #28
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)
Example #29
0
 class Arguments:
     ballot = graphene.ID(required=True)
     role = graphene.Argument(Role, required=True)
     student = graphene.ID(required=True)
     rank = graphene.Int(required=True)
Example #30
0
class AccountQueries(graphene.ObjectType):
    address_validation_rules = graphene.Field(
        AddressValidationData,
        description="Returns address validation rules.",
        country_code=graphene.Argument(
            CountryCodeEnum,
            description="Two-letter ISO 3166-1 country code.",
            required=True,
        ),
        country_area=graphene.Argument(
            graphene.String,
            description="Designation of a region, province or state."),
        city=graphene.Argument(graphene.String,
                               description="City or a town name."),
        city_area=graphene.Argument(
            graphene.String, description="Sublocality like a district."),
    )
    address = graphene.Field(
        Address,
        id=graphene.Argument(graphene.ID,
                             description="ID of an address.",
                             required=True),
        description="Look up an address by ID.",
    )
    customers = FilterInputConnectionField(
        User,
        filter=CustomerFilterInput(
            description="Filtering options for customers."),
        sort_by=UserSortingInput(description="Sort customers."),
        description="List of the shop's customers.",
    )
    permission_groups = FilterInputConnectionField(
        Group,
        filter=PermissionGroupFilterInput(
            description="Filtering options for permission groups."),
        sort_by=PermissionGroupSortingInput(
            description="Sort permission groups."),
        description="List of permission groups.",
    )
    permission_group = graphene.Field(
        Group,
        id=graphene.Argument(graphene.ID,
                             description="ID of the group.",
                             required=True),
        description="Look up permission group by ID.",
    )
    me = graphene.Field(User,
                        description="Return the currently authenticated user.")
    staff_users = FilterInputConnectionField(
        User,
        filter=StaffUserInput(
            description="Filtering options for staff users."),
        sort_by=UserSortingInput(description="Sort staff users."),
        description="List of the shop's staff users.",
    )
    service_accounts = FilterInputConnectionField(
        ServiceAccount,
        filter=ServiceAccountFilterInput(
            description="Filtering options for service accounts."),
        sort_by=ServiceAccountSortingInput(
            description="Sort service accounts."),
        description="List of the service accounts.",
        deprecation_reason=
        ("Use the `apps` query instead. This field will be removed after 2020-07-31."
         ),
    )
    service_account = graphene.Field(
        ServiceAccount,
        id=graphene.Argument(graphene.ID,
                             description="ID of the service account.",
                             required=True),
        description="Look up a service account by ID.",
        deprecation_reason=
        ("Use the `app` query instead. This field will be removed after 2020-07-31."
         ),
    )

    user = graphene.Field(
        User,
        id=graphene.Argument(graphene.ID,
                             description="ID of the user.",
                             required=True),
        description="Look up a user by ID.",
    )

    def resolve_address_validation_rules(self,
                                         info,
                                         country_code,
                                         country_area=None,
                                         city=None,
                                         city_area=None):
        return resolve_address_validation_rules(
            info,
            country_code,
            country_area=country_area,
            city=city,
            city_area=city_area,
        )

    @permission_required(AppPermission.MANAGE_APPS)
    def resolve_service_accounts(self, info, **kwargs):
        return resolve_service_accounts(info, **kwargs)

    @permission_required(AppPermission.MANAGE_APPS)
    def resolve_service_account(self, info, id):
        return graphene.Node.get_node_from_global_id(info, id, ServiceAccount)

    @permission_required(AccountPermissions.MANAGE_USERS)
    def resolve_customers(self, info, query=None, **kwargs):
        return resolve_customers(info, query=query, **kwargs)

    @permission_required(AccountPermissions.MANAGE_STAFF)
    def resolve_permission_groups(self, info, query=None, **kwargs):
        return resolve_permission_groups(info, query=query, **kwargs)

    @permission_required(AccountPermissions.MANAGE_STAFF)
    def resolve_permission_group(self, info, id):
        return graphene.Node.get_node_from_global_id(info, id, Group)

    def resolve_me(self, info):
        user = info.context.user
        return user if user.is_authenticated else None

    @permission_required(AccountPermissions.MANAGE_STAFF)
    def resolve_staff_users(self, info, query=None, **kwargs):
        return resolve_staff_users(info, query=query, **kwargs)

    @one_of_permissions_required(
        [AccountPermissions.MANAGE_STAFF, AccountPermissions.MANAGE_USERS])
    def resolve_user(self, info, id):
        return resolve_user(info, id)

    def resolve_address(self, info, id):
        return resolve_address(info, id)