Meta-fields for InvoiceTemplate, structured Customer address (#5519)

This commit is contained in:
Kevin Papst
2025-11-02 11:24:17 +01:00
committed by GitHub
parent 76821c24ed
commit cc64acf0f8
72 changed files with 2111 additions and 801 deletions

View File

@@ -17,6 +17,7 @@ use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\CalculatorInterface;
use App\Invoice\InvoiceModel;
use App\Invoice\TaxRow;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -43,11 +44,21 @@ abstract class AbstractCalculatorTestCase extends TestCase
$sut->setModel($model);
self::assertEquals(0, $sut->getTotal());
self::assertEquals(0, $sut->getVat());
self::assertEquals(0, $sut->getSubtotal());
self::assertEquals(0, $sut->getTimeWorked());
self::assertEquals(0, \count($sut->getEntries()));
self::assertEquals(0, $sut->getTax());
self::assertTax($sut, 0);
}
protected function assertTax(CalculatorInterface $sut, int $rate): void
{
self::assertEquals($rate, $sut->getVat()); // @phpstan-ignore method.deprecated
$rows = $sut->getTaxRows();
self::assertCount(1, $rows);
self::assertInstanceOf(TaxRow::class, $rows[0]);
self::assertEquals($rate, $rows[0]->getTax()->getRate());
}
private function getEmptyModel(): InvoiceModel

View File

@@ -138,7 +138,7 @@ class ActivityInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('activity', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -150,7 +150,7 @@ class ActivityUserInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('activity_user', $sut->getId());
self::assertEquals(3100.09, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2605.12, $sut->getSubtotal());
self::assertEquals(7000, $sut->getTimeWorked());

View File

@@ -114,7 +114,7 @@ class DateInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('date', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -116,7 +116,7 @@ class DateUserInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('date_user', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -72,7 +72,7 @@ class DefaultCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('default', $sut->getId());
self::assertEquals(581.17, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(488.38, $sut->getSubtotal());
self::assertEquals(5800, $sut->getTimeWorked());

View File

@@ -117,7 +117,7 @@ class PriceInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('price', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -113,7 +113,7 @@ class ProjectInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('project', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -116,7 +116,7 @@ class ProjectUserInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('project_user', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -95,7 +95,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('short', $sut->getId());
self::assertEquals(562.28, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(472.5, $sut->getSubtotal());
self::assertEquals(5800, $sut->getTimeWorked());
@@ -171,7 +171,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('short', $sut->getId());
self::assertEquals(581.17, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(488.38, $sut->getSubtotal());
self::assertEquals(5800, $sut->getTimeWorked());
@@ -241,7 +241,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('short', $sut->getId());
self::assertEquals(581.17, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(488.38, $sut->getSubtotal());
self::assertEquals(5800, $sut->getTimeWorked());

View File

@@ -110,7 +110,7 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('user', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -116,7 +116,7 @@ class WeeklyInvoiceCalculatorTest extends AbstractCalculatorTestCase
self::assertEquals('weekly', $sut->getId());
self::assertEquals(3000.13, $sut->getTotal());
self::assertEquals(19, $sut->getVat());
$this->assertTax($sut, 19);
self::assertEquals('EUR', $model->getCurrency());
self::assertEquals(2521.12, $sut->getSubtotal());
self::assertEquals(6600, $sut->getTimeWorked());

View File

@@ -36,6 +36,12 @@ class InvoiceModelCustomerHydratorTest extends TestCase
self::assertEquals([
'customer.id' => null,
'customer.address' => "Foo\nStreet\n1111 City",
'customer.address_line1' => '',
'customer.address_line2' => '',
'customer.address_line3' => '',
'customer.buyer_reference' => '',
'customer.city' => '',
'customer.postcode' => '',
'customer.name' => 'customer,with/special#name',
'customer.contact' => '',
'customer.company' => '',
@@ -43,6 +49,7 @@ class InvoiceModelCustomerHydratorTest extends TestCase
'customer.vat_id' => '',
'customer.number' => '',
'customer.country' => 'AT',
'customer.country_name' => 'Austria',
'customer.homepage' => '',
'customer.comment' => '',
'customer.email' => '',
@@ -63,12 +70,19 @@ class InvoiceModelCustomerHydratorTest extends TestCase
$keys = [
'customer.id',
'customer.address',
'customer.address_line1',
'customer.address_line2',
'customer.address_line3',
'customer.buyer_reference',
'customer.city',
'customer.postcode',
'customer.name',
'customer.contact',
'customer.company',
'customer.vat',
'customer.vat_id',
'customer.country',
'customer.country_name',
'customer.number',
'customer.homepage',
'customer.comment',

View File

@@ -33,12 +33,12 @@ class InvoiceModelDefaultHydratorTest extends TestCase
public function testHydrateThrowsOnMissing(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('InvoiceModel needs a template');
$this->expectExceptionMessage('InvoiceModel needs a calculator');
$model = $this->getInvoiceModel();
$obj = new ReflectionObject($model);
$prop = $obj->getProperty('template');
$prop = $obj->getProperty('calculator');
$prop->setAccessible(true);
$prop->setValue($model, null);
@@ -63,6 +63,7 @@ class InvoiceModelDefaultHydratorTest extends TestCase
'invoice.tax_hide',
'invoice.tax_nc',
'invoice.tax_plain',
'invoice.tax_rows',
'invoice.total_time',
'invoice.duration_decimal',
'invoice.first',

View File

@@ -28,8 +28,6 @@ class InvoiceModelTest extends TestCase
$sut = (new InvoiceModelFactoryFactory($this))->create()->createModel($formatter, new Customer('foo'), new InvoiceTemplate(), new InvoiceQuery());
self::assertNotNull($sut->getQuery());
self::assertNotNull($sut->getCustomer());
self::assertNotNull($sut->getTemplate());
self::assertFalse($sut->isPreview());
self::assertFalse($sut->isHideZeroTax());

View File

@@ -96,6 +96,7 @@ class DebugRendererTest extends TestCase
'invoice.language',
'invoice.tax_nc',
'invoice.tax_plain',
'invoice.tax_rows',
'invoice.total_time',
'invoice.duration_decimal',
'invoice.first',
@@ -137,12 +138,19 @@ class DebugRendererTest extends TestCase
'query.end_year',
'customer.id',
'customer.address',
'customer.address_line1',
'customer.address_line2',
'customer.address_line3',
'customer.buyer_reference',
'customer.city',
'customer.postcode',
'customer.name',
'customer.contact',
'customer.company',
'customer.vat',
'customer.vat_id',
'customer.country',
'customer.country_name',
'customer.number',
'customer.homepage',
'customer.comment',

View File

@@ -95,6 +95,7 @@ trait RendererTestTrait
$template->setTitle('a very *long* test invoice / template title with [ßpecial] chäracter');
$template->setVat(19);
$template->setLanguage('en');
$template->setCustomer($customer);
$pMeta = new ProjectMeta();
$pMeta->setName('foo-project')->setValue('bar-project')->setIsVisible(true);
@@ -279,6 +280,7 @@ trait RendererTestTrait
$template->setTitle('a test invoice template title');
$template->setVat(19);
$template->setLanguage('it');
$template->setCustomer($customer);
$project = new Project();
$project->setName('project name');

View File

@@ -59,7 +59,7 @@ class TwigRendererTest extends KernelTestCase
$sut = new TwigRenderer($twig);
$model = $this->getInvoiceModel();
$model->getTemplate()?->setLanguage('de');
$model->getTemplate()->setLanguage('de');
$document = $this->getInvoiceDocument('timesheet.html.twig');
$response = $sut->render($document, $model);
@@ -118,7 +118,7 @@ class TwigRendererTest extends KernelTestCase
$sut = new TwigRenderer($twig);
$model = $this->getInvoiceModel();
$model->getTemplate()?->setLanguage('de');
$model->getTemplate()->setLanguage('de');
foreach ($files as $filename) {
$document = new InvoiceDocument(new \SplFileInfo($filename));