support tags in invoices (#2526)

This commit is contained in:
Kevin Papst
2021-04-23 17:06:42 +02:00
committed by GitHub
parent 67d23ec6b2
commit bb94b11e37
9 changed files with 59 additions and 5 deletions

View File

@@ -114,5 +114,11 @@ abstract class AbstractMergedCalculator extends AbstractCalculator
if (empty($invoiceItem->getDescription()) && null !== $entry->getActivity()) { if (empty($invoiceItem->getDescription()) && null !== $entry->getActivity()) {
$invoiceItem->setDescription($entry->getActivity()->getName()); $invoiceItem->setDescription($entry->getActivity()->getName());
} }
if ($entry instanceof Timesheet) {
foreach ($entry->getTagsAsArray() as $tag) {
$invoiceItem->addTag($tag);
}
}
} }
} }

View File

@@ -62,6 +62,7 @@ class InvoiceItemDefaultHydrator implements InvoiceItemHydrator
'entry.description' => $description, 'entry.description' => $description,
'entry.amount' => $amount, 'entry.amount' => $amount,
'entry.type' => $item->getType(), 'entry.type' => $item->getType(),
'entry.tags' => implode(', ', $item->getTags()),
'entry.category' => $item->getCategory(), 'entry.category' => $item->getCategory(),
'entry.rate' => $formatter->getFormattedMoney($appliedRate, $currency), 'entry.rate' => $formatter->getFormattedMoney($appliedRate, $currency),
'entry.rate_nc' => $formatter->getFormattedMoney($appliedRate, $currency, false), 'entry.rate_nc' => $formatter->getFormattedMoney($appliedRate, $currency, false),

View File

@@ -75,6 +75,10 @@ final class InvoiceItem
* @var string * @var string
*/ */
private $category; private $category;
/**
* @var string[]
*/
private $tags = [];
public function addAdditionalField(string $name, ?string $value): InvoiceItem public function addAdditionalField(string $name, ?string $value): InvoiceItem
{ {
@@ -269,4 +273,23 @@ final class InvoiceItem
return $this; return $this;
} }
public function addTag(string $tag): void
{
foreach ($this->tags as $t) {
if (strcasecmp($tag, $t) === 0) {
return;
}
}
$this->tags[] = $tag;
}
/**
* @return string[]
*/
public function getTags(): array
{
return $this->tags;
}
} }

View File

@@ -288,6 +288,8 @@
if (jQuery(field).data('daterangepicker') !== undefined) { if (jQuery(field).data('daterangepicker') !== undefined) {
jQuery(field).data('daterangepicker').setStartDate(momentObj); jQuery(field).data('daterangepicker').setStartDate(momentObj);
jQuery(field).data('daterangepicker').setEndDate(momentObj); jQuery(field).data('daterangepicker').setEndDate(momentObj);
{# make sure that the project list is reloaded and the dates can be compared against the project end date #}
jQuery('#{{ blockPrefix }}_customer').trigger('change');
} }
} }
</script> </script>

View File

