#nullable enable using AyCode.Core.Loggers; using AyCode.Utils.Extensions; using FruitBank.Common.Entities; using FruitBank.Common.Interfaces; using FruitBank.Common.Models; using Mango.Nop.Core.Repositories; using Nop.Core; using Nop.Core.Caching; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Customers; using Nop.Data; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces; using Nop.Plugin.Misc.FruitBankPlugin.Services; using Nop.Services.Catalog; using FruitBank.Common.Dtos; using Mango.Nop.Core.Extensions; using Nop.Core.Domain.Orders; namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; public class FruitBankDbContext : MgDbContextBase, IOrderDtoDbSet, IOrderItemDtoDbSet, IPartnerDbSet, IShippingDbSet, IShippingDocumentDbSet, IShippingItemDbSet, IShippingItemPalletDbSet, IOrderItemPalletDbSet, IShippingDocumentToFilesDbSet, IFilesDbSet { private readonly FruitBankAttributeService _fruitBankAttributeService; private readonly IStoreContext _storeContext; private readonly IProductService _productService; private readonly IStaticCacheManager _staticCacheManager; public ProductDtoDbTable ProductDtos { get; set; } public OrderDtoDbTable OrderDtos { get; set; } public OrderItemDtoDbTable OrderItemDtos { get; set; } public PartnerDbTable Partners { get; set; } public ShippingDbTable Shippings { get; set; } public ShippingDocumentDbTable ShippingDocuments { get; set; } public ShippingItemDbTable ShippingItems { get; set; } public ShippingItemPalletDbTable ShippingItemPallets { get; set; } public OrderItemPalletDbTable OrderItemPallets { get; set; } public FilesDbTable Files { get; set; } public ShippingDocumentToFilesDbTable ShippingDocumentToFiles { get; set; } public IRepository Products { get; set; } public IRepository Customers { get; set; } public IRepository CustomerRoles { get; set; } public IRepository CustomerRoleMappings { get; set; } public FruitBankDbContext(INopDataProvider dataProvider, ILockService lockService, FruitBankAttributeService fruitBankAttributeService, IStoreContext storeContext, PartnerDbTable partnerDbTable, ShippingDbTable shippingDbTable, ShippingDocumentDbTable shippingDocumentDbTable, ShippingItemDbTable shippingItemDbTable, ShippingItemPalletDbTable shippingItemPalletDbTable, FilesDbTable filesDbTable, ShippingDocumentToFilesDbTable shippingDocumentToFilesDbTable, ProductDtoDbTable productDtoDbTable, OrderDtoDbTable orderDtoDbTable, OrderItemDtoDbTable orderItemDtoDbTable, OrderItemPalletDbTable orderItemPalletDbTable, IProductService productService, IStaticCacheManager staticCacheManager, IRepository productRepository, IRepository customerRepository, IRepository customerCustomerRoleMappingRepository, IRepository customerRoleRepository, IEnumerable logWriters) : base(dataProvider, lockService, logWriters) { _storeContext = storeContext; _productService = productService; _staticCacheManager = staticCacheManager; _fruitBankAttributeService = fruitBankAttributeService; Files = filesDbTable; Partners = partnerDbTable; Products = productRepository; ProductDtos = productDtoDbTable; OrderDtos = orderDtoDbTable; OrderItemDtos = orderItemDtoDbTable; OrderItemPallets = orderItemPalletDbTable; Shippings = shippingDbTable; ShippingDocuments = shippingDocumentDbTable; ShippingItems = shippingItemDbTable; ShippingItemPallets = shippingItemPalletDbTable; ShippingDocumentToFiles = shippingDocumentToFilesDbTable; Customers = customerRepository; CustomerRoles = customerRoleRepository; CustomerRoleMappings = customerCustomerRoleMappingRepository; } public IQueryable GetCustomersBySystemRoleName(string systemRoleName) { if (systemRoleName.IsNullOrWhiteSpace()) throw new ArgumentException("systemRoleName.IsNullOrWhiteSpace()", nameof(systemRoleName)); var query = from c in Customers.Table join crm in CustomerRoleMappings.Table on c.Id equals crm.CustomerId join cr in CustomerRoles.Table on crm.CustomerRoleId equals cr.Id where c.Active && !c.Deleted && cr.SystemName == systemRoleName select c; return query.Distinct().OrderBy(o => o.Username); } public IQueryable GetCustomerRolesByCustomerId(int customerId) { var query = from cr in CustomerRoles.Table join crm in CustomerRoleMappings.Table on cr.Id equals crm.CustomerRoleId where crm.CustomerId == customerId select cr; return query.Distinct(); } public IQueryable GetAllProducts(bool includeDeleted) => Products.Table.Where(p => includeDeleted || !p.Deleted).OrderBy(o => o.Name); public IQueryable GetAllProductDtos(bool includeDeleted) => GetAllProducts(includeDeleted).Select(product => new ProductDto(product)); public IAsyncEnumerable GetAllMeasuringProductDtos(bool includeDeleted) => GetAllProducts(includeDeleted).AsEnumerable().SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id))); public async Task GetMeasuringProductDtoByIdAsync(int productId) => await Products.Table.Where(product => product.Id == productId).AsEnumerable().SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id))).FirstOrDefaultAsync(); public async Task GetMeasuringAttributeValuesByProductIdAsync(int productId) => await _fruitBankAttributeService.GetMeasuringAttributeValuesAsync(productId); public async Task DeleteShippingSafeAsync(Shipping shipping) { await TransactionSafeAsync(async _ => { await Shippings.DeleteAsync(shipping, true); return true; }); } public async Task DeleteShippingDocumentSafeAsync(ShippingDocument shippingDocument) { await TransactionSafeAsync(async _ => { await ShippingDocuments.DeleteAsync(shippingDocument, true); return true; }); } public async Task DeleteShippingItemSafeAsync(ShippingItem shippingItem) { await TransactionSafeAsync(async _ => { await ShippingItems.DeleteAsync(shippingItem, true); return true; }); } public Task UpdateMeasuredShippingItemSafeAsync(ShippingItem shippingItem) { if (shippingItem.IsValidMeasuringValues()) return UpdateShippingItemSafeAsync(shippingItem); Logger.Error("shippingItem.IsMeasurable && !shippingItem.IsValidMeasuringValues()"); return Task.FromResult(false); } public Task UpdateShippingItemSafeAsync(ShippingItem shippingItem) => TransactionSafeAsync(async _ => await UpdateShippingItemAsync(shippingItem)); public async Task UpdateShippingItemAsync(ShippingItem shippingItem) { try { ProductDto? productDto = null; var productIsMeasurable = false; if (shippingItem.ProductId > 0) { productDto = await ProductDtos.GetByIdAsync(shippingItem.ProductId!.Value, true); if (productDto == null) throw new Exception($"shippingItem.ProductId > 0 && product == null; shippingItem.ProductId: {shippingItem.ProductId}"); productIsMeasurable = productDto.IsMeasurable; } shippingItem.IsMeasurable = productIsMeasurable; //if (shippingItem.ShippingItemPallets is { Count: > 0 }) await AddOrUpdateShippingItemPalletAsync(shippingItem); //await AddOrUpdateShippingItemPalletAsync(shippingItem.ShippingItemPallets.Where(x => x.IsValidMeasuringValues(shippingItem.IsMeasurable)), shippingItem); //Nem tudhatjuk, h minden Pallet-et tartalmaz-e a shippingItem paraméter! A Biztonság kedvéért lekérjük db-ből! - J. shippingItem.ShippingItemPallets = await ShippingItemPallets.GetAllByShippingItemIdAsync(shippingItem.Id, false).ToListAsync(); //Update előtt kivesszük a korábbi ShippingItem-et a db-ből! - J. var dbShippingItem = await ShippingItems.GetByIdAsync(shippingItem.Id, false); if (dbShippingItem == null) throw new Exception($"dbShippingItem == null; shippingItem.Id: {shippingItem.Id}"); var isMeasuredPrerequisite = productDto != null && shippingItem.PalletsOnDocument == shippingItem.ShippingItemPallets.Count && shippingItem.ShippingItemPallets.All(x => x.IsMeasuredAndValid(shippingItem.IsMeasurable)); SetupShippingItemMeasuringValues(shippingItem, isMeasuredPrerequisite); shippingItem.IsMeasured = isMeasuredPrerequisite && shippingItem.IsValidMeasuringValues(); await ShippingItems.UpdateAsync(shippingItem, shippingItem.IsMeasured != dbShippingItem.IsMeasured); if (shippingItem.ProductId == dbShippingItem.ProductId && shippingItem.IsMeasured == dbShippingItem.IsMeasured && shippingItem.IsMeasurable == dbShippingItem.IsMeasurable && shippingItem.MeasuredQuantity == dbShippingItem.MeasuredQuantity && // ReSharper disable once CompareOfFloatsByEqualityOperator shippingItem.MeasuredNetWeight == dbShippingItem.MeasuredNetWeight && // ReSharper disable once CompareOfFloatsByEqualityOperator shippingItem.MeasuredGrossWeight == dbShippingItem.MeasuredGrossWeight) { return true; } var productIdChanged = shippingItem.ProductId != dbShippingItem.ProductId; if (shippingItem.IsMeasured) { var quantityInc = productIdChanged ? shippingItem.MeasuredQuantity : shippingItem.MeasuredQuantity - dbShippingItem.MeasuredQuantity; productDto!.StockQuantity += quantityInc; if (!await UpdateProductDtoStockQuantityAsync(productDto, true)) throw new Exception($"UpdateProductStockQuantity() == false; shippingItem! product.Id: {productDto.Id}"); var incomingQuantity = productDto.GenericAttributes.GetValueOrNull(nameof(IIncomingQuantity.IncomingQuantity)); if (incomingQuantity != null) { await _fruitBankAttributeService.UpdateGenericAttributeAsync (productDto.Id, nameof(IIncomingQuantity.IncomingQuantity), incomingQuantity.Value - quantityInc); } if (productIsMeasurable) { await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync(productDto.Id, productIdChanged ? shippingItem.MeasuredNetWeight : shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight, shippingItem.IsMeasurable, true); } } //if (productIdUnchanged || !dbShippingItem.IsMeasured) return true; if (!productIdChanged && (shippingItem.IsMeasured || !dbShippingItem.IsMeasured)) return true; productDto = await ProductDtos.GetByIdAsync(dbShippingItem.ProductId); if (productDto != null) { productIsMeasurable = productDto.IsMeasurable; productDto.StockQuantity -= dbShippingItem.MeasuredQuantity; if (!await UpdateProductDtoStockQuantityAsync(productDto, true)) throw new Exception($"UpdateProductStockQuantity() == false; dbShippingItem! product.Id: {productDto.Id}"); var incomingQuantity = productDto.GenericAttributes.GetValueOrNull(nameof(IIncomingQuantity.IncomingQuantity)); if (incomingQuantity != null) { await _fruitBankAttributeService.UpdateGenericAttributeAsync (productDto.Id, nameof(IIncomingQuantity.IncomingQuantity), incomingQuantity.Value + dbShippingItem.MeasuredQuantity); } if (!productIsMeasurable) return true; var measuringValues = new MeasuringAttributeValues(productDto.Id, -dbShippingItem.MeasuredNetWeight, dbShippingItem.IsMeasurable); await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync(measuringValues, true); } else Logger.Warning($"product == null; dbShippingItem.ProductId: {dbShippingItem.ProductId}"); //else //TODO: productIdUnchanged-et lekezelni! - J. return true; } catch (Exception ex) { throw new Exception($"UpdateShippingItemAsync error! {shippingItem}; ex: {ex.Message}", ex); } } private static void SetupShippingItemMeasuringValues(ShippingItem shippingItem, bool shippingItemIsMeasured) { shippingItem.MeasuredQuantity = 0; shippingItem.MeasuredNetWeight = 0; shippingItem.MeasuredGrossWeight = 0; if (!shippingItemIsMeasured) return; foreach (var shippingItemPallet in shippingItem.ShippingItemPallets!.Where(x => x.IsMeasured && x.IsValidMeasuringValues(shippingItem.IsMeasurable))) { shippingItem.MeasuredQuantity += shippingItemPallet.TrayQuantity; if (!shippingItem.IsMeasurable) continue; shippingItem.MeasuredNetWeight += shippingItemPallet.NetWeight; shippingItem.MeasuredGrossWeight += shippingItemPallet.GrossWeight; } shippingItem.MeasuredNetWeight = double.Round(shippingItem.MeasuredNetWeight, 1); shippingItem.MeasuredGrossWeight = double.Round(shippingItem.MeasuredGrossWeight, 1); //if (shippingItem.MeasuredQuantity < 0) shippingItem.MeasuredQuantity = 0; //if (!shippingItem.IsMeasurable || shippingItem.MeasuredNetWeight < 0) shippingItem.MeasuredNetWeight = 0; //if (!shippingItem.IsMeasurable || shippingItem.MeasuredGrossWeight < 0) shippingItem.MeasuredGrossWeight = 0; } public async Task AddShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) { if (!await SetupShippingItemPalletMeauringValues(shippingItemPallet)) return null; await ShippingItemPallets.InsertAsync(shippingItemPallet); return shippingItemPallet; } public Task AddShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) => TransactionSafeAsync(async _ => await AddShippingItemPalletAsync(shippingItemPallet) != null); public async Task UpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) { if (!await SetupShippingItemPalletMeauringValues(shippingItemPallet)) return null; await ShippingItemPallets.UpdateAsync(shippingItemPallet); return shippingItemPallet; } public Task UpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) => TransactionSafeAsync(async _ => await UpdateShippingItemPalletAsync(shippingItemPallet) != null); public Task AddOrUpdateShippingItemPalletsSafeAsync(ShippingItem shippingItem) => AddOrUpdateShippingItemPalletsSafeAsync(shippingItem.ShippingItemPallets!, shippingItem); public Task AddOrUpdateShippingItemPalletsSafeAsync(IEnumerable shippingItemPallets, ShippingItem parentShippingItem) { return TransactionSafeAsync(async _ => { await AddOrUpdateShippingItemPalletAsync(shippingItemPallets, parentShippingItem); return true; }); } public Task AddOrUpdateShippingItemPalletAsync(ShippingItem shippingItem) => AddOrUpdateShippingItemPalletAsync(shippingItem.ShippingItemPallets!, shippingItem); public async Task AddOrUpdateShippingItemPalletAsync(IEnumerable shippingItemPallets, ShippingItem parentShippingItem) { foreach (var shippingItemPallet in shippingItemPallets) { shippingItemPallet.ShippingItem = parentShippingItem; if (await AddOrUpdateShippingItemPalletAsync(shippingItemPallet) == null) throw new Exception($"AddOrUpdateShippingItemPalletAsync->AddOrUpdateShippingItemPalletAsync() == null"); } } public async Task AddOrUpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) => await TransactionSafeAsync(async _ => await AddOrUpdateShippingItemPalletAsync(shippingItemPallet) != null); public async Task AddOrUpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) { if (shippingItemPallet.Id <= 0) return await AddShippingItemPalletAsync(shippingItemPallet); return await UpdateShippingItemPalletAsync(shippingItemPallet); } public async Task DeleteShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) { await TransactionSafeAsync(async _ => { await ShippingItemPallets.DeleteAsync(shippingItemPallet, false); return true; }); } public async Task SetOrderStatusToCompleteSafe(int orderId) => await TransactionSafeAsync(async _ => await SetOrderStatusToComplete(orderId) != null); public async Task SetOrderStatusToComplete(int orderId) { var orderDto = await OrderDtos.GetByIdAsync(orderId); if (orderDto == null) return null; if (!orderDto.IsMeasured || orderDto.OrderStatus == OrderStatus.Complete) return null; //throw new Exception($"SetOrderDtoToComplete; orderDto.IsMeasured == false; {orderDto}"); orderDto.OrderStatus = OrderStatus.Complete; await OrderDtos.UpdateAsync(orderDto); foreach (var orderItemDto in orderDto.OrderItemDtos) { if (!orderItemDto.IsMeasurable) continue; var gaNetWeight = CommonHelper.To(orderItemDto.GenericAttributes.FirstOrDefault(x => x.Key == nameof(IMeasuringNetWeight.NetWeight))?.Value ?? "0"); await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync (orderItemDto.Id, nameof(IMeasuringNetWeight.NetWeight), orderItemDto.NetWeight); await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync (orderItemDto.ProductId, -(orderItemDto.NetWeight-gaNetWeight), orderItemDto.IsMeasurable, true); } return orderDto; } public async Task AddOrderItemPalletAsync(OrderItemPallet orderItemPallet) { if (!await SetupOrderItemPalletMeauringValues(orderItemPallet)) return null; await OrderItemPallets.InsertAsync(orderItemPallet); return orderItemPallet; } public async Task UpdateOrderItemPalletAsync(OrderItemPallet orderItemPallet) { if (!await SetupOrderItemPalletMeauringValues(orderItemPallet)) return null; await OrderItemPallets.UpdateAsync(orderItemPallet); return orderItemPallet; } public async Task AddOrUpdateOrderItemPalletSafeAsync(OrderItemPallet orderItemPallet) => await TransactionSafeAsync(async _ => await AddOrUpdateOrderItemPalletAsync(orderItemPallet) != null); public async Task AddOrUpdateOrderItemPalletAsync(OrderItemPallet orderItemPallet) { if (orderItemPallet.Id <= 0) return await AddOrderItemPalletAsync(orderItemPallet); return await UpdateOrderItemPalletAsync(orderItemPallet); } private async Task SetupShippingItemPalletMeauringValues(ShippingItemPallet shippingItemPallet) { var shippingItem = shippingItemPallet.ShippingItem ?? await ShippingItems.GetByIdAsync(shippingItemPallet.ShippingItemId, false); if (shippingItem == null || shippingItemPallet.ShippingItemId != shippingItem.Id) return false; shippingItemPallet.SetupCustomItemPalletMeauringValues(shippingItem.IsMeasurable); return true; } private async Task SetupOrderItemPalletMeauringValues(OrderItemPallet orderItemPallet) { var orderItemDto = orderItemPallet.OrderItemDto ?? await OrderItemDtos.GetByIdAsync(orderItemPallet.OrderItemId); if (orderItemDto == null || orderItemPallet.OrderItemId != orderItemDto.Id) return false; orderItemPallet.SetupCustomItemPalletMeauringValues(orderItemDto.IsMeasurable); return true; } private async Task UpdateProductDtoStockQuantityAsync(int productDtoId, bool publishEvent) { var productDto = await ProductDtos.GetByIdAsync(productDtoId); if (productDto != null) return await UpdateProductDtoStockQuantityAsync(productDto, publishEvent); Logger.Error($"product == null; id: {productDtoId}"); return await Task.FromResult(false); } private async Task UpdateProductDtoStockQuantityAsync(ProductDto productDto, bool publishEvent) { //Itt mi legyen? RollBack? - J. if (productDto.StockQuantity < 0) Logger.Error($"productDto.StockQuantity < 0; Id: {productDto.Id}; StockQuantity: {productDto.StockQuantity}"); await ProductDtos.UpdateAsync(productDto, publishEvent); return await Task.FromResult(true); //var updatedRowsCount = await DataProvider.ExecuteNonQueryAsync($"update product set {nameof(Product.StockQuantity)} = {product.StockQuantity} where {nameof(Product.Id)} = {product.Id}"); //if (updatedRowsCount == 1) return await Task.FromResult(true); //Logger.Error($"Product updatedRowsCount != 1; id: {product.Id}"); //return await Task.FromResult(false); } public async Task> GetShippingDocumentsByShippingIdAsync(int shippingId) { var list = await ShippingDocuments.GetAll(true).Where(sd => sd.ShippingId == shippingId).ToListAsync(); return list; } }