This commit is contained in:
Adam 2025-09-30 17:18:54 +02:00
commit 865c13d62a
12 changed files with 318 additions and 97 deletions

View File

@ -190,11 +190,18 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Controllers
{
_logger.Detail($"GetMeasuringUsers invoked");
var customers = await ctx.GetCustormersBySystemRoleName(FruitBankConst.MeasuringRoleSystemName).Select(c => new CustomerDto(c)).ToListAsync();
var customers = await ctx.GetCustomersBySystemRoleName(FruitBankConst.MeasuringRoleSystemName).Select(c => new CustomerDto(c)).ToListAsync();
return customers; //.ToModelDto<CustomerDto>();
}
[SignalR(SignalRTags.GetCustomerRolesByCustomerId)]
public async Task<List<CustomerRole>> GetCustomerRolesByCustomerId(int customerId)
{
_logger.Detail($"GetCustomerRolesByCustomerId invoked; customerId: {customerId}");
return await ctx.GetCustomerRolesByCustomerId(customerId).ToListAsync();
}
[SignalR(SignalRTags.GetProductDtos)]
public async Task<List<ProductDto>> GetProductDtos()
{

View File

@ -1,24 +1,32 @@
using AyCode.Core.Loggers;
#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 NUglify.Helpers;
using Nop.Services.Common;
using System.Transactions;
using LinqToDB;
using Nop.Core.ComponentModel;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class FruitBankDbContext : MgDbContextBase, IPartnerDbSet<PartnerDbTable>, IShippingDbSet<ShippingDbTable>, IShippingItemDbSet<ShippingItemDbTable>, IShippingDocumentDbSet<ShippingDocumentDbTable>
{
private readonly FruitBankAttributeService _fruitBankAttributeService;
private readonly IStoreContext _storeContext;
private readonly IProductService _productService;
private readonly IStaticCacheManager _staticCacheManager;
@ -33,16 +41,19 @@ public class FruitBankDbContext : MgDbContextBase, IPartnerDbSet<PartnerDbTable>
public IRepository<CustomerCustomerRoleMapping> CustomerRoleMappings { get; set; }
public FruitBankDbContext(INopDataProvider dataProvider, PartnerDbTable partnerDbTable, ShippingDbTable shippingDbTable, ShippingItemDbTable shippingItemDbTable,
public FruitBankDbContext(INopDataProvider dataProvider, ILockService lockService, FruitBankAttributeService fruitBankAttributeService, IStoreContext storeContext,
PartnerDbTable partnerDbTable, ShippingDbTable shippingDbTable, ShippingItemDbTable shippingItemDbTable,
ShippingDocumentDbTable shippingDocumentDbTable, IProductService productService, IStaticCacheManager staticCacheManager,
IRepository<Product> productRepository,
IRepository<Customer> customerRepository,
IRepository<CustomerCustomerRoleMapping> customerCustomerRoleMappingRepository,
IRepository<CustomerRole> customerRoleRepository,
IEnumerable<IAcLogWriterBase> logWriters) : base(dataProvider, logWriters)
IEnumerable<IAcLogWriterBase> logWriters) : base(dataProvider, lockService, logWriters)
{
_storeContext = storeContext;
_productService = productService;
_staticCacheManager = staticCacheManager;
_fruitBankAttributeService = fruitBankAttributeService;
Partners = partnerDbTable;
Shippings = shippingDbTable;
@ -66,7 +77,7 @@ public class FruitBankDbContext : MgDbContextBase, IPartnerDbSet<PartnerDbTable>
return query;
}
public IQueryable<Customer> GetCustormersBySystemRoleName(string systemRoleName)
public IQueryable<Customer> GetCustomersBySystemRoleName(string systemRoleName)
{
if (systemRoleName.IsNullOrWhiteSpace()) throw new ArgumentException("systemRoleName.IsNullOrWhiteSpace()", nameof(systemRoleName));
@ -80,135 +91,150 @@ public class FruitBankDbContext : MgDbContextBase, IPartnerDbSet<PartnerDbTable>
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()
=> Products.Table.Where(p => !p.Deleted).OrderBy(o => o.Name);
public Task<bool> UpdateMeasuredShippingItemAsync(ShippingItem shippingItem)
{
if (!shippingItem.IsMeasurable || shippingItem.IsValidMeasuringValues()) return UpdateShippingItemAsync(shippingItem);
if (shippingItem.IsValidMeasuringValues()) return UpdateShippingItemAsync(shippingItem);
Logger.Error("shippingItem.IsMeasurable && !shippingItem.IsValidMeasuringValues()");
return Task.FromResult(false);
}
private static readonly ReaderWriterLockSlim _locker = new(LockRecursionPolicy.NoRecursion);
public async Task<bool> UpdateShippingItemAsync(ShippingItem shippingItem)
public Task<bool> UpdateShippingItemAsync(ShippingItem shippingItem)
{
if (shippingItem == null)
{
Logger.Error("shippingItem == null");
return await Task.FromResult(false);
return Task.FromResult(false);
}
//using (new ReaderWriteLockDisposable(_locker))
//_locker.EnterWriteLock();
//try
//{
using var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
return TransactionSafeAsync(async tr =>
{
try
{
//Mi van ha nem jött meg a termék? Nem fogják tudni menteni... - J.
if (shippingItem.MeasuredQuantity <= 0) shippingItem.MeasuredQuantity = null;
Product? product = null;
var productIsMeasurable = false;
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)
{
Logger.Error("dbShippingItem == null");
return await Task.FromResult(false);
}
Product product = null;
if (shippingItem.ProductId > 0)
{
product = await Products.GetByIdAsync(shippingItem.ProductId);
if (product == null)
{
Logger.Error($"shippingItem.ProductId > 0 && product == null; shippingItem.ProductId: {shippingItem.ProductId}");
return await Task.FromResult(false);
}
throw new Exception($"shippingItem.ProductId > 0 && product == null; shippingItem.ProductId: {shippingItem.ProductId}");
productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync<Product>(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);
await ShippingItems.UpdateAsync(shippingItem, shippingItem.IsMeasured != dbShippingItem.IsMeasured);
//TODO: a measuredweight-eket is! - J.
if (shippingItem.ProductId != dbShippingItem.ProductId ||
shippingItem.IsMeasured != dbShippingItem.IsMeasured || shippingItem.IsMeasurable != dbShippingItem.IsMeasurable ||
shippingItem.MeasuredQuantity != dbShippingItem.MeasuredQuantity ||
shippingItem.MeasuredNetWeight != dbShippingItem.MeasuredNetWeight || shippingItem.MeasuredGrossWeight != dbShippingItem.MeasuredGrossWeight)
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)
{
var productIdUnchanged = shippingItem.ProductId == dbShippingItem.ProductId;
return true;
}
if (shippingItem.IsMeasured)
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)
{
product!.StockQuantity += shippingItem.MeasuredQuantity.GetValueOrDefault(0);
if (!await UpdateProductStockQuantityAsync(product))
var measuringValues = new MeasuringAttributeValues
{
Logger.Error($"UpdateProductStockQuantity() == false; shippingItem! id: {product.Id}");
return await Task.FromResult(false);
}
}
NetWeight = productIdUnchanged ? shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight.GetValueOrDefault(0) : shippingItem.MeasuredNetWeight,
GrossWeight = productIdUnchanged ? shippingItem.MeasuredGrossWeight - dbShippingItem.MeasuredGrossWeight.GetValueOrDefault(0) : shippingItem.MeasuredGrossWeight,
IsMeasurable = shippingItem.IsMeasurable
};
if (dbShippingItem.IsMeasured)
{
product = await Products.GetByIdAsync(dbShippingItem.ProductId);
if (product != null)
{
product.StockQuantity -= dbShippingItem.MeasuredQuantity.GetValueOrDefault(0);
if (!await UpdateProductStockQuantityAsync(product))
{
Logger.Error($"UpdateProductStockQuantity() == false; dbShippingItem! id: {product.Id}");
return await Task.FromResult(false);
}
}
else Logger.Warning($"product == null; dbShippingItem.ProductId: {dbShippingItem.ProductId}");
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(product.Id, measuringValues, true);
}
}
if (productIdUnchanged || !dbShippingItem.IsMeasured) return true;
product = await Products.GetByIdAsync(dbShippingItem.ProductId);
if (product != null)
{
productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync<Product>(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(-dbShippingItem.MeasuredNetWeight.GetValueOrDefault(0), -dbShippingItem.MeasuredGrossWeight.GetValueOrDefault(0), dbShippingItem.IsMeasurable);
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(product.Id, measuringValues, true);
}
else Logger.Warning($"product == null; dbShippingItem.ProductId: {dbShippingItem.ProductId}");
//else //TODO: productIdUnchanged-et lekezelni! - J.
return true;
}
catch (Exception ex)
{
Logger.Error($"UpdateShippingItemAsync Transaction ERROR! Id: {shippingItem?.Id}", ex);
return await Task.FromResult(false);
throw new Exception($"UpdateShippingItemAsync->TransactionSafeAsync error! shippingItem.Id: {shippingItem.Id}; ex: {ex.Message}", ex);
}
transaction.Complete();
//}
//finally
//{
// _locker.ExitWriteLock();
//}
return await Task.FromResult(true);
});
}
private async Task<bool> UpdateProductStockQuantityAsync(int productId)
private async Task<bool> UpdateProductStockQuantityAsync(int productId, bool publishEvent)
{
var product = await Products.GetByIdAsync(productId);
if (product != null) return await UpdateProductStockQuantityAsync(product);
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)
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, true);
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}");

