[Addresses] add a cronjob to collate addresses with reference

This commit is contained in:
Julien Fastré 2023-07-12 18:00:29 +02:00
parent 1552b3c9d7
commit a7842b2597
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
5 changed files with 141 additions and 6 deletions

View File

@ -0,0 +1,6 @@
kind: Feature
body: |
[addresses] Add a cronjob to re-associate addresses with addresses reference every 6 hours
time: 2023-07-12T18:00:23.037677413+02:00
custom:
Issue: "112"

View File

@ -14,7 +14,7 @@ namespace Chill\MainBundle\Service\AddressGeographicalUnit;
use Doctrine\DBAL\Connection;
use Psr\Log\LoggerInterface;
final readonly class CollateAddressWithReferenceOrPostalCode
final readonly class CollateAddressWithReferenceOrPostalCode implements CollateAddressWithReferenceOrPostalCodeInterface
{
private const LOG_PREFIX = '[collate addresses] ';
/**
@ -62,8 +62,6 @@ final readonly class CollateAddressWithReferenceOrPostalCode
JOIN chill_main_postal_code cmpc on cma.postcode_id = cmpc.id,
chill_main_address_reference cmar JOIN chill_main_postal_code cmpc_reference ON cmar.postcode_id = cmpc_reference.id
WHERE
-- only where the reference is null
-- cma.addressreference_id IS NULL
cma.addressreference_id != cmar.id
-- only if cmpc is a reference (must be matched before executing this query)
AND cma.postcode_id = cmar.postcode_id
@ -113,9 +111,9 @@ final readonly class CollateAddressWithReferenceOrPostalCode
$pointUpdates,
$lastId,
] = $this->connection->transactional(function () use ($sinceId) {
$postCodeSetReferenceFromMostSimilar = $this->connection->executeQuery(self::FORCE_ORIGINAL_POSTAL_CODE, ['since_id' => $sinceId]);
$addressReferenceMatch = $this->connection->executeQuery(self::FORCE_MOST_SIMILAR_ADDRESS_REFERENCE, ['since_id' => $sinceId]);
$pointUpdates = $this->connection->executeQuery(self::UPDATE_POINT, ['since_id' => $sinceId]);
$postCodeSetReferenceFromMostSimilar = $this->connection->executeStatement(self::FORCE_ORIGINAL_POSTAL_CODE, ['since_id' => $sinceId]);
$addressReferenceMatch = $this->connection->executeStatement(self::FORCE_MOST_SIMILAR_ADDRESS_REFERENCE, ['since_id' => $sinceId]);
$pointUpdates = $this->connection->executeStatement(self::UPDATE_POINT, ['since_id' => $sinceId]);
$lastId = $this->connection->fetchOne(self::MAX_ADDRESS_ID);
return [

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Service\AddressGeographicalUnit;
use Chill\MainBundle\Cron\CronJobInterface;
use Chill\MainBundle\Entity\CronJobExecution;
use Symfony\Component\Clock\ClockInterface;
final readonly class CollateAddressWithReferenceOrPostalCodeCronJob implements CronJobInterface
{
private const LAST_MAX_ID = 'last-max-id';
public function __construct(
private ClockInterface $clock,
private CollateAddressWithReferenceOrPostalCodeInterface $collateAddressWithReferenceOrPostalCode,
) {
}
public function canRun(?CronJobExecution $cronJobExecution): bool
{
$now = $this->clock->now();
return $now->sub(new \DateInterval('PT6H')) > $cronJobExecution->getLastStart();
}
public function getKey(): string
{
return 'collate-address';
}
public function run(array $lastExecutionData): null|array
{
$maxId = ($this->collateAddressWithReferenceOrPostalCode)($lastExecutionData[self::LAST_MAX_ID] ?? 0);
return [self::LAST_MAX_ID => $maxId];
}
}

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Chill\MainBundle\Service\AddressGeographicalUnit;
interface CollateAddressWithReferenceOrPostalCodeInterface
{
/**
* @throws \Throwable
*/
public function __invoke(int $sinceId = 0): int;
}

View File

@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
/*
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
namespace Services\AddressGeographicalUnit;
use Chill\MainBundle\Entity\CronJobExecution;
use Chill\MainBundle\Service\AddressGeographicalUnit\CollateAddressWithReferenceOrPostalCodeCronJob;
use Chill\MainBundle\Service\AddressGeographicalUnit\CollateAddressWithReferenceOrPostalCodeInterface;
use PHPUnit\Framework\TestCase;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Component\Clock\MockClock;
/**
* @internal
* @coversNothing
*/
class CollateAddressWithReferenceOrPostalCodeCronJobTest extends TestCase
{
use ProphecyTrait;
/**
* @dataProvider provideDataCanRun
*/
public function testCanRun(\DateTimeImmutable $now, \DateTimeImmutable $lastExecution, bool $expected): void
{
$execution = new CronJobExecution('collate-address');
$execution ->setLastStart($lastExecution);
$clock = new MockClock($now);
$collator = $this->prophesize(CollateAddressWithReferenceOrPostalCodeInterface::class);
$job = new CollateAddressWithReferenceOrPostalCodeCronJob($clock, $collator->reveal());
self::assertEquals($expected, $job->canRun($execution));
}
public function testRun(): void
{
$clock = new MockClock();
$collator = $this->prophesize(CollateAddressWithReferenceOrPostalCodeInterface::class);
$collator->__invoke(0)->shouldBeCalledOnce();
$collator->__invoke(0)->willReturn(1);
$job = new CollateAddressWithReferenceOrPostalCodeCronJob($clock, $collator->reveal());
$actual = $job->run(['last-max-id' => 0]);
self::assertEquals(['last-max-id' => 1], $actual);
}
public static function provideDataCanRun(): iterable
{
yield [new \DateTimeImmutable('2023-07-10T12:00:00'), new \DateTimeImmutable('2023-07-10T11:00:00'), false];
yield [new \DateTimeImmutable('2023-07-10T12:00:00'), new \DateTimeImmutable('2023-07-10T05:00:00'), true];
yield [new \DateTimeImmutable('2023-07-10T12:00:00'), new \DateTimeImmutable('2023-07-01T12:00:00'), true];
}
}