change data filter on project month report (#2911)

This commit is contained in:
Kevin Papst
2021-11-05 09:45:12 +01:00
committed by GitHub
parent 042c119058
commit c8854b0775
15 changed files with 199 additions and 36 deletions

View File

@@ -13,3 +13,43 @@ form.form-narrow {
margin: 0 0 5px 0; margin: 0 0 5px 0;
} }
} }
/* bootstrap3 hack because the filter look plain ugly without it (see report: project month) */
.checkbox-menu li label {
display: block;
padding: 5px 15px 5px 10px !important;
clear: both;
font-weight: normal;
line-height: 1.42857143;
color: #333;
white-space: nowrap;
margin:0;
transition: background-color .4s ease;
}
.checkbox-menu li div.checkbox {
display: block;
width: 100%;
}
.checkbox-menu li div.radio {
display: block;
width: 100%;
}
.checkbox-menu li input {
margin: 0 5px !important;
position: relative;
}
.checkbox-menu li.active label {
background-color: #cbcbff;
font-weight:bold;
}
.checkbox-menu li label:hover,
.checkbox-menu li label:focus {
background-color: #f5f5f5;
}
.checkbox-menu li.active label:hover,
.checkbox-menu li.active label:focus {
background-color: #b8b8ff;
}

File diff suppressed because one or more lines are too long

View File

