Mango.Nop.Plugins/Nop.Plugin.Misc.AIPlugin/Domains/DataLayer/FruitBankDbContext.cs

468 lines
22 KiB
C#

#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 DevExpress.XtraExport.Helpers;
using FruitBank.Common.Dtos;
using Mango.Nop.Core.Dtos;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Nop.Core.Domain.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class FruitBankDbContext : MgDbContextBase,
IOrderDtoDbSet<OrderDtoDbTable>,
IOrderItemDtoDbSet<OrderItemDtoDbTable>,
IPartnerDbSet<PartnerDbTable>,
IShippingDbSet<ShippingDbTable>,
IShippingDocumentDbSet<ShippingDocumentDbTable>,
IShippingItemDbSet<ShippingItemDbTable>,
IShippingItemPalletDbSet<ShippingItemPalletDbTable>,
IOrderItemPalletDbSet<OrderItemPalletDbTable>,
IShippingDocumentToFilesDbSet<ShippingDocumentToFilesDbTable>,
IFilesDbSet<FilesDbTable>
{
private readonly FruitBankAttributeService _fruitBankAttributeService;
private readonly IStoreContext _storeContext;
private readonly IProductService _productService;
private readonly IStaticCacheManager _staticCacheManager;
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<Product> Products { get; set; }
public IRepository<Customer> Customers { get; set; }
public IRepository<CustomerRole> CustomerRoles { get; set; }
public IRepository<CustomerCustomerRoleMapping> 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,
OrderDtoDbTable orderDtoDbTable, OrderItemDtoDbTable orderItemDtoDbTable, OrderItemPalletDbTable orderItemPalletDbTable,
IProductService productService, IStaticCacheManager staticCacheManager,
IRepository<Product> productRepository,
IRepository<Customer> customerRepository,
IRepository<CustomerCustomerRoleMapping> customerCustomerRoleMappingRepository,
IRepository<CustomerRole> customerRoleRepository,
IEnumerable<IAcLogWriterBase> logWriters) : base(dataProvider, lockService, logWriters)
{
_storeContext = storeContext;
_productService = productService;
_staticCacheManager = staticCacheManager;
_fruitBankAttributeService = fruitBankAttributeService;
Files = filesDbTable;
Partners = partnerDbTable;
Products = productRepository;
OrderDtos = orderDtoDbTable;
OrderItemDtos = orderItemDtoDbTable;
OrderItemPallets = orderItemPalletDbTable;
Shippings = shippingDbTable;
ShippingDocuments = shippingDocumentDbTable;
ShippingItems = shippingItemDbTable;
ShippingItemPallets = shippingItemPalletDbTable;
ShippingDocumentToFiles = shippingDocumentToFilesDbTable;
Customers = customerRepository;
CustomerRoles = customerRoleRepository;
CustomerRoleMappings = customerCustomerRoleMappingRepository;
}
public IQueryable<Customer> 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<CustomerRole> 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<Product> GetAllProducts(bool includeDeleted)
=> Products.Table.Where(p => includeDeleted || !p.Deleted).OrderBy(o => o.Name);
public IQueryable<ProductDto> GetAllProductDtos(bool includeDeleted)
=> GetAllProducts(includeDeleted).Select(product => new ProductDto(product));
public IAsyncEnumerable<MeasuringProductDto> GetAllMeasuringProductDtos(bool includeDeleted)
=> GetAllProducts(includeDeleted).SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id)));
public async Task<MeasuringProductDto?> 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<MeasuringAttributeValues?> GetMeasuringAttributeValuesByProductIdAsync(int productId)
=> await _fruitBankAttributeService.GetMeasuringAttributeValuesAsync<Product>(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 Task<bool> UpdateMeasuredShippingItemSafeAsync(ShippingItem shippingItem)
{
if (shippingItem.IsValidMeasuringValues()) return UpdateShippingItemSafeAsync(shippingItem);
Logger.Error("shippingItem.IsMeasurable && !shippingItem.IsValidMeasuringValues()");
return Task.FromResult(false);
}
public Task<bool> UpdateShippingItemSafeAsync(ShippingItem shippingItem)
=> TransactionSafeAsync(async _ => await UpdateShippingItemAsync(shippingItem));
public async Task<bool> UpdateShippingItemAsync(ShippingItem shippingItem)
{
try
{
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>(product.Id);
}
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 = product != 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)
{
product!.StockQuantity += productIdChanged ? shippingItem.MeasuredQuantity : shippingItem.MeasuredQuantity - dbShippingItem.MeasuredQuantity;
if (!await UpdateProductStockQuantityAsync(product, true))
throw new Exception($"UpdateProductStockQuantity() == false; shippingItem! product.Id: {product.Id}");
if (productIsMeasurable)
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(product.Id,
productIdChanged ? shippingItem.MeasuredNetWeight : shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight,
productIdChanged ? shippingItem.MeasuredGrossWeight : shippingItem.MeasuredGrossWeight - dbShippingItem.MeasuredGrossWeight,
shippingItem.IsMeasurable, true);
}
//if (productIdUnchanged || !dbShippingItem.IsMeasured) return true;
if (!productIdChanged && (shippingItem.IsMeasured || !dbShippingItem.IsMeasured)) return true;
product = await Products.GetByIdAsync(dbShippingItem.ProductId);
if (product != null)
{
productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync<Product>(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<Product>(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<ShippingItemPallet?> AddShippingItemPalletAsync(ShippingItemPallet shippingItemPallet)
{
if (!await SetupShippingItemPalletMeauringValues(shippingItemPallet)) return null;
await ShippingItemPallets.InsertAsync(shippingItemPallet);
return shippingItemPallet;
}
public Task<bool> AddShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
=> TransactionSafeAsync(async tr => await AddShippingItemPalletAsync(shippingItemPallet) != null);
public async Task<ShippingItemPallet?> UpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet)
{
if (!await SetupShippingItemPalletMeauringValues(shippingItemPallet)) return null;
await ShippingItemPallets.UpdateAsync(shippingItemPallet);
return shippingItemPallet;
}
public Task<bool> UpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
=> TransactionSafeAsync(async tr => await UpdateShippingItemPalletAsync(shippingItemPallet) != null);
public Task AddOrUpdateShippingItemPalletsSafeAsync(ShippingItem shippingItem) => AddOrUpdateShippingItemPalletsSafeAsync(shippingItem.ShippingItemPallets!, shippingItem);
public Task<bool> AddOrUpdateShippingItemPalletsSafeAsync(IEnumerable<ShippingItemPallet> shippingItemPallets, ShippingItem parentShippingItem)
{
return TransactionSafeAsync(async tr =>
{
await AddOrUpdateShippingItemPalletAsync(shippingItemPallets, parentShippingItem);
return true;
});
}
public Task AddOrUpdateShippingItemPalletAsync(ShippingItem shippingItem) => AddOrUpdateShippingItemPalletAsync(shippingItem.ShippingItemPallets!, shippingItem);
public async Task AddOrUpdateShippingItemPalletAsync(IEnumerable<ShippingItemPallet> 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<bool> AddOrUpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
=> await TransactionSafeAsync(async tr => await AddOrUpdateShippingItemPalletAsync(shippingItemPallet) != null);
public async Task<ShippingItemPallet?> AddOrUpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet)
{
if (shippingItemPallet.Id <= 0) return await AddShippingItemPalletAsync(shippingItemPallet);
return await UpdateShippingItemPalletAsync(shippingItemPallet);
}
public async Task DeleteShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
{
await TransactionSafeAsync(async tr =>
{
await ShippingItemPallets.DeleteAsync(shippingItemPallet, false);
return true;
});
}
public async Task<bool> SetOrderStatusToCompleteSafe(int orderId)
=> await TransactionSafeAsync(async tr => await SetOrderStatusToComplete(orderId) != null);
public async Task<OrderDto?> 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<double>(orderItemDto.GenericAttributes.FirstOrDefault(x => x.Key == nameof(IMeasuringNetWeight.NetWeight))?.Value ?? "0");
await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<OrderItem, double>
(orderItemDto.Id, nameof(IMeasuringNetWeight.NetWeight), orderItemDto.NetWeight);
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>
(orderItemDto.ProductId, -(orderItemDto.NetWeight-gaNetWeight), 0, orderItemDto.IsMeasurable, true);
}
return orderDto;
}
public async Task<OrderItemPallet?> AddOrderItemPalletAsync(OrderItemPallet orderItemPallet)
{
if (!await SetupOrderItemPalletMeauringValues(orderItemPallet)) return null;
await OrderItemPallets.InsertAsync(orderItemPallet);
return orderItemPallet;
}
public async Task<OrderItemPallet?> UpdateOrderItemPalletAsync(OrderItemPallet orderItemPallet)
{
if (!await SetupOrderItemPalletMeauringValues(orderItemPallet)) return null;
await OrderItemPallets.UpdateAsync(orderItemPallet);
return orderItemPallet;
}
public async Task<bool> AddOrUpdateOrderItemPalletSafeAsync(OrderItemPallet orderItemPallet)
=> await TransactionSafeAsync(async tr => await AddOrUpdateOrderItemPalletAsync(orderItemPallet) != null);
public async Task<OrderItemPallet?> AddOrUpdateOrderItemPalletAsync(OrderItemPallet orderItemPallet)
{
if (orderItemPallet.Id <= 0) return await AddOrderItemPalletAsync(orderItemPallet);
return await UpdateOrderItemPalletAsync(orderItemPallet);
}
private async Task<bool> 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<bool> 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<bool> 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<bool> 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<List<ShippingDocument>> GetShippingDocumentsByShippingIdAsync(int shippingId)
{
var list = await ShippingDocuments.GetAll(true).Where(sd => sd.ShippingId == shippingId).ToListAsync();
return list;
}
}