use timesheet description in invoices (#1079)

This commit is contained in:
Kevin Papst
2019-09-04 10:54:21 +02:00
committed by GitHub
parent 93ab3d5666
commit 49e1a1c410
15 changed files with 51 additions and 95 deletions

View File

@@ -47,11 +47,12 @@ abstract class AbstractMergedCalculator extends AbstractCalculator
$invoiceItem->setEnd($entry->getEnd()); $invoiceItem->setEnd($entry->getEnd());
} }
if (null !== $this->model->getQuery()->getActivity()) { if (!empty($entry->getDescription())) {
$invoiceItem->setActivity($this->model->getQuery()->getActivity()); $description = '';
$invoiceItem->setDescription($this->model->getQuery()->getActivity()->getName()); if (!empty($invoiceItem->getDescription())) {
} elseif (null !== $this->model->getQuery()->getProject()) { $description = $invoiceItem->getDescription() . PHP_EOL;
$invoiceItem->setDescription($this->model->getQuery()->getProject()->getName()); }
$invoiceItem->setDescription($description . $entry->getDescription());
} }
if (null === $invoiceItem->getActivity()) { if (null === $invoiceItem->getActivity()) {

View File

@@ -47,8 +47,14 @@ abstract class AbstractSumInvoiceCalculator extends AbstractMergedCalculator imp
} }
$timesheet = $invoiceItems[$id]; $timesheet = $invoiceItems[$id];
$this->mergeTimesheets($timesheet, $entry); $this->mergeTimesheets($timesheet, $entry);
$this->mergeSumTimesheet($timesheet, $entry);
} }
return array_values($invoiceItems); return array_values($invoiceItems);
} }
protected function mergeSumTimesheet(InvoiceItem $invoiceItem, Timesheet $entry)
{
// allows to set values per calculator after merging the timesheet
}
} }

View File

@@ -11,6 +11,7 @@ namespace App\Invoice\Calculator;
use App\Entity\Timesheet; use App\Entity\Timesheet;
use App\Invoice\CalculatorInterface; use App\Invoice\CalculatorInterface;
use App\Invoice\InvoiceItem;
/** /**
* A calculator that sums up the timesheet records by activity. * A calculator that sums up the timesheet records by activity.
@@ -26,6 +27,12 @@ class ActivityInvoiceCalculator extends AbstractSumInvoiceCalculator implements
return (string) $timesheet->getActivity()->getId(); return (string) $timesheet->getActivity()->getId();
} }
protected function mergeSumTimesheet(InvoiceItem $invoiceItem, Timesheet $entry)
{
$invoiceItem->setActivity($entry->getActivity());
$invoiceItem->setDescription($entry->getActivity()->getName());
}
/** /**
* @return string * @return string
*/ */

View File

@@ -11,6 +11,7 @@ namespace App\Invoice\Calculator;
use App\Entity\Timesheet; use App\Entity\Timesheet;
use App\Invoice\CalculatorInterface; use App\Invoice\CalculatorInterface;
use App\Invoice\InvoiceItem;
/** /**
* A calculator that sums up the timesheet records by project. * A calculator that sums up the timesheet records by project.
@@ -26,6 +27,12 @@ class ProjectInvoiceCalculator extends AbstractSumInvoiceCalculator implements C
return (string) $timesheet->getProject()->getId(); return (string) $timesheet->getProject()->getId();
} }
protected function mergeSumTimesheet(InvoiceItem $invoiceItem, Timesheet $entry)
{
$invoiceItem->setProject($entry->getProject());
$invoiceItem->setDescription($entry->getProject()->getName());
}
/** /**
* @return string * @return string
*/ */

View File