@@ -6,7 +6,7 @@
"build/app.da44b7f8.js" "build/app.da44b7f8.js"
], ],
"css": [ "css": [
"build/app.d2b280dd.css" "build/app.3bc2b4d9.css"
] ]
}, },
"invoice": { "invoice": {

View File

@@ -1,5 +1,5 @@
{ {
"build/app.css": "build/app.d2b280dd.css", "build/app.css": "build/app.3bc2b4d9.css",
"build/app.js": "build/app.da44b7f8.js", "build/app.js": "build/app.da44b7f8.js",
"build/invoice.css": "build/invoice.ff32661a.css", "build/invoice.css": "build/invoice.ff32661a.css",
"build/invoice.js": "build/invoice.19f36eca.js", "build/invoice.js": "build/invoice.19f36eca.js",

View File

@@ -33,7 +33,7 @@ final class ProjectDateRangeController extends AbstractController
$form = $this->createForm(ProjectDateRangeForm::class, $query, [ $form = $this->createForm(ProjectDateRangeForm::class, $query, [
'timezone' => $user->getTimezone() 'timezone' => $user->getTimezone()
]); ]);
$form->submit($request->query->all(), false); $form->handleRequest($request);
$dateRange = new DateRange(true); $dateRange = new DateRange(true);
$dateRange->setBegin($query->getMonth()); $dateRange->setBegin($query->getMonth());

View File

@@ -18,6 +18,8 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
*/ */
class BudgetType extends AbstractType class BudgetType extends AbstractType
{ {
public const TYPE_MONTH = 'month';
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@@ -25,9 +27,12 @@ class BudgetType extends AbstractType
{ {
$resolver->setDefaults([ $resolver->setDefaults([
'label' => 'label.budgetType', 'label' => 'label.budgetType',
// not yet translated in enough languages
//'placeholder' => 'label.budgetType_full',
'required' => false, 'required' => false,
'search' => false,
'choices' => [ 'choices' => [
'label.budgetType_month' => 'month', 'label.budgetType_month' => self::TYPE_MONTH,
], ],
]); ]);
} }

View File

@@ -152,7 +152,7 @@ class ProjectStatisticService
->setParameter('end', $end, Types::DATETIME_MUTABLE) ->setParameter('end', $end, Types::DATETIME_MUTABLE)
; ;
if ($query->isOnlyWithRecords()) { if (!$query->isIncludeNoWork()) {
$qb2 = $this->repository->createQueryBuilder('t1'); $qb2 = $this->repository->createQueryBuilder('t1');
$qb2 $qb2
->select('1') ->select('1')
@@ -163,15 +163,28 @@ class ProjectStatisticService
$qb->andWhere($qb->expr()->exists($qb2)); $qb->andWhere($qb->expr()->exists($qb2));
} }
if (!$query->isIncludeNoBudget()) { if ($query->isIncludeNoBudget()) {
$qb $qb->andWhere(
->andWhere( $qb->expr()->eq('p.budget', 0.0),
$qb->expr()->eq('p.timeBudget', 0)
);
} else {
$qb->andWhere(
$qb->expr()->orX( $qb->expr()->orX(
$qb->expr()->gt('p.budget', 0.0), $qb->expr()->gt('p.budget', 0.0),
$qb->expr()->gt('p.timeBudget', 0) $qb->expr()->gt('p.timeBudget', 0)
) )
) );
; if ($query->isBudgetTypeMonthly()) {
$qb->andWhere(
$qb->expr()->eq('p.budgetType', ':typeMonth')
);
$qb->setParameter('typeMonth', 'month');
} else {
$qb->andWhere(
$qb->expr()->isNull('p.budgetType')
);
}
} }
if ($query->getCustomer() !== null) { if ($query->getCustomer() !== null) {

View File

@@ -13,6 +13,7 @@ use App\Form\Type\CustomerType;
use App\Form\Type\MonthPickerType; use App\Form\Type\MonthPickerType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -45,9 +46,20 @@ class ProjectDateRangeForm extends AbstractType
'model_timezone' => $options['timezone'], 'model_timezone' => $options['timezone'],
]); ]);
$builder->add('includeNoBudget', CheckboxType::class, [ $builder->add('includeNoWork', CheckboxType::class, [
'required' => false, 'required' => false,
'label' => 'label.includeNoBudget', 'label' => 'label.includeNoWork',
]);
$builder->add('budgetType', ChoiceType::class, [
'required' => true,
'multiple' => false,
'expanded' => true,
'choices' => [
'label.includeNoBudget' => 'none',
'label.includeBudgetType_full' => 'full',
'label.includeBudgetType_month' => 'month',
],
]); ]);
} }

View File

@@ -27,8 +27,8 @@ final class ProjectDateRangeQuery
*/ */
private $customer; private $customer;
private $includeNoBudget = false; private $includeNoWork = true;
private $onlyWithRecords = false; private $budgetType = 'month';
public function __construct(\DateTime $month, User $user) public function __construct(\DateTime $month, User $user)
{ {
@@ -38,22 +38,17 @@ final class ProjectDateRangeQuery
public function isIncludeNoBudget(): bool public function isIncludeNoBudget(): bool
{ {
return $this->includeNoBudget; return $this->budgetType === 'none';
} }
public function setIncludeNoBudget(bool $includeNoBudget): void public function isIncludeNoWork(): bool
{ {
$this->includeNoBudget = $includeNoBudget; return $this->includeNoWork;
} }
public function isOnlyWithRecords(): bool public function setIncludeNoWork(bool $includeNoWork): void
{ {
return $this->onlyWithRecords; $this->includeNoWork = $includeNoWork;
}
public function setOnlyWithRecords(bool $onlyWithRecords): void
{
$this->onlyWithRecords = $onlyWithRecords;
} }
public function getUser(): ?User public function getUser(): ?User
@@ -61,12 +56,12 @@ final class ProjectDateRangeQuery
return $this->user; return $this->user;
} }
public function getMonth(): \DateTime public function getMonth(): ?\DateTime
{ {
return $this->month; return $this->month;
} }
public function setMonth(\DateTime $month): void public function setMonth(?\DateTime $month): void
{ {
$this->month = $month; $this->month = $month;
} }
@@ -80,4 +75,19 @@ final class ProjectDateRangeQuery
{ {
$this->customer = $customer; $this->customer = $customer;
} }
public function isBudgetTypeMonthly(): bool
{
return $this->budgetType === 'month';
}
public function getBudgetType(): ?string
{
return $this->budgetType;
}
public function setBudgetType(?string $budgetType): void
{
$this->budgetType = $budgetType;
}
} }

View File

