From 83844a0c27de989fb8648c850f465c552daef5ab Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 14 Nov 2023 13:24:51 +1100 Subject: [PATCH] Task imports --- app/Import/Definitions/TaskMap.php | 66 +++++++++ app/Import/Providers/BaseImport.php | 88 ++++++++++++ app/Import/Providers/Csv.php | 30 +++++ .../Transformer/Csv/TaskTransformer.php | 126 ++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 app/Import/Definitions/TaskMap.php create mode 100644 app/Import/Transformer/Csv/TaskTransformer.php diff --git a/app/Import/Definitions/TaskMap.php b/app/Import/Definitions/TaskMap.php new file mode 100644 index 000000000000..d974fa51aea2 --- /dev/null +++ b/app/Import/Definitions/TaskMap.php @@ -0,0 +1,66 @@ + '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', + ]; + } +} diff --git a/app/Import/Providers/BaseImport.php b/app/Import/Providers/BaseImport.php index f5396e7efd6b..f934e59fde13 100644 --- a/app/Import/Providers/BaseImport.php +++ b/app/Import/Providers/BaseImport.php @@ -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) { diff --git a/app/Import/Providers/Csv.php b/app/Import/Providers/Csv.php index 9e29d5af9f41..97444ddb6f92 100644 --- a/app/Import/Providers/Csv.php +++ b/app/Import/Providers/Csv.php @@ -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) diff --git a/app/Import/Transformer/Csv/TaskTransformer.php b/app/Import/Transformer/Csv/TaskTransformer.php new file mode 100644 index 000000000000..060e5b04b0ce --- /dev/null +++ b/app/Import/Transformer/Csv/TaskTransformer.php @@ -0,0 +1,126 @@ +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++; + } + + } + +}