Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAP] improve building stats rows #10242

Merged
merged 1 commit into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/Entity/Pap/Building.php
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ public function setType(string $type): void
*/
public function getCampaignStatistics(): ?CampaignStatisticsInterface
{
return $this->currentCampaign ? $this->findStatisticsForCampaign($this->currentCampaign) : new BuildingStatistics($this, $this->currentCampaign);
if ($this->currentCampaign) {
return $this->findStatisticsForCampaign($this->currentCampaign) ?? new BuildingStatistics(
$this,
$this->currentCampaign
);
}

return null;
}
}
18 changes: 9 additions & 9 deletions src/Pap/BuildingStatisticsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,8 @@ public function __construct(
$this->campaignHistoryRepository = $campaignHistoryRepository;
}

public function updateStats(Building $building, Campaign $campaign): void
public function updateStats(Building $building, Campaign $campaign): BuildingStatistics
{
$campaignHistory = $this->campaignHistoryRepository->findLastFor($building, $campaign);

if (!$campaignHistory) {
return;
}

// building stats
if (!$buildingStats = $building->findStatisticsForCampaign($campaign)) {
$building->addStatistic($buildingStats = new BuildingStatistics(
Expand All @@ -48,8 +42,12 @@ public function updateStats(Building $building, Campaign $campaign): void
if ($buildingStats->isTodo()) {
$buildingStats->setStatus(BuildingStatusEnum::ONGOING);
}
$buildingStats->setLastPassage($campaignHistory->getUpdatedAt());
$buildingStats->setLastPassageDoneBy($campaignHistory->getQuestioner());

if ($campaignHistory = $this->campaignHistoryRepository->findLastFor($building, $campaign)) {
$buildingStats->setLastPassage($campaignHistory->getUpdatedAt());
$buildingStats->setLastPassageDoneBy($campaignHistory->getQuestioner());
}

$buildingStats->setNbVisitedDoors($this->campaignHistoryRepository->countDoorsForBuilding($building));
$buildingStats->setNbSurveys($this->dataSurveyRepository->countSurveysForBuilding($building));

Expand Down Expand Up @@ -97,5 +95,7 @@ public function updateStats(Building $building, Campaign $campaign): void
}

$this->em->flush();

return $buildingStats;
}
}
25 changes: 15 additions & 10 deletions src/Pap/Handler/BuildingEventCommandHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@
use App\Entity\Pap\CampaignStatisticsOwnerInterface;
use App\Pap\BuildingEventActionEnum;
use App\Pap\BuildingEventTypeEnum;
use App\Pap\BuildingStatisticsManager;
use App\Pap\BuildingStatusEnum;
use App\Pap\Command\BuildingEventAsyncCommand;
use App\Pap\Command\BuildingEventCommandInterface;
use App\Repository\Pap\BuildingEventRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class BuildingEventCommandHandler implements MessageHandlerInterface
{
private EntityManagerInterface $entityManager;
private BuildingEventRepository $buildingEventRepository;

public function __construct(EntityManagerInterface $entityManager, BuildingEventRepository $buildingEventRepository)
{
$this->entityManager = $entityManager;
$this->buildingEventRepository = $buildingEventRepository;
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly BuildingEventRepository $buildingEventRepository,
private readonly BuildingStatisticsManager $buildingStatisticsManager,
) {
}

public function __invoke(BuildingEventCommandInterface $command): void
Expand Down Expand Up @@ -64,21 +64,26 @@ public function __invoke(BuildingEventCommandInterface $command): void
throw new \InvalidArgumentException(sprintf('Type %s is not supported for creation a building statistics', $type));
}

$this->updateStatisticsCloseInfo($objectWithStats, $buildingEvent);
$this->updateStatisticsCloseInfo($objectWithStats, $buildingEvent, $command instanceof BuildingEventAsyncCommand);
}

$this->entityManager->flush();
}

