From a236da0149ae7bac5023efed7a2aeebaf4c81075 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Mon, 22 Jul 2024 19:31:19 +1000 Subject: [PATCH] v5.10.13 --- VERSION.txt | 2 +- app/Console/Commands/CreateSingleAccount.php | 43 ++++++++++++ app/Services/EDocument/Standards/Peppol.php | 67 ++++++++++++++++--- composer.json | 6 +- composer.lock | 49 ++++++++------ config/ninja.php | 4 +- .../Einvoice/Storecove/StorecoveTest.php | 45 ++++++++++++- tests/MockAccountData.php | 1 + 8 files changed, 182 insertions(+), 35 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 645ef4b267..d315f4df75 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.10.12 \ No newline at end of file +5.10.13 \ No newline at end of file diff --git a/app/Console/Commands/CreateSingleAccount.php b/app/Console/Commands/CreateSingleAccount.php index 50d915cca2..4a2146a334 100644 --- a/app/Console/Commands/CreateSingleAccount.php +++ b/app/Console/Commands/CreateSingleAccount.php @@ -385,6 +385,9 @@ class CreateSingleAccount extends Command }); + + $this->countryClients($company, $user); + $this->info("finished"); } @@ -1109,4 +1112,44 @@ class CreateSingleAccount extends Command event(new RecurringInvoiceWasCreated($invoice, $invoice->company, Ninja::eventVars())); } + + + private function countryClients($company, $user) + { + + Client::unguard(); + + Client::create([ + 'company_id' => $company->id, + 'user_id' => $user->id, + 'name' => 'Swiss Company AG', + 'website' => 'https://www.testcompany.ch', + 'private_notes' => 'These are some private notes about the test client.', + 'balance' => 0, + 'paid_to_date' => 0, + 'vat_number' => '654321987', + 'id_number' => 'CH9300762011623852957', // Sample Swiss IBAN + 'custom_value1' => '2024-07-22 10:00:00', + 'custom_value2' => 'blue', + 'custom_value3' => 'sampleword', + 'custom_value4' => 'test@example.com', + 'address1' => '123', + 'address2' => 'Test Street 45', + 'city' => 'Zurich', + 'state' => 'Zurich', + 'postal_code' => '8001', + 'country_id' => '756', // Switzerland + 'shipping_address1' => '123', + 'shipping_address2' => 'Test Street 45', + 'shipping_city' => 'Zurich', + 'shipping_state' => 'Zurich', + 'shipping_postal_code' => '8001', + 'shipping_country_id' => '756', // Switzerland + 'settings' => ClientSettings::Defaults(), + 'client_hash' => \Illuminate\Support\Str::random(32), + 'routing_id' => '', + ]); + + } + } diff --git a/app/Services/EDocument/Standards/Peppol.php b/app/Services/EDocument/Standards/Peppol.php index 99e6753aea..0fe4cf5d18 100644 --- a/app/Services/EDocument/Standards/Peppol.php +++ b/app/Services/EDocument/Standards/Peppol.php @@ -75,7 +75,7 @@ class Peppol extends AbstractService 'US' => 'EIN', 'US' => 'SSN', 'NZ' => 'GST', - 'CH' => 'VAT', + 'CH' => 'VAT', // VAT number = CHE - 999999999 - MWST|IVA|VAT 'IS' => 'VAT', 'LI' => 'VAT', 'NO' => 'VAT', @@ -85,6 +85,12 @@ class Peppol extends AbstractService 'BA' => 'VAT', 'BE' => 'VAT', 'BG' => 'VAT', + 'AU' => 'ABN', //Australia + 'CA' => 'CBN', //Canada + 'MX' => 'RFC', //Mexico + 'NZ' => 'GST', //Nuuu zulund + 'GB' => 'VAT', //Great Britain + 'SA' => 'TIN', //South Africa 'CY' => 'VAT', 'CZ' => 'VAT', 'DE' => 'VAT', //tested - requires Payment Means to be defined. @@ -175,8 +181,10 @@ class Peppol extends AbstractService $this->p_invoice->AccountingSupplierParty = $this->getAccountingSupplierParty(); $this->p_invoice->AccountingCustomerParty = $this->getAccountingCustomerParty(); $this->p_invoice->InvoiceLine = $this->getInvoiceLines(); + $this->p_invoice->TaxTotal = $this->getTotalTaxes(); $this->p_invoice->LegalMonetaryTotal = $this->getLegalMonetaryTotal(); + // $this->p_invoice->PaymentMeans = $this->getPaymentMeans(); // $payeeFinancialAccount = (new PayeeFinancialAccount()) @@ -191,8 +199,8 @@ class Peppol extends AbstractService } - private function getPaymentMeans(): PaymentMeans - { + // private function getPaymentMeans(): PaymentMeans + // { // $payeeFinancialAccount = new PayeeFinancialAccount() // $payeeFinancialAccount-> @@ -200,7 +208,7 @@ class Peppol extends AbstractService // $ppm->PayeeFinancialAccount = $payeeFinancialAccount; // return $ppm; - } + // } private function getLegalMonetaryTotal(): LegalMonetaryTotal { @@ -231,6 +239,16 @@ class Peppol extends AbstractService return $lmt; } + private function getTotalTaxAmount(): float + { + if(!$this->invoice->total_taxes) + return 0; + elseif($this->invoice->uses_inclusive_taxes) + return $this->invoice->total_taxes; + + return $this->calcAmountLineTax($this->invoice->tax_rate1, $this->invoice->amount) ?? 0; + } + private function getTotalTaxes(): array { $taxes = []; @@ -241,8 +259,7 @@ class Peppol extends AbstractService $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - // $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($this->invoice->tax_rate1, $this->invoice->amount) : $this->calcAmountLineTax($this->invoice->tax_rate1, $this->invoice->amount); - $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->invoice->total_taxes : $this->calcAmountLineTax($this->invoice->tax_rate1, $this->invoice->amount); + $tax_amount->amount = $this->getTotalTaxAmount(); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; @@ -256,7 +273,7 @@ class Peppol extends AbstractService $tc->ID = $type_id == '2' ? 'HUR' : 'C62'; $tc->Percent = $this->invoice->tax_rate1; $ts = new PeppolTaxScheme(); - $ts->ID = $this->invoice->tax_name1; + $ts->ID = strlen($this->invoice->tax_name1 ?? '') > 1 ? $this->invoice->tax_name1 : '0'; $tc->TaxScheme = $ts; $tax_subtotal->TaxCategory = $tc; @@ -363,6 +380,9 @@ class Peppol extends AbstractService if(count($item_taxes) > 0) { $line->TaxTotal = $item_taxes; } + // else { + // $line->TaxTotal = $this->zeroTaxAmount(); + // } $price = new Price(); $pa = new PriceAmount(); @@ -393,6 +413,37 @@ class Peppol extends AbstractService return $cost; } + private function zeroTaxAmount(): array + { + $blank_tax = []; + + $tax_amount = new TaxAmount(); + $tax_amount->currencyID = $this->invoice->client->currency()->code; + $tax_amount->amount = '0'; + $tax_subtotal = new TaxSubtotal(); + $tax_subtotal->TaxAmount = $tax_amount; + + $taxable_amount = new TaxableAmount(); + $taxable_amount->currencyID = $this->invoice->client->currency()->code; + $taxable_amount->amount = '0'; + $tax_subtotal->TaxableAmount = $taxable_amount; + $tc = new TaxCategory(); + $tc->ID = 'Z'; + $tc->Percent = 0; + $ts = new PeppolTaxScheme(); + $ts->ID = '0'; + $tc->TaxScheme = $ts; + $tax_subtotal->TaxCategory = $tc; + + $tax_total = new TaxTotal(); + $tax_total->TaxAmount = $tax_amount; + $tax_total->TaxSubtotal[] = $tax_subtotal; + $blank_tax[] = $tax_total; + + + return $blank_tax; + } + private function getItemTaxes(object $item): array { $item_taxes = []; @@ -541,7 +592,7 @@ $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiv $pi = new PartyIdentification; $vatID = new ID; - $vatID->schemeID = 'IT:VAT'; + $vatID->schemeID = 'CH:MWST'; $vatID->value = $this->invoice->client->vat_number; $pi->ID = $vatID; diff --git a/composer.json b/composer.json index 49afd89e94..ad25d17058 100644 --- a/composer.json +++ b/composer.json @@ -41,7 +41,7 @@ "authorizenet/authorizenet": "^2.0", "awobaz/compoships": "^2.1", "bacon/bacon-qr-code": "^2.0", - "beganovich/snappdf": "^5", + "beganovich/snappdf": "dev-master", "braintree/braintree_php": "^6.0", "btcpayserver/btcpayserver-greenfield-php": "^2.6", "checkout/checkout-sdk-php": "^3.0", @@ -194,6 +194,10 @@ { "type": "vcs", "url": "https://github.com/beganovich/php-ansible" + }, + { + "type": "vcs", + "url": "https://github.com/turbo124/snappdf" } ], "minimum-stability": "dev", diff --git a/composer.lock b/composer.lock index 0037775a98..541f0c0452 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7c67ca71986b97fc72bba5eba530e878", + "content-hash": "edc6905124cb32fef6a13befb3d5a4e1", "packages": [ { "name": "adrienrn/php-mimetyper", @@ -684,16 +684,16 @@ }, { "name": "beganovich/snappdf", - "version": "v5.0", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/beganovich/snappdf.git", - "reference": "3b21c7a88a4d05b01a606bc74f1950b0e9e820b1" + "url": "https://github.com/turbo124/snappdf.git", + "reference": "adadaf593dca174db46efa139bdff844b3a64da8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/beganovich/snappdf/zipball/3b21c7a88a4d05b01a606bc74f1950b0e9e820b1", - "reference": "3b21c7a88a4d05b01a606bc74f1950b0e9e820b1", + "url": "https://api.github.com/repos/turbo124/snappdf/zipball/adadaf593dca174db46efa139bdff844b3a64da8", + "reference": "adadaf593dca174db46efa139bdff844b3a64da8", "shasum": "" }, "require": { @@ -708,6 +708,7 @@ "friendsofphp/php-cs-fixer": "^3.6", "phpunit/phpunit": "^11.0" }, + "default-branch": true, "bin": [ "snappdf" ], @@ -717,7 +718,11 @@ "Beganovich\\Snappdf\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", + "autoload-dev": { + "psr-4": { + "Test\\Snappdf\\": "tests/" + } + }, "license": [ "MIT" ], @@ -729,10 +734,9 @@ ], "description": "Convert webpages or HTML into the PDF file using Chromium or Google Chrome.", "support": { - "issues": "https://github.com/beganovich/snappdf/issues", - "source": "https://github.com/beganovich/snappdf/tree/v5.0" + "source": "https://github.com/turbo124/snappdf/tree/master" }, - "time": "2024-03-20T22:03:41+00:00" + "time": "2024-07-22T09:26:26+00:00" }, { "name": "braintree/braintree_php", @@ -18944,16 +18948,16 @@ }, { "name": "spatie/backtrace", - "version": "1.6.1", + "version": "1.6.2", "source": { "type": "git", "url": "https://github.com/spatie/backtrace.git", - "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23" + "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/backtrace/zipball/8373b9d51638292e3bfd736a9c19a654111b4a23", - "reference": "8373b9d51638292e3bfd736a9c19a654111b4a23", + "url": "https://api.github.com/repos/spatie/backtrace/zipball/1a9a145b044677ae3424693f7b06479fc8c137a9", + "reference": "1a9a145b044677ae3424693f7b06479fc8c137a9", "shasum": "" }, "require": { @@ -18991,7 +18995,7 @@ "spatie" ], "support": { - "source": "https://github.com/spatie/backtrace/tree/1.6.1" + "source": "https://github.com/spatie/backtrace/tree/1.6.2" }, "funding": [ { @@ -19003,20 +19007,20 @@ "type": "other" } ], - "time": "2024-04-24T13:22:11+00:00" + "time": "2024-07-22T08:21:24+00:00" }, { "name": "spatie/error-solutions", - "version": "1.0.5", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/spatie/error-solutions.git", - "reference": "4bb6c734dc992b2db3e26df1ef021c75d2218b13" + "reference": "a014da18f2675ea15af0ba97f7e9aee59e13964f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/error-solutions/zipball/4bb6c734dc992b2db3e26df1ef021c75d2218b13", - "reference": "4bb6c734dc992b2db3e26df1ef021c75d2218b13", + "url": "https://api.github.com/repos/spatie/error-solutions/zipball/a014da18f2675ea15af0ba97f7e9aee59e13964f", + "reference": "a014da18f2675ea15af0ba97f7e9aee59e13964f", "shasum": "" }, "require": { @@ -19069,7 +19073,7 @@ ], "support": { "issues": "https://github.com/spatie/error-solutions/issues", - "source": "https://github.com/spatie/error-solutions/tree/1.0.5" + "source": "https://github.com/spatie/error-solutions/tree/1.1.0" }, "funding": [ { @@ -19077,7 +19081,7 @@ "type": "github" } ], - "time": "2024-07-09T12:13:32+00:00" + "time": "2024-07-22T08:18:22+00:00" }, { "name": "spatie/flare-client-php", @@ -19577,6 +19581,7 @@ "minimum-stability": "dev", "stability-flags": { "asm/php-ansible": 20, + "beganovich/snappdf": 20, "horstoeko/orderx": 20, "invoiceninja/einvoice": 20, "socialiteproviders/apple": 20 diff --git a/config/ninja.php b/config/ninja.php index 44f971416b..c832656df1 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.10.12'), - 'app_tag' => env('APP_TAG', '5.10.12'), + 'app_version' => env('APP_VERSION', '5.10.13'), + 'app_tag' => env('APP_TAG', '5.10.13'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/tests/Integration/Einvoice/Storecove/StorecoveTest.php b/tests/Integration/Einvoice/Storecove/StorecoveTest.php index 9b3178a44b..f37af88946 100644 --- a/tests/Integration/Einvoice/Storecove/StorecoveTest.php +++ b/tests/Integration/Einvoice/Storecove/StorecoveTest.php @@ -11,6 +11,8 @@ namespace Tests\Integration\Einvoice\Storecove; +use App\DataMapper\ClientSettings; +use App\Models\Client; use Tests\TestCase; use Tests\MockAccountData; use Illuminate\Foundation\Testing\DatabaseTransactions; @@ -64,7 +66,7 @@ class StorecoveTest extends TestCase // { // $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove(); - // $r = $sc->addIdentifier(290868, "DE923356489", "DE:VAT"); + // $r = $sc->addIdentifier(291394, "DE923356489", "DE:VAT"); // nlog($r); @@ -347,4 +349,45 @@ $x = ' } + public function testCreateCHClient() + { + + Client::unguard(); + + $c = + Client::create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'name' => 'Test Company AG', + 'website' => 'https://www.testcompany.ch', + 'private_notes' => 'These are some private notes about the test client.', + 'balance' => 0, + 'paid_to_date' => 0, + 'vat_number' => '654321987', + 'id_number' => 'CH9300762011623852957', // Sample Swiss IBAN + 'custom_value1' => '2024-07-22 10:00:00', + 'custom_value2' => 'blue', + 'custom_value3' => 'sampleword', + 'custom_value4' => 'test@example.com', + 'address1' => '123', + 'address2' => 'Test Street 45', + 'city' => 'Zurich', + 'state' => 'Zurich', + 'postal_code' => '8001', + 'country_id' => '756', // Switzerland + 'shipping_address1' => '123', + 'shipping_address2' => 'Test Street 45', + 'shipping_city' => 'Zurich', + 'shipping_state' => 'Zurich', + 'shipping_postal_code' => '8001', + 'shipping_country_id' => '756', // Switzerland + 'settings' => ClientSettings::Defaults(), + 'client_hash' => \Illuminate\Support\Str::random(32), + 'routing_id' => '', + ]); + + + $this->assertInstanceOf(\App\Models\Client::class, $c); + + } } diff --git a/tests/MockAccountData.php b/tests/MockAccountData.php index c2d047d2fe..4229db6ebc 100644 --- a/tests/MockAccountData.php +++ b/tests/MockAccountData.php @@ -848,4 +848,5 @@ trait MockAccountData return $line_items; } + }