@@ -12,6 +12,7 @@ namespace App\Tests\Invoice\Calculator;
use App\Entity\Activity; use App\Entity\Activity;
use App\Entity\Customer; use App\Entity\Customer;
use App\Entity\InvoiceTemplate; use App\Entity\InvoiceTemplate;
use App\Entity\Tag;
use App\Entity\Timesheet; use App\Entity\Timesheet;
use App\Invoice\Calculator\DefaultCalculator; use App\Invoice\Calculator\DefaultCalculator;
use App\Invoice\InvoiceModel; use App\Invoice\InvoiceModel;
@@ -31,27 +32,31 @@ class DefaultCalculatorTest extends AbstractCalculatorTest
public function testWithMultipleEntries() public function testWithMultipleEntries()
{ {
$date = new \DateTime();
$customer = new Customer(); $customer = new Customer();
$template = new InvoiceTemplate(); $template = new InvoiceTemplate();
$template->setVat(19); $template->setVat(19);
$timesheet = new Timesheet(); $timesheet = new Timesheet();
$timesheet->setDescription('foo 1'); $timesheet->setDescription('foo 1');
$timesheet->setBegin(new \DateTime()); $timesheet->setBegin(clone $date);
$timesheet->setDuration(3600); $timesheet->setDuration(3600);
$timesheet->setRate(293.27); $timesheet->setRate(293.27);
$timesheet->setActivity(new Activity()); $timesheet->setActivity(new Activity());
$timesheet->addTag((new Tag())->setName('foo'));
$timesheet->addTag((new Tag())->setName('bar'));
$timesheet2 = new Timesheet(); $timesheet2 = new Timesheet();
$timesheet2->setDescription('foo 2'); $timesheet2->setDescription('foo 2');
$timesheet2->setBegin(new \DateTime()); $timesheet2->setBegin(clone $date);
$timesheet2->setDuration(400); $timesheet2->setDuration(400);
$timesheet2->setRate(84); $timesheet2->setRate(84);
$timesheet2->setActivity(new Activity()); $timesheet2->setActivity(new Activity());
$timesheet2->addTag((new Tag())->setName('bar1'));
$timesheet3 = new Timesheet(); $timesheet3 = new Timesheet();
$timesheet3->setDescription('foo 3'); $timesheet3->setDescription('foo 3');
$timesheet3->setBegin(new \DateTime()); $timesheet3->setBegin(clone $date);
$timesheet3->setDuration(1800); $timesheet3->setDuration(1800);
$timesheet3->setRate(111.11); $timesheet3->setRate(111.11);
$timesheet3->setActivity(new Activity()); $timesheet3->setActivity(new Activity());

View File

@@ -13,6 +13,7 @@ use App\Entity\Activity;
use App\Entity\Customer; use App\Entity\Customer;
use App\Entity\InvoiceTemplate; use App\Entity\InvoiceTemplate;
use App\Entity\Project; use App\Entity\Project;
use App\Entity\Tag;
use App\Entity\Timesheet; use App\Entity\Timesheet;
use App\Entity\User; use App\Entity\User;
use App\Invoice\Calculator\ShortInvoiceCalculator; use App\Invoice\Calculator\ShortInvoiceCalculator;
@@ -56,6 +57,8 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
->setProject($project) ->setProject($project)
->setBegin(new \DateTime()) ->setBegin(new \DateTime())
->setEnd(new \DateTime()) ->setEnd(new \DateTime())
->addTag((new Tag())->setName('foo'))
->addTag((new Tag())->setName('bar'))
; ;
$timesheet2 = new Timesheet(); $timesheet2 = new Timesheet();
@@ -68,6 +71,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
->setProject($project) ->setProject($project)
->setBegin(new \DateTime()) ->setBegin(new \DateTime())
->setEnd(new \DateTime()) ->setEnd(new \DateTime())
->addTag((new Tag())->setName('bar1'))
; ;
$timesheet3 = new Timesheet(); $timesheet3 = new Timesheet();
@@ -112,6 +116,7 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTest
$this->assertEquals(472.5, $result->getRate()); $this->assertEquals(472.5, $result->getRate());
$this->assertEquals(5800, $result->getDuration()); $this->assertEquals(5800, $result->getDuration());
$this->assertEquals(3, $result->getAmount()); $this->assertEquals(3, $result->getAmount());
$this->assertEquals(['foo', 'bar', 'bar1'], $result->getTags());
} }
public function testWithMultipleEntriesDifferentRates() public function testWithMultipleEntriesDifferentRates()

View File

@@ -79,6 +79,7 @@ class InvoiceItemDefaultHydratorTest extends TestCase
'entry.customer.meta.foo-customer', 'entry.customer.meta.foo-customer',
'entry.category', 'entry.category',
'entry.type', 'entry.type',
'entry.tags',
]; ];
$keys = array_merge($keys, $metaFields); $keys = array_merge($keys, $metaFields);

View File

@@ -42,5 +42,15 @@ class InvoiceItemTest extends TestCase
self::assertEquals(0, $sut->getDuration()); self::assertEquals(0, $sut->getDuration());
self::assertNull($sut->getCategory()); self::assertNull($sut->getCategory());
self::assertNull($sut->getType()); self::assertNull($sut->getType());
self::assertEquals([], $sut->getTags());
$sut->addTag('foo');
$sut->addTag('foo');
$sut->addTag('foo1');
$sut->addTag('BaR');
$sut->addTag('bar');
$sut->addTag('FOO');
$sut->addTag('bar');
$sut->addTag('foo1');
self::assertEquals(['foo', 'foo1', 'BaR'], $sut->getTags());
} }
} }

View File

@@ -143,7 +143,7 @@ class DebugRendererTest extends TestCase
'user.title', 'user.title',
'user.meta.hello', 'user.meta.hello',
'user.meta.kitty', 'user.meta.kitty',
'testFromModelHydrator' 'testFromModelHydrator',
]; ];
if ($activityCounter > 1) { if ($activityCounter > 1) {
@@ -242,7 +242,8 @@ class DebugRendererTest extends TestCase
'entry.customer.meta.foo-customer', 'entry.customer.meta.foo-customer',
'entry.category', 'entry.category',
'entry.type', 'entry.type',
'testFromItemHydrator' 'testFromItemHydrator',
'entry.tags',
]; ];
$keys = array_merge($keys, $metaFields); $keys = array_merge($keys, $metaFields);