Improve UX for invoice template management (#4121)

change translations and to explain that calculator actually group items by fields
This commit is contained in:
Kevin Papst
2023-06-21 08:17:54 +02:00
committed by GitHub
parent 983bf2c88b
commit dd89363c72
33 changed files with 889 additions and 324 deletions

View File

@@ -16,6 +16,7 @@ use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\CalculatorInterface;
use App\Invoice\InvoiceModel;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -23,7 +24,18 @@ use PHPUnit\Framework\TestCase;
abstract class AbstractCalculatorTest extends TestCase
{
protected function assertEmptyModel(CalculatorInterface $sut)
abstract protected function getCalculator(): CalculatorInterface;
public function testCalculatorInterface(): void
{
$sut = $this->getCalculator();
self::assertLessThanOrEqual(20, \strlen($sut->getId()));
$this->assertEmptyModel($sut);
}
private function assertEmptyModel(CalculatorInterface $sut): void
{
$model = $this->getEmptyModel();
$this->assertEquals('EUR', $model->getCurrency());
@@ -38,7 +50,7 @@ abstract class AbstractCalculatorTest extends TestCase
$this->assertEquals(0, $sut->getTax());
}
protected function getEmptyModel()
private function getEmptyModel(): InvoiceModel
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -52,7 +64,7 @@ abstract class AbstractCalculatorTest extends TestCase
return $model;
}
protected function assertDescription(CalculatorInterface $sut, $addProject = false, $addActivity = false)
protected function assertDescription(CalculatorInterface $sut, $addProject = false, $addActivity = false): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();

View File

@@ -16,6 +16,7 @@ use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\ActivityInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -28,12 +29,12 @@ use App\Tests\Mocks\InvoiceModelFactoryFactory;
*/
class ActivityInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new ActivityInvoiceCalculator());
return new ActivityInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -140,7 +141,7 @@ class ActivityInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new ActivityInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('activity', $sut->getId());
@@ -149,16 +150,16 @@ class ActivityInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2521.12, $sut->getSubtotal());
$this->assertEquals(6600, $sut->getTimeWorked());
$this->assertEquals(5, \count($sut->getEntries()));
$entries = $sut->getEntries();
self::assertCount(4, $entries);
$this->assertEquals(404.38, $entries[0]->getRate());
$this->assertEquals(2032.74, $entries[1]->getRate());
$this->assertEquals(84, $entries[2]->getRate());
}
public function testDescriptionByActivity()
public function testDescriptionByActivity(): void
{
$this->assertDescription(new ActivityInvoiceCalculator(), false, true);
$this->assertDescription($this->getCalculator(), false, true);
}
}

View File

