diff --git a/.github/workflows/react_release.yml b/.github/workflows/react_release.yml index 2c795b37ddc8..e152890d2a68 100644 --- a/.github/workflows/react_release.yml +++ b/.github/workflows/react_release.yml @@ -38,8 +38,6 @@ jobs: sudo php artisan cache:clear sudo find ./vendor/bin/ -type f -exec chmod +x {} \; sudo find ./ -type d -exec chmod 755 {} \; - sudo rm -f public/main.* - sudo rm -f public/flutter* - name: Prepare React FrontEnd run: | diff --git a/VERSION.txt b/VERSION.txt index 58bc1d26e206..bf55a892b987 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.8.46 \ No newline at end of file +5.8.47 \ No newline at end of file diff --git a/app/Helpers/Invoice/CustomValuer.php b/app/Helpers/Invoice/CustomValuer.php index e12df5bcf0da..90fad3481312 100644 --- a/app/Helpers/Invoice/CustomValuer.php +++ b/app/Helpers/Invoice/CustomValuer.php @@ -27,10 +27,28 @@ trait CustomValuer public function valuerTax($custom_value, $has_custom_invoice_taxes) { - if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes) { + + if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) { return round($custom_value * ($this->invoice->tax_rate1 / 100), 2) + round($custom_value * ($this->invoice->tax_rate2 / 100), 2) + round($custom_value * ($this->invoice->tax_rate3 / 100), 2); } return 0; } + + public function multiInclusiveTax($value, $has_custom_invoice_taxes) { + + if (isset($custom_value) && is_numeric($custom_value) && $has_custom_invoice_taxes !== false) { + + $tax = 0; + + $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate1 / 100))), 2); + $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate2 / 100))), 2); + $tax += $this->formatValue($custom_value - ($custom_value / (1 + ($this->invoice->tax_rate3 / 100))), 2); + + return round($tax,2); + } + + return 0; + + } } diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index aae9c0848198..ae366e931f7f 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -106,18 +106,20 @@ class InvoiceSumInclusive private function calculateCustomValues() { - $this->total_taxes += $this->valuerTax($this->invoice->custom_surcharge1, $this->invoice->custom_surcharge_tax1); + + $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge1, $this->invoice->custom_surcharge_tax1); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge1); - $this->total_taxes += $this->valuerTax($this->invoice->custom_surcharge2, $this->invoice->custom_surcharge_tax2); + $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge2, $this->invoice->custom_surcharge_tax2); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge2); - $this->total_taxes += $this->valuerTax($this->invoice->custom_surcharge3, $this->invoice->custom_surcharge_tax3); + $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge3, $this->invoice->custom_surcharge_tax3); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge3); - $this->total_taxes += $this->valuerTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4); + $this->total_taxes += $this->multiInclusiveTax($this->invoice->custom_surcharge4, $this->invoice->custom_surcharge_tax4); $this->total_custom_values += $this->valuer($this->invoice->custom_surcharge4); + $this->total += $this->total_custom_values; return $this; @@ -126,7 +128,7 @@ class InvoiceSumInclusive private function calculateInvoiceTaxes() { $amount = $this->total; - + if ($this->invoice->discount > 0 && $this->invoice->is_amount_discount) { $amount = $this->formatValue(($this->sub_total - $this->invoice->discount), 2); } @@ -135,6 +137,23 @@ class InvoiceSumInclusive $amount = $this->formatValue(($this->sub_total - ($this->sub_total * ($this->invoice->discount / 100))), 2); } + //Handles cases where the surcharge is not taxed + if(is_numeric($this->invoice->custom_surcharge1) && $this->invoice->custom_surcharge1 > 0 && $this->invoice->custom_surcharge_tax1) { + $amount += $this->invoice->custom_surcharge1; + } + + if(is_numeric($this->invoice->custom_surcharge2) && $this->invoice->custom_surcharge2 > 0 && $this->invoice->custom_surcharge_tax2) { + $amount += $this->invoice->custom_surcharge2; + } + + if(is_numeric($this->invoice->custom_surcharge3) && $this->invoice->custom_surcharge3 > 0 && $this->invoice->custom_surcharge_tax3) { + $amount += $this->invoice->custom_surcharge3; + } + + if(is_numeric($this->invoice->custom_surcharge4) && $this->invoice->custom_surcharge4 > 0 && $this->invoice->custom_surcharge_tax4) { + $amount += $this->invoice->custom_surcharge4; + } + if (is_string($this->invoice->tax_name1) && strlen($this->invoice->tax_name1) > 1) { $tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount); $this->total_taxes += $tax; @@ -354,7 +373,7 @@ class InvoiceSumInclusive $this->total_taxes += $total_line_tax; } - + return $this; } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index df5d6241cbe0..7dcca92df223 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -204,7 +204,11 @@ class Invoice extends BaseModel 'is_deleted' => 'bool', 'is_amount_discount' => 'bool', 'tax_data' => 'object', - 'partial_due_date' => 'date:Y-m-d' + 'partial_due_date' => 'date:Y-m-d', + 'custom_surcharge_tax1' => 'bool', + 'custom_surcharge_tax2' => 'bool', + 'custom_surcharge_tax3' => 'bool', + 'custom_surcharge_tax4' => 'bool', ]; protected $with = []; diff --git a/app/PaymentDrivers/StripePaymentDriver.php b/app/PaymentDrivers/StripePaymentDriver.php index 0c388230869e..ce5be245554a 100644 --- a/app/PaymentDrivers/StripePaymentDriver.php +++ b/app/PaymentDrivers/StripePaymentDriver.php @@ -685,7 +685,7 @@ class StripePaymentDriver extends BaseDriver //payment_intent.succeeded - this will confirm or cancel the payment if ($request->type === 'payment_intent.succeeded') { - PaymentIntentWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(5, 10))); + PaymentIntentWebhook::dispatch($request->data, $request->company_key, $this->company_gateway->id)->delay(now()->addSeconds(rand(10, 15))); return response()->json([], 200); } diff --git a/app/Services/EDocument/Standards/FatturaPA.php b/app/Services/EDocument/Standards/FatturaPA.php index e8c0ad2145c7..6c08be878ae7 100644 --- a/app/Services/EDocument/Standards/FatturaPA.php +++ b/app/Services/EDocument/Standards/FatturaPA.php @@ -19,37 +19,37 @@ use SimpleXMLElement; - - - IT - 01234567890 + // Transmission data + // Transmitter ID + IT //Country code + 01234567890 //Taxpayer code - 00001 - FPR12 - ABCDE1 + 00001 // Transmission progress + FPR12// Transmission format + ABCDE1// Receiver code - + //Seller/Provider - + //Buyer/Recipient - - - TD01 - EUR - 2023-04-21 - 1 + //General data + // Document general data + TD01// Document type + EUR// Currency + 2023-04-21// Date + 1// Number - + //Goods and services data - + //Payment data @@ -60,6 +60,20 @@ class FatturaPA extends AbstractService { private $xml; + //urn:cen.eu:en16931:2017#compliant#urn:fatturapa.gov.it:CIUS-IT:2.0.0 + //UFF001 + + /** + * File Types + * + * EI01 => FILE VUOTO + * EI02 => SERVIZIO NON DISPONIBILE + * EI03 => UTENTE NON ABILITATO + */ + + /** + * @param Invoice $invoice + */ public function __construct(public Invoice $invoice) { $this->xml = new SimpleXMLElement(''); diff --git a/app/Utils/SystemHealth.php b/app/Utils/SystemHealth.php index c862091c162e..a15c0991c7a2 100644 --- a/app/Utils/SystemHealth.php +++ b/app/Utils/SystemHealth.php @@ -201,11 +201,12 @@ class SystemHealth private static function simpleDbCheck(): bool { - $result = true; + $result = false; try { - $pdo = DB::connection()->getPdo(); + $result = DB::connection()->getPdo(); $result = true; + $result = DB::connection()->getDatabaseName() && strlen(DB::connection()->getDatabaseName()) > 1; } catch (Exception $e) { $result = false; } diff --git a/config/ninja.php b/config/ninja.php index 4c0e77a57d42..7391e7839f92 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -17,8 +17,8 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'), - 'app_version' => env('APP_VERSION', '5.8.46'), - 'app_tag' => env('APP_TAG', '5.8.46'), + 'app_version' => env('APP_VERSION', '5.8.47'), + 'app_tag' => env('APP_TAG', '5.8.47'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/database/migrations/2022_06_16_025156_add_react_switching_flag.php b/database/migrations/2022_06_16_025156_add_react_switching_flag.php index 3c807d7e417c..6db24aff8096 100644 --- a/database/migrations/2022_06_16_025156_add_react_switching_flag.php +++ b/database/migrations/2022_06_16_025156_add_react_switching_flag.php @@ -21,7 +21,7 @@ return new class extends Migration { public function up() { Schema::table('accounts', function (Blueprint $table) { - $table->boolean('set_react_as_default_ap')->default(0); + $table->boolean('set_react_as_default_ap')->default(1); }); } diff --git a/database/schema/mysql-schema.dump b/database/schema/mysql-schema.dump index 31efb3175efc..95262fb2134a 100644 --- a/database/schema/mysql-schema.dump +++ b/database/schema/mysql-schema.dump @@ -41,7 +41,7 @@ CREATE TABLE `accounts` ( `hosted_client_count` int(10) unsigned DEFAULT NULL, `hosted_company_count` int(10) unsigned DEFAULT NULL, `inapp_transaction_id` varchar(100) DEFAULT NULL, - `set_react_as_default_ap` tinyint(1) NOT NULL DEFAULT 0, + `set_react_as_default_ap` tinyint(1) NOT NULL DEFAULT 1, `is_flagged` tinyint(1) NOT NULL DEFAULT 0, `is_verified_account` tinyint(1) NOT NULL DEFAULT 0, `account_sms_verification_code` text DEFAULT NULL, diff --git a/public/build/assets/setup-66b6b3c0.js b/public/build/assets/setup-66b6b3c0.js new file mode 100644 index 000000000000..655b0c5f830c --- /dev/null +++ b/public/build/assets/setup-66b6b3c0.js @@ -0,0 +1,9 @@ +import{A as a}from"./index-08e160a7.js";import"./_commonjsHelpers-725317a4.js";/** + * Invoice Ninja (https://invoiceninja.com) + * + * @link https://github.com/invoiceninja/invoiceninja source repository + * + * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) + * + * @license https://www.elastic.co/licensing/elastic-license + */class c{constructor(){this.checkDbButton=document.getElementById("test-db-connection"),this.checkDbAlert=document.getElementById("database-response")}handleDatabaseCheck(){let e=document.querySelector("meta[name=setup-db-check]").content,t={};document.querySelector('input[name="db_host"]')&&(t={db_host:document.querySelector('input[name="db_host"]').value,db_port:document.querySelector('input[name="db_port"]').value,db_database:document.querySelector('input[name="db_database"]').value,db_username:document.querySelector('input[name="db_username"]').value,db_password:document.querySelector('input[name="db_password"]').value}),this.checkDbButton.disabled=!0,a.post(e,t).then(s=>{this.handleSuccess(this.checkDbAlert,"account-wrapper"),this.handleSuccess(this.checkDbAlert,"submit-wrapper")}).catch(s=>this.handleFailure(this.checkDbAlert,s.response.data.message)).finally(()=>this.checkDbButton.disabled=!1)}handleSuccess(e,t=null){e.classList.remove("alert-failure"),e.innerText="Success!",e.classList.add("alert-success"),t&&(document.getElementById(t).classList.remove("hidden"),document.getElementById(t).scrollIntoView({behavior:"smooth",block:"center"}))}handleFailure(e,t=null){e.classList.remove("alert-success"),e.innerText=t||"Oops, looks like something isn't correct!",e.classList.add("alert-failure")}handle(){this.checkDbButton.addEventListener("click",()=>this.handleDatabaseCheck())}}new c().handle(); diff --git a/public/build/assets/setup-81f58464.js b/public/build/assets/setup-81f58464.js deleted file mode 100644 index 002076d86658..000000000000 --- a/public/build/assets/setup-81f58464.js +++ /dev/null @@ -1,9 +0,0 @@ -import{A as s}from"./index-08e160a7.js";import"./_commonjsHelpers-725317a4.js";/** - * Invoice Ninja (https://invoiceninja.com) - * - * @link https://github.com/invoiceninja/invoiceninja source repository - * - * @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com) - * - * @license https://www.elastic.co/licensing/elastic-license - */class a{constructor(){this.checkDbButton=document.getElementById("test-db-connection"),this.checkDbAlert=document.getElementById("database-response"),this.checkSmtpButton=document.getElementById("test-smtp-connection"),this.checkSmtpAlert=document.getElementById("smtp-response"),this.checkPdfButton=document.getElementById("test-pdf"),this.checkPdfAlert=document.getElementById("test-pdf-response")}handleDatabaseCheck(){let t=document.querySelector("meta[name=setup-db-check]").content,e={};document.querySelector('input[name="db_host"]')&&(e={db_host:document.querySelector('input[name="db_host"]').value,db_port:document.querySelector('input[name="db_port"]').value,db_database:document.querySelector('input[name="db_database"]').value,db_username:document.querySelector('input[name="db_username"]').value,db_password:document.querySelector('input[name="db_password"]').value}),this.checkDbButton.disabled=!0,s.post(t,e).then(c=>this.handleSuccess(this.checkDbAlert,"mail-wrapper")).catch(c=>this.handleFailure(this.checkDbAlert,c.response.data.message)).finally(()=>this.checkDbButton.disabled=!1)}handleSmtpCheck(){let t=document.querySelector("meta[name=setup-email-check]").content,e={mail_driver:document.querySelector('select[name="mail_driver"]').value,mail_name:document.querySelector('input[name="mail_name"]').value,mail_address:document.querySelector('input[name="mail_address"]').value,mail_username:document.querySelector('input[name="mail_username"]').value,mail_host:document.querySelector('input[name="mail_host"]').value,mail_port:document.querySelector('input[name="mail_port"]').value,encryption:document.querySelector('select[name="encryption"]').value,mail_password:document.querySelector('input[name="mail_password"]').value};if(this.checkSmtpButton.disabled=!0,e.mail_driver==="log")return this.handleSuccess(this.checkSmtpAlert,"account-wrapper"),this.handleSuccess(this.checkSmtpAlert,"submit-wrapper"),this.checkSmtpButton.disabled=!1;s.post(t,e).then(c=>{this.handleSuccess(this.checkSmtpAlert,"account-wrapper"),this.handleSuccess(this.checkSmtpAlert,"submit-wrapper")}).catch(c=>this.handleFailure(this.checkSmtpAlert,c.response.data.message)).finally(()=>this.checkSmtpButton.disabled=!1)}handleTestPdfCheck(){let t=document.querySelector("meta[name=setup-pdf-check]").content;this.checkPdfButton.disabled=!0,s.post(t,{}).then(e=>{try{return this.handleSuccess(this.checkPdfAlert,"database-wrapper")}catch{this.handleSuccess(this.checkPdfAlert,"database-wrapper"),this.checkPdfAlert.textContent="Success! PDF was generated succesfully."}}).catch(e=>{console.log(e),this.handleFailure(this.checkPdfAlert)}).finally(()=>this.checkPdfButton.disabled=!1)}handleSuccess(t,e=null){t.classList.remove("alert-failure"),t.innerText="Success!",t.classList.add("alert-success"),e&&(document.getElementById(e).classList.remove("hidden"),document.getElementById(e).scrollIntoView({behavior:"smooth",block:"center"}))}handleFailure(t,e=null){t.classList.remove("alert-success"),t.innerText=e||"Oops, looks like something isn't correct!",t.classList.add("alert-failure")}handle(){this.checkDbButton.addEventListener("click",()=>this.handleDatabaseCheck()),this.checkSmtpButton.addEventListener("click",()=>this.handleSmtpCheck()),this.checkPdfButton.addEventListener("click",()=>this.handleTestPdfCheck())}}new a().handle(); diff --git a/public/build/manifest.json b/public/build/manifest.json index 4f05b9e18ed3..9c4d3986b548 100644 --- a/public/build/manifest.json +++ b/public/build/manifest.json @@ -231,7 +231,7 @@ "src": "resources/js/clients/statements/view.js" }, "resources/js/setup/setup.js": { - "file": "assets/setup-81f58464.js", + "file": "assets/setup-66b6b3c0.js", "imports": [ "_index-08e160a7.js", "__commonjsHelpers-725317a4.js" diff --git a/public/js/assets/admin-4ed993c7.js b/public/js/assets/admin-4ed993c7.js new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/public/js/assets/admin-4ed993c7.js @@ -0,0 +1 @@ + diff --git a/public/js/assets/app-2d547327.css b/public/js/assets/app-2d547327.css new file mode 100644 index 000000000000..a52103e7689e --- /dev/null +++ b/public/js/assets/app-2d547327.css @@ -0,0 +1 @@ +@tailwind base;@tailwind components;@tailwind utilities;.pagination{@apply flex items-center !important;}.pagination .page-link{@apply -mt-px border-t-2 border-transparent pt-4 px-4 inline-flex items-center text-sm leading-5 font-medium text-gray-500 transition ease-in-out duration-150 cursor-pointer !important;}.pagination .page-link:hover{@apply text-gray-700 border-gray-300 !important;}.pagination .page-link:focus{@apply outline-none text-gray-700 border-gray-400;}.pagination .active>span{@apply text-blue-600 border-blue-600 !important;} diff --git a/resources/js/setup/setup.js b/resources/js/setup/setup.js index ae4de35f835f..8c472cb81a83 100644 --- a/resources/js/setup/setup.js +++ b/resources/js/setup/setup.js @@ -14,12 +14,6 @@ class Setup { constructor() { this.checkDbButton = document.getElementById('test-db-connection'); this.checkDbAlert = document.getElementById('database-response'); - - this.checkSmtpButton = document.getElementById('test-smtp-connection'); - this.checkSmtpAlert = document.getElementById('smtp-response'); - - this.checkPdfButton = document.getElementById('test-pdf'); - this.checkPdfAlert = document.getElementById('test-pdf-response'); } handleDatabaseCheck() { @@ -42,78 +36,16 @@ class Setup { this.checkDbButton.disabled = true; Axios.post(url, data) - .then((response) => - this.handleSuccess(this.checkDbAlert, 'mail-wrapper') + .then((response) =>{ + this.handleSuccess(this.checkDbAlert, 'account-wrapper'); + this.handleSuccess(this.checkDbAlert, 'submit-wrapper'); + } ) .catch((e) => this.handleFailure(this.checkDbAlert, e.response.data.message) ).finally(() => this.checkDbButton.disabled = false); } - handleSmtpCheck() { - let url = document.querySelector('meta[name=setup-email-check]').content; - - let data = { - mail_driver: document.querySelector('select[name="mail_driver"]') - .value, - mail_name: document.querySelector('input[name="mail_name"]').value, - mail_address: document.querySelector('input[name="mail_address"]') - .value, - mail_username: document.querySelector('input[name="mail_username"]') - .value, - mail_host: document.querySelector('input[name="mail_host"]').value, - mail_port: document.querySelector('input[name="mail_port"]').value, - encryption: document.querySelector('select[name="encryption"]') - .value, - mail_password: document.querySelector('input[name="mail_password"]') - .value, - }; - - this.checkSmtpButton.disabled = true; - - if (data.mail_driver === 'log') { - this.handleSuccess(this.checkSmtpAlert, 'account-wrapper'); - this.handleSuccess(this.checkSmtpAlert, 'submit-wrapper'); - - return (this.checkSmtpButton.disabled = false); - } - - Axios.post(url, data) - .then((response) => { - this.handleSuccess(this.checkSmtpAlert, 'account-wrapper'); - this.handleSuccess(this.checkSmtpAlert, 'submit-wrapper'); - }) - .catch((e) => - this.handleFailure(this.checkSmtpAlert, e.response.data.message) - ) - .finally(() => (this.checkSmtpButton.disabled = false)); - } - - handleTestPdfCheck() { - let url = document.querySelector('meta[name=setup-pdf-check]').content; - this.checkPdfButton.disabled = true; - - Axios.post(url, {}) - .then((response) => { - try { - //let win = window.open(response.data.url, '_blank'); - //win.focus(); - - return this.handleSuccess( - this.checkPdfAlert, - 'database-wrapper' - ); - } catch (error) { - this.handleSuccess(this.checkPdfAlert, 'database-wrapper'); - this.checkPdfAlert.textContent = `Success! PDF was generated succesfully.`; - } - }) - .catch((error) => { - console.log(error); - this.handleFailure(this.checkPdfAlert); - }) - .finally(() => (this.checkPdfButton.disabled = false)); - } handleSuccess(element, nextStep = null) { element.classList.remove('alert-failure'); @@ -140,14 +72,6 @@ class Setup { this.checkDbButton.addEventListener('click', () => this.handleDatabaseCheck() ); - - this.checkSmtpButton.addEventListener('click', () => - this.handleSmtpCheck() - ); - - this.checkPdfButton.addEventListener('click', () => - this.handleTestPdfCheck() - ); } } diff --git a/resources/views/portal/ninja2020/layout/clean_setup.blade.php b/resources/views/portal/ninja2020/layout/clean_setup.blade.php index 8894872e218a..62d64724417a 100644 --- a/resources/views/portal/ninja2020/layout/clean_setup.blade.php +++ b/resources/views/portal/ninja2020/layout/clean_setup.blade.php @@ -96,9 +96,7 @@ @stack('head') @if(strpos(Request::url(),'setup')) - - @endif diff --git a/resources/views/setup/_application.blade.php b/resources/views/setup/_application.blade.php index de2d37c11282..e69de29bb2d1 100644 --- a/resources/views/setup/_application.blade.php +++ b/resources/views/setup/_application.blade.php @@ -1,58 +0,0 @@ -
-
-

- {{ ctrans('texts.application_settings') }} -

-

- {{ ctrans('texts.application_settings_label') }} -

-
-
-
-
-
- {{ ctrans('texts.url') }}* -
-
- - (including http:// or https://) -
-
-
-
- {{ ctrans('texts.https') }} -
-
- - {{ ctrans('texts.require') }} - ({{ ctrans('texts.recommended_in_production') }}) -
-
-
-
- {{ ctrans('texts.reports') }} -
-
- - {{ ctrans('texts.send_fail_logs_to_our_server') }} - Read more - about how we use this. -
-
-
-
- -
-
-
-
-
-
-
-
diff --git a/resources/views/setup/_database.blade.php b/resources/views/setup/_database.blade.php index c63487c33e35..6ff0e314e33d 100644 --- a/resources/views/setup/_database.blade.php +++ b/resources/views/setup/_database.blade.php @@ -1,4 +1,52 @@ -