@@ -9,37 +9,21 @@
namespace App\Invoice\Calculator; namespace App\Invoice\Calculator;
use App\Entity\Timesheet;
use App\Invoice\CalculatorInterface; use App\Invoice\CalculatorInterface;
use App\Invoice\InvoiceItem;
/** /**
* A calculator that sums up the timesheet records by user. * A calculator that sums up the timesheet records by user.
*/ */
class UserInvoiceCalculator extends AbstractMergedCalculator implements CalculatorInterface class UserInvoiceCalculator extends AbstractSumInvoiceCalculator implements CalculatorInterface
{ {
/** protected function calculateSumIdentifier(Timesheet $timesheet): string
* @return InvoiceItem[]
*/
public function getEntries()
{ {
$entries = $this->model->getEntries(); if (null === $timesheet->getUser()->getId()) {
if (empty($entries)) { throw new \Exception('Cannot handle un-persisted user');
return [];
} }
/** @var InvoiceItem[] $invoiceItems */ return (string) $timesheet->getUser()->getId();
$invoiceItems = [];
foreach ($entries as $entry) {
$id = $entry->getUser()->getId();
if (!isset($invoiceItems[$id])) {
$invoiceItems[$id] = new InvoiceItem();
}
$invoiceItem = $invoiceItems[$id];
$this->mergeTimesheets($invoiceItem, $entry);
}
return array_values($invoiceItems);
} }
/** /**

View File

@@ -75,9 +75,9 @@
{% endif %} {% endif %}
<tr> <tr>
<td>{{ entry.begin|date_short }}</td> <td>{{ entry.begin|date_short }}</td>
<td> <td contenteditable="true">
{% if entry.description is not empty %} {% if entry.description is not empty %}
{{ entry.description }} {{ entry.description|nl2br }}
{% else %} {% else %}
{{ entry.activity.name }} / {{ entry.project.name }} {{ entry.activity.name }} / {{ entry.project.name }}
{% endif %} {% endif %}

View File

@@ -90,7 +90,7 @@
<tr> <tr>
<td contenteditable="true"> <td contenteditable="true">
{% if entry.description is not empty %} {% if entry.description is not empty %}
{{ entry.description }} {{ entry.description|nl2br }}
{% else %} {% else %}
{{ entry.activity.name }} / {{ entry.project.name }} {{ entry.activity.name }} / {{ entry.project.name }}
{% endif %} {% endif %}

View File

@@ -72,9 +72,9 @@
{% if model.query.user is empty %} {% if model.query.user is empty %}
<td>{{ widgets.username(entry.user) }}</td> <td>{{ widgets.username(entry.user) }}</td>
{% endif %} {% endif %}
<td> <td contenteditable="true">
{% if entry.description is not empty %} {% if entry.description is not empty %}
{{ entry.description }} {{ entry.description|nl2br }}
{% else %} {% else %}
{{ entry.activity.name }} / {{ entry.project.name }} {{ entry.activity.name }} / {{ entry.project.name }}
{% endif %} {% endif %}

View File

@@ -50,24 +50,19 @@ abstract class AbstractCalculatorTest extends TestCase
$template = new InvoiceTemplate(); $template = new InvoiceTemplate();
$template->setVat(19); $template->setVat(19);
$user = $this->getMockBuilder(User::class)->setMethods(['getId'])->disableOriginalConstructor()->getMock();
$user->method('getId')->willReturn(1);
$project = $this->getMockBuilder(Project::class)->setMethods(['getId', 'getCustomer', 'getName'])->disableOriginalConstructor()->getMock(); $project = $this->getMockBuilder(Project::class)->setMethods(['getId', 'getCustomer', 'getName'])->disableOriginalConstructor()->getMock();
$project->method('getId')->willReturn(1); $project->method('getId')->willReturn(1);
$project->method('getCustomer')->willReturn($customer); $project->method('getCustomer')->willReturn($customer);
$project->method('getName')->willReturn('project description'); $project->method('getName')->willReturn('project description');
$project1 = $this->getMockBuilder(Project::class)->setMethods(['getId', 'getName'])->disableOriginalConstructor()->getMock();
$project1->method('getId')->willReturn(1);
$project1->method('getName')->willReturn('bar');
$activity = $this->getMockBuilder(Activity::class)->setMethods(['getId', 'getProject', 'getName'])->disableOriginalConstructor()->getMock(); $activity = $this->getMockBuilder(Activity::class)->setMethods(['getId', 'getProject', 'getName'])->disableOriginalConstructor()->getMock();
$activity->method('getId')->willReturn(1); $activity->method('getId')->willReturn(1);
$activity->method('getProject')->willReturn($project); $activity->method('getProject')->willReturn($project);
$activity->method('getName')->willReturn('activity description'); $activity->method('getName')->willReturn('activity description');
$activity1 = $this->getMockBuilder(Activity::class)->setMethods(['getId', 'getName'])->disableOriginalConstructor()->getMock();
$activity1->method('getId')->willReturn(1);
$activity1->method('getName')->willReturn('foo');
$query = new InvoiceQuery(); $query = new InvoiceQuery();
if ($addProject === true) { if ($addProject === true) {
$query->setProject($project); $query->setProject($project);
@@ -81,9 +76,9 @@ abstract class AbstractCalculatorTest extends TestCase
->setBegin(new \DateTime()) ->setBegin(new \DateTime())
->setDuration(3600) ->setDuration(3600)
->setRate(293.27) ->setRate(293.27)
->setUser(new User()) ->setUser($user)
->setActivity($activity1) ->setActivity($activity)
->setProject($project1); ->setProject($project);
$model = new InvoiceModel(); $model = new InvoiceModel();
$model->setCustomer($customer); $model->setCustomer($customer);
@@ -101,7 +96,7 @@ abstract class AbstractCalculatorTest extends TestCase
} elseif ($addActivity === true) { } elseif ($addActivity === true) {
$this->assertEquals('activity description', $result->getDescription()); $this->assertEquals('activity description', $result->getDescription());
} else { } else {
$this->assertEquals('foo', $result->getDescription()); $this->assertEquals('timesheet description', $result->getDescription());
} }
} }
} }

View File

@@ -128,18 +128,8 @@ class ActivityInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals(84, $entries[2]->getRate()); $this->assertEquals(84, $entries[2]->getRate());
} }
public function testDescriptionByTimesheet()
{
$this->assertDescription(new ActivityInvoiceCalculator(), false, false);
}
public function testDescriptionByActivity() public function testDescriptionByActivity()
{ {
$this->assertDescription(new ActivityInvoiceCalculator(), false, true); $this->assertDescription(new ActivityInvoiceCalculator(), false, true);
} }
public function testDescriptionByProject()
{
$this->assertDescription(new ActivityInvoiceCalculator(), true, false);
}
} }

View File

@@ -135,14 +135,4 @@ class DateInvoiceCalculatorTest extends AbstractCalculatorTest
{ {
$this->assertDescription(new DateInvoiceCalculator(), false, false); $this->assertDescription(new DateInvoiceCalculator(), false, false);
} }
public function testDescriptionByActivity()
{
$this->assertDescription(new DateInvoiceCalculator(), false, true);
}
public function testDescriptionByProject()
{
$this->assertDescription(new DateInvoiceCalculator(), true, false);
}
} }

View File

@@ -35,18 +35,21 @@ class DefaultCalculatorTest extends AbstractCalculatorTest
$template->setVat(19); $template->setVat(19);
$timesheet = new Timesheet(); $timesheet = new Timesheet();
$timesheet->setDescription('foo 1');
$timesheet->setBegin(new \DateTime()); $timesheet->setBegin(new \DateTime());
$timesheet->setDuration(3600); $timesheet->setDuration(3600);
$timesheet->setRate(293.27); $timesheet->setRate(293.27);
$timesheet->setActivity(new Activity()); $timesheet->setActivity(new Activity());
$timesheet2 = new Timesheet(); $timesheet2 = new Timesheet();
$timesheet2->setDescription('foo 2');
$timesheet2->setBegin(new \DateTime()); $timesheet2->setBegin(new \DateTime());
$timesheet2->setDuration(400); $timesheet2->setDuration(400);
$timesheet2->setRate(84); $timesheet2->setRate(84);
$timesheet2->setActivity(new Activity()); $timesheet2->setActivity(new Activity());
$timesheet3 = new Timesheet(); $timesheet3 = new Timesheet();
$timesheet3->setDescription('foo 3');
$timesheet3->setBegin(new \DateTime()); $timesheet3->setBegin(new \DateTime());
$timesheet3->setDuration(1800); $timesheet3->setDuration(1800);
$timesheet3->setRate(111.11); $timesheet3->setRate(111.11);

View File

@@ -131,16 +131,6 @@ class ProjectInvoiceCalculatorTest extends AbstractCalculatorTest
self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate() + $entries[2]->getRate()); self::assertEquals(2521.12, $entries[0]->getRate() + $entries[1]->getRate() + $entries[2]->getRate());
} }
public function testDescriptionByTimesheet()
{
$this->assertDescription(new ProjectInvoiceCalculator(), false, false);
}
public function testDescriptionByActivity()
{
$this->assertDescription(new ProjectInvoiceCalculator(), false, true);
}
public function testDescriptionByProject() public function testDescriptionByProject()
{ {
$this->assertDescription(new ProjectInvoiceCalculator(), true, false); $this->assertDescription(new ProjectInvoiceCalculator(), true, false);

View File

@@ -190,14 +190,4 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
{ {
$this->assertDescription(new ShortInvoiceCalculator(), false, false); $this->assertDescription(new ShortInvoiceCalculator(), false, false);
} }
public function testDescriptionByActivity()
{
$this->assertDescription(new ShortInvoiceCalculator(), false, true);
}
public function testDescriptionByProject()
{
$this->assertDescription(new ShortInvoiceCalculator(), true, false);
}
} }

View File

@@ -46,6 +46,9 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTest
$user2 = $this->getMockBuilder(User::class)->setMethods(['getId'])->disableOriginalConstructor()->getMock(); $user2 = $this->getMockBuilder(User::class)->setMethods(['getId'])->disableOriginalConstructor()->getMock();
$user2->method('getId')->willReturn(2); $user2->method('getId')->willReturn(2);
$user3 = $this->getMockBuilder(User::class)->setMethods(['getId'])->disableOriginalConstructor()->getMock();
$user3->method('getId')->willReturn(3);
$timesheet = new Timesheet(); $timesheet = new Timesheet();
$timesheet $timesheet
->setBegin(new \DateTime()) ->setBegin(new \DateTime())
@@ -92,7 +95,7 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTest
->setEnd(new \DateTime()) ->setEnd(new \DateTime())
->setDuration(400) ->setDuration(400)
->setRate(84) ->setRate(84)
->setUser(new User()) ->setUser($user3)
->setActivity($activity) ->setActivity($activity)
->setProject((new Project())->setName('bar')); ->setProject((new Project())->setName('bar'));
@@ -128,14 +131,4 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTest
{ {
$this->assertDescription(new UserInvoiceCalculator(), false, false); $this->assertDescription(new UserInvoiceCalculator(), false, false);
} }
public function testDescriptionByActivity()
{
$this->assertDescription(new UserInvoiceCalculator(), false, true);
}
public function testDescriptionByProject()
{
$this->assertDescription(new UserInvoiceCalculator(), true, false);
}
} }