mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-22 06:21:44 +01:00
Invoice: Improve payment details (#5362)
* Invoice: Improve payment details Clearer description and display, especially for overpayments. Closes #5207. * Further refinements * Test fix
This commit is contained in:
parent
f20e6d3768
commit
229a4ea56c
14 changed files with 185 additions and 116 deletions
|
@ -298,7 +298,7 @@ retry:
|
||||||
var fetcher = new RateFetcher(factory);
|
var fetcher = new RateFetcher(factory);
|
||||||
var provider = new BTCPayNetworkProvider(ChainName.Mainnet);
|
var provider = new BTCPayNetworkProvider(ChainName.Mainnet);
|
||||||
var b = new StoreBlob();
|
var b = new StoreBlob();
|
||||||
string[] temporarilyBroken = { "UGX" };
|
string[] temporarilyBroken = { "COP", "UGX" };
|
||||||
foreach (var k in StoreBlob.RecommendedExchanges)
|
foreach (var k in StoreBlob.RecommendedExchanges)
|
||||||
{
|
{
|
||||||
b.DefaultCurrency = k.Key;
|
b.DefaultCurrency = k.Key;
|
||||||
|
@ -307,14 +307,20 @@ retry:
|
||||||
var result = fetcher.FetchRates(pairs, rules, default);
|
var result = fetcher.FetchRates(pairs, rules, default);
|
||||||
foreach ((CurrencyPair key, Task<RateResult> value) in result)
|
foreach ((CurrencyPair key, Task<RateResult> value) in result)
|
||||||
{
|
{
|
||||||
|
TestLogs.LogInformation($"Testing {key} when default currency is {k.Key}");
|
||||||
|
var rateResult = await value;
|
||||||
|
var hasRate = rateResult.BidAsk != null;
|
||||||
|
|
||||||
if (temporarilyBroken.Contains(k.Key))
|
if (temporarilyBroken.Contains(k.Key))
|
||||||
|
{
|
||||||
|
if (!hasRate)
|
||||||
{
|
{
|
||||||
TestLogs.LogInformation($"Skipping {key} because it is marked as temporarily broken");
|
TestLogs.LogInformation($"Skipping {key} because it is marked as temporarily broken");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var rateResult = await value;
|
TestLogs.LogInformation($"Note: {key} is marked as temporarily broken, but the rate is available");
|
||||||
TestLogs.LogInformation($"Testing {key} when default currency is {k.Key}");
|
}
|
||||||
Assert.True(rateResult.BidAsk != null, $"Impossible to get the rate {rateResult.EvaluatedRule}");
|
Assert.True(hasRate, $"Impossible to get the rate {rateResult.EvaluatedRule}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,6 +165,8 @@ namespace BTCPayServer.Controllers
|
||||||
model.CryptoPayments = details.CryptoPayments;
|
model.CryptoPayments = details.CryptoPayments;
|
||||||
model.Payments = details.Payments;
|
model.Payments = details.Payments;
|
||||||
model.Overpaid = details.Overpaid;
|
model.Overpaid = details.Overpaid;
|
||||||
|
model.StillDue = details.StillDue;
|
||||||
|
model.HasRates = details.HasRates;
|
||||||
|
|
||||||
if (additionalData.ContainsKey("receiptData"))
|
if (additionalData.ContainsKey("receiptData"))
|
||||||
{
|
{
|
||||||
|
@ -565,37 +567,42 @@ namespace BTCPayServer.Controllers
|
||||||
private InvoiceDetailsModel InvoicePopulatePayments(InvoiceEntity invoice)
|
private InvoiceDetailsModel InvoicePopulatePayments(InvoiceEntity invoice)
|
||||||
{
|
{
|
||||||
var overpaid = false;
|
var overpaid = false;
|
||||||
|
var stillDue = false;
|
||||||
|
var hasRates = false;
|
||||||
var model = new InvoiceDetailsModel
|
var model = new InvoiceDetailsModel
|
||||||
{
|
{
|
||||||
Archived = invoice.Archived,
|
Archived = invoice.Archived,
|
||||||
Payments = invoice.GetPayments(false),
|
Payments = invoice.GetPayments(false),
|
||||||
Overpaid = true,
|
|
||||||
CryptoPayments = invoice.GetPaymentMethods().Select(
|
CryptoPayments = invoice.GetPaymentMethods().Select(
|
||||||
data =>
|
data =>
|
||||||
{
|
{
|
||||||
var accounting = data.Calculate();
|
var accounting = data.Calculate();
|
||||||
var paymentMethodId = data.GetId();
|
var paymentMethodId = data.GetId();
|
||||||
|
var hasPayment = accounting.CryptoPaid > 0;
|
||||||
var overpaidAmount = accounting.OverpaidHelper;
|
var overpaidAmount = accounting.OverpaidHelper;
|
||||||
|
var rate = ExchangeRate(data.GetId().CryptoCode, data);
|
||||||
|
|
||||||
if (overpaidAmount > 0)
|
if (rate is not null) hasRates = true;
|
||||||
{
|
if (hasPayment && overpaidAmount > 0) overpaid = true;
|
||||||
overpaid = true;
|
if (hasPayment && accounting.Due > 0) stillDue = true;
|
||||||
}
|
|
||||||
|
|
||||||
return new InvoiceDetailsModel.CryptoPayment
|
return new InvoiceDetailsModel.CryptoPayment
|
||||||
{
|
{
|
||||||
|
Rate = rate,
|
||||||
|
PaymentMethodRaw = data,
|
||||||
PaymentMethodId = paymentMethodId,
|
PaymentMethodId = paymentMethodId,
|
||||||
PaymentMethod = paymentMethodId.ToPrettyString(),
|
PaymentMethod = paymentMethodId.ToPrettyString(),
|
||||||
Due = _displayFormatter.Currency(accounting.Due, paymentMethodId.CryptoCode),
|
TotalDue = _displayFormatter.Currency(accounting.TotalDue, paymentMethodId.CryptoCode),
|
||||||
Paid = _displayFormatter.Currency(accounting.CryptoPaid, paymentMethodId.CryptoCode),
|
Due = hasPayment ? _displayFormatter.Currency(accounting.Due, paymentMethodId.CryptoCode) : null,
|
||||||
Overpaid = _displayFormatter.Currency(overpaidAmount, paymentMethodId.CryptoCode),
|
Paid = hasPayment ? _displayFormatter.Currency(accounting.CryptoPaid, paymentMethodId.CryptoCode) : null,
|
||||||
Address = data.GetPaymentMethodDetails().GetPaymentDestination(),
|
Overpaid = hasPayment ? _displayFormatter.Currency(overpaidAmount, paymentMethodId.CryptoCode) : null,
|
||||||
Rate = ExchangeRate(data.GetId().CryptoCode, data),
|
Address = data.GetPaymentMethodDetails().GetPaymentDestination()
|
||||||
PaymentMethodRaw = data
|
|
||||||
};
|
};
|
||||||
}).ToList()
|
}).ToList(),
|
||||||
|
Overpaid = overpaid,
|
||||||
|
StillDue = stillDue,
|
||||||
|
HasRates = hasRates
|
||||||
};
|
};
|
||||||
model.Overpaid = overpaid;
|
|
||||||
|
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||||
public class CryptoPayment
|
public class CryptoPayment
|
||||||
{
|
{
|
||||||
public string PaymentMethod { get; set; }
|
public string PaymentMethod { get; set; }
|
||||||
|
public string TotalDue { get; set; }
|
||||||
public string Due { get; set; }
|
public string Due { get; set; }
|
||||||
public string Paid { get; set; }
|
public string Paid { get; set; }
|
||||||
public string Address { get; internal set; }
|
public string Address { get; internal set; }
|
||||||
|
@ -138,6 +139,8 @@ namespace BTCPayServer.Models.InvoicingModels
|
||||||
public bool CanMarkStatus => CanMarkSettled || CanMarkInvalid;
|
public bool CanMarkStatus => CanMarkSettled || CanMarkInvalid;
|
||||||
public List<RefundData> Refunds { get; set; }
|
public List<RefundData> Refunds { get; set; }
|
||||||
public bool ShowReceipt { get; set; }
|
public bool ShowReceipt { get; set; }
|
||||||
public bool Overpaid { get; set; } = false;
|
public bool Overpaid { get; set; }
|
||||||
|
public bool StillDue { get; set; }
|
||||||
|
public bool HasRates { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<h5>On-Chain Payments</h5>
|
<h5>On-Chain Payments</h5>
|
||||||
<div class="invoice-payments table-responsive mt-0">
|
<div class="invoice-payments table-responsive mt-0">
|
||||||
<table class="table table-hover mb-0">
|
<table class="table table-hover mb-0">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-75px">Crypto</th>
|
<th class="w-75px">Crypto</th>
|
||||||
<th class="w-100px">Index</th>
|
<th class="w-100px">Index</th>
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
</th>
|
</th>
|
||||||
}
|
}
|
||||||
<th class="text-end">Confirmations</th>
|
<th class="text-end">Confirmations</th>
|
||||||
<th class="w-150px text-end">Amount</th>
|
<th class="w-150px text-end">Paid</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
}
|
}
|
||||||
<td class="text-end">@payment.Confirmations</td>
|
<td class="text-end">@payment.Confirmations</td>
|
||||||
<td class="payment-value text-end text-nowrap">
|
<td class="payment-value text-end text-nowrap">
|
||||||
<span data-sensitive>@DisplayFormatter.Currency(payment.CryptoPaymentData.GetValue(), payment.Crypto)</span>
|
<span data-sensitive class="text-success">@DisplayFormatter.Currency(payment.CryptoPaymentData.GetValue(), payment.Crypto)</span>
|
||||||
@if (!string.IsNullOrEmpty(payment.AdditionalInformation))
|
@if (!string.IsNullOrEmpty(payment.AdditionalInformation))
|
||||||
{
|
{
|
||||||
<div>(@payment.AdditionalInformation)</div>
|
<div>(@payment.AdditionalInformation)</div>
|
||||||
|
|
|
@ -30,13 +30,13 @@
|
||||||
<h5>Off-Chain Payments</h5>
|
<h5>Off-Chain Payments</h5>
|
||||||
<div class="invoice-payments table-responsive mt-0">
|
<div class="invoice-payments table-responsive mt-0">
|
||||||
<table class="table table-hover mb-0">
|
<table class="table table-hover mb-0">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-75px">Crypto</th>
|
<th class="w-75px">Crypto</th>
|
||||||
<th class="w-100px">Type</th>
|
<th class="w-100px">Type</th>
|
||||||
<th class="w-175px">Destination</th>
|
<th class="w-175px">Destination</th>
|
||||||
<th class="text-nowrap">Payment Proof</th>
|
<th class="text-nowrap">Payment Proof</th>
|
||||||
<th class="w-150px text-end">Amount</th>
|
<th class="w-150px text-end">Paid</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
<vc:truncate-center text="@payment.PaymentProof" classes="truncate-center-id" />
|
<vc:truncate-center text="@payment.PaymentProof" classes="truncate-center-id" />
|
||||||
</td>
|
</td>
|
||||||
<td class="payment-value text-end text-nowrap">
|
<td class="payment-value text-end text-nowrap">
|
||||||
<span data-sensitive>@payment.Amount</span>
|
<span data-sensitive class="text-success">@payment.Amount</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
|
@using BTCPayServer.Services
|
||||||
@using BTCPayServer.Services.Altcoins.Monero.Payments
|
@using BTCPayServer.Services.Altcoins.Monero.Payments
|
||||||
@using BTCPayServer.Services.Altcoins.Monero.UI
|
@using BTCPayServer.Services.Altcoins.Monero.UI
|
||||||
|
@inject DisplayFormatter DisplayFormatter
|
||||||
@model IEnumerable<BTCPayServer.Services.Invoices.PaymentEntity>
|
@model IEnumerable<BTCPayServer.Services.Invoices.PaymentEntity>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
var onchainPayments = Model.Where(entity => entity.GetPaymentMethodId().PaymentType == MoneroPaymentType.Instance).Select(payment =>
|
var payments = Model.Where(entity => entity.GetPaymentMethodId().PaymentType == MoneroPaymentType.Instance).Select(payment =>
|
||||||
{
|
{
|
||||||
var m = new MoneroPaymentViewModel();
|
var m = new MoneroPaymentViewModel();
|
||||||
var onChainPaymentData = payment.GetCryptoPaymentData() as MoneroLikePaymentData;
|
var onChainPaymentData = payment.GetCryptoPaymentData() as MoneroLikePaymentData;
|
||||||
|
@ -26,37 +28,37 @@
|
||||||
m.ReceivedTime = payment.ReceivedTime;
|
m.ReceivedTime = payment.ReceivedTime;
|
||||||
m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId);
|
m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId);
|
||||||
return m;
|
return m;
|
||||||
});
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (onchainPayments.Any())
|
@if (payments.Any())
|
||||||
{
|
{
|
||||||
|
<section>
|
||||||
<h5>Monero Payments</h5>
|
<h5>Monero Payments</h5>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Crypto</th>
|
<th class="w-75px">Crypto</th>
|
||||||
<th>Deposit address</th>
|
<th class="w-175px">Destination</th>
|
||||||
<th>Amount</th>
|
<th class="text-nowrap">Payment Proof</th>
|
||||||
<th>Transaction Id</th>
|
<th class="text-end">Confirmations</th>
|
||||||
<th class="text-right">Confirmations</th>
|
<th class="w-150px text-end">Paid</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach (var payment in onchainPayments)
|
@foreach (var payment in payments)
|
||||||
{
|
{
|
||||||
<tr >
|
<tr >
|
||||||
<td>@payment.Crypto</td>
|
<td>@payment.Crypto</td>
|
||||||
<td>@payment.DepositAddress</td>
|
<td><vc:truncate-center text="@payment.DepositAddress" classes="truncate-center-id" /></td>
|
||||||
<td>@payment.Amount</td>
|
<td><vc:truncate-center text="@payment.TransactionId" link="@payment.TransactionLink" classes="truncate-center-id" /></td>
|
||||||
<td>
|
<td class="text-end">@payment.Confirmations</td>
|
||||||
<a href="@payment.TransactionLink" class="text-break" target="_blank" rel="noreferrer noopener">
|
<td class="payment-value text-end text-nowrap">
|
||||||
@payment.TransactionId
|
<span data-sensitive class="text-success">@DisplayFormatter.Currency(payment.Amount, payment.Crypto)</span>
|
||||||
</a>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">@payment.Confirmations</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</section>
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
@using System.Globalization
|
@using System.Globalization
|
||||||
|
@using BTCPayServer.Components.TruncateCenter
|
||||||
|
@using BTCPayServer.Services
|
||||||
@using BTCPayServer.Services.Altcoins.Zcash.Payments
|
@using BTCPayServer.Services.Altcoins.Zcash.Payments
|
||||||
@using BTCPayServer.Services.Altcoins.Zcash.UI
|
@using BTCPayServer.Services.Altcoins.Zcash.UI
|
||||||
|
@inject DisplayFormatter DisplayFormatter
|
||||||
@model IEnumerable<BTCPayServer.Services.Invoices.PaymentEntity>
|
@model IEnumerable<BTCPayServer.Services.Invoices.PaymentEntity>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
var onchainPayments = Model.Where(entity => entity.GetPaymentMethodId().PaymentType == ZcashPaymentType.Instance).Select(payment =>
|
var payments = Model.Where(entity => entity.GetPaymentMethodId().PaymentType == ZcashPaymentType.Instance).Select(payment =>
|
||||||
{
|
{
|
||||||
var m = new ZcashPaymentViewModel();
|
var m = new ZcashPaymentViewModel();
|
||||||
var onChainPaymentData = payment.GetCryptoPaymentData() as ZcashLikePaymentData;
|
var onChainPaymentData = payment.GetCryptoPaymentData() as ZcashLikePaymentData;
|
||||||
|
@ -26,37 +29,37 @@
|
||||||
m.ReceivedTime = payment.ReceivedTime;
|
m.ReceivedTime = payment.ReceivedTime;
|
||||||
m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId);
|
m.TransactionLink = string.Format(CultureInfo.InvariantCulture, payment.Network.BlockExplorerLink, m.TransactionId);
|
||||||
return m;
|
return m;
|
||||||
});
|
}).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (onchainPayments.Any())
|
@if (payments.Any())
|
||||||
{
|
{
|
||||||
|
<section>
|
||||||
<h5>Zcash Payments</h5>
|
<h5>Zcash Payments</h5>
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Crypto</th>
|
<th class="w-75px">Crypto</th>
|
||||||
<th>Deposit address</th>
|
<th class="w-175px">Destination</th>
|
||||||
<th>Amount</th>
|
<th class="text-nowrap">Payment Proof</th>
|
||||||
<th>Transaction Id</th>
|
<th class="text-end">Confirmations</th>
|
||||||
<th class="text-right">Confirmations</th>
|
<th class="w-150px text-end">Paid</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@foreach (var payment in onchainPayments)
|
@foreach (var payment in payments)
|
||||||
{
|
{
|
||||||
<tr >
|
<tr >
|
||||||
<td>@payment.Crypto</td>
|
<td>@payment.Crypto</td>
|
||||||
<td>@payment.DepositAddress</td>
|
<td><vc:truncate-center text="@payment.DepositAddress" classes="truncate-center-id" /></td>
|
||||||
<td>@payment.Amount</td>
|
<td><vc:truncate-center text="@payment.TransactionId" link="@payment.TransactionLink" classes="truncate-center-id" /></td>
|
||||||
<td>
|
<td class="text-end">@payment.Confirmations</td>
|
||||||
<a href="@payment.TransactionLink" class="text-break" target="_blank" rel="noreferrer noopener">
|
<td class="payment-value text-end text-nowrap">
|
||||||
@payment.TransactionId
|
<span data-sensitive class="text-success">@DisplayFormatter.Currency(payment.Amount, payment.Crypto)</span>
|
||||||
</a>
|
|
||||||
</td>
|
</td>
|
||||||
<td class="text-right">@payment.Confirmations</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</section>
|
||||||
}
|
}
|
||||||
|
|
|
@ -327,7 +327,7 @@
|
||||||
<td>@Model.TransactionSpeed</td>
|
<td>@Model.TransactionSpeed</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Total Fiat Due</th>
|
<th>Total Amount Due</th>
|
||||||
<td><span data-sensitive>@Model.Fiat</span></td>
|
<td><span data-sensitive>@Model.Fiat</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
@if (!string.IsNullOrEmpty(Model.RefundEmail))
|
@if (!string.IsNullOrEmpty(Model.RefundEmail))
|
||||||
|
@ -506,7 +506,8 @@
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xxl-constrain">
|
||||||
<h3 class="mb-3">Invoice Summary</h3>
|
<h3 class="mb-3">Invoice Summary</h3>
|
||||||
<partial name="ListInvoicesPaymentsPartial" model="(Model, true)" />
|
<partial name="ListInvoicesPaymentsPartial" model="(Model, true)" />
|
||||||
|
|
||||||
|
@ -655,3 +656,5 @@
|
||||||
</table>
|
</table>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
@section PageHeadContent
|
@section PageHeadContent
|
||||||
{
|
{
|
||||||
<style>
|
<style>
|
||||||
.invoice-payments {
|
.invoice-details-row > td {
|
||||||
padding-left: var(--btcpay-space-l);
|
padding: 1.5rem .5rem 0 2.65rem;
|
||||||
}
|
}
|
||||||
.dropdown > .btn {
|
.dropdown > .btn {
|
||||||
min-width: 7rem;
|
min-width: 7rem;
|
||||||
|
|
|
@ -6,22 +6,41 @@
|
||||||
.Where(entities => entities.Key != null);
|
.Where(entities => entities.Key != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (invoice.Overpaid)
|
||||||
|
{
|
||||||
|
var usedPaymentMethods = invoice.CryptoPayments.Count(p => p.Paid != null);
|
||||||
|
<p class="d-flex align-items-center gap-2 mb-3 text-warning">
|
||||||
|
<vc:icon symbol="warning"/>
|
||||||
|
This invoice got overpaid.
|
||||||
|
@if (usedPaymentMethods > 1)
|
||||||
|
{
|
||||||
|
@("Each payment method shows the total excess amount.")
|
||||||
|
}
|
||||||
|
</p>
|
||||||
|
}
|
||||||
<div class="invoice-payments table-responsive mt-0">
|
<div class="invoice-payments table-responsive mt-0">
|
||||||
<table class="table table-hover mb-0">
|
<table class="table table-hover mb-0">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="text-nowrap w-175px">Payment method</th>
|
<th class="text-nowrap w-175px">Payment method</th>
|
||||||
@if (Model.ShowAddress)
|
@if (Model.ShowAddress)
|
||||||
{
|
{
|
||||||
<th>Destination</th>
|
<th>Destination</th>
|
||||||
}
|
}
|
||||||
|
@if (invoice.HasRates)
|
||||||
|
{
|
||||||
<th class="w-150px text-end">Rate</th>
|
<th class="w-150px text-end">Rate</th>
|
||||||
<th class="w-150px text-end">Paid</th>
|
}
|
||||||
<th class="w-150px text-end">Due</th>
|
<th class="w-150px text-end">Total due</th>
|
||||||
@if (invoice.Overpaid)
|
@if (invoice.StillDue)
|
||||||
|
{
|
||||||
|
<th class="w-150px text-end">Still due</th>
|
||||||
|
}
|
||||||
|
else if (invoice.Overpaid)
|
||||||
{
|
{
|
||||||
<th class="w-150px text-end">Overpaid</th>
|
<th class="w-150px text-end">Overpaid</th>
|
||||||
}
|
}
|
||||||
|
<th class="w-150px text-end">Paid</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -35,13 +54,39 @@
|
||||||
<vc:truncate-center text="@payment.Address" classes="truncate-center-id" />
|
<vc:truncate-center text="@payment.Address" classes="truncate-center-id" />
|
||||||
</td>
|
</td>
|
||||||
}
|
}
|
||||||
<td class="text-nowrap text-end"><span data-sensitive>@payment.Rate</span></td>
|
@if (invoice.HasRates)
|
||||||
<td class="text-nowrap text-end"><span data-sensitive>@payment.Paid</span></td>
|
|
||||||
<td class="text-nowrap text-end"><span data-sensitive>@payment.Due</span></td>
|
|
||||||
@if (invoice.Overpaid)
|
|
||||||
{
|
{
|
||||||
<td class="text-nowrap text-end"><span data-sensitive>@payment.Overpaid</span></td>
|
<td class="text-nowrap text-end">
|
||||||
|
<span data-sensitive>@payment.Rate</span>
|
||||||
|
</td>
|
||||||
}
|
}
|
||||||
|
<td class="text-nowrap text-end">
|
||||||
|
<span data-sensitive>@payment.TotalDue</span>
|
||||||
|
</td>
|
||||||
|
@if (invoice.StillDue)
|
||||||
|
{
|
||||||
|
<td class="text-nowrap text-end">
|
||||||
|
@if (payment.Due != null)
|
||||||
|
{
|
||||||
|
<span data-sensitive>@payment.Due</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
}
|
||||||
|
else if (invoice.Overpaid)
|
||||||
|
{
|
||||||
|
<td class="text-nowrap text-end">
|
||||||
|
@if (payment.Overpaid != null)
|
||||||
|
{
|
||||||
|
<span data-sensitive class="text-warning">@payment.Overpaid</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
}
|
||||||
|
<td class="text-nowrap text-end">
|
||||||
|
@if (payment.Paid != null)
|
||||||
|
{
|
||||||
|
<span data-sensitive class="text-success">@payment.Paid</span>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
var details = payment.PaymentMethodRaw.GetPaymentMethodDetails();
|
var details = payment.PaymentMethodRaw.GetPaymentMethodDetails();
|
||||||
var name = details.GetAdditionalDataPartialName();
|
var name = details.GetAdditionalDataPartialName();
|
||||||
|
|
|
@ -164,7 +164,7 @@
|
||||||
{
|
{
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th permission="@Policies.CanModifyStoreSettings">
|
<th permission="@Policies.CanModifyStoreSettings">
|
||||||
<input id="@Model.PayoutState-selectAllCheckbox" type="checkbox" class="form-check-input selectAll" data-payout-state="@Model.PayoutState.ToString()" />
|
<input id="@Model.PayoutState-selectAllCheckbox" type="checkbox" class="form-check-input selectAll" data-payout-state="@Model.PayoutState.ToString()" />
|
||||||
|
|
|
@ -102,7 +102,7 @@
|
||||||
}
|
}
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">
|
<th scope="col">
|
||||||
<a asp-action="PullPayments"
|
<a asp-action="PullPayments"
|
||||||
|
|
|
@ -169,7 +169,7 @@
|
||||||
|
|
||||||
<div id="WalletTransactions" class="table-responsive-md">
|
<div id="WalletTransactions" class="table-responsive-md">
|
||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead class="thead-inverse">
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:2rem;" class="only-for-js">
|
<th style="width:2rem;" class="only-for-js">
|
||||||
<input id="selectAllCheckbox" type="checkbox" class="form-check-input" />
|
<input id="selectAllCheckbox" type="checkbox" class="form-check-input" />
|
||||||
|
|
|
@ -76,7 +76,7 @@ hr.primary {
|
||||||
|
|
||||||
@media (min-width: 1400px) {
|
@media (min-width: 1400px) {
|
||||||
.col-xxl-constrain {
|
.col-xxl-constrain {
|
||||||
max-width: 800px;
|
max-width: 984px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue