This commit is contained in:
Adam 2025-10-18 18:35:38 +02:00
commit 8aa84f1e79
46 changed files with 1232 additions and 663 deletions

View File

@ -11,7 +11,7 @@ using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax; using Nop.Core.Domain.Tax;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Factories; using Nop.Plugin.Misc.FruitBankPlugin.Factories;
using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Services.Common; using Nop.Services.Common;
using Nop.Services.Customers; using Nop.Services.Customers;
using Nop.Services.Messages; using Nop.Services.Messages;
@ -132,7 +132,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
return RedirectToAction("List", "Order"); return RedirectToAction("List", "Order");
// store attributes in GenericAttribute table // store attributes in GenericAttribute table
await _genericAttributeService.SaveAttributeAsync(order, nameof(OrderModelExtended.IsMeasurable), model.IsMeasurable); await _genericAttributeService.SaveAttributeAsync(order, nameof(IMeasurable.IsMeasurable), model.IsMeasurable);
await _genericAttributeService.SaveAttributeAsync(order, nameof(IOrderDto.DateOfReceipt), model.DateOfReceipt); await _genericAttributeService.SaveAttributeAsync(order, nameof(IOrderDto.DateOfReceipt), model.DateOfReceipt);
_notificationService.SuccessNotification("Custom attributes saved successfully."); _notificationService.SuccessNotification("Custom attributes saved successfully.");

View File

