1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 00:11:35 +02:00

Additional tests for report generation

This commit is contained in:
David Bomba 2023-07-18 18:21:12 +10:00
parent 9fc9a0fd78
commit a2b0a13c1f
5 changed files with 229 additions and 68 deletions

View File

@ -20,6 +20,7 @@ use App\Models\Payment;
use League\Fractal\Manager;
use Illuminate\Support\Carbon;
use App\Utils\Traits\MakesHash;
use App\Transformers\TaskTransformer;
use App\Transformers\PaymentTransformer;
use Illuminate\Database\Eloquent\Builder;
use League\Fractal\Serializer\ArraySerializer;
@ -348,8 +349,6 @@ class BaseExport
'custom_value4' => 'task.custom_value4',
'status' => 'task.status_id',
'project' => 'task.project_id',
'invoice' => 'task.invoice_id',
'client' => 'task.client_id',
];
protected function filterByClients($query)
@ -385,6 +384,7 @@ class BaseExport
'quote' => $value = $this->resolveQuoteKey($parts[1], $entity, $transformer),
'purchase_order' => $value = $this->resolvePurchaseOrderKey($parts[1], $entity, $transformer),
'payment' => $value = $this->resolvePaymentKey($parts[1], $entity, $transformer),
'task' => $value = $this->resolveTaskKey($parts[1], $entity, $transformer),
default => $value = ''
};
@ -450,6 +450,22 @@ class BaseExport
}
private function resolveTaskKey($column, $entity, $transformer)
{
nlog("searching for {$column}");
$transformed_entity = $transformer->transform($entity);
if(array_key_exists($column, $transformed_entity)) {
return $transformed_entity[$column];
}
return '';
}
private function resolveVendorKey($column, $entity, $transformer)
{
@ -587,7 +603,23 @@ class BaseExport
}
$transformed_invoice = $transformer->transform($entity);
if($transformer instanceof TaskTransformer) {
$transformed_invoice = $transformer->includeInvoice($entity);
if(!$transformed_invoice)
return '';
$manager = new Manager();
$manager->setSerializer(new ArraySerializer());
$transformed_invoice = $manager->createData($transformed_invoice)->toArray();
}
if(array_key_exists($column, $transformed_invoice)) {
return $transformed_invoice[$column];
} elseif (array_key_exists(str_replace("invoice.", "", $column), $transformed_invoice)) {
return $transformed_invoice[$column];
}
if($column == 'status')
return $entity->stringStatus($entity->status_id);
@ -886,6 +918,8 @@ class BaseExport
}
}
// nlog($header);
return $header;
}
}

View File

