From 7b5e0a4eb24a22edc8a029a74d323bc4a521be9d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Tue, 13 Jul 2021 20:11:00 +1000 Subject: [PATCH 1/7] Update migration route --- app/Http/Controllers/Migration/StepsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Migration/StepsController.php b/app/Http/Controllers/Migration/StepsController.php index e7e4d76a6822..f39eb37a5a71 100644 --- a/app/Http/Controllers/Migration/StepsController.php +++ b/app/Http/Controllers/Migration/StepsController.php @@ -70,7 +70,7 @@ class StepsController extends BaseController if ($request->option == 0) { - session()->put('MIGRATION_ENDPOINT', 'https://invoicing.co'); + session()->put('MIGRATION_ENDPOINT', 'https://v5-app1.invoicing.co'); return redirect( url('/migration/auth') From 7a07c3da1c43486b4cbe7e4dfaf359e3eece9f72 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 16 Jul 2021 08:45:07 +1000 Subject: [PATCH 2/7] Fixes for migrations --- app/Traits/GenerateMigrationResources.php | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/app/Traits/GenerateMigrationResources.php b/app/Traits/GenerateMigrationResources.php index 43d5c29aa814..fcdb04c90bfc 100644 --- a/app/Traits/GenerateMigrationResources.php +++ b/app/Traits/GenerateMigrationResources.php @@ -192,7 +192,7 @@ info("get company"); 'payment_terms' => $this->account->payment_terms ?: '', 'reset_counter_frequency_id' => $this->account->reset_counter_frequency_id ? (string) $this->transformFrequencyId ($this->account->reset_counter_frequency_id) : '0', - 'payment_type_id' => $this->account->payment_type_id ? (string) $this->account->payment_type_id : '1', + 'payment_type_id' => $this->account->payment_type_id ? (string) $this->transformPaymentType($this->account->payment_type_id) : '1', 'reset_counter_date' => $this->account->reset_counter_date ?: '', 'tax_name1' => $this->account->tax_name1 ?: '', 'tax_rate1' => $this->account->tax_rate1 ?: 0, @@ -431,10 +431,6 @@ info("get company"); foreach($agts as $agt) { $payment_method = $agt->default_payment_method; - - if(!$payment_method) - continue; - $contact = Contact::where('id', $payment_method->contact_id)->withTrashed()->first(); $transformed[] = [ @@ -1262,7 +1258,7 @@ info("get company"); { switch ($payment_type_id) { case PAYMENT_TYPE_CREDIT: - return 1; + return 32; case PAYMENT_TYPE_ACH: return 4; case PAYMENT_TYPE_VISA: @@ -1283,6 +1279,8 @@ info("get company"); return 12; case PAYMENT_TYPE_PAYPAL: return 13; + case 16: + return 15; case PAYMENT_TYPE_CARTE_BLANCHE: return 16; case PAYMENT_TYPE_UNIONPAY: @@ -1774,7 +1772,7 @@ info("translated gateway_type = {$translated_gateway_type}"); 'invoice_documents' => $expense->invoice_documents, 'invoice_id' => $expense->invoice_id, 'payment_date' => $expense->payment_date, - 'payment_type_id' => $expense->payment_type_id, + 'payment_type_id' => $this->transformPaymentType($expense->payment_type_id), 'private_notes' => $expense->private_notes, 'public_notes' => $expense->public_notes, 'recurring_expense_id' => $expense->recurring_expense_id, From 05b12a6bb9a8bcbd87f2daf849c2d32ea7d203e1 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Fri, 16 Jul 2021 15:40:52 +1000 Subject: [PATCH 3/7] Refactor for hosted migration --- .../Controllers/Migration/StepsController.php | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Migration/StepsController.php b/app/Http/Controllers/Migration/StepsController.php index f39eb37a5a71..fe0541fd9180 100644 --- a/app/Http/Controllers/Migration/StepsController.php +++ b/app/Http/Controllers/Migration/StepsController.php @@ -72,10 +72,17 @@ class StepsController extends BaseController session()->put('MIGRATION_ENDPOINT', 'https://v5-app1.invoicing.co'); + + //refactor here to make this a little more magical + // return redirect( - url('/migration/auth') + url('/migration/companies') ); + // return redirect( + // url('/migration/auth') + // ); + // return redirect( // url('/migration/endpoint') // ); @@ -209,6 +216,28 @@ class StepsController extends BaseController ); } + if(Utils::isNinja()) + { + + //push a job with $request->all() and the auth()->user() reference; + // + //In that job we will + // + //Create data file + // + //Send along a custom protected route + // + //auth as the end user + //and process as per normal. + // + //we should include a success failure email to contact@ so we can follow up. + + if ($completeService->isSuccessful()) { + return view('migration.completed'); + } + + } + $completeService = (new CompleteService(session('MIGRATION_ACCOUNT_TOKEN'))); try { From 0743b003ab39927f7c6e0c20b662ed43697765c9 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 17 Jul 2021 15:26:47 +1000 Subject: [PATCH 4/7] Streamlined hosted migration --- .../Controllers/Migration/StepsController.php | 8 +- app/Jobs/HostedMigration.php | 156 ++++++++++++++++++ config/ninja.php | 2 + 3 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 app/Jobs/HostedMigration.php diff --git a/app/Http/Controllers/Migration/StepsController.php b/app/Http/Controllers/Migration/StepsController.php index fe0541fd9180..cba445154ad9 100644 --- a/app/Http/Controllers/Migration/StepsController.php +++ b/app/Http/Controllers/Migration/StepsController.php @@ -72,11 +72,10 @@ class StepsController extends BaseController session()->put('MIGRATION_ENDPOINT', 'https://v5-app1.invoicing.co'); - //refactor here to make this a little more magical // return redirect( - url('/migration/companies') + url('/migration/companies?hosted=true') ); // return redirect( @@ -216,7 +215,7 @@ class StepsController extends BaseController ); } - if(Utils::isNinja()) + if($request->has('hosted') && $request->input('hosted') == 'true') { //push a job with $request->all() and the auth()->user() reference; @@ -231,7 +230,8 @@ class StepsController extends BaseController //and process as per normal. // //we should include a success failure email to contact@ so we can follow up. - + HostedMigration::dispatch(auth()->user(), $request->all(), config('database.default')); + if ($completeService->isSuccessful()) { return view('migration.completed'); } diff --git a/app/Jobs/HostedMigration.php b/app/Jobs/HostedMigration.php new file mode 100644 index 000000000000..eed4521a3177 --- /dev/null +++ b/app/Jobs/HostedMigration.php @@ -0,0 +1,156 @@ +user = $user; + $this->data = $data; + $this->db = $db; + $this->v4_secret = config('ninja.ninja_hosted_secret'); + } + + /** + * Execute the job. + */ + public function handle() + { + config(['database.default' => $this->db]); + + //Create or get a token + $this->getToken(); + //build the contents to be posted + + $completeService = (new CompleteService($this->migration_token)); + + $migrationData = $this->generateMigrationData($data); + + $completeService->data($migrationData) + ->endpoint('https://v5-app1.invoicing.co') + ->start(); + + } + + private function getToken() + { + $url = 'https://invoicing.co/api/v1/get_migration_account'; + + $headers = [ + 'X-API-HOSTED-SECRET' => $this->v4_secret, + 'X-Requested-With' => 'XMLHttpRequest', + 'Content-Type' => 'application/json', + ]; + + $body = [ + 'email' => $this->user->email, + ]; + + $response = Request::post($url, $headers, $body); + + if (in_array($response->code, [200])) { + + $data = $response->body(); + + $this->migration_token = $data['token']; + + } else { + info("getting token failed"); + info($response->raw_body); + + } + + } + + + public function generateMigrationData(array $data): array + { + set_time_limit(0); + + $migrationData = []; + + foreach ($data['companies'] as $company) { + $account = Account::where('account_key', $company['id'])->firstOrFail(); + + $this->account = $account; + + $date = date('Y-m-d'); + $accountKey = $this->account->account_key; + + $output = fopen('php://output', 'w') or Utils::fatalError(); + + $fileName = "{$accountKey}-{$date}-invoiceninja"; + + $localMigrationData['data'] = [ + 'account' => $this->getAccount(), + 'company' => $this->getCompany(), + 'users' => $this->getUsers(), + 'tax_rates' => $this->getTaxRates(), + 'payment_terms' => $this->getPaymentTerms(), + 'clients' => $this->getClients(), + 'company_gateways' => $this->getCompanyGateways(), + 'client_gateway_tokens' => $this->getClientGatewayTokens(), + 'vendors' => $this->getVendors(), + 'projects' => $this->getProjects(), + 'products' => $this->getProducts(), + 'credits' => $this->getCreditsNotes(), + 'invoices' => $this->getInvoices(), + 'recurring_invoices' => $this->getRecurringInvoices(), + 'quotes' => $this->getQuotes(), + 'payments' => array_merge($this->getPayments(), $this->getCredits()), + 'documents' => $this->getDocuments(), + 'expense_categories' => $this->getExpenseCategories(), + 'task_statuses' => $this->getTaskStatuses(), + 'expenses' => $this->getExpenses(), + 'tasks' => $this->getTasks(), + 'documents' => $this->getDocuments(), + 'ninja_tokens' => $this->getNinjaToken(), + ]; + + $localMigrationData['force'] = array_key_exists('force', $company); + + Storage::makeDirectory('migrations'); + $file = Storage::path("migrations/{$fileName}.zip"); + + //$file = storage_path("migrations/{$fileName}.zip"); + + ksort($localMigrationData); + + $zip = new \ZipArchive(); + $zip->open($file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE); + $zip->addFromString('migration.json', json_encode($localMigrationData, JSON_PRETTY_PRINT)); + $zip->close(); + + $localMigrationData['file'] = $file; + + $migrationData[] = $localMigrationData; + } + + return $migrationData; + + } +} \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index a585e50b7314..aeeece9de470 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -47,4 +47,6 @@ return [ 'subscription_key' => env('MSBOT_LUIS_SUBSCRIPTION_KEY'), ], + 'ninja_hosted_secret' => env('NINJA_HOSTED_SECRET', false), + ]; From 50a0532bf4ccdce9a402a13d7cd3bf291f5d5d06 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 17 Jul 2021 15:59:08 +1000 Subject: [PATCH 5/7] Streamline Hosted Migration --- app/Jobs/HostedMigration.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Jobs/HostedMigration.php b/app/Jobs/HostedMigration.php index eed4521a3177..3f14567966a9 100644 --- a/app/Jobs/HostedMigration.php +++ b/app/Jobs/HostedMigration.php @@ -47,7 +47,7 @@ class HostedMigration extends Job //build the contents to be posted $completeService = (new CompleteService($this->migration_token)); - + $migrationData = $this->generateMigrationData($data); $completeService->data($migrationData) @@ -67,7 +67,12 @@ class HostedMigration extends Job ]; $body = [ + 'first_name' => $this->user->first_name, + 'last_name' => $this->user->last_name, 'email' => $this->user->email, + 'privacy_policy' => true, + 'terms_of_service' => true, + 'password' => '', ]; $response = Request::post($url, $headers, $body); From 391df15a965a655623e7e37509b35ede7fe28a43 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 17 Jul 2021 18:58:42 +1000 Subject: [PATCH 6/7] Refactor Migration codebase --- .../Controllers/Migration/StepsController.php | 43 +++++++++---------- app/Jobs/HostedMigration.php | 19 ++++---- app/Services/Migration/CompleteService.php | 1 + app/Traits/GenerateMigrationResources.php | 12 ++---- 4 files changed, 35 insertions(+), 40 deletions(-) diff --git a/app/Http/Controllers/Migration/StepsController.php b/app/Http/Controllers/Migration/StepsController.php index cba445154ad9..c6bc6cb3110d 100644 --- a/app/Http/Controllers/Migration/StepsController.php +++ b/app/Http/Controllers/Migration/StepsController.php @@ -8,16 +8,17 @@ use App\Http\Requests\MigrationCompaniesRequest; use App\Http\Requests\MigrationEndpointRequest; use App\Http\Requests\MigrationForwardRequest; use App\Http\Requests\MigrationTypeRequest; +use App\Jobs\HostedMigration; use App\Libraries\Utils; use App\Models\Account; use App\Services\Migration\AuthService; use App\Services\Migration\CompanyService; use App\Services\Migration\CompleteService; use App\Traits\GenerateMigrationResources; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; use Validator; -use Illuminate\Http\Request; class StepsController extends BaseController { @@ -48,6 +49,17 @@ class StepsController extends BaseController */ public function start() { + if(Utils::isNinja()){ + + session()->put('MIGRATION_ENDPOINT', 'https://v5-app1.invoicing.co'); + // session()->put('MIGRATION_ENDPOINT', 'http://ninja.test:8000'); + session()->put('MIGRATION_ACCOUNT_TOKEN',''); + session()->put('MIGRAITON_API_SECRET', null); + + return $this->companies(); + + } + return view('migration.start'); } @@ -68,16 +80,13 @@ class StepsController extends BaseController { session()->put('MIGRATION_TYPE', $request->option); - if ($request->option == 0) { + if ($request->option == 0 || $request->option == '0') { - session()->put('MIGRATION_ENDPOINT', 'https://v5-app1.invoicing.co'); - - //refactor here to make this a little more magical - // return redirect( url('/migration/companies?hosted=true') ); + //old // return redirect( // url('/migration/auth') // ); @@ -124,6 +133,7 @@ class StepsController extends BaseController public function endpoint() { + if ($this->shouldGoBack('endpoint')) { return redirect( url($this->access['endpoint']['redirect']) @@ -214,27 +224,14 @@ class StepsController extends BaseController url($this->access['companies']['redirect']) ); } + $bool = true; - if($request->has('hosted') && $request->input('hosted') == 'true') + if(Utils::isNinja()) { - //push a job with $request->all() and the auth()->user() reference; - // - //In that job we will - // - //Create data file - // - //Send along a custom protected route - // - //auth as the end user - //and process as per normal. - // - //we should include a success failure email to contact@ so we can follow up. - HostedMigration::dispatch(auth()->user(), $request->all(), config('database.default')); + $this->dispatch(new HostedMigration(auth()->user(), $request->all(), config('database.default'))); - if ($completeService->isSuccessful()) { - return view('migration.completed'); - } + return view('migration.completed'); } diff --git a/app/Jobs/HostedMigration.php b/app/Jobs/HostedMigration.php index 3f14567966a9..e0725dbdf684 100644 --- a/app/Jobs/HostedMigration.php +++ b/app/Jobs/HostedMigration.php @@ -23,9 +23,7 @@ class HostedMigration extends Job private $v4_secret; - private $migration_token; - - public $account; + public $migration_token; public function __construct(User $user, array $data, $db) { @@ -40,18 +38,19 @@ class HostedMigration extends Job */ public function handle() { + config(['database.default' => $this->db]); //Create or get a token $this->getToken(); - //build the contents to be posted $completeService = (new CompleteService($this->migration_token)); - $migrationData = $this->generateMigrationData($data); + $migrationData = $this->generateMigrationData($this->data); $completeService->data($migrationData) ->endpoint('https://v5-app1.invoicing.co') + // ->endpoint('http://ninja.test:8000') ->start(); } @@ -59,6 +58,7 @@ class HostedMigration extends Job private function getToken() { $url = 'https://invoicing.co/api/v1/get_migration_account'; + // $url = 'http://ninja.test:8000/api/v1/get_migration_account'; $headers = [ 'X-API-HOSTED-SECRET' => $this->v4_secret, @@ -75,13 +75,15 @@ class HostedMigration extends Job 'password' => '', ]; + $body = \Unirest\Request\Body::json($body); + $response = Request::post($url, $headers, $body); if (in_array($response->code, [200])) { - $data = $response->body(); - - $this->migration_token = $data['token']; + $data = $response->body; + info(print_r($data,1)); + $this->migration_token = $data->token; } else { info("getting token failed"); @@ -89,6 +91,7 @@ class HostedMigration extends Job } + return $this; } diff --git a/app/Services/Migration/CompleteService.php b/app/Services/Migration/CompleteService.php index 140431388aff..171576e66458 100644 --- a/app/Services/Migration/CompleteService.php +++ b/app/Services/Migration/CompleteService.php @@ -40,6 +40,7 @@ class CompleteService public function start() { + $files = []; foreach ($this->data as $companyKey => $companyData) { diff --git a/app/Traits/GenerateMigrationResources.php b/app/Traits/GenerateMigrationResources.php index fcdb04c90bfc..6943c449096d 100644 --- a/app/Traits/GenerateMigrationResources.php +++ b/app/Traits/GenerateMigrationResources.php @@ -363,8 +363,6 @@ info("get company"); private function getClientSettings($client) { - info("get client settings"); - $settings = new \stdClass(); $settings->currency_id = $client->currency_id ? (string) $client->currency_id : (string) $client->account->currency_id; @@ -381,8 +379,7 @@ info("get company"); protected function getClientContacts($client) { - info("get client contacts"); - + $contacts = Contact::where('client_id', $client->id)->withTrashed()->get(); $transformed = []; @@ -995,7 +992,7 @@ info("get company"); public function getResourceInvitations($items, $resourceKeyId) { - info("get resource {$resourceKeyId} invitations"); + // info("get resource {$resourceKeyId} invitations"); $transformed = []; @@ -1068,7 +1065,7 @@ info("get company"); public function getInvoiceItems($items) { - info("get invoice items"); + // info("get invoice items"); $transformed = []; @@ -1394,12 +1391,9 @@ info("get company"); $fees_and_limits = $this->transformFeesAndLimits($gateway_type); -info("generated fees and limits = "); -info(print_r($fees_and_limits,1)); $translated_gateway_type = $this->translateGatewayTypeId($gateway_type); -info("translated gateway_type = {$translated_gateway_type}"); $fees->{$translated_gateway_type} = $fees_and_limits; } From 132439425620a1b966bede163622692f629d2252 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 17 Jul 2021 20:42:27 +1000 Subject: [PATCH 7/7] Fixes for financial year start --- app/Traits/GenerateMigrationResources.php | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/app/Traits/GenerateMigrationResources.php b/app/Traits/GenerateMigrationResources.php index 6943c449096d..23b23b109e7e 100644 --- a/app/Traits/GenerateMigrationResources.php +++ b/app/Traits/GenerateMigrationResources.php @@ -71,11 +71,21 @@ trait GenerateMigrationResources protected function getCompany() { -info("get company"); + info("get company"); + + $financial_year_start = null; + if($this->account->financial_year_start) + { + //2000-02-01 format + $exploded_date = explode("-", $this->account->financial_year_start); + + $financial_year_start = (int)$exploded_date[1]; + + } return [ 'first_day_of_week' => $this->account->start_of_week, - 'first_month_of_year' => $this->account->financial_year_start, + 'first_month_of_year' => $financial_year_start, 'version' => NINJA_VERSION, 'referral_code' => $this->account->referral_code ?: '', 'account_id' => $this->account->id, @@ -130,10 +140,15 @@ info("get company"); { info("get co settings"); + $timezone_id = $this->account->timezone_id ? $this->account->timezone_id : 15; + + if($timezone_id > 57) + $timezone_id = (string)($timezone_id - 1); + return [ 'auto_bill' => $this->transformAutoBill($this->account->token_billing_id), 'payment_terms' => $this->account->payment_terms ? (string) $this->account->payment_terms : '', - 'timezone_id' => $this->account->timezone_id ? (string) $this->account->timezone_id : '15', + 'timezone_id' => $timezone_id, 'date_format_id' => $this->account->date_format_id ? (string) $this->account->date_format_id : '1', 'currency_id' => $this->account->currency_id ? (string) $this->account->currency_id : '1', 'name' => $this->account->name ?: trans('texts.untitled'),