diff --git a/README.md b/README.md
index f39a66f367e1..190d4b7be602 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@

-
[](https://www.codacy.com/gh/turbo124/invoiceninja/dashboard?utm_source=github.com&utm_medium=referral&utm_content=turbo124/invoiceninja&utm_campaign=Badge_Grade)
diff --git a/app/Helpers/Epc/EpcQrGenerator.php b/app/Helpers/Epc/EpcQrGenerator.php
index adf36dc83887..457fb24550d3 100644
--- a/app/Helpers/Epc/EpcQrGenerator.php
+++ b/app/Helpers/Epc/EpcQrGenerator.php
@@ -45,8 +45,12 @@ class EpcQrGenerator
);
$writer = new Writer($renderer);
+ $this->validateFields();
+
$qr = $writer->writeString($this->encodeMessage());
+ nlog($qr);
+
return "";
@@ -60,9 +64,9 @@ class EpcQrGenerator
sprintf('%03d', $this->sepa['version']),
$this->sepa['characterSet'],
$this->sepa['identification'],
- $this->sepa['bic'],
+ isset($this->company?->custom_fields?->company2) ? $this->company->settings->custom_value2 : '',
$this->company->present()->name(),
- $this->company?->custom_fields?->company1 ?: '',
+ isset($this->company?->custom_fields?->company1) ? $this->company->settings->custom_value1 : '',
$this->formatMoney($this->amount),
$this->sepa['purpose'],
substr($this->invoice->number,0,34),
@@ -72,6 +76,17 @@ class EpcQrGenerator
}
+ private function validateFields()
+ {
+
+ if(isset($this->company?->custom_fields?->company2))
+ nlog('The BIC field is not present and _may_ be a required fields for EPC QR codes');
+
+ if(isset($this->company?->custom_fields?->company1))
+ nlog('The IBAN field is required');
+
+ }
+
private function formatMoney($value) {
return sprintf('EUR%s', number_format($value, 2, '.', ''));
}
diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php
index 6a7b89d56045..991489968dc4 100644
--- a/app/Http/Controllers/BaseController.php
+++ b/app/Http/Controllers/BaseController.php
@@ -996,6 +996,42 @@ class BaseController extends Controller
return redirect('/setup');
}
+ public function reactCatch()
+ {
+
+ if ((bool) $this->checkAppSetup() !== false && $account = Account::first()) {
+ if (config('ninja.require_https') && ! request()->isSecure()) {
+ return redirect()->secure(request()->getRequestUri());
+ }
+
+ $data = [];
+
+ //pass report errors bool to front end
+ $data['report_errors'] = Ninja::isSelfHost() ? $account->report_errors : true;
+
+ //pass referral code to front end
+ $data['rc'] = request()->has('rc') ? request()->input('rc') : '';
+ $data['build'] = request()->has('build') ? request()->input('build') : '';
+ $data['login'] = request()->has('login') ? request()->input('login') : 'false';
+ $data['signup'] = request()->has('signup') ? request()->input('signup') : 'false';
+
+ $data['user_agent'] = request()->server('HTTP_USER_AGENT');
+
+ $data['path'] = $this->setBuild();
+
+ $this->buildCache();
+
+ if (Ninja::isSelfHost() && $account->set_react_as_default_ap) {
+ return view('react.index', $data);
+ } else {
+ abort('page not found', 404);
+ }
+ }
+
+ return redirect('/setup');
+ }
+
+
private function setBuild()
{
$build = '';
diff --git a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php
index 0a719fbc308a..e22ae36fe2d8 100644
--- a/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php
+++ b/app/Http/Requests/RecurringInvoice/UpdateRecurringInvoiceRequest.php
@@ -90,7 +90,7 @@ class UpdateRecurringInvoiceRequest extends Request
if (isset($input['invitations'])) {
foreach ($input['invitations'] as $key => $value) {
- if (is_numeric($input['invitations'][$key]['id'])) {
+ if (isset($input['invitations'][$key]['id']) && is_numeric($input['invitations'][$key]['id'])) {
unset($input['invitations'][$key]['id']);
}
diff --git a/app/Repositories/BaseRepository.php b/app/Repositories/BaseRepository.php
index 127387abbfff..4d9451dcf83a 100644
--- a/app/Repositories/BaseRepository.php
+++ b/app/Repositories/BaseRepository.php
@@ -280,7 +280,7 @@ class BaseRepository
$model = $model->service()->applyNumber()->save();
/* Handle attempts where the deposit is greater than the amount/balance of the invoice */
- if((int)$model->balance != 0 && $model->partial > $model->amount)
+ if((int)$model->balance != 0 && $model->partial > $model->amount && $model->amount > 0)
$model->partial = min($model->amount, $model->balance);
/* Update product details if necessary - if we are inside a transaction - do nothing */
diff --git a/app/Transformers/VendorContactTransformer.php b/app/Transformers/VendorContactTransformer.php
index dbbdf6daedc4..5524cac59102 100644
--- a/app/Transformers/VendorContactTransformer.php
+++ b/app/Transformers/VendorContactTransformer.php
@@ -32,6 +32,7 @@ class VendorContactTransformer extends EntityTransformer
'id' => $this->encodePrimaryKey($vendor->id),
'first_name' => $vendor->first_name ?: '',
'last_name' => $vendor->last_name ?: '',
+ 'send_email' => (bool)$vendor->send_email,
'email' => $vendor->email ?: '',
'created_at' => (int) $vendor->created_at,
'updated_at' => (int) $vendor->updated_at,
diff --git a/app/Utils/HtmlEngine.php b/app/Utils/HtmlEngine.php
index f800b6db41a5..a022d5e1642e 100644
--- a/app/Utils/HtmlEngine.php
+++ b/app/Utils/HtmlEngine.php
@@ -12,6 +12,7 @@
namespace App\Utils;
+use App\Helpers\Epc\EpcQrGenerator;
use App\Helpers\SwissQr\SwissQrGenerator;
use App\Models\Country;
use App\Models\CreditInvitation;
@@ -581,6 +582,11 @@ class HtmlEngine
$data['$payments'] = ['value' => $payment_list, 'label' => ctrans('texts.payments')];
}
+ if($this->entity_string == 'invoice' && isset($this->company?->custom_fields?->company1))
+ {
+ $data['$sepa_qr_code'] = ['value' => (new EpcQrGenerator($this->company, $this->entity,$data['$amount_raw']['value']))->getQrCode(), 'label' => ''];
+ }
+
$arrKeysLength = array_map('strlen', array_keys($data));
array_multisort($arrKeysLength, SORT_DESC, $data);
diff --git a/package-lock.json b/package-lock.json
index a4aa03e29039..ed68ecd984a3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,7 +6,7 @@
"": {
"dependencies": {
"autoprefixer": "^10.3.7",
- "axios": "^0.24.0",
+ "axios": "^0.25",
"card-js": "^1.0.13",
"card-validator": "^8.1.1",
"clipboard": "^2.0.10",
@@ -2367,11 +2367,11 @@
}
},
"node_modules/axios": {
- "version": "0.24.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
- "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
+ "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"dependencies": {
- "follow-redirects": "^1.14.4"
+ "follow-redirects": "^1.14.7"
}
},
"node_modules/babel-loader": {
@@ -10890,11 +10890,11 @@
}
},
"axios": {
- "version": "0.24.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
- "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
+ "integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
"requires": {
- "follow-redirects": "^1.14.4"
+ "follow-redirects": "^1.14.7"
}
},
"babel-loader": {
diff --git a/resources/views/react/head.blade.php b/resources/views/react/head.blade.php
index 3c3109448361..5aac20938bba 100644
--- a/resources/views/react/head.blade.php
+++ b/resources/views/react/head.blade.php
@@ -1,207 +1,227 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/routes/web.php b/routes/web.php
index fc04c0a72f0f..9e5d3bf5fb0f 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -59,3 +59,5 @@ Route::get('checkout/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', [C
Route::get('mollie/3ds_redirect/{company_key}/{company_gateway_id}/{hash}', [Mollie3dsController::class, 'index'])->middleware('domain_db')->name('mollie.3ds_redirect');
Route::get('gocardless/ibp_redirect/{company_key}/{company_gateway_id}/{hash}', [GoCardlessController::class, 'ibpRedirect'])->middleware('domain_db')->name('gocardless.ibp_redirect');
Route::get('.well-known/apple-developer-merchantid-domain-association', [ApplePayDomainController::class, 'showAppleMerchantId']);
+
+Route::fallback([BaseController::class, 'reactCatch']);
\ No newline at end of file