private function updateStatisticsCloseInfo(
CampaignStatisticsOwnerInterface $object,
BuildingEvent $buildingEvent
BuildingEvent $buildingEvent,
bool $isAsync
): void {
$status = BuildingEventActionEnum::CLOSE === $buildingEvent->getAction() ? BuildingStatusEnum::COMPLETED : BuildingStatusEnum::ONGOING;
$campaign = $buildingEvent->getCampaign();
/** @var CampaignStatisticsInterface $stats */
if (!$stats = $object->findStatisticsForCampaign($campaign)) {
throw new \RuntimeException(sprintf('Statistics not found for entity "%s" with id "%s" for PAP campaign with id "%s"', $object::class, $object->getId(), $campaign->getId()));
if ($isAsync && $object instanceof Building) {
$stats = $this->buildingStatisticsManager->updateStats($object, $campaign);
} else {
throw new \RuntimeException(sprintf('Statistics not found for entity "%s" with id "%s" for PAP campaign with id "%s"', $object::class, $object->getId(), $campaign->getId()));
}
}

$statusDetail = null;
Expand Down
48 changes: 14 additions & 34 deletions src/Repository/Pap/AddressRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use App\Entity\Pap\Address;
use App\Entity\Pap\Campaign;
use App\Entity\Pap\VotePlace;
use App\Pap\BuildingStatusEnum;
use App\Repository\GeoZoneTrait;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\Query\Expr\Join;
Expand Down Expand Up @@ -41,16 +40,16 @@ public function findNear(
SELECT address.id
FROM pap_address AS address
INNER JOIN pap_building AS building ON building.address_id = address.id AND building.current_campaign_id IN ($activeCampaignsCondition)
WHERE
WHERE
address.offset_x BETWEEN :offset_x_1 AND :offset_x_2
AND address.offset_y BETWEEN :offset_y_1 AND :offset_y_2
ORDER BY
(6371 *
ORDER BY
(6371 *
ACOS(
COS(RADIANS(:latitude))
* COS(RADIANS(address.latitude))
* COS(RADIANS(address.longitude) - RADIANS(:longitude))
+ SIN(RADIANS(:latitude))
COS(RADIANS(:latitude))
* COS(RADIANS(address.latitude))
* COS(RADIANS(address.longitude) - RADIANS(:longitude))
+ SIN(RADIANS(:latitude))
* SIN(RADIANS(address.latitude))
))
LIMIT :limit
Expand Down Expand Up @@ -80,12 +79,12 @@ public function findNear(
->createQueryBuilder('address')
->select('address', 'building', 'stats')
->addSelect('
(6371 *
(6371 *
ACOS(
COS(RADIANS(:latitude))
* COS(RADIANS(address.latitude))
* COS(RADIANS(address.longitude) - RADIANS(:longitude))
+ SIN(RADIANS(:latitude))
COS(RADIANS(:latitude))
* COS(RADIANS(address.latitude))
* COS(RADIANS(address.longitude) - RADIANS(:longitude))
+ SIN(RADIANS(:latitude))
* SIN(RADIANS(address.latitude))
)) as HIDDEN distance
')
Expand All @@ -108,7 +107,7 @@ public function associatedCampaign(Campaign $campaign): void
$sql = <<<SQL
UPDATE pap_address AS address
INNER JOIN pap_building AS building ON building.address_id = address.id
LEFT JOIN pap_campaign AS current_campaign ON current_campaign.id = building.current_campaign_id
LEFT JOIN pap_campaign AS current_campaign ON current_campaign.id = building.current_campaign_id
SET building.current_campaign_id = :campaign_id
WHERE (current_campaign.id IS NULL OR current_campaign.finish_at < :start_date)
__VOTE_PLACE_CONDITION__
Expand Down Expand Up @@ -145,32 +144,13 @@ public function associatedCampaign(Campaign $campaign): void
$connection = $this->getEntityManager()->getConnection();
$connection->prepare($sql)->executeStatement($params);

// insert building statistics for new campaign
$sql = <<<SQL
INSERT IGNORE INTO pap_building_statistics (building_id, campaign_id, status, uuid, created_at, updated_at)
SELECT
building.id,
building.current_campaign_id,
:todo_status,
UUID(),
NOW(),
NOW()
FROM pap_building AS building
WHERE building.current_campaign_id = :campaign_id
SQL;

$connection->prepare($sql)->executeStatement([
'campaign_id' => $campaign->getId(),
'todo_status' => BuildingStatusEnum::TODO,
]);

// unlink campaign from buildings that not in campaign's vote places
if (isset($votePlaceIds)) {
$connection->prepare(<<<SQL
UPDATE pap_address AS address
INNER JOIN pap_building AS building ON building.address_id = address.id
SET building.current_campaign_id = NULL
WHERE building.current_campaign_id = :campaign_id
WHERE building.current_campaign_id = :campaign_id
AND address.vote_place_id NOT IN ($votePlaceIds)
SQL)->executeStatement([
'campaign_id' => $campaign->getId(),
Expand Down