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

![v5-develop phpunit](https://github.com/invoiceninja/invoiceninja/workflows/phpunit/badge.svg?branch=v5-develop) -![v5-stable phpunit](https://github.com/invoiceninja/invoiceninja/workflows/phpunit/badge.svg?branch=v5-stable) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/d16c78aad8574466bf83232b513ef4fb)](https://www.codacy.com/gh/turbo124/invoiceninja/dashboard?utm_source=github.com&utm_medium=referral&utm_content=turbo124/invoiceninja&utm_campaign=Badge_Grade) CLA assistant 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 " {$qr}"; @@ -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