diff --git a/VERSION.txt b/VERSION.txt index 576f92a4fe93..e9ea7868d298 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.10.10 \ No newline at end of file +5.10.11 \ No newline at end of file diff --git a/app/Http/Requests/Email/SendEmailRequest.php b/app/Http/Requests/Email/SendEmailRequest.php index c9ab8aff95f5..60d82aec59a6 100644 --- a/app/Http/Requests/Email/SendEmailRequest.php +++ b/app/Http/Requests/Email/SendEmailRequest.php @@ -94,7 +94,7 @@ class SendEmailRequest extends Request $this->entity_plural = Str::plural($input['entity']) ?? ''; - if (isset($input['entity'])) { + if (isset($input['entity']) && in_array($input['entity'], ['invoice','quote','credit','recurring_invoice','purchase_order','payment'])) { $input['entity'] = "App\Models\\".ucfirst(Str::camel($input['entity'])); } diff --git a/app/Services/EDocument/Gateway/Storecove/Storecove.php b/app/Services/EDocument/Gateway/Storecove/Storecove.php index 5527b4482f7e..fe1d0bbc1fec 100644 --- a/app/Services/EDocument/Gateway/Storecove/Storecove.php +++ b/app/Services/EDocument/Gateway/Storecove/Storecove.php @@ -103,24 +103,24 @@ class Storecove { $payload = [ "legalEntityId"=> 290868, "idempotencyGuid"=> \Illuminate\Support\Str::uuid(), - "routing"=> [ - "eIdentifiers" => [ - [ - "scheme" => "DE:VAT", - "id"=> "DE:VAT" - ], - ] + "routing" => [ + "eIdentifiers" => [], + "emails" => ["david@invoiceninja.com"] ], "document"=> [ 'documentType' => 'invoice', - 'rawDocumentData' => ['document' => base64_encode($document), 'parse' => true, 'parseStrategy', 'ubl'], - // - // ' + "rawDocumentData"=> [ + "document" => base64_encode($document), + "parse" => true, + "parseStrategy"=> "ubl", + ], ], ]; $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..8387a799e4ad 100644 --- a/app/Services/EDocument/Standards/Peppol.php +++ b/app/Services/EDocument/Standards/Peppol.php @@ -11,11 +11,14 @@ 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 App\Helpers\Invoice\Taxer; +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 +27,14 @@ 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 App\Utils\Traits\NumberFormatter; +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,16 +42,17 @@ 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 { + use Taxer; + use NumberFormatter; + private array $InvoiceTypeCodes = [ "380" => "Commercial invoice", "381" => "Credit note", @@ -59,16 +68,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 +105,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 +118,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(); @@ -115,12 +137,12 @@ class Peppol extends AbstractService $lea = new LineExtensionAmount(); $lea->currencyID = $this->invoice->client->currency()->code; - $lea->amount = $taxable; + $lea->amount = $this->invoice->uses_inclusive_taxes ? round($this->invoice->amount - $this->invoice->total_taxes, 2) : $taxable; $lmt->LineExtensionAmount = $lea; $tea = new TaxExclusiveAmount(); $tea->currencyID = $this->invoice->client->currency()->code; - $tea->amount = $taxable; + $tea->amount = $this->invoice->uses_inclusive_taxes ? round($this->invoice->amount - $this->invoice->total_taxes,2) : $taxable; $lmt->TaxExclusiveAmount = $tea; $tia = new TaxInclusiveAmount(); @@ -142,23 +164,21 @@ class Peppol extends AbstractService $type_id = $this->invoice->line_items[0]->type_id; - if(strlen($this->invoice->tax_name1 ?? '') > 1) { + // if(strlen($this->invoice->tax_name1 ?? '') > 1) { $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - $tax_amount->amount = round($this->invoice->amount * (1 / $this->invoice->tax_rate1), 2); + // $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_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; - $taxable_amount = new TaxableAmount(); $taxable_amount->currencyID = $this->invoice->client->currency()->code; - $taxable_amount->amount = $this->invoice->amount; + $taxable_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->invoice->amount - $this->invoice->total_taxes : $this->invoice->amount; $tax_subtotal->TaxableAmount = $taxable_amount; - - $tc = new TaxCategory(); $tc->ID = $type_id == '2' ? 'HUR' : 'C62'; $tc->Percent = $this->invoice->tax_rate1; @@ -169,24 +189,25 @@ class Peppol extends AbstractService $tax_total = new TaxTotal(); $tax_total->TaxAmount = $tax_amount; - $tax_total->TaxSubtotal = $tax_subtotal; + $tax_total->TaxSubtotal[] = $tax_subtotal; $taxes[] = $tax_total; - } + // } if(strlen($this->invoice->tax_name2 ?? '') > 1) { $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - $tax_amount->amount = round($this->invoice->amount * (1 / $this->invoice->tax_rate2), 2); + + $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($this->invoice->tax_rate2, $this->invoice->amount) : $this->calcAmountLineTax($this->invoice->tax_rate2, $this->invoice->amount); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; $taxable_amount = new TaxableAmount(); $taxable_amount->currencyID = $this->invoice->client->currency()->code; - $taxable_amount->amount = $this->invoice->amount; + $taxable_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->invoice->amount- $this->invoice->total_taxes : $this->invoice->amount; $tax_subtotal->TaxableAmount = $taxable_amount; @@ -211,14 +232,14 @@ class Peppol extends AbstractService $tax_amount = new TaxAmount(); $tax_amount->currencyID = $this->invoice->client->currency()->code; - $tax_amount->amount = round($this->invoice->amount * (1 / $this->invoice->tax_rate1), 2); + $tax_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($this->invoice->tax_rate3, $this->invoice->amount) : $this->calcAmountLineTax($this->invoice->tax_rate3, $this->invoice->amount); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; $taxable_amount = new TaxableAmount(); $taxable_amount->currencyID = $this->invoice->client->currency()->code; - $taxable_amount->amount = $this->invoice->amount; + $taxable_amount->amount = $this->invoice->uses_inclusive_taxes ? $this->invoice->amount - $this->invoice->total_taxes : $this->invoice->amount; $tax_subtotal->TaxableAmount = $taxable_amount; @@ -259,14 +280,11 @@ class Peppol extends AbstractService $lea = new LineExtensionAmount(); $lea->currencyID = $this->invoice->client->currency()->code; - $lea->amount = $item->line_total; + // $lea->amount = $item->line_total; + $lea->amount = $this->invoice->uses_inclusive_taxes ? $item->line_total - $this->calcInclusiveLineTax($item->tax_rate1, $item->line_total) : $item->line_total; $line->LineExtensionAmount = $lea; $line->Item = $_item; - // $ta = new TaxAmount; - // $ta->amount = $this->getItemTaxes($item); - // $ta->currencyID = $this->invoice->client->currency()->Code; - // $tt->TaxAmount = $ta; $item_taxes = $this->getItemTaxes($item); if(count($item_taxes) > 0) { @@ -276,7 +294,7 @@ class Peppol extends AbstractService $price = new Price(); $pa = new PriceAmount(); $pa->currencyID = $this->invoice->client->currency()->code; - $pa->amount = $this->costWithDiscount($item); + $pa->amount = $this->costWithDiscount($item) - ( $this->invoice->uses_inclusive_taxes ? ($this->calcInclusiveLineTax($item->tax_rate1, $item->line_total)/$item->quantity) : 0); $price->PriceAmount = $pa; $line->Price = $price; @@ -310,13 +328,13 @@ 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 = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate1, $item->line_total) : $this->calcAmountLineTax($item->tax_rate1, $item->line_total); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; $taxable_amount = new TaxableAmount(); $taxable_amount->currencyID = $this->invoice->client->currency()->code; - $taxable_amount->amount = $item->line_total; + $taxable_amount->amount = $this->invoice->uses_inclusive_taxes ? $item->line_total - $tax_amount->amount : $item->line_total; $tax_subtotal->TaxableAmount = $taxable_amount; $tc = new TaxCategory(); $tc->ID = $item->type_id == '2' ? 'HUR' : 'C62'; @@ -339,7 +357,8 @@ 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 = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate2, $item->line_total) : $this->calcAmountLineTax($item->tax_rate2, $item->line_total); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; @@ -372,7 +391,8 @@ 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 = $this->invoice->uses_inclusive_taxes ? $this->calcInclusiveLineTax($item->tax_rate3, $item->line_total) : $this->calcAmountLineTax($item->tax_rate3, $item->line_total); $tax_subtotal = new TaxSubtotal(); $tax_subtotal->TaxAmount = $tax_amount; @@ -520,4 +540,34 @@ 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/app/Services/EDocument/Standards/Settings/PropertyResolver.php b/app/Services/EDocument/Standards/Settings/PropertyResolver.php new file mode 100644 index 000000000000..2476a70b39a0 --- /dev/null +++ b/app/Services/EDocument/Standards/Settings/PropertyResolver.php @@ -0,0 +1,44 @@ +{$currentProperty})) { + $nextObject = $object->{$currentProperty}; + } elseif (is_array($object) && array_key_exists($currentProperty, $object)) { + $nextObject = $object[$currentProperty]; + } else { + return null; + } + + if (empty($pathSegments)) { + return $nextObject; + } + + return self::traverse($nextObject, $pathSegments); + } +} \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index 615673bec9c9..21f22b804175 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.10'), - 'app_tag' => env('APP_TAG', '5.10.10'), + 'app_version' => env('APP_VERSION', '5.10.11'), + 'app_tag' => env('APP_TAG', '5.10.11'), 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), diff --git a/routes/client.php b/routes/client.php index 8b29dc956c17..7f9d4614f0e0 100644 --- a/routes/client.php +++ b/routes/client.php @@ -144,20 +144,20 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie Route::get('unsubscribe/{entity}/{invitation_key}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'unsubscribe'])->name('unsubscribe'); }); -Route::get('route/{hash}', function ($hash) { +// Route::get('route/{hash}', function ($hash) { - $route = '/'; +// $route = '/'; - try { - $route = decrypt($hash); - } - catch (\Exception $e) { - abort(404); - } +// try { +// $route = decrypt($hash); +// } +// catch (\Exception $e) { +// abort(404); +// } - return redirect($route); +// return redirect($route); -})->middleware('throttle:404'); +// })->middleware('throttle:404'); Route::get('phantom/{entity}/{invitation_key}', [Phantom::class, 'displayInvitation'])->middleware(['invite_db', 'phantom_secret'])->name('phantom_view'); Route::get('blade/', [Phantom::class, 'blade'])->name('blade'); diff --git a/tests/Feature/EInvoice/PeppolTest.php b/tests/Feature/EInvoice/PeppolTest.php index 2933d571d488..e7d85b759340 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,233 @@ 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 testDeInvoiceInclusiveTaxes() + { + + $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' => true, + '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(100, $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("inclusive"); + 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 df05079470fd..e121caf0ba5c 100644 --- a/tests/Integration/Einvoice/Storecove/StorecoveTest.php +++ b/tests/Integration/Einvoice/Storecove/StorecoveTest.php @@ -103,125 +103,248 @@ class StorecoveTest extends TestCase public function testSendDocument() { - $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 - - '; + $x = ' + + + 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 + + + '; + +//inclusive +$x = ' + +DE-93090 + 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 + + + + + 15.97 + + 84.03 + 15.97 + + C62 + 0 + + + + + + + + 84.03 + 84.03 + 100.00 + 100.00 + + + 1 + 10 + 84.03 + + 15.97 + + 84.03 + 15.97 + + C62 + 19 + + mwst + + + + + + Product Description + Product Key + + + 8.403 + + +'; + - $sc = new \App\Services\EDocument\Gateway\Storecove\Storecove(); $sc->sendDocument($x);