innvoice
This commit is contained in:
parent
89aa10e07b
commit
f5b27f8c18
|
|
@ -5,6 +5,7 @@ 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;
|
||||
|
|
@ -176,7 +177,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
var order = new Order
|
||||
{
|
||||
OrderGuid = Guid.NewGuid(),
|
||||
CustomOrderNumber = "",
|
||||
CustomOrderNumber = null,
|
||||
CustomerId = customerId,
|
||||
CustomerLanguageId = customer.LanguageId ?? 1,
|
||||
CustomerTaxDisplayType = TaxDisplayType.IncludingTax,
|
||||
|
|
@ -217,7 +218,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
DiscountAmountInclTax = 0,
|
||||
DiscountAmountExclTax = 0
|
||||
};
|
||||
|
||||
//var valami = product.GenericAttributes.GetValueOrNull<bool>(nameof(IOrderDto.DateOfReceipt)); TEST - A.
|
||||
await _orderService.InsertOrderItemAsync(orderItem);
|
||||
}
|
||||
else _logger.Error($"(productDtosById.TryGetValue(item.Id, out var product) == false); {item}");
|
||||
|
|
@ -226,7 +227,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
return true;
|
||||
});
|
||||
|
||||
if (transactionSuccess) return RedirectToAction("Edit", new { id = order.Id });
|
||||
if (transactionSuccess) return RedirectToAction("Edit", "Order", new { id = order.Id });
|
||||
|
||||
_logger.Error($"(transactionSuccess == false)");
|
||||
return RedirectToAction("Error", new { id = order.Id });
|
||||
|
|
|
|||
|
|
@ -0,0 +1,397 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nop.Core;
|
||||
using Nop.Core.Domain.Orders;
|
||||
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 IGenericAttributeService _genericAttributeService;
|
||||
|
||||
public InnVoiceOrderController(
|
||||
IOrderService orderService,
|
||||
IWorkContext workContext,
|
||||
IStoreContext storeContext,
|
||||
ICustomerService customerService,
|
||||
ICountryService countryService,
|
||||
IProductService productService,
|
||||
InnVoiceOrderService innVoiceOrderService,
|
||||
IGenericAttributeService genericAttributeService)
|
||||
{
|
||||
_orderService = orderService;
|
||||
_workContext = workContext;
|
||||
_storeContext = storeContext;
|
||||
_customerService = customerService;
|
||||
_countryService = countryService;
|
||||
_productService = productService;
|
||||
_innVoiceOrderService = innVoiceOrderService;
|
||||
_genericAttributeService = genericAttributeService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an order in InnVoice from a NopCommerce order
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public async Task<IActionResult> CreateOrder(int orderId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var order = await _orderService.GetOrderByIdAsync(orderId);
|
||||
if (order == null)
|
||||
return Json(new { success = false, message = "Order not found" });
|
||||
|
||||
var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
|
||||
|
||||
// Get billing address
|
||||
var billingAddress = await _customerService.GetCustomerBillingAddressAsync(customer);
|
||||
if (billingAddress == null)
|
||||
return Json(new { success = false, message = "Billing address not found" });
|
||||
|
||||
var billingCountry = await _countryService.GetCountryByAddressAsync(billingAddress);
|
||||
var billingCountryCode = billingCountry?.TwoLetterIsoCode ?? "HU";
|
||||
|
||||
// Get shipping address
|
||||
var shippingAddress = await _customerService.GetCustomerShippingAddressAsync(customer);
|
||||
var shippingCountry = shippingAddress != null
|
||||
? await _countryService.GetCountryByAddressAsync(shippingAddress)
|
||||
: null;
|
||||
var shippingCountryCode = shippingCountry?.TwoLetterIsoCode ?? billingCountryCode;
|
||||
|
||||
// Create order request
|
||||
var orderRequest = new OrderCreateRequest
|
||||
{
|
||||
VevoNev = $"{billingAddress.FirstName} {billingAddress.LastName}",
|
||||
VevoIrsz = billingAddress.ZipPostalCode ?? "",
|
||||
VevoTelep = billingAddress.City ?? "",
|
||||
VevoUtcaHsz = $"{billingAddress.Address1} {billingAddress.Address2}".Trim(),
|
||||
VevoOrszag = billingCountryCode,
|
||||
VevoAdoszam = billingAddress.Company, // Or a custom field for tax number
|
||||
MegrendelestombID = 1, // Configure this based on your setup
|
||||
MegrendelesKelte = order.CreatedOnUtc.ToLocalTime(),
|
||||
Hatarido = DateTime.Now.AddDays(7), // 7 days delivery time
|
||||
Devizanem = order.CustomerCurrencyCode,
|
||||
FizetesiMod = order.PaymentMethodSystemName,
|
||||
Email = billingAddress.Email,
|
||||
Telefon = billingAddress.PhoneNumber,
|
||||
MegrendelesSzamStr = order.Id.ToString()
|
||||
};
|
||||
|
||||
// Add shipping address if different
|
||||
if (shippingAddress != null)
|
||||
{
|
||||
orderRequest.SzallNev = $"{shippingAddress.FirstName} {shippingAddress.LastName}";
|
||||
orderRequest.SzallIrsz = shippingAddress.ZipPostalCode ?? "";
|
||||
orderRequest.SzallTelep = shippingAddress.City ?? "";
|
||||
orderRequest.SzallUtcaHsz = $"{shippingAddress.Address1} {shippingAddress.Address2}".Trim();
|
||||
orderRequest.SzallOrszag = shippingCountryCode;
|
||||
}
|
||||
|
||||
// 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%", // Configure VAT rate as needed
|
||||
Brutto = true,
|
||||
EgysegAr = item.UnitPriceInclTax,
|
||||
Mennyiseg = item.Quantity,
|
||||
MennyisegEgyseg = "db",
|
||||
CikkSzam = product?.Sku
|
||||
});
|
||||
}
|
||||
|
||||
// Create order via API
|
||||
var response = await _innVoiceOrderService.CreateOrderAsync(orderRequest);
|
||||
|
||||
if (response.IsSuccess)
|
||||
{
|
||||
// Save the TechId, TableId, and PrintUrl to the order for future reference
|
||||
await _genericAttributeService.SaveAttributeAsync(
|
||||
order,
|
||||
"InnVoiceOrderTechId",
|
||||
response.TechId,
|
||||
(await _storeContext.GetCurrentStoreAsync()).Id
|
||||
);
|
||||
|
||||
await _genericAttributeService.SaveAttributeAsync(
|
||||
order,
|
||||
"InnVoiceOrderTableId",
|
||||
response.TableId?.ToString(),
|
||||
(await _storeContext.GetCurrentStoreAsync()).Id
|
||||
);
|
||||
|
||||
await _genericAttributeService.SaveAttributeAsync(
|
||||
order,
|
||||
"InnVoiceOrderPrintLink",
|
||||
response.PrintUrl?.ToString(),
|
||||
(await _storeContext.GetCurrentStoreAsync()).Id
|
||||
);
|
||||
|
||||
return Json(new
|
||||
{
|
||||
success = true,
|
||||
message = "Order created successfully in InnVoice",
|
||||
data = new
|
||||
{
|
||||
tableId = response.TableId,
|
||||
techId = response.TechId,
|
||||
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}"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 = order.CustomerCurrencyCode,
|
||||
FizetesiMod = order.PaymentMethodSystemName,
|
||||
Email = billingAddress.Email,
|
||||
Telefon = billingAddress.PhoneNumber,
|
||||
MegrendelesSzamStr = order.Id.ToString()
|
||||
};
|
||||
|
||||
// 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);
|
||||
|
||||
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
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Json(new
|
||||
{
|
||||
success = false,
|
||||
message = $"Error: {ex.Message}"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,219 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nop.Web.Areas.Admin.Controllers;
|
||||
using Nop.Web.Framework.Mvc.Filters;
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nop.Core;
|
||||
using Nop.Core.Domain.Orders;
|
||||
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.Services.Security;
|
||||
using Nop.Web.Framework.Controllers;
|
||||
using Nop.Web.Framework.Mvc.Filters;
|
||||
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
||||
{
|
||||
[Area(AreaNames.ADMIN)]
|
||||
[AuthorizeAdmin]
|
||||
public class InvoiceController : BaseAdminController
|
||||
[AuthorizeAdmin]
|
||||
//[AutoValidateAntiforgeryToken]
|
||||
public class InvoiceController : BasePluginController
|
||||
{
|
||||
private readonly IPermissionService _permissionService;
|
||||
private readonly IOrderService _orderService;
|
||||
private readonly IWorkContext _workContext;
|
||||
private readonly IStoreContext _storeContext;
|
||||
private readonly ICustomerService _customerService;
|
||||
private readonly ICountryService _countryService;
|
||||
private readonly IStateProvinceService _stateProvinceService;
|
||||
// Add your InnVoice API service
|
||||
private readonly InnVoiceApiService _innVoiceApiService;
|
||||
private readonly IProductService _productService;
|
||||
private readonly FruitBankAttributeService _fruitBankAttributeService;
|
||||
|
||||
public InvoiceController(IPermissionService permissionService)
|
||||
public InvoiceController(
|
||||
IOrderService orderService,
|
||||
IWorkContext workContext,
|
||||
IStoreContext storeContext,
|
||||
ICustomerService customerService,
|
||||
ICountryService countryService,
|
||||
IStateProvinceService stateProvinceService,
|
||||
InnVoiceApiService innVoiceApiService,
|
||||
IProductService productService,
|
||||
FruitBankAttributeService fruitBankAttributeService)
|
||||
{
|
||||
_permissionService = permissionService;
|
||||
_orderService = orderService;
|
||||
_workContext = workContext;
|
||||
_storeContext = storeContext;
|
||||
_customerService = customerService;
|
||||
_countryService = countryService;
|
||||
_stateProvinceService = stateProvinceService;
|
||||
_innVoiceApiService = innVoiceApiService;
|
||||
_productService = productService;
|
||||
_fruitBankAttributeService = fruitBankAttributeService;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> List()
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> CreateInvoice(int orderId)
|
||||
{
|
||||
if (!await _permissionService.AuthorizeAsync(StandardPermission.Security.ACCESS_ADMIN_PANEL))
|
||||
return AccessDeniedView();
|
||||
try
|
||||
{
|
||||
var order = await _orderService.GetOrderByIdAsync(orderId);
|
||||
if (order == null)
|
||||
return Json(new { success = false, message = "Order not found" });
|
||||
|
||||
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Invoice/List.cshtml");
|
||||
var customer = await _customerService.GetCustomerByIdAsync(order.CustomerId);
|
||||
|
||||
var billingAddress = await _customerService.GetCustomerBillingAddressAsync(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 = true,
|
||||
Email = billingAddress.Email,
|
||||
MegrendelesSzamStr = order.CustomOrderNumber,
|
||||
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
|
||||
|
||||
await _fruitBankAttributeService.InsertOrUpdateGenericAttributeAsync<Order, string>(orderId, nameof(InvoiceCreateResponse.TechId), response.TechId);
|
||||
|
||||
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
|
||||
{
|
||||
// Get the invoice from InnVoice using the saved TechId
|
||||
var techId = await _fruitBankAttributeService.GetGenericAttributeValueAsync<Order, string>(
|
||||
orderId,
|
||||
nameof(InvoiceCreateResponse.TechId),
|
||||
_storeContext.GetCurrentStore().Id
|
||||
);
|
||||
|
||||
if (string.IsNullOrEmpty(techId))
|
||||
{
|
||||
return Json(new
|
||||
{
|
||||
success = false,
|
||||
message = "No invoice TechId found for this order"
|
||||
});
|
||||
}
|
||||
|
||||
var invoices = await _innVoiceApiService.GetInvoiceByTechIdAsync(techId);
|
||||
|
||||
if (invoices != null && invoices.Count > 0)
|
||||
{
|
||||
var invoice = invoices.FirstOrDefault();
|
||||
return Json(new
|
||||
{
|
||||
success = true,
|
||||
data = new
|
||||
{
|
||||
tableId = invoice.TableId,
|
||||
invoiceNumber = invoice.InvoiceNumberFormatted, // or invoice.InvoiceNumber
|
||||
sorszam = invoice.InvoiceNumberFormatted,
|
||||
printUrl = invoice.PrintUrl,
|
||||
customerName = invoice.CustomerName,
|
||||
totalGross = invoice.TotalGross,
|
||||
currency = invoice.Currency,
|
||||
isProforma = invoice.IsProforma,
|
||||
isDraft = invoice.IsDraft
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Json(new
|
||||
{
|
||||
success = false,
|
||||
message = "No invoice found for this order"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Json(new
|
||||
{
|
||||
success = false,
|
||||
message = $"Error: {ex.Message}"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,6 +81,8 @@ public class PluginNopStartup : INopStartup
|
|||
services.AddScoped<IConsumer<OrderPlacedEvent>, EventConsumer>();
|
||||
services.AddScoped<IOrderMeasurementService, OrderMeasurementService>();
|
||||
services.AddScoped<PendingMeasurementCheckoutFilter>();
|
||||
services.AddScoped<InnVoiceApiService>();
|
||||
services.AddScoped<InnVoiceOrderService>();
|
||||
|
||||
//services.AddScoped<OrderListModel, OrderListModelExtended>();
|
||||
//services.AddScoped<OrderModel, OrderModelExtended>();
|
||||
|
|
|
|||
|
|
@ -136,6 +136,11 @@ public class RouteProvider : IRouteProvider
|
|||
name: "Plugin.FruitBank.Admin.Orders.CustomerSearchAutoComplete",
|
||||
pattern: "Admin/CustomOrder/CustomerSearchAutoComplete",
|
||||
defaults: new { controller = "CustomOrder", action = "CustomerSearchAutoComplete", area = AreaNames.ADMIN });
|
||||
|
||||
endpointRouteBuilder.MapControllerRoute(
|
||||
name: "Plugin.FruitBank.Admin.Invoice.CreateInvoice",
|
||||
pattern: "Admin/Invoice/CreateInvoice",
|
||||
defaults: new { controller = "Invoice", action = "CreateInvoice", area = AreaNames.ADMIN });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -7,9 +7,6 @@
|
|||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<CopyRefAssembliesToPublishDirectory>true</CopyRefAssembliesToPublishDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Services\InnvoiceApiService.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="logo.jpg" />
|
||||
|
|
@ -637,10 +634,6 @@
|
|||
<Content Include="$(OutDir)\System.ServiceModel.Primitives.dll" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Services\InnvoiceApiService.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- This target execute after "Build" target -->
|
||||
<Target Name="NopTarget" AfterTargets="Build">
|
||||
<MSBuild Projects="@(ClearPluginAssemblies)" Properties="PluginPath=$(OutDir)" Targets="NopClear" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,417 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using System.Linq;
|
||||
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service for managing orders in InnVoice API
|
||||
/// </summary>
|
||||
public class InnVoiceOrderService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly string _companyName;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly string _baseUrl;
|
||||
|
||||
public InnVoiceOrderService(string companyName = "apiteszt", string username = "apiteszt", string password = "dsjfluio4324hjhjfdhkjskjh213kjgsd", string baseUrl = "https://api.innvoice.hu")
|
||||
{
|
||||
_companyName = companyName ?? throw new ArgumentNullException(nameof(companyName));
|
||||
_username = username ?? throw new ArgumentNullException(nameof(username));
|
||||
_password = password ?? throw new ArgumentNullException(nameof(password));
|
||||
_baseUrl = baseUrl.TrimEnd('/');
|
||||
|
||||
_httpClient = new HttpClient();
|
||||
SetupAuthentication();
|
||||
}
|
||||
|
||||
private void SetupAuthentication()
|
||||
{
|
||||
var authToken = Convert.ToBase64String(
|
||||
System.Text.Encoding.ASCII.GetBytes($"{_username}:{_password}")
|
||||
);
|
||||
_httpClient.DefaultRequestHeaders.Authorization =
|
||||
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create one or more orders
|
||||
/// </summary>
|
||||
public async Task<List<OrderCreateResponse>> CreateOrdersAsync(List<OrderCreateRequest> orders)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/order";
|
||||
|
||||
var xml = BuildOrdersXml(orders);
|
||||
var content = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("data", xml)
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
return ParseOrderResponses(responseContent);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error creating orders: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a single order
|
||||
/// </summary>
|
||||
public async Task<OrderCreateResponse> CreateOrderAsync(OrderCreateRequest order)
|
||||
{
|
||||
var responses = await CreateOrdersAsync(new List<OrderCreateRequest> { order });
|
||||
return responses.FirstOrDefault();
|
||||
}
|
||||
|
||||
private string BuildOrdersXml(List<OrderCreateRequest> orders)
|
||||
{
|
||||
var ordersElement = new XElement("orders");
|
||||
|
||||
foreach (var order in orders)
|
||||
{
|
||||
var orderElement = new XElement("order");
|
||||
|
||||
orderElement.Add(new XElement("VevoNev", new XCData(order.VevoNev ?? "")));
|
||||
orderElement.Add(new XElement("VevoIrsz", new XCData(order.VevoIrsz ?? "")));
|
||||
orderElement.Add(new XElement("VevoTelep", new XCData(order.VevoTelep ?? "")));
|
||||
orderElement.Add(new XElement("VevoUtcaHsz", new XCData(order.VevoUtcaHsz ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(order.VevoOrszag))
|
||||
orderElement.Add(new XElement("VevoOrszag", new XCData(order.VevoOrszag)));
|
||||
|
||||
if (!string.IsNullOrEmpty(order.VevoAdoszam))
|
||||
orderElement.Add(new XElement("VevoAdoszam", new XCData(order.VevoAdoszam)));
|
||||
|
||||
if (!string.IsNullOrEmpty(order.SzallNev))
|
||||
orderElement.Add(new XElement("SzallNev", new XCData(order.SzallNev)));
|
||||
if (!string.IsNullOrEmpty(order.SzallIrsz))
|
||||
orderElement.Add(new XElement("SzallIrsz", new XCData(order.SzallIrsz)));
|
||||
if (!string.IsNullOrEmpty(order.SzallTelep))
|
||||
orderElement.Add(new XElement("SzallTelep", new XCData(order.SzallTelep)));
|
||||
if (!string.IsNullOrEmpty(order.SzallUtcaHsz))
|
||||
orderElement.Add(new XElement("SzallUtcaHsz", new XCData(order.SzallUtcaHsz)));
|
||||
if (!string.IsNullOrEmpty(order.SzallOrszag))
|
||||
orderElement.Add(new XElement("SzallOrszag", new XCData(order.SzallOrszag)));
|
||||
|
||||
orderElement.Add(new XElement("MegrendelestombID", new XCData(order.MegrendelestombID.ToString())));
|
||||
orderElement.Add(new XElement("MegrendelesKelte", new XCData(order.MegrendelesKelte.ToString("yyyy.MM.dd."))));
|
||||
orderElement.Add(new XElement("Hatarido", new XCData(order.Hatarido.ToString("yyyy.MM.dd."))));
|
||||
orderElement.Add(new XElement("Devizanem", new XCData(order.Devizanem ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(order.FizetesiMod))
|
||||
orderElement.Add(new XElement("FizetesiMod", new XCData(order.FizetesiMod)));
|
||||
if (!string.IsNullOrEmpty(order.Megjegyzes))
|
||||
orderElement.Add(new XElement("Megjegyzes", new XCData(order.Megjegyzes)));
|
||||
if (!string.IsNullOrEmpty(order.Email))
|
||||
orderElement.Add(new XElement("Email", new XCData(order.Email)));
|
||||
if (!string.IsNullOrEmpty(order.Telefon))
|
||||
orderElement.Add(new XElement("Telefon", new XCData(order.Telefon)));
|
||||
if (!string.IsNullOrEmpty(order.MegrendelesSzamStr))
|
||||
orderElement.Add(new XElement("MegrendelesSzamStr", new XCData(order.MegrendelesSzamStr)));
|
||||
|
||||
// Add items
|
||||
foreach (var item in order.Items)
|
||||
{
|
||||
var tetelElement = new XElement("tetel");
|
||||
tetelElement.Add(new XElement("TetelNev", item.TetelNev ?? ""));
|
||||
tetelElement.Add(new XElement("AfaSzoveg", item.AfaSzoveg ?? ""));
|
||||
tetelElement.Add(new XElement("Brutto", item.Brutto ? "1" : "0"));
|
||||
tetelElement.Add(new XElement("EgysegAr", item.EgysegAr.ToString()));
|
||||
tetelElement.Add(new XElement("Mennyiseg", item.Mennyiseg.ToString()));
|
||||
tetelElement.Add(new XElement("MennyisegEgyseg", new XCData(item.MennyisegEgyseg ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(item.CikkSzam))
|
||||
tetelElement.Add(new XElement("CikkSzam", new XCData(item.CikkSzam)));
|
||||
|
||||
orderElement.Add(tetelElement);
|
||||
}
|
||||
|
||||
ordersElement.Add(orderElement);
|
||||
}
|
||||
|
||||
return new XDeclaration("1.0", "UTF-8", null).ToString() + "\n" + ordersElement.ToString();
|
||||
}
|
||||
|
||||
private List<OrderCreateResponse> ParseOrderResponses(string xml)
|
||||
{
|
||||
var responses = new List<OrderCreateResponse>();
|
||||
|
||||
try
|
||||
{
|
||||
var doc = XDocument.Parse(xml);
|
||||
var orderElements = doc.Descendants("order");
|
||||
|
||||
foreach (var orderElement in orderElements)
|
||||
{
|
||||
var response = new OrderCreateResponse
|
||||
{
|
||||
ErrorCode = orderElement.Element("error")?.Value?.Trim(),
|
||||
Message = orderElement.Element("message")?.Value?.Trim(),
|
||||
TableId = int.TryParse(orderElement.Element("TABLE_ID")?.Value?.Trim(), out var tid) ? tid : (int?)null,
|
||||
TechId = orderElement.Element("techid")?.Value?.Trim(),
|
||||
PrintUrl = orderElement.Element("PrintUrl")?.Value?.Trim()
|
||||
};
|
||||
|
||||
responses.Add(response);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error parsing order response XML: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return responses;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get order by technical ID
|
||||
/// </summary>
|
||||
public async Task<List<InnVoiceOrder>> GetOrderByTechIdAsync(string techId)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/order/techid/{Uri.EscapeDataString(techId)}";
|
||||
return await GetOrdersFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get order by table ID
|
||||
/// </summary>
|
||||
public async Task<InnVoiceOrder> GetOrderByIdAsync(int tableId)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/order/id/{tableId}";
|
||||
var orders = await GetOrdersFromUrlAsync(url);
|
||||
return orders.Count > 0 ? orders[0] : null;
|
||||
}
|
||||
|
||||
private async Task<List<InnVoiceOrder>> GetOrdersFromUrlAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
// Parse XML response
|
||||
return ParseOrdersFromXml(content);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error calling InnVoice API: {ex.Message}", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error parsing API response: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private List<InnVoiceOrder> ParseOrdersFromXml(string xml)
|
||||
{
|
||||
var orders = new List<InnVoiceOrder>();
|
||||
|
||||
try
|
||||
{
|
||||
var doc = XDocument.Parse(xml);
|
||||
var orderElements = doc.Descendants("order");
|
||||
|
||||
foreach (var orderElement in orderElements)
|
||||
{
|
||||
var order = new InnVoiceOrder
|
||||
{
|
||||
TableId = GetIntValue(orderElement, "TABLE_ID"),
|
||||
VevoID = GetIntValue(orderElement, "VevoID"),
|
||||
CustomerName = GetStringValue(orderElement, "VevoNev"),
|
||||
CustomerZipCode = GetStringValue(orderElement, "VevoIrsz"),
|
||||
CustomerCity = GetStringValue(orderElement, "VevoTelep"),
|
||||
CustomerAddress = GetStringValue(orderElement, "VevoUtcaHsz"),
|
||||
CustomerCountry = GetStringValue(orderElement, "VevoOrszag"),
|
||||
CustomerTaxNumber = GetStringValue(orderElement, "VevoAdoszam"),
|
||||
ShippingName = GetStringValue(orderElement, "SzallNev"),
|
||||
ShippingZipCode = GetStringValue(orderElement, "SzallIrsz"),
|
||||
ShippingCity = GetStringValue(orderElement, "SzallTelep"),
|
||||
ShippingAddress = GetStringValue(orderElement, "SzallUtcaHsz"),
|
||||
ShippingCountry = GetStringValue(orderElement, "SzallOrszag"),
|
||||
OrderBookId = GetIntValue(orderElement, "MegrendelestombID"),
|
||||
OrderDate = GetStringValue(orderElement, "MegrendelesKelte"),
|
||||
DueDate = GetStringValue(orderElement, "Hatarido"),
|
||||
Currency = GetStringValue(orderElement, "Devizanem"),
|
||||
PaymentMethod = GetStringValue(orderElement, "FizetesiMod"),
|
||||
Notes = GetStringValue(orderElement, "Megjegyzes"),
|
||||
Email = GetStringValue(orderElement, "Email"),
|
||||
Phone = GetStringValue(orderElement, "Telefon"),
|
||||
ExternalOrderNumber = GetStringValue(orderElement, "MegrendelesSzamStr"),
|
||||
TotalNet = GetDecimalValue(orderElement, "NettoErtek"),
|
||||
TotalVAT = GetDecimalValue(orderElement, "AFAErtek"),
|
||||
TotalGross = GetDecimalValue(orderElement, "BruttoErtek"),
|
||||
TechId = GetStringValue(orderElement, "techid"),
|
||||
PrintUrl = GetStringValue(orderElement, "PrintLink"),
|
||||
UpdateTime = GetStringValue(orderElement, "_UpdateTime"),
|
||||
QueryTime = GetStringValue(orderElement, "QueryTime")
|
||||
};
|
||||
|
||||
// Parse line items
|
||||
var itemElements = orderElement.Descendants("tetel");
|
||||
foreach (var itemElement in itemElements)
|
||||
{
|
||||
order.Items.Add(new InnVoiceOrderLineItem
|
||||
{
|
||||
TableId = GetIntValue(itemElement, "TABLE_ID"),
|
||||
ItemName = GetStringValue(itemElement, "TetelNev"),
|
||||
ArticleNumber = GetStringValue(itemElement, "CikkSzam"),
|
||||
VATText = GetStringValue(itemElement, "AfaSzoveg"),
|
||||
VATRate = GetDecimalValue(itemElement, "AfaKulcs"),
|
||||
IsGross = GetIntValue(itemElement, "Brutto") == 1,
|
||||
UnitPrice = GetDecimalValue(itemElement, "EgysegAr"),
|
||||
Quantity = GetDecimalValue(itemElement, "Mennyiseg"),
|
||||
Unit = GetStringValue(itemElement, "MennyisegEgyseg")
|
||||
});
|
||||
}
|
||||
|
||||
orders.Add(order);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error parsing XML: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
return orders;
|
||||
}
|
||||
|
||||
private string GetStringValue(XElement element, string name)
|
||||
{
|
||||
return element.Element(name)?.Value?.Trim() ?? string.Empty;
|
||||
}
|
||||
|
||||
private int GetIntValue(XElement element, string name)
|
||||
{
|
||||
var value = GetStringValue(element, name);
|
||||
return int.TryParse(value, out var result) ? result : 0;
|
||||
}
|
||||
|
||||
private decimal GetDecimalValue(XElement element, string name)
|
||||
{
|
||||
var value = GetStringValue(element, name);
|
||||
return decimal.TryParse(value, out var result) ? result : 0m;
|
||||
}
|
||||
}
|
||||
|
||||
// Order Models
|
||||
public class OrderCreateRequest
|
||||
{
|
||||
public string VevoNev { get; set; }
|
||||
public string VevoIrsz { get; set; }
|
||||
public string VevoTelep { get; set; }
|
||||
public string VevoUtcaHsz { get; set; }
|
||||
public string VevoOrszag { get; set; }
|
||||
public string VevoAdoszam { get; set; }
|
||||
public string SzallNev { get; set; }
|
||||
public string SzallIrsz { get; set; }
|
||||
public string SzallTelep { get; set; }
|
||||
public string SzallUtcaHsz { get; set; }
|
||||
public string SzallOrszag { get; set; }
|
||||
public int MegrendelestombID { get; set; }
|
||||
public DateTime MegrendelesKelte { get; set; }
|
||||
public DateTime Hatarido { get; set; }
|
||||
public string Devizanem { get; set; }
|
||||
public string FizetesiMod { get; set; }
|
||||
public string Megjegyzes { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Telefon { get; set; }
|
||||
public string MegrendelesSzamStr { get; set; }
|
||||
|
||||
public List<InnVoiceOrderItem> Items { get; set; } = new List<InnVoiceOrderItem>();
|
||||
|
||||
public void AddItem(InnVoiceOrderItem item)
|
||||
{
|
||||
Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public class InnVoiceOrderItem
|
||||
{
|
||||
public string TetelNev { get; set; }
|
||||
public string AfaSzoveg { get; set; }
|
||||
public bool Brutto { get; set; }
|
||||
public decimal EgysegAr { get; set; }
|
||||
public decimal Mennyiseg { get; set; }
|
||||
public string MennyisegEgyseg { get; set; }
|
||||
public string CikkSzam { get; set; }
|
||||
}
|
||||
|
||||
public class OrderCreateResponse
|
||||
{
|
||||
public string ErrorCode { get; set; }
|
||||
public string Message { get; set; }
|
||||
public int? TableId { get; set; }
|
||||
public string TechId { get; set; }
|
||||
public string PrintUrl { get; set; }
|
||||
|
||||
public bool IsSuccess => ErrorCode == "200";
|
||||
}
|
||||
|
||||
public class InnVoiceApiException : Exception
|
||||
{
|
||||
public InnVoiceApiException(string message) : base(message) { }
|
||||
public InnVoiceApiException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
// Order GET response models
|
||||
public class InnVoiceOrder
|
||||
{
|
||||
public int TableId { get; set; }
|
||||
public int VevoID { get; set; }
|
||||
public string CustomerName { get; set; }
|
||||
public string CustomerZipCode { get; set; }
|
||||
public string CustomerCity { get; set; }
|
||||
public string CustomerAddress { get; set; }
|
||||
public string CustomerCountry { get; set; }
|
||||
public string CustomerTaxNumber { get; set; }
|
||||
public string ShippingName { get; set; }
|
||||
public string ShippingZipCode { get; set; }
|
||||
public string ShippingCity { get; set; }
|
||||
public string ShippingAddress { get; set; }
|
||||
public string ShippingCountry { get; set; }
|
||||
public int OrderBookId { get; set; }
|
||||
public string OrderDate { get; set; }
|
||||
public string DueDate { get; set; }
|
||||
public string Currency { get; set; }
|
||||
public string PaymentMethod { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string ExternalOrderNumber { get; set; }
|
||||
public decimal TotalNet { get; set; }
|
||||
public decimal TotalVAT { get; set; }
|
||||
public decimal TotalGross { get; set; }
|
||||
public string TechId { get; set; }
|
||||
public string PrintUrl { get; set; }
|
||||
public string UpdateTime { get; set; }
|
||||
public string QueryTime { get; set; }
|
||||
|
||||
public List<InnVoiceOrderLineItem> Items { get; set; } = new List<InnVoiceOrderLineItem>();
|
||||
}
|
||||
|
||||
public class InnVoiceOrderLineItem
|
||||
{
|
||||
public int TableId { get; set; }
|
||||
public string ItemName { get; set; }
|
||||
public string ArticleNumber { get; set; }
|
||||
public string VATText { get; set; }
|
||||
public decimal VATRate { get; set; }
|
||||
public bool IsGross { get; set; }
|
||||
public decimal UnitPrice { get; set; }
|
||||
public decimal Quantity { get; set; }
|
||||
public string Unit { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -10,487 +11,627 @@ using System.Text;
|
|||
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Service for interacting with InnVoice Invoice API
|
||||
/// API Documentation: https://help.innvoice.hu/hc/hu/articles/360003142839
|
||||
/// </summary>
|
||||
public class InnVoiceApiService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly string _companyName;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly string _baseUrl;
|
||||
/// <summary>
|
||||
/// Service for interacting with InnVoice Invoice API
|
||||
/// API Documentation: https://help.innvoice.hu/hc/hu/articles/360003142839
|
||||
/// </summary>
|
||||
public class InnVoiceApiService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly string _companyName;
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly string _baseUrl;
|
||||
|
||||
public InnVoiceApiService(string companyName, string username, string password, string baseUrl = "https://api.innvoice.hu")
|
||||
{
|
||||
_companyName = companyName ?? throw new ArgumentNullException(nameof(companyName));
|
||||
_username = username ?? throw new ArgumentNullException(nameof(username));
|
||||
_password = password ?? throw new ArgumentNullException(nameof(password));
|
||||
_baseUrl = baseUrl.TrimEnd('/');
|
||||
public InnVoiceApiService(string companyName = "apiteszt", string username = "apiteszt", string password = "dsjfluio4324hjhjfdhkjskjh213kjgsd", string baseUrl = "https://api.innvoice.hu")
|
||||
{
|
||||
_companyName = companyName ?? throw new ArgumentNullException(nameof(companyName));
|
||||
_username = username ?? throw new ArgumentNullException(nameof(username));
|
||||
_password = password ?? throw new ArgumentNullException(nameof(password));
|
||||
_baseUrl = baseUrl.TrimEnd('/');
|
||||
|
||||
_httpClient = new HttpClient();
|
||||
SetupAuthentication();
|
||||
}
|
||||
_httpClient = new HttpClient();
|
||||
SetupAuthentication();
|
||||
}
|
||||
|
||||
private void SetupAuthentication()
|
||||
{
|
||||
var authToken = Convert.ToBase64String(
|
||||
System.Text.Encoding.ASCII.GetBytes($"{_username}:{_password}")
|
||||
);
|
||||
_httpClient.DefaultRequestHeaders.Authorization =
|
||||
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authToken);
|
||||
}
|
||||
private void SetupAuthentication()
|
||||
{
|
||||
var authToken = Convert.ToBase64String(
|
||||
System.Text.Encoding.ASCII.GetBytes($"{_username}:{_password}")
|
||||
);
|
||||
_httpClient.DefaultRequestHeaders.Authorization =
|
||||
new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all invoices
|
||||
/// Rate limit: 20 times per hour without ID parameter
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetAllInvoicesAsync()
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get all invoices
|
||||
/// Rate limit: 20 times per hour without ID parameter
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetAllInvoicesAsync()
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoice by internal table ID
|
||||
/// </summary>
|
||||
public async Task<Invoice> GetInvoiceByIdAsync(int tableId)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/id/{tableId}";
|
||||
var invoices = await GetInvoicesFromUrlAsync(url);
|
||||
return invoices.Count > 0 ? invoices[0] : null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoice by internal table ID
|
||||
/// </summary>
|
||||
public async Task<Invoice> GetInvoiceByIdAsync(int tableId)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/id/{tableId}";
|
||||
var invoices = await GetInvoicesFromUrlAsync(url);
|
||||
return invoices.Count > 0 ? invoices[0] : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoice by invoice number
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoiceByNumberAsync(string invoiceNumber)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/invoicenumber/{Uri.EscapeDataString(invoiceNumber)}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoice by invoice number
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoiceByNumberAsync(string invoiceNumber)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/invoicenumber/{Uri.EscapeDataString(invoiceNumber)}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoices by creation date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByCreationDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/created/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoice by invoice number
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoiceByTechIdAsync(string techId)
|
||||
{
|
||||
//api.innvoice.hu/%regnev%/invoice/techid/%TECHID%
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/techid/{Uri.EscapeDataString(techId)}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoices by fulfillment date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByFulfillmentDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/fulfillment/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoices by due date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByDueDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/duedate/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoices by creation date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByCreationDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/created/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoices by payment date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByPaymentDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/paymentdate/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoices by fulfillment date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByFulfillmentDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/fulfillment/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoices by customer tax number
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByCustomerTaxNumberAsync(string taxNumber)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/taxnumber/{Uri.EscapeDataString(taxNumber)}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoices by due date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByDueDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/duedate/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get invoices modified since a specific timestamp
|
||||
/// Format: YYYYMMDDHHmmss (year, month, day, hour, minute, second)
|
||||
/// Recommended for tracking changes every 10 minutes
|
||||
/// Rate limit: Full queries or queries older than current month limited to 10 times per 30 days
|
||||
/// Recommended: Only use current month dates
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByUpdateTimeAsync(DateTime updateTime)
|
||||
{
|
||||
var timeStr = updateTime.ToString("yyyyMMddHHmmss");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/updatedtime/{timeStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get invoices by payment date
|
||||
/// Format: YYYYMMDD
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByPaymentDateAsync(DateTime date)
|
||||
{
|
||||
var dateStr = date.ToString("yyyyMMdd");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/paymentdate/{dateStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
private async Task<List<Invoice>> GetInvoicesFromUrlAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
/// <summary>
|
||||
/// Get invoices by customer tax number
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByCustomerTaxNumberAsync(string taxNumber)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/taxnumber/{Uri.EscapeDataString(taxNumber)}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
var invoices = JsonSerializer.Deserialize<List<Invoice>>(content, new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true
|
||||
});
|
||||
/// <summary>
|
||||
/// Get invoices modified since a specific timestamp
|
||||
/// Format: YYYYMMDDHHmmss (year, month, day, hour, minute, second)
|
||||
/// Recommended for tracking changes every 10 minutes
|
||||
/// Rate limit: Full queries or queries older than current month limited to 10 times per 30 days
|
||||
/// Recommended: Only use current month dates
|
||||
/// </summary>
|
||||
public async Task<List<Invoice>> GetInvoicesByUpdateTimeAsync(DateTime updateTime)
|
||||
{
|
||||
var timeStr = updateTime.ToString("yyyyMMddHHmmss");
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice/updatedtime/{timeStr}";
|
||||
return await GetInvoicesFromUrlAsync(url);
|
||||
}
|
||||
|
||||
return invoices ?? new List<Invoice>();
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error calling InnVoice API: {ex.Message}", ex);
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error parsing API response: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
private async Task<List<Invoice>> GetInvoicesFromUrlAsync(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.GetAsync(url);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
// Models
|
||||
public class Invoice
|
||||
{
|
||||
[JsonPropertyName("TABLE_ID")]
|
||||
public int TableId { get; set; }
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
[JsonPropertyName("InvoiceNumber")]
|
||||
public string InvoiceNumber { get; set; }
|
||||
// Parse XML response
|
||||
return ParseInvoicesFromXml(content);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error calling InnVoice API: {ex.Message}", ex);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error parsing API response: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("Created")]
|
||||
public string Created { get; set; }
|
||||
|
||||
[JsonPropertyName("Fulfillment")]
|
||||
public string Fulfillment { get; set; }
|
||||
|
||||
[JsonPropertyName("DueDate")]
|
||||
public string DueDate { get; set; }
|
||||
private List<Invoice> ParseInvoicesFromXml(string xml)
|
||||
{
|
||||
var invoices = new List<Invoice>();
|
||||
|
||||
[JsonPropertyName("PaymentDate")]
|
||||
public string PaymentDate { get; set; }
|
||||
try
|
||||
{
|
||||
var doc = XDocument.Parse(xml);
|
||||
var invoiceElements = doc.Descendants("invoice");
|
||||
|
||||
[JsonPropertyName("CustomerName")]
|
||||
public string CustomerName { get; set; }
|
||||
foreach (var invoiceElement in invoiceElements)
|
||||
{
|
||||
var invoice = new Invoice
|
||||
{
|
||||
TableId = GetIntValue(invoiceElement, "TABLE_ID"),
|
||||
VevoID = GetIntValue(invoiceElement, "VevoID"),
|
||||
CustomerName = GetStringValue(invoiceElement, "VevoNev"),
|
||||
CustomerZipCode = GetStringValue(invoiceElement, "VevoIrsz"),
|
||||
CustomerCity = GetStringValue(invoiceElement, "VevoTelep"),
|
||||
CustomerAddress = GetStringValue(invoiceElement, "VevoUtcaHsz"),
|
||||
CustomerCountry = GetStringValue(invoiceElement, "VevoOrszag"),
|
||||
CustomerTaxNumber = GetStringValue(invoiceElement, "VevoAdoszam"),
|
||||
CustomerGroupTaxNumber = GetStringValue(invoiceElement, "VevoCsAdoszam"),
|
||||
PaymentMethod = GetStringValue(invoiceElement, "FizetesiMod"),
|
||||
FulfillmentDate = GetStringValue(invoiceElement, "TeljesitesKelte"),
|
||||
InvoiceDate = GetStringValue(invoiceElement, "SzamlaKelte"),
|
||||
DueDate = GetStringValue(invoiceElement, "Hatarido"),
|
||||
Notes = GetStringValue(invoiceElement, "Megjegyzes"),
|
||||
Currency = GetStringValue(invoiceElement, "Devizanem"),
|
||||
IsDraft = GetIntValue(invoiceElement, "Felretett") == 1,
|
||||
IsCancelled = GetIntValue(invoiceElement, "Storno") == 1,
|
||||
IsAdvance = GetIntValue(invoiceElement, "Eloleg") == 1,
|
||||
IsProforma = GetIntValue(invoiceElement, "Proforma") == 1,
|
||||
TotalNet = GetDecimalValue(invoiceElement, "NettoErtek"),
|
||||
TotalVAT = GetDecimalValue(invoiceElement, "AFAErtek"),
|
||||
TotalGross = GetDecimalValue(invoiceElement, "BruttoErtek"),
|
||||
OutstandingAmount = GetDecimalValue(invoiceElement, "Hatralek"),
|
||||
OverdueAmount = GetDecimalValue(invoiceElement, "LejartHatralek"),
|
||||
PaidAmount = GetDecimalValue(invoiceElement, "Befizetes"),
|
||||
InvoiceNumber = GetStringValue(invoiceElement, "Sorszam"),
|
||||
InvoiceNumberFormatted = GetStringValue(invoiceElement, "SorszamFormatted"),
|
||||
InvoiceId = GetIntValue(invoiceElement, "SzamlaID"),
|
||||
UniqueId = GetStringValue(invoiceElement, "_UniqueID"),
|
||||
ExchangeRate = GetDecimalValue(invoiceElement, "Arfolyam"),
|
||||
InvoiceBookId = GetIntValue(invoiceElement, "SzamlatombID"),
|
||||
InvoiceBookName = GetStringValue(invoiceElement, "SzamlatombNev"),
|
||||
IsElectronic = GetIntValue(invoiceElement, "Eszamla") == 1,
|
||||
Phone = GetStringValue(invoiceElement, "Telefon"),
|
||||
Email = GetStringValue(invoiceElement, "Email"),
|
||||
UpdateTime = GetStringValue(invoiceElement, "_UpdateTime"),
|
||||
QueryTime = GetStringValue(invoiceElement, "QueryTime"),
|
||||
OrderNumber = GetStringValue(invoiceElement, "MegrendelesSzamStr"),
|
||||
OrderDate = GetStringValue(invoiceElement, "MegrendelesIdopontStr"),
|
||||
ShippingName = GetStringValue(invoiceElement, "SzallNev"),
|
||||
ShippingZipCode = GetStringValue(invoiceElement, "SzallIrsz"),
|
||||
ShippingCity = GetStringValue(invoiceElement, "SzallTelep"),
|
||||
ShippingAddress = GetStringValue(invoiceElement, "SzallUtcaHsz"),
|
||||
ShippingCountry = GetStringValue(invoiceElement, "SzallOrszag"),
|
||||
PrintUrl = GetStringValue(invoiceElement, "PrintLink"),
|
||||
InvoiceLink = GetStringValue(invoiceElement, "SzamlaLink"),
|
||||
HealthFundName = GetStringValue(invoiceElement, "VevoEPNev"),
|
||||
HealthFundCode = GetStringValue(invoiceElement, "VevoEPKod")
|
||||
};
|
||||
|
||||
[JsonPropertyName("CustomerTaxNumber")]
|
||||
public string CustomerTaxNumber { get; set; }
|
||||
// Parse line items
|
||||
var itemElements = invoiceElement.Descendants("tetel");
|
||||
foreach (var itemElement in itemElements)
|
||||
{
|
||||
invoice.Items.Add(new InvoiceLineItem
|
||||
{
|
||||
TableId = GetIntValue(itemElement, "TABLE_ID"),
|
||||
ItemName = GetStringValue(itemElement, "TetelNev"),
|
||||
ArticleNumber = GetStringValue(itemElement, "CikkSzam"),
|
||||
VTSZSZJ = GetStringValue(itemElement, "VTSZSZJ"),
|
||||
VATText = GetStringValue(itemElement, "AfaSzoveg"),
|
||||
VATRate = GetDecimalValue(itemElement, "AfaKulcs"),
|
||||
IsGross = GetIntValue(itemElement, "Brutto") == 1,
|
||||
UnitPrice = GetDecimalValue(itemElement, "EgysegAr"),
|
||||
Quantity = GetDecimalValue(itemElement, "Mennyiseg"),
|
||||
Unit = GetStringValue(itemElement, "MennyisegEgyseg"),
|
||||
ProductId = GetIntValue(itemElement, "TermekID"),
|
||||
DiscountAmount = GetDecimalValue(itemElement, "KedvezmenyOsszeg")
|
||||
});
|
||||
}
|
||||
|
||||
[JsonPropertyName("CustomerAddress")]
|
||||
public string CustomerAddress { get; set; }
|
||||
invoices.Add(invoice);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error parsing XML: {ex.Message}", ex);
|
||||
}
|
||||
|
||||
[JsonPropertyName("TotalNet")]
|
||||
public decimal TotalNet { get; set; }
|
||||
return invoices;
|
||||
}
|
||||
|
||||
[JsonPropertyName("TotalGross")]
|
||||
public decimal TotalGross { get; set; }
|
||||
private string GetStringValue(XElement element, string name)
|
||||
{
|
||||
return element.Element(name)?.Value?.Trim() ?? string.Empty;
|
||||
}
|
||||
|
||||
[JsonPropertyName("Currency")]
|
||||
public string Currency { get; set; }
|
||||
private int GetIntValue(XElement element, string name)
|
||||
{
|
||||
var value = GetStringValue(element, name);
|
||||
return int.TryParse(value, out var result) ? result : 0;
|
||||
}
|
||||
|
||||
[JsonPropertyName("Status")]
|
||||
public string Status { get; set; }
|
||||
private decimal GetDecimalValue(XElement element, string name)
|
||||
{
|
||||
var value = GetStringValue(element, name);
|
||||
return decimal.TryParse(value, out var result) ? result : 0m;
|
||||
}
|
||||
|
||||
[JsonPropertyName("InvoiceType")]
|
||||
public string InvoiceType { get; set; }
|
||||
|
||||
[JsonPropertyName("PaymentMethod")]
|
||||
public string PaymentMethod { get; set; }
|
||||
|
||||
// Add more properties as needed based on actual API response
|
||||
}
|
||||
|
||||
public class InnVoiceApiException : Exception
|
||||
{
|
||||
public InnVoiceApiException(string message) : base(message) { }
|
||||
public InnVoiceApiException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
// Invoice Creation Models
|
||||
public class InvoiceCreateRequest
|
||||
{
|
||||
public int VevoID { get; set; } = 0;
|
||||
public string VevoNev { get; set; }
|
||||
public string VevoIrsz { get; set; }
|
||||
public string VevoOrszag { get; set; }
|
||||
public string VevoTelep { get; set; }
|
||||
public string VevoUtcaHsz { get; set; }
|
||||
public string VevoEPNev { get; set; }
|
||||
public string VevoEPKod { get; set; }
|
||||
public string SzallNev { get; set; }
|
||||
public string SzallIrsz { get; set; }
|
||||
public string SzallTelep { get; set; }
|
||||
public string SzallUtcaHsz { get; set; }
|
||||
public string SzallOrszag { get; set; }
|
||||
public int SzamlatombID { get; set; }
|
||||
public DateTime SzamlaKelte { get; set; }
|
||||
public DateTime TeljesitesKelte { get; set; }
|
||||
public DateTime Hatarido { get; set; }
|
||||
public string Devizanem { get; set; }
|
||||
public string FizetesiMod { get; set; }
|
||||
public string Megjegyzes { get; set; }
|
||||
public string Nyelv1 { get; set; }
|
||||
public string Nyelv2 { get; set; }
|
||||
public decimal? Arfolyam { get; set; }
|
||||
public string ArfolyamDeviza { get; set; }
|
||||
public bool Fizetve { get; set; }
|
||||
public bool Eszamla { get; set; }
|
||||
public string VevoAdoszam { get; set; }
|
||||
public string VevoCsAdoszam { get; set; }
|
||||
public string Telefon { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string MegrendelesSzamStr { get; set; }
|
||||
public string MegrendelesIdopontStr { get; set; }
|
||||
public bool Felretett { get; set; }
|
||||
public bool Proforma { get; set; }
|
||||
public bool AutomatikusAr { get; set; }
|
||||
public bool Eloleg { get; set; }
|
||||
public bool Sendmail { get; set; }
|
||||
public string MailSubject { get; set; }
|
||||
public string MailBody { get; set; }
|
||||
public string Eredetiszamla { get; set; }
|
||||
|
||||
public List<InvoiceItem> Items { get; set; } = new List<InvoiceItem>();
|
||||
|
||||
public void AddItem(InvoiceItem item)
|
||||
{
|
||||
Items.Add(item);
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
var invoices = new XElement("invoices");
|
||||
var invoice = new XElement("invoice");
|
||||
|
||||
if (VevoID > 0)
|
||||
invoice.Add(new XElement("VevoID", new XCData(VevoID.ToString())));
|
||||
|
||||
invoice.Add(new XElement("VevoNev", new XCData(VevoNev ?? "")));
|
||||
invoice.Add(new XElement("VevoIrsz", new XCData(VevoIrsz ?? "")));
|
||||
invoice.Add(new XElement("VevoTelep", new XCData(VevoTelep ?? "")));
|
||||
invoice.Add(new XElement("VevoOrszag", new XCData(VevoOrszag ?? "")));
|
||||
invoice.Add(new XElement("VevoUtcaHsz", new XCData(VevoUtcaHsz ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(VevoEPNev))
|
||||
invoice.Add(new XElement("VevoEPNev", new XCData(VevoEPNev)));
|
||||
if (!string.IsNullOrEmpty(VevoEPKod))
|
||||
invoice.Add(new XElement("VevoEPKod", new XCData(VevoEPKod)));
|
||||
if (!string.IsNullOrEmpty(SzallNev))
|
||||
invoice.Add(new XElement("SzallNev", new XCData(SzallNev)));
|
||||
if (!string.IsNullOrEmpty(SzallIrsz))
|
||||
invoice.Add(new XElement("SzallIrsz", new XCData(SzallIrsz)));
|
||||
if (!string.IsNullOrEmpty(SzallTelep))
|
||||
invoice.Add(new XElement("SzallTelep", new XCData(SzallTelep)));
|
||||
if (!string.IsNullOrEmpty(SzallUtcaHsz))
|
||||
invoice.Add(new XElement("SzallUtcaHsz", new XCData(SzallUtcaHsz)));
|
||||
if (!string.IsNullOrEmpty(SzallOrszag))
|
||||
invoice.Add(new XElement("SzallOrszag", new XCData(SzallOrszag)));
|
||||
|
||||
invoice.Add(new XElement("SzamlatombID", new XCData(SzamlatombID.ToString())));
|
||||
invoice.Add(new XElement("SzamlaKelte", new XCData(SzamlaKelte.ToString("yyyy.MM.dd."))));
|
||||
invoice.Add(new XElement("TeljesitesKelte", new XCData(TeljesitesKelte.ToString("yyyy.MM.dd."))));
|
||||
invoice.Add(new XElement("Hatarido", new XCData(Hatarido.ToString("yyyy.MM.dd."))));
|
||||
invoice.Add(new XElement("Devizanem", new XCData(Devizanem ?? "")));
|
||||
invoice.Add(new XElement("FizetesiMod", new XCData(FizetesiMod ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(Megjegyzes))
|
||||
invoice.Add(new XElement("Megjegyzes", new XCData(Megjegyzes)));
|
||||
if (!string.IsNullOrEmpty(Nyelv1))
|
||||
invoice.Add(new XElement("Nyelv1", new XCData(Nyelv1)));
|
||||
if (!string.IsNullOrEmpty(Nyelv2))
|
||||
invoice.Add(new XElement("Nyelv2", new XCData(Nyelv2)));
|
||||
if (Arfolyam.HasValue)
|
||||
invoice.Add(new XElement("Arfolyam", new XCData(Arfolyam.Value.ToString())));
|
||||
if (!string.IsNullOrEmpty(ArfolyamDeviza))
|
||||
invoice.Add(new XElement("ArfolyamDeviza", new XCData(ArfolyamDeviza)));
|
||||
|
||||
invoice.Add(new XElement("Fizetve", Fizetve ? "1" : "0"));
|
||||
invoice.Add(new XElement("Eszamla", Eszamla ? "1" : "0"));
|
||||
|
||||
if (!string.IsNullOrEmpty(VevoAdoszam))
|
||||
invoice.Add(new XElement("VevoAdoszam", new XCData(VevoAdoszam)));
|
||||
if (!string.IsNullOrEmpty(VevoCsAdoszam))
|
||||
invoice.Add(new XElement("VevoCsAdoszam", new XCData(VevoCsAdoszam)));
|
||||
if (!string.IsNullOrEmpty(Telefon))
|
||||
invoice.Add(new XElement("Telefon", new XCData(Telefon)));
|
||||
if (!string.IsNullOrEmpty(Email))
|
||||
invoice.Add(new XElement("Email", new XCData(Email)));
|
||||
if (!string.IsNullOrEmpty(MegrendelesSzamStr))
|
||||
invoice.Add(new XElement("MegrendelesSzamStr", new XCData(MegrendelesSzamStr)));
|
||||
if (!string.IsNullOrEmpty(MegrendelesIdopontStr))
|
||||
invoice.Add(new XElement("MegrendelesIdopontStr", new XCData(MegrendelesIdopontStr)));
|
||||
|
||||
invoice.Add(new XElement("Felretett", Felretett ? "1" : "0"));
|
||||
invoice.Add(new XElement("Proforma", Proforma ? "1" : "0"));
|
||||
|
||||
if (AutomatikusAr)
|
||||
invoice.Add(new XElement("AutomatikusAr", "1"));
|
||||
if (Eloleg)
|
||||
invoice.Add(new XElement("Eloleg", "1"));
|
||||
if (Sendmail)
|
||||
{
|
||||
invoice.Add(new XElement("Sendmail", "1"));
|
||||
if (!string.IsNullOrEmpty(MailSubject))
|
||||
invoice.Add(new XElement("MailSubject", new XCData(MailSubject)));
|
||||
if (!string.IsNullOrEmpty(MailBody))
|
||||
invoice.Add(new XElement("MailBody", new XCData(MailBody)));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Eredetiszamla))
|
||||
invoice.Add(new XElement("Eredetiszamla", new XCData(Eredetiszamla)));
|
||||
|
||||
// Add items
|
||||
foreach (var item in Items)
|
||||
{
|
||||
var tetel = new XElement("tetel");
|
||||
tetel.Add(new XElement("TetelNev", new XCData(item.TetelNev ?? "")));
|
||||
tetel.Add(new XElement("AfaSzoveg", item.AfaSzoveg ?? ""));
|
||||
tetel.Add(new XElement("Brutto", item.Brutto ? "1" : "0"));
|
||||
tetel.Add(new XElement("EgysegAr", item.EgysegAr.ToString()));
|
||||
tetel.Add(new XElement("Mennyiseg", item.Mennyiseg.ToString()));
|
||||
tetel.Add(new XElement("MennyisegEgyseg", new XCData(item.MennyisegEgyseg ?? "")));
|
||||
|
||||
if (item.KedvezmenyOsszeg.HasValue)
|
||||
tetel.Add(new XElement("KedvezmenyOsszeg", item.KedvezmenyOsszeg.Value.ToString()));
|
||||
if (item.TermekID.HasValue)
|
||||
tetel.Add(new XElement("TermekID", item.TermekID.Value.ToString()));
|
||||
if (!string.IsNullOrEmpty(item.Megjegyzes))
|
||||
tetel.Add(new XElement("Megjegyzes", new XCData(item.Megjegyzes)));
|
||||
if (!string.IsNullOrEmpty(item.CikkSzam))
|
||||
tetel.Add(new XElement("CikkSzam", new XCData(item.CikkSzam)));
|
||||
if (!string.IsNullOrEmpty(item.VTSZSZJ))
|
||||
tetel.Add(new XElement("VTSZSZJ", new XCData(item.VTSZSZJ)));
|
||||
if (item.ElolegSzamlaTABLE_ID.HasValue)
|
||||
tetel.Add(new XElement("ElolegSzamlaTABLE_ID", item.ElolegSzamlaTABLE_ID.Value.ToString()));
|
||||
if (!string.IsNullOrEmpty(item.ElolegSzamlaSorszam))
|
||||
tetel.Add(new XElement("ElolegSzamlaSorszam", new XCData(item.ElolegSzamlaSorszam)));
|
||||
|
||||
invoice.Add(tetel);
|
||||
}
|
||||
|
||||
invoices.Add(invoice);
|
||||
return new XDeclaration("1.0", "UTF-8", null).ToString() + "\n" + invoices.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class InvoiceItem
|
||||
{
|
||||
public string TetelNev { get; set; }
|
||||
public string AfaSzoveg { get; set; }
|
||||
public bool Brutto { get; set; }
|
||||
public decimal EgysegAr { get; set; }
|
||||
public decimal Mennyiseg { get; set; }
|
||||
public string MennyisegEgyseg { get; set; }
|
||||
public decimal? KedvezmenyOsszeg { get; set; }
|
||||
public int? TermekID { get; set; }
|
||||
public string Megjegyzes { get; set; }
|
||||
public string CikkSzam { get; set; }
|
||||
public string VTSZSZJ { get; set; }
|
||||
public int? ElolegSzamlaTABLE_ID { get; set; }
|
||||
public string ElolegSzamlaSorszam { get; set; }
|
||||
}
|
||||
|
||||
public class InvoiceCreateResponse
|
||||
{
|
||||
public string ErrorCode { get; set; }
|
||||
public string Message { get; set; }
|
||||
public int? TableId { get; set; }
|
||||
public int? VevoID { get; set; }
|
||||
public string TechId { get; set; }
|
||||
public string Sorszam { get; set; }
|
||||
public string PrintUrl { get; set; }
|
||||
|
||||
public bool IsSuccess => ErrorCode == "200";
|
||||
|
||||
public static InvoiceCreateResponse FromXml(string xml)
|
||||
{
|
||||
var doc = XDocument.Parse(xml);
|
||||
var invoice = doc.Descendants("invoice").FirstOrDefault();
|
||||
|
||||
if (invoice == null)
|
||||
{
|
||||
throw new InnVoiceApiException("Invalid XML response format");
|
||||
}
|
||||
|
||||
return new InvoiceCreateResponse
|
||||
{
|
||||
ErrorCode = invoice.Element("error")?.Value,
|
||||
Message = invoice.Element("message")?.Value?.Trim(),
|
||||
TableId = int.TryParse(invoice.Element("TABLE_ID")?.Value?.Trim(), out var tid) ? tid : (int?)null,
|
||||
VevoID = int.TryParse(invoice.Element("VevoID")?.Value?.Trim(), out var vid) ? vid : (int?)null,
|
||||
TechId = invoice.Element("techid")?.Value?.Trim(),
|
||||
Sorszam = invoice.Element("Sorszam")?.Value?.Trim(),
|
||||
PrintUrl = invoice.Element("PrintUrl")?.Value?.Trim()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new invoice
|
||||
/// </summary>
|
||||
public async Task<InvoiceCreateResponse> CreateInvoiceAsync(InvoiceCreateRequest request)
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice";
|
||||
{
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice";
|
||||
|
||||
var xml = request.ToXml();
|
||||
var content = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("data", xml)
|
||||
});
|
||||
var xml = request.ToXml();
|
||||
var content = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("data", xml)
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
return InvoiceCreateResponse.FromXml(responseContent);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error creating invoice: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
return InvoiceCreateResponse.FromXml(responseContent);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error creating invoice: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update an existing invoice
|
||||
/// </summary>
|
||||
public async Task<InvoiceCreateResponse> UpdateInvoiceAsync(int tableId, InvoiceCreateRequest request)
|
||||
{
|
||||
// Set the VevoID if updating customer information
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice";
|
||||
/// <summary>
|
||||
/// Update an existing invoice
|
||||
/// </summary>
|
||||
public async Task<InvoiceCreateResponse> UpdateInvoiceAsync(int tableId, InvoiceCreateRequest request)
|
||||
{
|
||||
// Set the VevoID if updating customer information
|
||||
var url = $"{_baseUrl}/{_companyName}/invoice";
|
||||
|
||||
var xml = request.ToXml();
|
||||
var content = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("data", xml),
|
||||
new KeyValuePair<string, string>("id", tableId.ToString())
|
||||
});
|
||||
var xml = request.ToXml();
|
||||
var content = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("data", xml),
|
||||
new KeyValuePair<string, string>("id", tableId.ToString())
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.PostAsync(url, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
return InvoiceCreateResponse.FromXml(responseContent);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error updating invoice: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
return InvoiceCreateResponse.FromXml(responseContent);
|
||||
}
|
||||
catch (HttpRequestException ex)
|
||||
{
|
||||
throw new InnVoiceApiException($"Error updating invoice: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Models
|
||||
public class Invoice
|
||||
{
|
||||
public int TableId { get; set; }
|
||||
public int VevoID { get; set; }
|
||||
public string CustomerName { get; set; }
|
||||
public string CustomerZipCode { get; set; }
|
||||
public string CustomerCity { get; set; }
|
||||
public string CustomerAddress { get; set; }
|
||||
public string CustomerCountry { get; set; }
|
||||
public string CustomerTaxNumber { get; set; }
|
||||
public string CustomerGroupTaxNumber { get; set; }
|
||||
public string PaymentMethod { get; set; }
|
||||
public string FulfillmentDate { get; set; }
|
||||
public string InvoiceDate { get; set; }
|
||||
public string DueDate { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Currency { get; set; }
|
||||
public bool IsDraft { get; set; }
|
||||
public bool IsCancelled { get; set; }
|
||||
public bool IsAdvance { get; set; }
|
||||
public bool IsProforma { get; set; }
|
||||
public decimal TotalNet { get; set; }
|
||||
public decimal TotalVAT { get; set; }
|
||||
public decimal TotalGross { get; set; }
|
||||
public decimal OutstandingAmount { get; set; }
|
||||
public decimal OverdueAmount { get; set; }
|
||||
public decimal PaidAmount { get; set; }
|
||||
public string InvoiceNumber { get; set; }
|
||||
public string InvoiceNumberFormatted { get; set; }
|
||||
public int InvoiceId { get; set; }
|
||||
public string UniqueId { get; set; }
|
||||
public decimal ExchangeRate { get; set; }
|
||||
public int InvoiceBookId { get; set; }
|
||||
public string InvoiceBookName { get; set; }
|
||||
public bool IsElectronic { get; set; }
|
||||
public string Phone { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string UpdateTime { get; set; }
|
||||
public string QueryTime { get; set; }
|
||||
public string OrderNumber { get; set; }
|
||||
public string OrderDate { get; set; }
|
||||
public string ShippingName { get; set; }
|
||||
public string ShippingZipCode { get; set; }
|
||||
public string ShippingCity { get; set; }
|
||||
public string ShippingAddress { get; set; }
|
||||
public string ShippingCountry { get; set; }
|
||||
public string PrintUrl { get; set; }
|
||||
public string InvoiceLink { get; set; }
|
||||
public string HealthFundName { get; set; }
|
||||
public string HealthFundCode { get; set; }
|
||||
|
||||
public List<InvoiceLineItem> Items { get; set; } = new List<InvoiceLineItem>();
|
||||
}
|
||||
|
||||
public class InvoiceLineItem
|
||||
{
|
||||
public int TableId { get; set; }
|
||||
public string ItemName { get; set; }
|
||||
public string ArticleNumber { get; set; }
|
||||
public string VTSZSZJ { get; set; }
|
||||
public string VATText { get; set; }
|
||||
public decimal VATRate { get; set; }
|
||||
public bool IsGross { get; set; }
|
||||
public decimal UnitPrice { get; set; }
|
||||
public decimal Quantity { get; set; }
|
||||
public string Unit { get; set; }
|
||||
public int ProductId { get; set; }
|
||||
public decimal DiscountAmount { get; set; }
|
||||
}
|
||||
|
||||
|
||||
// Invoice Creation Models
|
||||
public class InvoiceCreateRequest
|
||||
{
|
||||
public int VevoID { get; set; } = 0;
|
||||
public string VevoNev { get; set; }
|
||||
public string VevoIrsz { get; set; }
|
||||
public string VevoOrszag { get; set; }
|
||||
public string VevoTelep { get; set; }
|
||||
public string VevoUtcaHsz { get; set; }
|
||||
public string VevoEPNev { get; set; }
|
||||
public string VevoEPKod { get; set; }
|
||||
public string SzallNev { get; set; }
|
||||
public string SzallIrsz { get; set; }
|
||||
public string SzallTelep { get; set; }
|
||||
public string SzallUtcaHsz { get; set; }
|
||||
public string SzallOrszag { get; set; }
|
||||
public int SzamlatombID { get; set; }
|
||||
public DateTime SzamlaKelte { get; set; }
|
||||
public DateTime TeljesitesKelte { get; set; }
|
||||
public DateTime Hatarido { get; set; }
|
||||
public string Devizanem { get; set; }
|
||||
public string FizetesiMod { get; set; }
|
||||
public string Megjegyzes { get; set; }
|
||||
public string Nyelv1 { get; set; }
|
||||
public string Nyelv2 { get; set; }
|
||||
public decimal? Arfolyam { get; set; }
|
||||
public string ArfolyamDeviza { get; set; }
|
||||
public bool Fizetve { get; set; }
|
||||
public bool Eszamla { get; set; }
|
||||
public string VevoAdoszam { get; set; }
|
||||
public string VevoCsAdoszam { get; set; }
|
||||
public string Telefon { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string MegrendelesSzamStr { get; set; }
|
||||
public string MegrendelesIdopontStr { get; set; }
|
||||
public bool Felretett { get; set; }
|
||||
public bool Proforma { get; set; }
|
||||
public bool AutomatikusAr { get; set; }
|
||||
public bool Eloleg { get; set; }
|
||||
public bool Sendmail { get; set; }
|
||||
public string MailSubject { get; set; }
|
||||
public string MailBody { get; set; }
|
||||
public string Eredetiszamla { get; set; }
|
||||
|
||||
public List<InvoiceItem> Items { get; set; } = new List<InvoiceItem>();
|
||||
|
||||
public void AddItem(InvoiceItem item)
|
||||
{
|
||||
Items.Add(item);
|
||||
}
|
||||
|
||||
public string ToXml()
|
||||
{
|
||||
var invoices = new XElement("invoices");
|
||||
var invoice = new XElement("invoice");
|
||||
|
||||
if (VevoID > 0)
|
||||
invoice.Add(new XElement("VevoID", new XCData(VevoID.ToString())));
|
||||
|
||||
invoice.Add(new XElement("VevoNev", new XCData(VevoNev ?? "")));
|
||||
invoice.Add(new XElement("VevoIrsz", new XCData(VevoIrsz ?? "")));
|
||||
invoice.Add(new XElement("VevoTelep", new XCData(VevoTelep ?? "")));
|
||||
invoice.Add(new XElement("VevoOrszag", new XCData(VevoOrszag ?? "")));
|
||||
invoice.Add(new XElement("VevoUtcaHsz", new XCData(VevoUtcaHsz ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(VevoEPNev))
|
||||
invoice.Add(new XElement("VevoEPNev", new XCData(VevoEPNev)));
|
||||
if (!string.IsNullOrEmpty(VevoEPKod))
|
||||
invoice.Add(new XElement("VevoEPKod", new XCData(VevoEPKod)));
|
||||
if (!string.IsNullOrEmpty(SzallNev))
|
||||
invoice.Add(new XElement("SzallNev", new XCData(SzallNev)));
|
||||
if (!string.IsNullOrEmpty(SzallIrsz))
|
||||
invoice.Add(new XElement("SzallIrsz", new XCData(SzallIrsz)));
|
||||
if (!string.IsNullOrEmpty(SzallTelep))
|
||||
invoice.Add(new XElement("SzallTelep", new XCData(SzallTelep)));
|
||||
if (!string.IsNullOrEmpty(SzallUtcaHsz))
|
||||
invoice.Add(new XElement("SzallUtcaHsz", new XCData(SzallUtcaHsz)));
|
||||
if (!string.IsNullOrEmpty(SzallOrszag))
|
||||
invoice.Add(new XElement("SzallOrszag", new XCData(SzallOrszag)));
|
||||
|
||||
invoice.Add(new XElement("SzamlatombID", new XCData(SzamlatombID.ToString())));
|
||||
invoice.Add(new XElement("SzamlaKelte", new XCData(SzamlaKelte.ToString("yyyy.MM.dd."))));
|
||||
invoice.Add(new XElement("TeljesitesKelte", new XCData(TeljesitesKelte.ToString("yyyy.MM.dd."))));
|
||||
invoice.Add(new XElement("Hatarido", new XCData(Hatarido.ToString("yyyy.MM.dd."))));
|
||||
invoice.Add(new XElement("Devizanem", new XCData(Devizanem ?? "")));
|
||||
invoice.Add(new XElement("FizetesiMod", new XCData(FizetesiMod ?? "")));
|
||||
|
||||
if (!string.IsNullOrEmpty(Megjegyzes))
|
||||
invoice.Add(new XElement("Megjegyzes", new XCData(Megjegyzes)));
|
||||
if (!string.IsNullOrEmpty(Nyelv1))
|
||||
invoice.Add(new XElement("Nyelv1", new XCData(Nyelv1)));
|
||||
if (!string.IsNullOrEmpty(Nyelv2))
|
||||
invoice.Add(new XElement("Nyelv2", new XCData(Nyelv2)));
|
||||
if (Arfolyam.HasValue)
|
||||
invoice.Add(new XElement("Arfolyam", new XCData(Arfolyam.Value.ToString())));
|
||||
if (!string.IsNullOrEmpty(ArfolyamDeviza))
|
||||
invoice.Add(new XElement("ArfolyamDeviza", new XCData(ArfolyamDeviza)));
|
||||
|
||||
invoice.Add(new XElement("Fizetve", Fizetve ? "1" : "0"));
|
||||
invoice.Add(new XElement("Eszamla", Eszamla ? "1" : "0"));
|
||||
|
||||
if (!string.IsNullOrEmpty(VevoAdoszam))
|
||||
invoice.Add(new XElement("VevoAdoszam", new XCData(VevoAdoszam)));
|
||||
if (!string.IsNullOrEmpty(VevoCsAdoszam))
|
||||
invoice.Add(new XElement("VevoCsAdoszam", new XCData(VevoCsAdoszam)));
|
||||
if (!string.IsNullOrEmpty(Telefon))
|
||||
invoice.Add(new XElement("Telefon", new XCData(Telefon)));
|
||||
if (!string.IsNullOrEmpty(Email))
|
||||
invoice.Add(new XElement("Email", new XCData(Email)));
|
||||
if (!string.IsNullOrEmpty(MegrendelesSzamStr))
|
||||
invoice.Add(new XElement("MegrendelesSzamStr", new XCData(MegrendelesSzamStr)));
|
||||
if (!string.IsNullOrEmpty(MegrendelesIdopontStr))
|
||||
invoice.Add(new XElement("MegrendelesIdopontStr", new XCData(MegrendelesIdopontStr)));
|
||||
|
||||
invoice.Add(new XElement("Felretett", Felretett ? "1" : "0"));
|
||||
invoice.Add(new XElement("Proforma", Proforma ? "1" : "0"));
|
||||
|
||||
if (AutomatikusAr)
|
||||
invoice.Add(new XElement("AutomatikusAr", "1"));
|
||||
if (Eloleg)
|
||||
invoice.Add(new XElement("Eloleg", "1"));
|
||||
if (Sendmail)
|
||||
{
|
||||
invoice.Add(new XElement("Sendmail", "1"));
|
||||
if (!string.IsNullOrEmpty(MailSubject))
|
||||
invoice.Add(new XElement("MailSubject", new XCData(MailSubject)));
|
||||
if (!string.IsNullOrEmpty(MailBody))
|
||||
invoice.Add(new XElement("MailBody", new XCData(MailBody)));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(Eredetiszamla))
|
||||
invoice.Add(new XElement("Eredetiszamla", new XCData(Eredetiszamla)));
|
||||
|
||||
// Add items
|
||||
foreach (var item in Items)
|
||||
{
|
||||
var tetel = new XElement("tetel");
|
||||
tetel.Add(new XElement("TetelNev", new XCData(item.TetelNev ?? "")));
|
||||
tetel.Add(new XElement("AfaSzoveg", item.AfaSzoveg ?? ""));
|
||||
tetel.Add(new XElement("Brutto", item.Brutto ? "1" : "0"));
|
||||
tetel.Add(new XElement("EgysegAr", item.EgysegAr.ToString()));
|
||||
tetel.Add(new XElement("Mennyiseg", item.Mennyiseg.ToString()));
|
||||
tetel.Add(new XElement("MennyisegEgyseg", new XCData(item.MennyisegEgyseg ?? "")));
|
||||
|
||||
if (item.KedvezmenyOsszeg.HasValue)
|
||||
tetel.Add(new XElement("KedvezmenyOsszeg", item.KedvezmenyOsszeg.Value.ToString()));
|
||||
if (item.TermekID.HasValue)
|
||||
tetel.Add(new XElement("TermekID", item.TermekID.Value.ToString()));
|
||||
if (!string.IsNullOrEmpty(item.Megjegyzes))
|
||||
tetel.Add(new XElement("Megjegyzes", new XCData(item.Megjegyzes)));
|
||||
if (!string.IsNullOrEmpty(item.CikkSzam))
|
||||
tetel.Add(new XElement("CikkSzam", new XCData(item.CikkSzam)));
|
||||
if (!string.IsNullOrEmpty(item.VTSZSZJ))
|
||||
tetel.Add(new XElement("VTSZSZJ", new XCData(item.VTSZSZJ)));
|
||||
if (item.ElolegSzamlaTABLE_ID.HasValue)
|
||||
tetel.Add(new XElement("ElolegSzamlaTABLE_ID", item.ElolegSzamlaTABLE_ID.Value.ToString()));
|
||||
if (!string.IsNullOrEmpty(item.ElolegSzamlaSorszam))
|
||||
tetel.Add(new XElement("ElolegSzamlaSorszam", new XCData(item.ElolegSzamlaSorszam)));
|
||||
|
||||
invoice.Add(tetel);
|
||||
}
|
||||
|
||||
invoices.Add(invoice);
|
||||
return new XDeclaration("1.0", "UTF-8", null).ToString() + "\n" + invoices.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class InvoiceItem
|
||||
{
|
||||
public string TetelNev { get; set; }
|
||||
public string AfaSzoveg { get; set; }
|
||||
public bool Brutto { get; set; }
|
||||
public decimal EgysegAr { get; set; }
|
||||
public decimal Mennyiseg { get; set; }
|
||||
public string MennyisegEgyseg { get; set; }
|
||||
public decimal? KedvezmenyOsszeg { get; set; }
|
||||
public int? TermekID { get; set; }
|
||||
public string Megjegyzes { get; set; }
|
||||
public string CikkSzam { get; set; }
|
||||
public string VTSZSZJ { get; set; }
|
||||
public int? ElolegSzamlaTABLE_ID { get; set; }
|
||||
public string ElolegSzamlaSorszam { get; set; }
|
||||
}
|
||||
|
||||
public class InvoiceCreateResponse
|
||||
{
|
||||
public string ErrorCode { get; set; }
|
||||
public string Message { get; set; }
|
||||
public int? TableId { get; set; }
|
||||
public int? VevoID { get; set; }
|
||||
public string TechId { get; set; }
|
||||
public string Sorszam { get; set; }
|
||||
public string PrintUrl { get; set; }
|
||||
|
||||
public bool IsSuccess => ErrorCode == "200";
|
||||
|
||||
public static InvoiceCreateResponse FromXml(string xml)
|
||||
{
|
||||
var doc = XDocument.Parse(xml);
|
||||
var invoice = doc.Descendants("invoice").FirstOrDefault();
|
||||
|
||||
if (invoice == null)
|
||||
{
|
||||
throw new InnVoiceApiException("Invalid XML response format");
|
||||
}
|
||||
|
||||
return new InvoiceCreateResponse
|
||||
{
|
||||
ErrorCode = invoice.Element("error")?.Value,
|
||||
Message = invoice.Element("message")?.Value?.Trim(),
|
||||
TableId = int.TryParse(invoice.Element("TABLE_ID")?.Value?.Trim(), out var tid) ? tid : (int?)null,
|
||||
VevoID = int.TryParse(invoice.Element("VevoID")?.Value?.Trim(), out var vid) ? vid : (int?)null,
|
||||
TechId = invoice.Element("techid")?.Value?.Trim(),
|
||||
Sorszam = invoice.Element("Sorszam")?.Value?.Trim(),
|
||||
PrintUrl = invoice.Element("PrintUrl")?.Value?.Trim()
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,44 @@
|
|||
@using Nop.Plugin.Misc.FruitBankPlugin.Models.Orders
|
||||
@model OrderAttributesModel
|
||||
|
||||
<!-- InnVoice Invoice Section -->
|
||||
<!-- InnVoice Management Section -->
|
||||
<div class="card card-default mb-3">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-file-invoice"></i>
|
||||
InnVoice Invoice Management
|
||||
InnVoice Management
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<!-- Order Subsection -->
|
||||
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<div class="col-12 col-md-3">
|
||||
<h5><i class="fas fa-shopping-cart"></i> Order</h5>
|
||||
<div id="orderStatus" class="alert alert-info" style="display: none;">
|
||||
<i class="fas fa-info-circle"></i> <span id="orderStatusMessage"></span>
|
||||
</div>
|
||||
<div id="orderDetails" style="display: none;">
|
||||
<p><strong>Order Table ID:</strong> <span id="orderTableId"></span></p>
|
||||
<p><strong>Order Tech ID:</strong> <span id="orderTechId"></span></p>
|
||||
<p>
|
||||
<a id="orderPdfLink" href="#" target="_blank" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-file-pdf"></i> View Order PDF
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-3 text-right">
|
||||
<button type="button" id="createOrderBtn" class="btn btn-success">
|
||||
<i class="fas fa-shopping-cart"></i> Create Order in InnVoice
|
||||
</button>
|
||||
<button type="button" id="checkOrderBtn" class="btn btn-secondary" style="display: none;">
|
||||
<i class="fas fa-sync"></i> Refresh Order
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-3">
|
||||
<h5><i class="fas fa-file-invoice-dollar"></i> Invoice</h5>
|
||||
<div id="invoiceStatus" class="alert alert-info" style="display: none;">
|
||||
<i class="fas fa-info-circle"></i> <span id="invoiceStatusMessage"></span>
|
||||
</div>
|
||||
|
|
@ -18,62 +47,66 @@
|
|||
<p><strong>Table ID:</strong> <span id="invoiceTableId"></span></p>
|
||||
<p>
|
||||
<a id="invoicePdfLink" href="#" target="_blank" class="btn btn-sm btn-info">
|
||||
<i class="fas fa-file-pdf"></i> View PDF
|
||||
<i class="fas fa-file-pdf"></i> View Invoice PDF
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 text-right">
|
||||
|
||||
<div class="col-12 col-md-3 text-right">
|
||||
<button type="button" id="createInvoiceBtn" class="btn btn-success">
|
||||
<i class="fas fa-file-invoice-dollar"></i> Create & Upload Invoice
|
||||
<i class="fas fa-file-invoice-dollar"></i> Create Invoice
|
||||
</button>
|
||||
<button type="button" id="checkInvoiceBtn" class="btn btn-secondary" style="display: none;">
|
||||
<i class="fas fa-sync"></i> Check Invoice Status
|
||||
<i class="fas fa-sync"></i> Refresh Invoice
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-12">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-3">
|
||||
<nop-label asp-for="IsMeasurable" />
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<nop-editor asp-for="IsMeasurable" />
|
||||
<span asp-validation-for="IsMeasurable"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-3">
|
||||
<nop-label asp-for="DateOfReceipt" />
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<nop-editor asp-for="DateOfReceipt" />
|
||||
<span asp-validation-for="DateOfReceipt"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 text-right">
|
||||
<button type="button" id="saveAttributesBtn" class="btn btn-primary">
|
||||
<i class="fa fa-save"></i> Save Attributes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Order Attributes Section -->
|
||||
<div class="card card-default">
|
||||
<div class="card-header">
|
||||
<i class="fas fa-tags"></i>
|
||||
Custom Order Attributes
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-3">
|
||||
<nop-label asp-for="IsMeasurable" />
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<nop-editor asp-for="IsMeasurable" />
|
||||
<span asp-validation-for="IsMeasurable"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-3">
|
||||
<nop-label asp-for="DateOfReceipt" />
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<nop-editor asp-for="DateOfReceipt" />
|
||||
<span asp-validation-for="DateOfReceipt"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 text-right">
|
||||
<button type="button" id="saveAttributesBtn" class="btn btn-primary">
|
||||
<i class="fa fa-save"></i> Save Attributes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
var createOrderUrl = '/Admin/InnVoiceOrder/CreateOrder';
|
||||
var getOrderStatusUrl = '/Admin/InnVoiceOrder/GetOrderStatus';
|
||||
var createInvoiceUrl = '/Admin/Invoice/CreateInvoice';
|
||||
var getInvoiceStatusUrl = '/Admin/Invoice/GetInvoiceStatus';
|
||||
|
||||
var orderExists = false;
|
||||
var invoiceExists = false;
|
||||
|
||||
// Save Order Attributes
|
||||
$("#saveAttributesBtn").click(function () {
|
||||
$.ajax({
|
||||
|
|
@ -94,8 +127,148 @@
|
|||
});
|
||||
});
|
||||
|
||||
// ========== ORDER MANAGEMENT ==========
|
||||
|
||||
// Create Order
|
||||
$("#createOrderBtn").click(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var btn = $(this);
|
||||
btn.prop("disabled", true).html('<i class="fas fa-spinner fa-spin"></i> Creating Order...');
|
||||
|
||||
showOrderStatus("Creating order in InnVoice, please wait...", "info");
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: createOrderUrl,
|
||||
data: { orderId: @Model.OrderId },
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
console.log("Order Response:", response);
|
||||
btn.prop("disabled", false).html('<i class="fas fa-shopping-cart"></i> Create Order in InnVoice');
|
||||
|
||||
if (response.success) {
|
||||
showOrderStatus("Order created successfully in InnVoice!", "success");
|
||||
displayOrderDetails(response.data);
|
||||
orderExists = true;
|
||||
updateOrderButtons();
|
||||
} else {
|
||||
showOrderStatus("Error: " + (response.message || "Unknown error"), "danger");
|
||||
}
|
||||
},
|
||||
error: function (xhr, status, error) {
|
||||
console.error("Order AJAX Error:", xhr, status, error);
|
||||
btn.prop("disabled", false).html('<i class="fas fa-shopping-cart"></i> Create Order in InnVoice');
|
||||
|
||||
var errorMessage = "Error creating order";
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
errorMessage = xhr.responseJSON.message;
|
||||
} else if (xhr.responseText) {
|
||||
try {
|
||||
var errorObj = JSON.parse(xhr.responseText);
|
||||
errorMessage = errorObj.message || errorMessage;
|
||||
} catch (e) {
|
||||
errorMessage = "Error: " + xhr.status + " - " + xhr.statusText;
|
||||
}
|
||||
}
|
||||
showOrderStatus(errorMessage, "danger");
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Check Order Status
|
||||
$("#checkOrderBtn").click(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var btn = $(this);
|
||||
btn.prop("disabled", true).html('<i class="fas fa-spinner fa-spin"></i> Checking...');
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: getOrderStatusUrl,
|
||||
data: { orderId: @Model.OrderId },
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
btn.prop("disabled", false).html('<i class="fas fa-sync"></i> Refresh Order');
|
||||
|
||||
if (response.success && response.data) {
|
||||
displayOrderDetails(response.data);
|
||||
showOrderStatus("Order details refreshed", "success");
|
||||
} else {
|
||||
showOrderStatus("No order found in InnVoice for this order", "warning");
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false).html('<i class="fas fa-sync"></i> Refresh Order');
|
||||
showOrderStatus("Error checking order status", "danger");
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
function showOrderStatus(message, type) {
|
||||
var statusDiv = $("#orderStatus");
|
||||
statusDiv.removeClass("alert-info alert-success alert-warning alert-danger")
|
||||
.addClass("alert-" + type);
|
||||
$("#orderStatusMessage").text(message);
|
||||
statusDiv.show();
|
||||
}
|
||||
|
||||
function displayOrderDetails(data) {
|
||||
$("#orderTableId").text(data.tableId || "N/A");
|
||||
$("#orderTechId").text(data.techId || "N/A");
|
||||
|
||||
if (data.printUrl) {
|
||||
$("#orderPdfLink").attr("href", data.printUrl).show();
|
||||
} else {
|
||||
$("#orderPdfLink").hide();
|
||||
}
|
||||
|
||||
$("#orderDetails").show();
|
||||
}
|
||||
|
||||
function updateOrderButtons() {
|
||||
if (orderExists) {
|
||||
$("#createOrderBtn").hide();
|
||||
$("#checkOrderBtn").show();
|
||||
} else {
|
||||
$("#createOrderBtn").show();
|
||||
$("#checkOrderBtn").hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if order exists on page load
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: getOrderStatusUrl,
|
||||
data: { orderId: @Model.OrderId },
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
if (response.success && response.data) {
|
||||
displayOrderDetails(response.data);
|
||||
orderExists = true;
|
||||
updateOrderButtons();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
// Silently fail on page load
|
||||
orderExists = false;
|
||||
updateOrderButtons();
|
||||
}
|
||||
});
|
||||
|
||||
// ========== INVOICE MANAGEMENT ==========
|
||||
|
||||
// Create Invoice
|
||||
$("#createInvoiceBtn").click(function () {
|
||||
$("#createInvoiceBtn").click(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var btn = $(this);
|
||||
btn.prop("disabled", true).html('<i class="fas fa-spinner fa-spin"></i> Creating Invoice...');
|
||||
|
||||
|
|
@ -103,60 +276,74 @@
|
|||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "@Url.Action("CreateInvoice", "InnVoice")",
|
||||
data: {
|
||||
orderId: "@Model.OrderId",
|
||||
__RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val()
|
||||
},
|
||||
url: createInvoiceUrl,
|
||||
data: { orderId: @Model.OrderId },
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
btn.prop("disabled", false).html('<i class="fas fa-file-invoice-dollar"></i> Create & Upload Invoice');
|
||||
console.log("Invoice Response:", response);
|
||||
btn.prop("disabled", false).html('<i class="fas fa-file-invoice-dollar"></i> Create Invoice');
|
||||
|
||||
if (response.success) {
|
||||
showInvoiceStatus("Invoice created successfully!", "success");
|
||||
displayInvoiceDetails(response.data);
|
||||
$("#checkInvoiceBtn").show();
|
||||
invoiceExists = true;
|
||||
updateInvoiceButtons();
|
||||
} else {
|
||||
showInvoiceStatus("Error: " + response.message, "danger");
|
||||
showInvoiceStatus("Error: " + (response.message || "Unknown error"), "danger");
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
btn.prop("disabled", false).html('<i class="fas fa-file-invoice-dollar"></i> Create & Upload Invoice');
|
||||
error: function (xhr, status, error) {
|
||||
console.error("Invoice AJAX Error:", xhr, status, error);
|
||||
btn.prop("disabled", false).html('<i class="fas fa-file-invoice-dollar"></i> Create Invoice');
|
||||
|
||||
var errorMessage = "Error creating invoice";
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
errorMessage = xhr.responseJSON.message;
|
||||
} else if (xhr.responseText) {
|
||||
try {
|
||||
var errorObj = JSON.parse(xhr.responseText);
|
||||
errorMessage = errorObj.message || errorMessage;
|
||||
} catch (e) {
|
||||
errorMessage = "Error: " + xhr.status + " - " + xhr.statusText;
|
||||
}
|
||||
}
|
||||
showInvoiceStatus(errorMessage, "danger");
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// Check Invoice Status
|
||||
$("#checkInvoiceBtn").click(function () {
|
||||
$("#checkInvoiceBtn").click(function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var btn = $(this);
|
||||
btn.prop("disabled", true).html('<i class="fas fa-spinner fa-spin"></i> Checking...');
|
||||
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "@Url.Action("GetInvoiceStatus", "InnVoice")",
|
||||
data: {
|
||||
orderId: "@Model.OrderId"
|
||||
},
|
||||
url: getInvoiceStatusUrl,
|
||||
data: { orderId: @Model.OrderId },
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
btn.prop("disabled", false).html('<i class="fas fa-sync"></i> Check Invoice Status');
|
||||
btn.prop("disabled", false).html('<i class="fas fa-sync"></i> Refresh Invoice');
|
||||
|
||||
if (response.success && response.data) {
|
||||
displayInvoiceDetails(response.data);
|
||||
showInvoiceStatus("Invoice details loaded", "success");
|
||||
showInvoiceStatus("Invoice details refreshed", "success");
|
||||
} else {
|
||||
showInvoiceStatus("No invoice found for this order", "warning");
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
btn.prop("disabled", false).html('<i class="fas fa-sync"></i> Check Invoice Status');
|
||||
btn.prop("disabled", false).html('<i class="fas fa-sync"></i> Refresh Invoice');
|
||||
showInvoiceStatus("Error checking invoice status", "danger");
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
function showInvoiceStatus(message, type) {
|
||||
|
|
@ -180,19 +367,34 @@
|
|||
$("#invoiceDetails").show();
|
||||
}
|
||||
|
||||
function updateInvoiceButtons() {
|
||||
if (invoiceExists) {
|
||||
$("#createInvoiceBtn").hide();
|
||||
$("#checkInvoiceBtn").show();
|
||||
} else {
|
||||
$("#createInvoiceBtn").show();
|
||||
$("#checkInvoiceBtn").hide();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if invoice exists on page load
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: "@Url.Action("GetInvoiceStatus", "InnVoice")",
|
||||
data: {
|
||||
orderId: "@Model.OrderId"
|
||||
},
|
||||
url: getInvoiceStatusUrl,
|
||||
data: { orderId: @Model.OrderId },
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
if (response.success && response.data) {
|
||||
displayInvoiceDetails(response.data);
|
||||
$("#checkInvoiceBtn").show();
|
||||
invoiceExists = true;
|
||||
updateInvoiceButtons();
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
// Silently fail on page load
|
||||
invoiceExists = false;
|
||||
updateInvoiceButtons();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue