using AyCode.Core.Loggers; using AyCode.Services.SignalRs; using FruitBank.Common.Dtos; using FruitBank.Common.Entities; using FruitBank.Common.Interfaces; using FruitBank.Common.Server.Interfaces; using FruitBank.Common.SignalRs; using Mango.Nop.Core.Extensions; using Mango.Nop.Core.Loggers; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Nop.Core.Domain.Customers; using Nop.Core.Domain.Orders; using Nop.Core.Domain.Payments; using Nop.Core.Domain.Shipping; using Nop.Core.Domain.Tax; using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer; using Nop.Plugin.Misc.FruitBankPlugin.Factories; using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders; using Nop.Services.Catalog; using Nop.Services.Common; using Nop.Services.Customers; using Nop.Services.Messages; using Nop.Services.Orders; using Nop.Services.Payments; using Nop.Services.Security; 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.Mvc.Filters; using System.Text.Json.Serialization; using System.Xml; using System.Xml.Serialization; namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers { [Area(AreaNames.ADMIN)] [AuthorizeAdmin] public class CustomOrderController : BaseAdminController, ICustomOrderSignalREndpointServer { private readonly FruitBankDbContext _dbContext; 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; // ... other dependencies private readonly ILogger _logger; public CustomOrderController(FruitBankDbContext fruitBankDbContext, IOrderService orderService, IOrderModelFactory orderModelFactory, ICustomOrderSignalREndpointServer customOrderSignalREndpoint, IPermissionService permissionService, IGenericAttributeService genericAttributeService, INotificationService notificationService, ICustomerService customerService, IProductService productService, IEnumerable logWriters) { _logger = new Logger(logWriters.ToArray()); _dbContext = fruitBankDbContext; _orderService = orderService; _orderModelFactory = orderModelFactory as CustomOrderModelFactory; _customOrderSignalREndpoint = customOrderSignalREndpoint; _permissionService = permissionService; _genericAttributeService = genericAttributeService; _notificationService = notificationService; _customerService = customerService; _productService = productService; // ... initialize other deps } #region CustomOrderSignalREndpoint [NonAction] public Task> GetAllOrderDtos() => _customOrderSignalREndpoint.GetAllOrderDtos(); [NonAction]public Task GetOrderDtoById(int orderId) => _customOrderSignalREndpoint.GetOrderDtoById(orderId); [NonAction]public Task> GetPendingOrderDtos() => _customOrderSignalREndpoint.GetPendingOrderDtos(); [NonAction] public Task StartMeasuring(int orderId, int userId) => _customOrderSignalREndpoint.StartMeasuring(orderId, userId); [NonAction]public Task SetOrderStatusToComplete(int orderId, int revisorId) => _customOrderSignalREndpoint.SetOrderStatusToComplete(orderId, revisorId); [NonAction] public Task> GetAllOrderDtoByIds(int[] orderIds) => _customOrderSignalREndpoint.GetAllOrderDtoByIds(orderIds); [NonAction] public Task AddOrUpdateMeasuredOrderItemPallet(OrderItemPallet orderItemPallet) => _customOrderSignalREndpoint.AddOrUpdateMeasuredOrderItemPallet(orderItemPallet); #endregion CustomOrderSignalREndpoint [CheckPermission(StandardPermission.Orders.ORDERS_VIEW)] public virtual async Task List(List orderStatuses = null, List paymentStatuses = null, List shippingStatuses = null) { //prepare model var model = await _orderModelFactory.PrepareOrderSearchModelAsync(new OrderSearchModel { OrderStatusIds = orderStatuses, PaymentStatusIds = paymentStatuses, ShippingStatusIds = shippingStatuses, }); return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/List.cshtml", model); } [HttpPost] [CheckPermission(StandardPermission.Orders.ORDERS_VIEW)] public async Task OrderList(OrderSearchModel searchModel) { //prepare model var orderListModel = await GetOrderListModelByFilter(searchModel); //var orderListModel = new OrderListModel(); var valami = Json(orderListModel); Console.WriteLine(valami); return valami; } public async Task GetOrderListModelByFilter(OrderSearchModel searchModel) { //return _customOrderService. var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel); _logger.Debug($"Total: {orderListModel.RecordsTotal}, Data Count: {orderListModel.Data.Count()}"); foreach (var item in orderListModel.Data.Take(3)) { _logger.Debug($"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 OrderList(OrderSearchModel searchModel) //{ // //prepare model // var model = await _orderModelFactory.PrepareOrderListModelAsync(searchModel); // return Json(model); //} [HttpPost] [ValidateAntiForgeryToken] public async Task 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"); // store attributes in GenericAttribute table await _genericAttributeService.SaveAttributeAsync(order, nameof(IMeasurable.IsMeasurable), model.IsMeasurable); await _genericAttributeService.SaveAttributeAsync(order, nameof(IOrderDto.DateOfReceipt), model.DateOfReceipt); _notificationService.SuccessNotification("Custom attributes saved successfully."); return RedirectToAction("Edit", "Order", new { id = model.OrderId }); } [HttpPost] //[CheckPermission(StandardPermission.Orders.ORDERS_CREATE)] public virtual async Task 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"); // Parse products var orderProducts = string.IsNullOrEmpty(orderProductsJson) ? [] : JsonConvert.DeserializeObject>(orderProductsJson); // Create order var order = new Order { OrderGuid = Guid.NewGuid(), CustomOrderNumber = null, 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 }; var productDtosById = await _dbContext.ProductDtos.GetAllByIds(orderProducts.Select(op => op.Id)).ToDictionaryAsync(p => p.Id, prodDto => prodDto); var transactionSuccess = await _dbContext.TransactionSafeAsync(async _ => { await _orderService.InsertOrderAsync(order); foreach (var item in orderProducts) { //var product = await _productService.GetProductByIdAsync(item.Id); //if (product != null) if (productDtosById.TryGetValue(item.Id, out var product)) { var orderItem = new OrderItem { OrderId = order.Id, ProductId = item.Id, Quantity = item.Quantity, UnitPriceInclTax = item.Price, UnitPriceExclTax = item.Price, PriceInclTax = item.Price * item.Quantity, PriceExclTax = item.Price * item.Quantity, OriginalProductCost = product.ProductCost, AttributeDescription = string.Empty, AttributesXml = string.Empty, DiscountAmountInclTax = 0, DiscountAmountExclTax = 0 }; //var valami = product.GenericAttributes.GetValueOrNull(nameof(IOrderDto.DateOfReceipt)); TEST - A. await _orderService.InsertOrderItemAsync(orderItem); } else _logger.Error($"(productDtosById.TryGetValue(item.Id, out var product) == false); {item}"); } return true; }); if (transactionSuccess) return RedirectToAction("Edit", "Order", new { id = order.Id }); _logger.Error($"(transactionSuccess == false)"); return RedirectToAction("Error", new { id = order.Id }); } public class OrderProductItem { 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)} [Id: {Id}; Name: {Name}; Sku: {Sku}; Quantity: {Quantity}; Price: {Price}]"; } } //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 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(Order order, string note) { return new OrderNote { CreatedOnUtc = order.CreatedOnUtc, DisplayToCustomer = true, OrderId = order.Id, Note = note }; } private static string SerializeCustomValuesToXml(Dictionary 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 CustomerSearchAutoComplete(string term) { if (string.IsNullOrWhiteSpace(term) || term.Length < 2) return Json(new List()); 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); // Combine and deduplicate results var allCustomers = customersByEmail .Union(customersByFirstName) .Union(customersByLastName) .DistinctBy(c => c.Id) .Take(maxResults) .ToList(); var result = new List(); foreach (var customer in allCustomers) { var fullName = await _customerService.GetCustomerFullNameAsync(customer); var displayText = !string.IsNullOrEmpty(customer.Email) ? $"{customer.Email} ({fullName})" : fullName; result.Add(new { label = displayText, value = customer.Id }); } return Json(result); } [HttpGet] [CheckPermission(StandardPermission.Catalog.PRODUCTS_VIEW)] public virtual async Task ProductSearchAutoComplete(string term) { if (string.IsNullOrWhiteSpace(term) || term.Length < 2) return Json(new List()); 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(); foreach (var product in products) { result.Add(new { label = product.Name, value = product.Id, sku = product.Sku, price = product.Price }); } return Json(result); } //[HttpPost] //public async Task 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 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}" // }); // } //} } }