Timesheet validator: prevent overbooking budgets (#2422)

This commit is contained in:
Kevin Papst
2021-03-13 14:41:29 +01:00
committed by GitHub
parent db1344573f
commit 3e9371bd6a
34 changed files with 1425 additions and 236 deletions

View File

@@ -93,26 +93,26 @@ class ActivityRepository extends EntityRepository
*/
public function getActivityStatistics(Activity $activity)
{
$stats = new ActivityStatistic();
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->addSelect('COUNT(t.id) as recordAmount')
->addSelect('SUM(t.duration) as recordDuration')
->addSelect('SUM(t.rate) as recordRate')
->addSelect('SUM(t.internalRate) as recordInternalRate')
->from(Timesheet::class, 't')
->addSelect('COUNT(t.id) as amount')
->addSelect('SUM(t.duration) as duration')
->addSelect('SUM(t.rate) as rate')
->addSelect('SUM(t.internalRate) as internal_rate')
->where('t.activity = :activity')
->setParameter('activity', $activity)
;
$timesheetResult = $qb->getQuery()->execute(['activity' => $activity], Query::HYDRATE_ARRAY);
$timesheetResult = $qb->getQuery()->getOneOrNullResult();
if (isset($timesheetResult[0])) {
$stats->setRecordAmount($timesheetResult[0]['recordAmount']);
$stats->setRecordDuration($timesheetResult[0]['recordDuration']);
$stats->setRecordRate($timesheetResult[0]['recordRate']);
$stats->setRecordInternalRate($timesheetResult[0]['recordInternalRate']);
$stats = new ActivityStatistic();
if (null !== $timesheetResult) {
$stats->setRecordAmount($timesheetResult['amount']);
$stats->setRecordDuration($timesheetResult['duration']);
$stats->setRecordRate($timesheetResult['rate']);
$stats->setRecordInternalRate($timesheetResult['internal_rate']);
}
return $stats;

View File

@@ -86,50 +86,56 @@ class CustomerRepository extends EntityRepository
*/
public function getCustomerStatistics(Customer $customer)
{
$stats = new CustomerStatistic();
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->addSelect('COUNT(t.id) as recordAmount')
->addSelect('SUM(t.duration) as recordDuration')
->addSelect('SUM(t.rate) as recordRate')
->addSelect('SUM(t.internalRate) as recordInternalRate')
->from(Timesheet::class, 't')
->join(Project::class, 'p', Query\Expr\Join::WITH, 't.project = p.id')
->addSelect('COUNT(t.id) as amount')
->addSelect('SUM(t.duration) as duration')
->addSelect('SUM(t.rate) as rate')
->addSelect('SUM(t.internalRate) as internal_rate')
->andWhere('p.customer = :customer')
->setParameter('customer', $customer)
;
$timesheetResult = $qb->getQuery()->execute(['customer' => $customer], Query::HYDRATE_ARRAY);
if (isset($timesheetResult[0])) {
$stats->setRecordAmount($timesheetResult[0]['recordAmount']);
$stats->setRecordDuration($timesheetResult[0]['recordDuration']);
$stats->setRecordRate($timesheetResult[0]['recordRate']);
$stats->setRecordInternalRate($timesheetResult[0]['recordInternalRate']);
$timesheetResult = $qb->getQuery()->getOneOrNullResult();
$stats = new CustomerStatistic();
if (null !== $timesheetResult) {
$stats->setRecordAmount($timesheetResult['amount']);
$stats->setRecordDuration($timesheetResult['duration']);
$stats->setRecordRate($timesheetResult['rate']);
$stats->setRecordInternalRate($timesheetResult['internal_rate']);
}
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select('COUNT(a.id) as activityAmount')
->select('COUNT(a.id) as amount')
->from(Activity::class, 'a')
->join(Project::class, 'p', Query\Expr\Join::WITH, 'a.project = p.id')
->andWhere('a.project = p.id')
->andWhere('p.customer = :customer')
->setParameter('customer', $customer)
;
$activityResult = $qb->getQuery()->execute(['customer' => $customer], Query::HYDRATE_ARRAY);
if (isset($activityResult[0])) {
$stats->setActivityAmount($activityResult[0]['activityAmount']);
$activityResult = $qb->getQuery()->getOneOrNullResult();
if (null !== $activityResult) {
$stats->setActivityAmount($activityResult['amount']);
}
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('COUNT(p.id) as projectAmount')
$qb->select('COUNT(p.id) as amount')
->from(Project::class, 'p')
->andWhere('p.customer = :customer')
->setParameter('customer', $customer)
;
$projectResult = $qb->getQuery()->execute(['customer' => $customer], Query::HYDRATE_ARRAY);
if (isset($projectResult[0])) {
$stats->setProjectAmount($projectResult[0]['projectAmount']);
$projectResult = $qb->getQuery()->getOneOrNullResult();
if (null !== $projectResult) {
$stats->setProjectAmount($projectResult['amount']);
}
return $stats;

View File

@@ -80,16 +80,13 @@ class ProjectRepository extends EntityRepository
public function getProjectStatistics(Project $project, ?DateTime $begin = null, ?DateTime $end = null): ProjectStatistic
{
$stats = new ProjectStatistic($project);
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->from(Timesheet::class, 't')
->addSelect('COUNT(t.id) as recordAmount')
->addSelect('SUM(t.duration) as recordDuration')
->addSelect('SUM(t.rate) as recordRate')
->addSelect('SUM(t.internalRate) as recordInternalRate')
->addSelect('COUNT(t.id) as amount')
->addSelect('SUM(t.duration) as duration')
->addSelect('SUM(t.rate) as rate')
->addSelect('SUM(t.internalRate) as internal_rate')
->andWhere('t.project = :project')
->setParameter('project', $project)
;
@@ -98,31 +95,35 @@ class ProjectRepository extends EntityRepository
$qb->andWhere($qb->expr()->gte('t.begin', ':begin'))
->setParameter('begin', $begin);
}
if (null !== $end) {
$qb->andWhere($qb->expr()->lte('t.end', ':end'))
->setParameter('end', $end);
}
$timesheetResult = $qb->getQuery()->getArrayResult();
$timesheetResult = $qb->getQuery()->getOneOrNullResult();
if (isset($timesheetResult[0])) {
$stats->setRecordAmount($timesheetResult[0]['recordAmount']);
$stats->setRecordDuration($timesheetResult[0]['recordDuration']);
$stats->setRecordRate($timesheetResult[0]['recordRate']);
$stats->setRecordInternalRate($timesheetResult[0]['recordInternalRate']);
$stats = new ProjectStatistic();
if (null !== $timesheetResult) {
$stats->setRecordAmount($timesheetResult['amount']);
$stats->setRecordDuration($timesheetResult['duration']);
$stats->setRecordRate($timesheetResult['rate']);
$stats->setRecordInternalRate($timesheetResult['internal_rate']);
}
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('COUNT(a.id) as activityAmount')
$qb
->from(Activity::class, 'a')
->select('COUNT(a.id) as amount')
->andWhere('a.project = :project')
->setParameter('project', $project)
;
$resultActivities = $qb->getQuery()->execute(['project' => $project], Query::HYDRATE_ARRAY);
if (isset($resultActivities[0])) {
$resultActivities = $resultActivities[0];
$resultActivities = $qb->getQuery()->getOneOrNullResult();
$stats->setActivityAmount($resultActivities['activityAmount']);
if (null !== $resultActivities) {
$stats->setActivityAmount($resultActivities['amount']);
}
return $stats;

View File

@@ -11,6 +11,7 @@ namespace App\Repository;
use App\Entity\ActivityRate;
use App\Entity\CustomerRate;
use App\Entity\Project;
use App\Entity\ProjectRate;
use App\Entity\RateInterface;
use App\Entity\Team;
@@ -26,7 +27,9 @@ use App\Repository\Paginator\PaginatorInterface;
use App\Repository\Query\TimesheetQuery;
use DateInterval;
use DateTime;
use Doctrine\ORM\AbstractQuery;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Exception;
use InvalidArgumentException;
@@ -45,6 +48,27 @@ class TimesheetRepository extends EntityRepository
public const STATS_QUERY_ACTIVE = 'active';
public const STATS_QUERY_MONTHLY = 'monthly';
public function getRawData(Timesheet $id): array
{
$qb = $this->createQueryBuilder('t');
$qb
->select([
't.rate',
't.duration',
't.hourlyRate',
'IDENTITY(p.customer) as customer',
'IDENTITY(t.project) as project',
'IDENTITY(t.activity) as activity',
'IDENTITY(t.user) as user'
])
->leftJoin(Project::class, 'p', Join::WITH, 'p.id = t.project')
->andWhere('t.id = :id')
->setParameter('id', $id)
;
return $qb->getQuery()->getSingleResult(AbstractQuery::HYDRATE_ARRAY);
}
/**
* @param mixed $id
* @param null $lockMode