fix: correctly apply due dates for contract and invoice upload reminders
This commit is contained in:
@@ -6,7 +6,7 @@ use App\Entity\Traits\BlameableEntity;
|
||||
use App\Entity\Traits\SoftDeletableEntity;
|
||||
use App\Entity\Traits\TimestampableEntity;
|
||||
use App\Repository\AssignmentRepository;
|
||||
use Carbon\CarbonPeriod;
|
||||
use Carbon\CarbonPeriodImmutable;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
@@ -270,13 +270,19 @@ class Assignment implements BlameableEntityInterface, TimestampableEntityInterfa
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEffectivePeriod(): ?CarbonPeriod
|
||||
/**
|
||||
* Immutable on purpose: a plain CarbonPeriod hands out mutable Carbon instances, so a caller
|
||||
* deriving one date from another - `$end = $period->getEndDate(); $end->addDays(14)` - moves
|
||||
* the original as well and silently collapses its own period. CarbonPeriodImmutable yields
|
||||
* CarbonImmutable from start, end and getEndDate(), which makes that mistake impossible.
|
||||
*/
|
||||
public function getEffectivePeriod(): ?CarbonPeriodImmutable
|
||||
{
|
||||
if (null !== $destination = $this->getDestination()) {
|
||||
$dateFrom = $this->getDateFrom() ?? $destination->getDateFrom();
|
||||
$dateTo = $this->getDateTo() ?? $destination->getDateTo();
|
||||
|
||||
return new CarbonPeriod($dateFrom, $dateTo);
|
||||
return new CarbonPeriodImmutable($dateFrom, $dateTo);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Entity;
|
||||
use App\Entity\Traits\BlameableEntity;
|
||||
use App\Entity\Traits\TimestampableEntity;
|
||||
use App\Repository\DispositionRepository;
|
||||
use Carbon\CarbonPeriod;
|
||||
use Carbon\CarbonPeriodImmutable;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
@@ -218,7 +218,11 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isContractDue(): bool
|
||||
/**
|
||||
* The period is passed in rather than hardcoded so that this, the reminder mail and the
|
||||
* admin overdue list all work from the same %contract_upload_deadline_days%.
|
||||
*/
|
||||
public function isContractDue(int $deadlineDays): bool
|
||||
{
|
||||
if (null !== $this->getDocumentByType(Upload::TYPE_CONTRACT)) {
|
||||
return false;
|
||||
@@ -226,12 +230,15 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
||||
|
||||
$assignment = $this->getAssignment();
|
||||
$assignmentPeriod = $assignment->getEffectivePeriod();
|
||||
$dueDateFrom = $this->getCreatedAt()->modify('+7 days');
|
||||
$dueDateFrom = $this->getCreatedAt()->modify(sprintf('+%d days', $deadlineDays));
|
||||
$dueDateTo = $assignmentPeriod->end->modify('-1 day');
|
||||
|
||||
$period = CarbonPeriod::create($dueDateFrom, $dueDateTo);
|
||||
$period = CarbonPeriodImmutable::create($dueDateFrom, $dueDateTo);
|
||||
|
||||
return $period->isStarted();
|
||||
// isStarted() alone stays true once the period has begun, so the dashboard kept
|
||||
// asking for a contract on the last day of the assignment - by which point
|
||||
// DispositionWorkflowGuardSubscriber already refuses the upload.
|
||||
return $period->isStarted() && false === $period->isEnded();
|
||||
}
|
||||
|
||||
public function isContractRejected(): bool
|
||||
@@ -243,7 +250,14 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
||||
return $contractDocument->isRejected();
|
||||
}
|
||||
|
||||
public function isInvoiceDue(): bool
|
||||
/**
|
||||
* The period is passed in rather than hardcoded so that this and the two invoice reminder
|
||||
* mails all work from the same %invoice_upload_deadline_days%.
|
||||
*
|
||||
* Unlike isContractDue() this deliberately stays true once the period has run out: nothing
|
||||
* blocks a late invoice upload, so the teamer should keep being asked for it.
|
||||
*/
|
||||
public function isInvoiceDue(int $deadlineDays): bool
|
||||
{
|
||||
if (null !== $this->getDocumentByType(Upload::TYPE_INVOICE)) {
|
||||
return false;
|
||||
@@ -251,8 +265,10 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
||||
|
||||
$assignment = $this->getAssignment();
|
||||
$assignmentPeriod = $assignment->getEffectivePeriod();
|
||||
$dueDateFrom = $assignmentPeriod->getEndDate();
|
||||
$dueDateTo = $dueDateFrom->addDays($deadlineDays);
|
||||
|
||||
$period = CarbonPeriod::create($assignmentPeriod->getEndDate(), $assignmentPeriod->getEndDate()->modify('+14 days'));
|
||||
$period = CarbonPeriodImmutable::create($dueDateFrom, $dueDateTo);
|
||||
|
||||
return $period->isStarted();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user