Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/Services/CustomPriceCalculationServi...

185 lines
8.4 KiB
C#

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<IAcLogWriterBase> logWriters)
: base(catalogSettings, currencySettings, categoryService, currencyService, customerService, discountService, manufacturerService,
productAttributeParser, productService,
cacheManager)
{
_logger = new Logger<CustomPriceCalculationService>(logWriters.ToArray());
_dbContext = dbContext;
// assign all base deps to local private vars if needed
_productAttributeService = productAttributeService;
_specificationAttributeService = specificationAttributeService;
_localizationService = localizationService;
}
public static decimal CalculateOrderItemFinalPrice(bool isMeasurable, decimal unitPrice, int quantity, double netWeight)
=> decimal.Round(unitPrice * (isMeasurable ? (decimal)netWeight: quantity), 0);
private static (decimal finalPriceInclTax, decimal finalPriceExclTax) CalculateOrderItemFinalPrices(int quantity, decimal unitPriceInclTax, decimal unitPriceExclTax, bool isMeasurable, double netWeight)
{
var finalPriceInclTax = CalculateOrderItemFinalPrice(isMeasurable, unitPriceInclTax, quantity, netWeight);
var finalPriceExclTax = CalculateOrderItemFinalPrice(isMeasurable, unitPriceExclTax, quantity, netWeight);
return (finalPriceInclTax, finalPriceExclTax);
}
public async Task<bool> CheckAndUpdateOrderItemFinalPricesAsync(OrderItem orderItem, OrderItemDto? orderItemDtoHelper = null)
{
orderItemDtoHelper ??= await _dbContext.OrderItemDtos.GetByIdAsync(orderItem.Id, true);
return await CheckAndUpdateOrderItemFinalPricesAsync(orderItem, orderItemDtoHelper.IsMeasurable, orderItemDtoHelper.NetWeight);
}
//public async Task<bool> CheckAndUpdateOrderItemFinalPricesAsync(OrderItemDto orderItemDto)
//{
// var orderItem = await _dbContext.OrderItems.GetByIdAsync(orderItemDto.Id);
// return await CheckAndUpdateOrderItemFinalPricesAsync(orderItem, orderItemDto.IsMeasurable, orderItemDto.NetWeight);
//}
/// <summary>
///
/// </summary>
/// <param name="orderItem"></param>
/// <param name="isMeasurable"></param>
/// /// <param name="netWeight"></param>
/// <returns>true if has changes</returns>
public async Task<bool> CheckAndUpdateOrderItemFinalPricesAsync(OrderItem orderItem, bool isMeasurable, double netWeight)
{
_logger.Info($"orderItem.Id: {orderItem.Id}");
var finalPrices = CalculateOrderItemFinalPrices(orderItem.Quantity, orderItem.UnitPriceInclTax, orderItem.UnitPriceExclTax, isMeasurable, netWeight);
if (finalPrices.finalPriceInclTax == orderItem.PriceInclTax && finalPrices.finalPriceExclTax == orderItem.PriceExclTax) return false;
_logger.Info($"orderItem.PriceInclTax({orderItem.PriceInclTax}) != finalPriceInclTax({finalPrices.finalPriceInclTax}) || " +
$"orderItem.PriceExclTax({orderItem.PriceExclTax}) != finalPriceExclTax({finalPrices.finalPriceExclTax})");
orderItem.PriceInclTax = finalPrices.finalPriceInclTax;
orderItem.PriceExclTax = finalPrices.finalPriceExclTax;
await _dbContext.OrderItems.UpdateAsync(orderItem, false);
return true;
}
/// <summary>
///
/// </summary>
/// <param name="order"></param>
/// <returns>true if has changes</returns>
public async Task<bool> CheckAndUpdateOrderTotalPrice(Order order)
{
var prevOrderTotal = order.OrderTotal;
var orderItemDtosById = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id).ToDictionaryAsync(k => k.Id, v => v);
var orderItems = await _dbContext.OrderItems.GetByIdsAsync(orderItemDtosById.Keys.ToList());
order.OrderTotal = 0;
foreach (var orderItem in orderItems)
{
var orderItemDto = orderItemDtosById[orderItem.Id];
await CheckAndUpdateOrderItemFinalPricesAsync(orderItem, orderItemDto.IsMeasurable, orderItemDto.NetWeight);
order.OrderTotal += orderItem.PriceInclTax;
}
if (order.OrderTotal == prevOrderTotal) return false;
_logger.Info($"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, false);
return true;
}
//public override async Task<(decimal priceWithoutDiscounts, decimal finalPrice, decimal appliedDiscountAmount, List<Discount> 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<Discount> 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);
var finalPrice = await base.GetFinalPriceAsync(product, customer, store, overriddenProductPrice, additionalCharge, includeDiscounts, quantity, rentalStartDate, rentalEndDate);
if (productDto.IsMeasurable)
{
//finalPrice.priceWithoutDiscounts = 0;
//return (0, finalPrice.finalPrice, finalPrice.appliedDiscountAmount, []);
return finalPrice;
//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 finalPrice;
}
}