mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-24 02:14:21 -04:00
Fixes for tests (#3082)
* Update client paid to date job: * Backup Invoice HTML when invoice is marked as sent and paid * Store HTML of invoice when invoice was paid * Fix foreign keys in db schema * V2 Endpoints for Company Migrations * Fixes for tests
This commit is contained in:
parent
6d225b7fe7
commit
f59585dd62
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ yarn-error.log
|
||||
.env.dusk.local
|
||||
/public/vendors/*
|
||||
public/mix-manifest.json
|
||||
*.log
|
@ -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([
|
||||
|
38
app/Events/Invoice/InvoiceWasPaid.php
Normal file
38
app/Events/Invoice/InvoiceWasPaid.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Events\Invoice;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class InvoiceWasPaid.
|
||||
*/
|
||||
class InvoiceWasPaid
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var Invoice
|
||||
*/
|
||||
public $invoice;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param Invoice $invoice
|
||||
*/
|
||||
public function __construct(Invoice $invoice)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
}
|
||||
}
|
144
app/Http/Controllers/MigrationController.php
Normal file
144
app/Http/Controllers/MigrationController.php
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\Account\CreateAccountRequest;
|
||||
use App\Jobs\Account\CreateAccount;
|
||||
use App\Models\Account;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyUser;
|
||||
use App\Transformers\AccountTransformer;
|
||||
use App\Transformers\CompanyUserTransformer;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class MigrationController extends BaseController
|
||||
{
|
||||
use DispatchesJobs;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Purge Company
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/api/v1/migration/purge/{company}",
|
||||
* operationId="postPurgeCompany",
|
||||
* tags={"migration"},
|
||||
* summary="Attempts to purge a company record and all its child records",
|
||||
* description="Attempts to purge a company record and all its child records",
|
||||
* @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 purgeCompany(Company $company)
|
||||
{
|
||||
|
||||
$company->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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
50
app/Jobs/Client/UpdateClientPaidToDate.php
Normal file
50
app/Jobs/Client/UpdateClientPaidToDate.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Jobs\Client;
|
||||
|
||||
|
||||
use App\Models\Client;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
|
||||
class UpdateClientPaidToDate
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
protected $amount;
|
||||
|
||||
protected $client;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public function __construct(Client $client, $amount)
|
||||
{
|
||||
$this->amount = $amount;
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$this->client->paid_to_date += $this->amount;
|
||||
$this->client->save();
|
||||
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
50
app/Listeners/Invoice/CreateInvoiceHtmlBackup.php
Normal file
50
app/Listeners/Invoice/CreateInvoiceHtmlBackup.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Listeners\Invoice;
|
||||
|
||||
use App\Models\Activity;
|
||||
use App\Repositories\ActivityRepository;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
class CreateInvoiceHtmlBackup implements ShouldQueue
|
||||
{
|
||||
protected $activity_repo;
|
||||
/**
|
||||
* Create the event listener.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ActivityRepository $activity_repo)
|
||||
{
|
||||
$this->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);
|
||||
}
|
||||
}
|
@ -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]);
|
||||
|
||||
});
|
||||
|
@ -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',
|
||||
|
@ -23,7 +23,6 @@ class CompanyUser extends Pivot
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'settings' => 'object',
|
||||
'permissions' => 'object',
|
||||
'updated_at' => 'timestamp',
|
||||
'created_at' => 'timestamp',
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
88
app/Utils/Traits/MakesInvoiceHtml.php
Normal file
88
app/Utils/Traits/MakesInvoiceHtml.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com)
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://opensource.org/licenses/AAL
|
||||
*/
|
||||
|
||||
namespace App\Utils\Traits;
|
||||
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
|
||||
|
||||
/**
|
||||
* Class MakesInvoiceHtml.
|
||||
*/
|
||||
trait MakesInvoiceHtml
|
||||
{
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
public 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
|
||||
*
|
||||
*/
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
@ -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',
|
||||
],
|
||||
],
|
||||
|
||||
|
@ -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');
|
||||
|
@ -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');
|
||||
|
96
tests/Feature/MigrationTest.php
Normal file
96
tests/Feature/MigrationTest.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Feature;
|
||||
|
||||
use App\Jobs\Account\CreateAccount;
|
||||
use App\Models\Account;
|
||||
use App\Models\Client;
|
||||
use App\Models\Company;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\UserSessionAttributes;
|
||||
use Faker\Factory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Foundation\Testing\WithFaker;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Tests\MockAccountData;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @covers App\Http\Controllers\MigrationController
|
||||
*/
|
||||
|
||||
class MigrationTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions;
|
||||
use MockAccountData;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Session::start();
|
||||
|
||||
$this->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);
|
||||
|
||||
}
|
||||
}
|
@ -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([
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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');
|
||||
|
||||
}
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user