View File

@ -29,9 +29,16 @@ public class ShippingDbTable : MgDbTableBase<Shipping>
}
public IQueryable<Shipping> GetAllNotMeasured(bool loadRelations)
=> GetAll(loadRelations).Where(s => !s.IsAllMeasured);
=> GetAll(loadRelations).Where(s => !s.IsAllMeasured || s.MeasuredDate == null || s.MeasuredDate < DateTime.Now.AddDays(1000));
public Task<Shipping> GetByIdAsync(int id, bool loadRelations)
=> GetAll(loadRelations).FirstOrDefaultAsync(s => s.Id == id);
protected override void OnUpdate(Shipping entity)
{
if (entity is { IsAllMeasured: true, MeasuredDate: null }) entity.MeasuredDate = DateTime.Now;
base.OnUpdate(entity);
}
}

View File

@ -16,8 +16,19 @@ public class ShippingItemDbTable : MgDbTableBase<ShippingItem>
{
}
public override IQueryable<ShippingItem> GetAll()
=> base.GetAll();
protected override void OnUpdate(ShippingItem entity)
{
RoundMeasuredValue(entity);
base.OnUpdate(entity);
}
protected override void OnInsert(ShippingItem entity)
{
RoundMeasuredValue(entity);
base.OnInsert(entity);
}
public override IQueryable<ShippingItem> GetAll() => base.GetAll();
public IQueryable<ShippingItem> GetAll(bool loadRelations)
{
@ -42,4 +53,10 @@ public class ShippingItemDbTable : MgDbTableBase<ShippingItem>
public IQueryable<ShippingItem> GetAllByShippingDocumentIdAsync(int shippingDocumentId, bool loadRelations)
=> GetAll(loadRelations).Where(si => si.ShippingDocumentId == shippingDocumentId);
private static void RoundMeasuredValue(ShippingItem shippingItem)
{
if (shippingItem.MeasuredNetWeight.HasValue) shippingItem.MeasuredNetWeight = double.Round(shippingItem.MeasuredNetWeight.Value, 1);
if (shippingItem.MeasuredGrossWeight.HasValue) shippingItem.MeasuredGrossWeight = double.Round(shippingItem.MeasuredGrossWeight.Value, 1);
}
}

