2017-09-13 08:47:34 +02:00
|
|
|
@model InvoicesModel
|
|
|
|
@{
|
2017-10-27 10:53:04 +02:00
|
|
|
ViewData["Title"] = "Invoices";
|
2018-11-09 09:13:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@section HeadScripts {
|
|
|
|
<script src="~/modal/btcpay.js"></script>
|
2017-09-13 08:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
<section>
|
2017-10-27 10:53:04 +02:00
|
|
|
<div class="container">
|
2017-09-13 08:47:34 +02:00
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
<div class="row">
|
|
|
|
<div class="col-lg-12 text-center">
|
2018-05-08 10:57:53 +02:00
|
|
|
<partial name="_StatusMessage" for="StatusMessage" />
|
2017-10-27 10:53:04 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
2017-09-13 08:47:34 +02:00
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
<div class="row">
|
|
|
|
<div class="col-lg-12 text-center">
|
|
|
|
<h2 class="section-heading">@ViewData["Title"]</h2>
|
|
|
|
<hr class="primary">
|
2017-12-03 15:35:52 +01:00
|
|
|
<p>Create, search or pay an invoice. (<a href="#help" data-toggle="collapse">Help</a>)</p>
|
|
|
|
<div id="help" class="collapse text-left">
|
2018-04-09 10:53:43 +02:00
|
|
|
<p>
|
2018-05-03 18:46:52 +02:00
|
|
|
You can search for invoice Id, deposit address, price, order id, store id, any buyer information and any product information.<br />
|
2019-04-26 01:28:03 +02:00
|
|
|
Be sure to split your search parameters with comma, for example: <code>startdate:2019-04-25 13:00:00, status:paid</code><br />
|
2018-05-05 16:25:09 +02:00
|
|
|
You can also apply filters to your search by searching for <code>filtername:value</code>, here is a list of supported filters
|
2018-04-09 10:53:43 +02:00
|
|
|
</p>
|
2017-12-03 15:35:52 +01:00
|
|
|
<ul>
|
2018-05-05 16:25:09 +02:00
|
|
|
<li><code>storeid:id</code> for filtering a specific store</li>
|
2019-01-06 10:00:55 +01:00
|
|
|
<li><code>orderid:id</code> for filtering a specific order</li>
|
|
|
|
<li><code>itemcode:code</code> for filtering a specific type of item purchased through the pos or crowdfund apps</li>
|
2018-05-05 16:25:09 +02:00
|
|
|
<li><code>status:(expired|invalid|complete|confirmed|paid|new)</code> for filtering a specific status</li>
|
|
|
|
<li><code>exceptionstatus:(paidover|paidlate|paidpartial)</code> for filtering a specific exception state</li>
|
2018-05-06 06:16:39 +02:00
|
|
|
<li><code>unusual:(true|false)</code> for filtering invoices which might requires merchant attention (those invalid or with an exceptionstatus)</li>
|
2019-04-26 01:13:17 +02:00
|
|
|
<li><code>startdate:yyyy-MM-dd HH:mm:ss</code> getting invoices that were created after certain date</li>
|
|
|
|
<li><code>enddate:yyyy-MM-dd HH:mm:ss</code> getting invoices that were created before certain date</li>
|
2017-12-03 15:35:52 +01:00
|
|
|
</ul>
|
2018-04-26 04:01:59 +02:00
|
|
|
<p>
|
2019-04-26 01:28:03 +02:00
|
|
|
If you want all confirmed and complete invoices, you can duplicate a filter <code>status:confirmed, status:complete</code>.
|
2018-04-26 04:01:59 +02:00
|
|
|
</p>
|
2017-12-03 15:35:52 +01:00
|
|
|
</div>
|
2018-10-12 03:09:13 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="row no-gutter" style="margin-bottom: 5px;">
|
2018-11-30 08:22:39 +01:00
|
|
|
<div class="col-lg-6">
|
2018-10-12 03:09:13 +02:00
|
|
|
<a asp-action="CreateInvoice" class="btn btn-primary" role="button"><span class="fa fa-plus"></span> Create a new invoice</a>
|
2018-11-30 08:22:39 +01:00
|
|
|
|
|
|
|
<a class="btn btn-primary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
|
|
Export
|
|
|
|
</a>
|
2019-04-05 16:44:30 +02:00
|
|
|
<a href="https://docs.btcpayserver.org/features/accounting" target="_blank">
|
|
|
|
<span class="fa fa-question-circle-o" title="More information..."></span>
|
|
|
|
</a>
|
2018-11-30 08:22:39 +01:00
|
|
|
<div class="dropdown-menu" aria-labelledby="dropdownMenuLink">
|
2019-04-26 01:13:17 +02:00
|
|
|
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="csv" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">CSV</a>
|
|
|
|
<a asp-action="Export" asp-route-timezoneoffset="0" asp-route-format="json" asp-route-searchTerm="@Model.SearchTerm" class="dropdown-item export-link" target="_blank">JSON</a>
|
2018-11-30 08:22:39 +01:00
|
|
|
</div>
|
2018-10-12 03:09:13 +02:00
|
|
|
</div>
|
|
|
|
|
2018-11-30 08:22:39 +01:00
|
|
|
<div class="col-lg-6">
|
2017-10-27 10:53:04 +02:00
|
|
|
<div class="form-group">
|
2019-04-26 01:13:17 +02:00
|
|
|
<form asp-action="ListInvoices" method="get" style="float:right;">
|
2018-04-09 10:53:43 +02:00
|
|
|
<div class="input-group">
|
2019-04-26 01:13:17 +02:00
|
|
|
<input asp-for="TimezoneOffset" type="hidden" />
|
2018-10-12 03:09:13 +02:00
|
|
|
<input asp-for="SearchTerm" class="form-control" style="width:300px;" />
|
2018-04-09 10:53:43 +02:00
|
|
|
<span class="input-group-btn">
|
|
|
|
<button type="submit" class="btn btn-primary" title="Search invoice">
|
|
|
|
<span class="fa fa-search"></span> Search
|
|
|
|
</button>
|
|
|
|
</span>
|
|
|
|
</div>
|
2017-10-27 10:53:04 +02:00
|
|
|
<input type="hidden" asp-for="Count" />
|
|
|
|
<span asp-validation-for="SearchTerm" class="text-danger"></span>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2017-09-13 08:47:34 +02:00
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
<div class="row">
|
2018-04-08 07:06:47 +02:00
|
|
|
<table class="table table-sm table-responsive-md">
|
2018-04-06 06:20:12 +02:00
|
|
|
<thead>
|
2017-10-27 10:53:04 +02:00
|
|
|
<tr>
|
2019-04-05 16:44:30 +02:00
|
|
|
<th style="min-width: 90px;" class="col-md-auto">
|
|
|
|
Date
|
|
|
|
<a href="javascript:switchTimeFormat()">
|
|
|
|
<span class="fa fa-clock-o" title="Switch date format"></span>
|
|
|
|
</a>
|
|
|
|
</th>
|
2019-04-30 06:25:11 +02:00
|
|
|
<th style="max-width: 180px;">OrderId</th>
|
2017-10-27 10:53:04 +02:00
|
|
|
<th>InvoiceId</th>
|
2019-05-03 21:54:40 +02:00
|
|
|
<th style="min-width: 140px;">Status</th>
|
2018-03-13 01:13:16 +01:00
|
|
|
<th style="text-align:right">Amount</th>
|
2018-03-13 07:28:39 +01:00
|
|
|
<th style="text-align:right">Actions</th>
|
2017-10-27 10:53:04 +02:00
|
|
|
</tr>
|
|
|
|
</thead>
|
|
|
|
<tbody>
|
2018-10-12 03:09:13 +02:00
|
|
|
@foreach (var invoice in Model.Invoices)
|
2017-10-27 10:53:04 +02:00
|
|
|
{
|
|
|
|
<tr>
|
2019-04-05 16:44:30 +02:00
|
|
|
<td>
|
|
|
|
<span class="switchTimeFormat" data-switch="@invoice.Date.ToTimeAgo()">
|
|
|
|
@invoice.Date.ToBrowserDate()
|
2019-04-30 05:45:33 +02:00
|
|
|
</span>
|
2019-04-05 16:44:30 +02:00
|
|
|
</td>
|
2019-04-30 06:25:11 +02:00
|
|
|
<td style="max-width: 180px;">
|
2018-10-12 03:09:13 +02:00
|
|
|
@if (invoice.RedirectUrl != string.Empty)
|
2018-03-13 01:13:16 +01:00
|
|
|
{
|
2019-04-30 06:25:11 +02:00
|
|
|
<a href="@invoice.RedirectUrl" class="wraptext200">@invoice.OrderId</a>
|
2018-03-13 01:13:16 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
<span>@invoice.OrderId</span>
|
|
|
|
}
|
|
|
|
</td>
|
2017-10-27 10:53:04 +02:00
|
|
|
<td>@invoice.InvoiceId</td>
|
2019-05-01 22:33:46 +02:00
|
|
|
<td>
|
2018-12-10 07:34:48 +01:00
|
|
|
@if (invoice.CanMarkStatus)
|
|
|
|
{
|
2019-05-03 21:54:40 +02:00
|
|
|
<div id="pavpill_@invoice.InvoiceId">
|
|
|
|
<span class="dropdown-toggle dropdown-toggle-split pavpill pavpil-@invoice.Status.ToString().ToLower()"
|
|
|
|
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
|
|
@invoice.StatusString
|
|
|
|
</span>
|
|
|
|
<div class="dropdown-menu pull-right">
|
|
|
|
@if (invoice.CanMarkInvalid)
|
|
|
|
{
|
|
|
|
<button class="dropdown-item small cursorPointer" onclick="changeInvoiceState(this, '@invoice.InvoiceId', 'invalid')">
|
|
|
|
Mark as invalid <span class="fa fa-times"></span>
|
|
|
|
</button>
|
|
|
|
}
|
|
|
|
@if (invoice.CanMarkComplete)
|
|
|
|
{
|
|
|
|
<button class="dropdown-item small cursorPointer" onclick="changeInvoiceState(this, '@invoice.InvoiceId', 'complete')">
|
|
|
|
Mark as complete <span class="fa fa-check-circle"></span>
|
|
|
|
</button>
|
|
|
|
}
|
|
|
|
</div>
|
2018-12-10 07:34:48 +01:00
|
|
|
</div>
|
|
|
|
}
|
2019-05-01 22:33:46 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
<span class="pavpill pavpil-@invoice.Status.ToString().ToLower()">@invoice.StatusString</span>
|
|
|
|
}
|
|
|
|
</td>
|
|
|
|
<td style="text-align:right">@invoice.AmountCurrency</td>
|
|
|
|
<td style="text-align:right">
|
|
|
|
@if (invoice.ShowCheckout)
|
|
|
|
{
|
|
|
|
<span>
|
|
|
|
<a asp-action="Checkout" asp-route-invoiceId="@invoice.InvoiceId">Checkout</a>
|
|
|
|
<a href="javascript:btcpay.showInvoice('@invoice.InvoiceId')">[^]</a>
|
|
|
|
@if (!invoice.CanMarkStatus)
|
|
|
|
{
|
|
|
|
<span>-</span>
|
|
|
|
}
|
|
|
|
</span>
|
|
|
|
}
|
2019-04-30 06:25:11 +02:00
|
|
|
|
2018-11-09 09:13:45 +01:00
|
|
|
<a asp-action="Invoice" asp-route-invoiceId="@invoice.InvoiceId">Details</a>
|
2019-04-30 06:25:11 +02:00
|
|
|
@*<span title="Details" class="fa fa-list"></span>*@
|
|
|
|
|
|
|
|
<a href="javascript:void(0);" onclick="detailsToggle(this, '@invoice.InvoiceId')">
|
|
|
|
<span title="Invoice Details Toggle" class="fa fa-1x fa-angle-double-down"></span>
|
|
|
|
</a>
|
2019-04-30 05:45:33 +02:00
|
|
|
</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>
|
2018-03-13 01:13:16 +01:00
|
|
|
</td>
|
2017-10-27 10:53:04 +02:00
|
|
|
</tr>
|
|
|
|
}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
2019-01-16 21:33:04 +01:00
|
|
|
|
2019-04-05 05:25:38 +02:00
|
|
|
<nav aria-label="..." class="w-100">
|
|
|
|
<ul class="pagination float-left">
|
|
|
|
<li class="page-item @(Model.Skip == 0 ? "disabled" : null)">
|
|
|
|
<a class="page-link" tabindex="-1" href="@listInvoices(-1, Model.Count)">«</a>
|
2019-01-16 21:33:04 +01:00
|
|
|
</li>
|
|
|
|
<li class="page-item disabled">
|
|
|
|
<span class="page-link">@(Model.Skip + 1) to @(Model.Skip + Model.Invoices.Count) of @Model.Total</span>
|
|
|
|
</li>
|
|
|
|
<li class="page-item @(Model.Total > (Model.Skip + Model.Invoices.Count) ? null : "disabled")">
|
2019-04-05 05:25:38 +02:00
|
|
|
<a class="page-link" href="@listInvoices(1, Model.Count)">»</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<ul class="pagination float-right">
|
|
|
|
<li class="page-item disabled">
|
|
|
|
<span class="page-link">Page Size:</span>
|
|
|
|
</li>
|
|
|
|
<li class="page-item @(Model.Count == 50 ? "active" : null)">
|
|
|
|
<a class="page-link" href="@listInvoices(0, 50)">50</a>
|
|
|
|
</li>
|
|
|
|
<li class="page-item @(Model.Count == 100 ? "active" : null)">
|
|
|
|
<a class="page-link" href="@listInvoices(0, 100)">100</a>
|
|
|
|
</li>
|
|
|
|
<li class="page-item @(Model.Count == 250 ? "active" : null)">
|
|
|
|
<a class="page-link" href="@listInvoices(0, 250)">250</a>
|
|
|
|
</li>
|
|
|
|
<li class="page-item @(Model.Count == 500 ? "active" : null)">
|
|
|
|
<a class="page-link" href="@listInvoices(0, 500)">500</a>
|
2019-01-16 21:33:04 +01:00
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</nav>
|
2019-04-05 16:44:30 +02:00
|
|
|
@{
|
2019-04-05 05:25:38 +02:00
|
|
|
string listInvoices(int prevNext, int count)
|
|
|
|
{
|
|
|
|
var skip = Model.Skip;
|
|
|
|
if (prevNext == -1)
|
|
|
|
skip = Math.Max(0, Model.Skip - Model.Count);
|
|
|
|
else if (prevNext == 1)
|
|
|
|
skip = Model.Skip + count;
|
|
|
|
|
|
|
|
var act = Url.Action("ListInvoices", new
|
|
|
|
{
|
|
|
|
searchTerm = Model.SearchTerm,
|
|
|
|
skip = skip,
|
|
|
|
count = count,
|
|
|
|
});
|
|
|
|
|
|
|
|
return act;
|
|
|
|
}
|
|
|
|
}
|
2017-10-27 10:53:04 +02:00
|
|
|
</div>
|
2017-09-13 08:47:34 +02:00
|
|
|
|
2017-10-27 10:53:04 +02:00
|
|
|
</div>
|
2019-04-05 16:44:30 +02:00
|
|
|
|
|
|
|
<script type="text/javascript">
|
2019-04-26 01:13:17 +02:00
|
|
|
$(function () {
|
|
|
|
var timezoneOffset = new Date().getTimezoneOffset()
|
|
|
|
$("#TimezoneOffset").val(timezoneOffset);
|
|
|
|
$(".export-link").each(function () {
|
|
|
|
this.href = this.href.replace("timezoneoffset=0", "timezoneoffset=" + timezoneOffset);
|
|
|
|
});
|
|
|
|
})
|
2019-04-30 05:45:33 +02:00
|
|
|
|
2019-04-30 06:25:11 +02:00
|
|
|
function detailsToggle(sender, invoiceId) {
|
|
|
|
$("#invoice_" + invoiceId).toggle(0, function () {
|
|
|
|
var detailsRow = $(this);
|
|
|
|
var btnToggle = $(sender).children().first();
|
|
|
|
if (detailsRow.is(':visible')) {
|
|
|
|
btnToggle.removeClass('fa-angle-double-down').addClass('fa-angle-double-up');
|
|
|
|
} else {
|
|
|
|
btnToggle.removeClass('fa-angle-double-up').addClass('fa-angle-double-down');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return false;
|
2019-04-30 05:45:33 +02:00
|
|
|
}
|
2019-05-03 21:54:40 +02:00
|
|
|
|
|
|
|
function changeInvoiceState(sender, invoiceId, newState) {
|
|
|
|
var pavpill = $("#pavpill_" + invoiceId);
|
|
|
|
var originalHtml = pavpill.html();
|
|
|
|
pavpill.html("<span class='fa fa-bitcoin fa-spin' style='margin-left:16px;'></span>");
|
|
|
|
|
|
|
|
$.post("invoices/" + invoiceId + "/changestate/" + newState)
|
|
|
|
.done(function (data) {
|
|
|
|
var statusHtml = "<span class='pavpill pavpil-" + newState + "'>" + data.statusString + "</span>";
|
|
|
|
pavpill.html(statusHtml);
|
|
|
|
})
|
|
|
|
.fail(function (data) {
|
|
|
|
pavpill.html(originalHtml.replace("dropdown-menu pull-right show", "dropdown-menu pull-right"));
|
|
|
|
alert("Invoice state update failed");
|
|
|
|
});
|
|
|
|
}
|
2019-04-05 16:44:30 +02:00
|
|
|
</script>
|
2019-04-30 05:45:33 +02:00
|
|
|
|
|
|
|
<style type="text/css">
|
|
|
|
.invoice-payments h3 {
|
|
|
|
font-size: 15px;
|
|
|
|
font-weight: bold;
|
|
|
|
}
|
2019-04-30 06:25:11 +02:00
|
|
|
|
|
|
|
.wraptext200 {
|
|
|
|
max-width: 200px;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
overflow: hidden;
|
|
|
|
display: block;
|
|
|
|
white-space: nowrap;
|
|
|
|
}
|
2019-05-01 22:33:46 +02:00
|
|
|
|
|
|
|
.pavpill {
|
|
|
|
display: inline-block;
|
|
|
|
padding: 0.3em 0.5em;
|
|
|
|
font-size: 85%;
|
|
|
|
font-weight: 500;
|
|
|
|
line-height: 1;
|
|
|
|
text-align: center;
|
|
|
|
white-space: nowrap;
|
|
|
|
vertical-align: baseline;
|
|
|
|
border-radius: 0.25rem;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pavpill.dropdown-toggle {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
2019-05-03 21:54:40 +02:00
|
|
|
.dropdown-item {
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
2019-05-01 22:33:46 +02:00
|
|
|
.pavpil-new {
|
|
|
|
background: #d4edda;
|
|
|
|
color: #000;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pavpil-expired {
|
|
|
|
background: #eee;
|
|
|
|
color: #000;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pavpil-invalid {
|
|
|
|
background: #c94a47;
|
|
|
|
color: #fff;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pavpil-confirmed, .pavpil-paid {
|
|
|
|
background: #f1c332;
|
|
|
|
color: #000;
|
|
|
|
}
|
|
|
|
|
|
|
|
.pavpil-complete {
|
|
|
|
background: #329f80;
|
|
|
|
color: #fff;
|
|
|
|
}
|
2019-04-30 05:45:33 +02:00
|
|
|
</style>
|
2017-10-27 10:53:04 +02:00
|
|
|
</section>
|