mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Additions for Invoice Report
This commit is contained in:
parent
f470d10f96
commit
b5fd275dcd
@ -12,8 +12,10 @@
|
|||||||
namespace App\Export\CSV;
|
namespace App\Export\CSV;
|
||||||
|
|
||||||
use App\Models\Client;
|
use App\Models\Client;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Models\Invoice;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
||||||
class BaseExport
|
class BaseExport
|
||||||
{
|
{
|
||||||
@ -46,6 +48,60 @@ class BaseExport
|
|||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function addInvoiceStatusFilter($query, $status): Builder
|
||||||
|
{
|
||||||
|
|
||||||
|
$status_parameters = explode(',', $status);
|
||||||
|
|
||||||
|
|
||||||
|
if(in_array('all', $status_parameters))
|
||||||
|
return $query;
|
||||||
|
|
||||||
|
$query->where(function ($nested) use ($status_parameters) {
|
||||||
|
|
||||||
|
$invoice_filters = [];
|
||||||
|
|
||||||
|
if (in_array('draft', $status_parameters)) {
|
||||||
|
$invoice_filters[] = Invoice::STATUS_DRAFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array('sent', $status_parameters)) {
|
||||||
|
$invoice_filters[] = Invoice::STATUS_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array('paid', $status_parameters)) {
|
||||||
|
$invoice_filters[] = Invoice::STATUS_PAID;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array('unpaid', $status_parameters)) {
|
||||||
|
$invoice_filters[] = Invoice::STATUS_SENT;
|
||||||
|
$invoice_filters[] = Invoice::STATUS_PARTIAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($invoice_filters) > 0) {
|
||||||
|
$nested->whereIn('status_id', $invoice_filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array('overdue', $status_parameters)) {
|
||||||
|
$nested->orWhereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
|
->where('due_date', '<', Carbon::now())
|
||||||
|
->orWhere('partial_due_date', '<', Carbon::now());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(in_array('viewed', $status_parameters)){
|
||||||
|
|
||||||
|
$nested->whereHas('invitations', function ($q){
|
||||||
|
$q->whereNotNull('viewed_date')->whereNotNull('deleted_at');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
protected function addDateRange($query)
|
protected function addDateRange($query)
|
||||||
{
|
{
|
||||||
$date_range = $this->input['date_range'];
|
$date_range = $this->input['date_range'];
|
||||||
|
@ -11,13 +11,15 @@
|
|||||||
|
|
||||||
namespace App\Export\CSV;
|
namespace App\Export\CSV;
|
||||||
|
|
||||||
use App\Libraries\MultiDB;
|
use App\Utils\Ninja;
|
||||||
|
use App\Utils\Number;
|
||||||
|
use League\Csv\Writer;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
use App\Transformers\InvoiceTransformer;
|
use App\Libraries\MultiDB;
|
||||||
use App\Utils\Ninja;
|
use App\Export\CSV\BaseExport;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use League\Csv\Writer;
|
use App\Transformers\InvoiceTransformer;
|
||||||
|
|
||||||
class InvoiceExport extends BaseExport
|
class InvoiceExport extends BaseExport
|
||||||
{
|
{
|
||||||
@ -63,6 +65,10 @@ class InvoiceExport extends BaseExport
|
|||||||
'terms' => 'terms',
|
'terms' => 'terms',
|
||||||
'total_taxes' => 'total_taxes',
|
'total_taxes' => 'total_taxes',
|
||||||
'currency_id' => 'currency_id',
|
'currency_id' => 'currency_id',
|
||||||
|
'payment_number' => 'payment_number',
|
||||||
|
'payment_date' => 'payment_date',
|
||||||
|
'payment_amount' => 'payment_amount',
|
||||||
|
'method' => 'method',
|
||||||
];
|
];
|
||||||
|
|
||||||
private array $decorate_keys = [
|
private array $decorate_keys = [
|
||||||
@ -107,6 +113,10 @@ class InvoiceExport extends BaseExport
|
|||||||
|
|
||||||
$query = $this->addDateRange($query);
|
$query = $this->addDateRange($query);
|
||||||
|
|
||||||
|
if(isset($this->input['status'])){
|
||||||
|
$query = $this->addInvoiceStatusFilter($query, $this->input['status']);
|
||||||
|
}
|
||||||
|
|
||||||
$query->cursor()
|
$query->cursor()
|
||||||
->each(function ($invoice) {
|
->each(function ($invoice) {
|
||||||
$this->csv->insertOne($this->buildRow($invoice));
|
$this->csv->insertOne($this->buildRow($invoice));
|
||||||
@ -151,7 +161,17 @@ class InvoiceExport extends BaseExport
|
|||||||
if (in_array('status_id', $this->input['report_keys'])) {
|
if (in_array('status_id', $this->input['report_keys'])) {
|
||||||
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
$entity['status'] = $invoice->stringStatus($invoice->status_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$payment_exists = $invoice->payments()->exists();
|
||||||
|
|
||||||
|
$entity['payment_number'] = $payment_exists ? $invoice->payments()->pluck('number')->implode(',') : '';
|
||||||
|
|
||||||
|
$entity['payment_date'] = $payment_exists ? $invoice->payments()->pluck('date')->implode(',') : '';
|
||||||
|
|
||||||
|
$entity['payment_amount'] = $payment_exists ? Number::formatMoney($invoice->payments()->sum('paymentables.amount'), $invoice->company) : ctrans('texts.unpaid');
|
||||||
|
|
||||||
|
$entity['method'] = $payment_exists ? $invoice->payments()->first()->translatedType() : "";
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ class GenericReportRequest extends Request
|
|||||||
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
|
'start_date' => 'bail|required_if:date_range,custom|nullable|date',
|
||||||
'report_keys' => 'present|array',
|
'report_keys' => 'present|array',
|
||||||
'send_email' => 'required|bool',
|
'send_email' => 'required|bool',
|
||||||
|
'status' => 'sometimes|string|nullable|in:all,draft,sent,viewed,paid,unpaid,overdue',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
145
tests/Feature/Export/ReportApiTest.php
Normal file
145
tests/Feature/Export/ReportApiTest.php
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Tests\Feature\Export;
|
||||||
|
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||||
|
use Tests\MockAccountData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class ReportApiTest extends TestCase
|
||||||
|
{
|
||||||
|
use MakesHash;
|
||||||
|
use MockAccountData;
|
||||||
|
|
||||||
|
public $faker;
|
||||||
|
|
||||||
|
protected function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->faker = \Faker\Factory::create();
|
||||||
|
|
||||||
|
$this->withoutMiddleware(
|
||||||
|
ThrottleRequests::class
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->withoutExceptionHandling();
|
||||||
|
|
||||||
|
$this->makeTestData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUserSalesReportApiRoute()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'send_email' => false,
|
||||||
|
'date_range' => 'all',
|
||||||
|
'report_keys' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/reports/user_sales_report', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testTaxSummaryReportApiRoute()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'send_email' => false,
|
||||||
|
'date_range' => 'all',
|
||||||
|
'report_keys' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/reports/tax_summary_report', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testClientSalesReportApiRoute()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'send_email' => false,
|
||||||
|
'date_range' => 'all',
|
||||||
|
'report_keys' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/reports/client_sales_report', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testArDetailReportApiRoute()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'send_email' => false,
|
||||||
|
'date_range' => 'all',
|
||||||
|
'report_keys' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/reports/ar_detail_report', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testArSummaryReportApiRoute()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'send_email' => false,
|
||||||
|
'date_range' => 'all',
|
||||||
|
'report_keys' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/reports/ar_summary_report', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testClientBalanceReportApiRoute()
|
||||||
|
{
|
||||||
|
$data = [
|
||||||
|
'send_email' => false,
|
||||||
|
'date_range' => 'all',
|
||||||
|
'report_keys' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->withHeaders([
|
||||||
|
'X-API-SECRET' => config('ninja.api_secret'),
|
||||||
|
'X-API-TOKEN' => $this->token,
|
||||||
|
])->postJson('/api/v1/reports/client_balance_report', $data)
|
||||||
|
->assertStatus(200);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user