Report previews

This commit is contained in:
David Bomba 2023-08-18 23:36:54 +10:00
parent 2752a2e651
commit 10ad6e0423
7 changed files with 150 additions and 48 deletions

View File

@ -11,14 +11,15 @@
namespace App\Export\CSV;
use App\Libraries\MultiDB;
use App\Models\Company;
use App\Models\Credit;
use App\Transformers\CreditTransformer;
use App\Utils\Ninja;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Facades\App;
use App\Utils\Number;
use App\Models\Credit;
use League\Csv\Writer;
use App\Models\Company;
use App\Libraries\MultiDB;
use Illuminate\Support\Facades\App;
use App\Transformers\CreditTransformer;
use Illuminate\Contracts\Database\Eloquent\Builder;
class CreditExport extends BaseExport
{
@ -81,16 +82,43 @@ class CreditExport extends BaseExport
$this->credit_transformer = new CreditTransformer();
}
public function returnJson(string $hash)
public function returnJson()
{
$query = $this->init();
$header = $this->buildHeader();
$report = $query->cursor()
->map(function ($credit) {
return $this->buildRow($credit);
})->toJson();
->map(function ($credit) {
$row = $this->buildRow($credit);
return $this->processMetaData($row, $credit);
})->toArray();
return array_merge([$header], $report);
}
private function processMetaData(array $row, Credit $credit): array
{
$clean_row = [];
foreach ($this->input['report_keys'] as $key => $value) {
$report_keys = explode(".", $value);
$column_key = str_replace("credit.", "", $value);
$clean_row[$key]['entity'] = $report_keys[0];
$clean_row[$key]['id'] = $report_keys[1];
$clean_row[$key]['hashed_id'] = $report_keys[0] == 'credit' ? null : $credit->{$report_keys[0]}->hashed_id ?? null;
$clean_row[$key]['value'] = $row[$column_key];
if(in_array($report_keys[1], ['amount', 'balance', 'partial', 'refunded', 'applied','unit_cost','cost','price']))
$clean_row[$key]['display_value'] = Number::formatMoney($row[$column_key], $credit->client);
else
$clean_row[$key]['display_value'] = $row[$column_key];
}
return $clean_row;
}
private function init(): Builder
@ -102,6 +130,10 @@ class CreditExport extends BaseExport
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
$query = Credit::query()
->withTrashed()
->with('client')->where('company_id', $this->company->id)
@ -112,23 +144,19 @@ class CreditExport extends BaseExport
return $query;
}
public function run()
public function run(): string
{
$query = $this->init();
//load the CSV document from a string
$this->csv = Writer::createFromString();
if (count($this->input['report_keys']) == 0) {
$this->input['report_keys'] = array_values($this->entity_keys);
}
//insert the header
$this->csv->insertOne($this->buildHeader());
// nlog($this->input['report_keys']);
$query->cursor()
->each(function ($credit) {
nlog($this->buildRow($credit));
$this->csv->insertOne($this->buildRow($credit));
});

View File

@ -14,6 +14,7 @@ namespace App\Http\Controllers\Reports;
use App\Export\CSV\CreditExport;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Report\GenericReportRequest;
use App\Jobs\Report\PreviewReport;
use App\Jobs\Report\SendToAdmin;
use App\Utils\Traits\MakesHash;
use Illuminate\Http\Response;
@ -72,17 +73,17 @@ class CreditReportController extends BaseController
}
// expect a list of visible fields, or use the default
$export = new CreditExport($user->company(), $request->all());
if($request->has('output') && $request->input('output') == 'json') {
$hash = \Illuminate\Support\Str::uuid();
$data = $export->returnJson($hash);
PreviewReport::dispatch($user->company(), $request->all(), CreditExport::class, $hash);
return response()->json(['message' => $hash], 200);
}
$export = new CreditExport($user->company(), $request->all());
$csv = $export->run();
$headers = [

View File

@ -27,8 +27,6 @@ class ReportPreviewController extends BaseController
public function __invoke(ReportPreviewRequest $request, ?string $hash)
{
/** @var \App\Models\User $user */
$user = auth()->user();
$report = Cache::get($hash);

View File

@ -32,7 +32,6 @@ class ReportPreviewRequest extends Request
public function rules()
{
return [
'hash' => 'bail|required|string',
];
}

View File

@ -0,0 +1,51 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2023. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Jobs\Report;
use App\Models\Company;
use App\Libraries\MultiDB;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Cache;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\Middleware\WithoutOverlapping;
class PreviewReport implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance
*/
public function __construct(protected Company $company, protected array $request, private string $report_class, protected string $hash)
{
}
public function handle()
{
MultiDB::setDb($this->company->db);
/** @var \App\Export\CSV\CreditExport $export */
$export = new $this->report_class($this->company, $this->request);
$report = $export->returnJson();
nlog($report);
Cache::put($this->hash, $report, 60 * 60);
}
public function middleware()
{
return [new WithoutOverlapping("report-{$this->company->company_key}")];
}
}

View File

@ -92,6 +92,7 @@ use App\Http\Controllers\Reports\InvoiceReportController;
use App\Http\Controllers\Reports\PaymentReportController;
use App\Http\Controllers\Reports\ProductReportController;
use App\Http\Controllers\Reports\ProfitAndLossController;
use App\Http\Controllers\Reports\ReportPreviewController;
use App\Http\Controllers\Reports\ActivityReportController;
use App\Http\Controllers\Reports\ARDetailReportController;
use App\Http\Controllers\Reports\DocumentReportController;
@ -312,7 +313,7 @@ Route::group(['middleware' => ['throttle:api', 'api_db', 'token_auth', 'locale']
Route::post('reports/client_sales_report', ClientSalesReportController::class);
Route::post('reports/tax_summary_report', TaxSummaryReportController::class);
Route::post('reports/user_sales_report', UserSalesReportController::class);
Route::post('reports/preview/{hash}', UserSalesReportController::class);
Route::post('reports/preview/{hash}', ReportPreviewController::class);
Route::resource('task_schedulers', TaskSchedulerController::class);

View File

@ -677,33 +677,57 @@ class ReportCsvGenerationTest extends TestCase
public function testCreditJsonReport()
{
// Credit::factory()->create([
// 'user_id' => $this->user->id,
// 'company_id' => $this->company->id,
// 'client_id' => $this->client->id,
// 'amount' => 100,
// 'balance' => 50,
// 'number' => '1234',
// 'status_id' => 2,
// 'discount' => 10,
// 'po_number' => '1234',
// 'public_notes' => 'Public',
// 'private_notes' => 'Private',
// 'terms' => 'Terms',
// ]);
Credit::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'amount' => 100,
'balance' => 50,
'number' => '1234',
'status_id' => 2,
'discount' => 10,
'po_number' => '1234',
'public_notes' => 'Public',
'private_notes' => 'Private',
'terms' => 'Terms',
]);
// $data = [
// 'date_range' => 'all',
// 'report_keys' => ["client.name","credit.number","credit.amount","payment.date", "payment.amount"],
// 'send_email' => false,
// ];
$data = [
'date_range' => 'all',
'report_keys' => ["client.name","credit.number","credit.amount","payment.date", "payment.amount"],
'send_email' => false,
];
// $response = $this->withHeaders([
// 'X-API-SECRET' => config('ninja.api_secret'),
// 'X-API-TOKEN' => $this->token,
// ])->post('/api/v1/reports/credits?output=json', $data);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/credits?output=json', $data);
$response->assertStatus(200);
$arr = $response->json();
nlog($arr['message']);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/preview/'.$arr['message']);
$response->assertStatus(409);
sleep(1);
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->postJson('/api/v1/reports/preview/'.$arr['message']);
$response->assertStatus(200);
nlog($response->json());
}
public function testCreditCustomColumnsCsvGeneration()