company = $company; $this->hash = $request['hash']; $this->entity_type = $request['entity_type']; $this->skip_header = $request['skip_header']; $this->column_map = $request['column_map']; } /** * Execute the job. * * * @return void */ public function handle() { MultiDB::setDb($this->company->db); $this->company->owner()->setCompany($this->company); Auth::login($this->company->owner(), true); $this->buildMaps(); //sort the array by key ksort($this->column_map); nlog("import".ucfirst($this->entity_type)); $this->{"import".ucfirst($this->entity_type)}(); $data = [ 'entity' => ucfirst($this->entity_type), 'errors' => $this->error_array, 'clients' => $this->maps['clients'], 'products' => $this->maps['products'], 'invoices' => $this->maps['invoices'], 'settings' => $this->company->settings ]; //nlog(print_r($data, 1)); MailRouter::dispatch(new ImportCompleted($data), $this->company, auth()->user()); } public function failed($exception) { } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// private function importInvoice() { $invoice_transformer = new InvoiceTransformer($this->maps); $records = $this->getCsvData(); $invoice_number_key = array_search('Invoice Number', reset($records)); if ($this->skip_header) { array_shift($records); } if (!$invoice_number_key) { nlog("no invoice number to use as key - returning"); return; } $unique_invoices = []; //get an array of unique invoice numbers foreach ($records as $key => $value) { $unique_invoices[] = $value[$invoice_number_key]; } foreach ($unique_invoices as $unique) { $invoices = array_filter($records, function ($value) use ($invoice_number_key, $unique) { return $value[$invoice_number_key] == $unique; }); $keys = $this->column_map; $values = array_intersect_key(reset($invoices), $this->column_map); $invoice_data = array_combine($keys, $values); $invoice = $invoice_transformer->transform($invoice_data); $this->processInvoice($invoices, $invoice); } } private function processInvoice($invoices, $invoice) { $invoice_repository = new InvoiceRepository(); $item_transformer = new InvoiceItemTransformer($this->maps); $items = []; foreach ($invoices as $record) { $keys = $this->column_map; $values = array_intersect_key($record, $this->column_map); $invoice_data = array_combine($keys, $values); $items[] = $item_transformer->transform($invoice_data); } $invoice['line_items'] = $this->cleanItems($items); $validator = Validator::make($invoice, (new StoreInvoiceRequest())->rules()); if ($validator->fails()) { $this->error_array['invoices'] = ['invoice' => $invoice, 'error' => json_encode($validator->errors())]; } else { if ($validator->fails()) { $this->error_array[] = ['invoice' => $invoice, 'error' => json_encode($validator->errors())]; } else { $invoice = $invoice_repository->save($invoice, InvoiceFactory::create($this->company->id, $this->setUser($record))); $this->maps['invoices'][] = $invoice->id; $this->performInvoiceActions($invoice, $record, $invoice_repository); } } } private function performInvoiceActions($invoice, $record, $invoice_repository) { $invoice = $this->actionInvoiceStatus($invoice, $record, $invoice_repository); } private function actionInvoiceStatus($invoice, $status, $invoice_repository) { switch ($status) { case 'Archived': $invoice_repository->archive($invoice); $invoice->fresh(); break; case 'Sent': $invoice = $invoice->service()->markSent()->save(); break; case 'Viewed': $invoice = $invoice->service()->markSent()->save(); break; default: # code... break; } if ($invoice->balance < $invoice->amount && $invoice->status_id <= Invoice::STATUS_SENT) { $invoice->status_id = Invoice::STATUS_PARTIAL; $invoice->save(); } return $invoice; } //todo limit client imports for hosted version private function importClient() { //clients $records = $this->getCsvData(); $contact_repository = new ClientContactRepository(); $client_repository = new ClientRepository($contact_repository); $client_transformer = new ClientTransformer($this->maps); if ($this->skip_header) { array_shift($records); } foreach ($records as $record) { $keys = $this->column_map; $values = array_intersect_key($record, $this->column_map); $client_data = array_combine($keys, $values); $client = $client_transformer->transform($client_data); $validator = Validator::make($client, (new StoreClientRequest())->rules()); if ($validator->fails()) { $this->error_array['clients'] = ['client' => $client, 'error' => json_encode($validator->errors())]; } else { $client = $client_repository->save($client, ClientFactory::create($this->company->id, $this->setUser($record))); if (array_key_exists('client.balance', $client_data)) { $client->balance = preg_replace('/[^0-9,.]+/', '', $client_data['client.balance']); } if (array_key_exists('client.paid_to_date', $client_data)) { $client->paid_to_date = preg_replace('/[^0-9,.]+/', '', $client_data['client.paid_to_date']); } $client->save(); $this->maps['clients'][] = $client->id; } } } private function importProduct() { $product_repository = new ProductRepository(); $product_transformer = new ProductTransformer($this->maps); $records = $this->getCsvData(); if ($this->skip_header) { array_shift($records); } foreach ($records as $record) { $keys = $this->column_map; $values = array_intersect_key($record, $this->column_map); $product_data = array_combine($keys, $values); $product = $product_transformer->transform($product_data); $validator = Validator::make($product, (new StoreProductRequest())->rules()); if ($validator->fails()) { $this->error_array['products'] = ['product' => $product, 'error' => json_encode($validator->errors())]; } else { $product = $product_repository->save($product, ProductFactory::create($this->company->id, $this->setUser($record))); $product->save(); $this->maps['products'][] = $product->id; } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// private function buildMaps() { $this->maps['currencies'] = Currency::all(); $this->maps['users'] = $this->company->users; $this->maps['company'] = $this->company; $this->maps['clients'] = []; $this->maps['products'] = []; $this->maps['invoices'] = []; return $this; } private function setUser($record) { $user_key_exists = array_search('client.user_id', $this->column_map); if ($user_key_exists) { return $this->findUser($record[$user_key_exists]); } else { return $this->company->owner()->id; } } private function findUser($user_hash) { $user = User::where('company_id', $this->company->id) ->where(\DB::raw('CONCAT_WS(" ", first_name, last_name)'), 'like', '%' . $user_hash . '%') ->first(); if ($user) { return $user->id; } else { return $this->company->owner()->id; } } private function getCsvData() { $base64_encoded_csv = Cache::get($this->hash); $csv = base64_decode($base64_encoded_csv); $csv = Reader::createFromString($csv); $stmt = new Statement(); $data = iterator_to_array($stmt->process($csv)); if (count($data) > 0) { $headers = $data[0]; // Remove Invoice Ninja headers if (count($headers) && count($data) > 4) { $firstCell = $headers[0]; if (strstr($firstCell, config('ninja.app_name'))) { array_shift($data); // Invoice Ninja... array_shift($data); // array_shift($data); // Enitty Type Header } } } return $data; } }