@@ -0,0 +1,181 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Invoice\Calculator;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\InvoiceTemplate;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\ActivityUserInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
/**
* @covers \App\Invoice\Calculator\ActivityUserInvoiceCalculator
* @covers \App\Invoice\Calculator\AbstractSumInvoiceCalculator
* @covers \App\Invoice\Calculator\AbstractMergedCalculator
* @covers \App\Invoice\Calculator\AbstractCalculator
*/
class ActivityUserInvoiceCalculatorTest extends AbstractCalculatorTest
{
protected function getCalculator(): CalculatorInterface
{
return new ActivityUserInvoiceCalculator();
}
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
$template->setVat(19);
$user1 = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$user1->method('getId')->willReturn(1);
$user2 = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$user2->method('getId')->willReturn(2);
$activity1 = $this->getMockBuilder(Activity::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$activity1->method('getId')->willReturn(1);
$activity2 = $this->getMockBuilder(Activity::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$activity2->method('getId')->willReturn(2);
$activity3 = $this->getMockBuilder(Activity::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$activity3->method('getId')->willReturn(3);
$timesheet = new Timesheet();
$timesheet
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(3600)
->setRate(293.27)
->setUser($user1)
->setActivity($activity1)
->setProject((new Project())->setName('bar'));
$timesheet2 = new Timesheet();
$timesheet2
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(400)
->setRate(84.75)
->setUser($user1)
->setActivity($activity2)
->setProject((new Project())->setName('bar'));
$timesheet3 = new Timesheet();
$timesheet3
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(1800)
->setRate(111.11)
->setUser($user1)
->setActivity($activity1)
->setProject((new Project())->setName('bar'));
$timesheet4 = new Timesheet();
$timesheet4
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(400)
->setRate(1947.99)
->setUser($user1)
->setActivity($activity2)
->setProject((new Project())->setName('bar'));
$timesheet5 = new Timesheet();
$timesheet5
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(400)
->setRate(84)
->setUser($user2)
->setActivity($activity3)
->setProject((new Project())->setName('bar'));
$timesheet5a = new Timesheet();
$timesheet5a
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(400)
->setRate(84)
->setUser($user1)
->setActivity($activity3)
->setProject((new Project())->setName('bar'));
$timesheet6 = new Timesheet();
$timesheet6
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(0)
->setRate(0)
->setUser($user1)
->setProject((new Project())->setName('bar'));
$timesheet7 = new Timesheet();
$timesheet7
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(0)
->setRate(0)
->setUser($user2)
->setActivity(new Activity())
->setProject((new Project())->setName('bar'));
$timesheet8 = new Timesheet();
$timesheet8
->setBegin(new \DateTime())
->setEnd(new \DateTime())
->setDuration(0)
->setRate(0)
->setUser($user2)
->setProject((new Project())->setName('bar'));
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5, $timesheet5a, $timesheet6, $timesheet7, $timesheet8];
$query = new InvoiceQuery();
$query->addActivity($activity1);
$model = (new InvoiceModelFactoryFactory($this))->create()->createModel(new DebugFormatter());
$model->setCustomer($customer);
$model->setTemplate($template);
$model->addEntries($entries);
$model->setQuery($query);
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('activity_user', $sut->getId());
$this->assertEquals(3100.09, $sut->getTotal());
$this->assertEquals(19, $sut->getVat());
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2605.12, $sut->getSubtotal());
$this->assertEquals(7000, $sut->getTimeWorked());
$entries = $sut->getEntries();
self::assertCount(6, $entries);
$this->assertEquals(404.38, $entries[0]->getRate());
$this->assertEquals(2032.74, $entries[1]->getRate());
$this->assertEquals(84.0, $entries[2]->getRate());
$this->assertEquals(84.0, $entries[3]->getRate());
$this->assertEquals(0, $entries[4]->getRate());
$this->assertEquals(0, $entries[5]->getRate());
}
public function testDescriptionByActivity(): void
{
$this->assertDescription($this->getCalculator(), false, true);
}
}

View File

