Task imports

This commit is contained in:
David Bomba 2023-11-14 13:24:51 +11:00
parent f7ae037584
commit 83844a0c27
4 changed files with 310 additions and 0 deletions

View File

@ -0,0 +1,66 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Import\Definitions;
class TaskMap
{
public static function importable()
{
return [
0 => 'task.number',
1 => 'task.user_id',
2 => 'task.rate',
3 => 'project.name',
4 => 'client.name',
5 => 'client.email',
6 => 'task.description',
7 => 'task.is_billable',
8 => 'task.start_date',
9 => 'task.end_date',
10 => 'task.start_time',
11 => 'task.end_time',
12 => 'task.duration',
13 => 'task.status',
14 => 'task.custom_value1',
15 => 'task.custom_value1',
16 => 'task.custom_value1',
17 => 'task.custom_value1',
18 => 'task.notes',
];
}
public static function import_keys()
{
return [
0 => 'texts.task_number',
1 => 'texts.user',
2 => 'texts.task_rate',
3 => 'texts.project',
4 => 'texts.client',
5 => 'texts.client_email',
6 => 'texts.description',
7 => 'texts.billable',
8 => 'texts.start_date',
9 => 'texts.end_date',
10 => 'texts.start_time',
11 => 'texts.end_time',
12 => 'texts.duration',
13 => 'texts.status',
14 => 'texts.task1',
15 => 'texts.task2',
16 => 'texts.task3',
17 => 'texts.task4',
18 => 'texts.notes',
];
}
}

View File

