1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-13 22:54:25 +01:00
invoiceninja/app/Jobs/Company/CompanyImport.php

1729 lines
53 KiB
PHP
Raw Normal View History

2021-05-14 07:23:00 +02:00
<?php
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
2022-04-27 05:20:41 +02:00
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
2021-05-14 07:23:00 +02:00
*
2021-06-16 08:58:16 +02:00
* @license https://www.elastic.co/licensing/elastic-license
2021-05-14 07:23:00 +02:00
*/
namespace App\Jobs\Company;
2021-05-27 07:57:07 +02:00
use App\Exceptions\ImportCompanyFailed;
2021-05-14 07:23:00 +02:00
use App\Exceptions\NonExistingMigrationFile;
use App\Factory\ClientContactFactory;
2021-05-14 07:23:00 +02:00
use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject;
use App\Jobs\Util\UnlinkFile;
use App\Libraries\MultiDB;
use App\Mail\DownloadBackup;
use App\Mail\DownloadInvoices;
2021-06-07 23:23:20 +02:00
use App\Mail\Import\CompanyImportFailure;
2021-06-29 02:04:09 +02:00
use App\Mail\Import\ImportCompleted;
2021-05-31 01:47:14 +02:00
use App\Models\Activity;
2021-06-05 04:42:56 +02:00
use App\Models\Backup;
use App\Models\BankIntegration;
use App\Models\BankTransaction;
2021-05-31 01:47:14 +02:00
use App\Models\Client;
use App\Models\ClientContact;
2021-05-31 02:10:19 +02:00
use App\Models\ClientGatewayToken;
2021-05-14 07:23:00 +02:00
use App\Models\Company;
2021-05-31 01:47:14 +02:00
use App\Models\CompanyGateway;
use App\Models\CompanyLedger;
2021-05-27 07:57:07 +02:00
use App\Models\CompanyUser;
2021-05-31 01:47:14 +02:00
use App\Models\Credit;
2021-05-14 07:23:00 +02:00
use App\Models\CreditInvitation;
2021-05-31 02:22:30 +02:00
use App\Models\Design;
2021-05-31 01:47:14 +02:00
use App\Models\Document;
use App\Models\Expense;
use App\Models\ExpenseCategory;
2021-05-31 02:10:19 +02:00
use App\Models\GroupSetting;
2021-05-31 02:22:30 +02:00
use App\Models\Invoice;
2021-05-14 07:23:00 +02:00
use App\Models\InvoiceInvitation;
2021-05-31 01:47:14 +02:00
use App\Models\Payment;
use App\Models\PaymentTerm;
use App\Models\Paymentable;
use App\Models\Product;
2021-06-04 12:07:45 +02:00
use App\Models\Project;
use App\Models\PurchaseOrder;
use App\Models\PurchaseOrderInvitation;
2021-05-31 01:47:14 +02:00
use App\Models\Quote;
2021-05-14 07:23:00 +02:00
use App\Models\QuoteInvitation;
use App\Models\RecurringExpense;
2021-05-14 07:23:00 +02:00
use App\Models\RecurringInvoice;
use App\Models\RecurringInvoiceInvitation;
2021-05-31 01:47:14 +02:00
use App\Models\Subscription;
2021-05-31 02:22:30 +02:00
use App\Models\Task;
2021-05-31 02:10:19 +02:00
use App\Models\TaskStatus;
2021-05-31 01:47:14 +02:00
use App\Models\TaxRate;
2021-05-14 07:23:00 +02:00
use App\Models\User;
2021-05-31 02:10:19 +02:00
use App\Models\Vendor;
2021-05-14 07:23:00 +02:00
use App\Models\VendorContact;
2021-05-31 02:22:30 +02:00
use App\Models\Webhook;
2021-05-31 00:55:27 +02:00
use App\Utils\Ninja;
use App\Utils\TempFile;
use App\Utils\Traits\GeneratesCounter;
2021-05-14 07:23:00 +02:00
use App\Utils\Traits\MakesHash;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\App;
2021-06-04 12:07:45 +02:00
use Illuminate\Support\Facades\Cache;
2021-05-14 07:23:00 +02:00
use Illuminate\Support\Facades\Storage;
2021-05-15 06:29:19 +02:00
use Illuminate\Support\Str;
use JsonMachine\JsonDecoder\ExtJsonDecoder;
use JsonMachine\JsonMachine;
2021-05-14 07:23:00 +02:00
use ZipArchive;
use function GuzzleHttp\json_encode;
2021-05-14 07:23:00 +02:00
class CompanyImport implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, MakesHash, GeneratesCounter;
2021-05-14 07:23:00 +02:00
2021-06-28 06:09:02 +02:00
public $tries = 1;
public $timeout = 0;
2021-05-15 06:29:19 +02:00
protected $current_app_version;
private $account;
2021-05-31 00:55:27 +02:00
public $company;
public $user;
2021-05-14 07:23:00 +02:00
2021-06-28 08:02:49 +02:00
private $file_location;
2021-05-14 07:23:00 +02:00
2021-05-31 00:55:27 +02:00
public $backup_file;
2021-05-14 07:23:00 +02:00
2021-05-15 06:29:19 +02:00
public $ids = [];
2021-05-31 00:55:27 +02:00
private $request_array = [];
2021-05-15 06:29:19 +02:00
2021-06-08 04:08:07 +02:00
public $message = '';
2021-06-07 07:42:39 +02:00
2021-06-08 05:45:19 +02:00
public $pre_flight_checks_pass = true;
public $force_user_coalesce = false;
public $company_owner;
2021-09-18 15:20:16 +02:00
private $file_path;
2021-05-15 06:29:19 +02:00
private $importables = [
2021-05-31 01:47:14 +02:00
// 'company',
2021-05-15 06:29:19 +02:00
'users',
2021-05-31 01:47:14 +02:00
'company_users',
2021-05-31 00:55:27 +02:00
'payment_terms',
'tax_rates',
'expense_categories',
'task_statuses',
'clients',
'client_contacts',
'vendors',
'vendor_contacts',
2021-05-31 00:55:27 +02:00
'projects',
2021-05-31 02:10:19 +02:00
'products',
2021-05-31 00:55:27 +02:00
'company_gateways',
'client_gateway_tokens',
'group_settings',
2021-05-31 02:10:19 +02:00
'subscriptions',
2021-05-31 00:55:27 +02:00
'recurring_invoices',
2021-05-31 02:10:19 +02:00
'recurring_invoice_invitations',
'invoices',
'invoice_invitations',
2021-05-31 00:55:27 +02:00
'quotes',
2021-05-31 02:10:19 +02:00
'quote_invitations',
'credits',
'credit_invitations',
'recurring_expenses',
2021-05-31 00:55:27 +02:00
'expenses',
'tasks',
2021-05-31 02:22:30 +02:00
'payments',
2021-05-31 00:55:27 +02:00
'company_ledger',
2021-05-31 02:22:30 +02:00
'designs',
'documents',
'webhooks',
'system_logs',
'purchase_orders',
'purchase_order_invitations',
'bank_integrations',
'bank_transactions',
'payments',
2021-05-15 06:29:19 +02:00
];
2022-03-18 05:39:56 +01:00
private $company_properties = [
"convert_products",
"fill_products",
"update_products",
"show_product_details",
"client_can_register",
"custom_surcharge_taxes1",
"custom_surcharge_taxes2",
"custom_surcharge_taxes3",
"custom_surcharge_taxes4",
"show_product_cost",
"enabled_tax_rates",
"enabled_modules",
"enable_product_cost",
"enable_product_quantity",
"default_quantity",
"subdomain",
"size_id",
"first_day_of_week",
"first_month_of_year",
"portal_mode",
"portal_domain",
"enable_modules",
"custom_fields",
"industry_id",
"slack_webhook_url",
"google_analytics_key",
"created_at",
"updated_at",
"enabled_item_tax_rates",
"is_large",
"enable_shop_api",
"default_auto_bill",
"mark_expenses_invoiceable",
"mark_expenses_paid",
"invoice_expense_documents",
"auto_start_tasks",
"invoice_task_timelog",
"invoice_task_documents",
"show_tasks_table",
"is_disabled",
"default_task_is_date_based",
"enable_product_discount",
"calculate_expense_tax_by_amount",
"expense_inclusive_taxes",
"session_timeout",
"oauth_password_required",
"invoice_task_datelog",
"default_password_timeout",
"show_task_end_date",
"markdown_enabled",
"use_comma_as_decimal_place",
"report_include_drafts",
"client_registration_fields",
"convert_rate_to_client",
];
2021-05-14 07:23:00 +02:00
/**
* Create a new job instance.
*
* @param Company $company
* @param User $user
2021-05-31 00:55:27 +02:00
* @param string $hash - the cache hash of the import data.
* @param array $request->all()
2021-05-14 07:23:00 +02:00
*/
2021-06-28 08:02:49 +02:00
public function __construct(Company $company, User $user, string $file_location, array $request_array)
2021-05-14 07:23:00 +02:00
{
$this->company = $company;
$this->user = $user;
2021-06-28 08:02:49 +02:00
$this->file_location = $file_location;
2021-05-31 00:55:27 +02:00
$this->request_array = $request_array;
2021-05-15 06:29:19 +02:00
$this->current_app_version = config('ninja.app_version');
2021-05-14 07:23:00 +02:00
}
private function getObject($key, $force_array = false)
2021-09-18 15:20:16 +02:00
{
set_time_limit(0);
$json = JsonMachine::fromFile($this->file_path, '/'.$key, new ExtJsonDecoder);
if($force_array)
return iterator_to_array($json);
return $json;
2021-09-18 15:20:16 +02:00
}
2021-05-14 07:23:00 +02:00
public function handle()
{
MultiDB::setDb($this->company->db);
2021-05-27 07:57:07 +02:00
$this->company = Company::where('company_key', $this->company->company_key)->firstOrFail();
2021-05-15 06:29:19 +02:00
$this->account = $this->company->account;
$this->company_owner = $this->company->owner();
2021-05-14 07:23:00 +02:00
2021-06-07 23:45:40 +02:00
nlog("Company ID = {$this->company->id}");
2021-06-28 08:02:49 +02:00
nlog("file_location ID = {$this->file_location}");
2021-06-07 23:46:00 +02:00
2021-06-28 08:02:49 +02:00
// $this->backup_file = Cache::get($this->hash);
2021-05-31 00:55:27 +02:00
2021-06-28 08:02:49 +02:00
if ( empty( $this->file_location ) )
2021-05-31 00:55:27 +02:00
throw new \Exception('No import data found, has the cache expired?');
// $this->backup_file = json_decode(file_get_contents($this->file_location));
$tmp_file = $this->unzipFile();
2021-09-18 15:20:16 +02:00
$this->file_path = $tmp_file;
2021-06-08 14:58:46 +02:00
$this->checkUserCount();
2021-06-01 00:09:38 +02:00
2021-06-04 12:07:45 +02:00
if(array_key_exists('import_settings', $this->request_array) && $this->request_array['import_settings'] == 'true') {
2021-06-08 14:58:46 +02:00
$this->preFlightChecks()->importSettings();
2021-06-01 00:09:38 +02:00
}
2021-06-04 12:07:45 +02:00
if(array_key_exists('import_data', $this->request_array) && $this->request_array['import_data'] == 'true') {
2021-06-01 00:09:38 +02:00
2021-06-07 23:23:20 +02:00
try{
2021-06-08 14:58:46 +02:00
$this->preFlightChecks()
2021-06-07 23:23:20 +02:00
->purgeCompanyData()
2022-03-18 05:39:56 +01:00
->importCompany()
->importData()
->postImportCleanup();
2021-06-07 23:23:20 +02:00
2021-06-29 02:04:09 +02:00
$data = [
'errors' => []
];
$_company = Company::find($this->company->id);
2021-06-29 02:04:09 +02:00
$nmo = new NinjaMailerObject;
$nmo->mailable = new ImportCompleted($_company, $data);
$nmo->company = $_company;
$nmo->settings = $_company->settings;
$nmo->to_user = $_company->owner();
2022-09-07 06:15:27 +02:00
NinjaMailerJob::dispatch($nmo);
2021-06-29 02:04:09 +02:00
2021-06-07 23:23:20 +02:00
}
catch(\Exception $e){
info($e->getMessage());
}
2021-06-01 00:09:38 +02:00
}
unlink($tmp_file);
2021-06-28 08:02:49 +02:00
2021-05-14 07:23:00 +02:00
}
//
private function postImportCleanup()
{
//ensure all clients have a contact
$this->company
->clients()
->whereDoesntHave('contacts')
->cursor()
->each(function ($client){
$new_contact = ClientContactFactory::create($client->company_id, $client->user_id);
$new_contact->client_id = $client->id;
$new_contact->contact_key = Str::random(40);
$new_contact->is_primary = true;
$new_contact->confirmed = true;
$new_contact->email = ' ';
$new_contact->save();
});
}
private function unzipFile()
{
2021-06-30 01:09:38 +02:00
$path = TempFile::filePath(Storage::disk(config('filesystems.default'))->get($this->file_location), basename($this->file_location));
$zip = new ZipArchive();
$archive = $zip->open($path);
$file_path = sys_get_temp_dir().'/'.sha1(microtime());
$zip->extractTo($file_path);
$zip->close();
$file_location = "{$file_path}/backup.json";
if (! file_exists($file_path))
throw new NonExistingMigrationFile('Backup file does not exist, or is corrupted.');
return $file_location;
}
2021-06-07 07:42:39 +02:00
/**
* On the hosted platform we cannot allow the
* import to start if there are users > plan number
* due to entity user_id dependencies
*
* @return bool
*/
private function checkUserCount()
{
if(Ninja::isSelfHost())
2021-06-08 05:45:19 +02:00
$this->pre_flight_checks_pass = true;
2021-06-07 07:42:39 +02:00
2021-09-18 15:20:16 +02:00
// $backup_users = $this->backup_file->users;
$backup_users = $this->getObject('users', true);
2021-06-07 07:42:39 +02:00
$company_users = $this->company->users;
2021-06-08 14:05:18 +02:00
nlog("Backup user count = ".count($backup_users));
2021-06-07 07:42:39 +02:00
if(count($backup_users) > 1){
2021-12-19 06:01:42 +01:00
2021-06-07 07:42:39 +02:00
}
2021-06-08 14:05:18 +02:00
nlog("backup users email = " . $backup_users[0]->email);
if(count($backup_users) == 1 && $this->company_owner->email != $backup_users[0]->email) {
2021-12-19 06:01:42 +01:00
2021-06-07 07:42:39 +02:00
}
$backup_users_emails = array_column($backup_users, 'email');
2021-06-07 07:42:39 +02:00
$company_users_emails = $company_users->pluck('email')->toArray();
$existing_user_count = count(array_intersect($backup_users_emails, $company_users_emails));
2021-06-08 14:05:18 +02:00
nlog("existing user count = {$existing_user_count}");
2021-06-07 07:42:39 +02:00
if($existing_user_count > 1){
2021-06-08 04:16:32 +02:00
if($this->account->plan == 'pro'){
2021-12-19 06:01:42 +01:00
2021-06-08 04:16:32 +02:00
}
2021-06-07 07:42:39 +02:00
if($this->account->plan == 'enterprise'){
}
}
if($this->company->account->isFreeHostedClient() && (count($this->getObject('clients', true)) > config('ninja.quotas.free.clients')) ){
2021-06-08 14:05:18 +02:00
nlog("client quota busted");
$client_limit = config('ninja.quotas.free.clients');
$client_count = count($this->getObject('clients', true));
$this->message = "You are attempting to import ({$client_count}) clients, your current plan allows a total of ({$client_limit})";
2021-06-08 13:45:23 +02:00
$this->pre_flight_checks_pass = false;
}
2021-06-08 05:45:19 +02:00
return $this;
2021-06-07 07:42:39 +02:00
}
2021-05-14 07:23:00 +02:00
//check if this is a complete company import OR if it is selective
/*
Company and settings only
Data
*/
private function preFlightChecks()
{
//check the file version and perform any necessary adjustments to the file in order to proceed - needed when we change schema
2021-09-18 15:20:16 +02:00
$data = (object)$this->getObject('app_version', true);
2021-09-18 15:20:16 +02:00
if($this->current_app_version != $data->app_version)
2021-05-15 06:29:19 +02:00
{
//perform some magic here
}
2021-06-08 05:45:19 +02:00
2021-06-08 13:45:23 +02:00
if($this->pre_flight_checks_pass === false)
2021-06-07 23:23:20 +02:00
{
2021-06-29 02:04:09 +02:00
$this->sendImportMail($this->message);
2021-06-08 04:16:32 +02:00
throw new \Exception($this->message);
2021-06-07 23:23:20 +02:00
}
2021-05-14 07:23:00 +02:00
return $this;
}
2021-05-31 00:55:27 +02:00
private function importSettings()
2021-05-14 07:23:00 +02:00
{
$co = (object)$this->getObject("company", true);
2021-12-31 06:32:22 +01:00
$settings = $co->settings;
$settings->invoice_number_counter = 1;
$settings->recurring_invoice_number_counter = 1;
$settings->quote_number_counter = 1;
$settings->credit_number_counter = 1;
$settings->task_number_counter = 1;
$settings->expense_number_counter = 1;
$settings->recurring_expense_number_counter = 1;
$settings->recurring_quote_number_counter = 1;
$settings->vendor_number_counter = 1;
$settings->ticket_number_counter = 1;
$settings->payment_number_counter = 1;
$settings->project_number_counter = 1;
2022-07-19 01:39:54 +02:00
$settings->purchase_order_number_counter = 1;
2021-09-18 15:20:16 +02:00
$this->company->settings = $co->settings;
// $this->company->settings = $this->backup_file->company->settings;
2021-05-31 00:55:27 +02:00
$this->company->save();
2021-05-14 07:23:00 +02:00
2021-05-31 00:55:27 +02:00
return $this;
2021-05-14 07:23:00 +02:00
}
2021-05-31 01:47:14 +02:00
private function purgeCompanyData()
{
$this->company->clients()->forceDelete();
2022-07-21 00:28:34 +02:00
$this->company->all_activities()->forceDelete();
2021-05-31 01:47:14 +02:00
$this->company->products()->forceDelete();
$this->company->projects()->forceDelete();
$this->company->tasks()->forceDelete();
$this->company->vendors()->forceDelete();
$this->company->expenses()->forceDelete();
2021-06-01 00:09:38 +02:00
$this->company->subscriptions()->forceDelete();
$this->company->purchase_orders()->forceDelete();
2021-05-31 01:47:14 +02:00
$this->company->save();
return $this;
}
2021-05-14 07:23:00 +02:00
private function importCompany()
{
2021-09-18 15:20:16 +02:00
//$tmp_company = $this->backup_file->company;
2022-03-18 05:39:56 +01:00
$tmp_company = (object)$this->getObject("company",true);
2021-05-31 00:55:27 +02:00
$tmp_company->company_key = $this->createHash();
$tmp_company->db = config('database.default');
$tmp_company->account_id = $this->account->id;
if(Ninja::isHosted())
$tmp_company->subdomain = MultiDB::randomSubdomainGenerator();
else
$tmp_company->subdomain = '';
2021-05-31 01:47:14 +02:00
2022-03-18 05:39:56 +01:00
foreach($this->company_properties as $value){
2022-05-03 09:24:35 +02:00
if(property_exists($tmp_company, $value))
$this->company->{$value} = $tmp_company->{$value};
2022-03-18 05:39:56 +01:00
}
2021-05-31 00:55:27 +02:00
$this->company->save();
2021-05-14 07:23:00 +02:00
return $this;
}
2021-05-31 01:47:14 +02:00
private function importData()
{
foreach($this->importables as $import){
2021-06-29 01:35:58 +02:00
$method = "import_{$import}";
2021-05-31 01:47:14 +02:00
2021-06-07 23:46:00 +02:00
nlog($method);
2021-06-07 23:51:21 +02:00
2021-05-31 01:47:14 +02:00
$this->{$method}();
}
2021-06-29 02:04:09 +02:00
nlog("finished importing company data");
2021-06-08 07:59:08 +02:00
2021-06-01 00:09:38 +02:00
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_bank_integrations()
{
$this->genericImport(BankIntegration::class,
['assigned_user_id','account_id', 'company_id', 'id', 'hashed_id'],
[
['users' => 'user_id'],
],
'bank_integrations',
'description');
return $this;
}
private function import_bank_transactions()
{
$this->genericImport(BankTransaction::class,
['assigned_user_id','company_id', 'id', 'hashed_id', 'user_id'],
[
['users' => 'user_id'],
['expenses' => 'expense_id'],
['vendors' => 'vendor_id'],
['expense_categories' => 'ninja_category_id'],
['expense_categories' => 'category_id'],
['bank_integrations' => 'bank_integration_id']
],
'bank_transactions',
null);
return $this;
}
private function import_recurring_expenses()
{
//unset / transforms / object_property / match_key
$this->genericImport(RecurringExpense::class,
2021-12-27 23:31:32 +01:00
['assigned_user_id', 'user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'project_id', 'vendor_id','recurring_expense_id'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['clients' => 'client_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
['invoices' => 'invoice_id'],
['expense_categories' => 'category_id'],
],
2021-12-27 23:31:32 +01:00
'recurring_expenses',
'number');
return $this;
}
2021-05-31 01:47:14 +02:00
private function import_payment_terms()
{
$this->genericImport(PaymentTerm::class,
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id'],
[['users' => 'user_id']],
'payment_terms',
'num_days');
return $this;
}
/* Cannot use generic as we are matching on two columns for existing data */
private function import_tax_rates()
{
2021-09-18 15:20:16 +02:00
// foreach($this->backup_file->tax_rates as $obj)
foreach((object)$this->getObject("tax_rates") as $obj)
2021-05-31 01:47:14 +02:00
{
$user_id = $this->transformId('users', $obj->user_id);
$obj_array = (array)$obj;
unset($obj_array['user_id']);
unset($obj_array['company_id']);
unset($obj_array['hashed_id']);
unset($obj_array['id']);
unset($obj_array['tax_rate_id']);
$new_obj = TaxRate::firstOrNew(
['name' => $obj->name, 'company_id' => $this->company->id, 'rate' => $obj->rate],
$obj_array,
);
2021-06-07 23:51:21 +02:00
$new_obj->company_id = $this->company->id;
$new_obj->user_id = $user_id;
2021-05-31 01:47:14 +02:00
$new_obj->save(['timestamps' => false]);
}
return $this;
}
private function import_expense_categories()
{
$this->genericImport(ExpenseCategory::class,
['user_id', 'company_id', 'id', 'hashed_id'],
[['users' => 'user_id']],
'expense_categories',
'name');
return $this;
}
private function import_task_statuses()
{
2021-05-31 02:10:19 +02:00
$this->genericImport(TaskStatus::class,
['user_id', 'company_id', 'id', 'hashed_id'],
[['users' => 'user_id']],
'task_statuses',
'name');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_clients()
{
2021-05-31 02:10:19 +02:00
$this->genericImport(Client::class,
2021-09-12 23:45:48 +02:00
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id', 'gateway_tokens', 'contacts', 'documents','country'],
2021-05-31 02:10:19 +02:00
[['users' => 'user_id'], ['users' => 'assigned_user_id']],
'clients',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_client_contacts()
{
2021-05-31 02:10:19 +02:00
$this->genericImport(ClientContact::class,
2021-09-12 23:45:48 +02:00
['user_id', 'company_id', 'id', 'hashed_id','company'],
2021-06-04 12:07:45 +02:00
[['users' => 'user_id'], ['clients' => 'client_id']],
2021-05-31 02:10:19 +02:00
'client_contacts',
'email');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_vendors()
{
2021-05-31 02:10:19 +02:00
$this->genericImport(Vendor::class,
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id'],
[['users' => 'user_id'], ['users' =>'assigned_user_id']],
'vendors',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_vendor_contacts()
{
$this->genericImport(VendorContact::class,
['user_id', 'company_id', 'id', 'hashed_id','company','assigned_user_id'],
[['users' => 'user_id'], ['vendors' => 'vendor_id']],
'vendor_contacts',
'email');
return $this;
}
2021-05-31 01:47:14 +02:00
private function import_projects()
{
2021-05-31 02:10:19 +02:00
$this->genericImport(Project::class,
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id','client_id'],
[['users' => 'user_id'], ['users' =>'assigned_user_id'], ['clients' => 'client_id']],
'projects',
'number');
return $this;
}
private function import_products()
{
$this->genericNewClassImport(Product::class,
['user_id', 'company_id', 'hashed_id', 'id'],
[['users' => 'user_id'], ['users' =>'assigned_user_id'], ['vendors' => 'vendor_id'], ['projects' => 'project_id']],
'products'
);
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_company_gateways()
{
2021-05-31 02:10:19 +02:00
$this->genericNewClassImport(CompanyGateway::class,
['user_id', 'company_id', 'hashed_id', 'id'],
[['users' => 'user_id']],
'company_gateways'
);
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_client_gateway_tokens()
{
2021-05-31 02:10:19 +02:00
$this->genericNewClassImport(ClientGatewayToken::class,
['company_id', 'id', 'hashed_id','client_id'],
[['clients' => 'client_id', 'company_gateways' => 'company_gateway_id']],
2021-05-31 02:10:19 +02:00
'client_gateway_tokens');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_group_settings()
{
2021-05-31 02:10:19 +02:00
$this->genericImport(GroupSetting::class,
['user_id', 'company_id', 'id', 'hashed_id'],
2021-05-31 02:10:19 +02:00
[['users' => 'user_id']],
'group_settings',
'name');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:10:19 +02:00
private function import_subscriptions()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:10:19 +02:00
$this->genericImport(Subscription::class,
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id'],
2021-05-31 02:10:19 +02:00
[['group_settings' => 'group_id'], ['users' => 'user_id'], ['users' => 'assigned_user_id']],
'subscriptions',
'name');
return $this;
}
private function import_recurring_invoices()
{
$this->genericImport(RecurringInvoice::class,
['user_id', 'assigned_user_id', 'company_id', 'id', 'hashed_id', 'client_id','subscription_id','project_id','vendor_id','status'],
[
['subscriptions' => 'subscription_id'],
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['clients' => 'client_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
['clients' => 'client_id'],
],
'recurring_invoices',
'number');
return $this;
}
private function import_recurring_invoice_invitations()
{
$this->genericImport(RecurringInvoiceInvitation::class,
['user_id', 'client_contact_id', 'company_id', 'id', 'hashed_id', 'recurring_invoice_id'],
[
['users' => 'user_id'],
['recurring_invoices' => 'recurring_invoice_id'],
['client_contacts' => 'client_contact_id'],
],
'recurring_invoice_invitations',
'key');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_invoices()
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Invoice::class,
['user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'recurring_id','status'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['recurring_invoices' => 'recurring_id'],
['clients' => 'client_id'],
['subscriptions' => 'subscription_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
],
'invoices',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:10:19 +02:00
private function import_invoice_invitations()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
$this->genericImport(InvoiceInvitation::class,
['user_id', 'client_contact_id', 'company_id', 'id', 'hashed_id', 'invoice_id'],
[
['users' => 'user_id'],
['invoices' => 'invoice_id'],
['client_contacts' => 'client_contact_id'],
],
'invoice_invitations',
'key');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_purchase_orders()
{
$this->genericImport(PurchaseOrder::class,
['user_id', 'company_id', 'id', 'hashed_id', 'recurring_id','status', 'vendor_id', 'subscription_id','client_id'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['recurring_invoices' => 'recurring_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
],
'purchase_orders',
'number');
return $this;
}
private function import_purchase_order_invitations()
{
$this->genericImport(PurchaseOrderInvitation::class,
['user_id', 'vendor_contact_id', 'company_id', 'id', 'hashed_id', 'purchase_order_id'],
[
['users' => 'user_id'],
['purchase_orders' => 'purchase_order_id'],
['vendor_contacts' => 'vendor_contact_id'],
],
'purchase_order_invitations',
'key');
return $this;
}
2021-05-31 01:47:14 +02:00
private function import_quotes()
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Quote::class,
['user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'recurring_id','status'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['recurring_invoices' => 'recurring_id'],
['clients' => 'client_id'],
['subscriptions' => 'subscription_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
],
'quotes',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:10:19 +02:00
private function import_quote_invitations()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
$this->genericImport(QuoteInvitation::class,
['user_id', 'client_contact_id', 'company_id', 'id', 'hashed_id', 'quote_id'],
[
['users' => 'user_id'],
['quotes' => 'quote_id'],
['client_contacts' => 'client_contact_id'],
],
'quote_invitations',
'key');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:10:19 +02:00
private function import_credits()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Credit::class,
['user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'recurring_id','status'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['recurring_invoices' => 'recurring_id'],
['clients' => 'client_id'],
['subscriptions' => 'subscription_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
],
'credits',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:10:19 +02:00
private function import_credit_invitations()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
$this->genericImport(CreditInvitation::class,
['user_id', 'client_contact_id', 'company_id', 'id', 'hashed_id', 'credit_id'],
[
['users' => 'user_id'],
['credits' => 'credit_id'],
['client_contacts' => 'client_contact_id'],
],
'credit_invitations',
'key');
2021-05-31 02:10:19 +02:00
2021-05-31 02:22:30 +02:00
return $this;
}
2021-05-31 02:10:19 +02:00
2021-05-31 01:47:14 +02:00
private function import_expenses()
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Expense::class,
2021-12-27 23:31:32 +01:00
['assigned_user_id', 'user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'project_id','vendor_id','recurring_expense_id'],
2021-05-31 02:22:30 +02:00
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['clients' => 'client_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
2021-09-29 13:11:01 +02:00
['invoices' => 'invoice_id'],
2021-12-27 23:31:32 +01:00
// ['recurring_expenses' => 'recurring_expense_id'],
['expense_categories' => 'category_id'],
2021-05-31 02:22:30 +02:00
],
'expenses',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_tasks()
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Task::class,
['assigned_user_id', 'user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'invoice_id','project_id'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['clients' => 'client_id'],
['projects' => 'project_id'],
['invoices' => 'invoice_id'],
],
'tasks',
'number');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:22:30 +02:00
private function import_payments()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Payment::class,
['assigned_user_id', 'user_id', 'client_id', 'company_id', 'id', 'hashed_id', 'client_contact_id','invitation_id','vendor_id','paymentables'],
[
['users' => 'user_id'],
['users' => 'assigned_user_id'],
['clients' => 'client_id'],
['client_contacts' => 'client_contact_id'],
['vendors' => 'vendor_id'],
['invoice_invitations' => 'invitation_id'],
['company_gateways' => 'company_gateway_id'],
['bank_transactions' => 'transaction_id'],
2021-05-31 02:22:30 +02:00
],
'payments',
'number');
2021-05-31 01:47:14 +02:00
2021-05-31 02:22:30 +02:00
$this->paymentablesImport();
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_activities()
{
2021-05-31 02:22:30 +02:00
$activities = [];
2021-06-04 13:39:35 +02:00
$this->genericNewClassImport(Activity::class,
2021-05-31 02:22:30 +02:00
[
'hashed_id',
'company_id',
2021-10-20 08:16:22 +02:00
'backup',
'invitation_id',
2021-12-20 05:25:40 +01:00
'payment_id',
2021-05-31 02:22:30 +02:00
],
[
['users' => 'user_id'],
['clients' => 'client_id'],
['client_contacts' => 'client_contact_id'],
['projects' => 'project_id'],
['vendors' => 'vendor_id'],
2021-12-20 05:25:40 +01:00
// ['payments' => 'payment_id'],
2021-05-31 02:22:30 +02:00
['invoices' => 'invoice_id'],
['credits' => 'credit_id'],
['tasks' => 'task_id'],
['expenses' => 'expense_id'],
['quotes' => 'quote_id'],
['subscriptions' => 'subscription_id'],
['recurring_invoices' => 'recurring_invoice_id'],
2021-12-31 06:32:22 +01:00
// ['recurring_expenses' => 'recurring_expense_id'],
// ['invitations' => 'invitation_id'],
2021-05-31 02:22:30 +02:00
],
2021-06-04 13:39:35 +02:00
'activities');
2021-05-31 02:22:30 +02:00
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_backups()
{
2021-05-31 02:22:30 +02:00
$this->genericImportWithoutCompany(Backup::class,
2021-06-05 04:42:56 +02:00
['hashed_id','id'],
2021-05-31 02:22:30 +02:00
[
['activities' => 'activity_id'],
],
'backups',
'created_at');
return $this;
}
private function import_company_ledger()
{
$this->genericImport(CompanyLedger::class,
['company_id', 'user_id', 'client_id', 'activity_id', 'id','account_id'],
[
['users' => 'user_id'],
['clients' => 'client_id'],
2021-06-05 04:42:56 +02:00
// ['activities' => 'activity_id'],
2021-05-31 02:22:30 +02:00
],
'company_ledger',
'created_at');
return $this;
2021-05-31 01:47:14 +02:00
2021-05-31 02:22:30 +02:00
}
2021-05-31 01:47:14 +02:00
2021-05-31 02:22:30 +02:00
private function import_designs()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
$this->genericImport(Design::class,
2021-09-01 10:17:29 +02:00
['company_id', 'user_id', 'hashed_id'],
2021-05-31 02:22:30 +02:00
[
['users' => 'user_id'],
],
'designs',
'name');
return $this;
2021-05-31 01:47:14 +02:00
}
2021-05-31 02:22:30 +02:00
private function import_documents()
2021-05-31 01:47:14 +02:00
{
2021-05-31 02:22:30 +02:00
2021-09-18 15:20:16 +02:00
foreach((object)$this->getObject("documents") as $document)
2021-05-31 02:22:30 +02:00
{
$new_document = new Document();
$new_document->user_id = $this->transformId('users', $document->user_id);
$new_document->assigned_user_id = $this->transformId('users', $document->assigned_user_id);
$new_document->company_id = $this->company->id;
$new_document->project_id = $this->transformId('projects', $document->project_id);
$new_document->vendor_id = $this->transformId('vendors', $document->vendor_id);
$new_document->url = $document->url;
$new_document->preview = $document->preview;
$new_document->name = $document->name;
$new_document->type = $document->type;
$new_document->disk = $document->disk;
$new_document->hash = $document->hash;
$new_document->size = $document->size;
$new_document->width = $document->width;
$new_document->height = $document->height;
$new_document->is_default = $document->is_default;
$new_document->custom_value1 = $document->custom_value1;
$new_document->custom_value2 = $document->custom_value2;
$new_document->custom_value3 = $document->custom_value3;
$new_document->custom_value4 = $document->custom_value4;
$new_document->deleted_at = $document->deleted_at;
$new_document->documentable_id = $this->transformDocumentId($document->documentable_id, $document->documentable_type);
$new_document->documentable_type = $document->documentable_type;
$new_document->save(['timestamps' => false]);
2021-05-31 01:47:14 +02:00
$storage_url = (object)$this->getObject('storage_url', true);
2022-11-11 04:52:50 +01:00
if(!Storage::exists($new_document->url) && is_string($storage_url)){
$url = $storage_url . $new_document->url;
$file = @file_get_contents($url);
if($file)
{
try{
Storage::disk(config('filesystems.default'))->put($new_document->url, $file);
}
catch(\Exception $e)
{
nlog($e->getMessage());
nlog("I could not upload {$new_document->url}");
}
}
}
2021-05-31 02:22:30 +02:00
}
return $this;
}
private function import_webhooks()
{
$this->genericImport(Webhook::class,
['company_id', 'user_id'],
[
['users' => 'user_id'],
],
'webhooks',
'created_at');
return $this;
}
private function import_system_logs()
{
return $this;
2021-05-31 01:47:14 +02:00
}
private function import_users()
2021-05-14 07:23:00 +02:00
{
2021-05-15 06:29:19 +02:00
User::unguard();
2021-05-14 07:23:00 +02:00
2021-09-18 15:20:16 +02:00
//foreach ($this->backup_file->users as $user)
foreach((object)$this->getObject("users") as $user)
2021-05-15 06:29:19 +02:00
{
2021-11-07 07:41:02 +01:00
if(User::withTrashed()->where('email', $user->email)->where('account_id', '!=', $this->account->id)->exists())
2021-05-27 07:57:07 +02:00
throw new ImportCompanyFailed("{$user->email} is already in the system attached to a different account");
2021-06-04 12:07:45 +02:00
$user_array = (array)$user;
unset($user_array['laravel_through_key']);
unset($user_array['hashed_id']);
unset($user_array['id']);
/*Make sure we are searching for archived users also and restore if we find them.*/
$new_user = User::withTrashed()->firstOrNew(
2021-05-15 06:29:19 +02:00
['email' => $user->email],
2021-06-04 12:07:45 +02:00
$user_array,
2021-11-07 07:41:02 +01:00
);
2021-05-15 06:29:19 +02:00
$new_user->account_id = $this->account->id;
$new_user->save(['timestamps' => false]);
2021-05-27 07:57:07 +02:00
$this->ids['users']["{$user->hashed_id}"] = $new_user->id;
}
User::reguard();
}
2021-05-31 01:47:14 +02:00
private function import_company_users()
2021-05-27 07:57:07 +02:00
{
CompanyUser::unguard();
2021-09-18 15:20:16 +02:00
// foreach($this->backup_file->company_users as $cu)
foreach((object)$this->getObject("company_users") as $cu)
2021-05-27 07:57:07 +02:00
{
2021-06-04 12:07:45 +02:00
$user_id = $this->transformId('users', $cu->user_id);
$cu_array = (array)$cu;
unset($cu_array['id']);
2021-08-25 08:58:23 +02:00
unset($cu_array['company_id']);
unset($cu_array['user_id']);
2022-05-04 01:29:43 +02:00
unset($cu_array['user']);
unset($cu_array['account']);
// $cu_array['settings'] = json_encode($cu_array['settings']);
// $cu_array['notifications'] = json_encode($cu_array['notifications']);
// $cu_array['permissions'] = json_encode($cu_array['permissions']);
2021-05-27 07:57:07 +02:00
$new_cu = CompanyUser::withTrashed()->firstOrNew(
2022-05-04 01:29:43 +02:00
['user_id' => $user_id, 'company_id' => $this->company->id],
$cu_array,
);
2021-05-27 07:57:07 +02:00
$new_cu->account_id = $this->account->id;
$new_cu->save(['timestamps' => false]);
2021-05-15 06:29:19 +02:00
}
2021-05-27 07:57:07 +02:00
CompanyUser::reguard();
2021-05-15 06:29:19 +02:00
}
2021-05-31 01:47:14 +02:00
private function transformDocumentId($id, $type)
{
switch ($type) {
case Company::class:
return $this->company->id;
break;
case Client::class:
return $this->transformId('clients', $id);
break;
case ClientContact::class:
return $this->transformId('client_contacts', $id);
break;
case Credit::class:
return $this->transformId('credits', $id);
break;
case Expense::class:
return $this->transformId('expenses', $id);
break;
case 'invoices':
return $this->transformId('invoices', $id);
break;
case Payment::class:
return $this->transformId('payments', $id);
break;
case Product::class:
return $this->transformId('products', $id);
break;
case Quote::class:
return $this->transformId('quotes', $id);
break;
case RecurringInvoice::class:
return $this->transformId('recurring_invoices', $id);
break;
case Company::class:
return $this->transformId('clients', $id);
break;
default:
# code...
break;
}
}
private function paymentablesImport()
{
2021-09-18 15:20:16 +02:00
// foreach($this->backup_file->payments as $payment)
foreach((object)$this->getObject("payments") as $payment)
2021-05-31 01:47:14 +02:00
{
foreach($payment->paymentables as $paymentable_obj)
{
$paymentable = new Paymentable();
$paymentable->payment_id = $this->transformId('payments', $paymentable_obj->payment_id);
$paymentable->paymentable_type = $paymentable_obj->paymentable_type;
$paymentable->amount = $paymentable_obj->amount;
$paymentable->refunded = $paymentable_obj->refunded;
$paymentable->created_at = $paymentable_obj->created_at;
$paymentable->deleted_at = $paymentable_obj->deleted_at;
$paymentable->updated_at = $paymentable_obj->updated_at;
$paymentable->paymentable_id = $this->convertPaymentableId($paymentable_obj->paymentable_type, $paymentable_obj->paymentable_id);
$paymentable->paymentable_type = $paymentable_obj->paymentable_type;
$paymentable->save(['timestamps' => false]);
}
}
2021-05-31 02:22:30 +02:00
return $this;
2021-05-31 01:47:14 +02:00
}
private function convertPaymentableId($type, $id)
{
switch ($type) {
case 'invoices':
return $this->transformId('invoices', $id);
break;
case Credit::class:
return $this->transformId('credits', $id);
break;
case Payment::class:
return $this->transformId('payments', $id);
default:
# code...
break;
}
}
private function genericNewClassImport($class, $unset, $transforms, $object_property)
{
$class::unguard();
2021-09-18 15:20:16 +02:00
foreach((object)$this->getObject($object_property) as $obj)
2021-05-31 01:47:14 +02:00
{
/* Remove unwanted keys*/
$obj_array = (array)$obj;
foreach($unset as $un){
unset($obj_array[$un]);
}
2021-08-25 08:58:23 +02:00
if($class instanceof CompanyGateway){
if(Ninja::isHosted() && $obj_array['gateway_key'] == 'd14dd26a37cecc30fdd65700bfb55b23'){
$obj_array['gateway_key'] = 'd14dd26a47cecc30fdd65700bfb67b34';
}
if(Ninja::isSelfHost() && $obj_array['gateway_key'] == 'd14dd26a47cecc30fdd65700bfb67b34'){
$obj_array['gateway_key'] = 'd14dd26a37cecc30fdd65700bfb55b23';
}
}
2021-10-20 08:16:22 +02:00
if(array_key_exists('deleted_at', $obj_array) && $obj_array['deleted_at'] > 1){
$obj_array['deleted_at'] = now();
}
2021-05-31 01:47:14 +02:00
$activity_invitation_key = false;
2021-06-04 13:39:35 +02:00
if($class == 'App\Models\Activity'){
2021-05-31 01:47:14 +02:00
if(isset($obj->invitation_id)){
2021-06-05 04:42:56 +02:00
2021-05-31 01:47:14 +02:00
if(isset($obj->invoice_id))
$activity_invitation_key = 'invoice_invitations';
elseif(isset($obj->quote_id))
$activity_invitation_key = 'quote_invitations';
elseif(isset($obj->credit_id))
2021-05-31 01:47:14 +02:00
$activity_invitation_key = 'credit_invitations';
2021-06-05 04:42:56 +02:00
2021-05-31 01:47:14 +02:00
}
2021-09-18 15:20:16 +02:00
$obj_array['account_id'] = $this->account->id;
2021-05-31 01:47:14 +02:00
}
/* Transform old keys to new keys */
foreach($transforms as $transform)
{
foreach($transform as $key => $value)
{
2021-06-05 04:42:56 +02:00
if($class == 'App\Models\Activity' && $activity_invitation_key && $key == 'invitations'){
2021-05-31 01:47:14 +02:00
$key = $activity_invitation_key;
2021-06-04 13:39:35 +02:00
}
2021-05-31 01:47:14 +02:00
$obj_array["{$value}"] = $this->transformId($key, $obj->{$value});
}
}
2021-06-04 13:39:35 +02:00
if($class == 'App\Models\CompanyGateway') {
2021-05-31 01:47:14 +02:00
$obj_array['config'] = encrypt($obj_array['config']);
}
$new_obj = new $class();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
$this->ids["{$object_property}"]["{$obj->hashed_id}"] = $new_obj->id;
}
$class::reguard();
}
2021-05-15 06:29:19 +02:00
2021-05-31 01:47:14 +02:00
private function genericImportWithoutCompany($class, $unset, $transforms, $object_property, $match_key)
2021-05-15 06:29:19 +02:00
{
2021-05-31 01:47:14 +02:00
$class::unguard();
2021-09-18 15:20:16 +02:00
//foreach($this->backup_file->{$object_property} as $obj)
foreach((object)$this->getObject($object_property) as $obj)
2021-05-31 01:47:14 +02:00
{
2021-06-29 01:35:58 +02:00
if(is_null($obj))
continue;
2021-06-29 02:04:09 +02:00
2021-05-31 01:47:14 +02:00
/* Remove unwanted keys*/
$obj_array = (array)$obj;
foreach($unset as $un){
unset($obj_array[$un]);
}
/* Transform old keys to new keys */
foreach($transforms as $transform)
{
foreach($transform as $key => $value)
{
$obj_array["{$value}"] = $this->transformId($key, $obj->{$value});
}
}
2021-10-20 08:16:22 +02:00
if(array_key_exists('deleted_at', $obj_array) && $obj_array['deleted_at'] > 1){
$obj_array['deleted_at'] = now();
}
2021-05-31 01:47:14 +02:00
/* New to convert product ids from old hashes to new hashes*/
if($class == 'App\Models\Subscription'){
$obj_array['product_ids'] = $this->recordProductIds($obj_array['product_ids']);
$obj_array['recurring_product_ids'] = $this->recordProductIds($obj_array['recurring_product_ids']);
$obj_array['webhook_configuration'] = json_encode($obj_array['webhook_configuration']);
2021-05-31 01:47:14 +02:00
}
$new_obj = $class::firstOrNew(
[$match_key => $obj->{$match_key}],
$obj_array,
);
$new_obj->save(['timestamps' => false]);
if($new_obj instanceof CompanyLedger){
}
else
$this->ids["{$object_property}"]["{$obj->hashed_id}"] = $new_obj->id;
}
$class::reguard();
}
2021-12-31 06:32:22 +01:00
/* Ensure if no number is set, we don't overwrite a record with an existing number */
2021-05-31 01:47:14 +02:00
private function genericImport($class, $unset, $transforms, $object_property, $match_key)
{
$class::unguard();
$x = 0;
2021-12-31 06:32:22 +01:00
2021-09-18 15:20:16 +02:00
foreach((object)$this->getObject($object_property) as $obj)
2021-05-31 01:47:14 +02:00
{
2021-05-31 01:47:14 +02:00
/* Remove unwanted keys*/
$obj_array = (array)$obj;
foreach($unset as $un){
unset($obj_array[$un]);
}
/* Transform old keys to new keys */
foreach($transforms as $transform)
{
foreach($transform as $key => $value)
{
$obj_array["{$value}"] = $this->transformId($key, $obj->{$value});
}
}
2021-10-20 08:16:22 +02:00
if(array_key_exists('deleted_at', $obj_array) && $obj_array['deleted_at'] > 1){
$obj_array['deleted_at'] = now();
}
2021-12-13 08:19:01 +01:00
2021-05-31 01:47:14 +02:00
/* New to convert product ids from old hashes to new hashes*/
if($class == 'App\Models\Subscription'){
2021-12-13 08:19:01 +01:00
if(array_key_exists('company', $obj_array))
unset($obj_array['company']);
$obj_array['webhook_configuration'] = (array)$obj_array['webhook_configuration'];
2021-09-05 06:03:21 +02:00
$obj_array['recurring_product_ids'] = '';
$obj_array['product_ids'] = '';
2021-05-31 01:47:14 +02:00
}
/* Expenses that don't have a number will not be inserted - so need to override here*/
if($class == 'App\Models\Expense' && is_null($obj->{$match_key})){
$new_obj = new Expense();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
2021-12-31 06:32:22 +01:00
$new_obj->number = $this->getNextExpenseNumber($new_obj);
}
elseif($class == 'App\Models\Invoice' && is_null($obj->{$match_key})){
$new_obj = new Invoice();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
2022-06-29 02:38:48 +02:00
$new_obj->number = $this->getNextInvoiceNumber($client = Client::withTrashed()->find($obj_array['client_id']),$new_obj);
}
elseif($class == 'App\Models\PurchaseOrder' && is_null($obj->{$match_key})){
$new_obj = new PurchaseOrder();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
$new_obj->number = $this->getNextPurchaseOrderNumber($new_obj);
}
elseif($class == 'App\Models\Payment' && is_null($obj->{$match_key})){
$new_obj = new Payment();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
2022-06-29 02:38:48 +02:00
$new_obj->number = $this->getNextPaymentNumber($client = Client::withTrashed()->find($obj_array['client_id']), $new_obj);
}
elseif($class == 'App\Models\Quote' && is_null($obj->{$match_key})){
$new_obj = new Quote();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
2022-06-29 02:38:48 +02:00
$new_obj->number = $this->getNextQuoteNumber($client = Client::withTrashed()->find($obj_array['client_id']), $new_obj);
}
2021-10-07 05:33:43 +02:00
elseif($class == 'App\Models\ClientContact'){
$new_obj = new ClientContact();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
}
elseif($class == 'App\Models\VendorContact'){
$new_obj = new VendorContact();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
}
2021-12-27 23:31:32 +01:00
elseif($class == 'App\Models\RecurringExpense' && is_null($obj->{$match_key})){
$new_obj = new RecurringExpense();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
$new_obj->number = $this->getNextRecurringExpenseNumber($new_obj);
2021-12-27 23:31:32 +01:00
}
elseif($class == 'App\Models\Project' && is_null($obj->{$match_key})){
$new_obj = new Project();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
$new_obj->number = $this->getNextProjectNumber($new_obj);
}
elseif($class == 'App\Models\Task' && is_null($obj->{$match_key})){
$new_obj = new Task();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
$new_obj->number = $this->getNextTaskNumber($new_obj);
}
elseif($class == 'App\Models\Vendor' && is_null($obj->{$match_key})){
$new_obj = new Vendor();
$new_obj->company_id = $this->company->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
$new_obj->number = $this->getNextVendorNumber($new_obj);
}
2022-01-26 23:16:45 +01:00
elseif($class == 'App\Models\CompanyLedger'){
$new_obj = $class::firstOrNew(
[$match_key => $obj->{$match_key}, 'company_id' => $this->company->id],
$obj_array,
);
}
elseif($class == 'App\Models\BankIntegration'){
$new_obj = new BankIntegration();
$new_obj->company_id = $this->company->id;
$new_obj->account_id = $this->account->id;
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
}
elseif($class == 'App\Models\BankTransaction'){
$new_obj = new BankTransaction();
$new_obj->company_id = $this->company->id;
$obj_array['invoice_ids'] = collect(explode(",",$obj_array['invoice_ids']))->map(function ($id) {
return $this->transformId('invoices', $id);
})->map(function ($encodeable){
return $this->encodePrimaryKey($encodeable);
})->implode(",");
$new_obj->fill($obj_array);
$new_obj->save(['timestamps' => false]);
}
else{
2021-12-31 06:32:22 +01:00
$new_obj = $class::withTrashed()->firstOrNew(
[$match_key => $obj->{$match_key}, 'company_id' => $this->company->id],
$obj_array,
);
}
2021-05-31 01:47:14 +02:00
$new_obj->save(['timestamps' => false]);
if($new_obj instanceof CompanyLedger){
}
else
$this->ids["{$object_property}"]["{$obj->hashed_id}"] = $new_obj->id;
}
$class::reguard();
}
private function recordProductIds($ids)
{
$id_array = explode(",", $ids);
$tmp_arr = [];
foreach($id_array as $id) {
2021-09-05 06:03:21 +02:00
if(!$id)
continue;
$id = $this->decodePrimaryKey($id);
nlog($id);
2021-05-31 01:47:14 +02:00
$tmp_arr[] = $this->encodePrimaryKey($this->transformId('products', $id));
}
return implode(",", $tmp_arr);
}
/* Transform all IDs from old to new
*
* In the case of users - we need to check if the system
* is attempting to migrate resources above their quota,
*
* ie. > 50 clients or more than 1 user
*/
2021-05-31 01:47:14 +02:00
private function transformId(string $resource, ?string $old): ?int
{
if(empty($old))
return null;
if ($resource == 'users' && $this->force_user_coalesce){
return $this->company_owner->id;
}
2021-05-15 06:29:19 +02:00
if (! array_key_exists($resource, $this->ids)) {
2021-06-29 02:04:09 +02:00
$this->sendImportMail("The Import failed due to missing data in the import file. Resource {$resource} not available.");
2021-05-15 06:29:19 +02:00
throw new \Exception("Resource {$resource} not available.");
}
if (! array_key_exists("{$old}", $this->ids[$resource])) {
2021-06-05 04:42:56 +02:00
// nlog($this->ids[$resource]);
nlog("searching for {$old} in {$resource}");
2021-06-29 01:35:58 +02:00
nlog("If we are missing a user - default to the company owner");
if($resource == 'users')
return $this->company_owner->id;
2021-06-29 02:04:09 +02:00
$this->sendImportMail("The Import failed due to missing data in the import file. Resource {$resource} not available.");
2021-12-20 05:25:40 +01:00
nlog($this->ids[$resource]);
2021-06-29 02:04:09 +02:00
2021-05-31 01:47:14 +02:00
throw new \Exception("Missing {$resource} key: {$old}");
2021-05-15 06:29:19 +02:00
}
return $this->ids[$resource]["{$old}"];
2021-05-14 07:23:00 +02:00
}
2021-05-31 01:47:14 +02:00
2021-06-29 02:04:09 +02:00
private function sendImportMail($message){
App::forgetInstance('translator');
$t = app('translator');
$t->replace(Ninja::transformTranslations($this->company->settings));
2021-06-29 02:04:09 +02:00
$_company = Company::find($this->company->id);
$nmo = new NinjaMailerObject;
$nmo->mailable = new CompanyImportFailure($_company, $message);
$nmo->company = $this->company;
$nmo->settings = $this->company->settings;
$nmo->to_user = $this->company->owner();
2022-09-07 06:15:27 +02:00
NinjaMailerJob::dispatch($nmo);
2021-06-29 02:04:09 +02:00
}
2021-05-14 07:23:00 +02:00
}