diff --git a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs index 64c0a04..e9aae89 100644 --- a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs +++ b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/CustomOrderController.cs @@ -17,6 +17,7 @@ using Nop.Core.Domain.Payments; using Nop.Core.Domain.Shipping; using Nop.Core.Domain.Tax; using Nop.Core.Events; +using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Factories; using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders; @@ -157,7 +158,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers public virtual async Task List(List orderStatuses = null, List paymentStatuses = null, List shippingStatuses = null) { //prepare model - var model = await _orderModelFactory.PrepareOrderSearchModelAsync(new OrderSearchModel + var model = await _orderModelFactory.PrepareOrderSearchModelAsync(new OrderSearchModelExtended { OrderStatusIds = orderStatuses, PaymentStatusIds = paymentStatuses, @@ -169,7 +170,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [HttpPost] [CheckPermission(StandardPermission.Orders.ORDERS_VIEW)] - public async Task OrderList(OrderSearchModel searchModel) + public async Task OrderList(OrderSearchModelExtended searchModel) { //prepare model var orderListModel = await GetOrderListModelByFilter(searchModel); @@ -213,7 +214,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/Edit.cshtml", model); } - public async Task GetOrderListModelByFilter(OrderSearchModel searchModel) + public async Task GetOrderListModelByFilter(OrderSearchModelExtended searchModel) { //return _customOrderService. var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel); @@ -736,7 +737,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [HttpPost, ActionName("ExportXml")] [FormValueRequired("exportxml-all")] [CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)] - public virtual async Task ExportXmlAll(OrderSearchModel model) + public virtual async Task ExportXmlAll(OrderSearchModelExtended model) { var startDateValue = model.StartDate == null ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()); @@ -832,7 +833,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers [HttpPost, ActionName("ExportExcel")] [FormValueRequired("exportexcel-all")] [CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)] - public virtual async Task ExportExcelAll(OrderSearchModel model) + public virtual async Task ExportExcelAll(OrderSearchModelExtended model) { var startDateValue = model.StartDate == null ? null : (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()); diff --git a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/InnVoiceOrderController.cs b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/InnVoiceOrderController.cs index 9c994a4..3cde4d9 100644 --- a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/InnVoiceOrderController.cs +++ b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Controllers/InnVoiceOrderController.cs @@ -63,125 +63,137 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers { try { + // Validate and get order var order = await _orderService.GetOrderByIdAsync(orderId); if (order == null) + { return Json(new { success = false, message = "Order not found" }); + } + // Validate and get customer var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId); + if (customer == null) + { + return Json(new { success = false, message = "Customer not found" }); + } - // Get billing address + // Get and validate billing address var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer); if (billingAddress == null) + { return Json(new { success = false, message = "Billing address not found" }); + } var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress); var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU"; - // Get shipping address - var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer); - - if (shippingAddress == null) - { - shippingAddress = billingAddress; - } - - var shippingCountry = shippingAddress != null - ? await _countryService.GetCountryByAddressAsync(shippingAddress) - : null; - var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode; + // Get shipping address (fallback to billing if not found) + var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer) ?? billingAddress; + var shippingCountry = await _countryService.GetCountryByAddressAsync(shippingAddress); + var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode; // Create order request var orderRequest = new OrderCreateRequest { - VevoNev = $"{billingAddress.FirstName} {billingAddress.LastName}", - VevoIrsz = billingAddress.ZipPostalCode ?? "", - VevoTelep = billingAddress.City ?? "", + VevoNev = customer.Company ?? string.Empty, + VevoIrsz = billingAddress.ZipPostalCode ?? string.Empty, + VevoTelep = billingAddress.City ?? string.Empty, VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(), VevoOrszag = billingCountryCode, - VevoAdoszam = billingAddress.Company, // Or a custom field for tax number - MegrendelestombID = 1, // Configure this based on your setup + VevoAdoszam = customer.VatNumber, + MegrendelestombID = 1, MegrendelesKelte = order.CreatedOnUtc.ToLocalTime(), - Hatarido = DateTime.Now.AddDays(7), // 7 days delivery time - Devizanem = "Ft", //TODO get real deault - A. + Hatarido = DateTime.Now.AddDays(7), + Devizanem = "Ft", // TODO: get real default - A. FizetesiMod = order.PaymentMethodSystemName ?? "átutalás", - Email = billingAddress.Email, - Telefon = billingAddress.PhoneNumber, + Email = customer.Email ?? string.Empty, + Telefon = billingAddress.PhoneNumber ?? string.Empty, MegrendelesSzamStr = order.Id.ToString() }; - // Add shipping address if different - if (shippingAddress != null) + // Add shipping address details + orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}".Trim(); + orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? string.Empty; + orderRequest.SzallTelep = shippingAddress.City ?? string.Empty; + orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim(); + orderRequest.SzallOrszag = shippingCountryCode; + + // Get and validate order items + var orderItems = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id, true).ToListAsync(); + + if (orderItems == null || orderItems.Count == 0) { - orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}"; - orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? ""; - orderRequest.SzallTelep = shippingAddress.City ?? ""; - orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim(); - orderRequest.SzallOrszag = shippingCountryCode; + return Json(new { success = false, message = "Order has no items" }); } // Add order items - //var orderItems = await _orderService.GetOrderItemsAsync(order.Id); - var orderItems = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id, true).ToListAsync(); - Console.WriteLine($"Order Items Count: {orderItems.Count}"); foreach (var item in orderItems) { - //var productDTO = await _productService.GetProductByIdAsync(item.ProductId); var product = _dbContext.ProductDtos.GetById(item.ProductId); - //string unit = product != null && product.IsMeasurable ? "kg" : "kt"; - if(item.IsMeasurable) { // in case of measurable products, quantity is in fact weight stored in item.EnteredQuantity + var productName = product?.Name ?? "Product"; + + if (item.IsMeasurable) + { + // For measurable products, quantity is weight stored in NetWeight orderRequest.AddItem(new InnVoiceOrderItem { - TetelNev = product?.Name ?? "Product", - AfaSzoveg = "27%", // Configure VAT rate as needed + TetelNev = productName, + AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically Brutto = true, EgysegAr = item.UnitPriceInclTax, - Mennyiseg = Convert.ToDecimal(item.NetWeight), + Mennyiseg = item.NetWeight > 0 ? Convert.ToDecimal(item.NetWeight) : 0, MennyisegEgyseg = "kg", - CikkSzam = "" + CikkSzam = string.Empty }); - } else { orderRequest.AddItem(new InnVoiceOrderItem { - TetelNev = product?.Name ?? "Product", - AfaSzoveg = "27%", // Configure VAT rate as needed + TetelNev = productName, + AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically Brutto = true, EgysegAr = item.UnitPriceInclTax, Mennyiseg = item.Quantity, MennyisegEgyseg = "kt", - CikkSzam = "" + CikkSzam = string.Empty }); } - } // Create order via API var response = await _innVoiceOrderService.CreateOrderAsync(orderRequest); + if (response == null) + { + return Json(new { success = false, message = "No response from InnVoice API" }); + } + if (response.IsSuccess) { - // Save the TechId, TableId, and PrintUrl to the order for future reference + var currentStore = await _storeContext.GetCurrentStoreAsync(); + var storeId = currentStore?.Id ?? 0; + + // Save InnVoice order details as attributes await _genericAttributeService.SaveAttributeAsync( order, "InnVoiceOrderTechId", response.TechId, - (await _storeContext.GetCurrentStoreAsync()).Id + storeId ); await _genericAttributeService.SaveAttributeAsync( order, "InnVoiceOrderTableId", - response.TableId?.ToString(), - (await _storeContext.GetCurrentStoreAsync()).Id + response.TableId?.ToString() ?? string.Empty, + storeId ); await _genericAttributeService.SaveAttributeAsync( order, "InnVoiceOrderPrintLink", - response.PrintUrl?.ToString(), - (await _storeContext.GetCurrentStoreAsync()).Id + response.PrintUrl?.ToString() ?? string.Empty, + storeId ); return Json(new @@ -196,17 +208,18 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers } }); } - else + + return Json(new { - return Json(new - { - success = false, - message = $"InnVoice API Error: {response.Message}" - }); - } + success = false, + message = $"InnVoice API Error: {response.Message ?? "Unknown error"}" + }); } catch (Exception ex) { + // Log the exception here + // _logger.LogError(ex, "Error creating order {OrderId} in InnVoice", orderId); + return Json(new { success = false, diff --git a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Models/Order/OrderSearchModelExtended.cs b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Models/Order/OrderSearchModelExtended.cs new file mode 100644 index 0000000..05ec6ac --- /dev/null +++ b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Models/Order/OrderSearchModelExtended.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.Mvc.Rendering; +using Nop.Web.Areas.Admin.Models.Orders; +using Nop.Web.Framework.Mvc.ModelBinding; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order +{ + public partial record OrderSearchModelExtended : OrderSearchModel + { + + [NopResourceDisplayName("Admin.Orders.List.BillingCompany")] + public string BillingCompany { get; set; } + + //public IList AvailableCompanies { get; set; } + + } +} diff --git a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/Order/List.cshtml b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/Order/List.cshtml index 4727a6c..85a98bc 100644 --- a/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/Order/List.cshtml +++ b/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/Order/List.cshtml @@ -1,7 +1,9 @@ -@model OrderSearchModel +@model OrderSearchModelExtended + @inject IStoreService storeService @using FruitBank.Common.Interfaces +@using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order @using Nop.Plugin.Misc.FruitBankPlugin.Models @using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders @using Nop.Services.Stores @@ -96,7 +98,7 @@ - @await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.OrderListButtons, additionalData = Model }) + @await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.OrderListButtons, additionalData = (OrderSearchModel)Model }) @@ -174,6 +176,45 @@ + +
+
+ +
+
+ + + + + +
+
+
@@ -326,6 +367,7 @@ new FilterParameter(nameof(Model.BillingEmail)), new FilterParameter(nameof(Model.BillingPhone)), new FilterParameter(nameof(Model.BillingLastName)), + new FilterParameter(nameof(Model.BillingCompany)), new FilterParameter(nameof(Model.BillingCountryId)), new FilterParameter(nameof(Model.PaymentMethodSystemName)), new FilterParameter(nameof(Model.ProductId)), diff --git a/Nop.Plugin.Misc.AIPlugin/Domains/DataLayer/FruitBankDbContext.cs b/Nop.Plugin.Misc.AIPlugin/Domains/DataLayer/FruitBankDbContext.cs index 9a943a2..0f5e19f 100644 --- a/Nop.Plugin.Misc.AIPlugin/Domains/DataLayer/FruitBankDbContext.cs +++ b/Nop.Plugin.Misc.AIPlugin/Domains/DataLayer/FruitBankDbContext.cs @@ -61,6 +61,7 @@ public class FruitBankDbContext : MgDbContextBase, public IRepository Customers { get; set; } public IRepository CustomerRoles { get; set; } public IRepository CustomerRoleMappings { get; set; } + public IRepository CustomerAddressMappings { get; set; } public FruitBankDbContext(INopDataProvider dataProvider, ILockService lockService, FruitBankAttributeService fruitBankAttributeService, IStoreContext storeContext, PartnerDbTable partnerDbTable, ShippingDbTable shippingDbTable, ShippingDocumentDbTable shippingDocumentDbTable, ShippingItemDbTable shippingItemDbTable, @@ -72,6 +73,7 @@ public class FruitBankDbContext : MgDbContextBase, IRepository productRepository, IRepository customerRepository, IRepository customerCustomerRoleMappingRepository, + IRepository customerAddressMappingRepository, IRepository customerRoleRepository,IEventPublisher eventPublisher, IEnumerable logWriters) : base(productRepository, orderRepository, orderItemRepository, dataProvider, lockService, new Logger(logWriters.ToArray())) { @@ -100,6 +102,7 @@ public class FruitBankDbContext : MgDbContextBase, Customers = customerRepository; CustomerRoles = customerRoleRepository; CustomerRoleMappings = customerCustomerRoleMappingRepository; + CustomerAddressMappings = customerAddressMappingRepository; } public IQueryable GetCustomersBySystemRoleName(string systemRoleName) @@ -528,4 +531,15 @@ public class FruitBankDbContext : MgDbContextBase, var list = await ShippingDocuments.GetAll(true).Where(sd => sd.ShippingId == shippingId).ToListAsync(); return list; } + + public async Task AddCustomerAddressMappingAsync(int customerId, int addressId) + { + var customerAddressMapping = new CustomerAddressMapping + { + CustomerId = customerId, + AddressId = addressId + }; + await CustomerAddressMappings.InsertAsync(customerAddressMapping); + return customerAddressMapping; + } } \ No newline at end of file diff --git a/Nop.Plugin.Misc.AIPlugin/Factories/CustomOrderModelFactory.cs b/Nop.Plugin.Misc.AIPlugin/Factories/CustomOrderModelFactory.cs index 695893a..5cd9b0f 100644 --- a/Nop.Plugin.Misc.AIPlugin/Factories/CustomOrderModelFactory.cs +++ b/Nop.Plugin.Misc.AIPlugin/Factories/CustomOrderModelFactory.cs @@ -39,6 +39,7 @@ 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; +using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order; namespace Nop.Plugin.Misc.FruitBankPlugin.Factories { @@ -149,7 +150,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories _orderMeasurementService = orderMeasurementService; } #endregion Ctor - public override async Task PrepareOrderSearchModelAsync(OrderSearchModel searchModel) + public override async Task PrepareOrderSearchModelAsync(OrderSearchModelExtended searchModel) { var baseModel = await base.PrepareOrderSearchModelAsync(searchModel); return baseModel; @@ -158,7 +159,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories public override async Task PrepareOrderListModelAsync(OrderSearchModel searchModel) => await base.PrepareOrderListModelAsync(searchModel); - public async Task PrepareOrderListModelExtendedAsync(OrderSearchModel searchModel) + public async Task PrepareOrderListModelExtendedAsync(OrderSearchModelExtended searchModel) { Dictionary orderDtosById = null; diff --git a/Nop.Plugin.Misc.AIPlugin/Factories/MgBase/MgOrderModelFactory.cs b/Nop.Plugin.Misc.AIPlugin/Factories/MgBase/MgOrderModelFactory.cs index 7ea8e50..f03c3f6 100644 --- a/Nop.Plugin.Misc.AIPlugin/Factories/MgBase/MgOrderModelFactory.cs +++ b/Nop.Plugin.Misc.AIPlugin/Factories/MgBase/MgOrderModelFactory.cs @@ -1,6 +1,8 @@ using AyCode.Core.Extensions; using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.AspNetCore.Mvc.Rendering; using Microsoft.AspNetCore.Mvc.Routing; +using Newtonsoft.Json; using Nop.Core; using Nop.Core.Domain.Catalog; using Nop.Core.Domain.Common; @@ -8,6 +10,7 @@ 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.Areas.Admin.Models.Order; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders; using Nop.Plugin.Misc.FruitBankPlugin.Services; @@ -30,7 +33,9 @@ using Nop.Services.Stores; using Nop.Services.Tax; using Nop.Services.Vendors; using Nop.Web.Areas.Admin.Factories; +using Nop.Web.Areas.Admin.Models.Common; using Nop.Web.Areas.Admin.Models.Orders; +using Nop.Web.Framework.Extensions; namespace Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase; @@ -138,18 +143,120 @@ public class MgOrderModelFactory : OrderMode } #endregion Cotr - public override Task PrepareOrderSearchModelAsync(OrderSearchModel searchModel) - => base.PrepareOrderSearchModelAsync(searchModel); - - public override Task PrepareOrderListModelAsync(OrderSearchModel searchModel) - => base.PrepareOrderListModelAsync(searchModel); - - public virtual async Task PrepareOrderListModelExtendedAsync(OrderSearchModel searchModel, Func dataItemCopiedCallback) + public virtual async Task PrepareOrderSearchModelAsync(OrderSearchModelExtended searchModel) { - var orderListModel = await PrepareOrderListModelAsync(searchModel); - var extendedRows = new List(orderListModel.RecordsFiltered); + ArgumentNullException.ThrowIfNull(searchModel); - foreach (var orderModel in orderListModel.Data.ToList()) + searchModel.IsLoggedInAsVendor = await _workContext.GetCurrentVendorAsync() != null; + searchModel.BillingPhoneEnabled = _addressSettings.PhoneEnabled; + + var licenseCheckModel = new LicenseCheckModel(); + try + { + var result = await _nopHttpClient.GetLicenseCheckDetailsAsync(); + if (!string.IsNullOrEmpty(result)) + { + licenseCheckModel = JsonConvert.DeserializeObject(result); + if (licenseCheckModel.DisplayWarning == false && licenseCheckModel.BlockPages == false) + await _settingService.SetSettingAsync($"{nameof(AdminAreaSettings)}.{nameof(AdminAreaSettings.CheckLicense)}", false); + } + } + catch { } + searchModel.LicenseCheckModel = licenseCheckModel; + + //prepare available order, payment and shipping statuses + await _baseAdminModelFactory.PrepareOrderStatusesAsync(searchModel.AvailableOrderStatuses); + if (searchModel.AvailableOrderStatuses.Any()) + { + if (searchModel.OrderStatusIds?.Any() ?? false) + { + var ids = searchModel.OrderStatusIds.Select(id => id.ToString()); + var statusItems = searchModel.AvailableOrderStatuses.Where(statusItem => ids.Contains(statusItem.Value)).ToList(); + foreach (var statusItem in statusItems) + { + statusItem.Selected = true; + } + } + else + searchModel.AvailableOrderStatuses.FirstOrDefault().Selected = true; + } + + await _baseAdminModelFactory.PreparePaymentStatusesAsync(searchModel.AvailablePaymentStatuses); + if (searchModel.AvailablePaymentStatuses.Any()) + { + if (searchModel.PaymentStatusIds?.Any() ?? false) + { + var ids = searchModel.PaymentStatusIds.Select(id => id.ToString()); + var statusItems = searchModel.AvailablePaymentStatuses.Where(statusItem => ids.Contains(statusItem.Value)).ToList(); + foreach (var statusItem in statusItems) + { + statusItem.Selected = true; + } + } + else + searchModel.AvailablePaymentStatuses.FirstOrDefault().Selected = true; + } + + await _baseAdminModelFactory.PrepareShippingStatusesAsync(searchModel.AvailableShippingStatuses); + if (searchModel.AvailableShippingStatuses.Any()) + { + if (searchModel.ShippingStatusIds?.Any() ?? false) + { + var ids = searchModel.ShippingStatusIds.Select(id => id.ToString()); + var statusItems = searchModel.AvailableShippingStatuses.Where(statusItem => ids.Contains(statusItem.Value)).ToList(); + foreach (var statusItem in statusItems) + { + statusItem.Selected = true; + } + } + else + searchModel.AvailableShippingStatuses.FirstOrDefault().Selected = true; + } + + //prepare available stores + await _baseAdminModelFactory.PrepareStoresAsync(searchModel.AvailableStores); + + //prepare available vendors + await _baseAdminModelFactory.PrepareVendorsAsync(searchModel.AvailableVendors); + + //prepare available warehouses + await _baseAdminModelFactory.PrepareWarehousesAsync(searchModel.AvailableWarehouses); + + + //prepare available payment methods + searchModel.AvailablePaymentMethods = (await _paymentPluginManager.LoadAllPluginsAsync()).Select(method => + new SelectListItem { Text = method.PluginDescriptor.FriendlyName, Value = method.PluginDescriptor.SystemName }).ToList(); + searchModel.AvailablePaymentMethods.Insert(0, new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.Common.All"), Value = string.Empty }); + + //prepare available billing countries + searchModel.AvailableCountries = (await _countryService.GetAllCountriesForBillingAsync(showHidden: true)) + .Select(country => new SelectListItem { Text = country.Name, Value = country.Id.ToString() }).ToList(); + searchModel.AvailableCountries.Insert(0, new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.Common.All"), Value = "0" }); + + //searchModel.AvailableCompanies = (await _customerService.GetAllCustomersAsync()) + // .Select(customer => new SelectListItem { Text = customer.Company, Value = customer.Id.ToString() }).ToList(); + //searchModel.AvailableCompanies.Insert(0, new SelectListItem { Text = await _localizationService.GetResourceAsync("Admin.Common.All"), Value = "0" }); + + //prepare grid + searchModel.SetGridPageSize(); + + searchModel.HideStoresList = _catalogSettings.IgnoreStoreLimitations || searchModel.AvailableStores.SelectionIsNotPossible(); + + return searchModel; + } + + public override async Task PrepareOrderListModelAsync(OrderSearchModel searchModel) + { + var preFiltered = await base.PrepareOrderListModelAsync(searchModel); + return preFiltered; + } + public virtual async Task PrepareOrderListModelExtendedAsync(OrderSearchModelExtended searchModel, Func dataItemCopiedCallback) + { + var prefiltered = await PrepareOrderListModelAsync(searchModel); + + var extendedRows = new List(prefiltered.RecordsFiltered); + + foreach (var orderModel in prefiltered.Data.ToList()) { var orderModelExtended = Activator.CreateInstance(); @@ -157,15 +264,22 @@ public class MgOrderModelFactory : OrderMode extendedRows.Add(orderModelExtended); if (dataItemCopiedCallback == null) continue; - await dataItemCopiedCallback.Invoke(orderListModel, orderModelExtended); + await dataItemCopiedCallback.Invoke(prefiltered, orderModelExtended); } - orderListModel.Data = null; + prefiltered.Data = null; //var orderListModelExtended = orderListModel.ToJson().JsonTo(); - var orderListModelExtended = orderListModel.CloneTo(); - orderListModelExtended.Data = extendedRows; + if(searchModel.BillingCompany != null) + { + //extendedRows = extendedRows.Where(x => x.CustomerCompany != null && x.CustomerCompany.IndexOf(searchModel.BillingCompany, StringComparison.InvariantCultureIgnoreCase) >= 0).ToList(); + extendedRows = extendedRows.Where(x => x.CustomerId == Convert.ToInt32(searchModel.BillingCompany)).ToList(); + } + + var orderListModelExtended = prefiltered.CloneTo(); + orderListModelExtended.Data = extendedRows; + orderListModelExtended.RecordsFiltered = extendedRows.Count; return orderListModelExtended; } } \ No newline at end of file diff --git a/Nop.Plugin.Misc.AIPlugin/Services/EventConsumer.cs b/Nop.Plugin.Misc.AIPlugin/Services/EventConsumer.cs index 0848d91..5627281 100644 --- a/Nop.Plugin.Misc.AIPlugin/Services/EventConsumer.cs +++ b/Nop.Plugin.Misc.AIPlugin/Services/EventConsumer.cs @@ -1,9 +1,17 @@ using FruitBank.Common.Interfaces; +using FruitBank.Common.Server; +using Mango.Nop.Core.Dtos; using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.IdentityModel.Tokens; using Nop.Core; using Nop.Core.Domain.Catalog; +using Nop.Core.Domain.Common; +using Nop.Core.Domain.Customers; using Nop.Core.Domain.Orders; +using Nop.Core.Domain.Tax; using Nop.Core.Events; +using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Models; using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders; using Nop.Services.Catalog; @@ -16,11 +24,10 @@ using Nop.Web.Framework.Events; using Nop.Web.Framework.Menu; using Nop.Web.Models.Sitemap; using System.Linq; -using Microsoft.IdentityModel.Tokens; namespace Nop.Plugin.Misc.FruitBankPlugin.Services { - public class EventConsumer : BaseAdminMenuCreatedEventConsumer, IConsumer, IConsumer>, IConsumer + public class EventConsumer : BaseAdminMenuCreatedEventConsumer, IConsumer>, IConsumer>, IConsumer, IConsumer>, IConsumer { private readonly IGenericAttributeService _genericAttributeService; private readonly IProductService _productService; @@ -32,7 +39,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services private readonly IAdminMenu _adminMenu; private readonly ILocalizationService _localizationService; private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IAddressService _addressService; private readonly FruitBankAttributeService _fruitBankAttributeService; + private readonly FruitBankDbContext _dbContext; public EventConsumer( IGenericAttributeService genericAttributeService, @@ -46,7 +55,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services IAdminMenu adminMenu, ILocalizationService localizationService, IHttpContextAccessor httpContextAccessor, - FruitBankAttributeService fruitBankAttributeService) : base(pluginManager) + IAddressService addressService, + FruitBankAttributeService fruitBankAttributeService, + FruitBankDbContext dbContext) : base(pluginManager) { _genericAttributeService = genericAttributeService; _productService = productService; @@ -58,7 +69,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services _adminMenu = adminMenu; _localizationService = localizationService; _httpContextAccessor = httpContextAccessor; + _addressService = addressService; _fruitBankAttributeService = fruitBankAttributeService; + _dbContext = dbContext; } protected override string PluginSystemName => "Misc.FruitBankPlugin"; @@ -210,5 +223,82 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services }); } + + public async Task HandleEventAsync(EntityInsertedEvent eventMessage) + { + await ProcessCustomerEventAsync(eventMessage?.Entity); + } + + public async Task HandleEventAsync(EntityUpdatedEvent eventMessage) + { + await ProcessCustomerEventAsync(eventMessage?.Entity); + } + + private async Task ProcessCustomerEventAsync(Customer customer) + { + if (customer == null) + { + return; + } + + if (!IsRegisteredCustomer(customer)) + { + return; + } + + await EnsureBillingAddressAsync(customer); + await SynchronizeTaxInformationAsync(customer); + } + + private bool IsRegisteredCustomer(Customer customer) + { + var customerRoles = _dbContext.GetCustomerRolesByCustomerId(customer.Id); + return customerRoles?.Any(role => role.SystemName == "Registered") ?? false; + } + + private async Task EnsureBillingAddressAsync(Customer customer) + { + if (customer.BillingAddressId != null) + { + return; + } + + var address = new Address + { + ZipPostalCode = customer.ZipPostalCode, + City = customer.City, + Address1 = customer.StreetAddress, + Address2 = customer.StreetAddress2, + CountryId = customer.CountryId > 0 ? customer.CountryId : null, + StateProvinceId = customer.StateProvinceId > 0 ? customer.StateProvinceId : null, + PhoneNumber = customer.Phone, + Company = customer.Company, + FirstName = customer.FirstName, + LastName = customer.LastName, + Email = customer.Email, + County = customer.County + }; + + await _addressService.InsertAddressAsync(address); + await _dbContext.AddCustomerAddressMappingAsync(customer.Id, address.Id); + customer.BillingAddressId = address.Id; + } + + private async Task SynchronizeTaxInformationAsync(Customer customer) + { + var taxId = await _fruitBankAttributeService.GetGenericAttributeValueAsync(customer.Id, "TaxId"); + + if (!string.IsNullOrWhiteSpace(taxId) && string.IsNullOrWhiteSpace(customer.VatNumber)) + { + customer.VatNumber = taxId; + } + else if (string.IsNullOrWhiteSpace(taxId) && !string.IsNullOrWhiteSpace(customer.VatNumber)) + { + await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync( + customer.Id, + "TaxId", + customer.VatNumber); + } + } } } diff --git a/Nop.Plugin.Misc.AIPlugin/Services/InnVoiceOrderService.cs b/Nop.Plugin.Misc.AIPlugin/Services/InnVoiceOrderService.cs index b12ff60..46014ac 100644 --- a/Nop.Plugin.Misc.AIPlugin/Services/InnVoiceOrderService.cs +++ b/Nop.Plugin.Misc.AIPlugin/Services/InnVoiceOrderService.cs @@ -18,7 +18,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services private readonly string _password; private readonly string _baseUrl; - public InnVoiceOrderService(string companyName = "fruitbank", string username = "fruitbank", string password = "YkKzM1dwJax0HTIPWIMABSqdSA", string baseUrl = "https://api.innvoice.hu") + public InnVoiceOrderService(string companyName = "fruitbank", string username = "fruitbank", string password = "YkKzM1dwJax0HTlPWlMABSqdSA", string baseUrl = "https://api.innvoice.hu") { _companyName = companyName ?? throw new ArgumentNullException(nameof(companyName)); _username = username ?? throw new ArgumentNullException(nameof(username)); diff --git a/Nop.Plugin.Misc.AIPlugin/Views/OrderAttributes.cshtml b/Nop.Plugin.Misc.AIPlugin/Views/OrderAttributes.cshtml index 151433e..d9ad4ed 100644 --- a/Nop.Plugin.Misc.AIPlugin/Views/OrderAttributes.cshtml +++ b/Nop.Plugin.Misc.AIPlugin/Views/OrderAttributes.cshtml @@ -10,8 +10,9 @@
+

Innvoice

-
Order
+
Megrendelés beküldése Innvoice-ba
@@ -20,22 +21,22 @@

Order Tech ID:

- View Order PDF + PDF megtekintése

-
+
-
+ @*
Invoice
-
+
*@ -
+ @*
-
+
*@