fix: correctly apply due dates for contract and invoice upload reminders

This commit is contained in:
Björn Fromme
2026-08-17 11:55:02 +02:00
parent 3e08965e48
commit 489aafed3e
22 changed files with 732 additions and 156 deletions
+23 -7
View File
@@ -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();
}