View File

@ -2,26 +2,35 @@
using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces;
using FruitBank.Common.Loggers;
using FruitBank.Common.Server;
using Mango.Nop.Core.Loggers;
using Mango.Nop.Services;
using Microsoft.AspNetCore.Http;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Events;
using Nop.Plugin.Misc.FruitBankPlugin.Controllers;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Common;
using Nop.Services.Events;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.EventConsumers;
public class FruitBankEventConsumer(IHttpContextAccessor httpContextAccessor, FruitBankDbContext ctx, IEnumerable<IAcLogWriterBase> logWriters) :
MgEventConsumer(httpContextAccessor, logWriters),
IConsumer<EntityUpdatedEvent<ShippingItem>>,
IConsumer<EntityUpdatedEvent<ShippingDocument>>
public class FruitBankEventConsumer(IHttpContextAccessor httpContextAccessor, FruitBankDbContext ctx, FruitBankAttributeService fruitBankAttributeService, IStoreContext storeContext, IEnumerable<IAcLogWriterBase> logWriters) :
MgEventConsumer(httpContextAccessor, logWriters), IConsumer<EntityUpdatedEvent<ShippingItem>>, IConsumer<EntityUpdatedEvent<ShippingDocument>>
{
public override Task HandleEventAsync(EntityUpdatedEvent<Product> eventMessage)
public override async Task HandleEventAsync(EntityUpdatedEvent<Product> eventMessage)
{
return base.HandleEventAsync(eventMessage);
var product = eventMessage.Entity;
var isMeasurableProduct = await fruitBankAttributeService.IsMeasurableEntityAsync<Product>(product.Id);
var shippingItems = await ctx.ShippingItems.Table
.Where(si => si.ProductId == product.Id && !si.IsMeasured && si.IsMeasurable != isMeasurableProduct)
.ToListAsync();
await ctx.ShippingItems.UpdateAsync(shippingItems, false);
await base.HandleEventAsync(eventMessage);
}
public async Task HandleEventAsync(EntityInsertedEvent<ShippingItem> eventMessage)
@ -49,7 +58,7 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAccessor, Fr
private async Task UpdateShippingDocumentIsAllMeasuredAsync(ShippingItem shippingItem)
{
//TODO: where: && IsMeasureable!!!! - J.
//TODO: where: && IsMeasurable!!!! - J.
var isAllShippingItemMeasured = ctx.ShippingItems.GetAll(false).Where(si => si.ShippingDocumentId == shippingItem.ShippingDocumentId).All(si => si.IsMeasured);
var shippingDocument = await ctx.ShippingDocuments.GetByIdAsync(shippingItem.ShippingDocumentId);

View File

@ -21,7 +21,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin
public class FruitBankPlugin : BasePlugin, IWidgetPlugin
{
protected readonly IActionContextAccessor _actionContextAccessor;
private readonly ISettingService _settingService;
//private readonly IWebHelper _webHelper;
protected readonly IPermissionService _permissionService;
protected readonly ILocalizationService _localizationService;
@ -35,9 +37,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin
ISettingService settingService,
//IWebHelper webHelper,
ILocalizationService localizationService,
IPermissionService permissionService,
IUrlHelperFactory urlHelperFactory,
IAdminMenu adminMenu)
IPermissionService permissionService,
IUrlHelperFactory urlHelperFactory,
IAdminMenu adminMenu)
{
_actionContextAccessor = actionContextAccessor;
_settingService = settingService;
@ -52,8 +54,13 @@ namespace Nop.Plugin.Misc.FruitBankPlugin
public override async Task InstallAsync()
{
//TODO: Add "Measuring" role - FruitBankConst.MeasuringRoleSystemName
//TODO: Add "MeasuringRevisor" role - FruitBankConst.MeasuringRevisorRoleSystemName
//TODO: Add "IsMeasurable" product attribute - FruitBankConst.IsMeasurableAttributeName
//TODO: Add "NeedsToBeMeasured" product attribute if not exists
//TODO: Add unique index to GenericAttribute[EntityId, KeyGroup, Key]???!? ÁTGONDOLNI, mert lehet esetleg lista is a visszaadott, de a nopcommerce kódban felülírja ha azonos key-el vannak! - J.
// Default settings
var settings = new FruitBankSettings
{

View File

@ -8,6 +8,7 @@ using FruitBank.Common.Interfaces;
using FruitBank.Common.Server.Services.Loggers;
using FruitBank.Common.Server.Services.SignalRs;
using Mango.Nop.Core.Loggers;
using Mango.Nop.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.SignalR;
@ -45,13 +46,15 @@ public class PluginNopStartup : INopStartup
});
//register services and interfaces
//services.AddDevExpressControls();
services.AddSingleton<ILockService, LockService>();
services.AddScoped<IAcLogWriterBase, ConsoleLogWriter>();
//services.AddScoped<IAcLogWriterBase, NopLogWriter>();
services.AddScoped<LoggerToLoggerApiController2>();
//services.AddSingleton<SessionService>();
services.AddScoped<FruitBankAttributeService>();
services.AddScoped<PartnerDbTable>();
services.AddScoped<ShippingDbTable>();
services.AddScoped<ShippingItemDbTable>();

View File

@ -110,6 +110,9 @@
<Reference Include="AyCode.Services.Server">
<HintPath>..\..\..\..\FruitBankHybridApp\FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Services.Server.dll</HintPath>
</Reference>
<Reference Include="AyCode.Utils">
<HintPath>..\..\..\..\FruitBankHybridApp\FruitBank.Common.Server\bin\Debug\net9.0\AyCode.Utils.dll</HintPath>
</Reference>
<Reference Include="FruitBank.Common">
<HintPath>..\..\..\..\FruitBankHybridApp\FruitBank.Common.Server\bin\Debug\net9.0\FruitBank.Common.dll</HintPath>
</Reference>

View File

@ -1,4 +1,5 @@
using System.Linq;
using FruitBank.Common.Interfaces;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Orders;
@ -96,7 +97,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
System.Diagnostics.Debug.WriteLine($"Spec Attribute: {specificationAttribute.Name}, Option: {specificationAttributeOption.Name}");
// Check if this is your "NeedsToBeMeasured" specification attribute
if (specificationAttribute.Name == "Measureable" &&
if (specificationAttribute.Name == "Measureable" && //nameof(MeasuringAttributeValues.IsMeasurable)
specificationAttributeOption.Name == "Yes") // or whatever value you set
{
requiresMeasurement = true;

View File

@ -0,0 +1,122 @@
#nullable enable
using FruitBank.Common.Interfaces;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Services.Common;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services;
public class FruitBankAttributeService(IGenericAttributeService genericAttributeService, IStoreContext storeContext)
{
public async Task<GenericAttribute?> GetGenericAttributeAsync<TEntity>(int entityId, string key, int storeId)
{
return (await genericAttributeService.GetAttributesForEntityAsync(entityId, typeof(TEntity).Name)).SingleOrDefault(ga => ga.StoreId == storeId && ga.Key == key);
}
public async Task<List<GenericAttribute>> GetMeasuringAttributesAsync<TEntity>(int entityId, int storeId)
{
var measuringAttributes = (await genericAttributeService.GetAttributesForEntityAsync(entityId, typeof(TEntity).Name))
.Where(ga => ga.StoreId == storeId &&
(ga.Key is nameof(MeasuringAttributeValues.NetWeight) or nameof(MeasuringAttributeValues.GrossWeight) or nameof(MeasuringAttributeValues.IsMeasurable)))
.ToList();
return measuringAttributes;
}
public Task<MeasuringAttributeValues?> GetMeasuringAttributeValuesAsync<TEntity>(int entityId)
=> GetMeasuringAttributeValuesAsync<TEntity>(entityId, storeContext.GetCurrentStore().Id);
public async Task<MeasuringAttributeValues?> GetMeasuringAttributeValuesAsync<TEntity>(int entityId, int storeId)
{
var measuringAttributes = await GetMeasuringAttributesAsync<TEntity>(entityId, storeId);
if (measuringAttributes.Count == 0) return null;
var measuringAttributeValues = new MeasuringAttributeValues(
CommonHelper.To<double?>(measuringAttributes.FirstOrDefault(ga => ga.Key == nameof(MeasuringAttributeValues.NetWeight))),
CommonHelper.To<double?>(measuringAttributes.FirstOrDefault(ga => ga.Key == nameof(MeasuringAttributeValues.GrossWeight))),
CommonHelper.To<bool?>(measuringAttributes.FirstOrDefault(ga => ga.Key == nameof(MeasuringAttributeValues.IsMeasurable))));
return measuringAttributeValues;
}
public Task<bool> IsMeasurableEntityAsync<TEntity>(int entityId) => IsMeasurableEntityAsync<TEntity>(entityId, storeContext.GetCurrentStore().Id);
public async Task<bool> IsMeasurableEntityAsync<TEntity>(int entityId, int storeId)
{
var measurableAttribute = await GetGenericAttributeAsync<TEntity>(entityId, nameof(MeasuringAttributeValues.IsMeasurable), storeId);
return measurableAttribute != null && CommonHelper.To<bool>(measurableAttribute.Value);
}
public Task InsertOrUpdateMeasuringAttributeValuesAsync<TEntity>(int entityId, MeasuringAttributeValues measuringAttributeValues, bool cumulativeWeightUpdate)
=> InsertOrUpdateMeasuringAttributeValuesAsync<TEntity>(entityId, storeContext.GetCurrentStore().Id, measuringAttributeValues, cumulativeWeightUpdate);
public async Task InsertOrUpdateMeasuringAttributeValuesAsync<TEntity>(int entityId, int storeId, MeasuringAttributeValues measuringAttributeValues, bool cumulativeWeightUpdate)
{
if (!measuringAttributeValues.HasValues()) throw new Exception($"FruitBankAttributeService->InsertOrUpdateMeasuringAttributeValuesAsync; measuringAttributeValues.HasValues() == false; entityId: {entityId}; values: {measuringAttributeValues}");
var measuringAttributes = await GetMeasuringAttributesAsync<TEntity>(entityId, storeId);
var netWeightAttribute = measuringAttributes.FirstOrDefault(ma => ma.Key == nameof(MeasuringAttributeValues.NetWeight));
if (netWeightAttribute != null) await UpdateMeasuringWeightAttributeValueAsync(netWeightAttribute, measuringAttributeValues.NetWeight!.Value, cumulativeWeightUpdate);
else await InsertGenericAttributeAsync<TEntity, double>(entityId, nameof(MeasuringAttributeValues.NetWeight), measuringAttributeValues.NetWeight!.Value, storeId);
var grossWeightAttribute = measuringAttributes.FirstOrDefault(ma => ma.Key == nameof(MeasuringAttributeValues.GrossWeight));
if (grossWeightAttribute != null) await UpdateMeasuringWeightAttributeValueAsync(grossWeightAttribute, measuringAttributeValues.GrossWeight!.Value, cumulativeWeightUpdate);
else await InsertGenericAttributeAsync<TEntity, double>(entityId, nameof(MeasuringAttributeValues.GrossWeight), measuringAttributeValues.GrossWeight!.Value, storeId);
var isMeasurableAttribute = measuringAttributes.FirstOrDefault(ma => ma.Key == nameof(MeasuringAttributeValues.IsMeasurable));
if (isMeasurableAttribute != null) await UpdateGenericAttributeAsync(isMeasurableAttribute, measuringAttributeValues.IsMeasurable!.Value);
else await InsertGenericAttributeAsync<TEntity, bool>(entityId, nameof(MeasuringAttributeValues.IsMeasurable), measuringAttributeValues.IsMeasurable!.Value, storeId);
}
private async Task UpdateMeasuringWeightAttributeValueAsync(GenericAttribute genericAttribute, double newWeightValue, bool cumulativeWeightUpdate)
{
await UpdateGenericAttributeAsync(genericAttribute, cumulativeWeightUpdate ? CommonHelper.To<double>(genericAttribute.Value) + newWeightValue : newWeightValue);
}
public async Task DeleteAllMeasuringAttributesAsync<TEntity>(int entityId, int storeId)
{
var measuringAttributes = await GetMeasuringAttributesAsync<TEntity>(entityId, storeId);
if (measuringAttributes.Count == 0) return;
foreach (var measuringAttribute in measuringAttributes)
{
await genericAttributeService.DeleteAttributeAsync(measuringAttribute);
}
}
public async Task InsertGenericAttributeAsync<TEntity, TPropType>(int entityId, string key, TPropType value, int storeId)
{
var genericAttribute = new GenericAttribute
{
Key = key,
EntityId = entityId,
KeyGroup = typeof(TEntity).Name,
Value = CommonHelper.To<string>(value),
StoreId = storeId
};
await genericAttributeService.InsertAttributeAsync(genericAttribute);
}
public async Task UpdateGenericAttributeAsync<TEntity, TPropType>(int entityId, string key, TPropType newValue, int storeId)
{
var ga = await GetGenericAttributeAsync<TEntity>(entityId, key, storeId);
await UpdateGenericAttributeAsync(ga!, newValue);
}
public async Task UpdateGenericAttributeAsync<TPropType>(GenericAttribute genericAttribute, TPropType newValue)
{
genericAttribute.Value = CommonHelper.To<string>(newValue);
await genericAttributeService.UpdateAttributeAsync(genericAttribute);
}
public async Task DeleteGenericAttributeAsync<TEntity>(int entityId, string key, int storeId)
{
var ga = await GetGenericAttributeAsync<TEntity>(entityId, key, storeId);
if (ga == null) return;
await genericAttributeService.DeleteAttributeAsync(ga);
}
}

View File

@ -0,0 +1,5 @@
using Mango.Nop.Services;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services;
public interface ILockService : IMgLockService{}

View File

@ -0,0 +1,14 @@
using Mango.Nop.Services;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services;
public class LockService : MgLockService, ILockService
{
public LockService() : this(new SemaphoreSlim(1))
{}
public LockService(SemaphoreSlim semaphoreSlim) : base(semaphoreSlim)
{
}
}