@ -46,9 +46,7 @@ class TaskExport extends BaseExport
'custom_value4' => 'custom_value4',
'status' => 'status_id',
'project' => 'project_id',
'invoice' => 'invoice_id',
'client' => 'client_id',
];
];
private array $decorate_keys = [
'status',
@ -109,38 +107,39 @@ class TaskExport extends BaseExport
$entity = [];
$transformed_entity = $this->entity_transformer->transform($task);
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if(!$keyval) {
$keyval = array_search(str_replace("task.", "", $key), $this->entity_keys) ?? $key;
}
if(!$keyval) {
$keyval = $key;
}
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} elseif (array_key_exists($keyval, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$keyval];
}
else {
$entity[$keyval] = $this->resolveKey($keyval, $task, $this->entity_transformer);
}
}
$entity['start_date'] = '';
$entity['end_date'] = '';
$entity['duration'] = '';
if (is_null($task->time_log) || (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) == 0)) {
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} else {
$entity[$keyval] = '';
}
}
$entity['start_date'] = '';
$entity['end_date'] = '';
$entity['duration'] = '';
$entity = $this->decorateAdvancedFields($task, $entity);
ksort($entity);
$this->csv->insertOne($entity);
} elseif (is_array(json_decode($task->time_log, 1)) && count(json_decode($task->time_log, 1)) > 0) {
foreach (array_values($this->input['report_keys']) as $key) {
$keyval = array_search($key, $this->entity_keys);
if (array_key_exists($key, $transformed_entity)) {
$entity[$keyval] = $transformed_entity[$key];
} else {
$entity[$keyval] = '';
}
}
} else {
$this->iterateLogs($task, $entity);
}
}
private function iterateLogs(Task $task, array $entity)
@ -163,39 +162,26 @@ class TaskExport extends BaseExport
}
foreach ($logs as $key => $item) {
if (in_array('start_date', $this->input['report_keys'])) {
if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) {
$entity['start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default);
}
if (in_array('end_date', $this->input['report_keys']) && $item[1] > 0) {
if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) {
$entity['end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default);
}
if (in_array('end_date', $this->input['report_keys']) && $item[1] == 0) {
if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] == 0) {
$entity['end_date'] = ctrans('texts.is_running');
}
if (in_array('duration', $this->input['report_keys'])) {
if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) {
$entity['duration'] = $task->calcDuration();
}
if (! array_key_exists('duration', $entity)) {
$entity['duration'] = '';
}
if (! array_key_exists('start_date', $entity)) {
$entity['start_date'] = '';
}
if (! array_key_exists('end_date', $entity)) {
$entity['end_date'] = '';
}
$entity = $this->decorateAdvancedFields($task, $entity);
ksort($entity);
$this->csv->insertOne($entity);
unset($entity['start_date']);
unset($entity['end_date']);
unset($entity['duration']);
@ -212,14 +198,6 @@ class TaskExport extends BaseExport
$entity['project'] = $task->project()->exists() ? $task->project->name : '';
}
if (in_array('client_id', $this->input['report_keys'])) {
$entity['client'] = $task->client ? $task->client->present()->name() : '';
}
if (in_array('invoice_id', $this->input['report_keys'])) {
$entity['invoice'] = $task->invoice ? $task->invoice->number : '';
}
return $entity;
}
}

View File

