Keresés partnerre a rendelések között, Felhasználó létrehozásakor automatikus számlázási cím hozzáadás, adószám szinkronizálás, egyéb kisebb fixek
This commit is contained in:
parent
9a94bc6c06
commit
30c8cd3e00
|
|
@ -17,6 +17,7 @@ using Nop.Core.Domain.Payments;
|
||||||
using Nop.Core.Domain.Shipping;
|
using Nop.Core.Domain.Shipping;
|
||||||
using Nop.Core.Domain.Tax;
|
using Nop.Core.Domain.Tax;
|
||||||
using Nop.Core.Events;
|
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.Domains.DataLayer;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Factories;
|
using Nop.Plugin.Misc.FruitBankPlugin.Factories;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
||||||
|
|
@ -157,7 +158,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
public virtual async Task<IActionResult> List(List<int> orderStatuses = null, List<int> paymentStatuses = null, List<int> shippingStatuses = null)
|
public virtual async Task<IActionResult> List(List<int> orderStatuses = null, List<int> paymentStatuses = null, List<int> shippingStatuses = null)
|
||||||
{
|
{
|
||||||
//prepare model
|
//prepare model
|
||||||
var model = await _orderModelFactory.PrepareOrderSearchModelAsync(new OrderSearchModel
|
var model = await _orderModelFactory.PrepareOrderSearchModelAsync(new OrderSearchModelExtended
|
||||||
{
|
{
|
||||||
OrderStatusIds = orderStatuses,
|
OrderStatusIds = orderStatuses,
|
||||||
PaymentStatusIds = paymentStatuses,
|
PaymentStatusIds = paymentStatuses,
|
||||||
|
|
@ -169,7 +170,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[CheckPermission(StandardPermission.Orders.ORDERS_VIEW)]
|
[CheckPermission(StandardPermission.Orders.ORDERS_VIEW)]
|
||||||
public async Task<IActionResult> OrderList(OrderSearchModel searchModel)
|
public async Task<IActionResult> OrderList(OrderSearchModelExtended searchModel)
|
||||||
{
|
{
|
||||||
//prepare model
|
//prepare model
|
||||||
var orderListModel = await GetOrderListModelByFilter(searchModel);
|
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);
|
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/Edit.cshtml", model);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<OrderListModelExtended> GetOrderListModelByFilter(OrderSearchModel searchModel)
|
public async Task<OrderListModelExtended> GetOrderListModelByFilter(OrderSearchModelExtended searchModel)
|
||||||
{
|
{
|
||||||
//return _customOrderService.
|
//return _customOrderService.
|
||||||
var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel);
|
var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel);
|
||||||
|
|
@ -736,7 +737,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
[HttpPost, ActionName("ExportXml")]
|
[HttpPost, ActionName("ExportXml")]
|
||||||
[FormValueRequired("exportxml-all")]
|
[FormValueRequired("exportxml-all")]
|
||||||
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
||||||
public virtual async Task<IActionResult> ExportXmlAll(OrderSearchModel model)
|
public virtual async Task<IActionResult> ExportXmlAll(OrderSearchModelExtended model)
|
||||||
{
|
{
|
||||||
var startDateValue = model.StartDate == null ? null
|
var startDateValue = model.StartDate == null ? null
|
||||||
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync());
|
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync());
|
||||||
|
|
@ -832,7 +833,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
[HttpPost, ActionName("ExportExcel")]
|
[HttpPost, ActionName("ExportExcel")]
|
||||||
[FormValueRequired("exportexcel-all")]
|
[FormValueRequired("exportexcel-all")]
|
||||||
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
||||||
public virtual async Task<IActionResult> ExportExcelAll(OrderSearchModel model)
|
public virtual async Task<IActionResult> ExportExcelAll(OrderSearchModelExtended model)
|
||||||
{
|
{
|
||||||
var startDateValue = model.StartDate == null ? null
|
var startDateValue = model.StartDate == null ? null
|
||||||
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync());
|
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync());
|
||||||
|
|
|
||||||
|
|
@ -63,125 +63,137 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// Validate and get order
|
||||||
var order = await _orderService.GetOrderByIdAsync(orderId);
|
var order = await _orderService.GetOrderByIdAsync(orderId);
|
||||||
if (order == null)
|
if (order == null)
|
||||||
|
{
|
||||||
return Json(new { success = false, message = "Order not found" });
|
return Json(new { success = false, message = "Order not found" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate and get customer
|
||||||
var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
|
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);
|
var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);
|
||||||
if (billingAddress == null)
|
if (billingAddress == null)
|
||||||
|
{
|
||||||
return Json(new { success = false, message = "Billing address not found" });
|
return Json(new { success = false, message = "Billing address not found" });
|
||||||
|
}
|
||||||
|
|
||||||
var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
|
var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
|
||||||
var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";
|
var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";
|
||||||
|
|
||||||
// Get shipping address
|
// Get shipping address (fallback to billing if not found)
|
||||||
var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer);
|
var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer) ?? billingAddress;
|
||||||
|
var shippingCountry = await _countryService.GetCountryByAddressAsync(shippingAddress);
|
||||||
if (shippingAddress == null)
|
|
||||||
{
|
|
||||||
shippingAddress = billingAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
var shippingCountry = shippingAddress != null
|
|
||||||
? await _countryService.GetCountryByAddressAsync(shippingAddress)
|
|
||||||
: null;
|
|
||||||
var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode;
|
var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode;
|
||||||
|
|
||||||
// Create order request
|
// Create order request
|
||||||
var orderRequest = new OrderCreateRequest
|
var orderRequest = new OrderCreateRequest
|
||||||
{
|
{
|
||||||
VevoNev = $"{billingAddress.FirstName} {billingAddress.LastName}",
|
VevoNev = customer.Company ?? string.Empty,
|
||||||
VevoIrsz = billingAddress.ZipPostalCode ?? "",
|
VevoIrsz = billingAddress.ZipPostalCode ?? string.Empty,
|
||||||
VevoTelep = billingAddress.City ?? "",
|
VevoTelep = billingAddress.City ?? string.Empty,
|
||||||
VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
|
VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
|
||||||
VevoOrszag = billingCountryCode,
|
VevoOrszag = billingCountryCode,
|
||||||
VevoAdoszam = billingAddress.Company, // Or a custom field for tax number
|
VevoAdoszam = customer.VatNumber,
|
||||||
MegrendelestombID = 1, // Configure this based on your setup
|
MegrendelestombID = 1,
|
||||||
MegrendelesKelte = order.CreatedOnUtc.ToLocalTime(),
|
MegrendelesKelte = order.CreatedOnUtc.ToLocalTime(),
|
||||||
Hatarido = DateTime.Now.AddDays(7), // 7 days delivery time
|
Hatarido = DateTime.Now.AddDays(7),
|
||||||
Devizanem = "Ft", //TODO get real deault - A.
|
Devizanem = "Ft", // TODO: get real default - A.
|
||||||
FizetesiMod = order.PaymentMethodSystemName ?? "átutalás",
|
FizetesiMod = order.PaymentMethodSystemName ?? "átutalás",
|
||||||
Email = billingAddress.Email,
|
Email = customer.Email ?? string.Empty,
|
||||||
Telefon = billingAddress.PhoneNumber,
|
Telefon = billingAddress.PhoneNumber ?? string.Empty,
|
||||||
MegrendelesSzamStr = order.Id.ToString()
|
MegrendelesSzamStr = order.Id.ToString()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add shipping address if different
|
// Add shipping address details
|
||||||
if (shippingAddress != null)
|
orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}".Trim();
|
||||||
{
|
orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? string.Empty;
|
||||||
orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}";
|
orderRequest.SzallTelep = shippingAddress.City ?? string.Empty;
|
||||||
orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? "";
|
|
||||||
orderRequest.SzallTelep = shippingAddress.City ?? "";
|
|
||||||
orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim();
|
orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim();
|
||||||
orderRequest.SzallOrszag = shippingCountryCode;
|
orderRequest.SzallOrszag = shippingCountryCode;
|
||||||
|
|
||||||
|
// Get and validate order items
|
||||||
|
var orderItems = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id, true).ToListAsync();
|
||||||
|
|
||||||
|
if (orderItems == null || orderItems.Count == 0)
|
||||||
|
{
|
||||||
|
return Json(new { success = false, message = "Order has no items" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add order 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)
|
foreach (var item in orderItems)
|
||||||
{
|
{
|
||||||
//var productDTO = await _productService.GetProductByIdAsync(item.ProductId);
|
|
||||||
var product = _dbContext.ProductDtos.GetById(item.ProductId);
|
var product = _dbContext.ProductDtos.GetById(item.ProductId);
|
||||||
//string unit = product != null && product.IsMeasurable ? "kg" : "kt";
|
var productName = product?.Name ?? "Product";
|
||||||
if(item.IsMeasurable) { // in case of measurable products, quantity is in fact weight stored in item.EnteredQuantity
|
|
||||||
|
if (item.IsMeasurable)
|
||||||
|
{
|
||||||
|
// For measurable products, quantity is weight stored in NetWeight
|
||||||
orderRequest.AddItem(new InnVoiceOrderItem
|
orderRequest.AddItem(new InnVoiceOrderItem
|
||||||
{
|
{
|
||||||
TetelNev = product?.Name ?? "Product",
|
TetelNev = productName,
|
||||||
AfaSzoveg = "27%", // Configure VAT rate as needed
|
AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically
|
||||||
Brutto = true,
|
Brutto = true,
|
||||||
EgysegAr = item.UnitPriceInclTax,
|
EgysegAr = item.UnitPriceInclTax,
|
||||||
Mennyiseg = Convert.ToDecimal(item.NetWeight),
|
Mennyiseg = item.NetWeight > 0 ? Convert.ToDecimal(item.NetWeight) : 0,
|
||||||
MennyisegEgyseg = "kg",
|
MennyisegEgyseg = "kg",
|
||||||
CikkSzam = ""
|
CikkSzam = string.Empty
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
orderRequest.AddItem(new InnVoiceOrderItem
|
orderRequest.AddItem(new InnVoiceOrderItem
|
||||||
{
|
{
|
||||||
TetelNev = product?.Name ?? "Product",
|
TetelNev = productName,
|
||||||
AfaSzoveg = "27%", // Configure VAT rate as needed
|
AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically
|
||||||
Brutto = true,
|
Brutto = true,
|
||||||
EgysegAr = item.UnitPriceInclTax,
|
EgysegAr = item.UnitPriceInclTax,
|
||||||
Mennyiseg = item.Quantity,
|
Mennyiseg = item.Quantity,
|
||||||
MennyisegEgyseg = "kt",
|
MennyisegEgyseg = "kt",
|
||||||
CikkSzam = ""
|
CikkSzam = string.Empty
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create order via API
|
// Create order via API
|
||||||
var response = await _innVoiceOrderService.CreateOrderAsync(orderRequest);
|
var response = await _innVoiceOrderService.CreateOrderAsync(orderRequest);
|
||||||
|
|
||||||
|
if (response == null)
|
||||||
|
{
|
||||||
|
return Json(new { success = false, message = "No response from InnVoice API" });
|
||||||
|
}
|
||||||
|
|
||||||
if (response.IsSuccess)
|
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(
|
await _genericAttributeService.SaveAttributeAsync(
|
||||||
order,
|
order,
|
||||||
"InnVoiceOrderTechId",
|
"InnVoiceOrderTechId",
|
||||||
response.TechId,
|
response.TechId,
|
||||||
(await _storeContext.GetCurrentStoreAsync()).Id
|
storeId
|
||||||
);
|
);
|
||||||
|
|
||||||
await _genericAttributeService.SaveAttributeAsync(
|
await _genericAttributeService.SaveAttributeAsync(
|
||||||
order,
|
order,
|
||||||
"InnVoiceOrderTableId",
|
"InnVoiceOrderTableId",
|
||||||
response.TableId?.ToString(),
|
response.TableId?.ToString() ?? string.Empty,
|
||||||
(await _storeContext.GetCurrentStoreAsync()).Id
|
storeId
|
||||||
);
|
);
|
||||||
|
|
||||||
await _genericAttributeService.SaveAttributeAsync(
|
await _genericAttributeService.SaveAttributeAsync(
|
||||||
order,
|
order,
|
||||||
"InnVoiceOrderPrintLink",
|
"InnVoiceOrderPrintLink",
|
||||||
response.PrintUrl?.ToString(),
|
response.PrintUrl?.ToString() ?? string.Empty,
|
||||||
(await _storeContext.GetCurrentStoreAsync()).Id
|
storeId
|
||||||
);
|
);
|
||||||
|
|
||||||
return Json(new
|
return Json(new
|
||||||
|
|
@ -196,17 +208,18 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return Json(new
|
return Json(new
|
||||||
{
|
{
|
||||||
success = false,
|
success = false,
|
||||||
message = $"InnVoice API Error: {response.Message}"
|
message = $"InnVoice API Error: {response.Message ?? "Unknown error"}"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
// Log the exception here
|
||||||
|
// _logger.LogError(ex, "Error creating order {OrderId} in InnVoice", orderId);
|
||||||
|
|
||||||
return Json(new
|
return Json(new
|
||||||
{
|
{
|
||||||
success = false,
|
success = false,
|
||||||
|
|
|
||||||
|
|
@ -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<SelectListItem> AvailableCompanies { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
@model OrderSearchModel
|
@model OrderSearchModelExtended
|
||||||
|
|
||||||
|
|
||||||
@inject IStoreService storeService
|
@inject IStoreService storeService
|
||||||
@using FruitBank.Common.Interfaces
|
@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
|
||||||
@using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
|
@using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
|
||||||
@using Nop.Services.Stores
|
@using Nop.Services.Stores
|
||||||
|
|
@ -96,7 +98,7 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.OrderListButtons, additionalData = Model })
|
@await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.OrderListButtons, additionalData = (OrderSearchModel)Model })
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -174,6 +176,45 @@
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<nop-label asp-for="BillingCompany" />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-8">
|
||||||
|
<input type="text" id="search-company-name" autocomplete="off" class="form-control" />
|
||||||
|
<span id="search-company-friendly-name"></span>
|
||||||
|
<button type="button" id="search-company-clear" class="btn bg-gray" style="display: none; margin-top: 5px;">@T("Admin.Common.Clear")</button>
|
||||||
|
<input asp-for="BillingCompany" autocomplete="off" style="display: none;" />
|
||||||
|
<script>
|
||||||
|
$(function() {
|
||||||
|
$('#search-company-name').autocomplete({
|
||||||
|
delay: 500,
|
||||||
|
minLength: 3,
|
||||||
|
source: '@Url.Action("CustomerSearchAutoComplete", "CustomOrder")',
|
||||||
|
select: function(event, ui) {
|
||||||
|
|
||||||
|
|
||||||
|
$('#@Html.IdFor(model => model.BillingCompany)').val(ui.item.value);
|
||||||
|
$('#search-company-friendly-name').text(ui.item.label);
|
||||||
|
|
||||||
|
$('#search-company-clear').show();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//remove button
|
||||||
|
$('#search-company-clear').click(function() {
|
||||||
|
$('#@Html.IdFor(model => model.BillingCompany)').val('');
|
||||||
|
$('#search-company-friendly-name').text('');
|
||||||
|
$('#search-company-clear').hide();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group row" @(Model.IsLoggedInAsVendor? Html.Raw("style='display: none;'") : null)>
|
<div class="form-group row" @(Model.IsLoggedInAsVendor? Html.Raw("style='display: none;'") : null)>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<nop-label asp-for="OrderStatusIds" />
|
<nop-label asp-for="OrderStatusIds" />
|
||||||
|
|
@ -326,6 +367,7 @@
|
||||||
new FilterParameter(nameof(Model.BillingEmail)),
|
new FilterParameter(nameof(Model.BillingEmail)),
|
||||||
new FilterParameter(nameof(Model.BillingPhone)),
|
new FilterParameter(nameof(Model.BillingPhone)),
|
||||||
new FilterParameter(nameof(Model.BillingLastName)),
|
new FilterParameter(nameof(Model.BillingLastName)),
|
||||||
|
new FilterParameter(nameof(Model.BillingCompany)),
|
||||||
new FilterParameter(nameof(Model.BillingCountryId)),
|
new FilterParameter(nameof(Model.BillingCountryId)),
|
||||||
new FilterParameter(nameof(Model.PaymentMethodSystemName)),
|
new FilterParameter(nameof(Model.PaymentMethodSystemName)),
|
||||||
new FilterParameter(nameof(Model.ProductId)),
|
new FilterParameter(nameof(Model.ProductId)),
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ public class FruitBankDbContext : MgDbContextBase,
|
||||||
public IRepository<Customer> Customers { get; set; }
|
public IRepository<Customer> Customers { get; set; }
|
||||||
public IRepository<CustomerRole> CustomerRoles { get; set; }
|
public IRepository<CustomerRole> CustomerRoles { get; set; }
|
||||||
public IRepository<CustomerCustomerRoleMapping> CustomerRoleMappings { get; set; }
|
public IRepository<CustomerCustomerRoleMapping> CustomerRoleMappings { get; set; }
|
||||||
|
public IRepository<CustomerAddressMapping> CustomerAddressMappings { get; set; }
|
||||||
|
|
||||||
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,
|
||||||
|
|
@ -72,6 +73,7 @@ public class FruitBankDbContext : MgDbContextBase,
|
||||||
IRepository<Product> productRepository,
|
IRepository<Product> productRepository,
|
||||||
IRepository<Customer> customerRepository,
|
IRepository<Customer> customerRepository,
|
||||||
IRepository<CustomerCustomerRoleMapping> customerCustomerRoleMappingRepository,
|
IRepository<CustomerCustomerRoleMapping> customerCustomerRoleMappingRepository,
|
||||||
|
IRepository<CustomerAddressMapping> customerAddressMappingRepository,
|
||||||
IRepository<CustomerRole> customerRoleRepository,IEventPublisher eventPublisher,
|
IRepository<CustomerRole> customerRoleRepository,IEventPublisher eventPublisher,
|
||||||
IEnumerable<IAcLogWriterBase> logWriters) : base(productRepository, orderRepository, orderItemRepository, dataProvider, lockService, new Logger<FruitBankDbContext>(logWriters.ToArray()))
|
IEnumerable<IAcLogWriterBase> logWriters) : base(productRepository, orderRepository, orderItemRepository, dataProvider, lockService, new Logger<FruitBankDbContext>(logWriters.ToArray()))
|
||||||
{
|
{
|
||||||
|
|
@ -100,6 +102,7 @@ public class FruitBankDbContext : MgDbContextBase,
|
||||||
Customers = customerRepository;
|
Customers = customerRepository;
|
||||||
CustomerRoles = customerRoleRepository;
|
CustomerRoles = customerRoleRepository;
|
||||||
CustomerRoleMappings = customerCustomerRoleMappingRepository;
|
CustomerRoleMappings = customerCustomerRoleMappingRepository;
|
||||||
|
CustomerAddressMappings = customerAddressMappingRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IQueryable<Customer> GetCustomersBySystemRoleName(string systemRoleName)
|
public IQueryable<Customer> GetCustomersBySystemRoleName(string systemRoleName)
|
||||||
|
|
@ -528,4 +531,15 @@ public class FruitBankDbContext : MgDbContextBase,
|
||||||
var list = await ShippingDocuments.GetAll(true).Where(sd => sd.ShippingId == shippingId).ToListAsync();
|
var list = await ShippingDocuments.GetAll(true).Where(sd => sd.ShippingId == shippingId).ToListAsync();
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<CustomerAddressMapping?> AddCustomerAddressMappingAsync(int customerId, int addressId)
|
||||||
|
{
|
||||||
|
var customerAddressMapping = new CustomerAddressMapping
|
||||||
|
{
|
||||||
|
CustomerId = customerId,
|
||||||
|
AddressId = addressId
|
||||||
|
};
|
||||||
|
await CustomerAddressMappings.InsertAsync(customerAddressMapping);
|
||||||
|
return customerAddressMapping;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,6 +39,7 @@ using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
|
using Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
|
||||||
using FruitBank.Common.Dtos;
|
using FruitBank.Common.Dtos;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
||||||
|
using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.Order;
|
||||||
|
|
||||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
|
||||||
{
|
{
|
||||||
|
|
@ -149,7 +150,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
|
||||||
_orderMeasurementService = orderMeasurementService;
|
_orderMeasurementService = orderMeasurementService;
|
||||||
}
|
}
|
||||||
#endregion Ctor
|
#endregion Ctor
|
||||||
public override async Task<OrderSearchModel> PrepareOrderSearchModelAsync(OrderSearchModel searchModel)
|
public override async Task<OrderSearchModelExtended> PrepareOrderSearchModelAsync(OrderSearchModelExtended searchModel)
|
||||||
{
|
{
|
||||||
var baseModel = await base.PrepareOrderSearchModelAsync(searchModel);
|
var baseModel = await base.PrepareOrderSearchModelAsync(searchModel);
|
||||||
return baseModel;
|
return baseModel;
|
||||||
|
|
@ -158,7 +159,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
|
||||||
public override async Task<OrderListModel> PrepareOrderListModelAsync(OrderSearchModel searchModel)
|
public override async Task<OrderListModel> PrepareOrderListModelAsync(OrderSearchModel searchModel)
|
||||||
=> await base.PrepareOrderListModelAsync(searchModel);
|
=> await base.PrepareOrderListModelAsync(searchModel);
|
||||||
|
|
||||||
public async Task<OrderListModelExtended> PrepareOrderListModelExtendedAsync(OrderSearchModel searchModel)
|
public async Task<OrderListModelExtended> PrepareOrderListModelExtendedAsync(OrderSearchModelExtended searchModel)
|
||||||
{
|
{
|
||||||
Dictionary<int, OrderDto> orderDtosById = null;
|
Dictionary<int, OrderDto> orderDtosById = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
using AyCode.Core.Extensions;
|
using AyCode.Core.Extensions;
|
||||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.AspNetCore.Mvc.Routing;
|
using Microsoft.AspNetCore.Mvc.Routing;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Nop.Core;
|
using Nop.Core;
|
||||||
using Nop.Core.Domain.Catalog;
|
using Nop.Core.Domain.Catalog;
|
||||||
using Nop.Core.Domain.Common;
|
using Nop.Core.Domain.Common;
|
||||||
|
|
@ -8,6 +10,7 @@ using Nop.Core.Domain.Directory;
|
||||||
using Nop.Core.Domain.Orders;
|
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.Areas.Admin.Models.Order;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
||||||
|
|
@ -30,7 +33,9 @@ using Nop.Services.Stores;
|
||||||
using Nop.Services.Tax;
|
using Nop.Services.Tax;
|
||||||
using Nop.Services.Vendors;
|
using Nop.Services.Vendors;
|
||||||
using Nop.Web.Areas.Admin.Factories;
|
using Nop.Web.Areas.Admin.Factories;
|
||||||
|
using Nop.Web.Areas.Admin.Models.Common;
|
||||||
using Nop.Web.Areas.Admin.Models.Orders;
|
using Nop.Web.Areas.Admin.Models.Orders;
|
||||||
|
using Nop.Web.Framework.Extensions;
|
||||||
|
|
||||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Factories.MgBase;
|
||||||
|
|
||||||
|
|
@ -138,18 +143,120 @@ public class MgOrderModelFactory<TOrderListModelExt, TOrderModelExt> : OrderMode
|
||||||
}
|
}
|
||||||
#endregion Cotr
|
#endregion Cotr
|
||||||
|
|
||||||
public override Task<OrderSearchModel> PrepareOrderSearchModelAsync(OrderSearchModel searchModel)
|
public virtual async Task<OrderSearchModelExtended> PrepareOrderSearchModelAsync(OrderSearchModelExtended 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);
|
ArgumentNullException.ThrowIfNull(searchModel);
|
||||||
var extendedRows = new List<TOrderModelExt>(orderListModel.RecordsFiltered);
|
|
||||||
|
|
||||||
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<LicenseCheckModel>(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<OrderListModel> PrepareOrderListModelAsync(OrderSearchModel searchModel)
|
||||||
|
{
|
||||||
|
var preFiltered = await base.PrepareOrderListModelAsync(searchModel);
|
||||||
|
return preFiltered;
|
||||||
|
}
|
||||||
|
public virtual async Task<TOrderListModelExt> PrepareOrderListModelExtendedAsync(OrderSearchModelExtended searchModel, Func<OrderListModel, TOrderModelExt, Task> dataItemCopiedCallback)
|
||||||
|
{
|
||||||
|
var prefiltered = await PrepareOrderListModelAsync(searchModel);
|
||||||
|
|
||||||
|
var extendedRows = new List<TOrderModelExt>(prefiltered.RecordsFiltered);
|
||||||
|
|
||||||
|
foreach (var orderModel in prefiltered.Data.ToList())
|
||||||
{
|
{
|
||||||
var orderModelExtended = Activator.CreateInstance<TOrderModelExt>();
|
var orderModelExtended = Activator.CreateInstance<TOrderModelExt>();
|
||||||
|
|
||||||
|
|
@ -157,15 +264,22 @@ public class MgOrderModelFactory<TOrderListModelExt, TOrderModelExt> : OrderMode
|
||||||
extendedRows.Add(orderModelExtended);
|
extendedRows.Add(orderModelExtended);
|
||||||
|
|
||||||
if (dataItemCopiedCallback == null) continue;
|
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<TOrderListModelExt>();
|
//var orderListModelExtended = orderListModel.ToJson().JsonTo<TOrderListModelExt>();
|
||||||
var orderListModelExtended = orderListModel.CloneTo<TOrderListModelExt>();
|
if(searchModel.BillingCompany != null)
|
||||||
orderListModelExtended.Data = extendedRows;
|
{
|
||||||
|
//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<TOrderListModelExt>();
|
||||||
|
orderListModelExtended.Data = extendedRows;
|
||||||
|
orderListModelExtended.RecordsFiltered = extendedRows.Count;
|
||||||
return orderListModelExtended;
|
return orderListModelExtended;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,17 @@
|
||||||
using FruitBank.Common.Interfaces;
|
using FruitBank.Common.Interfaces;
|
||||||
|
using FruitBank.Common.Server;
|
||||||
|
using Mango.Nop.Core.Dtos;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using Nop.Core;
|
using Nop.Core;
|
||||||
using Nop.Core.Domain.Catalog;
|
using Nop.Core.Domain.Catalog;
|
||||||
|
using Nop.Core.Domain.Common;
|
||||||
|
using Nop.Core.Domain.Customers;
|
||||||
using Nop.Core.Domain.Orders;
|
using Nop.Core.Domain.Orders;
|
||||||
|
using Nop.Core.Domain.Tax;
|
||||||
using Nop.Core.Events;
|
using Nop.Core.Events;
|
||||||
|
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Models;
|
using Nop.Plugin.Misc.FruitBankPlugin.Models;
|
||||||
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders;
|
||||||
using Nop.Services.Catalog;
|
using Nop.Services.Catalog;
|
||||||
|
|
@ -16,11 +24,10 @@ using Nop.Web.Framework.Events;
|
||||||
using Nop.Web.Framework.Menu;
|
using Nop.Web.Framework.Menu;
|
||||||
using Nop.Web.Models.Sitemap;
|
using Nop.Web.Models.Sitemap;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
|
||||||
|
|
||||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||||
{
|
{
|
||||||
public class EventConsumer : BaseAdminMenuCreatedEventConsumer, IConsumer<OrderPlacedEvent>, IConsumer<EntityUpdatedEvent<Order>>, IConsumer<AdminMenuCreatedEvent>
|
public class EventConsumer : BaseAdminMenuCreatedEventConsumer, IConsumer<EntityUpdatedEvent<Customer>>, IConsumer<EntityInsertedEvent<Customer>>, IConsumer<OrderPlacedEvent>, IConsumer<EntityUpdatedEvent<Order>>, IConsumer<AdminMenuCreatedEvent>
|
||||||
{
|
{
|
||||||
private readonly IGenericAttributeService _genericAttributeService;
|
private readonly IGenericAttributeService _genericAttributeService;
|
||||||
private readonly IProductService _productService;
|
private readonly IProductService _productService;
|
||||||
|
|
@ -32,7 +39,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||||
private readonly IAdminMenu _adminMenu;
|
private readonly IAdminMenu _adminMenu;
|
||||||
private readonly ILocalizationService _localizationService;
|
private readonly ILocalizationService _localizationService;
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
|
private readonly IAddressService _addressService;
|
||||||
private readonly FruitBankAttributeService _fruitBankAttributeService;
|
private readonly FruitBankAttributeService _fruitBankAttributeService;
|
||||||
|
private readonly FruitBankDbContext _dbContext;
|
||||||
|
|
||||||
public EventConsumer(
|
public EventConsumer(
|
||||||
IGenericAttributeService genericAttributeService,
|
IGenericAttributeService genericAttributeService,
|
||||||
|
|
@ -46,7 +55,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||||
IAdminMenu adminMenu,
|
IAdminMenu adminMenu,
|
||||||
ILocalizationService localizationService,
|
ILocalizationService localizationService,
|
||||||
IHttpContextAccessor httpContextAccessor,
|
IHttpContextAccessor httpContextAccessor,
|
||||||
FruitBankAttributeService fruitBankAttributeService) : base(pluginManager)
|
IAddressService addressService,
|
||||||
|
FruitBankAttributeService fruitBankAttributeService,
|
||||||
|
FruitBankDbContext dbContext) : base(pluginManager)
|
||||||
{
|
{
|
||||||
_genericAttributeService = genericAttributeService;
|
_genericAttributeService = genericAttributeService;
|
||||||
_productService = productService;
|
_productService = productService;
|
||||||
|
|
@ -58,7 +69,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||||
_adminMenu = adminMenu;
|
_adminMenu = adminMenu;
|
||||||
_localizationService = localizationService;
|
_localizationService = localizationService;
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
|
_addressService = addressService;
|
||||||
_fruitBankAttributeService = fruitBankAttributeService;
|
_fruitBankAttributeService = fruitBankAttributeService;
|
||||||
|
_dbContext = dbContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override string PluginSystemName => "Misc.FruitBankPlugin";
|
protected override string PluginSystemName => "Misc.FruitBankPlugin";
|
||||||
|
|
@ -210,5 +223,82 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityInsertedEvent<Customer> eventMessage)
|
||||||
|
{
|
||||||
|
await ProcessCustomerEventAsync(eventMessage?.Entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task HandleEventAsync(EntityUpdatedEvent<Customer> 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, string>(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, string>(
|
||||||
|
customer.Id,
|
||||||
|
"TaxId",
|
||||||
|
customer.VatNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||||
private readonly string _password;
|
private readonly string _password;
|
||||||
private readonly string _baseUrl;
|
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));
|
_companyName = companyName ?? throw new ArgumentNullException(nameof(companyName));
|
||||||
_username = username ?? throw new ArgumentNullException(nameof(username));
|
_username = username ?? throw new ArgumentNullException(nameof(username));
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<!-- Order Subsection -->
|
<!-- Order Subsection -->
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
|
<h3>Innvoice</h3>
|
||||||
<div class="col-12 col-md-3">
|
<div class="col-12 col-md-3">
|
||||||
<h5><i class="fas fa-shopping-cart"></i> Order</h5>
|
<h5><i class="fas fa-shopping-cart"></i> Megrendelés beküldése Innvoice-ba</h5>
|
||||||
<div id="orderStatus" class="alert alert-info" style="display: none;">
|
<div id="orderStatus" class="alert alert-info" style="display: none;">
|
||||||
<i class="fas fa-info-circle"></i> <span id="orderStatusMessage"></span>
|
<i class="fas fa-info-circle"></i> <span id="orderStatusMessage"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -20,22 +21,22 @@
|
||||||
<p><strong>Order Tech ID:</strong> <span id="orderTechId"></span></p>
|
<p><strong>Order Tech ID:</strong> <span id="orderTechId"></span></p>
|
||||||
<p>
|
<p>
|
||||||
<a id="orderPdfLink" href="#" target="_blank" class="btn btn-sm btn-info">
|
<a id="orderPdfLink" href="#" target="_blank" class="btn btn-sm btn-info">
|
||||||
<i class="fas fa-file-pdf"></i> View Order PDF
|
<i class="fas fa-file-pdf"></i> PDF megtekintése
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 col-md-3 text-right">
|
<div class="col-12 col-md-3 text-right float-end">
|
||||||
<button type="button" id="createOrderBtn" class="btn btn-success">
|
<button type="button" id="createOrderBtn" class="btn btn-success">
|
||||||
<i class="fas fa-shopping-cart"></i> Create Order in InnVoice
|
<i class="fas fa-shopping-cart"></i> Létrehozás
|
||||||
</button>
|
</button>
|
||||||
<button type="button" id="checkOrderBtn" class="btn btn-secondary" style="display: none;">
|
<button type="button" id="checkOrderBtn" class="btn btn-secondary" style="display: none;">
|
||||||
<i class="fas fa-sync"></i> Refresh Order
|
<i class="fas fa-sync"></i> Invoice adat ellenőrzése
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 col-md-3">
|
@* <div class="col-12 col-md-3">
|
||||||
<h5><i class="fas fa-file-invoice-dollar"></i> Invoice</h5>
|
<h5><i class="fas fa-file-invoice-dollar"></i> Invoice</h5>
|
||||||
<div id="invoiceStatus" class="alert alert-info" style="display: none;">
|
<div id="invoiceStatus" class="alert alert-info" style="display: none;">
|
||||||
<i class="fas fa-info-circle"></i> <span id="invoiceStatusMessage"></span>
|
<i class="fas fa-info-circle"></i> <span id="invoiceStatusMessage"></span>
|
||||||
|
|
@ -49,16 +50,16 @@
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> *@
|
||||||
|
|
||||||
<div class="col-12 col-md-3 text-right">
|
@* <div class="col-12 col-md-3 text-right">
|
||||||
<button type="button" id="createInvoiceBtn" class="btn btn-success">
|
<button type="button" id="createInvoiceBtn" class="btn btn-success">
|
||||||
<i class="fas fa-file-invoice-dollar"></i> Create Invoice
|
<i class="fas fa-file-invoice-dollar"></i> Create Invoice
|
||||||
</button>
|
</button>
|
||||||
<button type="button" id="checkInvoiceBtn" class="btn btn-secondary" style="display: none;">
|
<button type="button" id="checkInvoiceBtn" class="btn btn-secondary" style="display: none;">
|
||||||
<i class="fas fa-sync"></i> Refresh Invoice
|
<i class="fas fa-sync"></i> Refresh Invoice
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div> *@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Attributes Section (NO FORM TAG - just a div) -->
|
<!-- Attributes Section (NO FORM TAG - just a div) -->
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue