Extracting payment details population, refactoring invoice data load

This commit is contained in:
rockstardev 2019-04-29 22:45:33 -05:00 committed by Nicolas Dorier
parent 3cd37682d3
commit 6918b8a291
5 changed files with 279 additions and 241 deletions

View File

@ -47,9 +47,9 @@ namespace BTCPayServer.Controllers
if (invoice == null)
return NotFound();
var dto = invoice.EntityToDTO(_NetworkProvider);
var prodInfo = invoice.ProductInformation;
var store = await _StoreRepository.FindStore(invoice.StoreId);
InvoiceDetailsModel model = new InvoiceDetailsModel()
var model = new InvoiceDetailsModel()
{
StoreName = store.StoreName,
StoreLink = Url.Action(nameof(StoresController.UpdateStore), "Stores", new { storeId = store.Id }),
@ -65,20 +65,39 @@ namespace BTCPayServer.Controllers
MonitoringDate = invoice.MonitoringExpiration,
OrderId = invoice.OrderId,
BuyerInformation = invoice.BuyerInformation,
Fiat = _CurrencyNameTable.DisplayFormatCurrency(dto.Price, dto.Currency),
TaxIncluded = _CurrencyNameTable.DisplayFormatCurrency(invoice.ProductInformation.TaxIncluded, dto.Currency),
Fiat = _CurrencyNameTable.DisplayFormatCurrency(prodInfo.Price, prodInfo.Currency),
TaxIncluded = _CurrencyNameTable.DisplayFormatCurrency(prodInfo.TaxIncluded, prodInfo.Currency),
NotificationEmail = invoice.NotificationEmail,
NotificationUrl = invoice.NotificationURL,
RedirectUrl = invoice.RedirectURL,
ProductInformation = invoice.ProductInformation,
StatusException = invoice.ExceptionStatus,
Events = invoice.Events,
PosData = PosDataParser.ParsePosData(dto.PosData)
PosData = PosDataParser.ParsePosData(invoice.PosData),
StatusMessage = StatusMessage
};
model.Addresses = invoice.HistoricalAddresses.Select(h => new InvoiceDetailsModel.AddressModel
{
Destination = h.GetAddress(),
PaymentMethod = ToString(h.GetPaymentMethodId()),
Current = !h.UnAssigned.HasValue
}).ToArray();
var details = await InvoicePopulatePayments(invoice);
model.CryptoPayments = details.CryptoPayments;
model.OnChainPayments = details.OnChainPayments;
model.OffChainPayments = details.OffChainPayments;
return View(model);
}
private async Task<InvoiceDetailsModel> InvoicePopulatePayments(InvoiceEntity invoice)
{
var model = new InvoiceDetailsModel();
foreach (var data in invoice.GetPaymentMethods(null))
{
var cryptoInfo = dto.CryptoInfo.First(o => o.GetpaymentMethodId() == data.GetId());
var accounting = data.Calculate();
var paymentMethodId = data.GetId();
var cryptoPayment = new InvoiceDetailsModel.CryptoPayment();
@ -93,7 +112,6 @@ namespace BTCPayServer.Controllers
cryptoPayment.Address = onchainMethod.DepositAddress;
}
cryptoPayment.Rate = ExchangeRate(data);
cryptoPayment.PaymentUrl = cryptoInfo.PaymentUrls.BIP21;
model.CryptoPayments.Add(cryptoPayment);
}
@ -149,16 +167,10 @@ namespace BTCPayServer.Controllers
})
.ToArray();
await Task.WhenAll(onChainPayments);
model.Addresses = invoice.HistoricalAddresses.Select(h => new InvoiceDetailsModel.AddressModel
{
Destination = h.GetAddress(),
PaymentMethod = ToString(h.GetPaymentMethodId()),
Current = !h.UnAssigned.HasValue
}).ToArray();
model.OnChainPayments = onChainPayments.Select(p => p.GetAwaiter().GetResult()).OfType<InvoiceDetailsModel.Payment>().ToList();
model.OffChainPayments = onChainPayments.Select(p => p.GetAwaiter().GetResult()).OfType<InvoiceDetailsModel.OffChainPayment>().ToList();
model.StatusMessage = StatusMessage;
return View(model);
return model;
}
private string ToString(PaymentMethodId paymentMethodId)
@ -494,7 +506,8 @@ namespace BTCPayServer.Controllers
RedirectUrl = invoice.RedirectURL ?? string.Empty,
AmountCurrency = _CurrencyNameTable.DisplayFormatCurrency(invoice.ProductInformation.Price, invoice.ProductInformation.Currency),
CanMarkInvalid = state.CanMarkInvalid(),
CanMarkComplete = state.CanMarkComplete()
CanMarkComplete = state.CanMarkComplete(),
Details = await InvoicePopulatePayments(invoice)
});
}
model.Total = await counting;

