diff --git a/app/Console/Commands/CreateTestData.php b/app/Console/Commands/CreateTestData.php
index 7eec8f6d7641..7f9cca2694ef 100644
--- a/app/Console/Commands/CreateTestData.php
+++ b/app/Console/Commands/CreateTestData.php
@@ -456,8 +456,7 @@ class CreateTestData extends Command
$invoice = $invoice_calc->getInvoice();
$invoice->save();
-
- event(new CreateInvoiceInvitation($invoice));
+ $invoice->service()->createInvitations();
UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
diff --git a/app/Designs/Bold.php b/app/Designs/Bold.php
new file mode 100644
index 000000000000..cd587cb024f6
--- /dev/null
+++ b/app/Designs/Bold.php
@@ -0,0 +1,41 @@
+design = $design;
+
+ $this->input_variables = $input_variables;
+ }
+
+ /**
+ * Returns the design
+ * formatted HTML
+ * @return string The HTML design built
+ */
+ public function build() :string
+ {
+
+ $this->setDesign($this->getSection('header'))
+ ->setDesign($this->getSection('body'))
+ ->setDesign($this->getSection('table'))
+ ->setDesign($this->getSection('footer'));
+
+ return $this->html;
+ }
+
+
+ private function setDesign($section)
+ {
+
+ $this->html .= $section;
+
+ return $this;
+ }
+
+ /**
+ * Returns the template section on with the
+ * stacked variables replaced with single variables.
+ *
+ * @param string $section the method name to be executed ie header/body/table/footer
+ * @return string The HTML of the template section
+ */
+ public function getSection($section) :string
+ {
+ $this->exportVariables();
+
+ return str_replace(array_keys($this->exported_variables), array_values($this->exported_variables), $this->design->{$section}());
+ }
+
+ private function exportVariables()
+ {
+
+ $this->exported_variables['$client_details'] = $this->processVariables($this->input_variables['client_details'], $this->clientDetails());
+ $this->exported_variables['$company_details'] = $this->processVariables($this->input_variables['company_details'], $this->companyDetails());
+ $this->exported_variables['$company_address'] = $this->processVariables($this->input_variables['company_address'], $this->companyAddress());
+ $this->exported_variables['$invoice_details_labels'] = $this->processLabels($this->input_variables['invoice_details'], $this->invoiceDetails());
+ $this->exported_variables['$invoice_details'] = $this->processVariables($this->input_variables['invoice_details'], $this->invoiceDetails());
+
+ return $this;
+ }
+
+ private function processVariables($input_variables, $variables) :string
+ {
+
+ $output = '';
+
+ foreach($input_variables as $value)
+ $output .= $variables[$value];
+
+ return $output;
+
+ }
+
+ private function processLabels($input_variables, $variables) :string
+ {
+ $output = '';
+
+ foreach($input_variables as $value) {
+
+ $tmp = str_replace("", "_label", $variables[$value]);
+
+ $output .= $tmp;
+ }
+
+ return $output;
+ }
+
+ // private function exportVariables()
+ // {
+ // /*
+ // * $invoice_details_labels
+ // * $invoice_details
+ // */
+ // $header = $this->design->header();
+
+ // /*
+ // * $company_logo - full URL
+ // * $client_details
+ // */
+ // $body = $this->design->body();
+
+ // /*
+ // * $table_header
+ // * $table_body
+ // * $total_labels
+ // * $total_values
+ // */
+ // $table = $this->design->table();
+
+ // /*
+ // * $company_details
+ // * $company_address
+ // */
+ // $footer = $this->design->footer();
+ // }
+
+ private function clientDetails()
+ {
+
+ return [
+ 'name' => '
$client.name
',
+ 'id_number' => '$client.id_number
',
+ 'vat_number' => '$client.vat_number
',
+ 'address1' => '$client.address1
',
+ 'address2' => '$client.address2
',
+ 'city_state_postal' => '$client.city_state_postal
',
+ 'postal_city_state' => '$client.postal_city_state
',
+ 'country' => '$client.country
',
+ 'email' => '$client.email
',
+ 'custom_value1' => '$client.custom_value1
',
+ 'custom_value2' => '$client.custom_value2
',
+ 'custom_value3' => '$client.custom_value3
',
+ 'custom_value4' => '$client.custom_value4
',
+ ];
+
+ }
+
+ private function companyDetails()
+ {
+ return [
+ 'company_name' => '$company.company_name',
+ 'id_number' => '$company.id_number',
+ 'vat_number' => '$company.vat_number',
+ 'website' => '$company.website',
+ 'email' => '$company.email',
+ 'phone' => '$company.phone',
+ 'custom_value1' => '$company.custom_value1',
+ 'custom_value2' => '$company.custom_value2',
+ 'custom_value3' => '$company.custom_value3',
+ 'custom_value4' => '$company.custom_value4',
+ ];
+ }
+
+ private function companyAddress()
+ {
+
+ return [
+ 'address1' => '$company.address1',
+ 'address2' => '$company.address1',
+ 'city_state_postal' => '$company.city_state_postal',
+ 'postal_city_state' => '$company.postal_city_state',
+ 'country' => '$company.country',
+ 'custom_value1' => '$company.custom_value1',
+ 'custom_value2' => '$company.custom_value2',
+ 'custom_value3' => '$company.custom_value3',
+ 'custom_value4' => '$company.custom_value4',
+ ];
+
+ }
+
+ private function invoiceDetails()
+ {
+
+ return [
+ 'invoice_number' => '$invoice_number',
+ 'po_number' => '$po_number',
+ 'date' => '$date',
+ 'due_date' => '$due_date',
+ 'balance_due' => '$balance_due',
+ 'invoice_total' => '$invoice_total',
+ 'partial_due' => '$partial_due',
+ 'custom_value1' => '$invoice.custom_value1',
+ 'custom_value2' => '$invoice.custom_value2',
+ 'custom_value3' => '$invoice.custom_value3',
+ 'custom_value4' => '$invoice.custom_value4',
+ ];
+
+ }
+}
\ No newline at end of file
diff --git a/app/Designs/Modern.php b/app/Designs/Modern.php
new file mode 100644
index 000000000000..05c1c8e3b4c8
--- /dev/null
+++ b/app/Designs/Modern.php
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
$company.name
+
+
+
+ $invoice_details_labels
+
+
+ $invoice_details
+
+
+
+ ';
+
+ }
+
+ public function body()
+ {
+
+ return '
+
+
+ $company_logo
+
+
+
+ $client_details
+
+
+
+
+
+
+ ';
+
+ }
+
+ public function table_styles()
+ {
+ return [
+ 'table_header_class' => "px-4 py-2",
+ 'table_body_class' => "border-t border-b border-gray-900 px-4 py-4",
+ ];
+ }
+
+ public function table()
+ {
+
+ return '
+
+
+
+
+ $table_header
+
+
+
+
+ $table_body
+
+
+
+
+
+
+ $invoice.public_notes
+
+
+
+ $total_labels
+
+
+ $total_values
+
+
+
+
+
+
+
$terms_label
+ $terms
+
+
+
+
+
+
+ ';
+ }
+
+ public function footer()
+ {
+
+ return '
+
+
+
+
+
+
+ $company_details
+
+
+ $company_address
+
+
+
+
+
+
+ ';
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/SelfUpdateController.php b/app/Http/Controllers/SelfUpdateController.php
new file mode 100644
index 000000000000..24bca36f1713
--- /dev/null
+++ b/app/Http/Controllers/SelfUpdateController.php
@@ -0,0 +1,27 @@
+ []
];
return response()
- ->json(json_encode($error, JSON_PRETTY_PRINT), 403)
+ ->json($error, 403)
->header('X-App-Version', config('ninja.app_version'))
->header('X-Api-Version', config('ninja.api_version'));
}
diff --git a/app/Http/Middleware/ContactSetDb.php b/app/Http/Middleware/ContactSetDb.php
index 302f204501a8..d4fc3f7fa40e 100644
--- a/app/Http/Middleware/ContactSetDb.php
+++ b/app/Http/Middleware/ContactSetDb.php
@@ -34,10 +34,10 @@ class ContactSetDb
if ($request->header('X-API-TOKEN') && config('ninja.db.multi_db_enabled')) {
if (! MultiDB::contactFindAndSetDb($request->header('X-API-TOKEN'))) {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
} else {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
return $next($request);
diff --git a/app/Http/Middleware/ContactTokenAuth.php b/app/Http/Middleware/ContactTokenAuth.php
index 08392b0160f6..b0c7ec4b7a06 100644
--- a/app/Http/Middleware/ContactTokenAuth.php
+++ b/app/Http/Middleware/ContactTokenAuth.php
@@ -36,7 +36,7 @@ class ContactTokenAuth
//client_contact who once existed, but has been soft deleted
if (!$client_contact) {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
@@ -47,7 +47,7 @@ class ContactTokenAuth
//client_contact who has been disabled
if ($client_contact->is_locked) {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
//stateless, don't remember the contact.
@@ -60,7 +60,7 @@ class ContactTokenAuth
'errors' => []
];
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
return $next($request);
diff --git a/app/Http/Middleware/SetDomainNameDb.php b/app/Http/Middleware/SetDomainNameDb.php
index f9ce79510b58..db0e1359f22d 100644
--- a/app/Http/Middleware/SetDomainNameDb.php
+++ b/app/Http/Middleware/SetDomainNameDb.php
@@ -35,7 +35,7 @@ class SetDomainNameDb
**/
if ($request->getSchemeAndHttpHost() && config('ninja.db.multi_db_enabled') && ! MultiDB::findAndSetDbByDomain($request->getSchemeAndHttpHost())) {
if (request()->json) {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
} else {
abort(404);
}
diff --git a/app/Http/Middleware/SetInviteDb.php b/app/Http/Middleware/SetInviteDb.php
index 4f9bc5c6e1aa..d5a864e2fa48 100644
--- a/app/Http/Middleware/SetInviteDb.php
+++ b/app/Http/Middleware/SetInviteDb.php
@@ -35,7 +35,7 @@ class SetInviteDb
**/
if ($request->getSchemeAndHttpHost() && config('ninja.db.multi_db_enabled') && ! MultiDB::findAndSetDbByInvitation($request->route('entity'), $request->route('invitation_key'))) {
if (request()->json) {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
} else {
abort(404);
}
diff --git a/app/Http/Middleware/TokenAuth.php b/app/Http/Middleware/TokenAuth.php
index eee270c4b4e7..4b6641aa45ac 100644
--- a/app/Http/Middleware/TokenAuth.php
+++ b/app/Http/Middleware/TokenAuth.php
@@ -37,7 +37,7 @@ class TokenAuth
];
//user who once existed, but has been soft deleted
if (!$user) {
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
/*
@@ -56,7 +56,7 @@ class TokenAuth
'errors' => []
];
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
//stateless, don't remember the user.
@@ -69,7 +69,7 @@ class TokenAuth
'errors' => []
];
- return response()->json(json_encode($error, JSON_PRETTY_PRINT), 403);
+ return response()->json($error, 403);
}
return $next($request);
diff --git a/app/Jobs/Invoice/ReverseInvoicePayment.php b/app/Jobs/Invoice/ReverseInvoicePayment.php
index 35ab3652502b..692499f0b910 100644
--- a/app/Jobs/Invoice/ReverseInvoicePayment.php
+++ b/app/Jobs/Invoice/ReverseInvoicePayment.php
@@ -68,7 +68,8 @@ class ReverseInvoicePayment implements ShouldQueue
UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($this->payment->amount), $this->company);
- $client->updateBalance($this->payment->amount)
+ $client->service()
+ ->updateBalance($this->payment->amount)
->updatePaidToDate($this->payment->amount*-1)
->save();
diff --git a/app/Jobs/Invoice/UpdateInvoicePayment.php b/app/Jobs/Invoice/UpdateInvoicePayment.php
index 6829e91689af..3da29bdf2f8b 100644
--- a/app/Jobs/Invoice/UpdateInvoicePayment.php
+++ b/app/Jobs/Invoice/UpdateInvoicePayment.php
@@ -65,6 +65,7 @@ class UpdateInvoicePayment implements ShouldQueue
UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($invoice->balance*-1), $this->company);
$this->payment->client
+ ->service()
->updateBalance($invoice->balance*-1)
->updatePaidToDate($invoice->balance)
->save();
@@ -72,7 +73,8 @@ class UpdateInvoicePayment implements ShouldQueue
$invoice->pivot->amount = $invoice->balance;
$invoice->pivot->save();
- $invoice->clearPartial()
+ $invoice->service()
+ ->clearPartial()
->updateBalance($invoice->balance*-1)
->save();
});
@@ -96,7 +98,8 @@ class UpdateInvoicePayment implements ShouldQueue
if ($invoice->hasPartial()) {
UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($invoice->partial*-1), $this->company);
- $this->payment->client->updateBalance($invoice->partial*-1)
+ $this->payment->client->service()
+ ->updateBalance($invoice->partial*-1)
->updatePaidToDate($invoice->partial)
->save();
@@ -111,14 +114,15 @@ class UpdateInvoicePayment implements ShouldQueue
} else {
UpdateCompanyLedgerWithPayment::dispatchNow($this->payment, ($invoice->balance*-1), $this->company);
- $this->payment->client->updateBalance($invoice->balance*-1)
+ $this->payment->client->service()
+ ->updateBalance($invoice->balance*-1)
->updatePaidToDate($invoice->balance)
->save();
$invoice->pivot->amount = $invoice->balance;
$invoice->pivot->save();
- $invoice->clearPartial()->updateBalance($invoice->balance*-1)->save();
+ $invoice->service()->clearPartial()->updateBalance($invoice->balance*-1)->save();
}
});
} else {
diff --git a/app/Models/Client.php b/app/Models/Client.php
index f55de9884bb1..ab7baf21d80f 100644
--- a/app/Models/Client.php
+++ b/app/Models/Client.php
@@ -212,15 +212,11 @@ class Client extends BaseModel
return new ClientService($this);
}
- public function updatePaidToDate($amount) :ClientService
- {
- return $this->service()->updatePaidToDate($amount);
- }
-
public function updateBalance($amount) :ClientService
{
return $this->service()->updateBalance($amount);
}
+
/**
* Adjusts client "balances" when a client
* makes a payment that goes on file, but does
diff --git a/app/Models/Presenters/CompanyPresenter.php b/app/Models/Presenters/CompanyPresenter.php
index 7f309dfeed0e..9cfb444cff77 100644
--- a/app/Models/Presenters/CompanyPresenter.php
+++ b/app/Models/Presenters/CompanyPresenter.php
@@ -25,7 +25,11 @@ class CompanyPresenter extends EntityPresenter
*/
public function name()
{
- return $this->entity->name ?: ctrans('texts.untitled_account');
+ $settings = $this->entity->settings;
+
+ return $this->settings->name ?: ctrans('texts.untitled_account');
+
+ //return $this->entity->name ?: ctrans('texts.untitled_account');
}
public function logo($settings = null)
diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php
index 57d78f3fd08f..2f4cba0d85b8 100644
--- a/app/Providers/EventServiceProvider.php
+++ b/app/Providers/EventServiceProvider.php
@@ -47,6 +47,12 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
+ \Codedge\Updater\Events\UpdateAvailable::class => [
+ \Codedge\Updater\Listeners\SendUpdateAvailableNotification::class
+ ], // [3]
+ \Codedge\Updater\Events\UpdateSucceeded::class => [
+ \Codedge\Updater\Listeners\SendUpdateSucceededNotification::class
+ ],
UserWasCreated::class => [
SendVerificationNotification::class,
],
diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php
index e6e666b05da9..22aa797438cf 100644
--- a/app/Repositories/PaymentRepository.php
+++ b/app/Repositories/PaymentRepository.php
@@ -77,7 +77,7 @@ class PaymentRepository extends BaseRepository
if (!$payment->number)
$payment->number = $payment->client->getNextPaymentNumber($payment->client);
- $payment->client->updatePaidToDate($payment->amount)->save();
+ $payment->client->service()->updatePaidToDate($payment->amount)->save();
$invoice_totals = 0;
$credit_totals = 0;
diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php
index 0f4305170b50..9f3656792a56 100644
--- a/app/Services/Invoice/ApplyPayment.php
+++ b/app/Services/Invoice/ApplyPayment.php
@@ -31,7 +31,7 @@ class ApplyPayment
UpdateCompanyLedgerWithPayment::dispatchNow($payment, ($payment_amount*-1), $payment->company);
- $payment->client->updateBalance($payment_amount*-1)->save();
+ $payment->client->service()->updateBalance($payment_amount*-1)->save();
/* Update Pivot Record amount */
$payment->invoices->each(function ($inv) use($payment_amount){
diff --git a/app/Services/Invoice/MarkSent.php b/app/Services/Invoice/MarkSent.php
index 33f85eb9fb5c..e39af542dbbe 100644
--- a/app/Services/Invoice/MarkSent.php
+++ b/app/Services/Invoice/MarkSent.php
@@ -33,17 +33,15 @@ class MarkSent
return $invoice;
}
- $invoice->status_id = Invoice::STATUS_SENT;
-
$invoice->markInvitationsSent();
$invoice->setReminder();
event(new InvoiceWasMarkedSent($invoice, $invoice->company));
- $this->client->updateBalance($invoice->balance)->save();
+ $this->client->service()->updateBalance($invoice->balance)->save();
- $invoice->service()->applyNumber()->save();
+ $invoice->service()->setStatus(Invoice::STATUS_SENT)->applyNumber()->save();
UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
diff --git a/app/Utils/Traits/MakesInvoiceValues.php b/app/Utils/Traits/MakesInvoiceValues.php
index 91c0c31f1044..ac8fb673df63 100644
--- a/app/Utils/Traits/MakesInvoiceValues.php
+++ b/app/Utils/Traits/MakesInvoiceValues.php
@@ -121,6 +121,8 @@ trait MakesInvoiceValues
'unit_cost',
'custom_value1',
'custom_value2',
+ 'custom_value3',
+ 'custom_value4',
'delivery_note',
'date',
'method',
@@ -197,6 +199,7 @@ trait MakesInvoiceValues
$data['$total'] = Number::formatMoney($this->calc()->getTotal(), $this->client);
$data['$invoice.total'] = &$data['$total'];
$data['$amount'] = &$data['$total'];
+ $data['$invoice_total'] = &$data['$total'];
$data['$invoice.amount'] = &$data['$total'];
$data['$balance'] = Number::formatMoney($this->calc()->getBalance(), $this->client);
@@ -205,6 +208,11 @@ trait MakesInvoiceValues
$data['$invoice.taxes'] = &$data['$taxes'];
$data['$terms'] = $this->terms;
$data['$invoice.terms'] = &$data['$terms'];
+ $data['$invoice.custom_value1'] = $this->custom_value1;
+ $data['$invoice.custom_value2'] = $this->custom_value2;
+ $data['$invoice.custom_value3'] = $this->custom_value3;
+ $data['$invoice.custom_value4'] = $this->custom_value4;
+ $data['$invoice.public_notes'] = $this->public_notes;
// $data['$your_invoice'] = ;
// $data['$quote'] = ;
// $data['$your_quote'] = ;
@@ -247,14 +255,20 @@ trait MakesInvoiceValues
$data['$client.country'] = &$data['$country'];
$data['$email'] = isset($this->client->primary_contact()->first()->email) ?: 'no contact email on record';
$data['$client.email'] = &$data['$email'];
+ $data['$client.custom_value1'] = $this->client->custom_value1;
+ $data['$client.custom_value2'] = $this->client->custom_value2;
+ $data['$client.custom_value3'] = $this->client->custom_value3;
+ $data['$client.custom_value4'] = $this->client->custom_value4;
- if ($contact) {
- $data['$contact_name'] = $contact->present()->name();
- $data['$contact.name'] = &$data['$contact_name'];
- } else {
- $data['$contact_name'] = $this->client->present()->primary_contact_name();
- $data['$contact.name'] = &$data['$contact_name'];
- }
+ if(!$contact)
+ $contact = $this->client->primary_contact->first();
+
+ $data['$contact_name'] = $contact->present()->name();
+ $data['$contact.name'] = &$data['$contact_name'];
+ $data['$contact.custom_value1'] = $contact->custom_value1;
+ $data['$contact.custom_value2'] = $contact->custom_value2;
+ $data['$contact.custom_value3'] = $contact->custom_value3;
+ $data['$contact.custom_value4'] = $contact->custom_value4;
$data['$company.name'] = $this->company->present()->name();
$data['$company.address1'] = $settings->address1;
@@ -269,6 +283,12 @@ trait MakesInvoiceValues
$data['$company.id_number'] = $settings->id_number;
$data['$company.address'] = $this->company->present()->address($settings);
$data['$company.logo'] = $this->company->present()->logo($settings);
+ $data['$company.custom_value1'] = $this->company->custom_value1;
+ $data['$company.custom_value2'] = $this->company->custom_value2;
+ $data['$company.custom_value3'] = $this->company->custom_value3;
+ $data['$company.custom_value4'] = $this->company->custom_value4;
+ $data['$company.city_state_postal'] = $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, false);
+ $data['$company.postal_city_state'] = $this->company->present()->cityStateZip($settings->city, $settings->state, $settings->postal_code, true);
//$data['$blank'] = ;
//$data['$surcharge'] = ;
/*
@@ -286,7 +306,7 @@ trait MakesInvoiceValues
$data['$credit_to'] = ;
$data['$your_credit'] = ;
$data['$phone'] = ;
- $data['$invoice_total'] = ;
+
$data['$outstanding'] = ;
$data['$invoice_due_date'] = ;
$data['$quote_due_date'] = ;
diff --git a/composer.json b/composer.json
index 265f3161e3b4..17bb9df4f133 100644
--- a/composer.json
+++ b/composer.json
@@ -21,6 +21,7 @@
"php": ">=7.3",
"anahkiasen/former": "^4.2",
"asgrim/ofxparser": "^1.2",
+ "codedge/laravel-selfupdater": "^2.4",
"dacastro4/laravel-gmail": "^3.2",
"davejamesmiller/laravel-breadcrumbs": "5.x",
"fideloper/proxy": "^4.0",
diff --git a/config/app.php b/config/app.php
index 407b86b8a0d7..404bd3d57299 100644
--- a/config/app.php
+++ b/config/app.php
@@ -178,6 +178,7 @@ return [
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\ComposerServiceProvider::class,
+ Codedge\Updater\UpdaterServiceProvider::class,
],
@@ -227,7 +228,7 @@ return [
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
-
+ 'Updater' => Codedge\Updater\UpdaterFacade::class,
/*
* Dependency Facades
*/
diff --git a/config/self-update.php b/config/self-update.php
new file mode 100644
index 000000000000..05571ac6a20f
--- /dev/null
+++ b/config/self-update.php
@@ -0,0 +1,125 @@
+ env('SELF_UPDATER_SOURCE', 'github'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Version installed
+ |--------------------------------------------------------------------------
+ |
+ | Set this to the version of your software installed on your system.
+ |
+ */
+
+ 'version_installed' => env('SELF_UPDATER_VERSION_INSTALLED', ''),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Repository types
+ |--------------------------------------------------------------------------
+ |
+ | A repository can be of different types, which can be specified here.
+ | Current options:
+ | - github
+ | - http
+ |
+ */
+
+ 'repository_types' => [
+ 'github' => [
+ 'type' => 'github',
+ 'repository_vendor' => env('SELF_UPDATER_REPO_VENDOR', ''),
+ 'repository_name' => env('SELF_UPDATER_REPO_NAME', ''),
+ 'repository_url' => '',
+ 'download_path' => env('SELF_UPDATER_DOWNLOAD_PATH', '/tmp'),
+ 'private_access_token' => env('SELF_UPDATER_GITHUB_PRIVATE_ACCESS_TOKEN', ''),
+ ],
+ 'http' => [
+ 'type' => 'http',
+ 'repository_url' => env('SELF_UPDATER_REPO_URL', ''),
+ 'pkg_filename_format' => env('SELF_UPDATER_PKG_FILENAME_FORMAT', 'v_VERSION_'),
+ 'download_path' => env('SELF_UPDATER_DOWNLOAD_PATH', '/tmp'),
+ 'private_access_token' => env('SELF_UPDATER_HTTP_PRIVATE_ACCESS_TOKEN', ''),
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Exclude folders from update
+ |--------------------------------------------------------------------------
+ |
+ | Specifiy folders which should not be updated and will be skipped during the
+ | update process.
+ |
+ | Here's already a list of good examples to skip. You may want to keep those.
+ |
+ */
+
+ 'exclude_folders' => [
+ 'node_modules',
+ 'bootstrap/cache',
+ 'bower',
+ 'storage/app',
+ 'storage/framework',
+ 'storage/logs',
+ 'storage/self-update',
+ 'vendor',
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Event Logging
+ |--------------------------------------------------------------------------
+ |
+ | Configure if fired events should be logged
+ |
+ */
+
+ 'log_events' => env('SELF_UPDATER_LOG_EVENTS', false),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Mail To Settings
+ |--------------------------------------------------------------------------
+ |
+ | Configure if fired events should be logged
+ |
+ */
+
+ 'mail_to' => [
+ 'address' => env('SELF_UPDATER_MAILTO_ADDRESS', ''),
+ 'name' => env('SELF_UPDATER_MAILTO_NAME', ''),
+ 'subject_update_available' => env('SELF_UPDATER_MAILTO_UPDATE_AVAILABLE_SUBJECT', 'Update available'),
+ 'subject_update_succeeded' => env('SELF_UPDATER_MAILTO_UPDATE_SUCCEEDED_SUBJECT', 'Update succeeded'),
+ ],
+
+ /*
+ |---------------------------------------------------------------------------
+ | Register custom artisan commands
+ |---------------------------------------------------------------------------
+ */
+
+ 'artisan_commands' => [
+ 'pre_update' => [
+ //'command:signature' => [
+ // 'class' => Command class
+ // 'params' => []
+ //]
+ ],
+ 'post_update' => [
+
+ ],
+ ],
+
+];
diff --git a/database/seeds/RandomDataSeeder.php b/database/seeds/RandomDataSeeder.php
index 0a75caff7fc3..47f408442b36 100644
--- a/database/seeds/RandomDataSeeder.php
+++ b/database/seeds/RandomDataSeeder.php
@@ -166,7 +166,7 @@ class RandomDataSeeder extends Seeder
UpdateCompanyLedgerWithInvoice::dispatchNow($invoice, $invoice->balance, $invoice->company);
- $invoice->markSent()->save();
+ $invoice->service()->markSent()->save();
event(new InvoiceWasMarkedSent($invoice, $company));
diff --git a/tests/Integration/InvoiceDesignTest.php b/tests/Integration/InvoiceDesignTest.php
new file mode 100644
index 000000000000..6870a0dfa1f3
--- /dev/null
+++ b/tests/Integration/InvoiceDesignTest.php
@@ -0,0 +1,91 @@
+ [
+ 'name',
+ 'id_number',
+ 'vat_number',
+ 'address1',
+ 'address2',
+ 'city_state_postal',
+ 'postal_city_state',
+ 'country',
+ 'email',
+ 'custom_value1',
+ 'custom_value2',
+ 'custom_value3',
+ 'custom_value4',
+ ],
+ 'company_details' => [
+ 'company_name',
+ 'id_number',
+ 'vat_number',
+ 'website',
+ 'email',
+ 'phone',
+ 'custom_value1',
+ 'custom_value2',
+ 'custom_value3',
+ 'custom_value4',
+ ],
+ 'company_address' => [
+ 'address1',
+ 'address2',
+ 'city_state_postal',
+ 'postal_city_state',
+ 'country',
+ 'custom_value1',
+ 'custom_value2',
+ 'custom_value3',
+ 'custom_value4',
+ ],
+ 'invoice_details' => [
+ 'invoice_number',
+ 'po_number',
+ 'date',
+ 'due_date',
+ 'balance_due',
+ 'invoice_total',
+ 'partial_due',
+ 'custom_value1',
+ 'custom_value2',
+ 'custom_value3',
+ 'custom_value4',
+ ],
+ ];
+
+ $designer = new Designer($modern, $input_variables);
+
+ $html = $designer->build();
+
+ $this->assertNotNull($html);
+
+ \Log::error($html);
+ }
+}
+
+
\ No newline at end of file