mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-09 20:52:56 +01:00
Added ImportData job to use queue
This commit is contained in:
parent
2f838416b0
commit
7a13d93082
@ -2,59 +2,88 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Services\ImportService;
|
||||
use App\Jobs\ImportData;
|
||||
use Exception;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use Utils;
|
||||
use View;
|
||||
use Auth;
|
||||
|
||||
class ImportController extends BaseController
|
||||
{
|
||||
public function __construct(ImportService $importService)
|
||||
{
|
||||
//parent::__construct();
|
||||
|
||||
$this->importService = $importService;
|
||||
}
|
||||
|
||||
public function doImport()
|
||||
public function doImport(Request $request)
|
||||
{
|
||||
$source = Input::get('source');
|
||||
$files = [];
|
||||
$timestamp = time();
|
||||
|
||||
foreach (ImportService::$entityTypes as $entityType) {
|
||||
if (Input::file("{$entityType}_file")) {
|
||||
$files[$entityType] = Input::file("{$entityType}_file")->getRealPath();
|
||||
if ($source === IMPORT_CSV) {
|
||||
Session::forget("{$entityType}-data");
|
||||
$fileName = $entityType;
|
||||
if ($request->hasFile($fileName)) {
|
||||
$file = $request->file($fileName);
|
||||
$destinationPath = storage_path() . '/import';
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
|
||||
if (! in_array($extension, ['csv', 'xls', 'json'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newFileName = sprintf('%s_%s_%s.%s', Auth::user()->account_id, $timestamp, $fileName, $extension);
|
||||
$file->move($destinationPath, $newFileName);
|
||||
$files[$entityType] = $newFileName;
|
||||
}
|
||||
}
|
||||
|
||||
if (! count($files)) {
|
||||
Session::flash('error', trans('texts.select_file'));
|
||||
|
||||
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
|
||||
}
|
||||
|
||||
try {
|
||||
if ($source === IMPORT_CSV) {
|
||||
$data = $this->importService->mapCSV($files);
|
||||
|
||||
return View::make('accounts.import_map', ['data' => $data]);
|
||||
return View::make('accounts.import_map', [
|
||||
'data' => $data,
|
||||
'timestamp' => $timestamp,
|
||||
]);
|
||||
} elseif ($source === IMPORT_JSON) {
|
||||
$includeData = filter_var(Input::get('data'), FILTER_VALIDATE_BOOLEAN);
|
||||
$includeSettings = filter_var(Input::get('settings'), FILTER_VALIDATE_BOOLEAN);
|
||||
$results = $this->importService->importJSON($files[IMPORT_JSON], $includeData, $includeSettings);
|
||||
|
||||
return $this->showResult($results, $includeSettings);
|
||||
if (config('queue.default') === 'sync') {
|
||||
$results = $this->importService->importJSON($files[IMPORT_JSON], $includeData, $includeSettings);
|
||||
$message = $this->importService->presentResults($results, $includeSettings);
|
||||
} else {
|
||||
$settings = [
|
||||
'files' => $files,
|
||||
'include_data' => $includeData,
|
||||
'include_settings' => $includeSettings,
|
||||
];
|
||||
$this->dispatch(new ImportData(Auth::user(), IMPORT_JSON, $settings));
|
||||
$message = 'started...';
|
||||
}
|
||||
} else {
|
||||
$results = $this->importService->importFiles($source, $files);
|
||||
|
||||
return $this->showResult($results);
|
||||
if (config('queue.default') === 'sync') {
|
||||
$results = $this->importService->importFiles($source, $files);
|
||||
$message = $this->importService->presentResults($results);
|
||||
} else {
|
||||
$settings = [
|
||||
'files' => $files,
|
||||
'source' => $source,
|
||||
];
|
||||
$this->dispatch(new ImportData(Auth::user(), false, $settings));
|
||||
$message = 'started...';
|
||||
}
|
||||
}
|
||||
return redirect('/settings/' . ACCOUNT_IMPORT_EXPORT)->withWarning($message);
|
||||
} catch (Exception $exception) {
|
||||
Utils::logError($exception);
|
||||
Session::flash('error', $exception->getMessage());
|
||||
@ -65,13 +94,24 @@ class ImportController extends BaseController
|
||||
|
||||
public function doImportCSV()
|
||||
{
|
||||
$map = Input::get('map');
|
||||
$headers = Input::get('headers');
|
||||
|
||||
try {
|
||||
$results = $this->importService->importCSV($map, $headers);
|
||||
$map = Input::get('map');
|
||||
$headers = Input::get('headers');
|
||||
$timestamp = Input::get('timestamp');
|
||||
if (config('queue.default') === 'sync') {
|
||||
$results = $this->importService->importCSV($map, $headers, $timestamp);
|
||||
$message = $this->importService->presentResults($results);
|
||||
} else {
|
||||
$settings = [
|
||||
'timestamp' => $timestamp,
|
||||
'map' => $map,
|
||||
'headers' => $headers,
|
||||
];
|
||||
$this->dispatch(new ImportData(Auth::user(), IMPORT_CSV, $settings));
|
||||
$message = 'started...';
|
||||
}
|
||||
|
||||
return $this->showResult($results);
|
||||
return redirect('/settings/' . ACCOUNT_IMPORT_EXPORT)->withWarning($message);
|
||||
} catch (Exception $exception) {
|
||||
Utils::logError($exception);
|
||||
Session::flash('error', $exception->getMessage());
|
||||
@ -79,36 +119,4 @@ class ImportController extends BaseController
|
||||
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
|
||||
}
|
||||
}
|
||||
|
||||
private function showResult($results, $includeSettings = false)
|
||||
{
|
||||
$message = '';
|
||||
$skipped = [];
|
||||
|
||||
if ($includeSettings) {
|
||||
$message = trans('texts.imported_settings') . '<br/>';
|
||||
}
|
||||
|
||||
foreach ($results as $entityType => $entityResults) {
|
||||
if ($count = count($entityResults[RESULT_SUCCESS])) {
|
||||
$message .= trans("texts.created_{$entityType}s", ['count' => $count]) . '<br/>';
|
||||
}
|
||||
if (count($entityResults[RESULT_FAILURE])) {
|
||||
$skipped = array_merge($skipped, $entityResults[RESULT_FAILURE]);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($skipped)) {
|
||||
$message .= '<p/>' . trans('texts.failed_to_import') . '<br/>';
|
||||
foreach ($skipped as $skip) {
|
||||
$message .= json_encode($skip) . '<br/>';
|
||||
}
|
||||
}
|
||||
|
||||
if ($message) {
|
||||
Session::flash('warning', $message);
|
||||
}
|
||||
|
||||
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
|
||||
}
|
||||
}
|
||||
|
@ -302,6 +302,7 @@ class OnlinePaymentController extends BaseController
|
||||
}
|
||||
|
||||
Auth::onceUsingId($account->users[0]->id);
|
||||
$account->loadLocalizationSettings();
|
||||
$product = Product::scope(Input::get('product_id'))->first();
|
||||
|
||||
if (! $product) {
|
||||
|
80
app/Jobs/ImportData.php
Normal file
80
app/Jobs/ImportData.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Monolog\Logger;
|
||||
use App\Services\ImportService;
|
||||
use App\Ninja\Mailers\UserMailer;
|
||||
use Auth;
|
||||
|
||||
/**
|
||||
* Class SendInvoiceEmail.
|
||||
*/
|
||||
class ImportData extends Job implements ShouldQueue
|
||||
{
|
||||
use InteractsWithQueue, SerializesModels;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param mixed $files
|
||||
* @param mixed $settings
|
||||
*/
|
||||
public function __construct($user, $type, $settings)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->type = $type;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @param ContactMailer $mailer
|
||||
*/
|
||||
public function handle(ImportService $importService, UserMailer $userMailer)
|
||||
{
|
||||
$includeSettings = false;
|
||||
|
||||
Auth::onceUsingId($this->user->id);
|
||||
$this->user->account->loadLocalizationSettings();
|
||||
|
||||
if ($this->type === IMPORT_JSON) {
|
||||
$includeData = $this->settings['include_data'];
|
||||
$includeSettings = $this->settings['include_settings'];
|
||||
$files = $this->settings['files'];
|
||||
$results = $importService->importJSON($files[IMPORT_JSON], $includeData, $includeSettings);
|
||||
} elseif ($this->type === IMPORT_CSV) {
|
||||
$map = $this->settings['map'];
|
||||
$headers = $this->settings['headers'];
|
||||
$timestamp = $this->settings['timestamp'];
|
||||
$results = $importService->importCSV($map, $headers, $timestamp);
|
||||
} else {
|
||||
$source = $this->settings['source'];
|
||||
$files = $this->settings['files'];
|
||||
$results = $importService->importFiles($source, $files);
|
||||
}
|
||||
|
||||
$subject = trans('texts.import_complete');
|
||||
$message = $importService->presentResults($results, $includeSettings);
|
||||
$userMailer->sendMessage($this->user, $subject, $message);
|
||||
}
|
||||
}
|
@ -114,7 +114,7 @@ class UserMailer extends Mailer
|
||||
/**
|
||||
* @param Invitation $invitation
|
||||
*/
|
||||
public function sendMessage($user, $subject, $message, $invoice)
|
||||
public function sendMessage($user, $subject, $message, $invoice = false)
|
||||
{
|
||||
if (! $user->email) {
|
||||
return;
|
||||
@ -125,7 +125,7 @@ class UserMailer extends Mailer
|
||||
'userName' => $user->getDisplayName(),
|
||||
'primaryMessage' => $subject,
|
||||
'secondaryMessage' => $message,
|
||||
'invoiceLink' => $invoice->present()->multiAccountLink,
|
||||
'invoiceLink' => $invoice ? $invoice->present()->multiAccountLink : false,
|
||||
];
|
||||
|
||||
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
|
@ -149,7 +149,7 @@ class ImportService
|
||||
{
|
||||
$this->initMaps();
|
||||
|
||||
$file = file_get_contents($file);
|
||||
$file = file_get_contents(storage_path() . '/import/' . $file);
|
||||
$json = json_decode($file, true);
|
||||
$json = $this->removeIdFields($json);
|
||||
$transformer = new BaseTransformer($this->maps);
|
||||
@ -284,6 +284,7 @@ class ImportService
|
||||
|
||||
// Convert the data
|
||||
$row_list = [];
|
||||
$file = storage_path() . '/import/' . $file;
|
||||
|
||||
Excel::load($file, function ($reader) use ($source, $entityType, &$row_list, &$results) {
|
||||
$this->checkData($entityType, count($reader->all()));
|
||||
@ -539,29 +540,13 @@ class ImportService
|
||||
*/
|
||||
public function mapFile($entityType, $filename, $columns, $map)
|
||||
{
|
||||
require_once app_path().'/Includes/parsecsv.lib.php';
|
||||
$csv = new parseCSV();
|
||||
$csv->heading = false;
|
||||
$csv->auto($filename);
|
||||
|
||||
$data = $this->getCsvData($filename);
|
||||
$headers = false;
|
||||
$hasHeaders = false;
|
||||
$mapped = [];
|
||||
|
||||
if (count($csv->data) > 0) {
|
||||
$headers = $csv->data[0];
|
||||
|
||||
// Remove Invoice Ninja headers
|
||||
if (count($headers) && count($csv->data) > 4) {
|
||||
$firstCell = $headers[0];
|
||||
if (strstr($firstCell, APP_NAME)) {
|
||||
array_shift($csv->data); // Invoice Ninja...
|
||||
array_shift($csv->data); // <blank line>
|
||||
array_shift($csv->data); // Enitty Type Header
|
||||
}
|
||||
$headers = $csv->data[0];
|
||||
}
|
||||
|
||||
if (count($data) > 0) {
|
||||
$headers = $data[0];
|
||||
foreach ($headers as $title) {
|
||||
if (strpos(strtolower($title), 'name') > 0) {
|
||||
$hasHeaders = true;
|
||||
@ -583,11 +568,11 @@ class ImportService
|
||||
}
|
||||
}
|
||||
|
||||
Session::put("{$entityType}-data", $csv->data);
|
||||
//Session::put("{$entityType}-data", $csv->data);
|
||||
|
||||
$data = [
|
||||
'entityType' => $entityType,
|
||||
'data' => $csv->data,
|
||||
'data' => $data,
|
||||
'headers' => $headers,
|
||||
'hasHeaders' => $hasHeaders,
|
||||
'columns' => $columns,
|
||||
@ -597,6 +582,31 @@ class ImportService
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getCsvData($filename)
|
||||
{
|
||||
require_once app_path().'/Includes/parsecsv.lib.php';
|
||||
$csv = new parseCSV();
|
||||
$csv->heading = false;
|
||||
$csv->auto(storage_path() . '/import/' . $filename);
|
||||
$data = $csv->data;
|
||||
|
||||
if (count($data) > 0) {
|
||||
$headers = $data[0];
|
||||
|
||||
// Remove Invoice Ninja headers
|
||||
if (count($headers) && count($data) > 4) {
|
||||
$firstCell = $headers[0];
|
||||
if (strstr($firstCell, APP_NAME)) {
|
||||
array_shift($data); // Invoice Ninja...
|
||||
array_shift($data); // <blank line>
|
||||
array_shift($data); // Enitty Type Header
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param $pattern
|
||||
@ -642,12 +652,12 @@ class ImportService
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function importCSV(array $maps, $headers)
|
||||
public function importCSV(array $maps, $headers, $timestamp)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($maps as $entityType => $map) {
|
||||
$results[$entityType] = $this->executeCSV($entityType, $map, $headers[$entityType]);
|
||||
$results[$entityType] = $this->executeCSV($entityType, $map, $headers[$entityType], $timestamp);
|
||||
}
|
||||
|
||||
return $results;
|
||||
@ -660,7 +670,7 @@ class ImportService
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function executeCSV($entityType, $map, $hasHeaders)
|
||||
private function executeCSV($entityType, $map, $hasHeaders, $timestamp)
|
||||
{
|
||||
$results = [
|
||||
RESULT_SUCCESS => [],
|
||||
@ -668,7 +678,9 @@ class ImportService
|
||||
];
|
||||
$source = IMPORT_CSV;
|
||||
|
||||
$data = Session::get("{$entityType}-data");
|
||||
//$data = Session::get("{$entityType}-data");
|
||||
$filename = sprintf('%s_%s_%s.csv', Auth::user()->account_id, $timestamp, $entityType);
|
||||
$data = $this->getCsvData($filename);
|
||||
$this->checkData($entityType, count($data));
|
||||
$this->initMaps();
|
||||
|
||||
@ -707,7 +719,7 @@ class ImportService
|
||||
}
|
||||
}
|
||||
|
||||
Session::forget("{$entityType}-data");
|
||||
//Session::forget("{$entityType}-data");
|
||||
|
||||
return $results;
|
||||
}
|
||||
@ -894,4 +906,32 @@ class ImportService
|
||||
|
||||
return $isEmpty;
|
||||
}
|
||||
|
||||
public function presentResults($results, $includeSettings = false)
|
||||
{
|
||||
$message = '';
|
||||
$skipped = [];
|
||||
|
||||
if ($includeSettings) {
|
||||
$message = trans('texts.imported_settings') . '<br/>';
|
||||
}
|
||||
|
||||
foreach ($results as $entityType => $entityResults) {
|
||||
if ($count = count($entityResults[RESULT_SUCCESS])) {
|
||||
$message .= trans("texts.created_{$entityType}s", ['count' => $count]) . '<br/>';
|
||||
}
|
||||
if (count($entityResults[RESULT_FAILURE])) {
|
||||
$skipped = array_merge($skipped, $entityResults[RESULT_FAILURE]);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($skipped)) {
|
||||
$message .= '<p/>' . trans('texts.failed_to_import') . '<br/>';
|
||||
foreach ($skipped as $skip) {
|
||||
$message .= json_encode($skip) . '<br/>';
|
||||
}
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
|
@ -2460,6 +2460,8 @@ $LANG = array(
|
||||
'reply_to_email' => 'Reply-To Email',
|
||||
'reply_to_email_help' => 'Specify the reply-to address for client emails.',
|
||||
'bcc_email_help' => 'Privately include this address with client emails.',
|
||||
'import_complete' => 'Your import has successfully completed.',
|
||||
|
||||
|
||||
);
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
<br/>
|
||||
@foreach (\App\Services\ImportService::$entityTypes as $entityType)
|
||||
{!! Former::file("{$entityType}_file")
|
||||
{!! Former::file($entityType)
|
||||
->addGroupClass("import-file {$entityType}-file") !!}
|
||||
@endforeach
|
||||
|
||||
|
@ -6,6 +6,11 @@
|
||||
@include('accounts.nav', ['selected' => ACCOUNT_IMPORT_EXPORT])
|
||||
|
||||
{!! Former::open('/import_csv')->addClass('warn-on-exit') !!}
|
||||
{!! Former::populateField('timestamp', $timestamp) !!}
|
||||
|
||||
<div style="display:none">
|
||||
{!! Former::text('timestamp') !!}
|
||||
</div>
|
||||
|
||||
@foreach (App\Services\ImportService::$entityTypes as $entityType)
|
||||
@if (isset($data[$entityType]))
|
||||
|
Loading…
Reference in New Issue
Block a user