.Net10, VS2026; StockTaking in progress...

This commit is contained in:
Loretta 2025-12-01 16:17:57 +01:00
parent 805c5e2299
commit 070d7ec3d2
13 changed files with 351 additions and 15 deletions

View File

@ -0,0 +1,119 @@
using AyCode.Core.Loggers;
using AyCode.Services.SignalRs;
using FruitBank.Common.Entities;
using FruitBank.Common.Server.Interfaces;
using FruitBank.Common.Server.Services.SignalRs;
using FruitBank.Common.SignalRs;
using Mango.Nop.Core.Loggers;
using Nop.Core;
using Nop.Core.Events;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers;
public class StockSignalREndpointServer(StockTakingDbContext ctx, SignalRSendToClientService sendToClient, IEventPublisher eventPublisher, IWorkContext workContext, IEnumerable<IAcLogWriterBase> logWriters)
: IStockSignalREndpointServer
{
private const int LastStockTakingDays = 15;
private readonly ILogger _logger = new Logger<StockSignalREndpointServer>(logWriters.ToArray());
[SignalR(SignalRTags.GetStockTakings)]
public async Task<List<StockTaking>> GetStockTakings()
{
return await ctx.StockTakings.GetAll(true).ToListAsync();
}
public async Task<List<StockTaking>> GetStockTakingsByProductId(int productId)
{
throw new NotImplementedException();
}
[SignalR(SignalRTags.AddStockTaking)]
public async Task<StockTaking> AddStockTaking(StockTaking stockTaking)
{
var result = await ctx.TransactionSafeAsync(async _ =>
{
await ctx.StockTakings.InsertAsync(stockTaking);
var productDtos = await ctx.ProductDtos.GetAll(true).ToListAsync();
foreach (var productDto in productDtos)
{
var stockTakingItem = new StockTakingItem
{
StockTakingId = stockTaking.Id,
ProductId = productDto.Id,
//IsMeasurable = productDto.IsMeasurable,
OriginalStockQuantity = productDto.StockQuantity,
OriginalNetWeight = productDto.NetWeight
};
await ctx.StockTakingItems.InsertAsync(stockTakingItem);
}
return true;
});
if (result) return await ctx.StockTakings.GetByIdAsync(stockTaking.Id, false);
return null;
}
public async Task<StockTaking> UpdateStockTaking(StockTaking stockTaking)
{
throw new NotImplementedException();
}
[SignalR(SignalRTags.GetStockTakingItems)]
public async Task<List<StockTakingItem>> GetStockTakingItems()
{
return await ctx.StockTakingItems.GetAll(true).ToListAsync();
}
[SignalR(SignalRTags.GetStockTakingItemsById)]
public async Task<StockTakingItem> GetStockTakingItemsById(int stockTakingItemId)
{
var result = await ctx.StockTakingItems.GetByIdAsync(stockTakingItemId, true);
return result;
}
public async Task<List<StockTakingItem>> GetStockTakingItemsByProductId(int productId)
{
throw new NotImplementedException();
}
public async Task<List<StockTakingItem>> GetStockTakingItemsByStockTakingId(int stockTakingId)
{
throw new NotImplementedException();
}
public async Task<StockTakingItem> AddStockTakingItem(StockTakingItem stockTakingItem)
{
throw new NotImplementedException();
}
public async Task<StockTakingItem> UpdateStockTakingItem(StockTakingItem stockTakingItem)
{
throw new NotImplementedException();
}
public async Task<List<StockTakingItemPallet>> GetStockTakingItemPallets()
{
throw new NotImplementedException();
}
public async Task<List<StockTakingItemPallet>> GetStockTakingItemPalletsByProductId(int productId)
{
throw new NotImplementedException();
}
public async Task<StockTakingItemPallet> AddStockTakingItemPallet(StockTakingItemPallet stockTakingItemPallet)
{
throw new NotImplementedException();
}
public async Task<StockTakingItemPallet> UpdateStockTakingItemPallet(StockTakingItemPallet stockTakingItemPallet)
{
throw new NotImplementedException();
}
}

View File

