Ejemplo n.º 1
0
def get_best_selling_products(context,
                              n_products=12,
                              cutoff_days=30,
                              orderable_only=True):
    request = context["request"]
    data = get_best_selling_product_info(shop_ids=[request.shop.pk],
                                         cutoff_days=cutoff_days)
    product_ids = [d[0] for d in data][:n_products]

    products = []
    if orderable_only:
        # get suppliers for later use
        suppliers = Supplier.objects.all()
    for product in Product.objects.filter(id__in=product_ids):
        shop_product = product.get_shop_instance(request.shop)
        if orderable_only:
            for supplier in suppliers:
                if shop_product.is_orderable(
                        supplier, request.customer,
                        shop_product.minimum_purchase_quantity):
                    products.append(product)
                    break
        elif shop_product.is_visible(request.customer):
            products.append(product)
    products = cache_product_things(request, products)
    products = sorted(
        products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 2
0
    def best_selling(self, request):
        """
        Returns the top 20 (default) best selling products.
        To change the number of products, set the `limit` query param.
        """
        limit = int(parse_decimal_string(request.query_params.get("limit",
                                                                  20)))
        best_selling_products = get_best_selling_product_info(
            shop_ids=[request.shop.pk])
        combined_variation_products = defaultdict(int)

        for product_id, parent_id, qty in best_selling_products:
            if parent_id:
                combined_variation_products[parent_id] += qty
            else:
                combined_variation_products[product_id] += qty

        # take here the top `limit` records, because the filter_queryset below can mess with our work
        product_ids = [
            d[0] for d in sorted(six.iteritems(combined_variation_products),
                                 key=lambda i: i[1],
                                 reverse=True)[:limit]
        ]

        products_qs = Product.objects.filter(id__in=product_ids)
        products_qs = self.filter_queryset(products_qs).distinct()
        serializer = ProductSerializer(products_qs,
                                       many=True,
                                       context={"request": request})
        return Response(serializer.data)
Ejemplo n.º 3
0
def _get_best_selling_products(cutoff_days, n_products, orderable_only, request):  # noqa (C901)
    data = get_best_selling_product_info(
        shop_ids=[request.shop.pk],
        cutoff_days=cutoff_days
    )
    combined_variation_products = defaultdict(int)
    for product_id, parent_id, qty in data:
        if parent_id:
            combined_variation_products[parent_id] += qty
        else:
            combined_variation_products[product_id] += qty
    product_ids = [
        d[0] for
        d in sorted(six.iteritems(combined_variation_products), key=lambda i: i[1], reverse=True)
    ][:n_products]
    products = []
    if orderable_only:
        # get suppliers for later use
        suppliers = Supplier.objects.filter(shops__in=[request.shop])
    for product in Product.objects.filter(id__in=product_ids):
        try:
            shop_product = product.get_shop_instance(request.shop, allow_cache=True)
        except ShopProduct.DoesNotExist:
            continue
        if orderable_only:
            for supplier in suppliers:
                if shop_product.is_orderable(supplier, request.customer, shop_product.minimum_purchase_quantity):
                    products.append(product)
                    break
        elif shop_product.is_visible(request.customer):
            products.append(product)
    products = cache_product_things(request, products)
    products = sorted(products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 4
0
def _get_best_selling_products(cutoff_days, n_products, orderable_only, request, supplier=None):
    data = get_best_selling_product_info(
        shop_ids=[request.shop.pk],
        cutoff_days=cutoff_days,
        supplier=supplier,
        orderable_only=orderable_only,
        quantity=n_products,
    )
    sorted_product_ids = sorted(data, key=lambda item: item[1], reverse=True)
    product_ids = [item[0] for item in sorted_product_ids]

    catalog = ProductCatalog(
        ProductCatalogContext(
            shop=request.shop,
            user=getattr(request, "user", None),
            supplier=supplier,
            contact=getattr(request, "customer", None),
            purchasable_only=orderable_only,
            visibility=ShopProductVisibility.LISTED,
        )
    )
    valid_products_qs = (
        catalog.get_products_queryset()
        .filter(id__in=product_ids, mode__in=ProductMode.get_parent_modes())
        .distinct()[:n_products]
    )

    products = cache_product_things(request, valid_products_qs)
    # order products by the best selling order
    products = sorted(products, key=lambda product: product_ids.index(product.pk))
    return products
Ejemplo n.º 5
0
def get_best_selling_products(context, n_products=12, cutoff_days=30, orderable_only=True):
    request = context["request"]
    data = get_best_selling_product_info(
        shop_ids=[request.shop.pk],
        cutoff_days=cutoff_days
    )
    combined_variation_products = defaultdict(int)
    for product_id, parent_id, qty in data:
        if parent_id:
            combined_variation_products[parent_id] += qty
        else:
            combined_variation_products[product_id] += qty
    product_ids = [
        d[0] for d in sorted(six.iteritems(combined_variation_products), key=lambda i: i[1], reverse=True)][:n_products]
    products = []
    if orderable_only:
        # get suppliers for later use
        suppliers = Supplier.objects.all()
    for product in Product.objects.filter(id__in=product_ids):
        shop_product = product.get_shop_instance(request.shop)
        if orderable_only:
            for supplier in suppliers:
                if shop_product.is_orderable(supplier, request.customer, shop_product.minimum_purchase_quantity):
                    products.append(product)
                    break
        elif shop_product.is_visible(request.customer):
            products.append(product)
    products = cache_product_things(request, products)
    products = sorted(products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 6
0
def _get_best_selling_products(cutoff_days, n_products, orderable_only,
                               request):  # noqa (C901)
    data = get_best_selling_product_info(shop_ids=[request.shop.pk],
                                         cutoff_days=cutoff_days)
    combined_variation_products = defaultdict(int)
    for product_id, parent_id, qty in data:
        if parent_id:
            combined_variation_products[parent_id] += qty
        else:
            combined_variation_products[product_id] += qty

    # get all the product ids
    product_ids = [
        d[0] for d in sorted(six.iteritems(combined_variation_products),
                             key=lambda i: i[1],
                             reverse=True)
    ]

    # group product ids in groups of n_products
    # to prevent querying ALL products at once
    products = []
    for grouped_product_ids in _group_list_items(product_ids, n_products):
        valid_products_qs = Product.objects.listed(
            shop=request.shop, customer=request.customer).filter(
                id__in=grouped_product_ids,
                shop_products__shop=request.shop,
                shop_products__suppliers__enabled=True)
        for product in valid_products_qs.iterator():
            products.append(product)

            if len(products) == n_products:
                break

        if len(products) == n_products:
            break

    if orderable_only:
        valid_products = []
        suppliers = Supplier.objects.enabled().filter(shops=request.shop)

        for product in products:
            # this instance should always exist as the listed() queryset uses the current shop as a filter
            shop_product = product.get_shop_instance(request.shop,
                                                     allow_cache=True)

            for supplier in suppliers:
                if shop_product.is_orderable(
                        supplier, request.customer,
                        shop_product.minimum_purchase_quantity):
                    valid_products.append(product)
                    break

        products = valid_products

    products = cache_product_things(request, products)
    products = sorted(
        products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 7
0
def _get_best_selling_products(cutoff_days, n_products, orderable_only, request, sale_items_only):  # noqa (C901)
    data = get_best_selling_product_info(
        shop_ids=[request.shop.pk],
        cutoff_days=cutoff_days
    )
    combined_variation_products = defaultdict(int)
    for product_id, parent_id, qty in data:
        if parent_id:
            combined_variation_products[parent_id] += qty
        else:
            combined_variation_products[product_id] += qty

    # get all the product ids
    product_ids = [
        d[0] for
        d in sorted(six.iteritems(combined_variation_products), key=lambda i: i[1], reverse=True)
    ]

    products = []
    suppliers = []
    if orderable_only:
        # get suppliers for later use
        suppliers = Supplier.objects.enabled().filter(shops__in=[request.shop])

    if sale_items_only:
        from shuup.core.pricing import PricingContext
        pricing_context = PricingContext(shop=request.shop, customer=request.customer)

    # group product ids in groups of n_products
    # to prevent querying ALL products at once
    for grouped_product_ids in _group_list_items(product_ids, n_products):
        for product in Product.objects.filter(id__in=grouped_product_ids):
            if len(products) == n_products:
                break

            if sale_items_only and not _is_sale_item(product, pricing_context):
                continue

            try:
                shop_product = product.get_shop_instance(request.shop, allow_cache=True)
            except ShopProduct.DoesNotExist:
                continue

            if orderable_only:
                for supplier in suppliers:
                    if shop_product.is_orderable(supplier, request.customer, shop_product.minimum_purchase_quantity):
                        products.append(product)
                        break

            elif shop_product.is_visible(request.customer):
                products.append(product)

        if len(products) == n_products:
            break

    products = cache_product_things(request, products)
    products = sorted(products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 8
0
def _get_best_selling_products(cutoff_days, n_products, orderable_only, request):  # noqa (C901)
    data = get_best_selling_product_info(
        shop_ids=[request.shop.pk],
        cutoff_days=cutoff_days
    )
    combined_variation_products = defaultdict(int)
    for product_id, parent_id, qty in data:
        if parent_id:
            combined_variation_products[parent_id] += qty
        else:
            combined_variation_products[product_id] += qty

    # get all the product ids
    product_ids = [
        d[0] for
        d in sorted(six.iteritems(combined_variation_products), key=lambda i: i[1], reverse=True)
    ]

    # group product ids in groups of n_products
    # to prevent querying ALL products at once
    products = []
    for grouped_product_ids in _group_list_items(product_ids, n_products):
        valid_products_qs = Product.objects.listed(
            shop=request.shop,
            customer=request.customer
        ).filter(
            id__in=grouped_product_ids,
            shop_products__shop=request.shop,
            shop_products__suppliers__enabled=True
        )
        for product in valid_products_qs.iterator():
            products.append(product)

            if len(products) == n_products:
                break

        if len(products) == n_products:
            break

    if orderable_only:
        valid_products = []
        suppliers = Supplier.objects.enabled().filter(shops=request.shop)

        for product in products:
            # this instance should always exist as the listed() queryset uses the current shop as a filter
            shop_product = product.get_shop_instance(request.shop, allow_cache=True)

            for supplier in suppliers:
                if shop_product.is_orderable(supplier, request.customer, shop_product.minimum_purchase_quantity):
                    valid_products.append(product)
                    break

        products = valid_products

    products = cache_product_things(request, products)
    products = sorted(products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 9
0
def get_best_selling_products(context, n_products=12, cutoff_days=30, orderable_only=True):
    request = context["request"]
    data = get_best_selling_product_info(
        shop_ids=[request.shop.pk],
        cutoff_days=cutoff_days
    )
    product_ids = [d[0] for d in data][:n_products]

    products = []
    for product in Product.objects.filter(id__in=product_ids):
        shop_product = product.get_shop_instance(request.shop)
        if orderable_only:
            for supplier in Supplier.objects.all():
                if shop_product.is_orderable(supplier, request.customer, shop_product.minimum_purchase_quantity):
                    products.append(product)
                    break
        elif shop_product.is_visible(request.customer):
            products.append(product)
    products = cache_product_things(request, products)
    products = sorted(products, key=lambda p: product_ids.index(p.id))  # pragma: no branch
    return products
Ejemplo n.º 10
0
    def best_selling(self, request):
        """
        Returns the top 20 (default) best selling products.
        To change the number of products, set the `limit` query param.
        """
        limit = int(parse_decimal_string(request.query_params.get("limit", 20)))
        best_selling_products = get_best_selling_product_info(shop_ids=[request.shop.pk])
        combined_variation_products = defaultdict(int)

        for product_id, parent_id, qty in best_selling_products:
            if parent_id:
                combined_variation_products[parent_id] += qty
            else:
                combined_variation_products[product_id] += qty

        # take here the top `limit` records, because the filter_queryset below can mess with our work
        product_ids = [
            d[0] for d in sorted(six.iteritems(combined_variation_products), key=lambda i: i[1], reverse=True)[:limit]
        ]

        products_qs = Product.objects.filter(id__in=product_ids)
        products_qs = self.filter_queryset(products_qs).distinct()
        serializer = ProductSerializer(products_qs, many=True, context={"request": request})
        return Response(serializer.data)