mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-02-20 13:34:37 +01:00
Remove Confirmed state in UI (#3090)
* Remove Confirmed state in UI Closes #1789. * Add infobox & improve refund tooltip * Update BTCPayServer/Views/Invoice/ListInvoices.cshtml Add @dennisreimann suggestion Co-authored-by: d11n <mail@dennisreimann.de> * Add "don't show again" button Adds a "Don't Show Again" button to the infobox. Also a bugfix that was preventing the new status from showing in the invoice details page. * Add User blob and move invoice status notice to it Co-authored-by: d11n <mail@dennisreimann.de> Co-authored-by: Kukks <evilkukka@gmail.com>
This commit is contained in:
parent
f6afb9a3f0
commit
ec68d2a0e6
14 changed files with 225 additions and 50 deletions
|
@ -19,6 +19,8 @@ namespace BTCPayServer.Data
|
|||
public List<NotificationData> Notifications { get; set; }
|
||||
public List<UserStore> UserStores { get; set; }
|
||||
public List<Fido2Credential> Fido2Credentials { get; set; }
|
||||
|
||||
public byte[] Blob { get; set; }
|
||||
|
||||
public List<IdentityUserRole<string>> UserRoles { get; set; }
|
||||
|
||||
|
|
29
BTCPayServer.Data/Migrations/20211125081400_AddUserBlob.cs
Normal file
29
BTCPayServer.Data/Migrations/20211125081400_AddUserBlob.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace BTCPayServer.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20211125081400_AddUserBlob")]
|
||||
public partial class AddUserBlob : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<byte[]>(
|
||||
name: "Blob",
|
||||
table: "AspNetUsers",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Blob",
|
||||
table: "AspNetUsers");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,6 +105,9 @@ namespace BTCPayServer.Migrations
|
|||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("Blob")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
|
|
@ -104,7 +104,7 @@ namespace BTCPayServer.Controllers
|
|||
StoreLink = Url.Action(nameof(StoresController.PaymentMethods), "Stores", new { storeId = store.Id }),
|
||||
PaymentRequestLink = Url.Action(nameof(PaymentRequestController.ViewPaymentRequest), "PaymentRequest", new { id = invoice.Metadata.PaymentRequestId }),
|
||||
Id = invoice.Id,
|
||||
State = invoiceState.ToString(),
|
||||
State = invoiceState.Status.ToModernStatus().ToString(),
|
||||
TransactionSpeed = invoice.SpeedPolicy == SpeedPolicy.HighSpeed ? "high" :
|
||||
invoice.SpeedPolicy == SpeedPolicy.MediumSpeed ? "medium" :
|
||||
invoice.SpeedPolicy == SpeedPolicy.LowMediumSpeed ? "low-medium" :
|
||||
|
@ -128,7 +128,7 @@ namespace BTCPayServer.Controllers
|
|||
.Select(c => new Models.StoreViewModels.DeliveryViewModel(c))
|
||||
.ToList(),
|
||||
CanMarkInvalid = invoiceState.CanMarkInvalid(),
|
||||
CanMarkComplete = invoiceState.CanMarkComplete(),
|
||||
CanMarkSettled = invoiceState.CanMarkComplete(),
|
||||
};
|
||||
model.Addresses = invoice.HistoricalAddresses.Select(h =>
|
||||
new InvoiceDetailsModel.AddressModel
|
||||
|
@ -763,7 +763,7 @@ namespace BTCPayServer.Controllers
|
|||
RedirectUrl = invoice.RedirectURL?.AbsoluteUri ?? string.Empty,
|
||||
AmountCurrency = _CurrencyNameTable.DisplayFormatCurrency(invoice.Price, invoice.Currency),
|
||||
CanMarkInvalid = state.CanMarkInvalid(),
|
||||
CanMarkComplete = state.CanMarkComplete(),
|
||||
CanMarkSettled = state.CanMarkComplete(),
|
||||
Details = InvoicePopulatePayments(invoice),
|
||||
});
|
||||
}
|
||||
|
@ -936,10 +936,10 @@ namespace BTCPayServer.Controllers
|
|||
await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Invalid);
|
||||
model.StatusString = new InvoiceState("invalid", "marked").ToString();
|
||||
}
|
||||
else if (newState == "complete")
|
||||
else if (newState == "settled")
|
||||
{
|
||||
await _InvoiceRepository.MarkInvoiceStatus(invoiceId, InvoiceStatus.Settled);
|
||||
model.StatusString = new InvoiceState("complete", "marked").ToString();
|
||||
model.StatusString = new InvoiceState("settled", "marked").ToString();
|
||||
}
|
||||
|
||||
return Json(model);
|
||||
|
@ -999,6 +999,5 @@ namespace BTCPayServer.Controllers
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,6 +85,26 @@ namespace BTCPayServer.Controllers
|
|||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> DisableShowInvoiceStatusChangeHint()
|
||||
{
|
||||
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (user == null)
|
||||
{
|
||||
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
|
||||
}
|
||||
|
||||
var blob = user.GetBlob();
|
||||
blob.ShowInvoiceStatusChangeHint = false;
|
||||
if (user.SetBlob(blob))
|
||||
{
|
||||
await _userManager.UpdateAsync(user);
|
||||
}
|
||||
return RedirectToAction(nameof(Index));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Index(IndexViewModel model)
|
||||
|
|
33
BTCPayServer/Extensions/UserExtensions.cs
Normal file
33
BTCPayServer/Extensions/UserExtensions.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using System.Linq;
|
||||
using BTCPayServer.Data;
|
||||
using BTCPayServer.Services.Invoices;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer
|
||||
{
|
||||
public static class UserExtensions
|
||||
{
|
||||
public static UserBlob GetBlob(this ApplicationUser user)
|
||||
{
|
||||
var result = user.Blob == null
|
||||
? new UserBlob()
|
||||
: JObject.Parse(ZipUtils.Unzip(user.Blob)).ToObject<UserBlob>();
|
||||
return result;
|
||||
}
|
||||
public static bool SetBlob(this ApplicationUser user, UserBlob blob)
|
||||
{
|
||||
var newBytes = InvoiceRepository.ToBytes(blob);
|
||||
if (user.Blob != null && newBytes.SequenceEqual(user.Blob))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
user.Blob = newBytes;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class UserBlob
|
||||
{
|
||||
public bool ShowInvoiceStatusChangeHint { get; set; }
|
||||
}
|
||||
}
|
|
@ -163,6 +163,12 @@ namespace BTCPayServer.Hosting
|
|||
settings.MigratePayoutDestinationId = true;
|
||||
await _Settings.UpdateSetting(settings);
|
||||
}
|
||||
if (!settings.AddInitialUserBlob)
|
||||
{
|
||||
await AddInitialUserBlob();
|
||||
settings.AddInitialUserBlob = true;
|
||||
await _Settings.UpdateSetting(settings);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -171,6 +177,16 @@ namespace BTCPayServer.Hosting
|
|||
}
|
||||
}
|
||||
|
||||
private async Task AddInitialUserBlob()
|
||||
{
|
||||
await using var ctx = _DBContextFactory.CreateContext();
|
||||
foreach (var user in await ctx.Users.AsQueryable().ToArrayAsync())
|
||||
{
|
||||
user.SetBlob(new UserBlob() { ShowInvoiceStatusChangeHint = true });
|
||||
}
|
||||
await ctx.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private async Task MigratePayoutDestinationId()
|
||||
{
|
||||
await using var ctx = _DBContextFactory.CreateContext();
|
||||
|
|
|
@ -129,8 +129,8 @@ namespace BTCPayServer.Models.InvoicingModels
|
|||
public bool Archived { get; set; }
|
||||
public bool CanRefund { get; set; }
|
||||
public bool ShowCheckout { get; set; }
|
||||
public bool CanMarkComplete { get; set; }
|
||||
public bool CanMarkSettled { get; set; }
|
||||
public bool CanMarkInvalid { get; set; }
|
||||
public bool CanMarkStatus => CanMarkComplete || CanMarkInvalid;
|
||||
public bool CanMarkStatus => CanMarkSettled || CanMarkInvalid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@ namespace BTCPayServer.Models.InvoicingModels
|
|||
public string InvoiceId { get; set; }
|
||||
|
||||
public InvoiceState Status { get; set; }
|
||||
public bool CanMarkComplete { get; set; }
|
||||
public bool CanMarkSettled { get; set; }
|
||||
public bool CanMarkInvalid { get; set; }
|
||||
public bool CanMarkStatus => CanMarkComplete || CanMarkInvalid;
|
||||
public bool CanMarkStatus => CanMarkSettled || CanMarkInvalid;
|
||||
public bool ShowCheckout { get; set; }
|
||||
public string ExceptionStatus { get; set; }
|
||||
public string AmountCurrency { get; set; }
|
||||
|
|
|
@ -27,5 +27,6 @@ namespace BTCPayServer.Services
|
|||
public int? MigratedInvoiceTextSearchPages { get; set; }
|
||||
public bool MigrateAppCustomOption { get; set; }
|
||||
public bool MigratePayoutDestinationId { get; set; }
|
||||
public bool AddInitialUserBlob { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@
|
|||
<p>
|
||||
<ul>
|
||||
<li>Send a <code>GET</code> request to <code>https://btcpay.example.com/invoices/{invoiceId}</code> with <code>Content-Type: application/json; Authorization: Basic YourLegacyAPIkey"</code>, Legacy API key can be created with Access Tokens in Store settings</li>
|
||||
<li>Verify that the <code>orderId</code> is from your backend, that the <code>price</code> is correct and that <code>status</code> is either <code>confirmed</code> or <code>complete</code></li>
|
||||
<li>Verify that the <code>orderId</code> is from your backend, that the <code>price</code> is correct and that <code>status</code> is <code>settled</code></li>
|
||||
<li>You can then ship your order</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
@using BTCPayServer.Client.Models
|
||||
@model InvoiceDetailsModel
|
||||
@{
|
||||
ViewData["Title"] = $"Invoice {Model.Id}";
|
||||
|
@ -20,7 +21,7 @@
|
|||
$.post(invoiceId + "/changestate/" + newState)
|
||||
.done(function (data) {
|
||||
var alertClassModifier = {
|
||||
"complete (marked)": 'success',
|
||||
"settled (marked)": 'success',
|
||||
"invalid (marked)": 'danger'
|
||||
}[data.statusString];
|
||||
var statusHtml = "<span class='fs-6 fw-normal badge bg-" + alertClassModifier + "'>" + data.statusString + " <span class='fa fa-check'></span></span>"
|
||||
|
@ -63,7 +64,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<button href="#" class="btn btn-secondary text-nowrap" data-bs-toggle="tooltip" title="You can only issue refunds on invoices with confirmed payments" disabled><span class="fa fa-undo me-1"></span> Issue Refund</button>
|
||||
<button href="#" class="btn btn-secondary text-nowrap" data-bs-toggle="tooltip" title="You can only refund an invoice that has been settled. Please wait for the transaction to confirm on the blockchain before attempting to refund it." disabled><span class="fa fa-undo me-1"></span> Issue refund</button>
|
||||
}
|
||||
<form class="p-0 ms-3" asp-action="ToggleArchive" asp-route-invoiceId="@Model.Id" method="post">
|
||||
<button type="submit" class="btn @(Model.Archived ? "btn-warning" : "btn btn-danger")" id="btn-archive-toggle">
|
||||
|
@ -127,6 +128,10 @@
|
|||
<div class="dropdown">
|
||||
<button class="btn btn-secondary btn-sm dropdown-toggle py-1 px-2" type="button" id="markStatusDropdownMenuButton" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@Model.State
|
||||
@if (Model.StatusException != InvoiceExceptionStatus.None)
|
||||
{
|
||||
@String.Format("({0})", Model.StatusException.ToString());
|
||||
}
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="markStatusDropdownMenuButton">
|
||||
@if (Model.CanMarkInvalid)
|
||||
|
@ -135,10 +140,10 @@
|
|||
Mark as invalid <span class="fa fa-times"></span>
|
||||
</a>
|
||||
}
|
||||
@if (Model.CanMarkComplete)
|
||||
@if (Model.CanMarkSettled)
|
||||
{
|
||||
<a class="dropdown-item" href="#" data-id="@Model.Id" data-status="complete" data-change-invoice-status-button>
|
||||
Mark as complete <span class="fa fa-check-circle"></span>
|
||||
<a class="dropdown-item" href="#" data-id="@Model.Id" data-status="settled" data-change-invoice-status-button>
|
||||
Mark as settled <span class="fa fa-check-circle"></span>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
|
@ -147,6 +152,10 @@
|
|||
else
|
||||
{
|
||||
@Model.State
|
||||
@if (Model.StatusException != InvoiceExceptionStatus.None)
|
||||
{
|
||||
@String.Format(" ({0})", Model.StatusException.ToString());
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -384,4 +393,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
|
57
BTCPayServer/Views/Invoice/InvoiceStatusChangePartial.cshtml
Normal file
57
BTCPayServer/Views/Invoice/InvoiceStatusChangePartial.cshtml
Normal file
|
@ -0,0 +1,57 @@
|
|||
@inject UserManager<ApplicationUser> _userManager
|
||||
|
||||
@* This is a temporary infobox to inform users about the state changes in 1.4.0. It should be removed eventually. *@
|
||||
@if ((await _userManager.GetUserAsync(User)).GetBlob().ShowInvoiceStatusChangeHint)
|
||||
{
|
||||
<div class="row">
|
||||
<div class="alert alert-light alert-dismissible fade show" role="alert">
|
||||
<form method="post" asp-controller="Manage" asp-action="DisableShowInvoiceStatusChangeHint" id="invoicestatuschangeform">
|
||||
<h6><strong>Update v1.4.0:</strong> Invoice states have been updated to match the Greenfield API.</h6>
|
||||
<div class="float-start">
|
||||
<ul class="list-unstyled">
|
||||
<li>
|
||||
<span class="badge badge-processing">Paid</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
|
||||
</svg>
|
||||
<span class="badge badge-processing">Processing</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge badge-settled">Completed</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
|
||||
</svg>
|
||||
<span class="badge badge-settled">Settled</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="badge badge-settled">Confirmed</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-right" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h11.793l-3.147-3.146a.5.5 0 0 1 .708-.708l4 4a.5.5 0 0 1 0 .708l-4 4a.5.5 0 0 1-.708-.708L13.293 8.5H1.5A.5.5 0 0 1 1 8z"/>
|
||||
</svg>
|
||||
<span class="badge badge-settled">Settled</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="float-end">
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="alert">
|
||||
Dismiss
|
||||
</button>
|
||||
<button name="command" type="submit" value="save" class="btn btn-danger" data-bs-dismiss="alert">
|
||||
Don't Show Again
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
document.getElementById("invoicestatuschangeform").addEventListener("submit", function (event) {
|
||||
event.preventDefault();
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.open('POST', event.target.getAttribute('action'), true);
|
||||
xhttp.send(new FormData(event.target));
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -1,3 +1,4 @@
|
|||
@using BTCPayServer.Client.Models
|
||||
@model InvoicesModel
|
||||
@{
|
||||
ViewData.SetActivePageAndTitle(InvoiceNavPages.Index, "Invoices");
|
||||
|
@ -58,14 +59,13 @@
|
|||
background: #c94a47;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-confirmed,
|
||||
.badge-paid {
|
||||
|
||||
.badge-processing {
|
||||
background: #f1c332;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.badge-complete {
|
||||
|
||||
.badge-settled {
|
||||
background: #329f80;
|
||||
color: #fff;
|
||||
}
|
||||
|
@ -182,22 +182,23 @@
|
|||
<div class="container">
|
||||
<partial name="_StatusMessage" />
|
||||
|
||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||
<h2 class="mb-0">
|
||||
@ViewData["Title"]
|
||||
<small>
|
||||
<a href="https://docs.btcpayserver.org/PaymentRequests/" class="ms-1" target="_blank" rel="noreferrer noopener">
|
||||
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
||||
</a>
|
||||
</small>
|
||||
</h2>
|
||||
<a id="CreateNewInvoice" asp-action="CreateInvoice" asp-route-searchTerm="@Model.SearchTerm" class="btn btn-primary mt-3 mt-sm-0">
|
||||
<span class="fa fa-plus"></span>
|
||||
Create an invoice
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||
<h2 class="mb-0">
|
||||
@ViewData["Title"]
|
||||
<small>
|
||||
<a href="https://docs.btcpayserver.org/PaymentRequests/" class="ms-1" target="_blank" rel="noreferrer noopener">
|
||||
<span class="fa fa-question-circle-o text-secondary" title="More information..."></span>
|
||||
</a>
|
||||
</small>
|
||||
</h2>
|
||||
<a id="CreateNewInvoice" asp-action="CreateInvoice" asp-route-searchTerm="@Model.SearchTerm" class="btn btn-primary mt-3 mt-sm-0">
|
||||
<span class="fa fa-plus"></span>
|
||||
Create an invoice
|
||||
</a>
|
||||
</div>
|
||||
<partial name="InvoiceStatusChangePartial"/>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 col-lg-6 mb-5 mb-lg-2 ms-auto">
|
||||
<form asp-action="ListInvoices" method="get">
|
||||
<input type="hidden" asp-for="Count"/>
|
||||
|
@ -216,7 +217,7 @@
|
|||
|
||||
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="SearchOptionsToggle">
|
||||
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:invalid@{@storeIds}">Invalid Invoices</a>
|
||||
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:paid,status:confirmed,status:complete@{@storeIds}">Paid Invoices</a>
|
||||
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="status:processing,status:settled@{@storeIds}">Paid Invoices</a>
|
||||
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidLate@{@storeIds}">Paid Late Invoices</a>
|
||||
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidPartial@{@storeIds}">Paid Partial Invoices</a>
|
||||
<a class="dropdown-item" asp-action="ListInvoices" asp-route-count="@Model.Count" asp-route-searchTerm="exceptionstatus:paidOver@{@storeIds}">Paid Over Invoices</a>
|
||||
|
@ -295,15 +296,12 @@
|
|||
<li><code>storeid:id</code> for filtering a specific store</li>
|
||||
<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>
|
||||
<li><code>status:(expired|invalid|complete|confirmed|paid|new)</code> for filtering a specific status</li>
|
||||
<li><code>status:(expired|invalid|settled|processing|new)</code> for filtering a specific status</li>
|
||||
<li><code>exceptionstatus:(paidover|paidlate|paidpartial)</code> for filtering a specific exception state</li>
|
||||
<li><code>unusual:(true|false)</code> for filtering invoices which might requires merchant attention (those invalid or with an exceptionstatus)</li>
|
||||
<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>
|
||||
</ul>
|
||||
<p>
|
||||
If you want all confirmed and complete invoices, you can duplicate a filter <code>status:confirmed, status:complete</code>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -381,9 +379,13 @@
|
|||
}
|
||||
@if (invoice.CanMarkStatus)
|
||||
{
|
||||
<div id="pavpill_@invoice.InvoiceId" class="badge badge-@invoice.Status.ToString().ToLower()">
|
||||
<div id="pavpill_@invoice.InvoiceId" class="badge badge-@invoice.Status.Status.ToModernStatus().ToString().ToLower()">
|
||||
<span class="dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
@invoice.Status.ToString()
|
||||
@invoice.Status.Status.ToModernStatus().ToString() @* @invoice.Status.ToString() *@
|
||||
@if (invoice.Status.ExceptionStatus != InvoiceExceptionStatus.None)
|
||||
{
|
||||
@String.Format("({0})", @invoice.Status.ExceptionStatus.ToString());
|
||||
}
|
||||
</span>
|
||||
<div class="dropdown-menu pull-right">
|
||||
@if (invoice.CanMarkInvalid)
|
||||
|
@ -392,10 +394,10 @@
|
|||
Mark as invalid <span class="fa fa-times"></span>
|
||||
</button>
|
||||
}
|
||||
@if (invoice.CanMarkComplete)
|
||||
@if (invoice.CanMarkSettled)
|
||||
{
|
||||
<button class="dropdown-item small cursorPointer changeInvoiceState" data-invoice-id="@invoice.InvoiceId" data-new-state="complete">
|
||||
Mark as complete <span class="fa fa-check-circle"></span>
|
||||
<button class="dropdown-item small cursorPointer changeInvoiceState" data-invoice-id="@invoice.InvoiceId" data-new-state="settled">
|
||||
Mark as settled <span class="fa fa-check-circle"></span>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
@ -403,8 +405,12 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
<span class="badge badge-@invoice.Status.ToString().ToLower()">
|
||||
@invoice.Status.ToString().ToLower()
|
||||
<span class="badge badge-@invoice.Status.Status.ToModernStatus().ToString().ToLower()">
|
||||
@invoice.Status.Status.ToModernStatus().ToString() @* @invoice.Status.ToString().ToLower() *@
|
||||
@if (invoice.Status.ExceptionStatus != InvoiceExceptionStatus.None)
|
||||
{
|
||||
@String.Format("({0})", @invoice.Status.ExceptionStatus.ToString());
|
||||
}
|
||||
</span>
|
||||
}
|
||||
@foreach (var paymentType in invoice.Details.Payments.Select(payment => payment.GetPaymentMethodId()?.PaymentType).Distinct().Where(type => type != null && !string.IsNullOrEmpty(type.GetBadge())))
|
||||
|
|
Loading…
Add table
Reference in a new issue