improve project overview (#2467)
This commit is contained in:
@@ -45,17 +45,25 @@ final class ProjectViewModel
|
||||
* @var float
|
||||
*/
|
||||
private $notExportedRate = 0.00;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $notBilledDuration = 0;
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $notBilledRate = 0.00;
|
||||
|
||||
public function getProject(): ?Project
|
||||
{
|
||||
return $this->project;
|
||||
}
|
||||
|
||||
public function setProject(Project $project): void
|
||||
public function __construct(Project $project)
|
||||
{
|
||||
$this->project = $project;
|
||||
}
|
||||
|
||||
public function getProject(): Project
|
||||
{
|
||||
return $this->project;
|
||||
}
|
||||
|
||||
public function getDurationDay(): int
|
||||
{
|
||||
return $this->durationDay;
|
||||
@@ -116,6 +124,26 @@ final class ProjectViewModel
|
||||
$this->notExportedRate = $notExportedRate;
|
||||
}
|
||||
|
||||
public function getNotBilledDuration(): int
|
||||
{
|
||||
return $this->notBilledDuration;
|
||||
}
|
||||
|
||||
public function setNotBilledDuration(int $notBilledDuration): void
|
||||
{
|
||||
$this->notBilledDuration = $notBilledDuration;
|
||||
}
|
||||
|
||||
public function getNotBilledRate(): float
|
||||
{
|
||||
return $this->notBilledRate;
|
||||
}
|
||||
|
||||
public function setNotBilledRate(float $notBilledRate): void
|
||||
{
|
||||
$this->notBilledRate = $notBilledRate;
|
||||
}
|
||||
|
||||
public function getRateTotal(): float
|
||||
{
|
||||
return $this->rateTotal;
|
||||
|
||||
@@ -87,8 +87,7 @@ final class ProjectViewService
|
||||
|
||||
$projectViews = [];
|
||||
foreach ($result as $res) {
|
||||
$entity = new ProjectViewModel();
|
||||
$entity->setProject($res['project']);
|
||||
$entity = new ProjectViewModel($res['project']);
|
||||
$entity->setDurationTotal($res['totalDuration'] ?? 0);
|
||||
$entity->setRateTotal($res['totalRate'] ?? 0.00);
|
||||
|
||||
@@ -164,6 +163,25 @@ final class ProjectViewService
|
||||
$projectViews[$row['id']]->setNotExportedRate($row['rate']);
|
||||
}
|
||||
|
||||
// values for the all time (not exported and billable)
|
||||
$qb = $this->timesheetRepository->createQueryBuilder('t');
|
||||
$qb
|
||||
->select('IDENTITY(t.project) AS id, SUM(t.duration) AS duration, SUM(t.rate) AS rate')
|
||||
->andWhere($qb->expr()->in('t.project', ':project'))
|
||||
->andWhere('t.exported = :exported')
|
||||
->andWhere('t.billable = :billable')
|
||||
->groupBy('t.project')
|
||||
->setParameter('exported', false, Types::BOOLEAN)
|
||||
->setParameter('billable', true, Types::BOOLEAN)
|
||||
->setParameter('project', array_values($projectIds))
|
||||
;
|
||||
|
||||
$result = $qb->getQuery()->getScalarResult();
|
||||
foreach ($result as $row) {
|
||||
$projectViews[$row['id']]->setNotBilledDuration($row['duration']);
|
||||
$projectViews[$row['id']]->setNotBilledRate($row['rate']);
|
||||
}
|
||||
|
||||
return array_values($projectViews);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "macros/datatables.html.twig" as tables %}
|
||||
{% import "project/actions.html.twig" as projectActions %}
|
||||
{% block box_body_class %}project-view-reporting-box {% if hasData %}no-padding{% endif %} table-responsive{% endblock %}
|
||||
{% block box_body_class %}project-view-reporting-box {% if hasData %}no-padding{% endif %}{% endblock %}
|
||||
{% block box_before %}
|
||||
{{ form_start(form, {'attr': {'class': 'form-inline form-reporting', 'id': 'project-view-form'}}) }}
|
||||
{% endblock %}
|
||||
@@ -52,7 +52,6 @@
|
||||
{{ tables.datatable_header(tableName, columns, null, {'bordered': true, 'striped': false, 'boxClass': ''}) }}
|
||||
|
||||
{% for id, mapping in entries|sort((a, b) => a.customer.name <=> b.customer.name) %}
|
||||
{% if is_granted('budget', mapping.customer) %}
|
||||
<tr class="summary">
|
||||
<td colspan="11">{{ widgets.label_customer(mapping.customer) }}</td>
|
||||
</tr>
|
||||
@@ -60,7 +59,7 @@
|
||||
{% set project = entry.project %}
|
||||
{% set currency = project.customer.currency %}
|
||||
{% if is_granted('budget', project) %}
|
||||
<tr>
|
||||
<tr{% if is_granted('view', project) %} class="alternative-link open-edit" data-href="{{ path('project_details', {'id': project.id}) }}"{% endif %}>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'name') }}">{{ widgets.label_project(project) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'today') }}">{{ entry.durationDay|duration }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'week') }}">{{ entry.durationWeek|duration }}</td>
|
||||
@@ -87,11 +86,11 @@
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'stateMoney') }}">
|
||||
{% if is_granted('view_invoice') %}
|
||||
<a href="{{ path('invoice', {'customer': project.customer.id, 'projects[]': project.id, 'daterange': ''}) }}">
|
||||
{{ entry.notExportedRate|money(currency) }}
|
||||
<a href="{{ path('invoice', {'customers[]': project.customer.id, 'projects[]': project.id, 'daterange': ''}) }}">
|
||||
{{ entry.notBilledRate|money(currency) }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ entry.notExportedRate|money(currency) }}
|
||||
{{ entry.notBilledRate|money(currency) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'projectEnd') }}">{% if project.end is not null %}{{ project.end|date_short }}{% endif %}</td>
|
||||
@@ -102,7 +101,6 @@
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ tables.data_table_footer(entries) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -20,9 +20,10 @@ class ProjectViewModelTest extends TestCase
|
||||
{
|
||||
public function testDefaults()
|
||||
{
|
||||
$sut = new ProjectViewModel();
|
||||
$project = new Project();
|
||||
$sut = new ProjectViewModel($project);
|
||||
|
||||
self::assertNull($sut->getProject());
|
||||
self::assertSame($project, $sut->getProject());
|
||||
self::assertEquals(0, $sut->getDurationDay());
|
||||
self::assertEquals(0, $sut->getDurationMonth());
|
||||
self::assertEquals(0, $sut->getDurationTotal());
|
||||
@@ -34,11 +35,7 @@ class ProjectViewModelTest extends TestCase
|
||||
|
||||
public function testSetterGetter()
|
||||
{
|
||||
$sut = new ProjectViewModel();
|
||||
|
||||
$project = new Project();
|
||||
$sut->setProject($project);
|
||||
self::assertSame($project, $sut->getProject());
|
||||
$sut = new ProjectViewModel(new Project());
|
||||
|
||||
$sut->setDurationDay(123456789);
|
||||
$sut->setDurationMonth(23456789);
|
||||
|
||||
Reference in New Issue
Block a user