diff --git a/VERSION.txt b/VERSION.txt index 9d5d131a1f..b24ea85a7d 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.1.72 \ No newline at end of file +5.1.74 \ No newline at end of file diff --git a/app/Console/Commands/CheckDb.php b/app/Console/Commands/CheckDb.php new file mode 100644 index 0000000000..198a391f6e --- /dev/null +++ b/app/Console/Commands/CheckDb.php @@ -0,0 +1,166 @@ +entities as $entity) { + + $this->LogMessage("V5_DB1"); + + $count_db_1 = $entity::on('db-ninja-01')->count(); + $count_db_2 = $entity::on('db-ninja-02a')->count(); + + $diff = $count_db_1 - $count_db_2; + + if($diff != 0) + $this->logMessage("{$entity} DB1: {$count_db_1} - DB2: {$count_db_2} - diff = {$diff}"); + + } + + + foreach($this->entities as $entity) { + + $this->LogMessage("V5_DB2"); + + $count_db_1 = $entity::on('db-ninja-02')->count(); + $count_db_2 = $entity::on('db-ninja-01a')->count(); + + $diff = $count_db_1 - $count_db_2; + + if($diff != 0) + $this->logMessage("{$entity} DB1: {$count_db_1} - DB2: {$count_db_2} - diff = {$diff}"); + + } + } + + private function logMessage($str) + { + $str = date('Y-m-d h:i:s').' '.$str; + $this->info($str); + $this->log .= $str."\n"; + } + +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d519874bc6..f84fc6808c 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -75,7 +75,7 @@ class Kernel extends ConsoleKernel } - if(config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled')) { + if(config('queue.default') == 'database' && Ninja::isSelfHost() && config('ninja.internal_queue_enabled') && !config('ninja.is_docker')) { $schedule->command('queue:work')->everyMinute()->withoutOverlapping(); $schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping(); diff --git a/app/Jobs/Company/CompanyImport.php b/app/Jobs/Company/CompanyImport.php index 551670419c..3c010945c3 100644 --- a/app/Jobs/Company/CompanyImport.php +++ b/app/Jobs/Company/CompanyImport.php @@ -93,6 +93,10 @@ class CompanyImport implements ShouldQueue public $pre_flight_checks_pass = true; + public $force_user_coalesce = false; + + public $company_owner; + private $importables = [ // 'company', 'users', @@ -141,6 +145,7 @@ class CompanyImport implements ShouldQueue public function __construct(Company $company, User $user, string $hash, array $request_array) { $this->company = $company; + $this->user = $user; $this->hash = $hash; $this->request_array = $request_array; $this->current_app_version = config('ninja.app_version'); @@ -152,6 +157,7 @@ class CompanyImport implements ShouldQueue $this->company = Company::where('company_key', $this->company->company_key)->firstOrFail(); $this->account = $this->company->account; + $this->company_owner = $this->company->owner(); nlog("Company ID = {$this->company->id}"); nlog("Hash ID = {$this->hash}"); @@ -164,17 +170,18 @@ class CompanyImport implements ShouldQueue $this->backup_file = json_decode(base64_decode($this->backup_file)); // nlog($this->backup_file); + $this->checkUserCount(); if(array_key_exists('import_settings', $this->request_array) && $this->request_array['import_settings'] == 'true') { - $this->checkUserCount()->preFlightChecks()->importSettings(); + + $this->preFlightChecks()->importSettings(); } if(array_key_exists('import_data', $this->request_array) && $this->request_array['import_data'] == 'true') { try{ - $this->checkUserCount() - ->preFlightChecks() + $this->preFlightChecks() ->purgeCompanyData() ->importData(); @@ -206,23 +213,21 @@ class CompanyImport implements ShouldQueue $company_users = $this->company->users; - $company_owner = $this->company->owner(); - - if($this->company->account->isFreeHostedClient()){ - nlog("This is a free account"); nlog("Backup user count = ".count($backup_users)); if(count($backup_users) > 1){ - $this->message = 'Only one user can be in the import for a Free Account'; - $this->pre_flight_checks_pass = false; + // $this->message = 'Only one user can be in the import for a Free Account'; + // $this->pre_flight_checks_pass = false; + $this->force_user_coalesce = true; } nlog("backup users email = " . $backup_users[0]->email); - if(count($backup_users) == 1 && $company_owner->email != $backup_users[0]->email) { - $this->message = 'Account emails do not match. Account owner email must match backup user email'; - $this->pre_flight_checks_pass = false; + if(count($backup_users) == 1 && $this->company_owner->email != $backup_users[0]->email) { + // $this->message = 'Account emails do not match. Account owner email must match backup user email'; + // $this->pre_flight_checks_pass = false; + $this->force_user_coalesce = true; } $backup_users_emails = array_column($backup_users, 'email'); @@ -236,8 +241,9 @@ class CompanyImport implements ShouldQueue if($existing_user_count > 1){ if($this->account->plan == 'pro'){ - $this->message = 'Pro plan is limited to one user, you have multiple users in the backup file'; - $this->pre_flight_checks_pass = false; + // $this->message = 'Pro plan is limited to one user, you have multiple users in the backup file'; + // $this->pre_flight_checks_pass = false; + $this->force_user_coalesce = true; } if($this->account->plan == 'enterprise'){ @@ -268,11 +274,6 @@ class CompanyImport implements ShouldQueue } - } - - nlog($this->message); - nlog($this->pre_flight_checks_pass); - return $this; } @@ -1217,11 +1218,22 @@ class CompanyImport implements ShouldQueue 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 + */ 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; + } + if (! array_key_exists($resource, $this->ids)) { // nlog($this->ids); throw new \Exception("Resource {$resource} not available."); diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index 8cd498fa72..5b722eb194 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -212,7 +212,7 @@ class Import implements ShouldQueue } // if(Ninja::isHosted() && array_key_exists('ninja_tokens', $data)) - // $this->processNinjaTokens($data['ninja_tokens']); + $this->processNinjaTokens($data['ninja_tokens']); $this->setInitialCompanyLedgerBalances(); @@ -1659,8 +1659,10 @@ class Import implements ShouldQueue private function processNinjaTokens(array $data) { + nlog("attempting to process Ninja Tokens"); + if(Ninja::isHosted()) - \Modules\Admin\Jobs\Account\NinjaUser::dispatch($data, $this->company); + \Modules\Admin\Jobs\Account\NinjaUser::dispatchNow($data, $this->company); } diff --git a/app/PaymentDrivers/PayPalExpressPaymentDriver.php b/app/PaymentDrivers/PayPalExpressPaymentDriver.php index e007ebaaf5..0212787fd9 100644 --- a/app/PaymentDrivers/PayPalExpressPaymentDriver.php +++ b/app/PaymentDrivers/PayPalExpressPaymentDriver.php @@ -98,7 +98,7 @@ class PayPalExpressPaymentDriver extends BaseDriver $message = [ 'server_response' => $response->getMessage(), - 'data' => $this->checkout->payment_hash->data, + 'data' => $this->payment_hash->data, ]; SystemLogger::dispatch( diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index c3b283c4e5..b2c30fcc08 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -630,7 +630,7 @@ class SubscriptionService */ public function triggerWebhook($context) { - if (empty($this->subscription->webhook_configuration['post_purchase_url']) || empty($this->subscription->webhook_configuration['post_purchase_rest_method'])) { + if (empty($this->subscription->webhook_configuration['post_purchase_url']) || is_null($this->subscription->webhook_configuration['post_purchase_url']) || strlen($this->subscription->webhook_configuration['post_purchase_url']) < 1) { return ["message" => "Success", "status_code" => 200]; } diff --git a/config/database.php b/config/database.php index c516de1eee..0e9e4b7692 100644 --- a/config/database.php +++ b/config/database.php @@ -99,6 +99,24 @@ return [ // ), ], + 'db-ninja-01a' => [ + 'driver' => 'mysql', + 'host' => env('DB_HOST1', env('DB_HOST', '127.0.0.1')), + 'database' => env('DB_DATABASE2', env('DB_DATABASE', 'forge')), + 'username' => env('DB_USERNAME2', env('DB_USERNAME', 'forge')), + 'password' => env('DB_PASSWORD2', env('DB_PASSWORD', '')), + 'port' => env('DB_PORT1', env('DB_PORT', '3306')), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => env('DB_STRICT', false), + 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', + // 'options' => array( + // PDO::ATTR_EMULATE_PREPARES => true + // ), + ], + 'db-ninja-02' => [ 'driver' => 'mysql', 'host' => env('DB_HOST2', env('DB_HOST', '127.0.0.1')), @@ -116,6 +134,24 @@ return [ // PDO::ATTR_EMULATE_PREPARES => true // ), ], + + 'db-ninja-02a' => [ + 'driver' => 'mysql', + 'host' => env('DB_HOST2', env('DB_HOST', '127.0.0.1')), + 'database' => env('DB_DATABASE1', env('DB_DATABASE', 'forge')), + 'username' => env('DB_USERNAME1', env('DB_USERNAME', 'forge')), + 'password' => env('DB_PASSWORD1', env('DB_PASSWORD', '')), + 'port' => env('DB_PORT2', env('DB_PORT', '3306')), + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => env('DB_STRICT', false), + 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', + // 'options' => array( + // PDO::ATTR_EMULATE_PREPARES => true + // ), + ], ], /* diff --git a/config/ninja.php b/config/ninja.php index 4579e046aa..87c25c632b 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -14,8 +14,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => '5.1.72', - 'app_tag' => '5.1.72-release', + 'app_version' => '5.1.74', + 'app_tag' => '5.1.74-release', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''),