mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge branch 'address-importer-ban' into 'master'
Add service and command to import French addresses from BAN See merge request Chill-Projet/chill-bundles!781
This commit is contained in:
commit
cb5fd2b69d
5
.changes/unreleased/Feature-20250113-170824.yaml
Normal file
5
.changes/unreleased/Feature-20250113-170824.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
kind: Feature
|
||||
body: Add address importer from french Base d'Adresse Nationale (BAN)
|
||||
time: 2025-01-13T17:08:24.034500095+01:00
|
||||
custom:
|
||||
Issue: ""
|
@ -0,0 +1,48 @@
|
||||
<?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\Command;
|
||||
|
||||
use Chill\MainBundle\Service\Import\AddressReferenceFromBAN;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class LoadAddressesFRFromBANCommand extends Command
|
||||
{
|
||||
protected static $defaultDescription = 'Import FR addresses from BAN (see https://adresses.data.gouv.fr';
|
||||
|
||||
public function __construct(private readonly AddressReferenceFromBAN $addressReferenceFromBAN)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('chill:main:address-ref-from-ban')
|
||||
->addArgument('departementNo', InputArgument::REQUIRED | InputArgument::IS_ARRAY, 'a list of departement numbers')
|
||||
->addOption('send-report-email', 's', InputOption::VALUE_REQUIRED, 'Email address where a list of unimported addresses can be send');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
dump(__METHOD__);
|
||||
foreach ($input->getArgument('departementNo') as $departementNo) {
|
||||
$output->writeln('Import addresses for '.$departementNo);
|
||||
|
||||
$this->addressReferenceFromBAN->import($departementNo, $input->hasOption('send-report-email') ? $input->getOption('send-report-email') : null);
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
}
|
@ -311,7 +311,7 @@ final class AddressReferenceBaseImporter
|
||||
$email = (new Email())
|
||||
->addTo($sendAddressReportToEmail)
|
||||
->subject('Addresses that could not be imported')
|
||||
->attachFromPath($attachmentPath);
|
||||
->attach(file_get_contents($attachmentPath), sprintf('%s.gz', $path));
|
||||
|
||||
try {
|
||||
$this->mailer->send($email);
|
||||
|
@ -0,0 +1,106 @@
|
||||
<?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\Import;
|
||||
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Statement;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class AddressReferenceFromBAN
|
||||
{
|
||||
public function __construct(
|
||||
private readonly HttpClientInterface $client,
|
||||
private readonly AddressReferenceBaseImporter $baseImporter,
|
||||
private readonly AddressToReferenceMatcher $addressToReferenceMatcher,
|
||||
) {}
|
||||
|
||||
public function import(string $departementNo, ?string $sendAddressReportToEmail = null): void
|
||||
{
|
||||
if (!is_numeric($departementNo)) {
|
||||
throw new \UnexpectedValueException('Could not parse this department number');
|
||||
}
|
||||
|
||||
$url = sprintf('https://adresse.data.gouv.fr/data/ban/adresses/latest/csv/adresses-%s.csv.gz', $departementNo);
|
||||
|
||||
$response = $this->client->request('GET', $url);
|
||||
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
throw new \Exception('Could not download CSV: '.$response->getStatusCode());
|
||||
}
|
||||
|
||||
$path = sys_get_temp_dir().'/'.$departementNo.'.csv.gz';
|
||||
$file = fopen($path, 'w');
|
||||
|
||||
if (false === $file) {
|
||||
throw new \Exception('Could not create temporary file');
|
||||
}
|
||||
|
||||
foreach ($this->client->stream($response) as $chunk) {
|
||||
fwrite($file, $chunk->getContent());
|
||||
}
|
||||
|
||||
fclose($file);
|
||||
|
||||
// re-open it to read it
|
||||
$csvDecompressed = gzopen($path, 'r');
|
||||
|
||||
$csv = Reader::createFromStream($csvDecompressed);
|
||||
$csv->setDelimiter(';')->setHeaderOffset(0);
|
||||
$stmt = Statement::create()
|
||||
->process($csv, [
|
||||
'id',
|
||||
'id_fantoir',
|
||||
'numero',
|
||||
'rep',
|
||||
'nom_voie',
|
||||
'code_postal',
|
||||
'code_insee',
|
||||
'nom_commune',
|
||||
'code_insee_ancienne_commune',
|
||||
'nom_ancienne_commune',
|
||||
'x',
|
||||
'y',
|
||||
'lon',
|
||||
'lat',
|
||||
'type_position',
|
||||
'alias',
|
||||
'nom_ld',
|
||||
'libelle_acheminement',
|
||||
'nom_afnor',
|
||||
'source_position',
|
||||
'source_nom_voie',
|
||||
'certification_commune',
|
||||
'cad_parcelles',
|
||||
]);
|
||||
|
||||
foreach ($stmt as $record) {
|
||||
$this->baseImporter->importAddress(
|
||||
$record['id'],
|
||||
$record['code_insee'],
|
||||
$record['code_postal'],
|
||||
$record['nom_voie'],
|
||||
$record['numero'].' '.$record['rep'],
|
||||
'BAN.'.$departementNo,
|
||||
(float) $record['lat'],
|
||||
(float) $record['lon'],
|
||||
4326
|
||||
);
|
||||
}
|
||||
|
||||
$this->baseImporter->finalize(sendAddressReportToEmail: $sendAddressReportToEmail);
|
||||
|
||||
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||
|
||||
fclose($csvDecompressed);
|
||||
unlink($path);
|
||||
}
|
||||
}
|
@ -47,6 +47,12 @@ services:
|
||||
tags:
|
||||
- { name: console.command }
|
||||
|
||||
Chill\MainBundle\Command\LoadAddressesFRFromBANCommand:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
tags:
|
||||
- { name: console.command }
|
||||
|
||||
Chill\MainBundle\Command\LoadAddressesBEFromBestAddressCommand:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
|
Loading…
x
Reference in New Issue
Block a user