View File

@ -33,5 +33,7 @@ namespace BTCPayServer.Models.InvoicingModels
public string ExceptionStatus { get; set; }
public string AmountCurrency { get; set; }
public string StatusMessage { get; set; }
public InvoiceDetailsModel Details { get; set; }
}
}

View File

@ -42,257 +42,163 @@
</div>
</div>
<div class="row">
<div class="col-md-6">
<h3>Information</h3>
<table class="table table-sm table-responsive-md">
<tr>
<th>Store</th>
<td><a href="@Model.StoreLink">@Model.StoreName</a></td>
</tr>
<tr>
<th>Id</th>
<td>@Model.Id</td>
</tr>
<tr>
<th>State</th>
<td>@Model.State</td>
</tr>
<tr>
<th>Created date</th>
<td>@Model.CreatedDate.ToBrowserDate()</td>
</tr>
<tr>
<th>Expiration date</th>
<td>@Model.ExpirationDate.ToBrowserDate()</td>
</tr>
<tr>
<th>Monitoring date</th>
<td>@Model.MonitoringDate.ToBrowserDate()</td>
</tr>
<tr>
<th>Transaction speed</th>
<td>@Model.TransactionSpeed</td>
</tr>
<tr>
<th>Refund email</th>
<td><a href="mailto:@Model.RefundEmail">@Model.RefundEmail</a></td>
</tr>
<tr>
<th>Order Id</th>
<td>@Model.OrderId</td>
</tr>
<tr>
<th>Total fiat due</th>
<td>@Model.Fiat</td>
</tr>
<tr>
<th>Notification Email</th>
<td>@Model.NotificationEmail</td>
</tr>
<tr>
<th>Notification Url</th>
<td>@Model.NotificationUrl</td>
</tr>
<tr>
<th>Redirect Url</th>
<td><a href="@Model.RedirectUrl">@Model.RedirectUrl</a></td>
</tr>
</table>
</div>
<div class="col-md-6">
<h3>Buyer information</h3>
<table class="table table-sm table-responsive-md">
<tr>
<th>Name</th>
<td>@Model.BuyerInformation.BuyerName</td>
</tr>
<tr>
<th>Email</th>
<td><a href="mailto:@Model.BuyerInformation.BuyerEmail">@Model.BuyerInformation.BuyerEmail</a></td>
</tr>
<tr>
<th>Phone</th>
<td>@Model.BuyerInformation.BuyerPhone</td>
</tr>
<tr>
<th>Address 1</th>
<td>@Model.BuyerInformation.BuyerAddress1</td>
</tr>
<tr>
<th>Address 2</th>
<td>@Model.BuyerInformation.BuyerAddress2</td>
</tr>
<tr>
<th>City</th>
<td>@Model.BuyerInformation.BuyerCity</td>
</tr>
<tr>
<th>State</th>
<td>@Model.BuyerInformation.BuyerState</td>
</tr>
<tr>
<th>Country</th>
<td>@Model.BuyerInformation.BuyerCountry</td>
</tr>
<tr>
<th>Zip</th>
<td>@Model.BuyerInformation.BuyerZip</td>
</tr>
</table>
@if (Model.PosData.Count == 0)
{
<h3>Product information</h3>
<table class="table table-sm table-responsive-md">
<tr>
<th>Item code</th>
<td>@Model.ProductInformation.ItemCode</td>
</tr>
<tr>
<th>Item Description</th>
<td>@Model.ProductInformation.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>
@if (Model.PosData.Count != 0)
{
<div class="row">
<div class="col-md-6">
<h3>Product information</h3>
<h3>Information</h3>
<table class="table table-sm table-responsive-md">
<tr>
<th>Item code</th>
<td>@Model.ProductInformation.ItemCode</td>
<th>Store</th>
<td><a href="@Model.StoreLink">@Model.StoreName</a></td>
</tr>
<tr>
<th>Item Description</th>
<td>@Model.ProductInformation.ItemDesc</td>
<th>Id</th>
<td>@Model.Id</td>
</tr>
<tr>
<th>Price</th>
<th>State</th>
<td>@Model.State</td>
</tr>
<tr>
<th>Created date</th>
<td>@Model.CreatedDate.ToBrowserDate()</td>
</tr>
<tr>
<th>Expiration date</th>
<td>@Model.ExpirationDate.ToBrowserDate()</td>
</tr>
<tr>
<th>Monitoring date</th>
<td>@Model.MonitoringDate.ToBrowserDate()</td>
</tr>
<tr>
<th>Transaction speed</th>
<td>@Model.TransactionSpeed</td>
</tr>
<tr>
<th>Refund email</th>
<td><a href="mailto:@Model.RefundEmail">@Model.RefundEmail</a></td>
</tr>
<tr>
<th>Order Id</th>
<td>@Model.OrderId</td>
</tr>
<tr>
<th>Total fiat due</th>
<td>@Model.Fiat</td>
</tr>
<tr>
<th>Tax included</th>
<td>@Model.TaxIncluded</td>
<th>Notification Email</th>
<td>@Model.NotificationEmail</td>
</tr>
<tr>
<th>Notification Url</th>
<td>@Model.NotificationUrl</td>
</tr>
<tr>
<th>Redirect Url</th>
<td><a href="@Model.RedirectUrl">@Model.RedirectUrl</a></td>
</tr>
</table>
</div>
<div class="col-md-6">
<h3>Point of Sale Data</h3>
<partial name="PosData" model="@Model.PosData" />
</div>
</div>
}
<div class="row">
<div class="col-md-12">
<h3>Paid summary</h3>
<div class="col-md-6">
<h3>Buyer information</h3>
<table class="table table-sm table-responsive-md">
<thead class="thead-inverse">
<tr>
<th>Payment method</th>
<th>Address</th>
<th class="text-right">Rate</th>
<th class="text-right">Paid</th>
<th class="text-right">Due</th>
@if (Model.StatusException == InvoiceExceptionStatus.PaidOver)
{
<th class="text-right">Overpaid</th>
}
</tr>
</thead>
<tbody>
@foreach (var payment in Model.CryptoPayments)
{
<tr>
<td>@payment.PaymentMethod</td>
<td>@payment.Address</td>
<td class="text-right">@payment.Rate</td>
<td class="text-right">@payment.Paid</td>
<td class="text-right">@payment.Due</td>
@if (Model.StatusException == InvoiceExceptionStatus.PaidOver)
{
<td class="text-right">@payment.Overpaid</td>
}
</tr>
}
</tbody>
<tr>
<th>Name</th>
<td>@Model.BuyerInformation.BuyerName</td>
</tr>
<tr>
<th>Email</th>
<td><a href="mailto:@Model.BuyerInformation.BuyerEmail">@Model.BuyerInformation.BuyerEmail</a></td>
</tr>
<tr>
<th>Phone</th>
<td>@Model.BuyerInformation.BuyerPhone</td>
</tr>
<tr>
<th>Address 1</th>
<td>@Model.BuyerInformation.BuyerAddress1</td>
</tr>
<tr>
<th>Address 2</th>
<td>@Model.BuyerInformation.BuyerAddress2</td>
</tr>
<tr>
<th>City</th>
<td>@Model.BuyerInformation.BuyerCity</td>
</tr>
<tr>
<th>State</th>
<td>@Model.BuyerInformation.BuyerState</td>
</tr>
<tr>
<th>Country</th>
<td>@Model.BuyerInformation.BuyerCountry</td>
</tr>
<tr>
<th>Zip</th>
<td>@Model.BuyerInformation.BuyerZip</td>
</tr>
</table>
@if (Model.PosData.Count == 0)
{
<h3>Product information</h3>
<table class="table table-sm table-responsive-md">
<tr>
<th>Item code</th>
<td>@Model.ProductInformation.ItemCode</td>
</tr>
<tr>
<th>Item Description</th>
<td>@Model.ProductInformation.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>
@if (Model.OnChainPayments.Count > 0)
@if (Model.PosData.Count != 0)
{
<div class="row">
<div class="col-md-12">
<h3>On-Chain payments</h3>
<table class="table table-sm table-responsive-lg">
<thead class="thead-inverse">
<tr>
<th>Crypto</th>
<th>Deposit address</th>
<th>Transaction Id</th>
<th class="text-right">Confirmations</th>
</tr>
</thead>
<tbody>
@foreach (var payment in Model.OnChainPayments)
{
var replaced = payment.Replaced ? "class='linethrough'" : "";
<tr @replaced>
<td>@payment.Crypto</td>
<td>@payment.DepositAddress</td>
<td class="smMaxWidth text-truncate">
<a href="@payment.TransactionLink" target="_blank">
@payment.TransactionId
</a>
</td>
<td class="text-right">@payment.Confirmations</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
@if (Model.OffChainPayments.Count > 0)
{
<div class="row">
<div class="col-md-12">
<h3>Off-Chain payments</h3>
<div class="col-md-6">
<h3>Product information</h3>
<table class="table table-sm table-responsive-md">
<thead class="thead-inverse">
<tr>
<th class="firstCol">Crypto</th>
<th>BOLT11</th>
</tr>
</thead>
<tbody>
@foreach (var payment in Model.OffChainPayments)
{
<tr>
<td>@payment.Crypto</td>
<td class="smMaxWidth text-truncate">@payment.BOLT11</td>
</tr>
}
</tbody>
<tr>
<th>Item code</th>
<td>@Model.ProductInformation.ItemCode</td>
</tr>
<tr>
<th>Item Description</th>
<td>@Model.ProductInformation.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">
<h3>Point of Sale Data</h3>
<partial name="PosData" model="@Model.PosData" />
</div>
</div>
}
<partial name="InvoicePaymentsPartial" model="Model" />
<div class="row">
<div class="col-md-12">
<h3>Events</h3>

View File

@ -0,0 +1,97 @@
@model InvoiceDetailsModel
<div class="row">
<div class="col-md-12 invoice-payments">
<h3>Paid summary</h3>
<table class="table table-sm table-responsive-md">
<thead class="thead-inverse">
<tr>
<th>Payment method</th>
<th>Address</th>
<th class="text-right">Rate</th>
<th class="text-right">Paid</th>
<th class="text-right">Due</th>
@if (Model.StatusException == InvoiceExceptionStatus.PaidOver)
{
<th class="text-right">Overpaid</th>
}
</tr>
</thead>
<tbody>
@foreach (var payment in Model.CryptoPayments)
{
<tr>
<td>@payment.PaymentMethod</td>
<td>@payment.Address</td>
<td class="text-right">@payment.Rate</td>
<td class="text-right">@payment.Paid</td>
<td class="text-right">@payment.Due</td>
@if (Model.StatusException == InvoiceExceptionStatus.PaidOver)
{
<td class="text-right">@payment.Overpaid</td>
}
</tr>
}
</tbody>
</table>
</div>
</div>
@if (Model.OnChainPayments.Count > 0)
{
<div class="row">
<div class="col-md-12 invoice-payments">
<h3>On-Chain payments</h3>
<table class="table table-sm table-responsive-lg">
<thead class="thead-inverse">
<tr>
<th>Crypto</th>
<th>Deposit address</th>
<th>Transaction Id</th>
<th class="text-right">Confirmations</th>
</tr>
</thead>
<tbody>
@foreach (var payment in Model.OnChainPayments)
{
var replaced = payment.Replaced ? "class='linethrough'" : "";
<tr @replaced>
<td>@payment.Crypto</td>
<td>@payment.DepositAddress</td>
<td class="smMaxWidth text-truncate">
<a href="@payment.TransactionLink" target="_blank">
@payment.TransactionId
</a>
</td>
<td class="text-right">@payment.Confirmations</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}
@if (Model.OffChainPayments.Count > 0)
{
<div class="row">
<div class="col-md-12 invoice-payments">
<h3>Off-Chain payments</h3>
<table class="table table-sm table-responsive-md">
<thead class="thead-inverse">
<tr>
<th class="firstCol">Crypto</th>
<th>BOLT11</th>
</tr>
</thead>
<tbody>
@foreach (var payment in Model.OffChainPayments)
{
<tr>
<td>@payment.Crypto</td>
<td class="smMaxWidth text-truncate">@payment.BOLT11</td>
</tr>
}
</tbody>
</table>
</div>
</div>
}

View File

@ -103,7 +103,7 @@
<td>
<span class="switchTimeFormat" data-switch="@invoice.Date.ToTimeAgo()">
@invoice.Date.ToBrowserDate()
</span>
</span>
</td>
<td>
@if (invoice.RedirectUrl != string.Empty)
@ -151,6 +151,15 @@
</div>
}
<a asp-action="Invoice" asp-route-invoiceId="@invoice.InvoiceId">Details</a>
<a href="javascript:detailsToggle('@invoice.InvoiceId')">Expand</a>
</td>
</tr>
<tr id="invoice_@invoice.InvoiceId" style="display:none;">
<td colspan="99">
<div style="margin-left: 15px; margin-bottom: 0px;">
<partial name="InvoicePaymentsPartial" model="invoice.Details" />
</div>
</td>
</tr>
}
@ -219,5 +228,16 @@
this.href = this.href.replace("timezoneoffset=0", "timezoneoffset=" + timezoneOffset);
});
})
function detailsToggle(invoiceId) {
$("#invoice_" + invoiceId).toggle();
}
</script>
<style type="text/css">
.invoice-payments h3 {
font-size: 15px;
font-weight: bold;
}
</style>
</section>