481 lines
20 KiB
C#
481 lines
20 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Nop.Core;
|
|
using Nop.Core.Domain.Orders;
|
|
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
|
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
|
using Nop.Services.Catalog;
|
|
using Nop.Services.Common;
|
|
using Nop.Services.Customers;
|
|
using Nop.Services.Directory;
|
|
using Nop.Services.Orders;
|
|
using Nop.Web.Framework;
|
|
using Nop.Web.Framework.Controllers;
|
|
using Nop.Web.Framework.Mvc.Filters;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|
{
|
|
[Area(AreaNames.ADMIN)]
|
|
[AuthorizeAdmin]
|
|
public class InnVoiceOrderController : BasePluginController
|
|
{
|
|
private readonly IOrderService _orderService;
|
|
private readonly IWorkContext _workContext;
|
|
private readonly IStoreContext _storeContext;
|
|
private readonly ICustomerService _customerService;
|
|
private readonly ICountryService _countryService;
|
|
private readonly IProductService _productService;
|
|
private readonly InnVoiceOrderService _innVoiceOrderService;
|
|
private readonly FruitBankAttributeService _fruitBankAttributeService;
|
|
private readonly IGenericAttributeService _genericAttributeService;
|
|
private readonly FruitBankDbContext _dbContext;
|
|
|
|
public InnVoiceOrderController(
|
|
IOrderService orderService,
|
|
IWorkContext workContext,
|
|
IStoreContext storeContext,
|
|
ICustomerService customerService,
|
|
ICountryService countryService,
|
|
IProductService productService,
|
|
InnVoiceOrderService innVoiceOrderService,
|
|
FruitBankAttributeService fruitBankAttributeService,
|
|
IGenericAttributeService genericAttributeService,
|
|
FruitBankDbContext dbContext)
|
|
{
|
|
_orderService = orderService;
|
|
_workContext = workContext;
|
|
_storeContext = storeContext;
|
|
_customerService = customerService;
|
|
_countryService = countryService;
|
|
_productService = productService;
|
|
_innVoiceOrderService = innVoiceOrderService;
|
|
_fruitBankAttributeService = fruitBankAttributeService;
|
|
_genericAttributeService = genericAttributeService;
|
|
_dbContext = dbContext;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create an order in InnVoice from a NopCommerce order
|
|
/// </summary>
|
|
[HttpPost]
|
|
[IgnoreAntiforgeryToken]
|
|
public async Task<IActionResult> CreateOrder(int orderId)
|
|
{
|
|
try
|
|
{
|
|
// Validate and get order
|
|
var order = await _orderService.GetOrderByIdAsync(orderId);
|
|
var orderDto = await _dbContext.OrderDtos.GetByIdAsync(orderId, true);
|
|
if (order == null)
|
|
{
|
|
return Json(new { success = false, message = "Order not found" });
|
|
}
|
|
if (orderDto == null)
|
|
{
|
|
return Json(new { success = false, message = "OrderDTO not found" });
|
|
}
|
|
|
|
if (orderDto.DateOfReceipt == null)
|
|
{
|
|
return Json(new { success = false, message = "Ki kell tölteni az átvétel idejét." });
|
|
}
|
|
|
|
// Validate and get customer
|
|
var customer = await _customerService.GetCustomerByIdAsync(orderDto.CustomerId);
|
|
if (customer == null)
|
|
{
|
|
return Json(new { success = false, message = "Customer not found" });
|
|
}
|
|
|
|
// Get and validate billing address
|
|
var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);
|
|
if (billingAddress == null)
|
|
{
|
|
return Json(new { success = false, message = "Billing address not found" });
|
|
}
|
|
|
|
var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
|
|
var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";
|
|
|
|
// Get shipping address (fallback to billing if not found)
|
|
var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer) ?? billingAddress;
|
|
var shippingCountry = await _countryService.GetCountryByAddressAsync(shippingAddress);
|
|
var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode;
|
|
|
|
string megjegyzes = string.Empty;
|
|
|
|
// Create order request
|
|
var orderRequest = new OrderCreateRequest
|
|
{
|
|
VevoNev = customer.Company ?? string.Empty,
|
|
VevoIrsz = billingAddress.ZipPostalCode ?? string.Empty,
|
|
VevoTelep = billingAddress.City ?? string.Empty,
|
|
VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
|
|
VevoOrszag = billingCountryCode,
|
|
VevoAdoszam = customer.VatNumber,
|
|
MegrendelestombID = 1,
|
|
MegrendelesKelte = ((DateTime)orderDto.DateOfReceipt).ToLocalTime(),
|
|
Hatarido = DateTime.Now.AddDays(7),
|
|
Devizanem = "Ft", // TODO: get real default - A.
|
|
//FizetesiMod = order.PaymentMethodSystemName ?? "átutalás",
|
|
FizetesiMod = "átutalás",
|
|
//Email = customer.Email ?? string.Empty,
|
|
Email = billingAddress.Email ?? customer.Email ?? string.Empty,
|
|
Telefon = billingAddress.PhoneNumber ?? string.Empty,
|
|
MegrendelesSzamStr = orderDto.Id.ToString(),
|
|
Megjegyzes = $""
|
|
};
|
|
|
|
// Add shipping address details
|
|
orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}".Trim();
|
|
orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? string.Empty;
|
|
orderRequest.SzallTelep = shippingAddress.City ?? string.Empty;
|
|
orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim();
|
|
orderRequest.SzallOrszag = shippingCountryCode;
|
|
|
|
// Get and validate order items
|
|
var orderItems = await _dbContext.OrderItemDtos.GetAllByOrderId(order.Id, true).ToListAsync();
|
|
|
|
if (orderItems == null || orderItems.Count == 0)
|
|
{
|
|
return Json(new { success = false, message = "Order has no items" });
|
|
}
|
|
|
|
// Add order items
|
|
foreach (var item in orderItems)
|
|
{
|
|
var product = _dbContext.ProductDtos.GetById(item.ProductId);
|
|
var productName = product?.Name ?? "Product";
|
|
|
|
if (item.IsMeasurable)
|
|
{
|
|
// For measurable products, quantity is weight stored in NetWeight
|
|
orderRequest.AddItem(new InnVoiceOrderItem
|
|
{
|
|
TetelNev = productName,
|
|
AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically
|
|
Brutto = true,
|
|
EgysegAr = item.UnitPriceInclTax,
|
|
Mennyiseg = item.NetWeight > 0 ? Convert.ToDecimal(item.NetWeight) : 0,
|
|
MennyisegEgyseg = "kg",
|
|
CikkSzam = string.Empty
|
|
});
|
|
}
|
|
else
|
|
{
|
|
orderRequest.AddItem(new InnVoiceOrderItem
|
|
{
|
|
TetelNev = productName,
|
|
AfaSzoveg = "27%", // TODO: Configure VAT rate dynamically
|
|
Brutto = true,
|
|
EgysegAr = item.UnitPriceInclTax,
|
|
Mennyiseg = item.Quantity,
|
|
MennyisegEgyseg = "kt",
|
|
CikkSzam = string.Empty
|
|
});
|
|
}
|
|
|
|
if(item.UnitPriceInclTax != product.Price)
|
|
{
|
|
megjegyzes += $"{productName} egységár módosítva: {Math.Round(product.Price, 2)} Ft -> {Math.Round(item.UnitPriceInclTax, 2)} Ft; \n";
|
|
megjegyzes += $"Kedvezmény: { ((1 - (item.UnitPriceInclTax / product.Price)) * 100).ToString() }%; \n";
|
|
}
|
|
}
|
|
|
|
orderRequest.Megjegyzes = megjegyzes;
|
|
|
|
// Create order via API
|
|
var response = await _innVoiceOrderService.CreateOrderAsync(orderRequest);
|
|
|
|
if (response == null)
|
|
{
|
|
return Json(new { success = false, message = "No response from InnVoice API" });
|
|
}
|
|
|
|
if (response.IsSuccess)
|
|
{
|
|
var currentStore = await _storeContext.GetCurrentStoreAsync();
|
|
var storeId = currentStore?.Id ?? 0;
|
|
|
|
// Save InnVoice order details as attributes
|
|
//await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Order, string>(
|
|
// order.Id,
|
|
// "InnVoiceOrderTechId",
|
|
// response.TechId,
|
|
// storeId
|
|
//);
|
|
await _genericAttributeService.SaveAttributeAsync(
|
|
order,
|
|
"InnVoiceOrderTechId",
|
|
response.TechId,
|
|
storeId
|
|
);
|
|
|
|
await _genericAttributeService.SaveAttributeAsync(
|
|
order,
|
|
"InnVoiceOrderTableId",
|
|
response.TableId?.ToString() ?? string.Empty,
|
|
storeId
|
|
);
|
|
|
|
await _genericAttributeService.SaveAttributeAsync(
|
|
order,
|
|
"InnVoiceOrderPrintLink",
|
|
response.PrintUrl?.ToString() ?? string.Empty,
|
|
storeId
|
|
);
|
|
|
|
return Json(new
|
|
{
|
|
success = true,
|
|
message = "Order created successfully in InnVoice",
|
|
data = new
|
|
{
|
|
tableId = response.TableId,
|
|
techId = response.TechId,
|
|
printUrl = response.PrintUrl
|
|
}
|
|
});
|
|
}
|
|
|
|
return Json(new
|
|
{
|
|
success = false,
|
|
message = $"InnVoice API Error: {response.Message ?? "Unknown error"}"
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// Log the exception here
|
|
// _logger.LogError(ex, "Error creating order {OrderId} in InnVoice", orderId);
|
|
|
|
return Json(new
|
|
{
|
|
success = false,
|
|
message = $"Error: {ex.Message}"
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get InnVoice order status for a NopCommerce order
|
|
/// </summary>
|
|
/// <summary>
|
|
/// Get InnVoice order status for a NopCommerce order
|
|
/// </summary>
|
|
[HttpGet]
|
|
public async Task<IActionResult> GetOrderStatus(int orderId)
|
|
{
|
|
try
|
|
{
|
|
var order = await _orderService.GetOrderByIdAsync(orderId);
|
|
if (order == null)
|
|
return Json(new { success = false, message = "Order not found" });
|
|
|
|
var storeId = (await _storeContext.GetCurrentStoreAsync()).Id;
|
|
|
|
// Get saved InnVoice order TechId
|
|
var techId = await _genericAttributeService.GetAttributeAsync<string>(
|
|
order,
|
|
"InnVoiceOrderTechId",
|
|
storeId
|
|
);
|
|
|
|
var printLink = await _genericAttributeService.GetAttributeAsync<string>(
|
|
order,
|
|
"InnVoiceOrderPrintLink",
|
|
storeId
|
|
);
|
|
|
|
if (string.IsNullOrEmpty(techId))
|
|
{
|
|
return Json(new
|
|
{
|
|
success = false,
|
|
message = "No InnVoice order found for this order"
|
|
});
|
|
}
|
|
|
|
// Fetch the order details from InnVoice API using TechId
|
|
var innVoiceOrders = await _innVoiceOrderService.GetOrderByTechIdAsync(techId);
|
|
|
|
if (innVoiceOrders == null || innVoiceOrders.Count == 0)
|
|
{
|
|
return Json(new
|
|
{
|
|
success = false,
|
|
message = "Order not found in InnVoice"
|
|
});
|
|
}
|
|
|
|
var innVoiceOrder = innVoiceOrders.FirstOrDefault();
|
|
|
|
return Json(new
|
|
{
|
|
success = true,
|
|
data = new
|
|
{
|
|
tableId = innVoiceOrder.TableId,
|
|
techId = innVoiceOrder.TechId,
|
|
printUrl = printLink,
|
|
customerName = innVoiceOrder.CustomerName,
|
|
totalGross = innVoiceOrder.TotalGross,
|
|
currency = innVoiceOrder.Currency,
|
|
orderDate = innVoiceOrder.OrderDate
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Json(new
|
|
{
|
|
success = false,
|
|
message = $"Error: {ex.Message}"
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create multiple orders in InnVoice from multiple NopCommerce orders
|
|
/// </summary>
|
|
[HttpPost]
|
|
[IgnoreAntiforgeryToken]
|
|
public async Task<IActionResult> CreateMultipleOrders([FromBody] int[] orderIds)
|
|
{
|
|
try
|
|
{
|
|
if (orderIds == null || orderIds.Length == 0)
|
|
return Json(new { success = false, message = "No order IDs provided" });
|
|
|
|
var orderRequests = new List<OrderCreateRequest>();
|
|
|
|
foreach (var orderId in orderIds)
|
|
{
|
|
var order = await _orderService.GetOrderByIdAsync(orderId);
|
|
if (order == null)
|
|
continue;
|
|
|
|
var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
|
|
var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);
|
|
|
|
if (billingAddress == null)
|
|
continue;
|
|
|
|
var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
|
|
var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";
|
|
|
|
var orderRequest = new OrderCreateRequest
|
|
{
|
|
VevoNev = $"{billingAddress.FirstName} {billingAddress.LastName}",
|
|
VevoIrsz = billingAddress.ZipPostalCode ?? "",
|
|
VevoTelep = billingAddress.City ?? "",
|
|
VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
|
|
VevoOrszag = billingCountryCode,
|
|
MegrendelestombID = 1,
|
|
MegrendelesKelte = order.CreatedOnUtc.ToLocalTime(),
|
|
Hatarido = DateTime.Now.AddDays(7),
|
|
Devizanem = "Ft",
|
|
FizetesiMod = order.PaymentMethodSystemName,
|
|
Email = billingAddress.Email,
|
|
Telefon = billingAddress.PhoneNumber,
|
|
MegrendelesSzamStr = order.Id.ToString(),
|
|
Megjegyzes = $""
|
|
};
|
|
|
|
// Add order items
|
|
var orderItems = await _orderService.GetOrderItemsAsync(order.Id);
|
|
foreach (var item in orderItems)
|
|
{
|
|
var product = await _productService.GetProductByIdAsync(item.ProductId);
|
|
|
|
orderRequest.AddItem(new InnVoiceOrderItem
|
|
{
|
|
TetelNev = product?.Name ?? "Product",
|
|
AfaSzoveg = "27%",
|
|
Brutto = true,
|
|
EgysegAr = item.UnitPriceInclTax,
|
|
Mennyiseg = item.Quantity,
|
|
MennyisegEgyseg = "db",
|
|
CikkSzam = product?.Sku
|
|
});
|
|
}
|
|
|
|
orderRequests.Add(orderRequest);
|
|
}
|
|
|
|
if (orderRequests.Count == 0)
|
|
return Json(new { success = false, message = "No valid orders to create" });
|
|
|
|
// Create orders via API
|
|
var responses = await _innVoiceOrderService.CreateOrdersAsync(orderRequests);
|
|
|
|
if (responses != null)
|
|
{
|
|
var successCount = responses.Count(r => r.IsSuccess);
|
|
var failureCount = responses.Count - successCount;
|
|
|
|
// Save TechIds for successful orders
|
|
var storeId = (await _storeContext.GetCurrentStoreAsync()).Id;
|
|
for (int i = 0; i < responses.Count && i < orderIds.Length; i++)
|
|
{
|
|
if (responses[i].IsSuccess)
|
|
{
|
|
var order = await _orderService.GetOrderByIdAsync(orderIds[i]);
|
|
if (order != null)
|
|
{
|
|
await _genericAttributeService.SaveAttributeAsync(
|
|
order,
|
|
"InnVoiceOrderTechId",
|
|
responses[i].TechId,
|
|
storeId
|
|
);
|
|
|
|
await _genericAttributeService.SaveAttributeAsync(
|
|
order,
|
|
"InnVoiceOrderTableId",
|
|
responses[i].TableId?.ToString(),
|
|
storeId
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return Json(new
|
|
{
|
|
success = successCount > 0,
|
|
message = $"Created {successCount} orders successfully. {failureCount} failed.",
|
|
data = new
|
|
{
|
|
successCount,
|
|
failureCount,
|
|
responses = responses.Select(r => new
|
|
{
|
|
success = r.IsSuccess,
|
|
tableId = r.TableId,
|
|
techId = r.TechId,
|
|
message = r.Message,
|
|
printUrl = r.PrintUrl
|
|
})
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
throw new Exception($"InvoiceOrderAPi invalid response");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Json(new
|
|
{
|
|
success = false,
|
|
message = $"Error: {ex.Message}"
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|