From acf73fb6fd6b5347e2e6bd19036457194e755945 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 18 Jul 2024 12:21:24 +1000 Subject: [PATCH] DE solved! --- .../EDocument/Gateway/Storecove/Storecove.php | 2 + app/Services/EDocument/Standards/Peppol.php | 68 +++++- tests/Feature/EInvoice/PeppolTest.php | 125 +++++++++- .../Einvoice/Storecove/StorecoveTest.php | 231 +++++++++--------- 4 files changed, 292 insertions(+), 134 deletions(-) diff --git a/app/Services/EDocument/Gateway/Storecove/Storecove.php b/app/Services/EDocument/Gateway/Storecove/Storecove.php index c3a424799e7e..fe1d0bbc1fec 100644 --- a/app/Services/EDocument/Gateway/Storecove/Storecove.php +++ b/app/Services/EDocument/Gateway/Storecove/Storecove.php @@ -119,6 +119,8 @@ class Storecove { $uri = "document_submissions"; + nlog($payload); + $r = $this->httpClient($uri, (HttpVerb::POST)->value, $payload, $this->getHeaders()); nlog($r->body()); diff --git a/app/Services/EDocument/Standards/Peppol.php b/app/Services/EDocument/Standards/Peppol.php index 572f69212838..def2cee37bcd 100644 --- a/app/Services/EDocument/Standards/Peppol.php +++ b/app/Services/EDocument/Standards/Peppol.php @@ -11,11 +11,13 @@ namespace App\Services\EDocument\Standards; +use App\Models\Company; use App\Models\Invoice; use App\Services\AbstractService; use App\Helpers\Invoice\InvoiceSum; -use App\Helpers\Invoice\InvoiceSumInclusive; use InvoiceNinja\EInvoice\EInvoice; +use App\Helpers\Invoice\InvoiceSumInclusive; +use InvoiceNinja\EInvoice\Models\Peppol\PaymentMeans; use InvoiceNinja\EInvoice\Models\Peppol\ItemType\Item; use InvoiceNinja\EInvoice\Models\Peppol\PartyType\Party; use InvoiceNinja\EInvoice\Models\Peppol\PriceType\Price; @@ -24,9 +26,13 @@ use InvoiceNinja\EInvoice\Models\Peppol\ContactType\Contact; use InvoiceNinja\EInvoice\Models\Peppol\CountryType\Country; use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxAmount; use InvoiceNinja\EInvoice\Models\Peppol\TaxTotalType\TaxTotal; +use App\Services\EDocument\Standards\Settings\PropertyResolver; +use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PriceAmount; use InvoiceNinja\EInvoice\Models\Peppol\PartyNameType\PartyName; use InvoiceNinja\EInvoice\Models\Peppol\TaxSchemeType\TaxScheme; use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PayableAmount; +use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxableAmount; +use InvoiceNinja\EInvoice\Models\Peppol\TaxTotal as PeppolTaxTotal; use InvoiceNinja\EInvoice\Models\Peppol\InvoiceLineType\InvoiceLine; use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\TaxCategory; use InvoiceNinja\EInvoice\Models\Peppol\TaxSubtotalType\TaxSubtotal; @@ -34,13 +40,11 @@ use InvoiceNinja\EInvoice\Models\Peppol\TaxScheme as PeppolTaxScheme; use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxExclusiveAmount; use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxInclusiveAmount; use InvoiceNinja\EInvoice\Models\Peppol\AmountType\LineExtensionAmount; -use InvoiceNinja\EInvoice\Models\Peppol\AmountType\PriceAmount; -use InvoiceNinja\EInvoice\Models\Peppol\AmountType\TaxableAmount; use InvoiceNinja\EInvoice\Models\Peppol\MonetaryTotalType\LegalMonetaryTotal; use InvoiceNinja\EInvoice\Models\Peppol\TaxCategoryType\ClassifiedTaxCategory; use InvoiceNinja\EInvoice\Models\Peppol\CustomerPartyType\AccountingCustomerParty; use InvoiceNinja\EInvoice\Models\Peppol\SupplierPartyType\AccountingSupplierParty; -use InvoiceNinja\EInvoice\Models\Peppol\TaxTotal as PeppolTaxTotal; +use InvoiceNinja\EInvoice\Models\Peppol\FinancialAccountType\PayeeFinancialAccount; class Peppol extends AbstractService { @@ -59,16 +63,17 @@ class Peppol extends AbstractService "896" => "Debit note related to self-billed invoice" ]; - private \InvoiceNinja\EInvoice\Models\Peppol\Invoice $p_invoice; + private Company $company; private InvoiceSum | InvoiceSumInclusive $calc; /** * @param Invoice $invoice */ - public function __construct(public Invoice $invoice) + public function __construct(public Invoice $invoice, public ?\InvoiceNinja\EInvoice\Models\Peppol\Invoice $p_invoice = null) { - $this->p_invoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice(); + $this->p_invoice = $p_invoice ?? new \InvoiceNinja\EInvoice\Models\Peppol\Invoice(); + $this->company = $invoice->company; $this->calc = $this->invoice->calc(); } @@ -95,6 +100,7 @@ class Peppol extends AbstractService $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()) // ->setBankId($company->settings->custom_value1) @@ -107,6 +113,17 @@ class Peppol extends AbstractService } + private function getPaymentMeans(): PaymentMeans + { + // $payeeFinancialAccount = new PayeeFinancialAccount() + // $payeeFinancialAccount-> + + // $ppm = new PaymentMeans(); + // $ppm->PayeeFinancialAccount = $payeeFinancialAccount; + + // return $ppm; + } + private function getLegalMonetaryTotal(): LegalMonetaryTotal { $taxable = $this->getTaxable(); @@ -310,7 +327,7 @@ class Peppol extends AbstractService $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - $tax_amount->amount = round(($item->line_total * (1 / $item->tax_rate1)), 2); + $tax_amount->amount = round(($item->line_total * ($item->tax_rate1/100)), 2); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; @@ -339,7 +356,7 @@ class Peppol extends AbstractService $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - $tax_amount->amount = round(($item->line_total * (1 / $item->tax_rate2)), 2); + $tax_amount->amount = round(($item->line_total * ($item->tax_rate2/100)), 2); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; @@ -372,7 +389,7 @@ class Peppol extends AbstractService $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - $tax_amount->amount = round(($item->line_total * (1 / $item->tax_rate3)), 2); + $tax_amount->amount = round(($item->line_total * ($item->tax_rate3/100)), 2); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; @@ -520,4 +537,35 @@ class Peppol extends AbstractService return $total; } + public function setInvoiceDefaults(): self + { + $settings = [ + 'AccountingCostCode' => 7, + 'AccountingCost' => 7, + 'BuyerReference' => 6, + 'AccountingSupplierParty' => 1, + 'AccountingCustomerParty' => 2, + 'PayeeParty' => 1, + 'BuyerCustomerParty' => 2, + 'SellerSupplierParty' => 1, + 'TaxRepresentativeParty' => 1, + 'Delivery' => 1, + 'DeliveryTerms' => 7, + 'PaymentMeans' => 7, + 'PaymentTerms' => 7, + ]; + + foreach($settings as $prop => $visibility){ + + if($prop_value = PropertyResolver::resolve($this->invoice->client->e_invoice, $prop)) + $this->p_invoice->{$prop} = $prop_value; + elseif($prop_value = PropertyResolver::resolve($this->invoice->company->e_invoice, $prop)) { + $this->p_invoice->{$prop} = $prop_value; + } + + + } + + return $this; + } } diff --git a/tests/Feature/EInvoice/PeppolTest.php b/tests/Feature/EInvoice/PeppolTest.php index 2933d571d488..787ad6913e72 100644 --- a/tests/Feature/EInvoice/PeppolTest.php +++ b/tests/Feature/EInvoice/PeppolTest.php @@ -14,20 +14,23 @@ namespace Tests\Feature\EInvoice; use Tests\TestCase; use App\Models\Client; use App\Models\Company; +use App\Models\Invoice; use Tests\MockAccountData; +use App\DataMapper\InvoiceItem; use App\DataMapper\ClientSettings; use App\DataMapper\CompanySettings; -use App\DataMapper\InvoiceItem; -use App\Models\Invoice; +use InvoiceNinja\EInvoice\EInvoice; use InvoiceNinja\EInvoice\Symfony\Encode; -use App\Services\EDocument\Standards\FatturaPANew; use App\Services\EDocument\Standards\Peppol; +use App\Services\EDocument\Standards\FatturaPANew; use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\Foundation\Testing\DatabaseTransactions; -use InvoiceNinja\EInvoice\EInvoice; use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronica; +use InvoiceNinja\EInvoice\Models\Peppol\BranchType\FinancialInstitutionBranch; +use InvoiceNinja\EInvoice\Models\Peppol\FinancialAccountType\PayeeFinancialAccount; use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaBodyType\FatturaElettronicaBody; use InvoiceNinja\EInvoice\Models\FatturaPA\FatturaElettronicaHeaderType\FatturaElettronicaHeader; +use InvoiceNinja\EInvoice\Models\Peppol\PaymentMeans; /** * @test @@ -51,6 +54,120 @@ class PeppolTest extends TestCase ); } + public function testDeInvoice() + { + + $settings = CompanySettings::defaults(); + $settings->address1 = 'Dudweilerstr. 34b'; + $settings->city = 'Ost Alessa'; + $settings->state = 'Bayern'; + $settings->postal_code = '98060'; + $settings->vat_number = 'DE923356489'; + $settings->country_id = '276'; + $settings->currency_id = '3'; + + + $einvoice = new \InvoiceNinja\EInvoice\Models\Peppol\Invoice(); + + + $fib = new FinancialInstitutionBranch(); + $fib->ID = "DEUTDEMMXXX"; //BIC + $fib->Name = 'Deutsche Bank'; + + $pfa = new PayeeFinancialAccount(); + $pfa->ID = 'DE89370400440532013000'; + $pfa->Name = 'PFA-NAME'; + $pfa->AliasName = 'PFA-Alias'; + $pfa->AccountTypeCode = 'CHECKING'; + $pfa->AccountFormatCode = 'IBAN'; + $pfa->CurrencyCode = 'EUR'; + $pfa->FinancialInstitutionBranch = $fib; + + $pm = new PaymentMeans(); + $pm->PayeeFinancialAccount = $pfa; + $einvoice->PaymentMeans[] = $pm; + + $company = Company::factory()->create([ + 'account_id' => $this->account->id, + 'settings' => $settings, + 'e_invoice' => $einvoice, + ]); + + $client_settings = ClientSettings::defaults(); + $client_settings->currency_id = '3'; + + $client = Client::factory()->create([ + 'company_id' => $company->id, + 'user_id' => $this->user->id, + 'name' => 'German Client Name', + 'address1' => 'Kinderhausen 96b', + 'address2' => 'Apt. 842', + 'city' => 'Süd Jessestadt', + 'state' => 'Bayern', + 'postal_code' => '33323', + 'country_id' => 276, + 'routing_id' => 'ABC1234', + 'settings' => $client_settings, + ]); + + + $item = new InvoiceItem(); + $item->product_key = "Product Key"; + $item->notes = "Product Description"; + $item->cost = 10; + $item->quantity = 10; + $item->tax_rate1 = 19; + $item->tax_name1 = 'mwst'; + + $invoice = Invoice::factory()->create([ + 'company_id' => $company->id, + 'user_id' => $this->user->id, + 'client_id' => $client->id, + 'discount' => 0, + 'uses_inclusive_taxes' => false, + 'status_id' => 1, + 'tax_rate1' => 0, + 'tax_name1' => '', + 'tax_rate2' => 0, + 'tax_rate3' => 0, + 'tax_name2' => '', + 'tax_name3' => '', + 'line_items' => [$item], + 'number' => 'DE-'.rand(1000, 100000), + 'date' => now()->format('Y-m-d') + ]); + + $invoice = $invoice->calc()->getInvoice(); + $invoice->service()->markSent()->save(); + + $this->assertEquals(119, $invoice->amount); + + + $peppol = new Peppol($invoice); + $peppol->setInvoiceDefaults(); + $peppol->run(); + + $de_invoice = $peppol->getInvoice(); + + $this->assertNotNull($de_invoice); + + $e = new EInvoice(); + $xml = $e->encode($de_invoice, 'xml'); + $this->assertNotNull($xml); + + nlog($xml); + + $errors = $e->validate($de_invoice); + + if(count($errors) > 0) { + nlog($errors); + } + + $this->assertCount(0, $errors); + + + } + public function testInvoiceBoot() { diff --git a/tests/Integration/Einvoice/Storecove/StorecoveTest.php b/tests/Integration/Einvoice/Storecove/StorecoveTest.php index 2bd38ec13141..ab732d73af59 100644 --- a/tests/Integration/Einvoice/Storecove/StorecoveTest.php +++ b/tests/Integration/Einvoice/Storecove/StorecoveTest.php @@ -105,126 +105,117 @@ class StorecoveTest extends TestCase $x = ' - - 0061 - 2024-07-15 - 380 - - - - Eladio Ullrich I - - - Jasper Brook - Kodychester - 73445-5131 - South Dakota - - AT - - - - Jasper Brook - Kodychester - 73445-5131 - South Dakota - - AT - - - - small@example.com - - - - - - - Beispiel GmbH - - - 45 Hauptstraße - Berlin - 10115 - Berlin - - DE - - - - 45 Hauptstraße - Berlin - 10115 - Berlin - - DE - - - - TTKGjKW9Rv00LEr@example.com - - - - - - 215 - 215 - 215.00 - 215.00 - - - 1 - 1 - 10 - - 0.5 - - 10 - 0.5 - - C62 - 20 - - USt - - - - - - The Pro Plan NO MORE - ee - - - 10 - - - - 2 - 1 - 14 - - The Enterprise Plan - eee - - - 14 - - - - 3 - 1 - 191 - - Soluta provident. - k - - - 191 - - '; + + DE-77323 + 2024-07-18 + 380 + + + + Untitled Company + + + Dudweilerstr. 34b + Ost Alessa + 98060 + Bayern + + DE + + + + Dudweilerstr. 34b + Ost Alessa + 98060 + Bayern + + DE + + + + owner@gmail.com + + + + + + + German Client Name + + + Kinderhausen 96b + Süd Jessestadt + 33323 + Bayern + + DE + + + + Kinderhausen 96b + Süd Jessestadt + 33323 + Bayern + + DE + + + + No Email Set + + + + + + DE89370400440532013000 + PFA-NAME + PFA-Alias + CHECKING + IBAN + EUR + + DEUTDEMMXXX + Deutsche Bank + + + + + + 100 + 100 + 119.00 + 119.00 + + + 1 + 10 + 100 + + 19 + + 100 + 19 + + C62 + 19 + + mwst + + + + + + Product Description + Product Key + + + 10 + + + '; $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove(); $sc->sendDocument($x);