diff --git a/src/Invoice/Calculator/WeeklyInvoiceCalculator.php b/src/Invoice/Calculator/WeeklyInvoiceCalculator.php new file mode 100644 index 00000000..5f50303b --- /dev/null +++ b/src/Invoice/Calculator/WeeklyInvoiceCalculator.php @@ -0,0 +1,32 @@ +getBegin()->format('W'); + } + + /** + * @return string + */ + public function getId(): string + { + return 'weekly'; + } +} diff --git a/src/Invoice/Hydrator/InvoiceItemDefaultHydrator.php b/src/Invoice/Hydrator/InvoiceItemDefaultHydrator.php index 438ed95c..19c95d06 100644 --- a/src/Invoice/Hydrator/InvoiceItemDefaultHydrator.php +++ b/src/Invoice/Hydrator/InvoiceItemDefaultHydrator.php @@ -83,6 +83,8 @@ class InvoiceItemDefaultHydrator implements InvoiceItemHydrator 'entry.end_time' => $formatter->getFormattedTime($end), 'entry.end_timestamp' => $end->getTimestamp(), 'entry.date' => $formatter->getFormattedDateTime($begin), + 'entry.week' => \intval($begin->format('W')), + 'entry.weekyear' => $begin->format('o'), 'entry.user_id' => $user->getId(), 'entry.user_name' => $user->getUsername(), 'entry.user_title' => $user->getTitle(), diff --git a/tests/Invoice/Calculator/WeeklyInvoiceCalculatorTest.php b/tests/Invoice/Calculator/WeeklyInvoiceCalculatorTest.php new file mode 100644 index 00000000..bc5ddd66 --- /dev/null +++ b/tests/Invoice/Calculator/WeeklyInvoiceCalculatorTest.php @@ -0,0 +1,137 @@ +assertEmptyModel(new WeeklyInvoiceCalculator()); + } + + public function testWithMultipleEntries() + { + $customer = new Customer(); + $template = new InvoiceTemplate(); + $template->setVat(19); + + $user = $this->getMockBuilder(User::class)->onlyMethods(['getId'])->disableOriginalConstructor()->getMock(); + $user->method('getId')->willReturn(1); + + $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($user) + ->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($user) + ->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($user) + ->setActivity((new Activity())->setName('foo')) + ->setProject($project1); + + $timesheet4 = new Timesheet(); + $timesheet4 + ->setBegin(new DateTime()) + ->setEnd(new DateTime('2018-11-28')) + ->setDuration(400) + ->setRate(1947.99) + ->setUser($user) + ->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(new User()) + ->setActivity(new Activity()) + ->setProject($project3); + + $entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5]; + + $query = new InvoiceQuery(); + $query->setProjects([$project1]); + + $model = new InvoiceModel(new DebugFormatter()); + $model->setCustomer($customer); + $model->setTemplate($template); + $model->addEntries($entries); + $model->setQuery($query); + + $sut = new WeeklyInvoiceCalculator(); + $sut->setModel($model); + + $this->assertEquals('weekly', $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(2, $entries); + $this->assertEquals(573.13, $entries[0]->getRate()); + $this->assertEquals(1947.99, $entries[1]->getRate()); + self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate()); + } + + public function testDescriptionByTimesheet() + { + $this->assertDescription(new WeeklyInvoiceCalculator(), false, false); + } +} diff --git a/tests/Invoice/Hydrator/InvoiceItemDefaultHydratorTest.php b/tests/Invoice/Hydrator/InvoiceItemDefaultHydratorTest.php index 92254b94..396a51e6 100644 --- a/tests/Invoice/Hydrator/InvoiceItemDefaultHydratorTest.php +++ b/tests/Invoice/Hydrator/InvoiceItemDefaultHydratorTest.php @@ -62,6 +62,8 @@ class InvoiceItemDefaultHydratorTest extends TestCase 'entry.end_time', 'entry.end_timestamp', 'entry.date', + 'entry.week', + 'entry.weekyear', 'entry.user_id', 'entry.user_name', 'entry.user_alias', diff --git a/tests/Invoice/Renderer/DebugRendererTest.php b/tests/Invoice/Renderer/DebugRendererTest.php index d14a5cb9..f2934532 100644 --- a/tests/Invoice/Renderer/DebugRendererTest.php +++ b/tests/Invoice/Renderer/DebugRendererTest.php @@ -225,6 +225,8 @@ class DebugRendererTest extends TestCase 'entry.end_time', 'entry.end_timestamp', 'entry.date', + 'entry.week', + 'entry.weekyear', 'entry.user_id', 'entry.user_name', 'entry.user_alias', diff --git a/translations/invoice-calculator.de.xlf b/translations/invoice-calculator.de.xlf index 96feaaac..74755b2b 100644 --- a/translations/invoice-calculator.de.xlf +++ b/translations/invoice-calculator.de.xlf @@ -30,6 +30,10 @@ date Datum: ein Eintrag pro Tag (verwendet Startdatum) + + weekly + Wöchentlich: ein Eintrag pro Woche (verwendet Startdatum) + diff --git a/translations/invoice-calculator.en.xlf b/translations/invoice-calculator.en.xlf index 5dbc0986..f3427283 100644 --- a/translations/invoice-calculator.en.xlf +++ b/translations/invoice-calculator.en.xlf @@ -30,6 +30,10 @@ date Date: one entry per day (uses start date) + + weekly + Weekly: one entry per week (uses start date) +