@ -70,20 +70,30 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Controllers
return await ctx.GenericAttributeDtos.GetByIdAsync(genericAttributeDto.Id); return await ctx.GenericAttributeDtos.GetByIdAsync(genericAttributeDto.Id);
} }
[SignalR(SignalRTags.GetStockQuantityHistoryDtos)]
public async Task<List<StockQuantityHistoryDto>> GetStockQuantityHistoryDtos()
{
_logger.Detail($"GetStockQuantityHistoryDtos invoked; lastDaysCount: {LastShippingDays}");
var fromDateUtc = DateTime.UtcNow.Date.AddDays(-LastShippingDays);
return await ctx.StockQuantityHistoryDtos.GetAll(true).Where(sqh => sqh.CreatedOnUtc >= fromDateUtc).ToListAsync();
}
[SignalR(SignalRTags.GetStockQuantityHistoryDtosByProductId)]
public async Task<List<StockQuantityHistoryDto>> GetStockQuantityHistoryDtosByProductId(int productId)
{
_logger.Detail($"GetStockQuantityHistoryDtosByProductId invoked; productId: {productId}; lastDaysCount: {LastShippingDays}");
var fromDateUtc = DateTime.UtcNow.Date.AddDays(-LastShippingDays);
return await ctx.StockQuantityHistoryDtos.GetByProductIdAsync(productId, true).Where(sqh => sqh.CreatedOnUtc >= fromDateUtc).ToListAsync();
}
[SignalR(SignalRTags.GetMeasuringModels)] [SignalR(SignalRTags.GetMeasuringModels)]
public Task<List<MeasuringModel>> GetMeasuringModels() public Task<List<MeasuringModel>> GetMeasuringModels()
{ {
throw new NotImplementedException("GetMeasuringModels"); throw new NotImplementedException("GetMeasuringModels");
} }
[SignalR(SignalRTags.GetStockQuantityHistoryDtos)]
public async Task<List<StockQuantityHistoryDto>> GetStockQuantityHistoryDtos()
=> await ctx.StockQuantityHistoryDtos.GetAll(true).ToListAsync();
[SignalR(SignalRTags.GetStockQuantityHistoryDtosByProductId)]
public async Task<List<StockQuantityHistoryDto>> GetStockQuantityHistoryDtosByProductId(int productId)
=> await ctx.StockQuantityHistoryDtos.GetByProductIdAsync(productId, true).ToListAsync();
[SignalR(SignalRTags.GetPartners)] [SignalR(SignalRTags.GetPartners)]
public async Task<List<Partner>> GetPartners() public async Task<List<Partner>> GetPartners()
{ {

View File

@ -6,6 +6,7 @@ using FruitBank.Common.Dtos;
using FruitBank.Common.Entities; using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces; using FruitBank.Common.Interfaces;
using FruitBank.Common.Models; using FruitBank.Common.Models;
using Mango.Nop.Core.Dtos;
using Mango.Nop.Core.Entities; using Mango.Nop.Core.Entities;
using Mango.Nop.Core.Extensions; using Mango.Nop.Core.Extensions;
using Mango.Nop.Core.Loggers; using Mango.Nop.Core.Loggers;
@ -25,6 +26,7 @@ using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Catalog; using Nop.Services.Catalog;
using Nop.Services.Security; using Nop.Services.Security;
using WebMarkupMin.Core.Loggers; using WebMarkupMin.Core.Loggers;
using static Nop.Services.Security.StandardPermission;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
@ -101,8 +103,7 @@ public class FruitBankDbContext : MgDbContextBase,
Files = filesDbTable; Files = filesDbTable;
Partners = partnerDbTable; Partners = partnerDbTable;
Products = productRepository;
ProductDtos = productDtoDbTable; ProductDtos = productDtoDbTable;
OrderDtos = orderDtoDbTable; OrderDtos = orderDtoDbTable;
@ -766,4 +767,5 @@ public class FruitBankDbContext : MgDbContextBase,
await CustomerAddressMappings.InsertAsync(customerAddressMapping); await CustomerAddressMappings.InsertAsync(customerAddressMapping);
return customerAddressMapping; return customerAddressMapping;
} }
} }

View File

@ -0,0 +1,10 @@
using FruitBank.Common.Entities;
using Mango.Nop.Data.Interfaces;
using Nop.Data;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces;
public interface IStockTakingDbSet<TDbTable> : IMgDbTableBase where TDbTable : IRepository<StockTaking>
{
public TDbTable StockTakings { get; set; }
}

View File

@ -0,0 +1,10 @@
using FruitBank.Common.Entities;
using Mango.Nop.Data.Interfaces;
using Nop.Data;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces;
public interface IStockTakingItemDbSet<TDbTable> : IMgDbTableBase where TDbTable : IRepository<StockTakingItem>
{
public TDbTable StockTakingItems { get; set; }
}

View File

@ -0,0 +1,10 @@
using FruitBank.Common.Entities;
using Mango.Nop.Data.Interfaces;
using Nop.Data;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces;
public interface IStockTakingItemPalletDbSet<TDbTable> : IMgDbTableBase where TDbTable : IRepository<StockTakingItemPallet>
{
public TDbTable StockTakingItemPallets { get; set; }
}