@@ -16,6 +16,7 @@ use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\DateInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -29,12 +30,12 @@ use DateTime;
*/
class DateInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new DateInvoiceCalculator());
return new DateInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -113,7 +114,7 @@ class DateInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new DateInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('date', $sut->getId());
@@ -122,7 +123,6 @@ class DateInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2521.12, $sut->getSubtotal());
$this->assertEquals(6600, $sut->getTimeWorked());
$this->assertEquals(3, \count($sut->getEntries()));
$entries = $sut->getEntries();
self::assertCount(3, $entries);
@@ -132,8 +132,8 @@ class DateInvoiceCalculatorTest extends AbstractCalculatorTest
self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate() + $entries[2]->getRate());
}
public function testDescriptionByTimesheet()
public function testDescriptionByTimesheet(): void
{
$this->assertDescription(new DateInvoiceCalculator(), false, false);
$this->assertDescription($this->getCalculator(), false, false);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Invoice\Calculator;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\InvoiceTemplate;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\DateUserInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
use DateTime;
/**
* @covers \App\Invoice\Calculator\DateUserInvoiceCalculator
* @covers \App\Invoice\Calculator\AbstractSumInvoiceCalculator
* @covers \App\Invoice\Calculator\AbstractMergedCalculator
* @covers \App\Invoice\Calculator\AbstractCalculator
*/
class DateUserInvoiceCalculatorTest extends AbstractCalculatorTest
{
protected function getCalculator(): CalculatorInterface
{
return new DateUserInvoiceCalculator();
}
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
$template->setVat(19);
$user1 = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$user1->method('getId')->willReturn(1);
$user2 = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$user2->method('getId')->willReturn(2);
$project1 = $this->getMockBuilder(Project::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$project1->method('getId')->willReturn(1);
$project2 = $this->getMockBuilder(Project::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$project2->method('getId')->willReturn(2);
$project3 = $this->getMockBuilder(Project::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$project3->method('getId')->willReturn(3);
$timesheet = new Timesheet();
$timesheet
->setBegin(new DateTime('2018-11-29'))
->setEnd(new DateTime())
->setDuration(3600)
->setRate(293.27)
->setUser($user1)
->setActivity((new Activity())->setName('sdsd'))
->setProject($project1);
$timesheet2 = new Timesheet();
$timesheet2
->setBegin(new DateTime('2018-11-29'))
->setEnd(new DateTime())
->setDuration(400)
->setRate(84.75)
->setUser($user1)
->setActivity((new Activity())->setName('bar'))
->setProject($project2);
$timesheet3 = new Timesheet();
$timesheet3
->setBegin(new DateTime('2018-11-28'))
->setEnd(new DateTime())
->setDuration(1800)
->setRate(111.11)
->setUser($user1)
->setActivity((new Activity())->setName('foo'))
->setProject($project1);
$timesheet4 = new Timesheet();
$timesheet4
->setBegin(new DateTime())
->setEnd(new DateTime())
->setDuration(400)
->setRate(1947.99)
->setUser($user1)
->setActivity((new Activity())->setName('blub'))
->setProject($project2);
$timesheet5 = new Timesheet();
$timesheet5
->setBegin(new DateTime('2018-11-28'))
->setEnd(new DateTime())
->setDuration(400)
->setRate(84)
->setUser($user2)
->setActivity(new Activity())
->setProject($project3);
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
$query = new InvoiceQuery();
$query->setProjects([$project1]);
$model = (new InvoiceModelFactoryFactory($this))->create()->createModel(new DebugFormatter());
$model->setCustomer($customer);
$model->setTemplate($template);
$model->addEntries($entries);
$model->setQuery($query);
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('date_user', $sut->getId());
$this->assertEquals(3000.13, $sut->getTotal());
$this->assertEquals(19, $sut->getVat());
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2521.12, $sut->getSubtotal());
$this->assertEquals(6600, $sut->getTimeWorked());
$entries = $sut->getEntries();
self::assertCount(4, $entries);
$this->assertEquals(378.02, $entries[0]->getRate());
$this->assertEquals(111.11, $entries[1]->getRate());
$this->assertEquals(1947.99, $entries[2]->getRate());
$this->assertEquals(84, $entries[3]->getRate());
self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate() + $entries[2]->getRate() + $entries[3]->getRate());
}
public function testDescriptionByTimesheet(): void
{
$this->assertDescription($this->getCalculator(), false, false);
}
}

View File

@@ -15,6 +15,7 @@ use App\Entity\InvoiceTemplate;
use App\Entity\Tag;
use App\Entity\Timesheet;
use App\Invoice\Calculator\DefaultCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -25,12 +26,12 @@ use App\Tests\Mocks\InvoiceModelFactoryFactory;
*/
class DefaultCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new DefaultCalculator());
return new DefaultCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$date = new \DateTime();
$customer = new Customer('foo');
@@ -69,7 +70,7 @@ class DefaultCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery(new InvoiceQuery());
$sut = new DefaultCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('default', $sut->getId());

View File

@@ -15,8 +15,8 @@ use App\Entity\InvoiceTemplate;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\DateInvoiceCalculator;
use App\Invoice\Calculator\PriceInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -30,12 +30,12 @@ use DateTime;
*/
class PriceInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new DateInvoiceCalculator());
return new PriceInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -118,7 +118,7 @@ class PriceInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new PriceInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('price', $sut->getId());
@@ -136,8 +136,8 @@ class PriceInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals(84, $entries[3]->getRate());
}
public function testDescriptionByTimesheet()
public function testDescriptionByTimesheet(): void
{
$this->assertDescription(new PriceInvoiceCalculator(), false, false);
$this->assertDescription($this->getCalculator(), false, false);
}
}

