mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-18 22:44:29 +01:00
add invoicemetadata as a tab (#4693)
* add invocie metadata as a tab * Allow forms to add to posdata too in pos app * Cleanup view * Display additional information directly * Update BTCPayServer/Views/Shared/PosData.cshtml * Update BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs --------- Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
This commit is contained in:
@@ -106,6 +106,14 @@ namespace BTCPayServer.Controllers
|
||||
|
||||
var receipt = InvoiceDataBase.ReceiptOptions.Merge(store.GetStoreBlob().ReceiptOptions, invoice.ReceiptOptions);
|
||||
var invoiceState = invoice.GetInvoiceState();
|
||||
var posData = PosDataParser.ParsePosData(invoice.Metadata.PosData);
|
||||
var metaData = PosDataParser.ParsePosData(invoice.Metadata.ToJObject().ToString());
|
||||
var excludes = typeof(InvoiceMetadata).GetProperties()
|
||||
.Select(p => char.ToLowerInvariant(p.Name[0]) + p.Name[1..])
|
||||
.ToList();
|
||||
var additionalData = metaData
|
||||
.Where(dict => !excludes.Contains(dict.Key))
|
||||
.ToDictionary(dict=> dict.Key, dict=> dict.Value);
|
||||
var model = new InvoiceDetailsModel
|
||||
{
|
||||
StoreId = store.Id,
|
||||
@@ -131,7 +139,9 @@ namespace BTCPayServer.Controllers
|
||||
TypedMetadata = invoice.Metadata,
|
||||
StatusException = invoice.ExceptionStatus,
|
||||
Events = invoice.Events,
|
||||
PosData = PosDataParser.ParsePosData(invoice.Metadata.PosData),
|
||||
PosData = posData,
|
||||
Metadata = metaData,
|
||||
AdditionalData = additionalData,
|
||||
Archived = invoice.Archived,
|
||||
CanRefund = invoiceState.CanRefund(),
|
||||
Refunds = invoice.Refunds,
|
||||
|
||||
@@ -125,6 +125,8 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||
public List<Data.InvoiceEventData> Events { get; internal set; }
|
||||
public string NotificationEmail { get; internal set; }
|
||||
public Dictionary<string, object> PosData { get; set; }
|
||||
public Dictionary<string, object> Metadata { get; set; }
|
||||
public Dictionary<string, object> AdditionalData { get; set; }
|
||||
public List<PaymentEntity> Payments { get; set; }
|
||||
public bool Archived { get; set; }
|
||||
public bool CanRefund { get; set; }
|
||||
|
||||
@@ -299,12 +299,22 @@ namespace BTCPayServer.Plugins.PointOfSale.Controllers
|
||||
{
|
||||
entity.Metadata.OrderUrl = Request.GetDisplayUrl();
|
||||
|
||||
if (formResponseJObject is not null)
|
||||
{
|
||||
if (formResponseJObject is null) return;
|
||||
var meta = entity.Metadata.ToJObject();
|
||||
if (formResponseJObject.ContainsKey("posData") && meta.TryGetValue("posData", out var posDataValue) && posDataValue.Type == JTokenType.String)
|
||||
{
|
||||
try
|
||||
{
|
||||
meta["posData"] = JObject.Parse(posDataValue.Value<string>());
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// ignored as we don't want to break the invoice creation
|
||||
}
|
||||
}
|
||||
formResponseJObject.Merge(meta);
|
||||
entity.Metadata = InvoiceMetadata.FromJObject(formResponseJObject);
|
||||
}
|
||||
});
|
||||
return RedirectToAction(nameof(UIInvoiceController.Checkout), "UIInvoice", new { invoiceId = invoice.Data.Id });
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
@using BTCPayServer.Client.Models
|
||||
@model InvoiceDetailsModel
|
||||
@{
|
||||
ViewData["Title"] = $"Invoice {Model.Id}";
|
||||
@@ -9,6 +8,7 @@
|
||||
<style>
|
||||
#posData td > table:last-child { margin-bottom: 0 !important; }
|
||||
#posData table > tbody > tr:first-child > td > h4 { margin-top: 0 !important; }
|
||||
.invoice-information { display: flex; flex-wrap: wrap; gap: var(--btcpay-space-xl) var(--btcpay-space-xxl); }
|
||||
</style>
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="sticky-header-setup"></div>
|
||||
<div class="sticky-header d-flex flex-wrap gap-3 align-items-center justify-content-between">
|
||||
<h2 class="mb-0 text-break">@ViewData["Title"]</h2>
|
||||
@@ -126,10 +125,11 @@
|
||||
|
||||
<partial name="_StatusMessage"/>
|
||||
|
||||
<div class="row justify-content-between">
|
||||
<div class="col-md-6">
|
||||
<h3 class="mb-3">Invoice Information</h3>
|
||||
<table class="table mb-5">
|
||||
<div class="invoice-details">
|
||||
<div class="invoice-information mb-5">
|
||||
<div>
|
||||
<h3 class="mb-3">General Information</h3>
|
||||
<table class="table mb-0">
|
||||
<tr>
|
||||
<th class="fw-semibold">Store</th>
|
||||
<td>
|
||||
@@ -251,13 +251,13 @@
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
@if (Model.PosData.Count == 0)
|
||||
<div class="d-flex flex-column gap-5">
|
||||
@if (Model.PosData.Any())
|
||||
{
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<h3 class="mb-3">Product Information</h3>
|
||||
<table class="table mb-5">
|
||||
<table class="table mb-0">
|
||||
@if (!string.IsNullOrEmpty(Model.TypedMetadata.ItemCode))
|
||||
{
|
||||
<tr>
|
||||
@@ -294,13 +294,11 @@
|
||||
Model.TypedMetadata.BuyerCity is not null ||
|
||||
Model.TypedMetadata.BuyerState is not null ||
|
||||
Model.TypedMetadata.BuyerCountry is not null ||
|
||||
Model.TypedMetadata.BuyerZip is not null
|
||||
)
|
||||
Model.TypedMetadata.BuyerZip is not null)
|
||||
{
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<h3 class="mb-3">Buyer Information</h3>
|
||||
<div class="table-responsive-xl">
|
||||
<table class="table mb-5">
|
||||
<table class="table mb-0">
|
||||
@if (Model.TypedMetadata.BuyerName is not null)
|
||||
{
|
||||
<tr>
|
||||
@@ -368,44 +366,15 @@
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
@if (Model.AdditionalData.Any())
|
||||
{
|
||||
<div>
|
||||
<h3 class="mb-3">Additional Information</h3>
|
||||
<partial name="PosData" model="(Model.AdditionalData, 1)" />
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model.PosData.Count != 0)
|
||||
{
|
||||
<div class="col-md-6">
|
||||
<h3 class="mb-3">Product information</h3>
|
||||
<table class="table mb-5">
|
||||
@if (!string.IsNullOrEmpty(Model.TypedMetadata.ItemCode))
|
||||
{
|
||||
<tr>
|
||||
<th>Item code</th>
|
||||
<td>@Model.TypedMetadata.ItemCode</td>
|
||||
</tr>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(Model.TypedMetadata.ItemDesc))
|
||||
{
|
||||
<tr>
|
||||
<th>Item Description</th>
|
||||
<td>@Model.TypedMetadata.ItemDesc</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<th>Price</th>
|
||||
<td>@Model.Fiat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Tax included</th>
|
||||
<td>@Model.TaxIncluded</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6 mb-4" id="posData">
|
||||
<h3 class="mb-3">Point of Sale Data</h3>
|
||||
|
||||
<partial name="PosData" model="(Model.PosData, 1)"/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<h3 class="mb-0">Invoice Summary</h3>
|
||||
@@ -485,7 +454,6 @@
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if ((Model.Refunds?.Count ?? 0) > 0)
|
||||
{
|
||||
<h3 class="mb-3 mt-4">Refunds</h3>
|
||||
|
||||
Reference in New Issue
Block a user