View File

@ -0,0 +1,74 @@
#nullable enable
using AyCode.Core.Loggers;
using FruitBank.Common.Dtos;
using Mango.Nop.Core.Entities;
using Mango.Nop.Core.Loggers;
using Mango.Nop.Data.Repositories;
using Nop.Core;
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Orders;
using Nop.Core.Events;
using Nop.Data;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Catalog;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class StockTakingDbContext : MgDbContextBase,
IStockTakingDbSet<StockTakingDbTable>,
IStockTakingItemDbSet<StockTakingItemDbTable>,
IStockTakingItemPalletDbSet<StockTakingItemPalletDbTable>
{
public ProductDtoDbTable ProductDtos { get; set; }
public StockTakingDbTable StockTakings { get; set; }
public StockTakingItemDbTable StockTakingItems { get; set; }
public StockTakingItemPalletDbTable StockTakingItemPallets { get; set; }
public StockQuantityHistoryDtoDbTable StockQuantityHistoryDtos { get; set; }
public IRepository<GenericAttribute> GenericAttributes { get; set; }
public IRepository<StockQuantityHistory> StockQuantityHistories { get; set; }
public IRepository<StockQuantityHistoryExt> StockQuantityHistoriesExt { get; set; }
private readonly IStoreContext _storeContext;
private readonly IProductService _productService;
private readonly IStaticCacheManager _staticCacheManager;
protected readonly IEventPublisher _eventPublisher;
public StockTakingDbContext(INopDataProvider dataProvider, ILockService lockService, IStoreContext storeContext,
ProductDtoDbTable productDtoDbTable,
StockQuantityHistoryDtoDbTable stockQuantityHistoryDtos,
StockTakingDbTable stockTakingDbTable,
StockTakingItemDbTable stockTakingItemDbTable,
StockTakingItemPalletDbTable stockTakingItemPalletDbTable,
IProductService productService, IStaticCacheManager staticCacheManager,
IRepository<Order> orderRepository,
IRepository<OrderItem> orderItemRepository,
IRepository<Product> productRepository,
IRepository<GenericAttribute> genericAttributes,
IRepository<StockQuantityHistory> stockQuantityHistories,
IRepository<StockQuantityHistoryExt> stockQuantityHistoriesExt,
IEventPublisher eventPublisher,
IEnumerable<IAcLogWriterBase> logWriters) : base(productRepository, orderRepository, orderItemRepository, dataProvider, lockService, new Logger<StockTakingDbContext>(logWriters.ToArray()))
{
_eventPublisher = eventPublisher;
_storeContext = storeContext;
_productService = productService;
_staticCacheManager = staticCacheManager;
ProductDtos = productDtoDbTable;
GenericAttributes = genericAttributes;
StockQuantityHistories = stockQuantityHistories;
StockQuantityHistoriesExt = stockQuantityHistoriesExt;
StockQuantityHistoryDtos = stockQuantityHistoryDtos;
StockTakings = stockTakingDbTable;
StockTakingItems = stockTakingItemDbTable;
StockTakingItemPallets = stockTakingItemPalletDbTable;
}
}

View File

@ -0,0 +1,32 @@
using FruitBank.Common.Entities;
using LinqToDB;
using Mango.Nop.Data.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Events;
using Nop.Data;
using static LinqToDB.Reflection.Methods.LinqToDB.Insert;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class StockTakingDbTable : MgDbTableBase<StockTaking>
{
public StockTakingDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings)
{
}
public override IQueryable<StockTaking> GetAll() => base.GetAll();
public IQueryable<StockTaking> GetAll(bool loadRelations)
{
return loadRelations
? GetAll()
.LoadWith(st => st.StockTakingItems).ThenLoad(sti => sti.Product).ThenLoad(prod => prod.GenericAttributes)
//.LoadWith(st => st.StockTakingItems).ThenLoad(sti => sti.StockTakingItemPallets)
: GetAll().LoadWith(st => st.StockTakingItems);
}
public Task<StockTaking> GetByIdAsync(int id, bool loadRelations)
=> GetAll(loadRelations).FirstOrDefaultAsync(st => st.Id == id);
}

View File

@ -0,0 +1,31 @@
using FruitBank.Common.Entities;
using LinqToDB;
using Mango.Nop.Data.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Events;
using Nop.Data;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class StockTakingItemDbTable : MgDbTableBase<StockTakingItem>
{
public StockTakingItemDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings)
{
}
public override IQueryable<StockTakingItem> GetAll() => base.GetAll();
public IQueryable<StockTakingItem> GetAll(bool loadRelations)
{
return loadRelations
? GetAll()
.LoadWith(sti => sti.StockTaking)
//.LoadWith(sti => sti.StockTakingItemPallets)
.LoadWith(sti => sti.Product).ThenLoad(prod => prod.GenericAttributes)
: GetAll();
}
public Task<StockTakingItem> GetByIdAsync(int stockTakingItemId, bool loadRelations) => GetAll(loadRelations).FirstOrDefaultAsync(sti => sti.Id == stockTakingItemId);
}

View File

@ -0,0 +1,28 @@
using FruitBank.Common.Entities;
using LinqToDB;
using Mango.Nop.Data.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Events;
using Nop.Data;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class StockTakingItemPalletDbTable : MgDbTableBase<StockTakingItemPallet>
{
public StockTakingItemPalletDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings)
{
}
public override IQueryable<StockTakingItemPallet> GetAll() => base.GetAll();
public IQueryable<StockTakingItemPallet> GetAll(bool loadRelations)
{
return loadRelations
? GetAll()
.LoadWith(stip => stip.StockTakingItem).ThenLoad(sti => sti.StockTaking)
.LoadWith(stip => stip.StockTakingItem).ThenLoad(sti => sti.Product).ThenLoad(prod => prod.GenericAttributes)
: GetAll();
}
}

View File

@ -75,11 +75,17 @@ public class PluginNopStartup : INopStartup
services.AddScoped<StockQuantityHistoryDtoDbTable>(); services.AddScoped<StockQuantityHistoryDtoDbTable>();
services.AddScoped<StockTakingDbTable>();
services.AddScoped<StockTakingItemDbTable>();
services.AddScoped<StockTakingItemPalletDbTable>();
services.AddScoped<StockTakingDbContext>();
services.AddScoped<FruitBankDbContext>(); services.AddScoped<FruitBankDbContext>();
services.AddScoped<SignalRSendToClientService>(); services.AddScoped<SignalRSendToClientService>();
services.AddScoped<IFruitBankDataControllerServer, FruitBankDataController>(); services.AddScoped<IFruitBankDataControllerServer, FruitBankDataController>();
services.AddScoped<ICustomOrderSignalREndpointServer, CustomOrderSignalREndpoint>(); services.AddScoped<ICustomOrderSignalREndpointServer, CustomOrderSignalREndpoint>();
services.AddScoped<IStockSignalREndpointServer, StockSignalREndpointServer>();
//services.AddScoped<CustomModelFactory, ICustomerModelFactory>(); //services.AddScoped<CustomModelFactory, ICustomerModelFactory>();
services.AddScoped<IPriceCalculationService, CustomPriceCalculationService>(); services.AddScoped<IPriceCalculationService, CustomPriceCalculationService>();

View File

@ -7,6 +7,7 @@ using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common; using Nop.Core.Domain.Common;
using Nop.Core.Domain.Orders; using Nop.Core.Domain.Orders;
using Nop.Data.Mapping; using Nop.Data.Mapping;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
namespace Nop.Plugin.Misc.FruitBankPlugin.Mapping; namespace Nop.Plugin.Misc.FruitBankPlugin.Mapping;
@ -37,7 +38,10 @@ public partial class NameCompatibility : INameCompatibility
{ typeof(StockQuantityHistoryDto), nameof(StockQuantityHistory)}, { typeof(StockQuantityHistoryDto), nameof(StockQuantityHistory)},
{ typeof(StockQuantityHistoryExt), FruitBankConstClient.StockQuantityHistoryExtDbTableName}, { typeof(StockQuantityHistoryExt), FruitBankConstClient.StockQuantityHistoryExtDbTableName},
{ typeof(StockTaking), FruitBankConstClient.StockTakingDbTableName},
{ typeof(StockTakingItem), FruitBankConstClient.StockTakingItemDbTableName},
{ typeof(StockTakingItemPallet), FruitBankConstClient.StockTakingItemPalletDbTableName},
}; };

View File

@ -24,10 +24,10 @@
<PackageReference Include="DevExtreme.AspNet.Data" Version="5.1.0" /> <PackageReference Include="DevExtreme.AspNet.Data" Version="5.1.0" />
<!-- Your existing packages --> <!-- Your existing packages -->
<PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Common" Version="9.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.Json" Version="9.0.11" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.10" /> <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="9.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.10" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.11" />
<!--<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.10" />--> <!--<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.10" />-->
<PackageReference Include="PdfPig" Version="0.1.11" /> <PackageReference Include="PdfPig" Version="0.1.11" />