Files
btcpayserver/BTCPayServer/Views/Wallets/Payouts.cshtml
Andrew Camilleri cd9feccf6e Mark Payouts as Paid (#2539)
* Mark Payouts as Paid

This PR allows users to mark payouts as paid manually through the UI  and through the API. It also sets up the payout proof system to be able store a manual proof that will in a later PR allow you to specify a proof of payment (link or text)

* add docs, test and greenfield client

* remove extra docs stuff

* Update BTCPayServer.Tests/GreenfieldAPITests.cs

Co-authored-by: britttttk <39231115+britttttk@users.noreply.github.com>

* clean up pull payment/payouts fetch code

* Ensure payoutis are retrieved with pull payment

Co-authored-by: britttttk <39231115+britttttk@users.noreply.github.com>
2021-06-10 18:43:45 +09:00

147 lines
7.1 KiB
Plaintext

@using BTCPayServer.Client.Models
@model PayoutsModel
@inject IEnumerable<IPayoutHandler> PayoutHandlers;
@{
Layout = "../Shared/_NavLayout.cshtml";
ViewData.SetActivePageAndTitle(WalletsNavPages.Payouts, $"Manage {Model.PaymentMethodId.ToPrettyString()} payouts", Context.GetStoreData().StoreName);
}
@section PageFootContent {
<script>
function selectAll(e, elementClass)
{
const items = document.getElementsByClassName("selection-item-"+elementClass);
for (let i = 0; i < items.length; i++) {
items[i].checked = e.checked;
}
}
</script>
}
<form method="post">
<h4 class="mb-3">@ViewData["Title"]</h4>
@if (!Model.PayoutStateSets.Any())
{
<p class="text-secondary mt-3">
There are no payouts yet.
</p>
}
<div class="row">
<ul class="nav nav-pills">
@for (var index = 0; index < Model.PayoutStateSets.Count; index++)
{
var state = Model.PayoutStateSets[index];
<li class="nav-item py-0">
<a class="nav-link me-1 @(index == 0 ? "active" : "")" data-bs-toggle="tab" href="#@state.State" role="tab">@state.State.GetStateString() (@state.Payouts.Count)</a>
</li>
}
</ul>
</div>
<div class="row">
<div class="tab-content w-100">
@for (var index = 0; index < Model.PayoutStateSets.Count; index++)
{
var state = Model.PayoutStateSets[index];
var stateActions = new List<(string Action, string Text)>();
switch (state.State)
{
case PayoutState.AwaitingApproval:
stateActions.Add(("approve", "Approve selected payouts"));
stateActions.Add(("approve-pay", "Approve & Send selected payouts"));
stateActions.Add(("cancel", "Cancel selected payouts"));
break;
case PayoutState.AwaitingPayment:
stateActions.Add(("pay", "Send selected payouts"));
stateActions.Add(("cancel", "Cancel selected payouts"));
stateActions.Add(("mark-paid", "Mark selected payouts as already paid"));
break;
}
<div class="tab-pane @(index == 0 ? "active" : "") " id="@state.State" role="tabpanel">
<input type="hidden" asp-for="PayoutStateSets[index].State"/>
<input type="hidden" asp-for="PaymentMethodId"/>
@if (state.Payouts.Any() && stateActions.Any())
{
<div class="dropdown mt-2">
<button class="btn btn-primary dropdown-toggle" type="button" data-bs-toggle="dropdown" id="@state.State-actions">
Actions
</button>
<div class="dropdown-menu" aria-labelledby="@state.State-actions">
@foreach (var action in stateActions)
{
<button type="submit" id="@state.State-@action.Action" name="Command" class="dropdown-item" role="button" value="@state.State-@action.Action">@action.Text</button>
}
</div>
</div>
}
<div>
@if (state.Payouts.Any())
{
<table class="table table-sm table-responsive-lg">
<thead class="thead-inverse">
<tr>
<th>
<input id="@state.State-selectAllCheckbox" type="checkbox" class="form-check-input" onclick="selectAll(this, '@state.State.ToString()'); return true;"/>
</th>
<th style="min-width: 90px;" class="col-md-auto">
Date
</th>
<th class="text-start">Source</th>
<th class="text-start">Destination</th>
<th class="text-end">Amount</th>
@if (state.State != PayoutState.AwaitingApproval)
{
<th class="text-end">Transaction</th>
}
</tr>
</thead>
<tbody>
@for (int i = 0; i < state.Payouts.Count; i++)
{
var pp = state.Payouts[i];
<tr class="payout">
<td>
<span>
<input type="checkbox" class="selection-item-@state.State.ToString() form-check-input" asp-for="PayoutStateSets[index].Payouts[i].Selected"/>
<input type="hidden" asp-for="PayoutStateSets[index].Payouts[i].PayoutId"/>
</span>
</td>
<td>
<span>@pp.Date.ToBrowserDate()</span>
</td>
<td class="mw-100">
<span>@pp.PullPaymentName</span>
</td>
<td>
<span>@pp.Destination</span>
</td>
<td class="text-end">
<span>@pp.Amount</span>
</td>
@if (state.State != PayoutState.AwaitingApproval)
{
<td class="text-end">
@if (!(pp.ProofLink is null))
{
<a class="transaction-link" href="@pp.ProofLink">Link</a>
}
</td>
}
</tr>
}
</tbody>
</table>
}
else
{
<p class="mb-0 p-4" id="@state.State-no-payouts">No payouts.</p>
}
</div>
</div>
}
</div>
</div>
</form>