@ -37,6 +37,7 @@ class TaskTransformer extends EntityTransformer
'status',
'project',
'user',
'invoice',
];
public function includeDocuments(Task $task)
@ -46,6 +47,17 @@ class TaskTransformer extends EntityTransformer
return $this->includeCollection($task->documents, $transformer, Document::class);
}
public function includeInvoice(Task $task): ?Item
{
$transformer = new InvoiceTransformer($this->serializer);
if (!$task->user) {
return null;
}
return $this->includeItem($task->invoice, $transformer, Invoice::class);
}
public function includeUser(Task $task): ?Item
{
$transformer = new UserTransformer($this->serializer);

View File

@ -5,7 +5,7 @@ parameters:
treatPhpDocTypesAsCertain: false
parallel:
jobSize: 5
maximumNumberOfProcesses: 16
maximumNumberOfProcesses: 1
processTimeout: 600.0
ignoreErrors:
- '#Call to an undefined method .*badMethod\(\)#'

View File

@ -164,9 +164,92 @@ class ReportCsvGenerationTest extends TestCase
}
public function testTaskCustomColumnsCsvGeneration()
{
$invoice = \App\Models\Invoice::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'date' => '2023-01-01',
'amount' => 1000,
'balance' => 1000,
'number' => '123456',
'status_id' => 2,
'discount' => 10,
'po_number' => '12345',
'public_notes' => 'Public5',
'private_notes' => 'Private5',
'terms' => 'Terms5',
]);
$log = '[[1689547165,1689550765,"sumtin",true]]';
\App\Models\Task::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'invoice_id' => $invoice->id,
'description' => 'test1',
'time_log' => $log,
'custom_value1' => 'Custom 11',
'custom_value2' => 'Custom 22',
'custom_value3' => 'Custom 33',
'custom_value4' => 'Custom 44',
]);
$data = [
'date_range' => 'all',
'report_keys' => [
'client.name',
'invoice.number',
'invoice.amount',
'task.start_date',
'task.end_date',
'task.duration',
'task.description',
'task.custom_value1',
'task.custom_value2',
'task.custom_value3',
'task.custom_value4',
],
'send_email' => false,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/reports/tasks', $data);
$csv = $response->streamedContent();
$this->assertEquals(3600, $this->getFirstValueByColumn($csv, 'Task Duration'));
$this->assertEquals('test1', $this->getFirstValueByColumn($csv, 'Task Description'));
$this->assertEquals('16/Jul/2023', $this->getFirstValueByColumn($csv, 'Task Start Date'));
$this->assertEquals('16/Jul/2023', $this->getFirstValueByColumn($csv, 'Task End Date'));
$this->assertEquals('Custom 11', $this->getFirstValueByColumn($csv, 'Task Custom Value 1'));
$this->assertEquals('Custom 22', $this->getFirstValueByColumn($csv, 'Task Custom Value 2'));
$this->assertEquals('Custom 33', $this->getFirstValueByColumn($csv, 'Task Custom Value 3'));
$this->assertEquals('Custom 44', $this->getFirstValueByColumn($csv, 'Task Custom Value 4'));
$this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name'));
$this->assertEquals('123456', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number'));
$this->assertEquals(1000, $this->getFirstValueByColumn($csv, 'Invoice Amount'));
}
public function testTasksCsvGeneration()
{
\App\Models\Task::query()->cursor()->each(function ($t) {
$t->forceDelete();
});
$log = '[[1689547165,1689550765,"sumtin",true]]';
\App\Models\Task::factory()->create([
@ -247,13 +330,70 @@ class ReportCsvGenerationTest extends TestCase
public function testPaymentCsvGeneration()
{
$invoice = \App\Models\Invoice::factory()->create([
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'date' => '2023-01-01',
'amount' => 100,
'balance' => 100,
'number' => '12345',
'status_id' => 2,
'discount' => 10,
'po_number' => '1234',
'public_notes' => 'Public',
'private_notes' => 'Private',
'terms' => 'Terms',
]);
$invoice->client->balance = 100;
$invoice->client->paid_to_date = 0;
$invoice->push();
$invoice->service()->markPaid()->save();
$data = [
'date_range' => 'all',
'report_keys' => [
"payment.date",
"payment.amount",
"invoice.number",
"invoice.amount",
"client.name",
"client.balance",
"client.paid_to_date"
],
'send_email' => false,
];
$response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'),
'X-API-TOKEN' => $this->token,
])->post('/api/v1/reports/payments', $data);
$csv = $response->streamedContent();
$this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Payment Amount'));
$this->assertEquals(now()->addSeconds($this->company->timezone()->utc_offset)->format('Y-m-d'), $this->getFirstValueByColumn($csv, 'Payment Date'));
$this->assertEquals('12345', $this->getFirstValueByColumn($csv, 'Invoice Invoice Number'));
$this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Invoice Amount'));
$this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name'));
$this->assertEquals(0, $this->getFirstValueByColumn($csv, 'Client Balance'));
$this->assertEquals(100, $this->getFirstValueByColumn($csv, 'Client Paid to Date'));
}
public function testPaymentCustomFieldsCsvGeneration()
{
\App\Models\Payment::factory()->create([
'amount' => 500,
'date' => '2020-01-01',
'company_id' => $this->company->id,
'user_id' => $this->user->id,
'company_id' => $this->company->id,
'client_id' => $this->client->id,
'transaction_reference' => '1234',
]);
@ -279,6 +419,7 @@ class ReportCsvGenerationTest extends TestCase
}
public function testClientCsvGeneration()
{
@ -443,8 +584,6 @@ class ReportCsvGenerationTest extends TestCase
$csv = $response->streamedContent();
nlog($csv);
$this->assertEquals('bob', $this->getFirstValueByColumn($csv, 'Client Name'));
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Recurring Invoice Invoice Number'));
$this->assertEquals('Daily', $this->getFirstValueByColumn($csv, 'Recurring Invoice How Often'));
@ -694,8 +833,6 @@ class ReportCsvGenerationTest extends TestCase
$csv = $response->streamedContent();
nlog($csv);
$this->assertEquals('Vendor 1', $this->getFirstValueByColumn($csv, 'Vendor Name'));
$this->assertEquals('1234', $this->getFirstValueByColumn($csv, 'Purchase Order Number'));
$this->assertEquals('10', $this->getFirstValueByColumn($csv, 'Quantity'));