diff --git a/.gitignore b/.gitignore index e49b5983d393..cb976c37b93f 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ yarn-error.log .env.dusk.local /public/vendors/* public/mix-manifest.json +*.log \ No newline at end of file diff --git a/app/Console/Commands/CreateTestData.php b/app/Console/Commands/CreateTestData.php index 9c4913102102..167e22548423 100644 --- a/app/Console/Commands/CreateTestData.php +++ b/app/Console/Commands/CreateTestData.php @@ -119,8 +119,10 @@ class CreateTestData extends Command private function createClient($company, $user) { - $client = ClientFactory::create($company->id, $user->id); - $client->save(); + $client = factory(\App\Models\Client::class)->create([ + 'user_id' => $user->id, + 'company_id' => $company->id + ]); factory(\App\Models\ClientContact::class,1)->create([ diff --git a/app/Events/Invoice/InvoiceWasPaid.php b/app/Events/Invoice/InvoiceWasPaid.php new file mode 100644 index 000000000000..61904c95538e --- /dev/null +++ b/app/Events/Invoice/InvoiceWasPaid.php @@ -0,0 +1,38 @@ +invoice = $invoice; + } +} diff --git a/app/Http/Controllers/MigrationController.php b/app/Http/Controllers/MigrationController.php new file mode 100644 index 000000000000..f47f43349b9c --- /dev/null +++ b/app/Http/Controllers/MigrationController.php @@ -0,0 +1,144 @@ +delete(); + + return response()->json(['message'=>'Company purged'], 200); + } + + + + /** + * + * Purge Company but save settings + * + * @OA\Post( + * path="/api/v1/migration/purge_save_settings/{company}", + * operationId="postPurgeCompanySaveSettings", + * tags={"migration"}, + * summary="Attempts to purge a companies child records but save the company record and its settings", + * description="Attempts to purge a companies child records but save the company record and its settings", + * @OA\Parameter(ref="#/components/parameters/X-Api-Secret"), + * @OA\Parameter(ref="#/components/parameters/X-Api-Token"), + * @OA\Parameter(ref="#/components/parameters/X-Requested-With"), + * @OA\Parameter( + * name="company", + * in="path", + * description="The Company Hashed ID", + * example="D2J234DFA", + * required=true, + * @OA\Schema( + * type="string", + * format="string", + * ), + * ), + * @OA\Response( + * response=200, + * description="Success", + * @OA\Header(header="X-API-Version", ref="#/components/headers/X-API-Version"), + * @OA\Header(header="X-RateLimit-Remaining", ref="#/components/headers/X-RateLimit-Remaining"), + * @OA\Header(header="X-RateLimit-Limit", ref="#/components/headers/X-RateLimit-Limit"), + * ), + * @OA\Response( + * response=422, + * description="Validation error", + * @OA\JsonContent(ref="#/components/schemas/ValidationError"), + + * ), + * @OA\Response( + * response="default", + * description="Unexpected Error", + * @OA\JsonContent(ref="#/components/schemas/Error"), + * ), + * ) + */ + public function purgeCompanySaveSettings(Company $company) + { + $company->client->delete() + $company->save() + + return response()->json(['message'=>'Setting preserved'], 200); + + } + + +} diff --git a/app/Jobs/Client/UpdateClientPaidToDate.php b/app/Jobs/Client/UpdateClientPaidToDate.php new file mode 100644 index 000000000000..d833d293ce9f --- /dev/null +++ b/app/Jobs/Client/UpdateClientPaidToDate.php @@ -0,0 +1,50 @@ +amount = $amount; + $this->client = $client; + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + + $this->client->paid_to_date += $this->amount; + $this->client->save(); + + } +} diff --git a/app/Jobs/Invoice/ApplyPaymentToInvoice.php b/app/Jobs/Invoice/ApplyPaymentToInvoice.php index 7a791bb9ec26..f4133ac5f702 100644 --- a/app/Jobs/Invoice/ApplyPaymentToInvoice.php +++ b/app/Jobs/Invoice/ApplyPaymentToInvoice.php @@ -11,6 +11,7 @@ namespace App\Jobs\Invoice; +use App\Events\Invoice\InvoiceWasPaid; use App\Jobs\Invoice\ApplyInvoiceNumber; use App\Models\Invoice; use App\Models\Payment; @@ -95,8 +96,11 @@ class ApplyPaymentToInvoice implements ShouldQueue $this->invoice->balance = $this->invoice->balance + $adjustment; /* Update Invoice Status */ - if($this->invoice->balance == 0) + if($this->invoice->balance == 0){ $this->invoice->status_id = Invoice::STATUS_PAID; + $this->invoice->save(); + event(new InvoiceWasPaid($this->invoice)); + } elseif($this->payment->amount > 0 && $this->invoice->balance > 0) $this->invoice->status_id = Invoice::STATUS_PARTIAL; diff --git a/app/Jobs/Invoice/CreateInvoicePdf.php b/app/Jobs/Invoice/CreateInvoicePdf.php index 7e5aa960e6f0..c19a0967b9b0 100644 --- a/app/Jobs/Invoice/CreateInvoicePdf.php +++ b/app/Jobs/Invoice/CreateInvoicePdf.php @@ -16,13 +16,13 @@ use App\Models\Payment; use App\Models\PaymentTerm; use App\Repositories\InvoiceRepository; use App\Utils\Traits\NumberFormatter; +use App\Utils\Traits\MakesInvoiceHtml; 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\Carbon; -use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Storage; use Spatie\Browsershot\Browsershot; @@ -30,7 +30,7 @@ use Symfony\Component\Debug\Exception\FatalThrowableError; class CreateInvoicePdf implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter; + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, NumberFormatter, MakesInvoiceHtml; public $invoice; @@ -89,67 +89,5 @@ class CreateInvoicePdf implements ShouldQueue //->savePdf('test.pdf'); } - /** - * Generate the HTML invoice parsing variables - * and generating the final invoice HTML - * - * @param string $design either the path to the design template, OR the full design template string - * @param Collection $invoice The invoice object - * - * @return string The invoice string in HTML format - */ - private function generateInvoiceHtml($design, $invoice) :string - { - $variables = array_merge($invoice->makeLabels(), $invoice->makeValues()); - $design = str_replace(array_keys($variables), array_values($variables), $design); - - $data['invoice'] = $invoice; - - return $this->renderView($design, $data); - - //return view($design, $data)->render(); - - } - - /** - * Parses the blade file string and processes the template variables - * - * @param string $string The Blade file string - * @param array $data The array of template variables - * @return string The return HTML string - * - */ - private function renderView($string, $data) :string - { - if (!$data) { - $data = []; - } - - $data['__env'] = app(\Illuminate\View\Factory::class); - - $php = Blade::compileString($string); - - $obLevel = ob_get_level(); - ob_start(); - extract($data, EXTR_SKIP); - - try { - eval('?' . '>' . $php); - } catch (\Exception $e) { - while (ob_get_level() > $obLevel) { - ob_end_clean(); - } - - throw $e; - } catch (\Throwable $e) { - while (ob_get_level() > $obLevel) { - ob_end_clean(); - } - - throw new FatalThrowableError($e); - } - - return ob_get_clean(); - } } diff --git a/app/Jobs/Invoice/MarkInvoicePaid.php b/app/Jobs/Invoice/MarkInvoicePaid.php index daf7c08c890d..70db6138b485 100644 --- a/app/Jobs/Invoice/MarkInvoicePaid.php +++ b/app/Jobs/Invoice/MarkInvoicePaid.php @@ -72,8 +72,8 @@ class MarkInvoicePaid implements ShouldQueue event(new PaymentWasCreated($payment)); UpdateCompanyLedgerWithPayment::dispatchNow($payment, ($payment->amount*-1)); - UpdateClientBalance::dispatchNow($payment->client, $this->payment->amount*-1); - UpdateClientPaidToDate::dispatchNow($payment->client, $this->payment->amount); + UpdateClientBalance::dispatchNow($payment->client, $payment->amount*-1); + UpdateClientPaidToDate::dispatchNow($payment->client, $payment->amount); return $this->invoice; } diff --git a/app/Listeners/Invoice/CreateInvoiceHtmlBackup.php b/app/Listeners/Invoice/CreateInvoiceHtmlBackup.php new file mode 100644 index 000000000000..4e374bdaef76 --- /dev/null +++ b/app/Listeners/Invoice/CreateInvoiceHtmlBackup.php @@ -0,0 +1,50 @@ +activity_repo = $activity_repo; + } + + /** + * Handle the event. + * + * @param object $event + * @return void + */ + public function handle($event) + { + + $fields = new \stdClass; + + $fields->invoice_id = $event->invoice->id; + $fields->user_id = $event->invoice->user_id; + $fields->company_id = $event->invoice->company_id; + $fields->activity_type_id = Activity::MARK_SENT_INVOICE; + + $this->activity_repo->save($fields, $event->invoice); + } +} diff --git a/app/Listeners/Invoice/UpdateInvoiceInvitations.php b/app/Listeners/Invoice/UpdateInvoiceInvitations.php index 9f801a07e9f1..f97cd39ee12c 100644 --- a/app/Listeners/Invoice/UpdateInvoiceInvitations.php +++ b/app/Listeners/Invoice/UpdateInvoiceInvitations.php @@ -45,8 +45,6 @@ class UpdateInvoiceInvitations implements ShouldQueue */ $invoices->each(function ($invoice) use($payment) { - $invoice->status_id = Invoice::STATUS_PAID; - $invoice->save(); $invoice->invitations()->update(['transaction_reference' => $payment->transaction_reference]); }); diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 6259804c1d43..d18cd4ca8c80 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -67,7 +67,9 @@ class Activity extends StaticModel const ARCHIVE_USER=50; const DELETE_USER=51; const RESTORE_USER=52; - + const MARK_SENT_INVOICE=53; + const PAID_INVOICE=54; + protected $casts = [ 'is_system' => 'boolean', 'updated_at' => 'timestamp', diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index e5a8ddfbebb4..c8a525edeaae 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -23,7 +23,6 @@ class CompanyUser extends Pivot * @var array */ protected $casts = [ - 'settings' => 'object', 'permissions' => 'object', 'updated_at' => 'timestamp', 'created_at' => 'timestamp', diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 3fc46992aa84..d03e8e28aed1 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -11,6 +11,8 @@ namespace App\Models; +use App\Events\Invoice\InvoiceWasMarkedSent; +use App\Events\Invoice\InvoiceWasPaid; use App\Events\Invoice\InvoiceWasUpdated; use App\Helpers\Invoice\InvoiceSum; use App\Helpers\Invoice\InvoiceSumInclusive; @@ -370,8 +372,13 @@ class Invoice extends BaseModel $this->balance = $this->balance + $balance_adjustment; - if($this->balance == 0) + if($this->balance == 0) { $this->status_id = self::STATUS_PAID; + $this->save(); + event(new InvoiceWasPaid($this)); + + return; + } $this->save(); } @@ -399,6 +406,8 @@ class Invoice extends BaseModel $this->markInvitationsSent(); + event(new InvoiceWasMarkedSent($this)); + UpdateClientBalance::dispatchNow($this->client, $this->balance); $this->save(); diff --git a/app/Models/User.php b/app/Models/User.php index f744055d8081..00ba47d07b27 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -327,7 +327,11 @@ class User extends Authenticatable implements MustVerifyEmail public function hasPermission($permission) : bool { - return $this->permissionsFlat()->contains($permission); + + return (stripos($this->user_company()->permissions, $permission) !== false); + + + // return $this->permissionsFlat()->contains($permission); } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index b89f58773e25..0e7f4e0ebb4e 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -15,6 +15,7 @@ use App\Events\Client\ClientWasCreated; use App\Events\Contact\ContactLoggedIn; use App\Events\Invoice\InvoiceWasCreated; use App\Events\Invoice\InvoiceWasMarkedSent; +use App\Events\Invoice\InvoiceWasPaid; use App\Events\Invoice\InvoiceWasUpdated; use App\Events\Payment\PaymentWasCreated; use App\Events\Payment\PaymentWasDeleted; @@ -25,6 +26,7 @@ use App\Listeners\Activity\PaymentCreatedActivity; use App\Listeners\Activity\PaymentDeletedActivity; use App\Listeners\Contact\UpdateContactLastLogin; use App\Listeners\Invoice\CreateInvoiceActivity; +use App\Listeners\Invoice\CreateInvoiceHtmlBackup; use App\Listeners\Invoice\CreateInvoiceInvitation; use App\Listeners\Invoice\CreateInvoicePdf; use App\Listeners\Invoice\UpdateInvoiceActivity; @@ -59,10 +61,10 @@ class EventServiceProvider extends ServiceProvider PaymentWasCreated::class => [ PaymentCreatedActivity::class, //UpdateInvoicePayment::class, - UpdateInvoiceInvitations::class, + //UpdateInvoiceInvitations::class, ], PaymentWasDeleted::class => [ - PaymentDeletedActivity::class + PaymentDeletedActivity::class, ], 'App\Events\ClientWasArchived' => [ 'App\Listeners\ActivityListener@archivedClient', @@ -82,7 +84,7 @@ class EventServiceProvider extends ServiceProvider //Invoices InvoiceWasMarkedSent::class => [ - CreateInvoiceInvitation::class, + CreateInvoiceHtmlBackup::class, ], InvoiceWasUpdated::class => [ UpdateInvoiceActivity::class, @@ -92,6 +94,9 @@ class EventServiceProvider extends ServiceProvider CreateInvoiceActivity::class, CreateInvoicePdf::class, ], + InvoiceWasPaid::class => [ + CreateInvoiceHtmlBackup::class, + ] ]; /** diff --git a/app/Repositories/ActivityRepository.php b/app/Repositories/ActivityRepository.php index 7d8230dad73b..3a0ef9b2688d 100644 --- a/app/Repositories/ActivityRepository.php +++ b/app/Repositories/ActivityRepository.php @@ -14,6 +14,8 @@ namespace App\Repositories; use App\Models\Activity; use App\Models\Backup; use App\Models\Client; +use App\Models\Invoice; +use App\Utils\Traits\MakesInvoiceHtml; use Illuminate\Support\Facades\Log; /** @@ -21,7 +23,7 @@ use Illuminate\Support\Facades\Log; */ class ActivityRepository extends BaseRepository { - + use MakesInvoiceHtml; /** * Save the Activity * @@ -66,6 +68,11 @@ class ActivityRepository extends BaseRepository else $entity->load('company','client'); + + if(get_class($entity) == Invoice::class && ($activity->activity_type_id == Activity::MARK_SENT_INVOICE || $activity->activity_type_id == Activity::PAID_INVOICE)) + $backup->html_backup = $this->generateInvoiceHtml($entity->design(), $entity); + + $backup->activity_id = $activity->id; $backup->json_backup = $entity->toJson(); $backup->save(); diff --git a/app/Utils/Traits/GeneratesCounter.php b/app/Utils/Traits/GeneratesCounter.php index 379ccb46924f..e3f75dc01496 100644 --- a/app/Utils/Traits/GeneratesCounter.php +++ b/app/Utils/Traits/GeneratesCounter.php @@ -18,7 +18,6 @@ use App\Models\Quote; use App\Models\RecurringInvoice; use App\Models\Timezone; use Illuminate\Support\Carbon; -use Illuminate\Support\Facades\Log; /** * Class GeneratesCounter @@ -43,7 +42,6 @@ trait GeneratesCounter //todo handle if we have specific client patterns in the future $pattern = $client->getSetting('invoice_number_pattern'); - //Determine if we are using client_counters if(strpos($pattern, 'clientCounter')) { @@ -65,10 +63,12 @@ trait GeneratesCounter $pattern = $client->getSetting('invoice_number_pattern'); $prefix = $client->getSetting('invoice_number_prefix'); $padding = $client->getSetting('counter_padding'); + $invoice_number = $this->checkEntityNumber(Invoice::class, $client, $counter, $padding, $prefix, $pattern); $this->incrementCounter($counter_entity, 'invoice_number_counter'); + return $invoice_number; } @@ -173,7 +173,7 @@ trait GeneratesCounter public function hasSharedCounter(Client $client) : bool { - return $client->getSettingsByKey('shared_invoice_quote_counter') === TRUE; + return $client->getSetting('shared_invoice_quote_counter') === TRUE; } @@ -213,6 +213,7 @@ trait GeneratesCounter } while ($check); + return $number; } @@ -235,6 +236,7 @@ trait GeneratesCounter private function prefixCounter($counter, $prefix) : string { + if(strlen($prefix) == 0) return $counter; @@ -330,6 +332,7 @@ trait GeneratesCounter */ private function applyNumberPattern(Client $client, string $counter, $pattern) :string { + if(!$pattern) return $counter; diff --git a/app/Utils/Traits/MakesInvoiceHtml.php b/app/Utils/Traits/MakesInvoiceHtml.php new file mode 100644 index 000000000000..5d7c8d493425 --- /dev/null +++ b/app/Utils/Traits/MakesInvoiceHtml.php @@ -0,0 +1,88 @@ +makeLabels(), $invoice->makeValues()); + $design = str_replace(array_keys($variables), array_values($variables), $design); + + $data['invoice'] = $invoice; + + return $this->renderView($design, $data); + + //return view($design, $data)->render(); + + } + + /** + * Parses the blade file string and processes the template variables + * + * @param string $string The Blade file string + * @param array $data The array of template variables + * @return string The return HTML string + * + */ + public function renderView($string, $data) :string + { + if (!$data) { + $data = []; + } + + $data['__env'] = app(\Illuminate\View\Factory::class); + + $php = Blade::compileString($string); + + $obLevel = ob_get_level(); + ob_start(); + extract($data, EXTR_SKIP); + + try { + eval('?' . '>' . $php); + } catch (\Exception $e) { + while (ob_get_level() > $obLevel) { + ob_end_clean(); + } + + throw $e; + } catch (\Throwable $e) { + while (ob_get_level() > $obLevel) { + ob_end_clean(); + } + + throw new FatalThrowableError($e); + } + + return ob_get_clean(); + } + +} \ No newline at end of file diff --git a/config/database.php b/config/database.php index 62465f38115e..d5dc85dbc2aa 100644 --- a/config/database.php +++ b/config/database.php @@ -41,11 +41,11 @@ return [ 'username' => env('DB_USERNAME1', 'forge'), 'password' => env('DB_PASSWORD1', ''), 'port' => env('DB_PORT1', '3306'), - 'charset' => 'utf8', - 'collation' => 'utf8_unicode_ci', + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', 'prefix' => '', 'strict' => env('DB_STRICT', false), - 'engine' => 'InnoDB', + 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', ], 'sqlite' => [ @@ -92,7 +92,7 @@ return [ 'prefix' => '', 'prefix_indexes' => true, 'strict' => env('DB_STRICT', false), - 'engine' => 'InnoDB', + 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', ], 'db-ninja-02' => [ @@ -107,7 +107,7 @@ return [ 'prefix' => '', 'prefix_indexes' => true, 'strict' => env('DB_STRICT', false), - 'engine' => 'InnoDB', + 'engine' => 'InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8', ], ], diff --git a/database/migrations/2014_10_13_000000_create_users_table.php b/database/migrations/2014_10_13_000000_create_users_table.php index 392394e56f15..f9f10a069d1b 100644 --- a/database/migrations/2014_10_13_000000_create_users_table.php +++ b/database/migrations/2014_10_13_000000_create_users_table.php @@ -15,6 +15,9 @@ class CreateUsersTable extends Migration public function up() { + DB::raw("SET GLOBAL innodb_file_per_table=1;"); + DB::raw("SET GLOBAL innodb_file_format=Barracuda;"); + Schema::create('languages', function ($table) { $table->increments('id'); $table->string('name'); @@ -179,7 +182,7 @@ class CreateUsersTable extends Migration }); - DB::statement('ALTER table companies key_block_size=8 row_format=compressed'); + //DB::statement('ALTER table companies key_block_size=8 row_format=compressed'); Schema::create('company_user', function (Blueprint $table) { @@ -195,6 +198,7 @@ class CreateUsersTable extends Migration $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->index(['account_id', 'company_id']); @@ -255,8 +259,7 @@ class CreateUsersTable extends Migration $table->unique(['oauth_user_id', 'oauth_provider_id']); - - // $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); + $table->foreign('user_id')->references('user_id')->on('company_users')->onDelete('cascade'); }); @@ -364,7 +367,6 @@ class CreateUsersTable extends Migration $table->timestamps(6); $table->softDeletes('deleted_at', 6); - $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); $table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); //$table->unique(['company_id', 'email']); }); @@ -755,7 +757,7 @@ class CreateUsersTable extends Migration $t->foreign('client_contact_id')->references('id')->on('client_contacts')->onDelete('cascade'); $t->foreign('company_gateway_id')->references('id')->on('company_gateways')->onDelete('cascade'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - ; + $t->foreign('payment_type_id')->references('id')->on('payment_types'); }); @@ -766,6 +768,9 @@ class CreateUsersTable extends Migration $table->unsignedInteger('paymentable_id'); $table->decimal('amount', 16, 4)->default(0); $table->string('paymentable_type'); + + $table->foreign('payment_id')->references('id')->on('payments')->onDelete('cascade'); + }); Schema::create('payment_libraries', function ($t) { @@ -896,7 +901,8 @@ class CreateUsersTable extends Migration Schema::create('backups', function ($table) { $table->increments('id'); $table->unsignedInteger('activity_id'); - $table->mediumText('json_backup')->nullable(); + $table->longText('json_backup')->nullable(); + $table->longText('html_backup')->nullable(); $table->timestamps(6); $table->foreign('activity_id')->references('id')->on('activities')->onDelete('cascade'); diff --git a/routes/api.php b/routes/api.php index a172749c0774..668a4bd443c7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -73,6 +73,9 @@ Route::group(['middleware' => ['api_db','api_secret_check','token_auth'], 'prefi Route::post('users/bulk', 'UserController@bulk')->name('users.bulk')->middleware('password_protected'); + Route::post('migration/purge/{company}', 'MigrationController@purgeCompany'); + Route::post('migration/purge_save_settings/{company}', 'MigrationController@purgeCompanySaveSettings'); + Route::resource('companies', 'CompanyController'); // name = (companies. index / create / show / update / destroy / edit Route::resource('company_gateways', 'CompanyGatewayController'); diff --git a/tests/Feature/MigrationTest.php b/tests/Feature/MigrationTest.php new file mode 100644 index 000000000000..2179e0954715 --- /dev/null +++ b/tests/Feature/MigrationTest.php @@ -0,0 +1,96 @@ +faker = \Faker\Factory::create(); + + Model::reguard(); + + $this->makeTestData(); + } + + + public function testCompanyExists() + { + + $co = Company::find($this->company->id); + + // $this->assertNull($this->company); + $this->assertNotNull($co); + } + + public function testThatCompanyDeletesCompletely() + { + $company_id = $this->company->id; + + $this->company->delete(); + $this->company->fresh(); + + $co = Company::find($company_id); + + // $this->assertNull($this->company); + $this->assertNull($co); + + } + + public function testCompanyChildDeletes() + { + + $this->makeTestData(); + + $this->assertNotNull($this->company); + + $co = Client::whereCompanyId($this->company->id)->get(); + $inv = Invoice::whereCompanyId($this->company->id)->get(); + + $this->assertEquals($co->count(),1); + $this->assertEquals($inv->count(),1); + + DB::statement( 'DELETE FROM `clients` WHERE `company_id`=:company_id', array('company_id' => $this->company->id) ); + + $co = Client::whereCompanyId($this->company->id)->get(); + $inv = Invoice::whereCompanyId($this->company->id)->get(); + + $this->assertEquals($co->count(),0); + $this->assertEquals($inv->count(),0); + + $this->assertNotNull($this->company); + $this->assertNotNull($this->company->settings); + $this->assertNotNull($this->company->settings->timezone_id); + + } +} \ No newline at end of file diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index 853241e56fe4..c44fbaa24c6f 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -28,6 +28,7 @@ use App\Models\GroupSetting; use App\Models\Invoice; use App\Models\Quote; use App\Models\RecurringInvoice; +use App\Models\User; use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; use Illuminate\Support\Carbon; @@ -93,11 +94,15 @@ trait MockAccountData $this->account->default_company_id = $this->company->id; $this->account->save(); - $this->user = factory(\App\Models\User::class)->create([ - // 'account_id' => $account->id, - 'confirmation_code' => $this->createDbHash(config('database.default')) - ]); + $this->user = User::whereEmail('user@example.com')->first(); + if(!$this->user){ + $this->user = factory(\App\Models\User::class)->create([ + // 'account_id' => $account->id, + 'confirmation_code' => $this->createDbHash(config('database.default')) + ]); + } + $this->token = \Illuminate\Support\Str::random(64); $company_token = CompanyToken::create([ diff --git a/tests/Unit/FactoryCreationTest.php b/tests/Unit/FactoryCreationTest.php index 178ed4b1965f..e05bd4395881 100644 --- a/tests/Unit/FactoryCreationTest.php +++ b/tests/Unit/FactoryCreationTest.php @@ -9,10 +9,12 @@ use App\Factory\InvoiceFactory; use App\Factory\ProductFactory; use App\Factory\UserFactory; use App\Models\Client; +use App\Models\User; use App\Utils\Traits\MakesHash; use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Session; +use Tests\MockAccountData; use Tests\TestCase; /** @@ -22,6 +24,7 @@ class FactoryCreationTest extends TestCase { use MakesHash; use DatabaseTransactions; + use MockAccountData; public function setUp() :void { @@ -34,21 +37,8 @@ class FactoryCreationTest extends TestCase Model::reguard(); - - $this->account = factory(\App\Models\Account::class)->create(); - $this->company = factory(\App\Models\Company::class)->create([ - 'account_id' => $this->account->id, - 'domain' => 'ninja.test', - - ]); - - $this->account->default_company_id = $this->company->id; - $this->account->save(); - - $this->user = factory(\App\Models\User::class)->create([ - // 'account_id' => $account->id, - 'confirmation_code' => $this->createDbHash(config('database.default')) - ]); + $this->makeTestData(); + } /** @@ -120,13 +110,13 @@ class FactoryCreationTest extends TestCase */ public function testClientCreate() { - $client = ClientFactory::create($this->company->id, $this->user->id); + $cliz = ClientFactory::create($this->company->id, $this->user->id); - $client->save(); + $cliz->save(); - $this->assertNotNull($client); + $this->assertNotNull($cliz); - $this->assertInternalType("int", $client->id); + $this->assertInternalType("int", $cliz->id); } /** @@ -136,33 +126,13 @@ class FactoryCreationTest extends TestCase public function testClientContactCreate() { - factory(\App\Models\Client::class)->create(['user_id' => $this->user->id, 'company_id' => $this->company->id])->each(function ($c){ + $cliz = ClientFactory::create($this->company->id, $this->user->id); - factory(\App\Models\ClientContact::class,1)->create([ - 'user_id' => $this->user->id, - 'client_id' => $c->id, - 'company_id' => $this->company->id, - 'is_primary' => 1 - ]); + $cliz->save(); - factory(\App\Models\ClientContact::class,2)->create([ - 'user_id' => $this->user->id, - 'client_id' => $c->id, - 'company_id' => $this->company->id - ]); - - }); - - $client = Client::whereUserId($this->user->id)->whereCompanyId($this->company->id)->first(); - - - $contact = ClientContactFactory::create($this->company->id, $this->user->id); - $contact->client_id = $client->id; - $contact->save(); - - $this->assertNotNull($contact); - - $this->assertInternalType("int", $contact->id); + $this->assertNotNull($cliz->contacts); + $this->assertEquals(1, $cliz->contacts->count()); + $this->assertInternalType("int", $cliz->contacts->first()->id); } diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index 02f3ffc2a48d..31591780fe6c 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -2,12 +2,15 @@ namespace Tests\Unit; +use App\DataMapper\ClientSettings; use App\DataMapper\DefaultSettings; +use App\Factory\ClientFactory; use App\Models\Client; use App\Models\Company; use App\Models\Credit; use App\Models\Invoice; use App\Models\RecurringInvoice; +use App\Models\User; use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\GeneratesNumberCounter; use App\Utils\Traits\MakesHash; @@ -15,6 +18,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Session; +use Tests\MockAccountData; use Tests\TestCase; /** @@ -26,7 +30,7 @@ class GeneratesCounterTest extends TestCase use GeneratesCounter; use DatabaseTransactions; use MakesHash; - //use MockAccountData; + use MockAccountData; public function setUp() :void { @@ -36,49 +40,8 @@ class GeneratesCounterTest extends TestCase Session::start(); $this->faker = \Faker\Factory::create(); Model::reguard(); - $account = factory(\App\Models\Account::class)->create(); - $company = factory(\App\Models\Company::class)->create([ - 'account_id' => $account->id, - 'domain' => 'ninja.test', - ]); - $account->default_company_id = $company->id; - $account->save(); - $user = factory(\App\Models\User::class)->create([ - // 'account_id' => $account->id, - 'confirmation_code' => $this->createDbHash(config('database.default')) - ]); - $userPermissions = collect([ - 'view_invoice', - 'view_client', - 'edit_client', - 'edit_invoice', - 'create_invoice', - 'create_client' - ]); - $userSettings = DefaultSettings::userSettings(); - $user->companies()->attach($company->id, [ - 'account_id' => $account->id, - 'is_owner' => 1, - 'is_admin' => 1, - 'permissions' => $userPermissions->toJson(), - 'settings' => json_encode($userSettings), - 'is_locked' => 0, - ]); - factory(\App\Models\Client::class)->create(['user_id' => $user->id, 'company_id' => $company->id])->each(function ($c) use ($user, $company){ - factory(\App\Models\ClientContact::class,1)->create([ - 'user_id' => $user->id, - 'client_id' => $c->id, - 'company_id' => $company->id, - 'is_primary' => 1 - ]); - factory(\App\Models\ClientContact::class,2)->create([ - 'user_id' => $user->id, - 'client_id' => $c->id, - 'company_id' => $company->id - ]); - }); - $this->client = Client::whereUserId($user->id)->whereCompanyId($company->id)->first(); + $this->makeTestData(); } @@ -92,11 +55,11 @@ class GeneratesCounterTest extends TestCase $invoice_number = $this->getNextInvoiceNumber($this->client); - $this->assertEquals($invoice_number, 1); + $this->assertEquals($invoice_number, 0007); $invoice_number = $this->getNextInvoiceNumber($this->client); - $this->assertEquals($invoice_number, 2); + $this->assertEquals($invoice_number, '0008'); } @@ -110,6 +73,10 @@ class GeneratesCounterTest extends TestCase $this->client->company->settings = $settings; $this->client->company->save(); + $this->client->settings = $settings; + $this->client->save(); + $this->client->fresh(); + $invoice_number = $this->getNextInvoiceNumber($this->client); $invoice_number2 = $this->getNextInvoiceNumber($this->client); @@ -121,70 +88,86 @@ class GeneratesCounterTest extends TestCase public function testInvoiceClientNumberPattern() { - $settings = $this->client->company->settings; + $settings = $this->company->settings; + $settings->client_number_prefix = ''; + $settings->client_number_pattern = '{$year}-{$clientCounter}'; + $settings->client_number_counter = 10; - $settings->invoice_number_prefix = ''; - $settings->invoice_number_pattern = '{$year}-{$clientCounter}'; - $this->client->company->settings = $settings; - $this->client->company->save(); + $this->company->settings = $settings; + $this->company->save(); $settings = $this->client->settings; - $settings->invoice_number_counter = 10; + $settings->client_number_pattern = '{$year}-{$clientCounter}'; + $settings->client_number_counter = 10; $this->client->settings = $settings; $this->client->save(); + $this->client->fresh(); - $this->assertEquals($this->client->settings->invoice_number_counter,10); + $this->assertEquals($this->client->settings->client_number_counter,10); + $this->assertEquals($this->client->getSetting('client_number_pattern'), '{$year}-{$clientCounter}'); - $invoice_number = $this->getNextInvoiceNumber($this->client); + $invoice_number = $this->getNextClientNumber($this->client); - $this->assertEquals($invoice_number, '2019-0010'); + $this->assertEquals($invoice_number, '2019-0001'); - $invoice_number = $this->getNextInvoiceNumber($this->client); - $this->assertEquals($invoice_number, '2019-0011'); + $invoice_number = $this->getNextClientNumber($this->client); + $this->assertEquals($invoice_number, '2019-0002'); } public function testInvoicePadding() { - $settings = $this->client->company->settings; + $settings = $this->company->settings; $settings->counter_padding = 5; - $this->client->company->settings = $settings; - $this->client->push(); + $settings->invoice_number_counter = 7; + //$this->client->settings = $settings; + $this->company->settings = $settings; + $this->company->save(); - $invoice_number = $this->getNextInvoiceNumber($this->client); + $cliz = ClientFactory::create($this->company->id, $this->user->id); + $cliz->settings = ClientSettings::defaults(); + $cliz->save(); + $invoice_number = $this->getNextInvoiceNumber($cliz); - $this->assertEquals($this->client->company->settings->counter_padding, 5); + $this->assertEquals($cliz->getSetting('counter_padding'), 5); + $this->assertEquals($invoice_number, '00007'); $this->assertEquals(strlen($invoice_number), 5); - $this->assertEquals($invoice_number, '00001'); - - $settings = $this->client->company->settings; + $settings = $this->company->settings; $settings->counter_padding = 10; - $this->client->company->settings = $settings; - $this->client->push(); + $this->company->settings = $settings; + $this->company->save(); + + $cliz = ClientFactory::create($this->company->id, $this->user->id); + $cliz->settings = ClientSettings::defaults(); + $cliz->save(); - $invoice_number = $this->getNextInvoiceNumber($this->client); + $invoice_number = $this->getNextInvoiceNumber($cliz); - $this->assertEquals($this->client->company->settings->counter_padding, 10); + $this->assertEquals($cliz->getSetting('counter_padding'), 10); $this->assertEquals(strlen($invoice_number), 10); - $this->assertEquals($invoice_number, '0000000002'); + $this->assertEquals($invoice_number, '0000000007'); } public function testInvoicePrefix() { - $settings = $this->client->company->settings; + $settings = $this->company->settings; $settings->invoice_number_prefix = 'X'; - $this->client->company->settings = $settings; - $this->client->company->save(); + $this->company->settings = $settings; + $this->company->save(); - $invoice_number = $this->getNextInvoiceNumber($this->client); + $cliz = ClientFactory::create($this->company->id, $this->user->id); + $cliz->settings = ClientSettings::defaults(); + $cliz->save(); + + $invoice_number = $this->getNextInvoiceNumber($cliz); $this->assertEquals($invoice_number, 'X0001'); - $invoice_number = $this->getNextInvoiceNumber($this->client); + $invoice_number = $this->getNextInvoiceNumber($cliz); $this->assertEquals($invoice_number, 'X0002'); @@ -206,16 +189,20 @@ class GeneratesCounterTest extends TestCase public function testClientNumberPrefix() { - $settings = $this->client->company->settings; + $settings = $this->company->settings; $settings->client_number_prefix = 'C'; - $this->client->company->settings = $settings; - $this->client->company->save(); + $this->company->settings = $settings; + $this->company->save(); - $client_number = $this->getNextClientNumber($this->client); + $cliz = ClientFactory::create($this->company->id, $this->user->id); + $cliz->settings = ClientSettings::defaults(); + $cliz->save(); + + $client_number = $this->getNextClientNumber($cliz); $this->assertEquals($client_number, 'C0001'); - $client_number = $this->getNextClientNumber($this->client); + $client_number = $this->getNextClientNumber($cliz); $this->assertEquals($client_number, 'C0002'); @@ -224,21 +211,23 @@ class GeneratesCounterTest extends TestCase public function testClientNumberPattern() { - $settings = $this->client->company->settings; + $settings = $this->company->settings; $settings->client_number_prefix = ''; $settings->client_number_pattern = '{$year}-{$user_id}-{$counter}'; - $this->client->company->settings = $settings; - $this->client->company->save(); - $this->client->save(); - $this->client->fresh(); + $this->company->settings = $settings; + $this->company->save(); - $client_number = $this->getNextClientNumber($this->client); - - $this->assertEquals($client_number, date('Y') . '-' . $this->client->user_id . '-0001'); + $cliz = ClientFactory::create($this->company->id, $this->user->id); + $cliz->settings = ClientSettings::defaults(); + $cliz->save(); - $client_number = $this->getNextClientNumber($this->client); + $client_number = $this->getNextClientNumber($cliz); - $this->assertEquals($client_number, date('Y') . '-' . $this->client->user_id . '-0002'); + $this->assertEquals($client_number, date('Y') . '-' . str_pad($this->client->user_id, 2, '0', STR_PAD_LEFT) . '-0001'); + + $client_number = $this->getNextClientNumber($cliz); + + $this->assertEquals($client_number, date('Y') . '-' . str_pad($this->client->user_id, 2, '0', STR_PAD_LEFT) . '-0002'); } /*