#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, IShippingItemDbSet, IShippingDocumentDbSet { 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 ShippingItemDbTable ShippingItems { get; set; } public ShippingDocumentDbTable ShippingDocuments { 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, ShippingItemDbTable shippingItemDbTable, ShippingDocumentDbTable shippingDocumentDbTable, 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; Partners = partnerDbTable; Shippings = shippingDbTable; ShippingItems = shippingItemDbTable; ShippingDocuments = shippingDocumentDbTable; Products = productRepository; Customers = customerRepository; CustomerRoles = customerRoleRepository; CustomerRoleMappings = customerCustomerRoleMappingRepository; } public IQueryable GetMeasuringModelByShippingId(int shippingId) { var query = from p in Partners.Table join s in Shippings.Table on p.Id equals s.PartnerId where s.Id == shippingId select new MeasuringModel(p.Name); return query; } 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 Task UpdateMeasuredShippingItemAsync(ShippingItem shippingItem) { if (shippingItem.IsValidMeasuringValues()) return UpdateShippingItemAsync(shippingItem); Logger.Error("shippingItem.IsMeasurable && !shippingItem.IsValidMeasuringValues()"); return Task.FromResult(false); } public Task UpdateShippingItemAsync(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 = null; if (!shippingItem.IsMeasurable || shippingItem.MeasuredNetWeight <= 0) shippingItem.MeasuredNetWeight = null; if (!shippingItem.IsMeasurable || shippingItem.MeasuredGrossWeight <= 0) shippingItem.MeasuredGrossWeight = null; //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!.Value - dbShippingItem.MeasuredQuantity.GetValueOrDefault(0) : shippingItem.MeasuredQuantity!.Value; if (!await UpdateProductStockQuantityAsync(product, true)) throw new Exception($"UpdateProductStockQuantity() == false; shippingItem! product.Id: {product.Id}"); if (productIsMeasurable) { var measuringValues = new MeasuringAttributeValues { Id = product.Id, NetWeight = productIdUnchanged ? shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight.GetValueOrDefault(0) : shippingItem.MeasuredNetWeight, GrossWeight = productIdUnchanged ? shippingItem.MeasuredGrossWeight - dbShippingItem.MeasuredGrossWeight.GetValueOrDefault(0) : shippingItem.MeasuredGrossWeight, IsMeasurable = shippingItem.IsMeasurable }; await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync(measuringValues, 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.GetValueOrDefault(0); 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.GetValueOrDefault(0), -dbShippingItem.MeasuredGrossWeight.GetValueOrDefault(0), 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->TransactionSafeAsync error! shippingItem.Id: {shippingItem.Id}; ex: {ex.Message}", ex); } }); } 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; } }