mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 16:00:56 -04:00
Merge pull request #4029 from beganovich/v2-show-payment-fees-in-invoice-table
Show gateway fees status for invoices
This commit is contained in:
commit
dc4f6d0d5c
@ -20,35 +20,37 @@ class InvoicesTable extends Component
|
|||||||
|
|
||||||
public $status = [];
|
public $status = [];
|
||||||
|
|
||||||
public function statusChange($status)
|
|
||||||
{
|
|
||||||
if (in_array($status, $this->status)) {
|
|
||||||
return $this->status = array_diff($this->status, [$status]);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_push($this->status, $status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
|
$local_status = [];
|
||||||
|
|
||||||
$query = Invoice::query()
|
$query = Invoice::query()
|
||||||
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');
|
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');
|
||||||
|
|
||||||
if (in_array('paid', $this->status)) {
|
if (in_array('paid', $this->status)) {
|
||||||
$query = $query->orWhere('status_id', Invoice::STATUS_PAID);
|
$local_status[] = Invoice::STATUS_PAID;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array('unpaid', $this->status)) {
|
if (in_array('unpaid', $this->status)) {
|
||||||
$query = $query->orWhereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]);
|
$local_status[] = Invoice::STATUS_SENT;
|
||||||
|
$local_status[] = Invoice::STATUS_PARTIAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array('overdue', $this->status)) {
|
if (in_array('overdue', $this->status)) {
|
||||||
$query = $query->orWhereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
$local_status[] = Invoice::STATUS_SENT;
|
||||||
->where(function ($query) {
|
$local_status[] = Invoice::STATUS_PARTIAL;
|
||||||
$query
|
}
|
||||||
->orWhere('due_date', '<', Carbon::now())
|
|
||||||
->orWhere('partial_due_date', '<', Carbon::now());
|
if (count($local_status) > 0) {
|
||||||
});
|
$query = $query->whereIn('status_id', array_unique($local_status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array('overdue', $this->status)) {
|
||||||
|
$query = $query->where(function ($query) {
|
||||||
|
$query
|
||||||
|
->orWhere('due_date', '<', Carbon::now())
|
||||||
|
->orWhere('partial_due_date', '<', Carbon::now());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $query
|
$query = $query
|
||||||
@ -56,6 +58,27 @@ class InvoicesTable extends Component
|
|||||||
->where('status_id', '<>', Invoice::STATUS_DRAFT)
|
->where('status_id', '<>', Invoice::STATUS_DRAFT)
|
||||||
->paginate($this->per_page);
|
->paginate($this->per_page);
|
||||||
|
|
||||||
|
if (in_array('gateway_fees', $this->status)) {
|
||||||
|
$transformed = $query
|
||||||
|
->getCollection()
|
||||||
|
->filter(function ($invoice) {
|
||||||
|
$invoice['line_items'] = collect($invoice->line_items)
|
||||||
|
->filter(function ($item) {
|
||||||
|
return $item->type_id == "4" || $item->type_id == 4;
|
||||||
|
});
|
||||||
|
|
||||||
|
return count($invoice['line_items']);
|
||||||
|
});
|
||||||
|
|
||||||
|
$query = new \Illuminate\Pagination\LengthAwarePaginator(
|
||||||
|
$transformed,
|
||||||
|
$transformed->count(),
|
||||||
|
$query->perPage(),
|
||||||
|
$query->currentPage(),
|
||||||
|
['path' => request()->url(), 'query' => ['page' => $query->currentPage()]]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return render('components.livewire.invoices-table', [
|
return render('components.livewire.invoices-table', [
|
||||||
'invoices' => $query,
|
'invoices' => $query,
|
||||||
]);
|
]);
|
||||||
|
@ -4,6 +4,7 @@ namespace App\Http\Livewire;
|
|||||||
|
|
||||||
use App\Models\Quote;
|
use App\Models\Quote;
|
||||||
use App\Utils\Traits\WithSorting;
|
use App\Utils\Traits\WithSorting;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Livewire\WithPagination;
|
use Livewire\WithPagination;
|
||||||
|
|
||||||
@ -15,34 +16,13 @@ class QuotesTable extends Component
|
|||||||
public $per_page = 10;
|
public $per_page = 10;
|
||||||
public $status = [];
|
public $status = [];
|
||||||
|
|
||||||
public function statusChange($status)
|
|
||||||
{
|
|
||||||
if (in_array($status, $this->status)) {
|
|
||||||
return $this->status = array_diff($this->status, [$status]);
|
|
||||||
}
|
|
||||||
|
|
||||||
array_push($this->status, $status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function render()
|
public function render()
|
||||||
{
|
{
|
||||||
$query = Quote::query()
|
$query = Quote::query()
|
||||||
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');
|
->orderBy($this->sort_field, $this->sort_asc ? 'asc' : 'desc');
|
||||||
|
|
||||||
if (in_array('draft', $this->status)) {
|
if (count($this->status) > 0) {
|
||||||
$query = $query->orWhere('status_id', Quote::STATUS_DRAFT);
|
$query = $query->whereIn('status_id', $this->status);
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array('sent', $this->status)) {
|
|
||||||
$query = $query->orWhere('status_id', Quote::STATUS_SENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array('approved', $this->status)) {
|
|
||||||
$query = $query->orWhere('status_id', Quote::STATUS_APPROVED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_array('expired', $this->status)) {
|
|
||||||
$query = $query->orWhere('status_id', Quote::STATUS_EXPIRED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $query
|
$query = $query
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<span class="mr-2 text-sm hidden md:block">{{ ctrans('texts.per_page') }}</span>
|
<span class="hidden mr-2 text-sm md:block">{{ ctrans('texts.per_page') }}</span>
|
||||||
<select wire:model="per_page" class="form-select py-1 text-sm">
|
<select wire:model="per_page" class="py-1 text-sm form-select">
|
||||||
<option>5</option>
|
<option>5</option>
|
||||||
<option selected>10</option>
|
<option selected>10</option>
|
||||||
<option>15</option>
|
<option>15</option>
|
||||||
@ -11,50 +11,54 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('paid')" type="checkbox" class="form-checkbox cursor-pointer" id="paid-checkbox">
|
<input wire:model="status" value="paid" type="checkbox" class="cursor-pointer form-checkbox" id="paid-checkbox">
|
||||||
<label for="paid-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_paid') }}</label>
|
<label for="paid-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_paid') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('unpaid')" type="checkbox" class="form-checkbox cursor-pointer" id="unpaid-checkbox">
|
<input wire:model="status" value="unpaid" type="checkbox" class="cursor-pointer form-checkbox" id="unpaid-checkbox">
|
||||||
<label for="unpaid-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_unpaid') }}</label>
|
<label for="unpaid-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_unpaid') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('overdue')" type="checkbox" class="form-checkbox cursor-pointer" id="overdue-checkbox">
|
<input wire:model="status" value="overdue" type="checkbox" class="cursor-pointer form-checkbox" id="overdue-checkbox">
|
||||||
<label for="overdue-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.overdue') }}</label>
|
<label for="overdue-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.overdue') }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mr-3">
|
||||||
|
<input wire:model="status" value="gateway_fees" type="checkbox" class="cursor-pointer form-checkbox" id="gateway-fees-checkbox">
|
||||||
|
<label for="gateway-fees-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.gateway_fees') }}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
<div class="py-2 -my-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
||||||
<div class="align-middle inline-block min-w-full overflow-hidden rounded">
|
<div class="inline-block min-w-full overflow-hidden align-middle rounded">
|
||||||
<table class="min-w-full shadow rounded border border-gray-200 mt-4 invoices-table">
|
<table class="min-w-full mt-4 border border-gray-200 rounded shadow invoices-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" class="form-check form-check-parent">
|
<input type="checkbox" class="form-check form-check-parent">
|
||||||
</label>
|
</label>
|
||||||
</th>
|
</th>
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
|
||||||
<span role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
<span role="button" wire:click="sortBy('number')" class="cursor-pointer">
|
||||||
{{ ctrans('texts.invoice_number') }}
|
{{ ctrans('texts.invoice_number') }}
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
|
||||||
<span role="button" wire:click="sortBy('date')" class="cursor-pointer">
|
<span role="button" wire:click="sortBy('date')" class="cursor-pointer">
|
||||||
{{ ctrans('texts.invoice_date') }}
|
{{ ctrans('texts.invoice_date') }}
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
|
||||||
<span role="button" wire:click="sortBy('balance')" class="cursor-pointer">
|
<span role="button" wire:click="sortBy('balance')" class="cursor-pointer">
|
||||||
{{ ctrans('texts.balance') }}
|
{{ ctrans('texts.balance') }}
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
|
||||||
<span role="button" wire:click="sortBy('due_date')" class="cursor-pointer">
|
<span role="button" wire:click="sortBy('due_date')" class="cursor-pointer">
|
||||||
{{ ctrans('texts.due_date') }}
|
{{ ctrans('texts.due_date') }}
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">
|
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-gray-500 uppercase border-b border-gray-200 bg-gray-50">
|
||||||
<span role="button" wire:click="sortBy('status_id')" class="cursor-pointer">
|
<span role="button" wire:click="sortBy('status_id')" class="cursor-pointer">
|
||||||
{{ ctrans('texts.status') }}
|
{{ ctrans('texts.status') }}
|
||||||
</span>
|
</span>
|
||||||
@ -65,33 +69,33 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
@forelse($invoices as $invoice)
|
@forelse($invoices as $invoice)
|
||||||
<tr class="bg-white group hover:bg-gray-100">
|
<tr class="bg-white group hover:bg-gray-100">
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
|
<td class="px-6 py-4 text-sm font-medium leading-5 text-gray-900 whitespace-no-wrap">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" class="form-check form-check-child" data-value="{{ $invoice->hashed_id }}">
|
<input type="checkbox" class="form-check form-check-child" data-value="{{ $invoice->hashed_id }}">
|
||||||
</label>
|
</label>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap">
|
||||||
{{ $invoice->number }}
|
{{ $invoice->number }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap">
|
||||||
{{ $invoice->formatDate($invoice->date, $invoice->client->date_format()) }}
|
{{ $invoice->formatDate($invoice->date, $invoice->client->date_format()) }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap">
|
||||||
{{ App\Utils\Number::formatMoney($invoice->balance, $invoice->client) }}
|
{{ App\Utils\Number::formatMoney($invoice->balance, $invoice->client) }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap">
|
||||||
{{ $invoice->formatDate($invoice->due_date, $invoice->client->date_format()) }}
|
{{ $invoice->formatDate($invoice->due_date, $invoice->client->date_format()) }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
<td class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap">
|
||||||
{!! App\Models\Invoice::badgeForStatus($invoice->status) !!}
|
{!! App\Models\Invoice::badgeForStatus($invoice->status) !!}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-no-wrap flex items-center justify-end text-sm leading-5 font-medium">
|
<td class="flex items-center justify-end px-6 py-4 text-sm font-medium leading-5 whitespace-no-wrap">
|
||||||
@if($invoice->isPayable())
|
@if($invoice->isPayable())
|
||||||
<form action="{{ route('client.invoices.bulk') }}" method="post">
|
<form action="{{ route('client.invoices.bulk') }}" method="post">
|
||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">
|
<input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">
|
||||||
<input type="hidden" name="action" value="payment">
|
<input type="hidden" name="action" value="payment">
|
||||||
<button class="button button-primary py-1 px-2 text-xs uppercase mr-3">
|
<button class="px-2 py-1 mr-3 text-xs uppercase button button-primary">
|
||||||
@lang('texts.pay_now')
|
@lang('texts.pay_now')
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@ -103,7 +107,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr class="bg-white group hover:bg-gray-100">
|
<tr class="bg-white group hover:bg-gray-100">
|
||||||
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500" colspan="100%">
|
<td class="px-6 py-4 text-sm leading-5 text-gray-500 whitespace-no-wrap" colspan="100%">
|
||||||
{{ ctrans('texts.no_results') }}
|
{{ ctrans('texts.no_results') }}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -112,9 +116,9 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center md:justify-between mt-6 mb-6">
|
<div class="flex justify-center mt-6 mb-6 md:justify-between">
|
||||||
@if($invoices->total() > 0)
|
@if($invoices->total() > 0)
|
||||||
<span class="text-gray-700 text-sm hidden md:block">
|
<span class="hidden text-sm text-gray-700 md:block">
|
||||||
{{ ctrans('texts.showing_x_of', ['first' => $invoices->firstItem(), 'last' => $invoices->lastItem(), 'total' => $invoices->total()]) }}
|
{{ ctrans('texts.showing_x_of', ['first' => $invoices->firstItem(), 'last' => $invoices->lastItem(), 'total' => $invoices->total()]) }}
|
||||||
</span>
|
</span>
|
||||||
@endif
|
@endif
|
||||||
|
@ -11,19 +11,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('draft')" type="checkbox" class="cursor-pointer form-checkbox" id="draft-checkbox">
|
<input wire:model="status" value="{{ App\Models\Quote::STATUS_DRAFT }}" type="checkbox" class="cursor-pointer form-checkbox" id="draft-checkbox">
|
||||||
<label for="draft-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_draft') }}</label>
|
<label for="draft-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_draft') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('sent')" value="sent" type="checkbox" class="cursor-pointer form-checkbox" id="sent-checkbox">
|
<input wire:model="status" value="{{ App\Models\Quote::STATUS_SENT }}" value="sent" type="checkbox" class="cursor-pointer form-checkbox" id="sent-checkbox">
|
||||||
<label for="sent-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_pending') }}</label>
|
<label for="sent-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.status_pending') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('approved')" value="approved" type="checkbox" class="cursor-pointer form-checkbox" id="approved-checkbox">
|
<input wire:model="status" value="{{ App\Models\Quote::STATUS_APPROVED }}" value="approved" type="checkbox" class="cursor-pointer form-checkbox" id="approved-checkbox">
|
||||||
<label for="approved-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.approved') }}</label>
|
<label for="approved-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.approved') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="mr-3">
|
<div class="mr-3">
|
||||||
<input wire:click="statusChange('expired')" value="expired" type="checkbox" class="cursor-pointer form-checkbox" id="expired-checkbox">
|
<input wire:model="status" value="{{ App\Models\Quote::STATUS_EXPIRED }}" value="expired" type="checkbox" class="cursor-pointer form-checkbox" id="expired-checkbox">
|
||||||
<label for="expired-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.expired') }}</label>
|
<label for="expired-checkbox" class="text-sm cursor-pointer">{{ ctrans('texts.expired') }}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user