728 lines
23 KiB
PHP
728 lines
23 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Services;
|
|
|
|
use App\Models\DatevExport;
|
|
use App\Models\DatevExportLine;
|
|
use App\Services\DatevExportService;
|
|
use Tests\TestCase;
|
|
|
|
class DatevExportServiceTest extends TestCase
|
|
{
|
|
private DatevExportService $service;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
$this->service = new DatevExportService;
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Revenue Account Mapping Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function it_maps_domestic_19_percent_to_account_8400_bu_9()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 19, true, false, false);
|
|
|
|
$this->assertEquals(8400, $result['konto']);
|
|
$this->assertEquals(9, $result['bu']);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_maps_domestic_7_percent_to_account_8300_bu_8()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 7, true, false, false);
|
|
|
|
$this->assertEquals(8300, $result['konto']);
|
|
$this->assertEquals(8, $result['bu']);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_maps_domestic_5_percent_to_account_8300_bu_8()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 5, true, false, false);
|
|
|
|
$this->assertEquals(8300, $result['konto']);
|
|
$this->assertEquals(8, $result['bu']);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_maps_eu_with_ustid_to_account_8125_bu_1()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 19, false, true, true);
|
|
|
|
$this->assertEquals(8125, $result['konto']);
|
|
$this->assertEquals(1, $result['bu']);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_maps_eu_without_ustid_to_domestic_19_percent()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 19, false, true, false);
|
|
|
|
$this->assertEquals(8400, $result['konto']);
|
|
$this->assertEquals(9, $result['bu']);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_maps_eu_without_ustid_7_percent_to_domestic_7()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 7, false, true, false);
|
|
|
|
$this->assertEquals(8300, $result['konto']);
|
|
$this->assertEquals(8, $result['bu']);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_maps_third_country_exempt_to_account_8120_bu_11()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineRevenueAccount');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, 19, false, false, false);
|
|
|
|
$this->assertEquals(8120, $result['konto']);
|
|
$this->assertEquals(11, $result['bu']);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Commission Tax Status Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function it_determines_normal_tax_status_for_vat_registered()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineCommissionTaxStatus');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->reverse_charge = false;
|
|
$account->taxable_sales = 1;
|
|
|
|
$result = $method->invoke($this->service, $account);
|
|
|
|
$this->assertEquals('normal', $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_determines_kleinunternehmer_for_taxable_sales_2()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineCommissionTaxStatus');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->reverse_charge = false;
|
|
$account->taxable_sales = 2;
|
|
|
|
$result = $method->invoke($this->service, $account);
|
|
|
|
$this->assertEquals('kleinunternehmer', $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_determines_reverse_charge_when_flag_is_set()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineCommissionTaxStatus');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->reverse_charge = true;
|
|
$account->taxable_sales = 1;
|
|
|
|
$result = $method->invoke($this->service, $account);
|
|
|
|
$this->assertEquals('reverse_charge', $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function reverse_charge_takes_priority_over_other_statuses()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineCommissionTaxStatus');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->reverse_charge = true;
|
|
$account->taxable_sales = 2; // Even if Kleinunternehmer, RC takes priority
|
|
|
|
$result = $method->invoke($this->service, $account);
|
|
|
|
$this->assertEquals('reverse_charge', $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function null_account_defaults_to_normal()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'determineCommissionTaxStatus');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, null);
|
|
|
|
$this->assertEquals('normal', $result);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| CSV Rendering Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function it_renders_csv_row_with_correct_column_count()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'renderCsvRow');
|
|
$method->setAccessible(true);
|
|
|
|
$data = [
|
|
'amount_gross' => 119.00,
|
|
'soll_haben' => 'H',
|
|
'konto' => 8400,
|
|
'gegenkonto' => 10000,
|
|
'bu_schluessel' => 9,
|
|
'belegdatum' => '2025-07-01',
|
|
'belegfeld1' => '202500123',
|
|
'buchungstext' => 'Mustermann Max',
|
|
'eu_ustid' => null,
|
|
];
|
|
|
|
$row = $method->invoke($this->service, $data);
|
|
$columns = explode(';', $row);
|
|
|
|
$this->assertCount(116, $columns, 'DATEV CSV row must have exactly 116 columns');
|
|
}
|
|
|
|
/** @test */
|
|
public function it_formats_amount_with_comma_as_decimal_separator()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'renderCsvRow');
|
|
$method->setAccessible(true);
|
|
|
|
$data = [
|
|
'amount_gross' => 1234.56,
|
|
'soll_haben' => 'H',
|
|
'konto' => 8400,
|
|
'gegenkonto' => 10000,
|
|
'bu_schluessel' => 9,
|
|
'belegdatum' => '2025-07-01',
|
|
'belegfeld1' => 'TEST-001',
|
|
'buchungstext' => 'Test',
|
|
];
|
|
|
|
$row = $method->invoke($this->service, $data);
|
|
$columns = explode(';', $row);
|
|
|
|
$this->assertEquals('1234,56', $columns[0], 'Amount must use comma as decimal separator');
|
|
}
|
|
|
|
/** @test */
|
|
public function it_formats_belegdatum_as_ddmm()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'renderCsvRow');
|
|
$method->setAccessible(true);
|
|
|
|
$data = [
|
|
'amount_gross' => 100.00,
|
|
'soll_haben' => 'H',
|
|
'konto' => 8400,
|
|
'gegenkonto' => 10000,
|
|
'bu_schluessel' => 9,
|
|
'belegdatum' => '2025-07-15',
|
|
'belegfeld1' => 'TEST',
|
|
'buchungstext' => 'Test',
|
|
];
|
|
|
|
$row = $method->invoke($this->service, $data);
|
|
$columns = explode(';', $row);
|
|
|
|
$this->assertEquals('1507', $columns[9], 'Belegdatum must be in TTMM format');
|
|
}
|
|
|
|
/** @test */
|
|
public function it_places_fields_in_correct_datev_columns()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'renderCsvRow');
|
|
$method->setAccessible(true);
|
|
|
|
$data = [
|
|
'amount_gross' => 119.00,
|
|
'soll_haben' => 'H',
|
|
'konto' => 8400,
|
|
'gegenkonto' => 10000,
|
|
'bu_schluessel' => 9,
|
|
'belegdatum' => '2025-01-07',
|
|
'belegfeld1' => '202500001',
|
|
'buchungstext' => 'Nachname Vorname',
|
|
'eu_ustid' => 'DE123456789',
|
|
];
|
|
|
|
$row = $method->invoke($this->service, $data);
|
|
$columns = explode(';', $row);
|
|
|
|
// Spalte A (Index 0): Umsatz
|
|
$this->assertEquals('119,00', $columns[0]);
|
|
|
|
// Spalte B (Index 1): Soll/Haben
|
|
$this->assertEquals('H', $columns[1]);
|
|
|
|
// Spalte G (Index 6): Konto
|
|
$this->assertEquals('8400', $columns[6]);
|
|
|
|
// Spalte H (Index 7): Gegenkonto
|
|
$this->assertEquals('10000', $columns[7]);
|
|
|
|
// Spalte I (Index 8): BU-Schluessel
|
|
$this->assertEquals('9', $columns[8]);
|
|
|
|
// Spalte J (Index 9): Belegdatum (TTMM)
|
|
$this->assertEquals('0701', $columns[9]);
|
|
|
|
// Spalte K (Index 10): Belegfeld 1
|
|
$this->assertEquals('202500001', $columns[10]);
|
|
|
|
// Spalte N (Index 13): Buchungstext
|
|
$this->assertEquals('Nachname Vorname', $columns[13]);
|
|
|
|
// Spalte AN (Index 39): EU-Land u. UStID
|
|
$this->assertEquals('DE123456789', $columns[39]);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Validation Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function validation_detects_missing_belegdatum()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'invoice',
|
|
'source_id' => 1,
|
|
'amount_gross' => 100,
|
|
'belegdatum' => null,
|
|
'belegfeld1' => 'TEST-001',
|
|
'buchungstext' => 'Test',
|
|
'bu_schluessel' => 9,
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$this->assertFalse($result['valid']);
|
|
$this->assertNotEmpty($result['errors']);
|
|
$this->assertStringContainsString('Belegdatum', $result['errors'][0]['message']);
|
|
}
|
|
|
|
/** @test */
|
|
public function validation_detects_missing_belegnummer()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'invoice',
|
|
'source_id' => 1,
|
|
'amount_gross' => 100,
|
|
'belegdatum' => '2025-01-01',
|
|
'belegfeld1' => '',
|
|
'buchungstext' => 'Test',
|
|
'bu_schluessel' => 9,
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$this->assertFalse($result['valid']);
|
|
$this->assertStringContainsString('Belegnummer', $result['errors'][0]['message']);
|
|
}
|
|
|
|
/** @test */
|
|
public function validation_warns_on_eu_delivery_without_ustid()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'invoice',
|
|
'source_id' => 1,
|
|
'amount_gross' => 100,
|
|
'belegdatum' => '2025-01-01',
|
|
'belegfeld1' => 'TEST-001',
|
|
'buchungstext' => 'Test',
|
|
'bu_schluessel' => 1,
|
|
'eu_ustid' => null,
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertNotEmpty($result['warnings']);
|
|
$this->assertStringContainsString('EU-Lieferung', $result['warnings'][0]['message']);
|
|
}
|
|
|
|
/** @test */
|
|
public function validation_warns_on_reverse_charge_without_ustid()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'credit',
|
|
'source_id' => 1,
|
|
'amount_gross' => 50,
|
|
'belegdatum' => '2025-01-01',
|
|
'belegfeld1' => 'GS-001',
|
|
'buchungstext' => 'Test',
|
|
'bu_schluessel' => 94,
|
|
'eu_ustid' => null,
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertNotEmpty($result['warnings']);
|
|
$this->assertStringContainsString('Reverse Charge', $result['warnings'][0]['message']);
|
|
}
|
|
|
|
/** @test */
|
|
public function validation_passes_for_complete_data()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'invoice',
|
|
'source_id' => 1,
|
|
'amount_gross' => 119.00,
|
|
'belegdatum' => '2025-07-01',
|
|
'belegfeld1' => '202500001',
|
|
'buchungstext' => 'Mustermann Max',
|
|
'bu_schluessel' => 9,
|
|
'eu_ustid' => null,
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$this->assertTrue($result['valid']);
|
|
$this->assertEmpty($result['errors']);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Number Parsing Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function it_parses_formatted_numbers_correctly()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'parseNumber');
|
|
$method->setAccessible(true);
|
|
|
|
// Standard format from number_format
|
|
$this->assertEquals(5.00, $method->invoke($this->service, '5.00'));
|
|
$this->assertEquals(1234.56, $method->invoke($this->service, '1234.56'));
|
|
|
|
// Comma format
|
|
$this->assertEquals(5.00, $method->invoke($this->service, '5,00'));
|
|
}
|
|
|
|
/** @test */
|
|
public function it_parses_homeparty_tax_split_format()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'parseNumber');
|
|
$method->setAccessible(true);
|
|
|
|
// Homeparty format: ['vk_tax' => '5.00', 'ek_tax' => '2.00']
|
|
$result = $method->invoke($this->service, ['vk_tax' => '15.50', 'ek_tax' => '7.50']);
|
|
|
|
$this->assertEquals(15.50, $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_parses_homeparty_ek_tax_split_format_with_preferred_key()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'parseNumber');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, ['vk_tax' => '15.50', 'ek_tax' => '7.50'], 'ek_tax');
|
|
|
|
$this->assertEquals(7.50, $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_parses_homeparty_ek_net_split_format_with_preferred_key()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'parseNumber');
|
|
$method->setAccessible(true);
|
|
|
|
$result = $method->invoke($this->service, ['vk_net' => '123.45', 'ek_net' => '67.89'], 'ek_net');
|
|
|
|
$this->assertEquals(67.89, $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_resolves_net_split_from_collective_order_when_order_has_none()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'resolveNetSplit');
|
|
$method->setAccessible(true);
|
|
|
|
$collectOrder = new \stdClass;
|
|
$collectOrder->net_split = ['19' => '533.61'];
|
|
|
|
$order = new \stdClass;
|
|
$order->net_split = null;
|
|
$order->shopping_collect_order = $collectOrder;
|
|
|
|
$result = $method->invoke($this->service, $order);
|
|
|
|
$this->assertEquals(['19' => '533.61'], $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_prefers_order_net_split_over_collective_order_net_split()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'resolveNetSplit');
|
|
$method->setAccessible(true);
|
|
|
|
$collectOrder = new \stdClass;
|
|
$collectOrder->net_split = ['19' => '533.61'];
|
|
|
|
$order = new \stdClass;
|
|
$order->net_split = ['19' => '677.51'];
|
|
$order->shopping_collect_order = $collectOrder;
|
|
|
|
$result = $method->invoke($this->service, $order);
|
|
|
|
$this->assertEquals(['19' => '677.51'], $result);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Model Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function datev_export_status_labels_are_defined()
|
|
{
|
|
$this->assertEquals('Entwurf', DatevExport::STATUS_LABELS[DatevExport::STATUS_DRAFT]);
|
|
$this->assertEquals('Generiert', DatevExport::STATUS_LABELS[DatevExport::STATUS_GENERATED]);
|
|
$this->assertEquals('Heruntergeladen', DatevExport::STATUS_LABELS[DatevExport::STATUS_DOWNLOADED]);
|
|
$this->assertEquals('Gesperrt', DatevExport::STATUS_LABELS[DatevExport::STATUS_LOCKED]);
|
|
}
|
|
|
|
/** @test */
|
|
public function datev_export_line_source_types_are_defined()
|
|
{
|
|
$this->assertEquals('invoice', DatevExportLine::SOURCE_INVOICE);
|
|
$this->assertEquals('credit', DatevExportLine::SOURCE_CREDIT);
|
|
$this->assertEquals('cancellation', DatevExportLine::SOURCE_CANCELLATION);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| EU USt-ID Resolution Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function it_resolves_eu_ustid_from_order_auth_user_account()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'resolveEuUstid');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->tax_identification_number = 'ATU12345678';
|
|
|
|
$user = new \stdClass;
|
|
$user->account = $account;
|
|
|
|
$order = new \stdClass;
|
|
$order->auth_user = $user;
|
|
|
|
$result = $method->invoke($this->service, $order, false);
|
|
|
|
$this->assertEquals('ATU12345678', $result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_returns_null_ustid_for_domestic_orders()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'resolveEuUstid');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->tax_identification_number = 'DE123456789';
|
|
|
|
$user = new \stdClass;
|
|
$user->account = $account;
|
|
|
|
$order = new \stdClass;
|
|
$order->auth_user = $user;
|
|
|
|
$result = $method->invoke($this->service, $order, true);
|
|
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_returns_null_ustid_for_guest_orders()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'resolveEuUstid');
|
|
$method->setAccessible(true);
|
|
|
|
$order = new \stdClass;
|
|
$order->auth_user = null;
|
|
|
|
$result = $method->invoke($this->service, $order, false);
|
|
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
/** @test */
|
|
public function it_returns_null_ustid_when_account_has_no_tax_id()
|
|
{
|
|
$method = new \ReflectionMethod(DatevExportService::class, 'resolveEuUstid');
|
|
$method->setAccessible(true);
|
|
|
|
$account = new \stdClass;
|
|
$account->tax_identification_number = null;
|
|
|
|
$user = new \stdClass;
|
|
$user->account = $account;
|
|
|
|
$order = new \stdClass;
|
|
$order->auth_user = $user;
|
|
|
|
$result = $method->invoke($this->service, $order, false);
|
|
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
/** @test */
|
|
public function validation_no_warning_for_eu_delivery_with_ustid()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'invoice',
|
|
'source_id' => 1,
|
|
'amount_gross' => 100,
|
|
'belegdatum' => '2025-01-01',
|
|
'belegfeld1' => 'TEST-001',
|
|
'buchungstext' => 'Test',
|
|
'bu_schluessel' => 1,
|
|
'eu_ustid' => 'ATU12345678',
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$this->assertTrue($result['valid']);
|
|
$euWarnings = array_filter($result['warnings'], fn ($w) => str_contains($w['message'], 'EU-Lieferung'));
|
|
$this->assertEmpty($euWarnings);
|
|
}
|
|
|
|
/** @test */
|
|
public function validation_returns_structured_entries_with_metadata()
|
|
{
|
|
$lines = collect([
|
|
[
|
|
'source_type' => 'invoice',
|
|
'source_id' => 42,
|
|
'order_id' => 100,
|
|
'user_id' => 5,
|
|
'amount_gross' => 100,
|
|
'belegdatum' => '2025-01-01',
|
|
'belegfeld1' => 'TEST-001',
|
|
'buchungstext' => 'Test',
|
|
'bu_schluessel' => 1,
|
|
'eu_ustid' => null,
|
|
],
|
|
]);
|
|
|
|
$result = $this->service->validate($lines);
|
|
|
|
$warning = $result['warnings'][0];
|
|
$this->assertIsArray($warning);
|
|
$this->assertArrayHasKey('message', $warning);
|
|
$this->assertArrayHasKey('source_id', $warning);
|
|
$this->assertArrayHasKey('order_id', $warning);
|
|
$this->assertArrayHasKey('user_id', $warning);
|
|
$this->assertEquals(42, $warning['source_id']);
|
|
$this->assertEquals(100, $warning['order_id']);
|
|
$this->assertEquals(5, $warning['user_id']);
|
|
}
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Config Tests
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
/** @test */
|
|
public function datev_config_has_required_keys()
|
|
{
|
|
$this->assertNotNull(config('datev.revenue_accounts'));
|
|
$this->assertNotNull(config('datev.commission_accounts'));
|
|
$this->assertNotNull(config('datev.commission_tax_keys'));
|
|
$this->assertNotNull(config('datev.counteraccount_map'));
|
|
$this->assertNotNull(config('datev.sammeldebitor'));
|
|
$this->assertNotNull(config('datev.sammelkreditor'));
|
|
}
|
|
|
|
/** @test */
|
|
public function datev_config_revenue_accounts_are_complete()
|
|
{
|
|
$accounts = config('datev.revenue_accounts');
|
|
|
|
$this->assertArrayHasKey('domestic_19', $accounts);
|
|
$this->assertArrayHasKey('domestic_7', $accounts);
|
|
$this->assertArrayHasKey('eu_exempt', $accounts);
|
|
$this->assertArrayHasKey('third_country_exempt', $accounts);
|
|
|
|
// Verify correct account numbers
|
|
$this->assertEquals(8400, $accounts['domestic_19']['konto']);
|
|
$this->assertEquals(8300, $accounts['domestic_7']['konto']);
|
|
$this->assertEquals(8125, $accounts['eu_exempt']['konto']);
|
|
$this->assertEquals(8120, $accounts['third_country_exempt']['konto']);
|
|
}
|
|
|
|
/** @test */
|
|
public function datev_config_commission_accounts_map_correctly()
|
|
{
|
|
$accounts = config('datev.commission_accounts');
|
|
|
|
$this->assertEquals(4760, $accounts['shop']);
|
|
$this->assertEquals(4760, $accounts['growth_bonus']);
|
|
$this->assertEquals(4764, $accounts['payline']);
|
|
}
|
|
|
|
/** @test */
|
|
public function datev_column_headers_have_correct_count()
|
|
{
|
|
$reflection = new \ReflectionClass(DatevExportService::class);
|
|
$prop = $reflection->getConstant('COLUMN_COUNT');
|
|
|
|
$this->assertEquals(116, $prop);
|
|
}
|
|
}
|