/// <summary> /// Gets the final price for a child product by running a nested calculation pipeline. /// </summary> /// <param name="childProduct"> /// The child product (e.g. associated product of a grouped product or a bundle item part) to calculate price for. /// Must not be the same product as <see cref="PriceCalculationContext.Product"/>. /// </param> /// <param name="context">The calculator context of the root pipeline.</param> /// <param name="childContextConfigurer">An optional configurer action for the child context.</param> /// <returns>The nested calculator context.</returns> protected async Task <CalculatorContext> CalculateChildPriceAsync(Product childProduct, CalculatorContext context, Action <CalculatorContext> childContextConfigurer = null) { if (context.Product == childProduct) { throw new InvalidOperationException("The product of a nested calculation pipeline cannot be the same as that of the root pipeline. It would result in a deadlock."); } var childCalculatorContext = new CalculatorContext(context, childProduct.Price) { Product = childProduct }; childContextConfigurer?.Invoke(childCalculatorContext); // INFO: we know that options have been cloned. if (context.Options.ChildProductsBatchContext != null) { childCalculatorContext.Options.BatchContext = context.Options.ChildProductsBatchContext; } // Get calculators for child product context var calculators = _calculatorFactory.GetCalculators(childCalculatorContext); // Run calculators await _calculatorFactory.RunCalculators(calculators, childCalculatorContext); return(childCalculatorContext); }
/// <summary> /// Gets the final price for a child product by running a nested calculation pipeline. /// </summary> /// <param name="childProduct"> /// The child product (e.g. associated product of a grouped product or a bundle item part) to calculate price for. /// </param> /// <param name="context">The calculator context of the root pipeline.</param> /// <param name="childContextConfigurer">An optional configurer action for the child context.</param> /// <returns>The nested calculator context.</returns> protected async Task <CalculatorContext> CalculateChildPriceAsync(Product childProduct, CalculatorContext context, Action <CalculatorContext> childContextConfigurer = null) { if (context.Product == childProduct) { // TODO: (core) Decent error message for price calculation deadlocking. throw new InvalidOperationException("Deadlock"); } var childCalculatorContext = new CalculatorContext(context, childProduct.Price) { Product = childProduct }; childContextConfigurer?.Invoke(childCalculatorContext); // INFO: we know that options have been cloned. if (context.Options.ChildProductsBatchContext != null) { childCalculatorContext.Options.BatchContext = context.Options.ChildProductsBatchContext; } // Get calculators for child product context var calculators = _calculatorFactory.GetCalculators(childCalculatorContext); // Run calculators await _calculatorFactory.RunCalculators(calculators, childCalculatorContext); return(childCalculatorContext); }
/// <summary> /// Gets the final price for a child product by running a nested calculation pipeline. /// </summary> /// <returns>The nested calculator context.</returns> protected async Task <CalculatorContext> CalculateChildPriceAsync(Product childProduct, CalculatorContext context) { if (context.Product == childProduct) { // TODO: (core) Decent error message for price calculation deadlocking. throw new InvalidOperationException("Deadlock"); } var childCalculatorContext = new CalculatorContext(context, childProduct.Price) { Product = childProduct, Quantity = int.MaxValue }; // INFO: we know that options have been cloned. childCalculatorContext.Options.BatchContext = context.Options.ChildProductsBatchContext; childCalculatorContext.Options.IgnoreGroupedProducts = true; childCalculatorContext.Options.IgnoreBundles = true; // Get calculators for child product context var calculators = _calculatorFactory.GetCalculators(childCalculatorContext); // Run calculators await _calculatorFactory.RunCalculators(calculators, childCalculatorContext); return(childCalculatorContext); }
private async Task <CalculatorContext> RunCalculators(PriceCalculationContext context) { Guard.NotNull(context, nameof(context)); // Remember source product. var product = context.Product; // Collect calculators var calculators = _calculatorFactory.GetCalculators(context); var calculatorContext = new CalculatorContext(context, product.Price); // Run all collected calculators await _calculatorFactory.RunCalculators(calculators, calculatorContext); return(calculatorContext); }