using AyCode.Core.Loggers; using AyCode.Entities; using FruitBank.Common.Dtos; using Mango.Nop.Core.Loggers; using Nop.Core; using Nop.Core.Caching; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Customers; using Nop.Core.Domain.Directory; using Nop.Core.Domain.Discounts; using Nop.Core.Domain.Orders; using Nop.Core.Domain.Stores; using Nop.Data; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Services.Catalog; using Nop.Services.Customers; using Nop.Services.Directory; using Nop.Services.Discounts; using Nop.Services.Localization; namespace Nop.Plugin.Misc.FruitBankPlugin.Services; public class CustomPriceCalculationService : PriceCalculationService { private FruitBankDbContext _dbContext; private readonly IProductAttributeService _productAttributeService; private readonly ISpecificationAttributeService _specificationAttributeService; private readonly ILocalizationService _localizationService; private ILogger _logger; public CustomPriceCalculationService( FruitBankDbContext dbContext, // inject all base deps CatalogSettings catalogSettings, CurrencySettings currencySettings, ICategoryService categoryService, ICurrencyService currencyService, IManufacturerService manufacturerService, IProductAttributeParser productAttributeParser, IProductAttributeService productAttributeService, ISpecificationAttributeService specificationAttributeService, IProductService productService, ICustomerService customerService, IDiscountService discountService, IDiscountPluginManager discountPluginManager, ILocalizationService localizationService, IStaticCacheManager cacheManager, IWorkContext workContext, IEnumerable logWriters) : base(catalogSettings, currencySettings, categoryService, currencyService, customerService, discountService, manufacturerService, productAttributeParser, productService, cacheManager) { _logger = new Logger(logWriters.ToArray()); _dbContext = dbContext; // assign all base deps to local private vars if needed _productAttributeService = productAttributeService; _specificationAttributeService = specificationAttributeService; _localizationService = localizationService; } public decimal CalculateOrderItemFinalPrice(OrderItemDto orderItemDto, decimal unitPrice, int quantity) => decimal.Round(unitPrice * (orderItemDto.IsMeasurable ? (decimal)orderItemDto.NetWeight : quantity), 0); public async Task CheckAndUpdateOrderItemFinalPricesAsync(OrderItem orderItem) { var orderItemDto = await _dbContext.OrderItemDtos.GetByIdAsync(orderItem.Id, true); return await CheckAndUpdateOrderItemFinalPricesAsync(orderItem, orderItemDto); } public async Task CheckAndUpdateOrderItemFinalPricesAsync(OrderItemDto orderItemDto) { var orderItem = await _dbContext.OrderItems.GetByIdAsync(orderItemDto.Id); return await CheckAndUpdateOrderItemFinalPricesAsync(orderItem, orderItemDto); } public async Task CheckAndUpdateOrderItemFinalPricesAsync(OrderItem orderItem, OrderItemDto orderItemDto) { _logger.Info($"CustomPriceCalculationService->CheckAndUpdateOrderItemFinalPricesAsync; orderItem.Id: {orderItem.Id}"); var finalPriceInclTax = CalculateOrderItemFinalPrice(orderItemDto, orderItem.UnitPriceInclTax, orderItem.Quantity); var finalPriceExclTax = CalculateOrderItemFinalPrice(orderItemDto, orderItem.UnitPriceExclTax, orderItem.Quantity); if (orderItem.PriceInclTax == finalPriceInclTax && orderItem.PriceExclTax == finalPriceExclTax) return false; _logger.Error($"CustomPriceCalculationService->CheckAndUpdateOrderItemFinalPricesAsync; " + $"orderItem.PriceInclTax({orderItem.PriceInclTax}) != finalPriceInclTax({finalPriceInclTax}) || " + $"orderItem.PriceExclTax({orderItem.PriceExclTax}) != finalPriceExclTax({finalPriceExclTax})"); orderItem.PriceInclTax = finalPriceInclTax; orderItem.PriceExclTax = finalPriceExclTax; await _dbContext.OrderItems.UpdateAsync(orderItem, false); return true; } public async Task CheckAndUpdateOrderTotalPrice(Order order) { var prevOrderTotal = order.OrderTotal; var orderItemDtos = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id).ToListAsync(); order.OrderTotal = 0; foreach (var itemDto in orderItemDtos) { await CheckAndUpdateOrderItemFinalPricesAsync(itemDto); order.OrderTotal += itemDto.PriceInclTax; } if (order.OrderTotal == prevOrderTotal) return; _logger.Error($"HandleEventAsync->CheckAndUpdateOrderItemFinalPrices; order.OrderTotal({order.OrderTotal}) == prevOrderTotal({prevOrderTotal})"); order.OrderSubtotalInclTax = order.OrderTotal; order.OrderSubtotalExclTax = order.OrderTotal; order.OrderSubTotalDiscountInclTax = order.OrderTotal; order.OrderSubTotalDiscountExclTax = order.OrderTotal; await _dbContext.Orders.UpdateAsync(order); } //public override async Task<(decimal priceWithoutDiscounts, decimal finalPrice, decimal appliedDiscountAmount, List appliedDiscounts)> GetFinalPriceAsync( // Product product, Customer customer, Store store, decimal? overriddenProductPrice, decimal additionalCharge = 0, bool includeDiscounts = true, // int quantity = 1, DateTime? rentalStartDate = null, DateTime? rentalEndDate = null) public override async Task<(decimal priceWithoutDiscounts, decimal finalPrice, decimal appliedDiscountAmount, List appliedDiscounts)> GetFinalPriceAsync (Product product, Customer customer, Store store, decimal? overriddenProductPrice, decimal additionalCharge, bool includeDiscounts, int quantity, DateTime? rentalStartDate, DateTime? rentalEndDate) { var productDto = await _dbContext.ProductDtos.GetByIdAsync(product.Id, true); if (productDto.IsMeasurable) { return (0, 0, 0m, []); //return (overriddenProductPrice.GetValueOrDefault(0), overriddenProductPrice.GetValueOrDefault(0), 0m, []); } //var productAttributeMappings = await _specificationAttributeService.GetProductSpecificationAttributesAsync(product.Id); ////Product Attributes //foreach (var pam in productAttributeMappings) //{ // //get option // var attributeOtion = await _specificationAttributeService.GetSpecificationAttributeOptionByIdAsync(pam.SpecificationAttributeOptionId); // //get attribute // var attribute = await _specificationAttributeService.GetSpecificationAttributeByIdAsync(attributeOtion.SpecificationAttributeId); // // you can check for specific attribute by its name or id // if (attribute.Name == "Needs to be measured for price") // { // return (0m, 0m, 0m, []); // } //} return await base.GetFinalPriceAsync(product, customer, store, overriddenProductPrice, additionalCharge, includeDiscounts, quantity, rentalStartDate, rentalEndDate); } }