Subscriptions (#3682)

* Working on subscriptions

* Implement return type in models

* Subscription implementation

* Improvements to handling importation of large accountS

* Loggin imports

* Activate collector

* Improve memory usage of import script

* Quote actions

* Send Quotes

* Fixes for seg faults!

* Minor fixes

* Fixes for client contact scopes
This commit is contained in:
David Bomba 2020-05-09 08:35:49 +10:00 committed by GitHub
parent 6e89affc93
commit d9d2e21f93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 373 additions and 81 deletions

View File

@ -11,14 +11,14 @@
namespace App\Factory;
use App\Models\quote;
use App\Models\Quote;
class CloneQuoteFactory
{
public static function create($quote, $user_id)
{
$clone_quote = $quote->replicate();
$clone_quote->status_id = quote::STATUS_DRAFT;
$clone_quote->status_id = Quote::STATUS_DRAFT;
$clone_quote->number = null;
$clone_quote->date = null;
$clone_quote->due_date = null;

View File

@ -1,4 +1,14 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Factory;
use App\Models\Invoice;
@ -8,12 +18,25 @@ class CloneQuoteToInvoiceFactory
{
public static function create(Quote $quote, $user_id) : ?Invoice
{
$invoice = new Invoice();
$invoice->user_id = $user_id;
$invoice->po_number = $quote->po_number;
$invoice->footer = $quote->footer;
$invoice->line_items = $quote->line_items;
return $invoice;
$invoice = new Invoice();
$quote_array = $quote->toArray();
unset($quote_array['client']);
unset($quote_array['company']);
unset($quote_array['hashed_id']);
unset($quote_array['id']);
foreach($quote_array as $key => $value)
$invoice->{$key} = $value;
$invoice->due_date = null;
$invoice->partial_due_date = null;
$invoice->number = null;
$invoice->status_id = null;
return $invoice;
}
}

View File

@ -28,7 +28,7 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Laravel\Socialite\Facades\Socialite;
use Turbo124\Collector\Facades\LightLogs;
use Turbo124\Beacon\Facades\LightLogs;
class LoginController extends BaseController
{

View File

@ -501,9 +501,7 @@ class QuoteController extends BaseController
*/
public function bulk()
{
/*
* WIP!
*/
$action = request()->input('action');
$ids = request()->input('ids');
@ -511,14 +509,14 @@ class QuoteController extends BaseController
$quotes = Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company()->get();
if (!$quotes) {
return response()->json(['message' => 'No Quotes Found']);
return response()->json(['message' => 'No Quote/s Found']);
}
/*
* Download Invoice/s
*/
if ($action == 'download' && $quotes->count() > 1) {
if ($action == 'download' && $quotes->count() >= 1) {
$quotes->each(function ($quote) {
if (auth()->user()->cannot('view', $quote)) {
return response()->json(['message'=>'Insufficient privileges to access quote '. $quote->number]);
@ -627,8 +625,8 @@ class QuoteController extends BaseController
switch ($action) {
case 'clone_to_invoice':
$this->entity_type = Quote::class;
$this->entity_transformer = QuoteTransformer::class;
$this->entity_type = Invoice::class;
$this->entity_transformer = InvoiceTransformer::class;
$invoice = CloneQuoteToInvoiceFactory::create($quote, auth()->user()->id);
return $this->itemResponse($invoice);
@ -646,17 +644,16 @@ class QuoteController extends BaseController
return $this->itemResponse($quote->service()->approve()->save());
break;
case 'convert':
//convert quote to an invoice make sure we link the two entities!!!
$this->entity_type = Invoice::class;
$this->entity_transformer = InvoiceTransformer::class;
return $this->itemResponse($quote->service()->convertToInvoice());
break;
case 'history':
# code...
break;
case 'delivery_note':
# code...
break;
case 'mark_paid':
# code...
break;
case 'download':
return response()->download(TempFile::path($quote->pdf_file_path()), basename($quote->pdf_file_path()));
break;
@ -669,6 +666,7 @@ class QuoteController extends BaseController
return $this->listResponse($quote);
break;
case 'email':
$this->quote->service()->sendEmail();
return response()->json(['message'=>'email sent'], 200);
break;
case 'mark_sent':

View File

@ -184,7 +184,7 @@ class PayPalExpressPaymentDriver extends BasePaymentDriver
private function buildReturnUrl($input) : string
{
$url = $this->client->company->domain() . "client/payments/process/response";
$url = $this->client->company->domain() . "/client/payments/process/response";
$url .= "?company_gateway_id={$this->company_gateway->id}&gateway_type_id=".GatewayType::PAYPAL;
$url .= "&hashed_ids=" . implode(",", $input['hashed_ids']);
$url .= "&amount=".$input['amount'];

View File

@ -1,4 +1,14 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Services\Credit;
use App\Models\Credit;

View File

@ -103,12 +103,12 @@ class InvoiceService
}
public function getInvoicePdf($contact)
public function getInvoicePdf($contact = null)
{
return (new GetInvoicePdf($this->invoice, $contact))->run();
}
public function sendEmail($contact)
public function sendEmail($contact = null)
{
$send_email = new SendEmail($this->invoice, null, $contact);

View File

@ -22,6 +22,10 @@ class SendEmail extends AbstractService
{
protected $invoice;
protected $reminder_template;
protected $contact;
public function __construct(Invoice $invoice, $reminder_template = null, ClientContact $contact = null)
{
$this->invoice = $invoice;

View File

@ -47,7 +47,7 @@ class PaymentService
public function sendEmail($contact = null)
{
return (new SendEmail($this->payment))->run(null, $contact);
return (new SendEmail($this->payment, $contact))->run();
}
public function reversePayment()

View File

@ -9,9 +9,13 @@ class SendEmail
{
public $payment;
public function __construct($payment)
public $contact;
public function __construct($payment, $contact)
{
$this->payment = $payment;
$this->contact = $contact;
}
/**
@ -19,7 +23,7 @@ class SendEmail
* @param string $reminder_template The template name ie reminder1
* @return array
*/
public function run($contact = null): array
public function run()
{
$email_builder = (new PaymentEmail())->build($this->payment, $contact);

View File

@ -1,6 +1,17 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Services\Quote;
use App\Factory\CloneQuoteToInvoiceFactory;
use App\Models\Invoice;
use App\Models\Quote;
use App\Repositories\QuoteRepository;
@ -38,18 +49,18 @@ class QuoteService
return $this;
}
public function getQuotePdf($contact)
public function getQuotePdf($contact = null)
{
$get_invoice_pdf = new GetQuotePdf();
return $get_invoice_pdf($this->quote, $contact);
}
public function sendEmail($contact) :QuoteService
public function sendEmail($contact = null) :QuoteService
{
$send_email = new SendEmail($this->quote);
$send_email = new SendEmail($this->quote, null, $contact);
$send_email->run(null, $contact);
$send_email->run();
return $this;
}
@ -116,18 +127,17 @@ class QuoteService
public function convertToInvoice() :Invoice
{
Invoice::unguard();
$invoice = new Invoice((array) $this->quote);
$invoice = CloneQuoteToInvoiceFactory::create($this->quote, $this->quote->user_id);
$invoice->status_id = Invoice::STATUS_SENT;
$invoice->due_date = null;
$invoice->invitations = null;
$invoice->number = null;
$invoice->save();
Invoice::reguard();
$invoice->service()->markSent()->createInvitations()->save();
$invoice->service()
->markSent()
->createInvitations()
->save();
return $invoice;
}

View File

@ -4,31 +4,40 @@ namespace App\Services\Quote;
use App\Helpers\Email\QuoteEmail;
use App\Jobs\Quote\EmailQuote;
use App\Models\ClientContact;
use App\Models\Quote;
class SendEmail
{
public $quote;
public function __construct($quote)
protected $reminder_template;
protected $contact;
public function __construct($quote, $reminder_template = null, ClientContact $contact = null)
{
$this->quote = $quote;
$this->reminder_template = $reminder_template;
$this->contact = $contact;
}
/**
* Builds the correct template to send
* @param string $reminder_template The template name ie reminder1
* @param string $this->reminder_template The template name ie reminder1
* @return array
*/
public function run($reminder_template = null, $contact = null): array
public function run(): array
{
if (!$reminder_template) {
$reminder_template = $this->quote->status_id == Quote::STATUS_DRAFT || Carbon::parse($this->quote->due_date) > now() ? 'invoice' : $this->quote->calculateTemplate();
if (!$this->reminder_template) {
$this->reminder_template = $this->quote->calculateTemplate();
}
$this->quote->invitations->each(function ($invitation) {
if ($invitation->contact->send_email && $invitation->contact->email) {
$email_builder = (new QuoteEmail())->build($invitation, $reminder_template);
$email_builder = (new QuoteEmail())->build($invitation, $this->reminder_template);
EmailQuote::dispatchNow($email_builder, $invitation);
}

View File

@ -55,7 +55,7 @@
"staudenmeir/eloquent-has-many-deep": "^1.11",
"stripe/stripe-php": "^7.0",
"superbalist/laravel-google-cloud-storage": "^2.2",
"turbo124/collector": "^0",
"turbo124/beacon": "^0",
"webpatser/laravel-countries": "dev-master#75992ad",
"yajra/laravel-datatables-oracle": "~9.0"
},

View File

@ -3,9 +3,9 @@
return [
/**
* Enable or disable the collector
* Enable or disable the beacon
*/
'enabled' => false,
'enabled' => true,
/**
* The API endpoint for logs
@ -15,7 +15,7 @@ return [
/**
* Your API key
*/
'api_key' => env('COLLECTOR_API_KEY',''),
'api_key' => env('BEACON_API_KEY',''),
/**
* Should batch requests
@ -26,7 +26,7 @@ return [
* The default key used to store
* metrics for batching
*/
'cache_key' => 'collector',
'cache_key' => 'beacon',
/**
* Determines whether to log the
@ -34,9 +34,9 @@ return [
* the built in metrics.
*/
'system_logging' => [
'Turbo124\Collector\Jobs\System\CpuMetric',
'Turbo124\Collector\Jobs\System\HdMetric',
'Turbo124\Collector\Jobs\System\MemMetric',
'Turbo124\Beacon\Jobs\System\CpuMetric',
'Turbo124\Beacon\Jobs\System\HdMetric',
'Turbo124\Beacon\Jobs\System\MemMetric',
],
];

223
package-lock.json generated
View File

@ -6188,6 +6188,54 @@
"find-up": "^3.0.0"
}
},
"pkg-up": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz",
"integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=",
"requires": {
"find-up": "^2.1.0"
},
"dependencies": {
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"requires": {
"locate-path": "^2.0.0"
}
},
"locate-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"requires": {
"p-locate": "^2.0.0",
"path-exists": "^3.0.0"
}
},
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"requires": {
"p-try": "^1.0.0"
}
},
"p-locate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"requires": {
"p-limit": "^1.1.0"
}
},
"p-try": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
}
}
},
"portfinder": {
"version": "1.0.25",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
@ -8219,13 +8267,16 @@
}
},
"tailwindcss": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.2.0.tgz",
"integrity": "sha512-CKvY0ytB3ze5qvynG7qv4XSpQtFNGPbu9pUn8qFdkqgD8Yo/vGss8mhzbqls44YCXTl4G62p3qVZBj45qrd6FQ==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.4.5.tgz",
"integrity": "sha512-MJW96Rz3G3RrFDbDuQCU893y4bf5hMWeVbMgcCqUfLNPbO9wRogDibCEvdKitD6aX9Y90SDT2FOKD17+WmIFLQ==",
"requires": {
"@fullhuman/postcss-purgecss": "^2.1.2",
"autoprefixer": "^9.4.5",
"browserslist": "^4.12.0",
"bytes": "^3.0.0",
"chalk": "^3.0.0",
"chalk": "^4.0.0",
"color": "^3.1.2",
"detective": "^5.2.0",
"fs-extra": "^8.0.0",
"lodash": "^4.17.15",
@ -8241,22 +8292,94 @@
"resolve": "^1.14.2"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"@fullhuman/postcss-purgecss": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@fullhuman/postcss-purgecss/-/postcss-purgecss-2.2.0.tgz",
"integrity": "sha512-q4zYAn8L9olA5uneaLhxkHRBoug9dnAqytbdX9R5dbzSORobhYr1yGR2JN3Q1UMd5RB0apm1NvJekHaymal/BQ==",
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
"postcss": "7.0.28",
"purgecss": "^2.2.0"
},
"dependencies": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"postcss": {
"version": "7.0.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.28.tgz",
"integrity": "sha512-YU6nVhyWIsVtlNlnAj1fHTsUKW5qxm3KEgzq2Jj6KTEFOTK8QWR12eIDvrlWhiSTK8WIBFTBhOJV4DY6dUuEbw==",
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
}
}
}
},
"browserslist": {
"version": "4.12.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
"integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==",
"requires": {
"caniuse-lite": "^1.0.30001043",
"electron-to-chromium": "^1.3.413",
"node-releases": "^1.1.53",
"pkg-up": "^2.0.0"
}
},
"caniuse-lite": {
"version": "1.0.30001053",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001053.tgz",
"integrity": "sha512-HtV4wwIZl6GA4Oznse8aR274XUOYGZnQLcf/P8vHgmlfqSNelwD+id8CyHOceqLqt9yfKmo7DUZTh1EuS9pukg=="
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
"integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"color-convert": {
@ -8272,6 +8395,16 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
},
"electron-to-chromium": {
"version": "1.3.430",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.430.tgz",
"integrity": "sha512-HMDYkANGhx6vfbqpOf/hc6hWEmiOipOHGDeRDeUb3HLD3XIWpvKQxFgWf0tgHcr3aNv6I/8VPecplqmQsXoZSw=="
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@ -8282,17 +8415,65 @@
"universalify": "^0.1.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
"node-releases": {
"version": "1.1.55",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.55.tgz",
"integrity": "sha512-H3R3YR/8TjT5WPin/wOoHOUPHgvj8leuU/Keta/rwelEQN9pA/S2Dx8/se4pZ2LBxSd0nAGzsNzhqwa77v7F1w=="
},
"purgecss": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.2.1.tgz",
"integrity": "sha512-wngRSLW1dpNr8kr3TL9nTJMyTFI5BiRiaUUEys5M1CA4zEHLF25fRHoshEeDqmhstaNTOddmpYM34zRrUtEGbQ==",
"requires": {
"commander": "^5.0.0",
"glob": "^7.0.0",
"postcss": "7.0.28",
"postcss-selector-parser": "^6.0.2"
},
"dependencies": {
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"dependencies": {
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"postcss": {
"version": "7.0.28",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.28.tgz",
"integrity": "sha512-YU6nVhyWIsVtlNlnAj1fHTsUKW5qxm3KEgzq2Jj6KTEFOTK8QWR12eIDvrlWhiSTK8WIBFTBhOJV4DY6dUuEbw==",
"requires": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
"supports-color": "^6.1.0"
}
}
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"requires": {
"has-flag": "^4.0.0"
"has-flag": "^3.0.0"
}
}
}

View File

@ -156,16 +156,18 @@ class DesignTest extends TestCase
public function testAllDesigns()
{
for ($x=1; $x<=10; $x++) {
$settings = $this->invoice->client->settings;
$settings->quote_design_id = (string)$this->encodePrimaryKey($x);
$settings->all_pages_header = true;
$settings->all_pages_footer = true;
$this->quote->client_id = $this->client->id;
$this->quote->setRelation('client', $this->client);
$this->quote->save();
for ($x=1; $x<=10; $x++) {
$settings = $this->invoice->client->settings;
$settings->quote_design_id = (string)$this->encodePrimaryKey($x);
$settings->all_pages_header = true;
$settings->all_pages_footer = true;
$this->client->settings = $settings;
$this->client->save();
@ -179,7 +181,9 @@ class DesignTest extends TestCase
CreateQuotePdf::dispatchNow($invitation);
$this->quote->number = $this->getNextQuoteNumber($this->quote->client);
$this->quote->save();
// $this->quote->save();
}
$this->assertTrue(true);

View File

@ -0,0 +1,49 @@
<?php
namespace Tests\Unit;
use App\Factory\CloneQuoteToInvoiceFactory;
use App\Factory\InvoiceFactory;
use App\Factory\InvoiceItemFactory;
use App\Helpers\Invoice\InvoiceSum;
use App\Models\Invoice;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\MockAccountData;
use Tests\TestCase;
/**
* @test
*/
class CloneQuoteToInvoiceFactoryTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public function setUp() :void
{
parent::setUp();
$this->makeTestData();
}
public function testCloneProperties()
{
$invoice = CloneQuoteToInvoiceFactory::create($this->quote, $this->quote->user_id);
$this->assertNull($invoice->due_date);
$this->assertNull($invoice->partial_due_date);
$this->assertNull($invoice->number);
}
public function testQuoteToInvoiceConversionService()
{
$invoice = $this->quote->service()->convertToInvoice();
$this->assertTrue($invoice instanceof Invoice);
}
}