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