View File

@@ -16,6 +16,7 @@ use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\ProjectInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -29,12 +30,12 @@ use DateTime;
*/
class ProjectInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new ProjectInvoiceCalculator());
return new ProjectInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -113,7 +114,7 @@ class ProjectInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new ProjectInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('project', $sut->getId());
@@ -122,7 +123,6 @@ class ProjectInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2521.12, $sut->getSubtotal());
$this->assertEquals(6600, $sut->getTimeWorked());
$this->assertEquals(3, \count($sut->getEntries()));
$entries = $sut->getEntries();
self::assertCount(3, $entries);
@@ -132,8 +132,8 @@ class ProjectInvoiceCalculatorTest extends AbstractCalculatorTest
self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate() + $entries[2]->getRate());
}
public function testDescriptionByProject()
public function testDescriptionByProject(): void
{
$this->assertDescription(new ProjectInvoiceCalculator(), true, false);
$this->assertDescription($this->getCalculator(), true, false);
}
}

View File

@@ -0,0 +1,142 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Invoice\Calculator;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\InvoiceTemplate;
use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\ProjectUserInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
use DateTime;
/**
* @covers \App\Invoice\Calculator\ProjectUserInvoiceCalculator
* @covers \App\Invoice\Calculator\AbstractSumInvoiceCalculator
* @covers \App\Invoice\Calculator\AbstractMergedCalculator
* @covers \App\Invoice\Calculator\AbstractCalculator
*/
class ProjectUserInvoiceCalculatorTest extends AbstractCalculatorTest
{
protected function getCalculator(): CalculatorInterface
{
return new ProjectUserInvoiceCalculator();
}
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
$template->setVat(19);
$user1 = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$user1->method('getId')->willReturn(1);
$user2 = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$user2->method('getId')->willReturn(2);
$project1 = $this->getMockBuilder(Project::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$project1->method('getId')->willReturn(1);
$project2 = $this->getMockBuilder(Project::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$project2->method('getId')->willReturn(2);
$project3 = $this->getMockBuilder(Project::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock();
$project3->method('getId')->willReturn(3);
$timesheet = new Timesheet();
$timesheet
->setBegin(new DateTime())
->setEnd(new DateTime())
->setDuration(3600)
->setRate(293.27)
->setUser($user1)
->setActivity((new Activity())->setName('sdsd'))
->setProject($project1);
$timesheet2 = new Timesheet();
$timesheet2
->setBegin(new DateTime())
->setEnd(new DateTime())
->setDuration(400)
->setRate(84.75)
->setUser($user1)
->setActivity((new Activity())->setName('bar'))
->setProject($project2);
$timesheet3 = new Timesheet();
$timesheet3
->setBegin(new DateTime())
->setEnd(new DateTime())
->setDuration(1800)
->setRate(111.11)
->setUser($user1)
->setActivity((new Activity())->setName('foo'))
->setProject($project1);
$timesheet4 = new Timesheet();
$timesheet4
->setBegin(new DateTime())
->setEnd(new DateTime())
->setDuration(400)
->setRate(1947.99)
->setUser($user1)
->setActivity((new Activity())->setName('blub'))
->setProject($project2);
$timesheet5 = new Timesheet();
$timesheet5
->setBegin(new DateTime())
->setEnd(new DateTime())
->setDuration(400)
->setRate(84)
->setUser($user2)
->setActivity(new Activity())
->setProject($project3);
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
$query = new InvoiceQuery();
$query->setProjects([$project1]);
$model = (new InvoiceModelFactoryFactory($this))->create()->createModel(new DebugFormatter());
$model->setCustomer($customer);
$model->setTemplate($template);
$model->addEntries($entries);
$model->setQuery($query);
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('project_user', $sut->getId());
$this->assertEquals(3000.13, $sut->getTotal());
$this->assertEquals(19, $sut->getVat());
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2521.12, $sut->getSubtotal());
$this->assertEquals(6600, $sut->getTimeWorked());
$entries = $sut->getEntries();
self::assertCount(3, $entries);
$this->assertEquals(404.38, $entries[0]->getRate());
$this->assertEquals(2032.74, $entries[1]->getRate());
$this->assertEquals(84, $entries[2]->getRate());
self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate() + $entries[2]->getRate());
}
public function testDescriptionByProject(): void
{
$this->assertDescription($this->getCalculator(), true, false);
}
}

