feat: per-disposition feedback waiver
The overdue-feedback lists are a live query without stored state, so a feedback nobody will provide any more could not be written off. The new disposition.feedback_waived flag takes a placement out of the admin and manager dashboards, the house-manager list and the reminder mail. Statistics still count a waived placement as a missing feedback. The flag has no UI yet and is set by SQL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
c04d9e0faf
commit
7e182e3d51
4 files changed
+74
No files matched your search
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the per-placement feedback waiver.
|
||||||
|
*
|
||||||
|
* The overdue-feedback lists are a live query without any stored state, so there was no way to
|
||||||
|
* write off a feedback nobody will provide any more. The flag takes a placement out of the
|
||||||
|
* dashboards' overdue lists, the house-manager list and the reminder mail.
|
||||||
|
*
|
||||||
|
* Written by hand rather than taken from doctrine:migrations:diff, which also carries the
|
||||||
|
* pre-existing drift of the dev database.
|
||||||
|
*/
|
||||||
|
final class Version20261013120000 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add the feedback_waived flag to dispositions';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE disposition ADD feedback_waived TINYINT DEFAULT 0 NOT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE disposition DROP feedback_waived');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -72,6 +72,14 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
|||||||
#[ORM\Column(type: Types::BOOLEAN)]
|
#[ORM\Column(type: Types::BOOLEAN)]
|
||||||
private bool $syncedWithBusProNet = false;
|
private bool $syncedWithBusProNet = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The office no longer expects a feedback for this placement, so nothing chases one: not the
|
||||||
|
* dashboards' overdue lists, not the house-manager list, not the reminder mail. It still
|
||||||
|
* counts as missing in the statistics.
|
||||||
|
*/
|
||||||
|
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
|
||||||
|
private bool $feedbackWaived = false;
|
||||||
|
|
||||||
public function __construct(Application $application)
|
public function __construct(Application $application)
|
||||||
{
|
{
|
||||||
$this->uuid = Uuid::v4();
|
$this->uuid = Uuid::v4();
|
||||||
@@ -353,4 +361,16 @@ class Disposition implements BlameableEntityInterface, TimestampableEntityInterf
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isFeedbackWaived(): bool
|
||||||
|
{
|
||||||
|
return $this->feedbackWaived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFeedbackWaived(bool $feedbackWaived): static
|
||||||
|
{
|
||||||
|
$this->feedbackWaived = $feedbackWaived;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -225,9 +225,12 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
$qb->expr()->notIn('assignment.status', ':status'),
|
$qb->expr()->notIn('assignment.status', ':status'),
|
||||||
$qb->expr()->lte('destination.dateTo', ':dateTo'),
|
$qb->expr()->lte('destination.dateTo', ':dateTo'),
|
||||||
$qb->expr()->isNull('feedback'),
|
$qb->expr()->isNull('feedback'),
|
||||||
|
// waived placements are written off: nobody is asked for their feedback any more
|
||||||
|
$qb->expr()->eq('disposition.feedbackWaived', ':feedbackWaived'),
|
||||||
$this->excludesSkipFormalities($qb)
|
$this->excludesSkipFormalities($qb)
|
||||||
))
|
))
|
||||||
->setParameter('status', [Assignment::STATUS_CALLED_OFF, Assignment::STATUS_DELETED])
|
->setParameter('status', [Assignment::STATUS_CALLED_OFF, Assignment::STATUS_DELETED])
|
||||||
|
->setParameter('feedbackWaived', false)
|
||||||
;
|
;
|
||||||
|
|
||||||
$dateTo = new \DateTimeImmutable();
|
$dateTo = new \DateTimeImmutable();
|
||||||
|
|||||||
@@ -212,6 +212,21 @@ class DispositionRepositoryTest extends KernelTestCase
|
|||||||
$this->assertFalse($query->getParameter('skipFormalities')->getValue());
|
$this->assertFalse($query->getParameter('skipFormalities')->getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A waived placement is written off by the office. The same query backs every surface that
|
||||||
|
* chases a feedback, so this is the one place the waiver has to be honoured.
|
||||||
|
*/
|
||||||
|
public function testPendingFeedbackSkipsWaivedDispositions(): void
|
||||||
|
{
|
||||||
|
$query = $this->repository()->getDispositionsWithPendingFeedbackQuery();
|
||||||
|
|
||||||
|
$this->assertStringContainsString(
|
||||||
|
'disposition.feedbackWaived = :feedbackWaived',
|
||||||
|
$query->getDQL()
|
||||||
|
);
|
||||||
|
$this->assertFalse($query->getParameter('feedbackWaived')->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Otherwise placements nobody is expected to rate would be counted as missingFeedbacks and
|
* Otherwise placements nobody is expected to rate would be counted as missingFeedbacks and
|
||||||
* drag every hotel's percentage down.
|
* drag every hotel's percentage down.
|
||||||
|
|||||||
Reference in new issue
Block a user