@@ -38,7 +38,26 @@
{{ widgets.action_button('visibility', {'modal': ('#modal_' ~ tableName), 'class': 'btn-sm'}) }} {{ widgets.action_button('visibility', {'modal': ('#modal_' ~ tableName), 'class': 'btn-sm'}) }}
{% endblock %} {% endblock %}
{% block box_title %} {% block box_title %}
{{ form_widget(form) }} {% if form.customer is defined %}
{{ form_widget(form.customer) }}
{% endif %}
{% if form.month is defined %}
{{ form_widget(form.month) }}
{% endif %}
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="{{ 'filter'|icon }}"></i> <span class="caret"></span>
</button>
<ul class="dropdown-menu checkbox-menu">
<li>
{{ form_widget(form.includeNoWork) }}
</li>
<li>
{{ form_widget(form.budgetType) }}
</li>
</ul>
</div>
{{ form_rest(form) }}
{% endblock %} {% endblock %}
{% block box_body %} {% block box_body %}
{% if not hasData %} {% if not hasData %}

View File

@@ -52,7 +52,32 @@
{{ widgets.action_button('visibility', {'modal': ('#modal_' ~ tableName), 'class': 'btn-sm'}) }} {{ widgets.action_button('visibility', {'modal': ('#modal_' ~ tableName), 'class': 'btn-sm'}) }}
{% endblock %} {% endblock %}
{% block box_title %} {% block box_title %}
{{ form_widget(form) }} {% if form.customer is defined %}
{{ form_widget(form.customer) }}
{% endif %}
{% if form.month is defined %}
{{ form_widget(form.month) }}
{% endif %}
{% if form.includeNoBudget is defined or form.includeNoWork is defined %}
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="{{ 'filter'|icon }}"></i> <span class="caret"></span>
</button>
<ul class="dropdown-menu checkbox-menu">
{% if form.includeNoBudget is defined %}
<li>
{{ form_widget(form.includeNoBudget) }}
</li>
{% endif %}
{% if form.includeNoWork is defined %}
<li>
{{ form_widget(form.includeNoWork) }}
</li>
{% endif %}
</ul>
</div>
{% endif %}
{{ form_rest(form) }}
{% endblock %} {% endblock %}
{% block box_body %} {% block box_body %}
{% if not hasData %} {% if not hasData %}

View File

@@ -9,6 +9,7 @@
namespace App\Tests\Controller\Reporting; namespace App\Tests\Controller\Reporting;
use App\Entity\Project;
use App\Entity\User; use App\Entity\User;
use App\Tests\Controller\ControllerBaseTest; use App\Tests\Controller\ControllerBaseTest;
use App\Tests\DataFixtures\ActivityFixtures; use App\Tests\DataFixtures\ActivityFixtures;
@@ -39,6 +40,9 @@ class ProjectDateRangeControllerTest extends ControllerBaseTest
$projects->setCustomers($customers); $projects->setCustomers($customers);
$projects->setAmount(2); $projects->setAmount(2);
$projects->setIsVisible(true); $projects->setIsVisible(true);
$projects->setCallback(function (Project $project) {
$project->setIsMonthlyBudget();
});
$this->importFixture($projects); $this->importFixture($projects);
$activities = new ActivityFixtures(); $activities = new ActivityFixtures();

View File

@@ -28,8 +28,11 @@ class ProjectDateRangeQueryTest extends TestCase
self::assertEquals($date->getTimestamp(), $sut->getMonth()->getTimestamp()); self::assertEquals($date->getTimestamp(), $sut->getMonth()->getTimestamp());
self::assertSame($user, $sut->getUser()); self::assertSame($user, $sut->getUser());
self::assertNull($sut->getCustomer()); self::assertNull($sut->getCustomer());
self::assertFalse($sut->isOnlyWithRecords()); self::assertTrue($sut->isIncludeNoWork());
self::assertEquals('month', $sut->getBudgetType());
self::assertFalse($sut->isIncludeNoBudget()); self::assertFalse($sut->isIncludeNoBudget());
self::assertTrue($sut->isBudgetTypeMonthly());
} }
public function testSetterGetter() public function testSetterGetter()
@@ -41,12 +44,20 @@ class ProjectDateRangeQueryTest extends TestCase
$sut->setMonth($date); $sut->setMonth($date);
$sut->setCustomer($customer); $sut->setCustomer($customer);
$sut->setIncludeNoBudget(true); $sut->setIncludeNoWork(false);
$sut->setOnlyWithRecords(true);
self::assertEquals($date->getTimestamp(), $sut->getMonth()->getTimestamp()); self::assertEquals($date->getTimestamp(), $sut->getMonth()->getTimestamp());
self::assertSame($customer, $sut->getCustomer()); self::assertSame($customer, $sut->getCustomer());
self::assertTrue($sut->isOnlyWithRecords()); self::assertFalse($sut->isIncludeNoWork());
$sut->setBudgetType('none');
self::assertEquals('none', $sut->getBudgetType());
self::assertTrue($sut->isIncludeNoBudget()); self::assertTrue($sut->isIncludeNoBudget());
self::assertFalse($sut->isBudgetTypeMonthly());
$sut->setBudgetType('full');
self::assertEquals('full', $sut->getBudgetType());
self::assertFalse($sut->isBudgetTypeMonthly());
self::assertFalse($sut->isIncludeNoBudget());
} }
} }

