1369 lines
58 KiB
C#
1369 lines
58 KiB
C#
using AyCode.Core.Extensions;
|
|
using AyCode.Core.Loggers;
|
|
using AyCode.Services.Server.SignalRs;
|
|
using AyCode.Services.SignalRs;
|
|
using AyCode.Utils.Extensions;
|
|
using DocumentFormat.OpenXml.Spreadsheet;
|
|
using FluentMigrator.Runner.Generators.Base;
|
|
using FruitBank.Common.Dtos;
|
|
using FruitBank.Common.Entities;
|
|
using FruitBank.Common.Interfaces;
|
|
using FruitBank.Common.Server.Interfaces;
|
|
using FruitBank.Common.Server.Services.SignalRs;
|
|
using FruitBank.Common.SignalRs;
|
|
using Mango.Nop.Core.Extensions;
|
|
using Mango.Nop.Core.Loggers;
|
|
using MessagePack.Resolvers;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
using Newtonsoft.Json;
|
|
using Nop.Core;
|
|
using Nop.Core.Domain.Catalog;
|
|
using Nop.Core.Domain.Customers;
|
|
using Nop.Core.Domain.Orders;
|
|
using Nop.Core.Domain.Payments;
|
|
using Nop.Core.Domain.Shipping;
|
|
using Nop.Core.Domain.Stores;
|
|
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;
|
|
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
|
using Nop.Services.Catalog;
|
|
using Nop.Services.Common;
|
|
using Nop.Services.Customers;
|
|
using Nop.Services.ExportImport;
|
|
using Nop.Services.Helpers;
|
|
using Nop.Services.Localization;
|
|
using Nop.Services.Logging;
|
|
using Nop.Services.Messages;
|
|
using Nop.Services.Orders;
|
|
using Nop.Services.Payments;
|
|
using Nop.Services.Plugins;
|
|
using Nop.Services.Security;
|
|
using Nop.Services.Tax;
|
|
using Nop.Web.Areas.Admin.Controllers;
|
|
using Nop.Web.Areas.Admin.Factories;
|
|
using Nop.Web.Areas.Admin.Models.Orders;
|
|
using Nop.Web.Framework;
|
|
using Nop.Web.Framework.Controllers;
|
|
using Nop.Web.Framework.Mvc.Filters;
|
|
using System.Text;
|
|
using System.Text.Json.Serialization;
|
|
using System.Threading.Tasks;
|
|
using System.Xml;
|
|
using System.Xml.Serialization;
|
|
using static Nop.Services.Security.StandardPermission;
|
|
|
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|
{
|
|
[Area(AreaNames.ADMIN)]
|
|
[AuthorizeAdmin]
|
|
public class CustomOrderController : BaseAdminController, ICustomOrderSignalREndpointServer
|
|
{
|
|
private readonly FruitBankDbContext _dbContext;
|
|
private readonly SignalRSendToClientService _sendToClient;
|
|
|
|
private readonly IOrderService _orderService;
|
|
private readonly CustomOrderModelFactory _orderModelFactory;
|
|
private readonly ICustomOrderSignalREndpointServer _customOrderSignalREndpoint;
|
|
private readonly IPermissionService _permissionService;
|
|
private readonly IGenericAttributeService _genericAttributeService;
|
|
private readonly INotificationService _notificationService;
|
|
private readonly ICustomerService _customerService;
|
|
private readonly IProductService _productService;
|
|
private readonly IStoreContext _storeContext;
|
|
private readonly IWorkContext _workContext;
|
|
private readonly IPriceCalculationService _priceCalculationService;
|
|
protected readonly IEventPublisher _eventPublisher;
|
|
protected readonly ILocalizationService _localizationService;
|
|
protected readonly ICustomerActivityService _customerActivityService;
|
|
protected readonly IExportManager _exportManager;
|
|
protected readonly IGiftCardService _giftCardService;
|
|
protected readonly IImportManager _importManager;
|
|
protected readonly IDateTimeHelper _dateTimeHelper;
|
|
protected readonly ITaxService _taxService;
|
|
protected readonly MeasurementService _measurementService;
|
|
private static readonly char[] _separator = [','];
|
|
// ... other dependencies
|
|
|
|
private readonly Mango.Nop.Core.Loggers.ILogger _logger;
|
|
|
|
protected virtual async ValueTask<bool> HasAccessToOrderAsync(Order order)
|
|
{
|
|
return order != null && await HasAccessToOrderAsync(order.Id);
|
|
}
|
|
|
|
protected virtual async Task<bool> HasAccessToOrderAsync(int orderId)
|
|
{
|
|
if (orderId == 0)
|
|
return false;
|
|
|
|
var currentVendor = await _workContext.GetCurrentVendorAsync();
|
|
if (currentVendor == null)
|
|
//not a vendor; has access
|
|
return true;
|
|
|
|
var vendorId = currentVendor.Id;
|
|
var hasVendorProducts = (await _orderService.GetOrderItemsAsync(orderId, vendorId: vendorId)).Any();
|
|
|
|
return hasVendorProducts;
|
|
}
|
|
|
|
public CustomOrderController(FruitBankDbContext fruitBankDbContext, SignalRSendToClientService sendToClient,
|
|
IOrderService orderService,
|
|
IPriceCalculationService priceCalculationService,
|
|
IOrderModelFactory orderModelFactory,
|
|
ICustomOrderSignalREndpointServer customOrderSignalREndpoint,
|
|
IPermissionService permissionService,
|
|
IGenericAttributeService genericAttributeService,
|
|
INotificationService notificationService,
|
|
ICustomerService customerService,
|
|
IProductService productService,
|
|
IEnumerable<IAcLogWriterBase> logWriters,
|
|
IStoreContext storeContext,
|
|
IWorkContext workContext,
|
|
IEventPublisher eventPublisher,
|
|
ILocalizationService localizationService,
|
|
ICustomerActivityService customerActivityService,
|
|
IExportManager exportManager,
|
|
IGiftCardService giftCardService,
|
|
IImportManager importManager,
|
|
IDateTimeHelper dateTimeHelper,
|
|
ITaxService taxService,
|
|
MeasurementService measurementService)
|
|
{
|
|
_logger = new Logger<CustomOrderController>(logWriters.ToArray());
|
|
|
|
_dbContext = fruitBankDbContext;
|
|
_sendToClient = sendToClient;
|
|
|
|
_orderService = orderService;
|
|
_orderModelFactory = orderModelFactory as CustomOrderModelFactory;
|
|
_customOrderSignalREndpoint = customOrderSignalREndpoint;
|
|
_permissionService = permissionService;
|
|
_genericAttributeService = genericAttributeService;
|
|
_notificationService = notificationService;
|
|
_customerService = customerService;
|
|
_productService = productService;
|
|
_storeContext = storeContext;
|
|
_workContext = workContext;
|
|
_priceCalculationService = priceCalculationService;
|
|
_eventPublisher = eventPublisher;
|
|
_localizationService = localizationService;
|
|
_customerActivityService = customerActivityService;
|
|
|
|
_exportManager = exportManager;
|
|
_giftCardService = giftCardService;
|
|
_importManager = importManager;
|
|
_dateTimeHelper = dateTimeHelper;
|
|
_taxService = taxService;
|
|
_measurementService = measurementService;
|
|
// ... initialize other deps
|
|
}
|
|
|
|
#region CustomOrderSignalREndpoint
|
|
|
|
[NonAction]
|
|
public Task<List<OrderDto>> GetAllOrderDtos() => _customOrderSignalREndpoint.GetAllOrderDtos();
|
|
|
|
[NonAction]
|
|
public Task<OrderDto> GetOrderDtoById(int orderId) => _customOrderSignalREndpoint.GetOrderDtoById(orderId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderDto>> GetPendingOrderDtos() => _customOrderSignalREndpoint.GetPendingOrderDtos();
|
|
|
|
[NonAction]
|
|
public Task<List<OrderDto>> GetPendingOrderDtosForMeasuring(int lastDaysCount) => _customOrderSignalREndpoint.GetPendingOrderDtosForMeasuring(lastDaysCount);
|
|
|
|
[NonAction]
|
|
public Task<OrderDto> StartMeasuring(int orderId, int userId) => _customOrderSignalREndpoint.StartMeasuring(orderId, userId);
|
|
|
|
[NonAction]
|
|
public Task<OrderDto> SetOrderStatusToComplete(int orderId, int revisorId) => _customOrderSignalREndpoint.SetOrderStatusToComplete(orderId, revisorId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderDto>> GetAllOrderDtoByIds(int[] orderIds) => _customOrderSignalREndpoint.GetAllOrderDtoByIds(orderIds);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemDto>> GetAllOrderItemDtos() => _customOrderSignalREndpoint.GetAllOrderItemDtos();
|
|
|
|
[NonAction]
|
|
public Task<List<OrderDto>> GetAllOrderDtoByProductId(int productId) => _customOrderSignalREndpoint.GetAllOrderDtoByProductId(productId);
|
|
|
|
[NonAction]
|
|
public Task<OrderItemDto> GetOrderItemDtoById(int orderItemId) => _customOrderSignalREndpoint.GetOrderItemDtoById(orderItemId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemDto>> GetAllOrderItemDtoByOrderId(int orderId) => _customOrderSignalREndpoint.GetAllOrderItemDtoByOrderId(orderId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemDto>> GetAllOrderItemDtoByProductId(int productId) => _customOrderSignalREndpoint.GetAllOrderItemDtoByProductId(productId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemPallet>> GetAllOrderItemPallets() => _customOrderSignalREndpoint.GetAllOrderItemPallets();
|
|
|
|
[NonAction]
|
|
public Task<OrderItemPallet> GetOrderItemPalletById(int orderItemPalletId) => _customOrderSignalREndpoint.GetOrderItemPalletById(orderItemPalletId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemPallet>> GetAllOrderItemPalletByOrderItemId(int orderItemId) => _customOrderSignalREndpoint.GetAllOrderItemPalletByOrderItemId(orderItemId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemPallet>> GetAllOrderItemPalletByOrderId(int orderId) => _customOrderSignalREndpoint.GetAllOrderItemPalletByOrderId(orderId);
|
|
|
|
[NonAction]
|
|
public Task<List<OrderItemPallet>> GetAllOrderItemPalletByProductId(int productId) => _customOrderSignalREndpoint.GetAllOrderItemPalletByProductId(productId);
|
|
|
|
[NonAction]
|
|
public Task<OrderItemPallet> AddOrUpdateMeasuredOrderItemPallet(OrderItemPallet orderItemPallet) => _customOrderSignalREndpoint.AddOrUpdateMeasuredOrderItemPallet(orderItemPallet);
|
|
|
|
#endregion CustomOrderSignalREndpoint
|
|
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_VIEW)]
|
|
public virtual async Task<IActionResult> List(List<int> orderStatuses = null, List<int> paymentStatuses = null, List<int> shippingStatuses = null)
|
|
{
|
|
//prepare model
|
|
var model = await _orderModelFactory.PrepareOrderSearchModelAsync(new OrderSearchModelExtended
|
|
{
|
|
OrderStatusIds = orderStatuses,
|
|
PaymentStatusIds = paymentStatuses,
|
|
ShippingStatusIds = shippingStatuses,
|
|
Length = 50,
|
|
AvailablePageSizes = "20,50,100,500",
|
|
SortColumn = "Id",
|
|
SortColumnDirection = "desc",
|
|
});
|
|
|
|
model.SetGridSort("Id", "desc");
|
|
model.SetGridPageSize(50, "20,50,100,500");
|
|
|
|
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/List.cshtml", model);
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_VIEW)]
|
|
public async Task<IActionResult> OrderList(OrderSearchModelExtended searchModel)
|
|
{
|
|
//prepare model
|
|
//if (searchModel.SortColumn.IsNullOrWhiteSpace())
|
|
//{
|
|
// searchModel.SortColumn = "Id";
|
|
// searchModel.SortColumnDirection = "desc";
|
|
//}
|
|
|
|
var orderListModel = await GetOrderListModelByFilter(searchModel);
|
|
//var orderListModel = new OrderListModel();
|
|
|
|
var valami = Json(orderListModel);
|
|
Console.WriteLine(valami);
|
|
return valami;
|
|
}
|
|
|
|
[HttpPost, ActionName("List")]
|
|
[FormValueRequired("go-to-order-by-number")]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_VIEW)]
|
|
public virtual async Task<IActionResult> GoToOrderId(OrderSearchModel model)
|
|
{
|
|
var order = await _orderService.GetOrderByCustomOrderNumberAsync(model.GoDirectlyToCustomOrderNumber);
|
|
|
|
if (order == null)
|
|
return await List();
|
|
|
|
return RedirectToAction("Edit", new { id = order.Id });
|
|
}
|
|
|
|
[HttpGet]
|
|
//[Route("Edit/{id}")]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_VIEW)]
|
|
public virtual async Task<IActionResult> Edit(int id)
|
|
{
|
|
//try to get an order with the specified id
|
|
var order = await _orderService.GetOrderByIdAsync(id);
|
|
if (order == null || order.Deleted)
|
|
return RedirectToAction("List");
|
|
|
|
//a vendor does not have access to this functionality
|
|
if (await _workContext.GetCurrentVendorAsync() != null)
|
|
return RedirectToAction("List");
|
|
|
|
//prepare model
|
|
var model = await _orderModelFactory.PrepareOrderModelExtendedAsync(null, order);
|
|
|
|
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/Edit.cshtml", model);
|
|
}
|
|
|
|
//public async Task<OrderListModelExtended> GetOrderListModelByFilter(OrderSearchModelExtended searchModel)
|
|
//{
|
|
// //return _customOrderService.
|
|
// var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel);
|
|
|
|
// _logger.Detail($"Total: {orderListModel.RecordsTotal}, Data Count: {orderListModel.Data.Count()}");
|
|
// foreach (var item in orderListModel.Data.Take(3))
|
|
// {
|
|
// _logger.Detail($"Order: {item.Id}, {item.CustomOrderNumber}");
|
|
// }
|
|
|
|
// return orderListModel;
|
|
//}
|
|
|
|
public async Task<OrderListModelExtended> GetOrderListModelByFilter(OrderSearchModelExtended searchModel)
|
|
{
|
|
//if (searchModel.SortColumn.IsNullOrWhiteSpace())
|
|
{
|
|
var sortColumnIndex = Request.Form["order[0][column]"].FirstOrDefault();
|
|
var sortDirection = Request.Form["order[0][dir]"].FirstOrDefault();
|
|
|
|
if (!string.IsNullOrEmpty(sortColumnIndex))
|
|
{
|
|
// Get the column name from the column index
|
|
var columnName = Request.Form[$"columns[{sortColumnIndex}][data]"].FirstOrDefault();
|
|
|
|
searchModel.SortColumn = columnName;
|
|
|
|
if(int.Parse(sortColumnIndex) > 0) searchModel.SortColumnDirection = sortDirection; // "asc" or "desc"
|
|
else searchModel.SortColumnDirection = "desc";
|
|
}
|
|
//else
|
|
//{
|
|
// searchModel.SortColumn = "Id";
|
|
// searchModel.SortColumnDirection = "desc";
|
|
//}
|
|
}
|
|
|
|
|
|
// Get the paginated data
|
|
var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel);
|
|
|
|
_logger.Detail($"Total: {orderListModel.RecordsTotal}, Data Count: {orderListModel.Data.Count()}");
|
|
|
|
// Apply sorting if specified
|
|
if (!string.IsNullOrEmpty(searchModel.SortColumn) && orderListModel.Data.Any())
|
|
{
|
|
var sortedData = orderListModel.Data.AsQueryable();
|
|
|
|
sortedData = searchModel.SortColumn.ToLowerInvariant() switch
|
|
{
|
|
"id" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.Id)
|
|
: sortedData.OrderByDescending(o => o.Id),
|
|
"customercompany" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.CustomerCompany)
|
|
: sortedData.OrderByDescending(o => o.CustomerCompany),
|
|
"customordernumber" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.CustomOrderNumber)
|
|
: sortedData.OrderByDescending(o => o.CustomOrderNumber),
|
|
"ordertotal" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.OrderTotal)
|
|
: sortedData.OrderByDescending(o => o.OrderTotal),
|
|
"createdon" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.CreatedOn)
|
|
: sortedData.OrderByDescending(o => o.CreatedOn),
|
|
"orderstatusid" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.OrderStatusId)
|
|
: sortedData.OrderByDescending(o => o.OrderStatusId),
|
|
"paymentstatusid" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.PaymentStatusId)
|
|
: sortedData.OrderByDescending(o => o.PaymentStatusId),
|
|
"shippingstatusid" => searchModel.SortColumnDirection == "asc"
|
|
? sortedData.OrderBy(o => o.ShippingStatusId)
|
|
: sortedData.OrderByDescending(o => o.ShippingStatusId),
|
|
_ => sortedData
|
|
};
|
|
|
|
orderListModel.Data = sortedData.ToList();
|
|
orderListModel.RecordsTotal = orderListModel.Data.Count();
|
|
//orderListModel.Draw = searchModel.Draw;
|
|
|
|
Console.WriteLine($"Sorted Data Count: {orderListModel.Data.Count()}");
|
|
Console.WriteLine($"Total Records: {orderListModel.RecordsTotal}");
|
|
Console.WriteLine($"Filtered Records: {orderListModel.RecordsFiltered}");
|
|
Console.WriteLine($"Draw: {orderListModel.Draw}");
|
|
|
|
|
|
_logger.Detail($"Sorted by {searchModel.SortColumn} {searchModel.SortColumnDirection}");
|
|
}
|
|
|
|
foreach (var item in orderListModel.Data.Take(3))
|
|
{
|
|
_logger.Detail($"Order: {item.Id}, {item.CustomOrderNumber}");
|
|
}
|
|
|
|
return orderListModel;
|
|
}
|
|
|
|
|
|
public virtual IActionResult Test()
|
|
{
|
|
// Your custom logic here
|
|
// This will use your custom List.cshtml view
|
|
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/Test.cshtml");
|
|
}
|
|
|
|
//[HttpPost]
|
|
//[CheckPermission(Nop.Services.Security.StandardPermission.Orders.ORDERS_VIEW)]
|
|
//public virtual async Task<IActionResult> OrderList(OrderSearchModel searchModel)
|
|
//{
|
|
// //prepare model
|
|
// var model = await _orderModelFactory.PrepareOrderListModelAsync(searchModel);
|
|
|
|
// return Json(model);
|
|
//}
|
|
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> SaveOrderAttributes(OrderAttributesModel model)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
// reload order page with errors
|
|
return RedirectToAction("Edit", "Order", new { id = model.OrderId });
|
|
}
|
|
|
|
var order = await _orderService.GetOrderByIdAsync(model.OrderId);
|
|
if (order == null)
|
|
return RedirectToAction("List", "Order");
|
|
|
|
//TODO: A FruitBankAttributeService-t használjuk és akkor az OrderDto lehet lekérni és beadni a SaveAttribute-ba! - J.
|
|
|
|
// store attributes in GenericAttribute table
|
|
//await _genericAttributeService.SaveAttributeAsync(order, nameof(IMeasurable.IsMeasurable), model.IsMeasurable, _storeContext.GetCurrentStore().Id);
|
|
await _genericAttributeService.SaveAttributeAsync(order, nameof(IOrderDto.DateOfReceipt), model.DateOfReceipt, _storeContext.GetCurrentStore().Id);
|
|
|
|
var orderDto = await _dbContext.OrderDtos.GetByIdAsync(model.OrderId, true);
|
|
await _sendToClient.SendOrderChanged(orderDto);
|
|
|
|
_notificationService.SuccessNotification("Custom attributes saved successfully.");
|
|
return RedirectToAction("Edit", "Order", new { id = model.OrderId });
|
|
}
|
|
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> AllowRevision(OrderRevisionModel model)
|
|
{
|
|
if (!ModelState.IsValid)
|
|
{
|
|
// reload order page with errors
|
|
return RedirectToAction("Edit", "Order", new { id = model.OrderId });
|
|
}
|
|
|
|
var order = await _orderService.GetOrderByIdAsync(model.OrderId);
|
|
if (order == null)
|
|
return RedirectToAction("List", "Order");
|
|
|
|
|
|
//MeasurementService.OrderItemMeasuringReset
|
|
//Todo: ezt orderitiemnként kéne kirakni?? - Á.
|
|
var valami = await _measurementService.OrderItemMeasuringReset(model.OrderItemId);
|
|
|
|
return RedirectToAction("Edit", "Order", new { id = model.OrderId });
|
|
}
|
|
|
|
|
|
|
|
[HttpPost]
|
|
//[CheckPermission(StandardPermission.Orders.ORDERS_CREATE)]
|
|
public virtual async Task<IActionResult> Create(int customerId, string orderProductsJson)
|
|
{
|
|
if (!await _permissionService.AuthorizeAsync(StandardPermission.Orders.ORDERS_CREATE_EDIT_DELETE))
|
|
return AccessDeniedView();
|
|
|
|
// Validate customer
|
|
var customer = await _customerService.GetCustomerByIdAsync(customerId);
|
|
if (customer == null) return RedirectToAction("List");
|
|
|
|
var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);
|
|
if (billingAddress == null)
|
|
{
|
|
//let's see if he has any address at all
|
|
var addresses = await _customerService.GetAddressesByCustomerIdAsync(customer.Id);
|
|
if (addresses != null && addresses.Count > 0)
|
|
{
|
|
//set the first one as billing
|
|
billingAddress = addresses[0];
|
|
customer.BillingAddressId = billingAddress.Id;
|
|
await _customerService.UpdateCustomerAsync(customer);
|
|
}
|
|
else
|
|
{
|
|
//no address at all, cannot create order
|
|
_logger.Error($"Cannot create order for customer {customer.Id}, no billing address found.");
|
|
return RedirectToAction("List");
|
|
}
|
|
}
|
|
|
|
//var currency = await _workContext.GetWorkingCurrencyAsync();
|
|
//customer.CurrencyId = currency.Id;
|
|
|
|
// Parse products
|
|
var orderProducts = string.IsNullOrEmpty(orderProductsJson) ? [] : JsonConvert.DeserializeObject<List<OrderProductItem>>(orderProductsJson);
|
|
|
|
// Create order
|
|
var order = new Order
|
|
{
|
|
OrderGuid = Guid.NewGuid(),
|
|
CustomOrderNumber = "",
|
|
CustomerId = customerId,
|
|
CustomerLanguageId = customer.LanguageId ?? 1,
|
|
CustomerTaxDisplayType = TaxDisplayType.IncludingTax,
|
|
CustomerIp = string.Empty,
|
|
OrderStatus = OrderStatus.Pending,
|
|
PaymentStatus = PaymentStatus.Pending,
|
|
ShippingStatus = ShippingStatus.ShippingNotRequired,
|
|
CreatedOnUtc = DateTime.UtcNow,
|
|
BillingAddressId = customer.BillingAddressId ?? 0,
|
|
ShippingAddressId = customer.ShippingAddressId,
|
|
PaymentMethodSystemName = "Payments.CheckMoneyOrder", // Default payment method
|
|
CustomerCurrencyCode = "HUF", // TODO: GET Default currency - A.
|
|
|
|
OrderTotal = 0,
|
|
OrderSubtotalInclTax = 0,
|
|
OrderSubtotalExclTax = 0,
|
|
OrderSubTotalDiscountInclTax = 0,
|
|
OrderSubTotalDiscountExclTax = 0,
|
|
};
|
|
|
|
//var productDtosById = await _dbContext.ProductDtos.GetAllByIds(orderProducts.Select(op => op.Id)).ToDictionaryAsync(p => p.Id, prodDto => prodDto);
|
|
var store = await _storeContext.GetCurrentStoreAsync();
|
|
var admin = await _workContext.GetCurrentCustomerAsync();
|
|
|
|
var transactionSuccess = await _dbContext.TransactionSafeAsync(async _ =>
|
|
{
|
|
await _orderService.InsertOrderAsync(order);
|
|
order.CustomOrderNumber = order.Id.ToString();
|
|
|
|
await AddOrderItemsThenUpdateOrder(order, orderProducts, true, customer, store, admin);
|
|
return true;
|
|
});
|
|
|
|
if (transactionSuccess)
|
|
{
|
|
//var orderDto = await _dbContext.OrderDtos.GetByIdAsync(order.Id, true);
|
|
//await _sendToClient.SendMeasuringNotification("Módosult a rendelés, mérjétek újra!", orderDto);
|
|
|
|
return RedirectToAction("Edit", "Order", new { id = order.Id });
|
|
}
|
|
|
|
_logger.Error($"(transactionSuccess == false)");
|
|
return RedirectToAction("Error", new { id = order.Id });
|
|
}
|
|
|
|
private async Task AddOrderItemsThenUpdateOrder<TOrderProductItem>(Order order, IReadOnlyList<TOrderProductItem> orderProductItems, bool unitPricesIncludeDiscounts, Customer customer = null, Store store = null, Customer admin = null)
|
|
where TOrderProductItem : IOrderProductItemBase
|
|
{
|
|
store ??= await _storeContext.GetCurrentStoreAsync();
|
|
admin ??= await _workContext.GetCurrentCustomerAsync();
|
|
customer ??= await _workContext.GetCurrentCustomerAsync();
|
|
|
|
var helperProductDtosByOrderItemId = await _dbContext.ProductDtos.GetAllByIds(orderProductItems.Select(x => x.Id).ToArray()).ToDictionaryAsync(k => k.Id, v => v);
|
|
|
|
foreach (var orderProductItem in orderProductItems)
|
|
{
|
|
var product = await _productService.GetProductByIdAsync(orderProductItem.Id);
|
|
if (product == null)
|
|
{
|
|
_logger.Warning($"Product with ID {orderProductItem.Id} not found");
|
|
continue;
|
|
|
|
//var errorText = $"product == null; productId: {item.Id};";
|
|
|
|
//_logger.Error($"{errorText}");
|
|
//throw new Exception($"{errorText}");
|
|
}
|
|
|
|
//var stockQuantity = await _productService.GetTotalStockQuantityAsync(product);
|
|
var productDto = helperProductDtosByOrderItemId[orderProductItem.Id];
|
|
var isMeasurable = productDto.IsMeasurable;
|
|
|
|
if ((product.StockQuantity + productDto.IncomingQuantity) - orderProductItem.Quantity < 0)
|
|
{
|
|
//errorMessage = $"Nem elérhető készleten!";
|
|
var errorText = $"((product.StockQuantity + productDto.IncomingQuantity) - item.Quantity < 0); productId: {product.Id}; (product.StockQuantity + productDto.IncomingQuantity) - item.Quantity: {(product.StockQuantity + productDto.IncomingQuantity) - orderProductItem.Quantity}";
|
|
|
|
_logger.Error($"{errorText}");
|
|
throw new Exception($"{errorText}");
|
|
}
|
|
|
|
if(orderProductItem.Price != product.Price)
|
|
{
|
|
//manual price change
|
|
unitPricesIncludeDiscounts = false;
|
|
}
|
|
else
|
|
{
|
|
unitPricesIncludeDiscounts = true;
|
|
}
|
|
|
|
|
|
var orderItem = await CreateOrderItem(product, order, orderProductItem, isMeasurable, unitPricesIncludeDiscounts, customer, store);
|
|
|
|
await _orderService.InsertOrderItemAsync(orderItem);
|
|
await _productService.AdjustInventoryAsync(product, -orderItem.Quantity, orderItem.AttributesXml, string.Format(await _localizationService.GetResourceAsync("Admin.StockQuantityHistory.Messages.PlaceOrder"), order.Id));
|
|
|
|
var priceCalculation = await _priceCalculationService.GetFinalPriceAsync(product, customer, store, includeDiscounts: false);
|
|
var unitPriceInclTaxValue = priceCalculation.finalPrice;
|
|
|
|
var (unitPriceExclTaxValue, _) = await _taxService.GetProductPriceAsync(product, unitPriceInclTaxValue, false, customer);
|
|
|
|
order.OrderSubtotalInclTax += unitPriceInclTaxValue * orderItem.Quantity;
|
|
order.OrderSubtotalExclTax += unitPriceExclTaxValue * orderItem.Quantity;
|
|
|
|
order.OrderSubTotalDiscountInclTax += order.OrderSubtotalInclTax - orderItem.PriceInclTax;
|
|
order.OrderSubTotalDiscountExclTax += order.OrderSubtotalExclTax - orderItem.PriceExclTax;
|
|
|
|
//order.OrderTax
|
|
//order.TaxRates
|
|
|
|
order.OrderTotal += orderItem.PriceInclTax + order.OrderShippingInclTax + order.PaymentMethodAdditionalFeeInclTax;
|
|
}
|
|
|
|
await _orderService.UpdateOrderAsync(order);
|
|
|
|
await InsertOrderNoteAsync(order.Id, false, $"Products added {orderProductItems.Count} item to order by {admin.FirstName} {admin.LastName}, (CustomerId: {admin.Id})");
|
|
}
|
|
|
|
private async Task<OrderItem> CreateOrderItem<TOrderProductItem>(Product product, Order order, TOrderProductItem orderProductItem, bool isMeasurable, bool unitPricesIncludeDiscounts, Customer customer = null, Store store = null)
|
|
where TOrderProductItem : IOrderProductItemBase
|
|
{
|
|
if (product.Id != orderProductItem.Id)
|
|
throw new Exception($"CustomOrderController->CreateOrderItem; (product.Id != orderProductItem.Id)");
|
|
|
|
store ??= await _storeContext.GetCurrentStoreAsync();
|
|
customer ??= await _workContext.GetCurrentCustomerAsync();
|
|
|
|
decimal unitPriceInclTaxValue = 0;
|
|
|
|
if (unitPricesIncludeDiscounts)
|
|
{
|
|
var priceCalculation = await _priceCalculationService.GetFinalPriceAsync(product, customer, store, includeDiscounts: unitPricesIncludeDiscounts);
|
|
unitPriceInclTaxValue = priceCalculation.finalPrice;
|
|
}
|
|
else
|
|
{
|
|
unitPriceInclTaxValue = orderProductItem.Price;
|
|
}
|
|
|
|
|
|
// Calculate tax
|
|
//var (unitPriceInclTaxValue, _) = await _taxService.GetProductPriceAsync(product, unitPrice, true, customer);
|
|
var (unitPriceExclTaxValue, _) = await _taxService.GetProductPriceAsync(product, unitPriceInclTaxValue, false, customer);
|
|
|
|
return new OrderItem
|
|
{
|
|
OrderId = order.Id,
|
|
ProductId = orderProductItem.Id,
|
|
Quantity = orderProductItem.Quantity,
|
|
|
|
OrderItemGuid = Guid.NewGuid(),
|
|
|
|
UnitPriceInclTax = unitPriceInclTaxValue,
|
|
UnitPriceExclTax = unitPriceExclTaxValue,
|
|
|
|
PriceInclTax = isMeasurable ? 0 : unitPriceInclTaxValue * orderProductItem.Quantity,
|
|
PriceExclTax = isMeasurable ? 0 : unitPriceExclTaxValue * orderProductItem.Quantity,
|
|
|
|
OriginalProductCost = await _priceCalculationService.GetProductCostAsync(product, null),
|
|
|
|
AttributeDescription = string.Empty,
|
|
AttributesXml = string.Empty,
|
|
|
|
DiscountAmountInclTax = decimal.Zero,
|
|
DiscountAmountExclTax = decimal.Zero,
|
|
|
|
DownloadCount = 0,
|
|
IsDownloadActivated = false,
|
|
LicenseDownloadId = 0,
|
|
ItemWeight = product.Weight * orderProductItem.Quantity,
|
|
RentalStartDateUtc = null,
|
|
RentalEndDateUtc = null
|
|
};
|
|
}
|
|
|
|
public interface IOrderProductItemBase
|
|
{
|
|
/// <summary>
|
|
/// ProductId
|
|
/// </summary>
|
|
public int Id { get; set; }
|
|
public int Quantity { get; set; }
|
|
public decimal Price { get; set; }
|
|
}
|
|
|
|
public class OrderProductItem : IOrderProductItemBase
|
|
{
|
|
/// <summary>
|
|
/// ProductId
|
|
/// </summary>
|
|
public int Id { get; set; }
|
|
public string Name { get; set; }
|
|
public string Sku { get; set; }
|
|
public int Quantity { get; set; }
|
|
public decimal Price { get; set; }
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"{nameof(OrderProductItem)} [ProductId: {Id}; Name: {Name}; Sku: {Sku}; Quantity: {Quantity}; Price: {Price}]";
|
|
}
|
|
}
|
|
|
|
public class AddProductModel : OrderProductItem
|
|
{
|
|
///// <summary>
|
|
///// ProductId
|
|
///// </summary>
|
|
//public int Id { get; set; }
|
|
//public string Name { get; set; }
|
|
//public string Sku { get; set; }
|
|
//public int Quantity { get; set; }
|
|
//public decimal Price { get; set; }
|
|
public int StockQuantity { get; set; }
|
|
public int IncomingQuantity { get; set; }
|
|
}
|
|
|
|
//private static OrderItem CreateOrderItem(ProductToAuctionMapping productToAuction, Order order, decimal orderTotal)
|
|
//{
|
|
// return new OrderItem
|
|
// {
|
|
// ProductId = productToAuction.ProductId,
|
|
// OrderId = order.Id,
|
|
// OrderItemGuid = Guid.NewGuid(),
|
|
// PriceExclTax = orderTotal,
|
|
// PriceInclTax = orderTotal,
|
|
// UnitPriceExclTax = orderTotal,
|
|
// UnitPriceInclTax = orderTotal,
|
|
// Quantity = productToAuction.ProductAmount,
|
|
// };
|
|
//}
|
|
|
|
//private static Order CreateOrder(ProductToAuctionMapping productToAuction, decimal orderTotal, Customer customer, Address billingAddress, int storeId, Dictionary<string, object> customValues)
|
|
//{
|
|
// return new Order
|
|
// {
|
|
// BillingAddressId = billingAddress.Id,
|
|
// CreatedOnUtc = DateTime.UtcNow,
|
|
// CurrencyRate = 1,
|
|
// CustomOrderNumber = productToAuction.AuctionId + "/" + productToAuction.SortIndex,
|
|
// CustomValuesXml = SerializeCustomValuesToXml(customValues),
|
|
// CustomerCurrencyCode = "HUF",
|
|
// CustomerId = productToAuction.WinnerCustomerId,
|
|
// CustomerLanguageId = 2,
|
|
// CustomerTaxDisplayType = TaxDisplayType.IncludingTax,
|
|
// OrderGuid = Guid.NewGuid(),
|
|
// OrderStatus = OrderStatus.Pending,
|
|
// OrderTotal = orderTotal,
|
|
// PaymentStatus = PaymentStatus.Pending,
|
|
// PaymentMethodSystemName = "Payments.CheckMoneyOrder",
|
|
// ShippingStatus = ShippingStatus.ShippingNotRequired,
|
|
// StoreId = storeId,
|
|
// VatNumber = customer.VatNumber,
|
|
// CustomerIp = customer.LastIpAddress,
|
|
// OrderSubtotalExclTax = orderTotal,
|
|
// OrderSubtotalInclTax = orderTotal
|
|
// };
|
|
//}
|
|
|
|
private static OrderNote CreateOrderNote(int orderId, bool displayToCustomer, string note)
|
|
{
|
|
return new OrderNote
|
|
{
|
|
CreatedOnUtc = DateTime.UtcNow,//order.CreatedOnUtc,
|
|
DisplayToCustomer = displayToCustomer,
|
|
OrderId = orderId,
|
|
Note = note
|
|
};
|
|
}
|
|
|
|
public Task InsertOrderNoteAsync(int orderId, bool displayToCustomer, string note)
|
|
{
|
|
var orderNote = CreateOrderNote(orderId, displayToCustomer, note);
|
|
return _orderService.InsertOrderNoteAsync(orderNote);
|
|
}
|
|
|
|
private static string SerializeCustomValuesToXml(Dictionary<string, object> sourceDictionary)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(sourceDictionary);
|
|
|
|
if (!sourceDictionary.Any())
|
|
return null;
|
|
|
|
var ds = new DictionarySerializer(sourceDictionary);
|
|
var xs = new XmlSerializer(typeof(DictionarySerializer));
|
|
|
|
using var textWriter = new StringWriter();
|
|
using (var xmlWriter = XmlWriter.Create(textWriter))
|
|
{
|
|
xs.Serialize(xmlWriter, ds);
|
|
}
|
|
|
|
var result = textWriter.ToString();
|
|
return result;
|
|
}
|
|
|
|
|
|
[HttpGet] // Change from [HttpPost] to [HttpGet]
|
|
[CheckPermission(StandardPermission.Customers.CUSTOMERS_VIEW)]
|
|
public virtual async Task<IActionResult> CustomerSearchAutoComplete(string term)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(term) || term.Length < 2)
|
|
return Json(new List<object>());
|
|
|
|
const int maxResults = 15;
|
|
|
|
// Search by email (contains)
|
|
var customersByEmail = await _customerService.GetAllCustomersAsync(
|
|
email: term,
|
|
pageIndex: 0,
|
|
pageSize: maxResults);
|
|
|
|
// Search by first name (contains)
|
|
var customersByFirstName = await _customerService.GetAllCustomersAsync(
|
|
firstName: term,
|
|
pageIndex: 0,
|
|
pageSize: maxResults);
|
|
|
|
// Search by last name (contains)
|
|
var customersByLastName = await _customerService.GetAllCustomersAsync(
|
|
lastName: term,
|
|
pageIndex: 0,
|
|
pageSize: maxResults);
|
|
|
|
var customersByCompanyName = await _customerService.GetAllCustomersAsync(
|
|
company: term,
|
|
pageIndex: 0,
|
|
pageSize: maxResults);
|
|
|
|
// Combine and deduplicate results
|
|
var allCustomers = customersByEmail
|
|
.Union(customersByFirstName)
|
|
.Union(customersByLastName)
|
|
.Union(customersByCompanyName)
|
|
.DistinctBy(c => c.Id)
|
|
.Take(maxResults)
|
|
.ToList();
|
|
|
|
var result = new List<object>();
|
|
foreach (var customer in allCustomers)
|
|
{
|
|
var fullName = await _customerService.GetCustomerFullNameAsync(customer);
|
|
var company = customer.Company;
|
|
|
|
if (string.IsNullOrEmpty(fullName))
|
|
fullName = "[No name]";
|
|
if (string.IsNullOrEmpty(company))
|
|
company = "[No company]";
|
|
|
|
string fullText = $"{company} ({fullName}), {customer.Email}";
|
|
|
|
//var displayText = !string.IsNullOrEmpty(customer.Email)
|
|
// ? $"{customer.Email}, {customer.Company} ({fullName})"
|
|
// : fullName;
|
|
|
|
result.Add(new
|
|
{
|
|
label = fullText,
|
|
value = customer.Id
|
|
});
|
|
}
|
|
|
|
return Json(result);
|
|
}
|
|
|
|
[HttpGet]
|
|
[CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)]
|
|
public virtual async Task<IActionResult> ProductSearchAutoComplete(string term)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(term) || term.Length < 2)
|
|
return Json(new List<object>());
|
|
|
|
const int maxResults = 15;
|
|
|
|
// Search products by name or SKU
|
|
var products = await _productService.SearchProductsAsync(
|
|
keywords: term,
|
|
pageIndex: 0,
|
|
pageSize: maxResults);
|
|
|
|
var result = new List<object>();
|
|
var productDtosById = await _dbContext.ProductDtos.GetAllByIds(products.Select(p => p.Id)).ToDictionaryAsync(k => k.Id, v => v);
|
|
|
|
foreach (var product in products)
|
|
{
|
|
var productDto = productDtosById[product.Id];
|
|
|
|
result.Add(new
|
|
{
|
|
label = $"{product.Name} [RENDELHETŐ: {(product.StockQuantity + productDto.IncomingQuantity)}] [ÁR: {product.Price}]",
|
|
value = product.Id,
|
|
sku = product.Sku,
|
|
price = product.Price,
|
|
stockQuantity = product.StockQuantity,
|
|
incomingQuantity = productDto.IncomingQuantity,
|
|
});
|
|
}
|
|
|
|
return Json(result);
|
|
}
|
|
|
|
//[HttpPost]
|
|
//public async Task<IActionResult> CreateInvoice(int orderId)
|
|
//{
|
|
// try
|
|
// {
|
|
// var order = await _orderService.GetOrderByIdAsync(orderId);
|
|
// if (order == null)
|
|
// return Json(new { success = false, message = "Order not found" });
|
|
|
|
// var billingAddress = await _customerService.GetCustomerBillingAddressAsync(order.Customer);
|
|
// if (billingAddress == null)
|
|
// return Json(new { success = false, message = "Billing address not found" });
|
|
|
|
// var country = await _countryService.GetCountryByAddressAsync(billingAddress);
|
|
// var countryCode = country?.TwoLetterIsoCode ?? "HU";
|
|
|
|
// // Create invoice request
|
|
// var invoiceRequest = new InvoiceCreateRequest
|
|
// {
|
|
// VevoNev = $"{billingAddress.FirstName} {billingAddress.LastName}",
|
|
// VevoIrsz = billingAddress.ZipPostalCode ?? "",
|
|
// VevoTelep = billingAddress.City ?? "",
|
|
// VevoOrszag = countryCode,
|
|
// VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
|
|
// SzamlatombID = 1, // Configure this based on your setup
|
|
// SzamlaKelte = DateTime.Now,
|
|
// TeljesitesKelte = DateTime.Now,
|
|
// Hatarido = DateTime.Now.AddDays(15), // 15 days payment term
|
|
// Devizanem = order.CustomerCurrencyCode,
|
|
// FizetesiMod = order.PaymentMethodSystemName,
|
|
// Felretett = false,
|
|
// Proforma = false,
|
|
// Email = billingAddress.Email,
|
|
// Telefon = billingAddress.PhoneNumber
|
|
// };
|
|
|
|
// // Add order items
|
|
// var orderItems = await _orderService.GetOrderItemsAsync(order.Id);
|
|
// foreach (var item in orderItems)
|
|
// {
|
|
// var product = await _productService.GetProductByIdAsync(item.ProductId);
|
|
|
|
// invoiceRequest.AddItem(new InvoiceItem
|
|
// {
|
|
// TetelNev = product?.Name ?? "Product",
|
|
// AfaSzoveg = "27%", // Configure VAT rate as needed
|
|
// Brutto = true,
|
|
// EgysegAr = item.UnitPriceInclTax,
|
|
// Mennyiseg = item.Quantity,
|
|
// MennyisegEgyseg = "db",
|
|
// CikkSzam = product?.Sku
|
|
// });
|
|
// }
|
|
|
|
// // Create invoice via API
|
|
// var response = await _innVoiceApiService.CreateInvoiceAsync(invoiceRequest);
|
|
|
|
// if (response.IsSuccess)
|
|
// {
|
|
// // TODO: Save invoice details to your database for future reference
|
|
// // You might want to create a custom table to store:
|
|
// // - OrderId
|
|
// // - InnVoice TableId
|
|
// // - Invoice Number
|
|
// // - PDF URL
|
|
// // - Created Date
|
|
|
|
// return Json(new
|
|
// {
|
|
// success = true,
|
|
// message = "Invoice created successfully",
|
|
// data = new
|
|
// {
|
|
// tableId = response.TableId,
|
|
// invoiceNumber = response.Sorszam,
|
|
// sorszam = response.Sorszam,
|
|
// printUrl = response.PrintUrl
|
|
// }
|
|
// });
|
|
// }
|
|
// else
|
|
// {
|
|
// return Json(new
|
|
// {
|
|
// success = false,
|
|
// message = $"InnVoice API Error: {response.Message}"
|
|
// });
|
|
// }
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// return Json(new
|
|
// {
|
|
// success = false,
|
|
// message = $"Error: {ex.Message}"
|
|
// });
|
|
// }
|
|
//}
|
|
|
|
//[HttpGet]
|
|
//public async Task<IActionResult> GetInvoiceStatus(int orderId)
|
|
//{
|
|
// try
|
|
// {
|
|
// // TODO: Retrieve invoice details from your database
|
|
// // This is a placeholder - you need to implement actual storage/retrieval
|
|
|
|
// // Example: var invoiceData = await _yourInvoiceService.GetByOrderIdAsync(orderId);
|
|
// // if (invoiceData != null)
|
|
// // {
|
|
// // return Json(new
|
|
// // {
|
|
// // success = true,
|
|
// // data = new
|
|
// // {
|
|
// // tableId = invoiceData.TableId,
|
|
// // invoiceNumber = invoiceData.InvoiceNumber,
|
|
// // sorszam = invoiceData.InvoiceNumber,
|
|
// // printUrl = invoiceData.PrintUrl
|
|
// // }
|
|
// // });
|
|
// // }
|
|
|
|
// return Json(new
|
|
// {
|
|
// success = false,
|
|
// message = "No invoice found for this order"
|
|
// });
|
|
// }
|
|
// catch (Exception ex)
|
|
// {
|
|
// return Json(new
|
|
// {
|
|
// success = false,
|
|
// message = $"Error: {ex.Message}"
|
|
// });
|
|
// }
|
|
//}
|
|
|
|
|
|
//THE REST
|
|
|
|
#region Export / Import
|
|
|
|
[HttpPost, ActionName("ExportXml")]
|
|
[FormValueRequired("exportxml-all")]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
|
public virtual async Task<IActionResult> ExportXmlAll(OrderSearchModelExtended model)
|
|
{
|
|
var startDateValue = model.StartDate == null
|
|
? null
|
|
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync());
|
|
|
|
var endDateValue = model.EndDate == null
|
|
? null
|
|
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.EndDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()).AddDays(1);
|
|
|
|
//a vendor should have access only to his products
|
|
var currentVendor = await _workContext.GetCurrentVendorAsync();
|
|
if (currentVendor != null)
|
|
{
|
|
model.VendorId = currentVendor.Id;
|
|
}
|
|
|
|
var orderStatusIds = model.OrderStatusIds != null && !model.OrderStatusIds.Contains(0)
|
|
? model.OrderStatusIds.ToList()
|
|
: null;
|
|
var paymentStatusIds = model.PaymentStatusIds != null && !model.PaymentStatusIds.Contains(0)
|
|
? model.PaymentStatusIds.ToList()
|
|
: null;
|
|
var shippingStatusIds = model.ShippingStatusIds != null && !model.ShippingStatusIds.Contains(0)
|
|
? model.ShippingStatusIds.ToList()
|
|
: null;
|
|
|
|
var filterByProductId = 0;
|
|
var product = await _productService.GetProductByIdAsync(model.ProductId);
|
|
if (product != null && (currentVendor == null || product.VendorId == currentVendor.Id))
|
|
filterByProductId = model.ProductId;
|
|
|
|
//load orders
|
|
var orders = await _orderService.SearchOrdersAsync(storeId: model.StoreId,
|
|
vendorId: model.VendorId,
|
|
productId: filterByProductId,
|
|
warehouseId: model.WarehouseId,
|
|
paymentMethodSystemName: model.PaymentMethodSystemName,
|
|
createdFromUtc: startDateValue,
|
|
createdToUtc: endDateValue,
|
|
osIds: orderStatusIds,
|
|
psIds: paymentStatusIds,
|
|
ssIds: shippingStatusIds,
|
|
billingPhone: model.BillingPhone,
|
|
billingEmail: model.BillingEmail,
|
|
billingLastName: model.BillingLastName,
|
|
billingCountryId: model.BillingCountryId,
|
|
orderNotes: model.OrderNotes);
|
|
|
|
//ensure that we at least one order selected
|
|
if (!orders.Any())
|
|
{
|
|
_notificationService.ErrorNotification(await _localizationService.GetResourceAsync("Admin.Orders.NoOrders"));
|
|
return RedirectToAction("List");
|
|
}
|
|
|
|
try
|
|
{
|
|
var xml = await _exportManager.ExportOrdersToXmlAsync(orders);
|
|
return File(Encoding.UTF8.GetBytes(xml), MimeTypes.ApplicationXml, "orders.xml");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await _notificationService.ErrorNotificationAsync(exc);
|
|
return RedirectToAction("List");
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
|
public virtual async Task<IActionResult> ExportXmlSelected(string selectedIds)
|
|
{
|
|
var orders = new List<Order>();
|
|
if (selectedIds != null)
|
|
{
|
|
var ids = selectedIds
|
|
.Split(_separator, StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(x => Convert.ToInt32(x))
|
|
.ToArray();
|
|
orders.AddRange(await (await _orderService.GetOrdersByIdsAsync(ids))
|
|
.WhereAwait(HasAccessToOrderAsync).ToListAsync());
|
|
}
|
|
|
|
try
|
|
{
|
|
var xml = await _exportManager.ExportOrdersToXmlAsync(orders);
|
|
return File(Encoding.UTF8.GetBytes(xml), MimeTypes.ApplicationXml, "orders.xml");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await _notificationService.ErrorNotificationAsync(exc);
|
|
return RedirectToAction("List");
|
|
}
|
|
}
|
|
|
|
[HttpPost, ActionName("ExportExcel")]
|
|
[FormValueRequired("exportexcel-all")]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
|
public virtual async Task<IActionResult> ExportExcelAll(OrderSearchModelExtended model)
|
|
{
|
|
var startDateValue = model.StartDate == null
|
|
? null
|
|
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.StartDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync());
|
|
|
|
var endDateValue = model.EndDate == null
|
|
? null
|
|
: (DateTime?)_dateTimeHelper.ConvertToUtcTime(model.EndDate.Value, await _dateTimeHelper.GetCurrentTimeZoneAsync()).AddDays(1);
|
|
|
|
//a vendor should have access only to his products
|
|
var currentVendor = await _workContext.GetCurrentVendorAsync();
|
|
if (currentVendor != null)
|
|
{
|
|
model.VendorId = currentVendor.Id;
|
|
}
|
|
|
|
var orderStatusIds = model.OrderStatusIds != null && !model.OrderStatusIds.Contains(0)
|
|
? model.OrderStatusIds.ToList()
|
|
: null;
|
|
var paymentStatusIds = model.PaymentStatusIds != null && !model.PaymentStatusIds.Contains(0)
|
|
? model.PaymentStatusIds.ToList()
|
|
: null;
|
|
var shippingStatusIds = model.ShippingStatusIds != null && !model.ShippingStatusIds.Contains(0)
|
|
? model.ShippingStatusIds.ToList()
|
|
: null;
|
|
|
|
var filterByProductId = 0;
|
|
var product = await _productService.GetProductByIdAsync(model.ProductId);
|
|
if (product != null && (currentVendor == null || product.VendorId == currentVendor.Id))
|
|
filterByProductId = model.ProductId;
|
|
|
|
//load orders
|
|
var orders = await _orderService.SearchOrdersAsync(storeId: model.StoreId,
|
|
vendorId: model.VendorId,
|
|
productId: filterByProductId,
|
|
warehouseId: model.WarehouseId,
|
|
paymentMethodSystemName: model.PaymentMethodSystemName,
|
|
createdFromUtc: startDateValue,
|
|
createdToUtc: endDateValue,
|
|
osIds: orderStatusIds,
|
|
psIds: paymentStatusIds,
|
|
ssIds: shippingStatusIds,
|
|
billingPhone: model.BillingPhone,
|
|
billingEmail: model.BillingEmail,
|
|
billingLastName: model.BillingLastName,
|
|
billingCountryId: model.BillingCountryId,
|
|
orderNotes: model.OrderNotes);
|
|
|
|
//ensure that we at least one order selected
|
|
if (!orders.Any())
|
|
{
|
|
_notificationService.ErrorNotification(await _localizationService.GetResourceAsync("Admin.Orders.NoOrders"));
|
|
return RedirectToAction("List");
|
|
}
|
|
|
|
try
|
|
{
|
|
var bytes = await _exportManager.ExportOrdersToXlsxAsync(orders);
|
|
return File(bytes, MimeTypes.TextXlsx, "orders.xlsx");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await _notificationService.ErrorNotificationAsync(exc);
|
|
return RedirectToAction("List");
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
|
public virtual async Task<IActionResult> ExportExcelSelected(string selectedIds)
|
|
{
|
|
var orders = new List<Order>();
|
|
if (selectedIds != null)
|
|
{
|
|
var ids = selectedIds
|
|
.Split(_separator, StringSplitOptions.RemoveEmptyEntries)
|
|
.Select(x => Convert.ToInt32(x))
|
|
.ToArray();
|
|
orders.AddRange(await (await _orderService.GetOrdersByIdsAsync(ids)).WhereAwait(HasAccessToOrderAsync).ToListAsync());
|
|
}
|
|
|
|
try
|
|
{
|
|
var bytes = await _exportManager.ExportOrdersToXlsxAsync(orders);
|
|
return File(bytes, MimeTypes.TextXlsx, "orders.xlsx");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await _notificationService.ErrorNotificationAsync(exc);
|
|
return RedirectToAction("List");
|
|
}
|
|
}
|
|
|
|
[HttpPost]
|
|
[CheckPermission(StandardPermission.Orders.ORDERS_IMPORT_EXPORT)]
|
|
public virtual async Task<IActionResult> ImportFromXlsx(IFormFile importexcelfile)
|
|
{
|
|
//a vendor cannot import orders
|
|
if (await _workContext.GetCurrentVendorAsync() != null)
|
|
return AccessDeniedView();
|
|
|
|
try
|
|
{
|
|
if (importexcelfile != null && importexcelfile.Length > 0)
|
|
{
|
|
await _importManager.ImportOrdersFromXlsxAsync(importexcelfile.OpenReadStream());
|
|
}
|
|
else
|
|
{
|
|
_notificationService.ErrorNotification(await _localizationService.GetResourceAsync("Admin.Common.UploadFile"));
|
|
return RedirectToAction("List");
|
|
}
|
|
|
|
_notificationService.SuccessNotification(await _localizationService.GetResourceAsync("Admin.Orders.Imported"));
|
|
|
|
return RedirectToAction("List");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
await _notificationService.ErrorNotificationAsync(exc);
|
|
return RedirectToAction("List");
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
[HttpPost]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> SendOrderNotification(int orderId, string message)
|
|
{
|
|
try
|
|
{
|
|
if (string.IsNullOrWhiteSpace(message))
|
|
{
|
|
return Json(new { success = false, message = "Az üzenet nem lehet üres" });
|
|
}
|
|
|
|
var orderDto = await _dbContext.OrderDtos.GetByIdAsync(orderId, true);
|
|
|
|
await _sendToClient.SendMeasuringNotification(message, orderDto);
|
|
return Json(new { success = true, message = "Üzenet sikeresen elküldve" });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"Error sending notification for order {orderId}", ex);
|
|
|
|
return Json(new { success = false, message = $"Hiba történt: {ex.Message}" });
|
|
}
|
|
}
|
|
|
|
|
|
[HttpPost]
|
|
//[IgnoreAntiforgeryToken]
|
|
[ValidateAntiForgeryToken]
|
|
public async Task<IActionResult> FruitBankAddProductToOrder(int orderId, string productsJson)
|
|
{
|
|
try
|
|
{
|
|
_logger.Info($"AddProductToOrder - OrderId: {orderId}, ProductsJson: {productsJson}");
|
|
|
|
if (!await _permissionService.AuthorizeAsync(StandardPermission.Orders.ORDERS_CREATE_EDIT_DELETE))
|
|
return Json(new { success = false, message = "Access denied" });
|
|
|
|
if (string.IsNullOrEmpty(productsJson))
|
|
return Json(new { success = false, message = "No products data received" });
|
|
|
|
var order = await _orderService.GetOrderByIdAsync(orderId);
|
|
|
|
if (order == null || order.Deleted)
|
|
return Json(new { success = false, message = "Order not found" });
|
|
|
|
// Deserialize products
|
|
var products = productsJson.JsonTo<List<AddProductModel>>(); //JsonConvert.DeserializeObject<List<AddProductModel>>(productsJson);
|
|
|
|
if (products == null || products.Count == 0)
|
|
return Json(new { success = false, message = "No products to add" });
|
|
|
|
var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
|
|
var store = await _storeContext.GetCurrentStoreAsync();
|
|
var admin = await _workContext.GetCurrentCustomerAsync();
|
|
|
|
string errorMessage = "";
|
|
|
|
var transactionSuccess = await _dbContext.TransactionSafeAsync(async _ =>
|
|
{
|
|
await AddOrderItemsThenUpdateOrder(order, products, true, customer, store, admin);
|
|
return true;
|
|
});
|
|
|
|
if (transactionSuccess)
|
|
{
|
|
_logger.Info($"Successfully added {products.Count} products to order {orderId}");
|
|
|
|
//var orderDto = await _dbContext.OrderDtos.GetByIdAsync(order.Id, true);
|
|
//await _sendToClient.SendMeasuringNotification("Módosult a rendelés, mérjétek újra!", orderDto);
|
|
|
|
return Json(new { success = true, message = "Products added successfully" });
|
|
}
|
|
else
|
|
{
|
|
return Json(new { success = false, message = errorMessage });
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"Error adding products to order {orderId}, {ex.Message}");
|
|
return Json(new { success = false, message = $"Error: {ex.Message}" });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|