View File

@@ -17,6 +17,7 @@ use App\Entity\Tag;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\ShortInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Invoice\InvoiceItem;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
@@ -29,12 +30,12 @@ use App\Tests\Mocks\InvoiceModelFactoryFactory;
*/
class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new ShortInvoiceCalculator());
return new ShortInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -97,7 +98,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new ShortInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('short', $sut->getId());
@@ -119,7 +120,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals(['foo', 'bar', 'bar1'], $result->getTags());
}
public function testWithMultipleEntriesDifferentRates()
public function testWithMultipleEntriesDifferentRates(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -179,7 +180,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new ShortInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('short', $sut->getId());
@@ -200,7 +201,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals(1, $result->getAmount());
}
public function testWithMixedRateTypes()
public function testWithMixedRateTypes(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -258,7 +259,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new ShortInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('short', $sut->getId());
@@ -279,8 +280,8 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals(1, $result->getAmount());
}
public function testDescriptionByTimesheet()
public function testDescriptionByTimesheet(): void
{
$this->assertDescription(new ShortInvoiceCalculator(), false, false);
$this->assertDescription($this->getCalculator(), false, false);
}
}

View File

@@ -16,6 +16,7 @@ use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\UserInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -27,12 +28,12 @@ use App\Tests\Mocks\InvoiceModelFactoryFactory;
*/
class UserInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new UserInvoiceCalculator());
return new UserInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -111,7 +112,7 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new UserInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('user', $sut->getId());
@@ -120,16 +121,16 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals('EUR', $model->getCurrency());
$this->assertEquals(2521.12, $sut->getSubtotal());
$this->assertEquals(6600, $sut->getTimeWorked());
$this->assertEquals(3, \count($sut->getEntries()));
$entries = $sut->getEntries();
self::assertCount(3, $entries);
$this->assertEquals(404.38, $entries[0]->getRate());
$this->assertEquals(2032.74, $entries[1]->getRate());
$this->assertEquals(84, $entries[2]->getRate());
}
public function testDescriptionByTimesheet()
public function testDescriptionByTimesheet(): void
{
$this->assertDescription(new UserInvoiceCalculator(), false, false);
$this->assertDescription($this->getCalculator(), false, false);
}
}

View File

@@ -16,6 +16,7 @@ use App\Entity\Project;
use App\Entity\Timesheet;
use App\Entity\User;
use App\Invoice\Calculator\WeeklyInvoiceCalculator;
use App\Invoice\CalculatorInterface;
use App\Repository\Query\InvoiceQuery;
use App\Tests\Invoice\DebugFormatter;
use App\Tests\Mocks\InvoiceModelFactoryFactory;
@@ -29,12 +30,12 @@ use DateTime;
*/
class WeeklyInvoiceCalculatorTest extends AbstractCalculatorTest
{
public function testEmptyModel()
protected function getCalculator(): CalculatorInterface
{
$this->assertEmptyModel(new WeeklyInvoiceCalculator());
return new WeeklyInvoiceCalculator();
}
public function testWithMultipleEntries()
public function testWithMultipleEntries(): void
{
$customer = new Customer('foo');
$template = new InvoiceTemplate();
@@ -116,7 +117,7 @@ class WeeklyInvoiceCalculatorTest extends AbstractCalculatorTest
$model->addEntries($entries);
$model->setQuery($query);
$sut = new WeeklyInvoiceCalculator();
$sut = $this->getCalculator();
$sut->setModel($model);
$this->assertEquals('weekly', $sut->getId());
@@ -133,8 +134,8 @@ class WeeklyInvoiceCalculatorTest extends AbstractCalculatorTest
self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate());
}
public function testDescriptionByTimesheet()
public function testDescriptionByTimesheet(): void
{
$this->assertDescription(new WeeklyInvoiceCalculator(), false, false);
$this->assertDescription($this->getCalculator(), false, false);
}
}