#nullable enable using AyCode.Core.Loggers; using AyCode.Utils.Extensions; using FruitBank.Common.Entities; using FruitBank.Common.Interfaces; using FruitBank.Common.Models; using FruitBank.Common.Server; using LinqToDB; using LinqToDB.Common; using Mango.Nop.Core.Loggers; using Mango.Nop.Core.Repositories; using Nop.Core; using Nop.Core.Caching; using Nop.Core.ComponentModel; 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 Nop.Services.Common; using System.Transactions; using FruitBank.Common.Dtos; using Mango.Nop.Core.Dtos; namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; public class FruitBankDbContext : MgDbContextBase, IPartnerDbSet, IShippingDbSet, IShippingDocumentDbSet, IShippingItemDbSet, IShippingItemPalletDbSet, IShippingDocumentToFilesDbSet, IFilesDbSet { private readonly FruitBankAttributeService _fruitBankAttributeService; private readonly IStoreContext _storeContext; private readonly IProductService _productService; private readonly IStaticCacheManager _staticCacheManager; 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 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, 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; Shippings = shippingDbTable; ShippingDocuments = shippingDocumentDbTable; ShippingItems = shippingItemDbTable; ShippingItemPallets = shippingItemPalletDbTable; ShippingDocumentToFiles = shippingDocumentToFilesDbTable; Products = productRepository; 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).SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id))); public async Task GetMeasuringProductDtoByIdAsync(int productId) => await Products.Table.Where(product => product.Id == productId).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 tr => { await Shippings.DeleteAsync(shipping, true); return true; }); } public async Task DeleteShippingDocumentSafeAsync(ShippingDocument shippingDocument) { await TransactionSafeAsync(async tr => { await ShippingDocuments.DeleteAsync(shippingDocument, true); return true; }); } public async Task DeleteShippingItemSafeAsync(ShippingItem shippingItem) { await TransactionSafeAsync(async tr => { await ShippingItems.DeleteAsync(shippingItem, true); return true; }); } public async Task DeleteShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) { await TransactionSafeAsync(async tr => { await ShippingItemPallets.DeleteAsync(shippingItemPallet, false); 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) { if (shippingItem == null) { Logger.Error("shippingItem == null"); return Task.FromResult(false); } return TransactionSafeAsync(async tr => { try { //Mi van ha nem jött meg a termék? Nem fogják tudni menteni... - J. Product? product = null; var productIsMeasurable = false; if (shippingItem.ProductId > 0) { product = await Products.GetByIdAsync(shippingItem.ProductId); if (product == null) throw new Exception($"shippingItem.ProductId > 0 && product == null; shippingItem.ProductId: {shippingItem.ProductId}"); productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync(product.Id); } shippingItem.IsMeasurable = productIsMeasurable; 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; //Update előtt kivesszük a korábbi ShippingItem-et a db-ből! - J. var dbShippingItem = await ShippingItems.GetByIdAsync(shippingItem.Id); if (dbShippingItem == null) throw new Exception($"dbShippingItem == null; shippingItem.Id: {shippingItem.Id}"); shippingItem.IsMeasured = product != null && 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 productIdUnchanged = shippingItem.ProductId == dbShippingItem.ProductId; if (shippingItem.IsMeasured) { product!.StockQuantity += productIdUnchanged ? shippingItem.MeasuredQuantity - dbShippingItem.MeasuredQuantity : shippingItem.MeasuredQuantity; if (!await UpdateProductStockQuantityAsync(product, true)) throw new Exception($"UpdateProductStockQuantity() == false; shippingItem! product.Id: {product.Id}"); if (productIsMeasurable) await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync(product.Id, productIdUnchanged ? shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight : shippingItem.MeasuredNetWeight, productIdUnchanged ? shippingItem.MeasuredGrossWeight - dbShippingItem.MeasuredGrossWeight : shippingItem.MeasuredGrossWeight, shippingItem.IsMeasurable, true); } if (productIdUnchanged || !dbShippingItem.IsMeasured) return true; product = await Products.GetByIdAsync(dbShippingItem.ProductId); if (product != null) { productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync(product.Id); product.StockQuantity -= dbShippingItem.MeasuredQuantity; if (!await UpdateProductStockQuantityAsync(product, true)) throw new Exception($"UpdateProductStockQuantity() == false; dbShippingItem! product.Id: {product.Id}"); if (!productIsMeasurable) return true; var measuringValues = new MeasuringAttributeValues(product.Id, -dbShippingItem.MeasuredNetWeight, -dbShippingItem.MeasuredGrossWeight, 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($"UpdateShippingItemSafeAsync->TransactionSafeAsync error! shippingItem.Id: {shippingItem.Id}; ex: {ex.Message}", ex); } }); } public async Task AddShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) { if (!await ShippingItemPalletSetup(shippingItemPallet)) return null; await ShippingItemPallets.InsertAsync(shippingItemPallet); return shippingItemPallet; } public async Task UpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) { if (!await ShippingItemPalletSetup(shippingItemPallet)) return null; await ShippingItemPallets.UpdateAsync(shippingItemPallet); return shippingItemPallet; } private async Task ShippingItemPalletSetup(ShippingItemPallet shippingItemPallet) { var shippingItem = await ShippingItems.GetByIdAsync(shippingItemPallet.ShippingItemId, false); if (shippingItem == null) return false; if (!shippingItem.IsMeasurable) { shippingItemPallet.NetWeight = 0; shippingItemPallet.GrossWeight = 0; } shippingItemPallet.IsMeasured = shippingItemPallet.IsValidMeasuringValues(shippingItem.IsMeasurable); return true; } private async Task UpdateProductStockQuantityAsync(int productId, bool publishEvent) { var product = await Products.GetByIdAsync(productId); if (product != null) return await UpdateProductStockQuantityAsync(product, publishEvent); Logger.Error($"product == null; id: {productId}"); return await Task.FromResult(false); } private async Task UpdateProductStockQuantityAsync(Product product, bool publishEvent) { //Itt mi legyen? RollBack? - J. if (product.StockQuantity < 0) Logger.Error($"product.StockQuantity < 0; Id: {product.Id}; StockQuantity: {product.StockQuantity}"); await Products.UpdateAsync(product, 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; } }