@ -16,6 +16,7 @@ use App\Factory\InvoiceFactory;
use App\Factory\PaymentFactory;
use App\Factory\QuoteFactory;
use App\Factory\RecurringInvoiceFactory;
use App\Factory\TaskFactory;
use App\Http\Requests\Quote\StoreQuoteRequest;
use App\Import\ImportException;
use App\Jobs\Mail\NinjaMailerJob;
@ -30,6 +31,7 @@ use App\Repositories\InvoiceRepository;
use App\Repositories\PaymentRepository;
use App\Repositories\QuoteRepository;
use App\Repositories\RecurringInvoiceRepository;
use App\Repositories\TaskRepository;
use App\Utils\Traits\CleanLineItems;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
@ -158,6 +160,32 @@ class BaseImport
}, $csvData);
}
private function groupTasks($csvData, $key)
{
if (! $key) {
return $csvData;
}
// Group by tasks.
$grouped = [];
foreach ($csvData as $item) {
if (empty($item[$key])) {
$this->error_array['task'][] = [
'task' => $item,
'error' => 'No task number',
];
} else {
$grouped[$item[$key]][] = $item;
}
}
return $grouped;
}
private function groupInvoices($csvData, $key)
{
if (! $key) {
@ -413,6 +441,66 @@ class BaseImport
return $count;
}
public function ingestTasks($tasks, $task_number_key)
{
$count = 0;
$task_transformer = $this->transformer;
$task_repository = new TaskRepository();
// $task_repository->import_mode = true;
$tasks = $this->groupTasks($tasks, $task_number_key);
foreach ($tasks as $raw_task) {
$task_data = [];
try {
$task_data = $task_transformer->transform($raw_task);
$task_data['user_id'] = $this->company->owner()->id;
$validator = $this->request_name::runFormRequest($task_data);
if ($validator->fails()) {
$this->error_array['task'][] = [
'invoice' => $task_data,
'error' => $validator->errors()->all(),
];
} else {
$task = TaskFactory::create(
$this->company->id,
$this->company->owner()->id
);
$task_repository->save($task_data, $task);
$count++;
}
} catch (\Exception $ex) {
if (\DB::connection(config('database.default'))->transactionLevel() > 0) {
\DB::connection(config('database.default'))->rollBack();
}
if ($ex instanceof ImportException) {
$message = $ex->getMessage();
} else {
report($ex);
$message = 'Unknown error ';
nlog($ex->getMessage());
nlog($task_data);
}
$this->error_array['task'][] = [
'task' => $task_data,
'error' => $message,
];
}
}
return $count;
}
public function ingestInvoices($invoices, $invoice_number_key)
{

View File

@ -19,6 +19,7 @@ use App\Factory\PaymentFactory;
use App\Factory\ProductFactory;
use App\Factory\QuoteFactory;
use App\Factory\RecurringInvoiceFactory;
use App\Factory\TaskFactory;
use App\Factory\VendorFactory;
use App\Http\Requests\BankTransaction\StoreBankTransactionRequest;
use App\Http\Requests\Client\StoreClientRequest;
@ -28,6 +29,7 @@ use App\Http\Requests\Payment\StorePaymentRequest;
use App\Http\Requests\Product\StoreProductRequest;
use App\Http\Requests\Quote\StoreQuoteRequest;
use App\Http\Requests\RecurringInvoice\StoreRecurringInvoiceRequest;
use App\Http\Requests\Task\StoreTaskRequest;
use App\Http\Requests\Vendor\StoreVendorRequest;
use App\Import\Transformer\Bank\BankTransformer;
use App\Import\Transformer\Csv\ClientTransformer;
@ -37,6 +39,7 @@ use App\Import\Transformer\Csv\PaymentTransformer;
use App\Import\Transformer\Csv\ProductTransformer;
use App\Import\Transformer\Csv\QuoteTransformer;
use App\Import\Transformer\Csv\RecurringInvoiceTransformer;
use App\Import\Transformer\Csv\TaskTransformer;
use App\Import\Transformer\Csv\VendorTransformer;
use App\Repositories\BankTransactionRepository;
use App\Repositories\ClientRepository;
@ -46,6 +49,7 @@ use App\Repositories\PaymentRepository;
use App\Repositories\ProductRepository;
use App\Repositories\QuoteRepository;
use App\Repositories\RecurringInvoiceRepository;
use App\Repositories\TaskRepository;
use App\Repositories\VendorRepository;
use App\Services\Bank\BankMatchingService;
use App\Utils\Traits\MakesHash;
@ -69,6 +73,7 @@ class Csv extends BaseImport implements ImportInterface
'quote',
'bank_transaction',
'recurring_invoice',
'tasks',
])
) {
$this->{$entity}();
@ -348,6 +353,31 @@ class Csv extends BaseImport implements ImportInterface
public function task()
{
$entity_type = 'task';
$data = $this->getCsvData($entity_type);
if (is_array($data)) {
$data = $this->preTransformCsv($data, $entity_type);
}
if (empty($data)) {
$this->entity_count['invoices'] = 0;
return;
}
$this->request_name = StoreTaskRequest::class;
$this->repository_name = TaskRepository::class;
$this->factory_name = TaskFactory::class;
$this->repository = app()->make($this->repository_name);
// $this->repository->import_mode = true;
$this->transformer = new TaskTransformer($this->company);
$task_count = $this->ingestTasks($data, 'task.number');
$this->entity_count['tasks'] = $task_count;
}
public function transform(array $data)

View File

@ -0,0 +1,126 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/
namespace App\Import\Transformer\Csv;
use App\Import\Transformer\BaseTransformer;
/**
* Class TaskTransformer.
*/
class TaskTransformer extends BaseTransformer
{
private int $stubbed_timestamp = 0;
/**
* @param $data
*
* @return bool|array
*/
public function transform($task_items_data)
{
$this->stubbed_timestamp = time();
$task_data = reset($task_items_data);
$clientId = $this->getClient(
$this->getString($task_data, 'client.name'),
$this->getString($task_data, 'client.email')
);
$transformed = [
'company_id' => $this->company->id,
'number' => $this->getString($task_data, 'task.number'),
'user_id' => $this->getString($task_data, 'task.user_id'),
'client_id' => $clientId,
'project_id' => $this->getProjectId($task_data['project.name'], $clientId),
'description' => $this->getString($task_data, 'task.description'),
'status' => $this->getTaskStatusId($task_data),
'custom_value1' => $this->getString($task_data, 'task.custom_value1'),
'custom_value2' => $this->getString($task_data, 'task.custom_value2'),
'custom_value3' => $this->getString($task_data, 'task.custom_value3'),
'custom_value4' => $this->getString($task_data, 'task.custom_value4'),
];
$time_log = collect($task_items_data)
->map(function ($item) {
return $this->parseLog($item);
})->toJson();
nlog($time_log);
$transformed['time_log'] = $time_log;
return $transformed;
}
private function parseLog($item): array
{
$start_date = false;
$end_date = false;
$notes = $item['task.notes'] ?? '';
$is_billable = $item['task.is_billable'] ?? false;
if(isset($item['start_date']) &&
isset($item['end_date'])) {
$start_date = $this->resolveStartDate($item);
$end_date = $this->resolveEndDate($item);
} elseif(isset($item['duration'])) {
$duration = strtotime($item['duration']) - strtotime('TODAY');
$start_date = $this->stubbed_timestamp;
$end_date = $this->stubbed_timestamp + $duration;
$this->stubbed_timestamp++;
} else {
return [];
}
return [$start_date, $end_date, $notes, $is_billable];
}
private function resolveStartDate($item)
{
$stub_start_date = $item['start_date'] . ' ' . isset($item['start_time']) ?? '';
try {
$stub_start_date = \Carbon\Carbon::parse($stub_start_date);
$this->stubbed_timestamp = $stub_start_date->timestamp;
return $stub_start_date->timestamp;
} catch (\Exception $e) {
return $this->stubbed_timestamp;
}
}
private function resolveEndDate($item)
{
$stub_start_date = $item['end_date'] . ' ' . isset($item['end_time']) ?? '';
try {
$stub_start_date = \Carbon\Carbon::parse($stub_start_date);
if($stub_start_date->timestamp == $this->stubbed_timestamp) {
$this->stubbed_timestamp++;
return $this->stubbed_timestamp;
}
$this->stubbed_timestamp = $stub_start_date->timestamp++;
return $stub_start_date->timestamp;
} catch (\Exception $e) {
return $this->stubbed_timestamp++;
}
}
}