@ -13,6 +13,7 @@ using Nop.Core.Domain.Tax;
using Nop.Core.Domain.Vendors; using Nop.Core.Domain.Vendors;
using Nop.Core.Http; using Nop.Core.Http;
using Nop.Core.Infrastructure; using Nop.Core.Infrastructure;
using Nop.Plugin.Misc.FruitBankPlugin.Factories;
using Nop.Services.Catalog; using Nop.Services.Catalog;
using Nop.Services.Common; using Nop.Services.Common;
using Nop.Services.Configuration; using Nop.Services.Configuration;
@ -44,6 +45,7 @@ public partial class CustomProductController : BaseAdminController
{ {
#region Fields #region Fields
private readonly CustomProductModelFactory _productModelFactory;
protected readonly AdminAreaSettings _adminAreaSettings; protected readonly AdminAreaSettings _adminAreaSettings;
protected readonly IAclService _aclService; protected readonly IAclService _aclService;
protected readonly IBackInStockSubscriptionService _backInStockSubscriptionService; protected readonly IBackInStockSubscriptionService _backInStockSubscriptionService;
@ -70,7 +72,6 @@ public partial class CustomProductController : BaseAdminController
protected readonly IProductAttributeFormatter _productAttributeFormatter; protected readonly IProductAttributeFormatter _productAttributeFormatter;
protected readonly IProductAttributeParser _productAttributeParser; protected readonly IProductAttributeParser _productAttributeParser;
protected readonly IProductAttributeService _productAttributeService; protected readonly IProductAttributeService _productAttributeService;
protected readonly IProductModelFactory _productModelFactory;
protected readonly IProductService _productService; protected readonly IProductService _productService;
protected readonly IProductTagService _productTagService; protected readonly IProductTagService _productTagService;
protected readonly ISettingService _settingService; protected readonly ISettingService _settingService;
@ -159,7 +160,7 @@ public partial class CustomProductController : BaseAdminController
_productAttributeFormatter = productAttributeFormatter; _productAttributeFormatter = productAttributeFormatter;
_productAttributeParser = productAttributeParser; _productAttributeParser = productAttributeParser;
_productAttributeService = productAttributeService; _productAttributeService = productAttributeService;
_productModelFactory = productModelFactory; _productModelFactory = productModelFactory as CustomProductModelFactory;
_productService = productService; _productService = productService;
_productTagService = productTagService; _productTagService = productTagService;
_settingService = settingService; _settingService = settingService;
@ -878,7 +879,6 @@ public partial class CustomProductController : BaseAdminController
[CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)] [CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)]
public virtual async Task<IActionResult> List() public virtual async Task<IActionResult> List()
{ {
//prepare model
var model = await _productModelFactory.PrepareProductSearchModelAsync(new ProductSearchModel()); var model = await _productModelFactory.PrepareProductSearchModelAsync(new ProductSearchModel());
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Product/List.cshtml", model); return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Product/List.cshtml", model);
@ -918,7 +918,7 @@ public partial class CustomProductController : BaseAdminController
public virtual async Task<IActionResult> ProductList(ProductSearchModel searchModel) public virtual async Task<IActionResult> ProductList(ProductSearchModel searchModel)
{ {
//prepare model //prepare model
var model = await _productModelFactory.PrepareProductListModelAsync(searchModel); var model = await _productModelFactory.PrepareProductListModelExtendedAsync(searchModel);
return Json(model); return Json(model);
} }

View File

@ -1,6 +1,7 @@
@model ProductSearchModel @model ProductSearchModel
@using Nop.Core.Domain.Catalog; @using Nop.Core.Domain.Catalog;
@using Nop.Plugin.Misc.FruitBankPlugin.Models.Products
@{ @{
//page title //page title
@ -238,13 +239,14 @@
IsMasterCheckBox = true, IsMasterCheckBox = true,
Render = new RenderCheckBox("checkbox_products"), Render = new RenderCheckBox("checkbox_products"),
ClassName = NopColumnClassDefaults.CenterAll, ClassName = NopColumnClassDefaults.CenterAll,
Width = "50" Width = "40"
}, },
new ColumnProperty(nameof(ProductModel.PictureThumbnailUrl)) new ColumnProperty(nameof(ProductModel.PictureThumbnailUrl))
{ {
Title = T("Admin.Catalog.Products.Fields.PictureThumbnailUrl").Text, Title = T("Admin.Catalog.Products.Fields.PictureThumbnailUrl").Text,
Width = "100", Width = "100",
Render = new RenderPicture(width: 100) Render = new RenderPicture(width: 100),
Visible = false
}, },
new ColumnProperty(nameof(ProductModel.Name)) new ColumnProperty(nameof(ProductModel.Name))
{ {
@ -252,7 +254,7 @@
}, },
new ColumnProperty(nameof(ProductModel.Sku)) new ColumnProperty(nameof(ProductModel.Sku))
{ {
Title = T("Admin.Catalog.Products.Fields.Sku").Text, Title = "SKU", //T("Admin.Catalog.Products.Fields.Sku").Text,
Width = "100" Width = "100"
}, },
new ColumnProperty(nameof(ProductModel.FormattedPrice)) new ColumnProperty(nameof(ProductModel.FormattedPrice))
@ -263,10 +265,29 @@
{ {
Title = T("Admin.Catalog.Products.Fields.StockQuantity").Text Title = T("Admin.Catalog.Products.Fields.StockQuantity").Text
}, },
new ColumnProperty(nameof(ProductModelExtended.NetWeight))
{
Title = "Súly(kg)"//T("Admin.Catalog.Products.Fields.NetWeight").Text
},
new ColumnProperty(nameof(ProductModelExtended.Tare))
{
Title = "Tára(kg)"//T("Admin.Catalog.Products.Fields.Tare").Text
},
new ColumnProperty(nameof(ProductModelExtended.IncomingQuantity))
{
Title = "Bejövő"//T("Admin.Catalog.Products.Fields.Tare").Text
},
new ColumnProperty(nameof(ProductModelExtended.IsMeasurable))
{
Title = "Mérendő?",//T("Admin.Catalog.Products.Fields.Tare").Text
Width = "75",
ClassName = NopColumnClassDefaults.CenterAll,
Render = new RenderBoolean()
},
new ColumnProperty(nameof(ProductModel.Published)) new ColumnProperty(nameof(ProductModel.Published))
{ {
Title = T("Admin.Catalog.Products.Fields.Published").Text, Title = T("Admin.Catalog.Products.Fields.Published").Text,
Width = "80", Width = "75",
ClassName = NopColumnClassDefaults.CenterAll, ClassName = NopColumnClassDefaults.CenterAll,
Render = new RenderBoolean() Render = new RenderBoolean()
}, },
@ -282,6 +303,7 @@
<script> <script>
$(function() { $(function() {
$('#delete-selected-action-confirmation-submit-button').bind('click', function () { $('#delete-selected-action-confirmation-submit-button').bind('click', function () {
var postData = { var postData = {

View File

@ -5,7 +5,7 @@ using Microsoft.AspNetCore.Mvc;
using Nop.Core; using Nop.Core;
using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Orders; using Nop.Core.Domain.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Services; using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Common; using Nop.Services.Common;
using Nop.Web.Areas.Admin.Models.Catalog; using Nop.Web.Areas.Admin.Models.Catalog;
@ -37,7 +37,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Components
if (model.OrderId > 0) if (model.OrderId > 0)
{ {
var orderPickupAttributeValue = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Order, DateTime?>(model.OrderId, nameof(IOrderDto.DateOfReceipt)); var orderPickupAttributeValue = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Order, DateTime?>(model.OrderId, nameof(IOrderDto.DateOfReceipt));
var orderMeasurableAttributeValue = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Order, bool>(model.OrderId, nameof(OrderModelExtended.IsMeasurable)); var orderMeasurableAttributeValue = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Order, bool>(model.OrderId, nameof(IMeasurable.IsMeasurable));
model.IsMeasurable = orderMeasurableAttributeValue; model.IsMeasurable = orderMeasurableAttributeValue;
if(orderPickupAttributeValue.HasValue && orderPickupAttributeValue.Value != DateTime.MinValue) if(orderPickupAttributeValue.HasValue && orderPickupAttributeValue.Value != DateTime.MinValue)

View File

@ -42,7 +42,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Components
} }
model.Tare = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Product, double>(model.ProductId, nameof(ITare.Tare)); model.Tare = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Product, double>(model.ProductId, nameof(ITare.Tare));
model.IncomingQuantity = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Product, int>(model.ProductId, "IncomingQuantity"); model.IncomingQuantity = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Product, int>(model.ProductId, nameof(IIncomingQuantity.IncomingQuantity));
} }
return View("~/Plugins/Misc.FruitBankPlugin/Views/ProductAttributes.cshtml", model); return View("~/Plugins/Misc.FruitBankPlugin/Views/ProductAttributes.cshtml", model);

View File

@ -4,26 +4,17 @@ using AyCode.Utils.Extensions;
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 FruitBank.Common.Server;
using LinqToDB;
using LinqToDB.Common;
using Mango.Nop.Core.Loggers;
using Mango.Nop.Core.Repositories; using Mango.Nop.Core.Repositories;
using Nop.Core; using Nop.Core;
using Nop.Core.Caching; using Nop.Core.Caching;
using Nop.Core.ComponentModel;
using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Customers; using Nop.Core.Domain.Customers;
using Nop.Data; using Nop.Data;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces;
using Nop.Plugin.Misc.FruitBankPlugin.Services; using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Catalog; using Nop.Services.Catalog;
using Nop.Services.Common;
using System.Transactions;
using DevExpress.XtraExport.Helpers;
using FruitBank.Common.Dtos; using FruitBank.Common.Dtos;
using Mango.Nop.Core.Dtos; using Mango.Nop.Core.Extensions;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Nop.Core.Domain.Orders; using Nop.Core.Domain.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
@ -45,6 +36,8 @@ public class FruitBankDbContext : MgDbContextBase,
private readonly IProductService _productService; private readonly IProductService _productService;
private readonly IStaticCacheManager _staticCacheManager; private readonly IStaticCacheManager _staticCacheManager;
public ProductDtoDbTable ProductDtos { get; set; }
public OrderDtoDbTable OrderDtos { get; set; } public OrderDtoDbTable OrderDtos { get; set; }
public OrderItemDtoDbTable OrderItemDtos { get; set; } public OrderItemDtoDbTable OrderItemDtos { get; set; }
@ -67,7 +60,7 @@ public class FruitBankDbContext : MgDbContextBase,
public FruitBankDbContext(INopDataProvider dataProvider, ILockService lockService, FruitBankAttributeService fruitBankAttributeService, IStoreContext storeContext, public FruitBankDbContext(INopDataProvider dataProvider, ILockService lockService, FruitBankAttributeService fruitBankAttributeService, IStoreContext storeContext,
PartnerDbTable partnerDbTable, ShippingDbTable shippingDbTable, ShippingDocumentDbTable shippingDocumentDbTable, ShippingItemDbTable shippingItemDbTable, PartnerDbTable partnerDbTable, ShippingDbTable shippingDbTable, ShippingDocumentDbTable shippingDocumentDbTable, ShippingItemDbTable shippingItemDbTable,
ShippingItemPalletDbTable shippingItemPalletDbTable, FilesDbTable filesDbTable, ShippingDocumentToFilesDbTable shippingDocumentToFilesDbTable, ShippingItemPalletDbTable shippingItemPalletDbTable, FilesDbTable filesDbTable, ShippingDocumentToFilesDbTable shippingDocumentToFilesDbTable,
OrderDtoDbTable orderDtoDbTable, OrderItemDtoDbTable orderItemDtoDbTable, OrderItemPalletDbTable orderItemPalletDbTable, ProductDtoDbTable productDtoDbTable, OrderDtoDbTable orderDtoDbTable, OrderItemDtoDbTable orderItemDtoDbTable, OrderItemPalletDbTable orderItemPalletDbTable,
IProductService productService, IStaticCacheManager staticCacheManager, IProductService productService, IStaticCacheManager staticCacheManager,
IRepository<Product> productRepository, IRepository<Product> productRepository,
IRepository<Customer> customerRepository, IRepository<Customer> customerRepository,
@ -84,6 +77,8 @@ public class FruitBankDbContext : MgDbContextBase,
Partners = partnerDbTable; Partners = partnerDbTable;
Products = productRepository; Products = productRepository;
ProductDtos = productDtoDbTable;
OrderDtos = orderDtoDbTable; OrderDtos = orderDtoDbTable;
OrderItemDtos = orderItemDtoDbTable; OrderItemDtos = orderItemDtoDbTable;
OrderItemPallets = orderItemPalletDbTable; OrderItemPallets = orderItemPalletDbTable;
@ -131,17 +126,17 @@ public class FruitBankDbContext : MgDbContextBase,
=> GetAllProducts(includeDeleted).Select(product => new ProductDto(product)); => GetAllProducts(includeDeleted).Select(product => new ProductDto(product));
public IAsyncEnumerable<MeasuringProductDto> GetAllMeasuringProductDtos(bool includeDeleted) public IAsyncEnumerable<MeasuringProductDto> GetAllMeasuringProductDtos(bool includeDeleted)
=> GetAllProducts(includeDeleted).SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id))); => GetAllProducts(includeDeleted).AsEnumerable().SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id)));
public async Task<MeasuringProductDto?> GetMeasuringProductDtoByIdAsync(int productId) 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(); => await Products.Table.Where(product => product.Id == productId).AsEnumerable().SelectAwait(async product => new MeasuringProductDto(product, await GetMeasuringAttributeValuesByProductIdAsync(product.Id))).FirstOrDefaultAsync();
public async Task<MeasuringAttributeValues?> GetMeasuringAttributeValuesByProductIdAsync(int productId) public async Task<MeasuringAttributeValues?> GetMeasuringAttributeValuesByProductIdAsync(int productId)
=> await _fruitBankAttributeService.GetMeasuringAttributeValuesAsync<Product>(productId); => await _fruitBankAttributeService.GetMeasuringAttributeValuesAsync<Product>(productId);
public async Task DeleteShippingSafeAsync(Shipping shipping) public async Task DeleteShippingSafeAsync(Shipping shipping)
{ {
await TransactionSafeAsync(async tr => await TransactionSafeAsync(async _ =>
{ {
await Shippings.DeleteAsync(shipping, true); await Shippings.DeleteAsync(shipping, true);
return true; return true;
@ -150,7 +145,7 @@ public class FruitBankDbContext : MgDbContextBase,
public async Task DeleteShippingDocumentSafeAsync(ShippingDocument shippingDocument) public async Task DeleteShippingDocumentSafeAsync(ShippingDocument shippingDocument)
{ {
await TransactionSafeAsync(async tr => await TransactionSafeAsync(async _ =>
{ {
await ShippingDocuments.DeleteAsync(shippingDocument, true); await ShippingDocuments.DeleteAsync(shippingDocument, true);
return true; return true;
@ -159,7 +154,7 @@ public class FruitBankDbContext : MgDbContextBase,
public async Task DeleteShippingItemSafeAsync(ShippingItem shippingItem) public async Task DeleteShippingItemSafeAsync(ShippingItem shippingItem)
{ {
await TransactionSafeAsync(async tr => await TransactionSafeAsync(async _ =>
{ {
await ShippingItems.DeleteAsync(shippingItem, true); await ShippingItems.DeleteAsync(shippingItem, true);
return true; return true;
@ -181,17 +176,17 @@ public class FruitBankDbContext : MgDbContextBase,
{ {
try try
{ {
Product? product = null; ProductDto? productDto = null;
var productIsMeasurable = false; var productIsMeasurable = false;
if (shippingItem.ProductId > 0) if (shippingItem.ProductId > 0)
{ {
product = await Products.GetByIdAsync(shippingItem.ProductId); productDto = await ProductDtos.GetByIdAsync(shippingItem.ProductId!.Value, true);
if (product == null) if (productDto == null)
throw new Exception($"shippingItem.ProductId > 0 && product == null; shippingItem.ProductId: {shippingItem.ProductId}"); throw new Exception($"shippingItem.ProductId > 0 && product == null; shippingItem.ProductId: {shippingItem.ProductId}");
productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync<Product>(product.Id); productIsMeasurable = productDto.IsMeasurable;
} }
shippingItem.IsMeasurable = productIsMeasurable; shippingItem.IsMeasurable = productIsMeasurable;
@ -207,7 +202,7 @@ public class FruitBankDbContext : MgDbContextBase,
var dbShippingItem = await ShippingItems.GetByIdAsync(shippingItem.Id, false); var dbShippingItem = await ShippingItems.GetByIdAsync(shippingItem.Id, false);
if (dbShippingItem == null) throw new Exception($"dbShippingItem == null; shippingItem.Id: {shippingItem.Id}"); if (dbShippingItem == null) throw new Exception($"dbShippingItem == null; shippingItem.Id: {shippingItem.Id}");
var isMeasuredPrerequisite = product != null && shippingItem.PalletsOnDocument == shippingItem.ShippingItemPallets.Count var isMeasuredPrerequisite = productDto != null && shippingItem.PalletsOnDocument == shippingItem.ShippingItemPallets.Count
&& shippingItem.ShippingItemPallets.All(x => x.IsMeasuredAndValid(shippingItem.IsMeasurable)); && shippingItem.ShippingItemPallets.All(x => x.IsMeasuredAndValid(shippingItem.IsMeasurable));
SetupShippingItemMeasuringValues(shippingItem, isMeasuredPrerequisite); SetupShippingItemMeasuringValues(shippingItem, isMeasuredPrerequisite);
@ -230,36 +225,51 @@ public class FruitBankDbContext : MgDbContextBase,
if (shippingItem.IsMeasured) if (shippingItem.IsMeasured)
{ {
product!.StockQuantity += productIdChanged ? shippingItem.MeasuredQuantity : shippingItem.MeasuredQuantity - dbShippingItem.MeasuredQuantity; var quantityInc = productIdChanged ? shippingItem.MeasuredQuantity : shippingItem.MeasuredQuantity - dbShippingItem.MeasuredQuantity;
productDto!.StockQuantity += quantityInc;
if (!await UpdateProductStockQuantityAsync(product, true)) if (!await UpdateProductDtoStockQuantityAsync(productDto, true))
throw new Exception($"UpdateProductStockQuantity() == false; shippingItem! product.Id: {product.Id}"); throw new Exception($"UpdateProductStockQuantity() == false; shippingItem! product.Id: {productDto.Id}");
var incomingQuantity = productDto.GenericAttributes.GetValueOrNull<int>(nameof(IIncomingQuantity.IncomingQuantity));
if (incomingQuantity != null)
{
await _fruitBankAttributeService.UpdateGenericAttributeAsync<Product, int>
(productDto.Id, nameof(IIncomingQuantity.IncomingQuantity), incomingQuantity.Value - quantityInc);
}
if (productIsMeasurable) if (productIsMeasurable)
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(product.Id, {
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(productDto.Id,
productIdChanged ? shippingItem.MeasuredNetWeight : shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight, productIdChanged ? shippingItem.MeasuredNetWeight : shippingItem.MeasuredNetWeight - dbShippingItem.MeasuredNetWeight,
productIdChanged ? shippingItem.MeasuredGrossWeight : shippingItem.MeasuredGrossWeight - dbShippingItem.MeasuredGrossWeight,
shippingItem.IsMeasurable, true); shippingItem.IsMeasurable, true);
} }
}
//if (productIdUnchanged || !dbShippingItem.IsMeasured) return true; //if (productIdUnchanged || !dbShippingItem.IsMeasured) return true;
if (!productIdChanged && (shippingItem.IsMeasured || !dbShippingItem.IsMeasured)) return true; if (!productIdChanged && (shippingItem.IsMeasured || !dbShippingItem.IsMeasured)) return true;
product = await Products.GetByIdAsync(dbShippingItem.ProductId); productDto = await ProductDtos.GetByIdAsync(dbShippingItem.ProductId);
if (product != null) if (productDto != null)
{ {
productIsMeasurable = await _fruitBankAttributeService.IsMeasurableEntityAsync<Product>(product.Id); productIsMeasurable = productDto.IsMeasurable;
product.StockQuantity -= dbShippingItem.MeasuredQuantity; productDto.StockQuantity -= dbShippingItem.MeasuredQuantity;
if (!await UpdateProductStockQuantityAsync(product, true)) if (!await UpdateProductDtoStockQuantityAsync(productDto, true))
throw new Exception($"UpdateProductStockQuantity() == false; dbShippingItem! product.Id: {product.Id}"); throw new Exception($"UpdateProductStockQuantity() == false; dbShippingItem! product.Id: {productDto.Id}");
var incomingQuantity = productDto.GenericAttributes.GetValueOrNull<int>(nameof(IIncomingQuantity.IncomingQuantity));
if (incomingQuantity != null)
{
await _fruitBankAttributeService.UpdateGenericAttributeAsync<Product, int>
(productDto.Id, nameof(IIncomingQuantity.IncomingQuantity), incomingQuantity.Value + dbShippingItem.MeasuredQuantity);
}
if (!productIsMeasurable) return true; if (!productIsMeasurable) return true;
var measuringValues = new MeasuringAttributeValues(product.Id, -dbShippingItem.MeasuredNetWeight, -dbShippingItem.MeasuredGrossWeight, dbShippingItem.IsMeasurable); var measuringValues = new MeasuringAttributeValues(productDto.Id, -dbShippingItem.MeasuredNetWeight, dbShippingItem.IsMeasurable);
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(measuringValues, true); await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(measuringValues, true);
} }
else Logger.Warning($"product == null; dbShippingItem.ProductId: {dbShippingItem.ProductId}"); else Logger.Warning($"product == null; dbShippingItem.ProductId: {dbShippingItem.ProductId}");
//else //TODO: productIdUnchanged-et lekezelni! - J. //else //TODO: productIdUnchanged-et lekezelni! - J.
@ -306,7 +316,7 @@ public class FruitBankDbContext : MgDbContextBase,
} }
public Task<bool> AddShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) public Task<bool> AddShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
=> TransactionSafeAsync(async tr => await AddShippingItemPalletAsync(shippingItemPallet) != null); => TransactionSafeAsync(async _ => await AddShippingItemPalletAsync(shippingItemPallet) != null);
public async Task<ShippingItemPallet?> UpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) public async Task<ShippingItemPallet?> UpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet)
{ {
@ -317,13 +327,13 @@ public class FruitBankDbContext : MgDbContextBase,
} }
public Task<bool> UpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) public Task<bool> UpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
=> TransactionSafeAsync(async tr => await UpdateShippingItemPalletAsync(shippingItemPallet) != null); => TransactionSafeAsync(async _ => await UpdateShippingItemPalletAsync(shippingItemPallet) != null);
public Task AddOrUpdateShippingItemPalletsSafeAsync(ShippingItem shippingItem) => AddOrUpdateShippingItemPalletsSafeAsync(shippingItem.ShippingItemPallets!, shippingItem); public Task AddOrUpdateShippingItemPalletsSafeAsync(ShippingItem shippingItem) => AddOrUpdateShippingItemPalletsSafeAsync(shippingItem.ShippingItemPallets!, shippingItem);
public Task<bool> AddOrUpdateShippingItemPalletsSafeAsync(IEnumerable<ShippingItemPallet> shippingItemPallets, ShippingItem parentShippingItem) public Task<bool> AddOrUpdateShippingItemPalletsSafeAsync(IEnumerable<ShippingItemPallet> shippingItemPallets, ShippingItem parentShippingItem)
{ {
return TransactionSafeAsync(async tr => return TransactionSafeAsync(async _ =>
{ {
await AddOrUpdateShippingItemPalletAsync(shippingItemPallets, parentShippingItem); await AddOrUpdateShippingItemPalletAsync(shippingItemPallets, parentShippingItem);
return true; return true;
@ -344,7 +354,7 @@ public class FruitBankDbContext : MgDbContextBase,
} }
public async Task<bool> AddOrUpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) public async Task<bool> AddOrUpdateShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
=> await TransactionSafeAsync(async tr => await AddOrUpdateShippingItemPalletAsync(shippingItemPallet) != null); => await TransactionSafeAsync(async _ => await AddOrUpdateShippingItemPalletAsync(shippingItemPallet) != null);
public async Task<ShippingItemPallet?> AddOrUpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet) public async Task<ShippingItemPallet?> AddOrUpdateShippingItemPalletAsync(ShippingItemPallet shippingItemPallet)
{ {
@ -355,7 +365,7 @@ public class FruitBankDbContext : MgDbContextBase,
public async Task DeleteShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet) public async Task DeleteShippingItemPalletSafeAsync(ShippingItemPallet shippingItemPallet)
{ {
await TransactionSafeAsync(async tr => await TransactionSafeAsync(async _ =>
{ {
await ShippingItemPallets.DeleteAsync(shippingItemPallet, false); await ShippingItemPallets.DeleteAsync(shippingItemPallet, false);
return true; return true;
@ -363,7 +373,7 @@ public class FruitBankDbContext : MgDbContextBase,
} }
public async Task<bool> SetOrderStatusToCompleteSafe(int orderId) public async Task<bool> SetOrderStatusToCompleteSafe(int orderId)
=> await TransactionSafeAsync(async tr => await SetOrderStatusToComplete(orderId) != null); => await TransactionSafeAsync(async _ => await SetOrderStatusToComplete(orderId) != null);
public async Task<OrderDto?> SetOrderStatusToComplete(int orderId) public async Task<OrderDto?> SetOrderStatusToComplete(int orderId)
{ {
@ -385,7 +395,7 @@ public class FruitBankDbContext : MgDbContextBase,
(orderItemDto.Id, nameof(IMeasuringNetWeight.NetWeight), orderItemDto.NetWeight); (orderItemDto.Id, nameof(IMeasuringNetWeight.NetWeight), orderItemDto.NetWeight);
await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product> await _fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>
(orderItemDto.ProductId, -(orderItemDto.NetWeight-gaNetWeight), 0, orderItemDto.IsMeasurable, true); (orderItemDto.ProductId, -(orderItemDto.NetWeight-gaNetWeight), orderItemDto.IsMeasurable, true);
} }
return orderDto; return orderDto;
@ -408,7 +418,7 @@ public class FruitBankDbContext : MgDbContextBase,
} }
public async Task<bool> AddOrUpdateOrderItemPalletSafeAsync(OrderItemPallet orderItemPallet) public async Task<bool> AddOrUpdateOrderItemPalletSafeAsync(OrderItemPallet orderItemPallet)
=> await TransactionSafeAsync(async tr => await AddOrUpdateOrderItemPalletAsync(orderItemPallet) != null); => await TransactionSafeAsync(async _ => await AddOrUpdateOrderItemPalletAsync(orderItemPallet) != null);
public async Task<OrderItemPallet?> AddOrUpdateOrderItemPalletAsync(OrderItemPallet orderItemPallet) public async Task<OrderItemPallet?> AddOrUpdateOrderItemPalletAsync(OrderItemPallet orderItemPallet)
{ {
@ -435,22 +445,22 @@ public class FruitBankDbContext : MgDbContextBase,
return true; return true;
} }
private async Task<bool> UpdateProductStockQuantityAsync(int productId, bool publishEvent) private async Task<bool> UpdateProductDtoStockQuantityAsync(int productDtoId, bool publishEvent)
{ {
var product = await Products.GetByIdAsync(productId); var productDto = await ProductDtos.GetByIdAsync(productDtoId);
if (product != null) return await UpdateProductStockQuantityAsync(product, publishEvent); if (productDto != null) return await UpdateProductDtoStockQuantityAsync(productDto, publishEvent);
Logger.Error($"product == null; id: {productId}"); Logger.Error($"product == null; id: {productDtoId}");
return await Task.FromResult(false); return await Task.FromResult(false);
} }
private async Task<bool> UpdateProductStockQuantityAsync(Product product, bool publishEvent) private async Task<bool> UpdateProductDtoStockQuantityAsync(ProductDto productDto, bool publishEvent)
{ {
//Itt mi legyen? RollBack? - J. //Itt mi legyen? RollBack? - J.
if (product.StockQuantity < 0) if (productDto.StockQuantity < 0)
Logger.Error($"product.StockQuantity < 0; Id: {product.Id}; StockQuantity: {product.StockQuantity}"); Logger.Error($"productDto.StockQuantity < 0; Id: {productDto.Id}; StockQuantity: {productDto.StockQuantity}");
await Products.UpdateAsync(product, publishEvent); await ProductDtos.UpdateAsync(productDto, publishEvent);
return await Task.FromResult(true); return await Task.FromResult(true);
//var updatedRowsCount = await DataProvider.ExecuteNonQueryAsync($"update product set {nameof(Product.StockQuantity)} = {product.StockQuantity} where {nameof(Product.Id)} = {product.Id}"); //var updatedRowsCount = await DataProvider.ExecuteNonQueryAsync($"update product set {nameof(Product.StockQuantity)} = {product.StockQuantity} where {nameof(Product.Id)} = {product.Id}");

View File

@ -11,28 +11,7 @@ using Nop.Services.Logging;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class OrderItemDtoDbTable : MgDbTableBase<OrderItemDto> public class OrderDtoDbTable : MgDtoDbTableBase<OrderDto, Order>
{
public OrderItemDtoDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings, ILogger logger)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings, logger)
{
}
public IQueryable<OrderItemDto> GetAll(bool loadRelations)
{
return GetAll()
.LoadWith(oi => oi.OrderDto)
.LoadWith(oi => oi.OrderItemPallets)
.LoadWith(oi => oi.GenericAttributes)
.LoadWith(oi => oi.ProductDto).ThenLoad(prod => prod.GenericAttributes);
}
public Task<OrderItemDto> GetByIdAsync(int orderItemId) => GetAll(true).Where(x => x.Id == orderItemId).FirstOrDefaultAsync(null);
public IQueryable<OrderItemDto> GetAllByOrderId(int orderId)=> GetAll(true).Where(o => o.OrderId == orderId);
}
public class OrderDtoDbTable : MgDbTableBase<OrderDto>
{ {
public OrderDtoDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings, ILogger logger) public OrderDtoDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings, ILogger logger)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings, logger) : base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings, logger)
@ -43,14 +22,15 @@ public class OrderDtoDbTable : MgDbTableBase<OrderDto>
{ {
return GetAll() return GetAll()
.LoadWith(o => o.GenericAttributes) .LoadWith(o => o.GenericAttributes)
.LoadWith(o => o.Customer)
.LoadWith(o => o.OrderItemDtos).ThenLoad(oi => oi.ProductDto).ThenLoad(prod => prod.GenericAttributes) .LoadWith(o => o.OrderItemDtos).ThenLoad(oi => oi.ProductDto).ThenLoad(prod => prod.GenericAttributes)
.LoadWith(o => o.OrderItemDtos).ThenLoad(oi => oi.GenericAttributes) .LoadWith(o => o.OrderItemDtos).ThenLoad(oi => oi.GenericAttributes)
.LoadWith(o => o.OrderItemDtos).ThenLoad(oi => oi.OrderItemPallets); .LoadWith(o => o.OrderItemDtos).ThenLoad(oi => oi.OrderItemPallets);
} }
public Task<OrderDto> GetByIdAsync(int orderId) => GetAll(true).Where(x => x.Id == orderId).FirstOrDefaultAsync(null); public Task<OrderDto> GetByIdAsync(int orderId, bool loadRelations) => GetAll(loadRelations).Where(x => x.Id == orderId).FirstOrDefaultAsync(null);
public IQueryable<OrderDto> GetAllByOrderStatus(OrderStatus orderStatus) => GetAll(true).Where(o => o.OrderStatusId == (int)orderStatus); public IQueryable<OrderDto> GetAllByOrderStatus(OrderStatus orderStatus, bool loadRelations = true) => GetAll(loadRelations).Where(o => o.OrderStatusId == (int)orderStatus);
public IQueryable<OrderDto> GetAllByIds(IEnumerable<int> orderIds) => GetAll(true).Where(o => orderIds.Contains(o.Id)); public IQueryable<OrderDto> GetAllByIds(IEnumerable<int> orderIds, bool loadRelations = true) => GetAll(loadRelations).Where(o => orderIds.Contains(o.Id));
} }

View File

@ -0,0 +1,32 @@
using FruitBank.Common.Dtos;
using LinqToDB;
using Mango.Nop.Core.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Domain.Orders;
using Nop.Core.Events;
using Nop.Data;
using Nop.Services.Logging;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class OrderItemDtoDbTable : MgDtoDbTableBase<OrderItemDto, OrderItem>
{
public OrderItemDtoDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings, ILogger logger)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings, logger)
{
}
public IQueryable<OrderItemDto> GetAll(bool loadRelations)
{
return GetAll()
.LoadWith(oi => oi.OrderDto)
.LoadWith(oi => oi.OrderItemPallets)
.LoadWith(oi => oi.GenericAttributes)
.LoadWith(oi => oi.ProductDto).ThenLoad(prod => prod.GenericAttributes);
}
public Task<OrderItemDto> GetByIdAsync(int orderItemId, bool loadRelations) => GetAll(loadRelations).Where(x => x.Id == orderItemId).FirstOrDefaultAsync(null);
public IQueryable<OrderItemDto> GetAllByOrderId(int orderId, bool loadRelations = true)=> GetAll(loadRelations).Where(o => o.OrderId == orderId);
}

View File

@ -0,0 +1,28 @@
using FruitBank.Common.Dtos;
using LinqToDB;
using Mango.Nop.Core.Repositories;
using Nop.Core.Caching;
using Nop.Core.Configuration;
using Nop.Core.Domain.Catalog;
using Nop.Core.Events;
using Nop.Data;
using Nop.Services.Logging;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
public class ProductDtoDbTable : MgDtoDbTableBase<ProductDto, Product>
{
public ProductDtoDbTable(IEventPublisher eventPublisher, INopDataProvider dataProvider, IShortTermCacheManager shortTermCacheManager, IStaticCacheManager staticCacheManager, AppSettings appSettings, ILogger logger)
: base(eventPublisher, dataProvider, shortTermCacheManager, staticCacheManager, appSettings, logger)
{
}
public IQueryable<ProductDto> GetAll(bool loadRelations)
{
return GetAll().LoadWith(p => p.GenericAttributes);
}
public Task<ProductDto> GetByIdAsync(int productId, bool loadRelations) => GetAll(loadRelations).Where(x => x.Id == productId).FirstOrDefaultAsync(null);
public IQueryable<ProductDto> GetAllByIds(IEnumerable<int> productIds, bool loadRelations = true) => GetAll(loadRelations).Where(p => productIds.Contains(p.Id));
}

View File

@ -25,7 +25,7 @@ public class ShippingDbTable : MgDbTableBase<Shipping>
? GetAll() ? GetAll()
.LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingItems).ThenLoad(si => si.ShippingItemPallets) .LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingItems).ThenLoad(si => si.ShippingItemPallets)
.LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingItems).ThenLoad(si => si.Pallet) .LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingItems).ThenLoad(si => si.Pallet)
.LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingItems).ThenLoad(si => si.Product) .LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingItems).ThenLoad(si => si.ProductDto).ThenLoad(prod => prod.GenericAttributes)
.LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingDocumentToFiles).ThenLoad(sdtof => sdtof.ShippingDocumentFile) .LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.ShippingDocumentToFiles).ThenLoad(sdtof => sdtof.ShippingDocumentFile)
.LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.Partner) .LoadWith(s => s.ShippingDocuments).ThenLoad(sd => sd.Partner)
: GetAll(); : GetAll();

View File

@ -25,7 +25,7 @@ public class ShippingDocumentDbTable : MgDbTableBase<ShippingDocument>
? GetAll() ? GetAll()
.LoadWith(sd => sd.Shipping) .LoadWith(sd => sd.Shipping)
.LoadWith(sd => sd.ShippingItems).ThenLoad(si => si.Pallet) .LoadWith(sd => sd.ShippingItems).ThenLoad(si => si.Pallet)
.LoadWith(sd => sd.ShippingItems).ThenLoad(si => si.Product) .LoadWith(sd => sd.ShippingItems).ThenLoad(si => si.ProductDto).ThenLoad(prod => prod.GenericAttributes)
.LoadWith(sd => sd.ShippingItems).ThenLoad(si => si.ShippingItemPallets) .LoadWith(sd => sd.ShippingItems).ThenLoad(si => si.ShippingItemPallets)
.LoadWith(sd => sd.ShippingDocumentToFiles).ThenLoad(sdtof => sdtof.ShippingDocumentFile) .LoadWith(sd => sd.ShippingDocumentToFiles).ThenLoad(sdtof => sdtof.ShippingDocumentFile)
.LoadWith(sd => sd.Partner) .LoadWith(sd => sd.Partner)

View File

@ -38,9 +38,9 @@ public class ShippingItemDbTable : MgDbTableBase<ShippingItem>
.LoadWith(si => si.ShippingDocument).ThenLoad(p => p.Partner) .LoadWith(si => si.ShippingDocument).ThenLoad(p => p.Partner)
.LoadWith(si => si.ShippingDocument).ThenLoad(sd => sd.ShippingDocumentToFiles).ThenLoad(sdtof => sdtof.ShippingDocumentFile) .LoadWith(si => si.ShippingDocument).ThenLoad(sd => sd.ShippingDocumentToFiles).ThenLoad(sdtof => sdtof.ShippingDocumentFile)
.LoadWith(si => si.ShippingItemPallets) .LoadWith(si => si.ShippingItemPallets)
.LoadWith(si => si.Product) .LoadWith(si => si.ProductDto).ThenLoad(prod => prod.GenericAttributes)
.LoadWith(si => si.Pallet) .LoadWith(si => si.Pallet)
: GetAll().LoadWith(si => si.ShippingItemPallets).LoadWith(si => si.Product).LoadWith(si => si.Pallet); : GetAll().LoadWith(si => si.ShippingItemPallets).LoadWith(si => si.ProductDto).ThenLoad(prod => prod.GenericAttributes).LoadWith(si => si.Pallet);
} }
public IQueryable<ShippingItem> GetAllNotMeasured(bool loadRelations) public IQueryable<ShippingItem> GetAllNotMeasured(bool loadRelations)

View File

@ -1,9 +1,12 @@
using AyCode.Core.Loggers; using System.Diagnostics.CodeAnalysis;
using AyCode.Core.Loggers;
using AyCode.Interfaces.Entities; using AyCode.Interfaces.Entities;
using FruitBank.Common.Dtos;
using FruitBank.Common.Entities; using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces; using FruitBank.Common.Interfaces;
using FruitBank.Common.Loggers; using FruitBank.Common.Loggers;
using FruitBank.Common.Server; using FruitBank.Common.Server;
using Humanizer;
using Mango.Nop.Core.Loggers; using Mango.Nop.Core.Loggers;
using Mango.Nop.Services; using Mango.Nop.Services;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -36,58 +39,83 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
{ {
var product = eventMessage.Entity; var product = eventMessage.Entity;
await SaveProductCustomAttributesAsync(eventMessage.Entity); var saveProductCustomAttributesResult = await SaveProductCustomAttributesAsync(eventMessage.Entity);
var isMeasurableProduct = await fruitBankAttributeService.IsMeasurableEntityAsync<Product>(product.Id); //var isMeasurableProduct = await fruitBankAttributeService.IsMeasurableEntityAsync<Product>(product.Id);
if (saveProductCustomAttributesResult is { IsMeasurableChanged: true, IsMeasurable: not null })
{
var shippingItems = await ctx.ShippingItems.Table var shippingItems = await ctx.ShippingItems.Table
.Where(si => si.ProductId == product.Id && !si.IsMeasured && si.IsMeasurable != isMeasurableProduct) .Where(si => si.ProductId == product.Id && !si.IsMeasured && si.IsMeasurable != saveProductCustomAttributesResult.IsMeasurable.Value)
.ToListAsync(); .ToListAsync();
foreach (var shippingItem in shippingItems) if (shippingItems.Count > 0)
shippingItem.IsMeasurable = isMeasurableProduct; {
foreach (var shippingItem in shippingItems) shippingItem.IsMeasurable = saveProductCustomAttributesResult.IsMeasurable.Value;
await ctx.ShippingItems.UpdateAsync(shippingItems, false); await ctx.ShippingItems.UpdateAsync(shippingItems, false);
}
}
await base.HandleEventAsync(eventMessage); await base.HandleEventAsync(eventMessage);
} }
public override async Task HandleEventAsync(EntityInsertedEvent<Product> eventMessage) public override async Task HandleEventAsync(EntityInsertedEvent<Product> eventMessage)
{ {
await SaveProductCustomAttributesAsync(eventMessage.Entity); await SaveProductCustomAttributesAsync(eventMessage.Entity); //TODO: ez ide miért kell? - J.
await base.HandleEventAsync(eventMessage); await base.HandleEventAsync(eventMessage);
} }
private async Task SaveProductCustomAttributesAsync(Product product) /// <summary>
///
/// </summary>
/// <param name="product"></param>
/// <returns>IsMeasureable</returns>
/// <exception cref="Exception"></exception>
private async Task<(bool IsMeasurableChanged, bool? IsMeasurable)> SaveProductCustomAttributesAsync(Product product)
{ {
if (product == null) return; if (product == null) return (false, null);
var form = HttpContextAccessor.HttpContext?.Request?.Form; var hasForm = HttpContextAccessor.HttpContext?.Request?.HasFormContentType ?? false;
if (form == null || form.Count == 0) return; var form = hasForm ? HttpContextAccessor.HttpContext.Request.Form : null;
if (form.ContainsKey(nameof(IMeasurable.IsMeasurable)) && form.ContainsKey(nameof(IMeasuringNetWeight.NetWeight))) if (form == null || form.Count == 0 ||
!form.ContainsKey(nameof(IMeasurable.IsMeasurable)) || !form.ContainsKey(nameof(IMeasuringNetWeight.NetWeight)) ||
!form.ContainsKey(nameof(IIncomingQuantity.IncomingQuantity)) || !form.ContainsKey(nameof(ITare.Tare))) return (false, null);
bool? isMeasurable = null;
var isMeasurableChanged = false;
var productDto = product.Id > 0 ? await ctx.ProductDtos.GetByIdAsync(product.Id, false) : null;
//IsMeasurable
isMeasurable = form[nameof(IMeasurable.IsMeasurable)].ToString().Contains("true");
if (productDto == null || productDto.IsMeasurable != isMeasurable.Value)
{ {
var isMeasurable = form[nameof(IMeasurable.IsMeasurable)].ToString().Contains("true"); await fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Product, bool>(product.Id, nameof(IMeasurable.IsMeasurable), isMeasurable.Value);
//var isMeasurable = CommonHelper.To<bool>(form[nameof(IMeasurable.IsMeasurable)].ToString()); isMeasurableChanged = true;
var netWeight = CommonHelper.To<double>(form[nameof(IMeasuringNetWeight.NetWeight)].ToString());
await fruitBankAttributeService.InsertOrUpdateMeasuringAttributeValuesAsync<Product>(product.Id, netWeight, 0, isMeasurable, false);
} }
if (form.ContainsKey(nameof(ITare.Tare))) //NetWeight
{ var netWeight = double.Round(CommonHelper.To<double>(form[nameof(IMeasuringNetWeight.NetWeight)].ToString()), 1);
var tare = CommonHelper.To<double>(form[nameof(ITare.Tare)].ToString()); if (productDto == null || productDto.NetWeight != netWeight)
await fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Product, double>(product.Id, nameof(IMeasuringNetWeight.NetWeight), netWeight);
//Tára
var tare = double.Round(CommonHelper.To<double>(form[nameof(ITare.Tare)].ToString()), 1);
if (tare < 0) throw new Exception($"FruitBankEventConsumer->SaveProductCustomAttributesAsync(); (tare < 0); productId: {product.Id}; tare: {tare}"); if (tare < 0) throw new Exception($"FruitBankEventConsumer->SaveProductCustomAttributesAsync(); (tare < 0); productId: {product.Id}; tare: {tare}");
if (productDto == null || productDto.Tare != tare)
await fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Product, double>(product.Id, nameof(ITare.Tare), tare); await fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Product, double>(product.Id, nameof(ITare.Tare), tare);
}
if (form.ContainsKey("IncomingQuantity")) //IncomingQuantity
{ var incomingQuantity = CommonHelper.To<int>(form[nameof(IIncomingQuantity.IncomingQuantity)].ToString());
var incomingQuantity = CommonHelper.To<int>(form["IncomingQuantity"].ToString());
if (incomingQuantity < 0) throw new Exception($"FruitBankEventConsumer->SaveProductCustomAttributesAsync(); (incomingQuantity < 0); productId: {product.Id}; incomingQuantity: {incomingQuantity}"); if (incomingQuantity < 0) throw new Exception($"FruitBankEventConsumer->SaveProductCustomAttributesAsync(); (incomingQuantity < 0); productId: {product.Id}; incomingQuantity: {incomingQuantity}");
await fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Product, int>(product.Id, "IncomingQuantity", incomingQuantity); if (productDto == null || productDto.IncomingQuantity != incomingQuantity)
} await fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Product, int>(product.Id, nameof(IIncomingQuantity.IncomingQuantity), incomingQuantity);
return (isMeasurableChanged, isMeasurable);
} }
public async Task HandleEventAsync(EntityInsertedEvent<ShippingItemPallet> eventMessage) public async Task HandleEventAsync(EntityInsertedEvent<ShippingItemPallet> eventMessage)

View File

@ -11,7 +11,6 @@ using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping; using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax; using Nop.Core.Domain.Tax;
using Nop.Plugin.Misc.FruitBankPlugin.Helpers; using Nop.Plugin.Misc.FruitBankPlugin.Helpers;
using Nop.Plugin.Misc.FruitBankPlugin.Models;
using Nop.Plugin.Misc.FruitBankPlugin.Services; using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Affiliates; using Nop.Services.Affiliates;
using Nop.Services.Catalog; using Nop.Services.Catalog;
@ -37,15 +36,18 @@ using System.Collections;
using System.Reflection; using System.Reflection;
using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Arm;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
using FruitBank.Common.Dtos;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
{ {
public class CustomOrderModelFactory : OrderModelFactory public class CustomOrderModelFactory : MgOrderModelFactory<OrderListModelExtended, OrderModelExtended>
{ {
private FruitBankDbContext _ctx; private readonly FruitBankDbContext _ctx;
private readonly IOrderMeasurementService _orderMeasurementService; private readonly IOrderMeasurementService _orderMeasurementService;
private readonly IGenericAttributeService _genericAttributeService;
#region Ctor
public CustomOrderModelFactory( public CustomOrderModelFactory(
FruitBankDbContext ctx, FruitBankDbContext ctx,
IOrderMeasurementService orderMeasurementService, IOrderMeasurementService orderMeasurementService,
@ -139,40 +141,17 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
orderSettings, orderSettings,
shippingSettings, shippingSettings,
urlRecordService, urlRecordService,
taxSettings taxSettings,
genericAttributeService
) )
{ {
_ctx = ctx; _ctx = ctx;
_orderMeasurementService = orderMeasurementService; _orderMeasurementService = orderMeasurementService;
_genericAttributeService = genericAttributeService;
} }
#endregion Ctor
public override async Task<OrderSearchModel> PrepareOrderSearchModelAsync(OrderSearchModel searchModel) public override async Task<OrderSearchModel> PrepareOrderSearchModelAsync(OrderSearchModel searchModel)
{ {
// let base prepare default model first
var baseModel = await base.PrepareOrderSearchModelAsync(searchModel); var baseModel = await base.PrepareOrderSearchModelAsync(searchModel);
//foreach (var order in baseModel.order)
// create derived/extended instance
//var extended = new OrderSearchModelExtended();
// copy all public instance properties from baseModel to extended
//CopyModelHelper.CopyPublicProperties(baseModel, extended);
// try to obtain NeedsMeasurement from the incoming searchModel (if it's extended)
//bool? needsMeasurement = null;
//var prop = searchModel?.GetType().GetProperty("NeedsMeasurement", BindingFlags.Public | BindingFlags.Instance);
//if (prop != null && prop.PropertyType == typeof(bool?))
//{
// needsMeasurement = (bool?)prop.GetValue(searchModel);
//}
//extended.NeedsMeasurement = needsMeasurement;
// return the extended object (it's assignable to OrderSearchModel)
//return extended;
return baseModel; return baseModel;
} }
@ -181,18 +160,14 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
public async Task<OrderListModelExtended> PrepareOrderListModelExtendedAsync(OrderSearchModel searchModel) public async Task<OrderListModelExtended> PrepareOrderListModelExtendedAsync(OrderSearchModel searchModel)
{ {
var orderListModel = await PrepareOrderListModelAsync(searchModel); Dictionary<int, OrderDto> orderDtosById = null;
var extendedRows = new List<OrderModelExtended>(orderListModel.RecordsFiltered);
var orderDtosById = await _ctx.OrderDtos.GetAllByIds(orderListModel.Data.Select(x => x.Id)).ToDictionaryAsync(k => k.Id, v => v); var orderListModelExtended = await base.PrepareOrderListModelExtendedAsync(searchModel, async (orderListModel, orderModelExtended) =>
foreach (var orderModel in orderListModel.Data)
{ {
var orderDto = orderDtosById[orderModel.Id]; orderDtosById ??= await _ctx.OrderDtos.GetAllByIds(orderListModel.Data.Select(x => x.Id)).ToDictionaryAsync(k => k.Id, v => v);
var orderDto = orderDtosById[orderModelExtended.Id];
var orderModelExtended = new OrderModelExtended();
PropertyHelper.CopyPublicValueTypeProperties(orderModel, orderModelExtended);
orderModelExtended.IsMeasured = orderDto.IsMeasured;
orderModelExtended.IsMeasurable = orderDto.IsMeasurable; orderModelExtended.IsMeasurable = orderDto.IsMeasurable;
orderModelExtended.DateOfReceipt = orderDto.DateOfReceipt; orderModelExtended.DateOfReceipt = orderDto.DateOfReceipt;
@ -200,13 +175,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
//orderModelExtended.DateOfReceipt = await GetPickupDateTimeAsync(orderModel); //orderModelExtended.DateOfReceipt = await GetPickupDateTimeAsync(orderModel);
Console.WriteLine(orderModelExtended.Id); Console.WriteLine(orderModelExtended.Id);
extendedRows.Add(orderModelExtended); });
}
orderListModel.Data = null;
var orderListModelExtended = orderListModel.ToJson().JsonTo<OrderListModelExtended>();
orderListModelExtended.Data = extendedRows;
return orderListModelExtended; return orderListModelExtended;
} }
@ -232,7 +201,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
var fullOrder = await _orderService.GetOrderByIdAsync(order.Id); var fullOrder = await _orderService.GetOrderByIdAsync(order.Id);
if (fullOrder != null) if (fullOrder != null)
{ {
dateTime = await _genericAttributeService.GetAttributeAsync<DateTime>(fullOrder, nameof(IOrderDto.DateOfReceipt)); dateTime = await GenericAttributeService.GetAttributeAsync<DateTime>(fullOrder, nameof(IOrderDto.DateOfReceipt));
if(dateTime == DateTime.MinValue || !dateTime.HasValue) if(dateTime == DateTime.MinValue || !dateTime.HasValue)
{ {
dateTime = null; dateTime = null;

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,171 @@
using AyCode.Core.Extensions;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Affiliates;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Configuration;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Discounts;
using Nop.Services.Helpers;
using Nop.Services.Localization;
using Nop.Services.Media;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Security;
using Nop.Services.Seo;
using Nop.Services.Shipping;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
using Nop.Web.Areas.Admin.Factories;
using Nop.Web.Areas.Admin.Models.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
public class MgOrderModelFactory<TOrderListModelExt, TOrderModelExt> : OrderModelFactory
where TOrderListModelExt:OrderListModelExtended where TOrderModelExt: OrderModelExtended
{
protected IGenericAttributeService GenericAttributeService;
#region Ctor
public MgOrderModelFactory(
AddressSettings addressSettings,
CatalogSettings catalogSettings,
CurrencySettings currencySettings,
IActionContextAccessor actionContextAccessor,
IAddressModelFactory addressModelFactory,
IAddressService addressService,
IAffiliateService affiliateService,
IBaseAdminModelFactory baseAdminModelFactory,
ICountryService countryService,
ICurrencyService currencyService,
ICustomerService customerService,
IDateTimeHelper dateTimeHelper,
IDiscountService discountService,
IDownloadService downloadService,
IEncryptionService encryptionService,
IGiftCardService giftCardService,
ILocalizationService localizationService,
IMeasureService measureService,
IOrderProcessingService orderProcessingService,
IOrderReportService orderReportService,
IOrderService orderService,
IPaymentPluginManager paymentPluginManager,
IPaymentService paymentService,
IPictureService pictureService,
IPriceCalculationService priceCalculationService,
IPriceFormatter priceFormatter,
IProductAttributeService productAttributeService,
IProductService productService,
IReturnRequestService returnRequestService,
IRewardPointService rewardPointService,
ISettingService settingService,
IShipmentService shipmentService,
IShippingService shippingService,
IStateProvinceService stateProvinceService,
IStoreService storeService,
ITaxService taxService,
IUrlHelperFactory urlHelperFactory,
IVendorService vendorService,
IWorkContext workContext,
MeasureSettings measureSettings,
NopHttpClient nopHttpClient,
OrderSettings orderSettings,
ShippingSettings shippingSettings,
IUrlRecordService urlRecordService,
TaxSettings taxSettings,
IGenericAttributeService genericAttributeService)
: base(addressSettings,
catalogSettings,
currencySettings,
actionContextAccessor,
addressModelFactory,
addressService,
affiliateService,
baseAdminModelFactory,
countryService,
currencyService,
customerService,
dateTimeHelper,
discountService,
downloadService,
encryptionService,
giftCardService,
localizationService,
measureService,
orderProcessingService,
orderReportService,
orderService,
paymentPluginManager,
paymentService,
pictureService,
priceCalculationService,
priceFormatter,
productAttributeService,
productService,
returnRequestService,
rewardPointService,
settingService,
shipmentService,
shippingService,
stateProvinceService,
storeService,
taxService,
urlHelperFactory,
vendorService,
workContext,
measureSettings,
nopHttpClient,
orderSettings,
shippingSettings,
urlRecordService,
taxSettings
)
{
GenericAttributeService = genericAttributeService;
}
#endregion Cotr
public override Task<OrderSearchModel> PrepareOrderSearchModelAsync(OrderSearchModel searchModel)
=> base.PrepareOrderSearchModelAsync(searchModel);
public override Task<OrderListModel> PrepareOrderListModelAsync(OrderSearchModel searchModel)
=> base.PrepareOrderListModelAsync(searchModel);
public virtual async Task<TOrderListModelExt> PrepareOrderListModelExtendedAsync(OrderSearchModel searchModel, Func<OrderListModel, TOrderModelExt, Task> dataItemCopiedCallback)
{
var orderListModel = await PrepareOrderListModelAsync(searchModel);
var extendedRows = new List<TOrderModelExt>(orderListModel.RecordsFiltered);
foreach (var orderModel in orderListModel.Data.ToList())
{
var orderModelExtended = Activator.CreateInstance<TOrderModelExt>();
PropertyHelper.CopyPublicValueTypeProperties(orderModel, orderModelExtended);
extendedRows.Add(orderModelExtended);
if (dataItemCopiedCallback == null) continue;
await dataItemCopiedCallback.Invoke(orderListModel, orderModelExtended);
}
orderListModel.Data = null;
//var orderListModelExtended = orderListModel.ToJson().JsonTo<TOrderListModelExt>();
var orderListModelExtended = orderListModel.CloneTo<TOrderListModelExt>();
orderListModelExtended.Data = extendedRows;
return orderListModelExtended;
}
}

View File

@ -0,0 +1,165 @@
using AyCode.Core.Extensions;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Nop.Core;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Shipping;
using Nop.Core.Domain.Tax;
using Nop.Core.Domain.Vendors;
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Products;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Affiliates;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Configuration;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.Discounts;
using Nop.Services.Helpers;
using Nop.Services.Localization;
using Nop.Services.Media;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Security;
using Nop.Services.Seo;
using Nop.Services.Shipping;
using Nop.Services.Stores;
using Nop.Services.Tax;
using Nop.Services.Vendors;
using Nop.Web.Areas.Admin.Factories;
using Nop.Web.Areas.Admin.Models.Catalog;
using Nop.Web.Areas.Admin.Models.Orders;
using Nop.Web.Framework.Factories;
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
public class MgProductModelFactory<TProductListModelExt, TProductModelExt> : ProductModelFactory
where TProductListModelExt : ProductListModelExtended where TProductModelExt : ProductModelExtended
{
protected IGenericAttributeService GenericAttributeService;
#region Ctor
public MgProductModelFactory(
CatalogSettings catalogSettings,
CurrencySettings currencySettings,
IAddressService addressService,
IBaseAdminModelFactory baseAdminModelFactory,
ICategoryService categoryService,
ICurrencyService currencyService,
ICustomerService customerService,
IDateTimeHelper dateTimeHelper,
IDiscountService discountService,
IDiscountSupportedModelFactory discountSupportedModelFactory,
ILocalizationService localizationService,
ILocalizedModelFactory localizedModelFactory,
IManufacturerService manufacturerService,
IMeasureService measureService,
IOrderService orderService,
IPictureService pictureService,
IPriceFormatter priceFormatter,
IProductAttributeFormatter productAttributeFormatter,
IProductAttributeParser productAttributeParser,
IProductAttributeService productAttributeService,
IProductService productService,
IProductTagService productTagService,
IProductTemplateService productTemplateService,
ISettingModelFactory settingModelFactory,
ISettingService settingService,
IShipmentService shipmentService,
IShippingService shippingService,
IShoppingCartService shoppingCartService,
ISpecificationAttributeService specificationAttributeService,
IStoreMappingSupportedModelFactory storeMappingSupportedModelFactory,
IStoreContext storeContext,
IStoreService storeService,
IUrlRecordService urlRecordService,
IVideoService videoService,
IWorkContext workContext,
MeasureSettings measureSettings,
NopHttpClient nopHttpClient,
TaxSettings taxSettings,
VendorSettings vendorSettings,
IGenericAttributeService genericAttributeService)
: base(
catalogSettings,
currencySettings,
addressService,
baseAdminModelFactory,
categoryService,
currencyService,
customerService,
dateTimeHelper,
discountService,
discountSupportedModelFactory,
localizationService,
localizedModelFactory,
manufacturerService,
measureService,
orderService,
pictureService,
priceFormatter,
productAttributeFormatter,
productAttributeParser,
productAttributeService,
productService,
productTagService,
productTemplateService,
settingModelFactory,
settingService,
shipmentService,
shippingService,
shoppingCartService,
specificationAttributeService,
storeMappingSupportedModelFactory,
storeContext,
storeService,
urlRecordService,
videoService,
workContext,
measureSettings,
nopHttpClient,
taxSettings,
vendorSettings)
{
GenericAttributeService = genericAttributeService;
}
#endregion Cotr
public override Task<ProductSearchModel> PrepareProductSearchModelAsync(ProductSearchModel searchModel)
=> base.PrepareProductSearchModelAsync(searchModel);
public override Task<ProductListModel> PrepareProductListModelAsync(ProductSearchModel searchModel)
=> base.PrepareProductListModelAsync(searchModel);
public virtual async Task<TProductListModelExt> PrepareProductListModelExtendedAsync(ProductSearchModel searchModel, Func<ProductListModel, TProductModelExt, Task> dataItemCopiedCallback)
{
var productListModel = await PrepareProductListModelAsync(searchModel);
var extendedRows = new List<TProductModelExt>(productListModel.RecordsFiltered);
foreach (var productModel in productListModel.Data.ToList())
{
var productModelExtended = Activator.CreateInstance<TProductModelExt>();
PropertyHelper.CopyPublicValueTypeProperties(productModel, productModelExtended);
extendedRows.Add(productModelExtended);
if (dataItemCopiedCallback == null) continue;
await dataItemCopiedCallback.Invoke(productListModel, productModelExtended);
}
productListModel.Data = null;
//var productListModelExtended = productListModel.ToJson().JsonTo<TProductListModelExt>();
var productListModelExtended = productListModel.CloneTo<TProductListModelExt>();
productListModelExtended.Data = extendedRows;
return productListModelExtended;
}
}

View File

@ -58,6 +58,7 @@ public class PluginNopStartup : INopStartup
services.AddScoped<FruitBankAttributeService>(); services.AddScoped<FruitBankAttributeService>();
services.AddScoped<ProductDtoDbTable>();
services.AddScoped<OrderDtoDbTable>(); services.AddScoped<OrderDtoDbTable>();
services.AddScoped<OrderItemDtoDbTable>(); services.AddScoped<OrderItemDtoDbTable>();
services.AddScoped<OrderItemPalletDbTable>(); services.AddScoped<OrderItemPalletDbTable>();
@ -86,6 +87,7 @@ public class PluginNopStartup : INopStartup
//services.AddScoped<OrderSearchModel, OrderSearchModelExtended>(); //services.AddScoped<OrderSearchModel, OrderSearchModelExtended>();
services.AddScoped<IOrderModelFactory, CustomOrderModelFactory>(); services.AddScoped<IOrderModelFactory, CustomOrderModelFactory>();
services.AddScoped<IProductModelFactory, CustomProductModelFactory>();
services.AddScoped<IGenericAttributeService, GenericAttributeService>(); services.AddScoped<IGenericAttributeService, GenericAttributeService>();
services.AddScoped<CerebrasAPIService>(); services.AddScoped<CerebrasAPIService>();
services.AddScoped<OpenAIApiService>(); services.AddScoped<OpenAIApiService>();

View File

@ -1,8 +0,0 @@
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models;
public interface IOrderListModelExtended<T>: IPagedModel<T> where T : BaseNopModel
{
public bool? NeedsMeasurement { get; set; }
}

View File

@ -0,0 +1,7 @@
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase;
public interface IMgListModelExtended<T>: IPagedModel<T> where T : BaseNopModel, IMgModelExtended
{
}

View File

@ -0,0 +1,5 @@
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase;
public interface IMgModelExtended
{
}

View File

@ -0,0 +1,5 @@
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
public interface IMgOrderListModelExtended<T>: IMgListModelExtended<T> where T : MgOrderModelExtended
{
}

View File

@ -0,0 +1,5 @@
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
public interface IMgOrderModelExtended : IMgModelExtended
{
}

View File

@ -0,0 +1,8 @@
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
public partial record MgOrderListModelExtended<TOrderModelExt> : BasePagedListModel<TOrderModelExt>, IMgOrderListModelExtended<TOrderModelExt>
where TOrderModelExt: MgOrderModelExtended
{
}

View File

@ -0,0 +1,8 @@
using Nop.Web.Areas.Admin.Models.Orders;
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
public partial record MgOrderModelExtended : OrderModel, IMgOrderModelExtended
{
}

View File

@ -0,0 +1,5 @@
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
public interface IMgProductListModelExtended<T>: IMgListModelExtended<T> where T : MgProductModelExtended
{
}

View File

@ -0,0 +1,5 @@
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
public interface IMgProductModelExtended : IMgModelExtended
{
}

View File

@ -0,0 +1,8 @@
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
public partial record MgProductListModelExtended<TProductModelExt> : BasePagedListModel<TProductModelExt>, IMgProductListModelExtended<TProductModelExt>
where TProductModelExt: MgProductModelExtended
{
}

View File

@ -0,0 +1,8 @@
using Nop.Web.Areas.Admin.Models.Catalog;
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
public partial record MgProductModelExtended : ProductModel, IMgProductModelExtended
{
}

View File

@ -1,11 +0,0 @@
using Nop.Web.Areas.Admin.Models.Orders;
using Nop.Web.Framework.Models;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models
{
public partial record OrderListModelExtended : BasePagedListModel<OrderModelExtended>, IOrderListModelExtended<OrderModelExtended>
{
public bool? NeedsMeasurement { get; set; }
}
}

View File

@ -1,11 +0,0 @@
using Nop.Web.Areas.Admin.Models.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models
{
public partial record OrderModelExtended : OrderModel
{
public bool IsMeasurable { get; set; }
public DateTime? DateOfReceipt { get; set; }
}
}

View File

@ -1,10 +0,0 @@
using Nop.Web.Areas.Admin.Models.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models
{
public partial record OrderSearchModelExtended : OrderSearchModel
{
public bool? NeedsMeasurement { get; set; }
}
}

View File

@ -0,0 +1,7 @@
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
public interface IOrderListModelExtended: IMgOrderListModelExtended<OrderModelExtended>
{
}

View File

@ -0,0 +1,9 @@
using FruitBank.Common.Interfaces;
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
public interface IOrderModelExtended : IMgOrderModelExtended, IMeasurable, IMeasured
{
public DateTime? DateOfReceipt { get; set; }
}

View File

@ -2,7 +2,7 @@
using Nop.Web.Framework.Models; using Nop.Web.Framework.Models;
using Nop.Web.Framework.Mvc.ModelBinding; using Nop.Web.Framework.Mvc.ModelBinding;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
{ {
public record OrderAttributesModel : BaseNopModel, IMeasurable public record OrderAttributesModel : BaseNopModel, IMeasurable
{ {

View File

@ -0,0 +1,10 @@
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
using Nop.Web.Areas.Admin.Models.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
{
public partial record OrderListModelExtended : MgOrderListModelExtended<OrderModelExtended>, IOrderListModelExtended
{
}
}

View File

@ -0,0 +1,12 @@
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
{
public partial record OrderModelExtended : MgOrderModelExtended, IOrderModelExtended
{
public bool IsMeasured { get; set; }
public bool IsMeasurable { get; set; }
public DateTime? DateOfReceipt { get; set; }
}
}

View File

@ -4,7 +4,7 @@ using Nop.Web.Framework.Mvc.ModelBinding;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models namespace Nop.Plugin.Misc.FruitBankPlugin.Models
{ {
public record ProductAttributesModel : BaseNopModel, IMeasurable, IMeasuringWeights, ITare public record ProductAttributesModel : BaseNopModel, IMeasurable, IMeasuringWeights, ITare, IIncomingQuantity
{ {
public int ProductId { get; set; } public int ProductId { get; set; }
@ -18,7 +18,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Models
public double GrossWeight { get; set; } public double GrossWeight { get; set; }
[NopResourceDisplayName("Plugins.YourCompany.ProductAttributes.Fields.IncomingQuantity")] [NopResourceDisplayName("Plugins.YourCompany.ProductAttributes.Fields.IncomingQuantity")]
public int? IncomingQuantity { get; set; } public int IncomingQuantity { get; set; }
[NopResourceDisplayName("Plugins.YourCompany.ProductAttributes.Fields.Tare")] [NopResourceDisplayName("Plugins.YourCompany.ProductAttributes.Fields.Tare")]
public double Tare { get; set; } public double Tare { get; set; }

View File

@ -0,0 +1,9 @@

using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Products;
public interface IProductListModelExtended: IMgProductListModelExtended<ProductModelExtended>
{
}

View File

@ -0,0 +1,9 @@
using FruitBank.Common.Interfaces;
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Products;
public interface IProductModelExtended : IMgProductModelExtended, IMeasurable, ITare, IMeasuringNetWeight, IIncomingQuantity
{
}

View File

@ -0,0 +1,11 @@
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
using Nop.Web.Areas.Admin.Models.Orders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Products
{
public partial record ProductListModelExtended : MgProductListModelExtended<ProductModelExtended>, IProductListModelExtended
{
}
}

View File

@ -0,0 +1,15 @@
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.OrderModels;
using Nop.Plugin.Misc.FruitBankPlugin.Models.MgBase.ProductModels;
namespace Nop.Plugin.Misc.FruitBankPlugin.Models.Products
{
public partial record ProductModelExtended : MgProductModelExtended, IProductModelExtended
{
public bool IsMeasurable { get; set; }
public double Tare { get; set; }
public double NetWeight { get; set; }
public int IncomingQuantity { get; set; }
}
}

View File

@ -5,6 +5,7 @@ using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Orders; using Nop.Core.Domain.Orders;
using Nop.Core.Events; using Nop.Core.Events;
using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Plugin.Misc.FruitBankPlugin.Models;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Services.Catalog; using Nop.Services.Catalog;
using Nop.Services.Common; using Nop.Services.Common;
using Nop.Services.Events; using Nop.Services.Events;
@ -122,7 +123,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
var store = await _storeContext.GetCurrentStoreAsync(); var store = await _storeContext.GetCurrentStoreAsync();
// itt adjuk hozzá a GenericAttribute flag-et az orderhez // itt adjuk hozzá a GenericAttribute flag-et az orderhez
await _genericAttributeService.SaveAttributeAsync(order, await _genericAttributeService.SaveAttributeAsync(order,
nameof(OrderModelExtended.IsMeasurable), true, store.Id); nameof(IMeasurable.IsMeasurable), true, store.Id);
// status pending // status pending
// paymentstatus pending // paymentstatus pending
} }

View File

@ -10,7 +10,6 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services;
public class FruitBankAttributeService(IGenericAttributeService genericAttributeService, IStoreContext storeContext) public class FruitBankAttributeService(IGenericAttributeService genericAttributeService, IStoreContext storeContext)
{ {
private const string NET_WEIGHT_KEY = nameof(IMeasuringAttributeValues.NetWeight); private const string NET_WEIGHT_KEY = nameof(IMeasuringAttributeValues.NetWeight);
private const string GROSS_WEIGHT_KEY = nameof(IMeasuringAttributeValues.GrossWeight);
private const string IS_MEASURABLE_KEY = nameof(IMeasuringAttributeValues.IsMeasurable); private const string IS_MEASURABLE_KEY = nameof(IMeasuringAttributeValues.IsMeasurable);
@ -31,11 +30,11 @@ public class FruitBankAttributeService(IGenericAttributeService genericAttribute
public async Task<List<GenericAttribute>?> GetMeasuringAttributesAsync<TEntity>(int entityId, int storeId) public async Task<List<GenericAttribute>?> GetMeasuringAttributesAsync<TEntity>(int entityId, int storeId)
{ {
var measuringAttributes = (await genericAttributeService.GetAttributesForEntityAsync(entityId, typeof(TEntity).Name)) var measuringAttributes = (await genericAttributeService.GetAttributesForEntityAsync(entityId, typeof(TEntity).Name))
.Where(ga => ga.StoreId == storeId && ga.Key is NET_WEIGHT_KEY or GROSS_WEIGHT_KEY or IS_MEASURABLE_KEY) .Where(ga => ga.StoreId == storeId && ga.Key is NET_WEIGHT_KEY or IS_MEASURABLE_KEY)
.ToList(); .ToList();
if (measuringAttributes.Count == 0) return null; if (measuringAttributes.Count == 0) return null;
if (measuringAttributes.Count != 3) throw new Exception($"FruitBankAttributeService->GetMeasuringAttributesAsync(); measuringAttributes.Count != 3; entityId: {entityId}"); if (measuringAttributes.Count != 2) throw new Exception($"FruitBankAttributeService->GetMeasuringAttributesAsync(); measuringAttributes.Count != 2; entityId: {entityId}");
return measuringAttributes; return measuringAttributes;
} }
@ -51,7 +50,6 @@ public class FruitBankAttributeService(IGenericAttributeService genericAttribute
var measuringAttributeValues = new MeasuringAttributeValues( var measuringAttributeValues = new MeasuringAttributeValues(
entityId, entityId,
CommonHelper.To<double>(measuringAttributes.Single(ga => ga.Key == NET_WEIGHT_KEY).Value), CommonHelper.To<double>(measuringAttributes.Single(ga => ga.Key == NET_WEIGHT_KEY).Value),
CommonHelper.To<double>(measuringAttributes.Single(ga => ga.Key == GROSS_WEIGHT_KEY).Value),
CommonHelper.To<bool>(measuringAttributes.Single(ga => ga.Key == IS_MEASURABLE_KEY).Value)); CommonHelper.To<bool>(measuringAttributes.Single(ga => ga.Key == IS_MEASURABLE_KEY).Value));
return measuringAttributeValues; return measuringAttributeValues;
@ -64,13 +62,12 @@ public class FruitBankAttributeService(IGenericAttributeService genericAttribute
return measurableAttribute != null && CommonHelper.To<bool>(measurableAttribute.Value); return measurableAttribute != null && CommonHelper.To<bool>(measurableAttribute.Value);
} }
public async Task<MeasuringAttributeValues> InsertOrUpdateMeasuringAttributeValuesAsync<TEntity>(int entityId, double netWeight, double grossWeight, bool isMeasurable, bool cumulativeWeightUpdate) public async Task<MeasuringAttributeValues> InsertOrUpdateMeasuringAttributeValuesAsync<TEntity>(int entityId, double netWeight, bool isMeasurable, bool cumulativeWeightUpdate)
{ {
var measuringAttributeValues = new MeasuringAttributeValues var measuringAttributeValues = new MeasuringAttributeValues
{ {
Id = entityId, Id = entityId,
NetWeight = netWeight, NetWeight = netWeight,
GrossWeight = grossWeight,
IsMeasurable = isMeasurable IsMeasurable = isMeasurable
}; };
@ -91,27 +88,15 @@ public class FruitBankAttributeService(IGenericAttributeService genericAttribute
if (measuringAttributes == null) if (measuringAttributes == null)
{ {
await InsertGenericAttributeAsync<TEntity, double>(entityId, NET_WEIGHT_KEY, double.Round(measuringAttributeValues.NetWeight, 1), storeId); await InsertGenericAttributeAsync<TEntity, double>(entityId, NET_WEIGHT_KEY, double.Round(measuringAttributeValues.NetWeight, 1), storeId);
await InsertGenericAttributeAsync<TEntity, double>(entityId, GROSS_WEIGHT_KEY, double.Round(measuringAttributeValues.GrossWeight, 1), storeId);
await InsertGenericAttributeAsync<TEntity, bool>(entityId, IS_MEASURABLE_KEY, measuringAttributeValues.IsMeasurable, storeId); await InsertGenericAttributeAsync<TEntity, bool>(entityId, IS_MEASURABLE_KEY, measuringAttributeValues.IsMeasurable, storeId);
return; return;
} }
await UpdateMeasuringWeightAttributeValueAsync(measuringAttributes.Single(ma => ma.Key == NET_WEIGHT_KEY), measuringAttributeValues.NetWeight, cumulativeWeightUpdate); await UpdateMeasuringWeightAttributeValueAsync(measuringAttributes.Single(ma => ma.Key == NET_WEIGHT_KEY), measuringAttributeValues.NetWeight, cumulativeWeightUpdate);
await UpdateMeasuringWeightAttributeValueAsync(measuringAttributes.Single(ma => ma.Key == GROSS_WEIGHT_KEY), measuringAttributeValues.GrossWeight, cumulativeWeightUpdate);
await UpdateGenericAttributeAsync(measuringAttributes.Single(ma => ma.Key == IS_MEASURABLE_KEY), measuringAttributeValues.IsMeasurable);
//var netWeightAttribute = measuringAttributes?.SingleOrDefault(ma => ma.Key == NET_WEIGHT_KEY); //TODO: ezzel mi legyen? - J.
//if (netWeightAttribute != null) await UpdateMeasuringWeightAttributeValueAsync(netWeightAttribute, measuringAttributeValues.NetWeight, cumulativeWeightUpdate); //await UpdateGenericAttributeAsync(measuringAttributes.Single(ma => ma.Key == IS_MEASURABLE_KEY), measuringAttributeValues.IsMeasurable);
//else await InsertGenericAttributeAsync<TEntity, double>(entityId, NET_WEIGHT_KEY, measuringAttributeValues.NetWeight, storeId);
//var grossWeightAttribute = measuringAttributes?.SingleOrDefault(ma => ma.Key == GROSS_WEIGHT_KEY);
//if (grossWeightAttribute != null) await UpdateMeasuringWeightAttributeValueAsync(grossWeightAttribute, measuringAttributeValues.GrossWeight, cumulativeWeightUpdate);
//else await InsertGenericAttributeAsync<TEntity, double>(entityId, GROSS_WEIGHT_KEY, measuringAttributeValues.GrossWeight, storeId);
//var isMeasurableAttribute = measuringAttributes?.SingleOrDefault(ma => ma.Key == IS_MEASURABLE_KEY);
//if (isMeasurableAttribute != null) await UpdateGenericAttributeAsync(isMeasurableAttribute, measuringAttributeValues.IsMeasurable);
//else await InsertGenericAttributeAsync<TEntity, bool>(entityId, IS_MEASURABLE_KEY, measuringAttributeValues.IsMeasurable, storeId);
} }
private async Task UpdateMeasuringWeightAttributeValueAsync(GenericAttribute genericAttribute, double newWeightValue, bool cumulativeWeightUpdate) private async Task UpdateMeasuringWeightAttributeValueAsync(GenericAttribute genericAttribute, double newWeightValue, bool cumulativeWeightUpdate)

View File

@ -1,5 +1,6 @@
using Nop.Core.Domain.Orders; using FruitBank.Common.Interfaces;
using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Core.Domain.Orders;
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
using Nop.Services.Common; using Nop.Services.Common;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services namespace Nop.Plugin.Misc.FruitBankPlugin.Services
@ -24,7 +25,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
return false; return false;
return await _genericAttributeService.GetAttributeAsync<bool>( return await _genericAttributeService.GetAttributeAsync<bool>(
order, nameof(OrderModelExtended.IsMeasurable), order.StoreId); order, nameof(IMeasurable.IsMeasurable), order.StoreId);
} }
} }
} }

View File

@ -1,4 +1,5 @@
@model Nop.Plugin.Misc.FruitBankPlugin.Models.OrderAttributesModel @using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
@model OrderAttributesModel
<div class="card card-default"> <div class="card card-default">
<div class="card-header"> <div class="card-header">