View File

@@ -1216,6 +1216,14 @@
<source>label.includeNoBudget</source> <source>label.includeNoBudget</source>
<target>Einträge ohne Budget anzeigen</target> <target>Einträge ohne Budget anzeigen</target>
</trans-unit> </trans-unit>
<trans-unit id="label.includeBudgetType_month">
<source>label.includeBudgetType_month</source>
<target>Einträge mit "Monats" Budget anzeigen</target>
</trans-unit>
<trans-unit id="label.includeBudgetType_full">
<source>label.includeBudgetType_full</source>
<target>Einträge mit "Lebenszyklus" Budget anzeigen</target>
</trans-unit>
<trans-unit id="label.not_exported"> <trans-unit id="label.not_exported">
<source>label.not_exported</source> <source>label.not_exported</source>
<target>Nicht exportiert</target> <target>Nicht exportiert</target>
@@ -1244,6 +1252,10 @@
<source>label.budgetType_month</source> <source>label.budgetType_month</source>
<target>Monatlich</target> <target>Monatlich</target>
</trans-unit> </trans-unit>
<trans-unit id="label.budgetType_full">
<source>label.budgetType_full</source>
<target>Lebenszyklus</target>
</trans-unit>
<trans-unit id="delete_warning.short_stats"> <trans-unit id="delete_warning.short_stats">
<source>delete_warning.short_stats</source> <source>delete_warning.short_stats</source>
<target>Momentan existieren insgesamt %records% Zeiteinträge, welche sich auf eine Gesamtdauer von %duration% belaufen.</target> <target>Momentan existieren insgesamt %records% Zeiteinträge, welche sich auf eine Gesamtdauer von %duration% belaufen.</target>

View File

@@ -1216,6 +1216,14 @@
<source>label.includeNoBudget</source> <source>label.includeNoBudget</source>
<target>Show entries without budget</target> <target>Show entries without budget</target>
</trans-unit> </trans-unit>
<trans-unit id="label.includeBudgetType_month">
<source>label.includeBudgetType_month</source>
<target>Show entries with "monthly" budget</target>
</trans-unit>
<trans-unit id="label.includeBudgetType_full">
<source>label.includeBudgetType_full</source>
<target>Show entries with "life cycle" budget</target>
</trans-unit>
<trans-unit id="label.not_exported"> <trans-unit id="label.not_exported">
<source>label.not_exported</source> <source>label.not_exported</source>
<target>Not exported</target> <target>Not exported</target>
@@ -1244,6 +1252,10 @@
<source>label.budgetType_month</source> <source>label.budgetType_month</source>
<target>Monthly</target> <target>Monthly</target>
</trans-unit> </trans-unit>
<trans-unit id="label.budgetType_full">
<source>label.budgetType_full</source>
<target>Life cycle</target>
</trans-unit>
<trans-unit id="delete_warning.short_stats"> <trans-unit id="delete_warning.short_stats">
<source>delete_warning.short_stats</source> <source>delete_warning.short_stats</source>
<target>Currently %records% time-records exists, which sum up to a total duration of %duration%.</target> <target>Currently %records% time-records exists, which sum up to a total duration of %duration%.</target>