def handle_cross_sell_post_save(sender, instance, **kwargs):
    shop_ids = list(
        ShopProduct.objects.filter(
            product__in=[instance.product1, instance.product2]).values_list(
                "shop", flat=True).distinct())
    for shop_id in shop_ids:
        context_cache.bump_cache_for_item(
            cache_utils.get_cross_sells_cache_item(shop_id))
Exemplo n.º 2
0
def handle_cross_sell_post_save(sender, instance, **kwargs):
    shop_ids = list(
        ShopProduct.objects.filter(
            product__in=[instance.product1, instance.product2]
        ).values_list("shop", flat=True).distinct()
    )
    for shop_id in shop_ids:
        context_cache.bump_cache_for_item(cache_utils.get_cross_sells_cache_item(shop_id))
    def handle(self, *args, **options):
        # Clear all existing ProductCrossSell objects
        ProductCrossSell.objects.filter(type=ProductCrossSellType.BOUGHT_WITH).delete()

        # Handle all ordered products
        ordered_product_ids = OrderLine.objects.filter(
            type=OrderLineType.PRODUCT).values_list("product_id", flat=True).distinct()
        for product_id in ordered_product_ids.distinct():
            add_bought_with_relations_for_product(product_id)

        for shop in Shop.objects.all():
            context_cache.bump_cache_for_item(cache_utils.get_cross_sells_cache_item(shop))
Exemplo n.º 4
0
def get_product_cross_sells(context,
                            product,
                            relation_type=ProductCrossSellType.RELATED,
                            count=4,
                            orderable_only=True):
    request = context["request"]

    key, products = context_cache.get_cached_value(
        identifier="product_cross_sells",
        item=cache_utils.get_cross_sells_cache_item(request.shop),
        context=request,
        product=product,
        relation_type=relation_type,
        count=count,
        orderable_only=orderable_only)

    if products is not None:
        return products

    rtype = map_relation_type(relation_type)
    related_product_ids = list((ProductCrossSell.objects.filter(
        product1=product,
        type=rtype).order_by("weight")[:(count * 4)]).values_list(
            "product2_id", flat=True))

    related_products = []
    for product in Product.objects.filter(id__in=related_product_ids):
        try:
            shop_product = product.get_shop_instance(request.shop,
                                                     allow_cache=True)
        except ShopProduct.DoesNotExist:
            continue
        if orderable_only:
            for supplier in Supplier.objects.enabled():
                if shop_product.is_orderable(
                        supplier,
                        request.customer,
                        shop_product.minimum_purchase_quantity,
                        allow_cache=True):
                    related_products.append(product)
                    break
        elif shop_product.is_visible(request.customer):
            related_products.append(product)

    # Order related products by weight. Related product ids is in weight order.
    # If same related product is linked twice to product then lowest weight stands.
    related_products.sort(
        key=lambda prod: list(related_product_ids).index(prod.id))
    products = related_products[:count]
    context_cache.set_cached_value(
        key, products, settings.SHUUP_TEMPLATE_HELPERS_CACHE_DURATION)
    return products
Exemplo n.º 5
0
def get_product_cross_sells(
        context, product, relation_type=ProductCrossSellType.RELATED,
        count=4, orderable_only=True):
    request = context["request"]

    key, products = context_cache.get_cached_value(
        identifier="product_cross_sells",
        item=cache_utils.get_cross_sells_cache_item(request.shop),
        context=request,
        product=product,
        relation_type=relation_type,
        count=count,
        orderable_only=orderable_only
    )

    if products is not None:
        return products

    rtype = map_relation_type(relation_type)
    related_product_ids = list((
        ProductCrossSell.objects
        .filter(product1=product, type=rtype)
        .order_by("weight")[:(count * 4)]).values_list("product2_id", flat=True)
    )

    related_products = []
    for product in Product.objects.filter(id__in=related_product_ids):
        try:
            shop_product = product.get_shop_instance(request.shop, allow_cache=True)
        except ShopProduct.DoesNotExist:
            continue
        if orderable_only:
            for supplier in Supplier.objects.enabled():
                if shop_product.is_orderable(
                        supplier, request.customer, shop_product.minimum_purchase_quantity, allow_cache=True):
                    related_products.append(product)
                    break
        elif shop_product.is_visible(request.customer):
            related_products.append(product)

    # Order related products by weight. Related product ids is in weight order.
    # If same related product is linked twice to product then lowest weight stands.
    related_products.sort(key=lambda prod: list(related_product_ids).index(prod.id))
    products = related_products[:count]
    context_cache.set_cached_value(key, products, settings.SHUUP_TEMPLATE_HELPERS_CACHE_DURATION)
    return products
Exemplo n.º 6
0
def get_product_cross_sells(
        context, product, relation_type=ProductCrossSellType.RELATED,
        count=4, orderable_only=True, use_variation_parents=False):
    request = context["request"]

    key, products = context_cache.get_cached_value(
        identifier="product_cross_sells",
        item=cache_utils.get_cross_sells_cache_item(request.shop),
        context=request,
        product=product,
        relation_type=relation_type,
        count=count,
        orderable_only=orderable_only,
        use_variation_parents=use_variation_parents
    )

    if products is not None:
        return products

    rtype = map_relation_type(relation_type)

    # if this product is parent, then use all children instead
    if product.mode in [ProductMode.VARIABLE_VARIATION_PARENT, ProductMode.SIMPLE_VARIATION_PARENT]:
        cross_sell_products = ProductCrossSell.objects.filter(
            product1__in=product.variation_children.all(),
            type=rtype
        )
    else:
        cross_sell_products = ProductCrossSell.objects.filter(product1=product, type=rtype)

    related_product_ids = list(
        cross_sell_products.order_by("weight")[:(count * 4)].values_list("product2_id", flat=True)
    )

    sorted_related_products = []
    for product in Product.objects.filter(id__in=related_product_ids):
        sort_order = related_product_ids.index(product.pk)

        # use the variation parent when configured
        if use_variation_parents and product.variation_parent:
            product = product.variation_parent

        try:
            shop_product = product.get_shop_instance(request.shop, allow_cache=True)
        except ShopProduct.DoesNotExist:
            continue
        if orderable_only:
            for supplier in Supplier.objects.enabled():
                if shop_product.is_orderable(
                        supplier, request.customer, shop_product.minimum_purchase_quantity, allow_cache=True):
                    sorted_related_products.append((sort_order, product))
                    break
        elif shop_product.is_visible(request.customer):
            sorted_related_products.append((sort_order, product))

    # Order related products by weight. Related product ids is in weight order.
    # If same related product is linked twice to product then lowest weight stands.
    sorted_related_products.sort(key=lambda pair: pair[0])
    products = []

    for sort_order, product in sorted_related_products[:count]:
        if product not in products:
            products.append(product)

    context_cache.set_cached_value(key, products, settings.SHUUP_TEMPLATE_HELPERS_CACHE_DURATION)
    return products