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

draft: Stage #89

Draft
wants to merge 116 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
6992a38
Merge branch 'stage'
Dec 14, 2021
b6cd349
Create Entity
SebastianStorz Dec 5, 2022
db11114
Create Query for old values
SebastianStorz Dec 5, 2022
eed608d
Create Aggregator and Injection
SebastianStorz Dec 6, 2022
8c2477f
Commit before cleanign up entity again.
SebastianStorz Dec 6, 2022
0afa10a
Clean up Entity
SebastianStorz Dec 6, 2022
14ecb8a
Add aggregation to update end_date when finished
SebastianStorz Dec 6, 2022
5dcfd7f
Implement Aggregation for new Employments and fixes to Aggregation
SebastianStorz Dec 7, 2022
8768d22
Implement Anonymization for deleted Persons
SebastianStorz Dec 7, 2022
12270cc
Remove unecessary comment
SebastianStorz Dec 7, 2022
5d408d0
Merge branch 'stage'
Dec 14, 2022
abf70d8
add user information to sentry and clean up .env files
SebastianStorz Jun 21, 2023
20e0877
lint
SebastianStorz Jun 21, 2023
f8d6cd5
Merge branch 'sentry' into issue/hc-212
SebastianStorz Jun 27, 2023
77ba73a
add basic RoleOverview endpoint
SebastianStorz Jun 28, 2023
76ba101
add colors to role overview and filter endpoint
SebastianStorz Jun 29, 2023
3608862
fix missing canton information and link between groups
SebastianStorz Jul 4, 2023
53fb593
enable necessary features only
SebastianStorz Jul 4, 2023
98a5a46
enable fetching in cronjob
SebastianStorz Jul 4, 2023
1c5a708
lint
SebastianStorz Jul 5, 2023
002e30f
fix: deactivate bruteforce group import
SebastianStorz Jul 5, 2023
16f4a59
lint
SebastianStorz Jul 5, 2023
d63c0c5
Add some doc for clarity
SebastianStorz Jul 5, 2023
29c09fc
fix undefined index warning
SebastianStorz Jul 5, 2023
e2204b1
implement group meeting locations
SebastianStorz Jul 11, 2023
2b3ddfc
remove var dump
SebastianStorz Jul 11, 2023
5ab45bc
lint
SebastianStorz Jul 11, 2023
942ac60
Sanitize Lat and Long
SebastianStorz Jul 12, 2023
9e78a69
add check to only aggregate meeting points of current date
SebastianStorz Jul 12, 2023
e0816d9
Add sorting to ensure newest qualifications get displayed
SebastianStorz Jul 13, 2023
7e78610
lint inline control structures
SebastianStorz Jul 13, 2023
4aff37d
fix .env.test
SebastianStorz Jul 17, 2023
dec22f8
Merge branch 'stage'
SebastianStorz Jul 17, 2023
0e2153d
minor fixes
SebastianStorz Jul 18, 2023
3c686b2
lint
SebastianStorz Jul 18, 2023
369da63
Merge branch 'issue/hc-212' into stage
SebastianStorz Jul 18, 2023
1bc30d5
partial implementation without backend filters
SebastianStorz Sep 1, 2023
5011724
enable reflections for census
SebastianStorz Sep 7, 2023
0f5bfd3
fix roleoverview date range filter
SebastianStorz Sep 7, 2023
eeaa4f0
Merge pull request #92 from digio-ch/issue/hc-194
TaminoWalter Sep 8, 2023
df5ad63
Merge pull request #93 from digio-ch/stage
SebastianStorz Sep 14, 2023
dfedf01
fix: wrong parameter order
SebastianStorz Sep 19, 2023
7932db5
fix: move groupsetting creation to end of group creation
SebastianStorz Sep 19, 2023
db9fdba
Merge pull request #94 from digio-ch/bugfix
c0depwn Sep 25, 2023
6e54d13
WIP: All widgets without filter
SebastianStorz Sep 26, 2023
67eadb5
Merge branch 'stage' into issue/hc-235
SebastianStorz Sep 26, 2023
42f6c00
lint
SebastianStorz Sep 26, 2023
73d96d7
Merge pull request #95 from digio-ch/issue/hc-235
SebastianStorz Sep 26, 2023
0d6733e
lint
SebastianStorz Sep 26, 2023
d764bcf
Merge pull request #96 from digio-ch/issue/hc-235
SebastianStorz Sep 26, 2023
e5f1f19
Add filter
SebastianStorz Sep 27, 2023
d5af65a
lint
SebastianStorz Sep 27, 2023
455ea41
Merge branch 'stage' into issue/hc-235
SebastianStorz Sep 27, 2023
50aeeb4
Merge pull request #97 from digio-ch/issue/hc-235
SebastianStorz Sep 27, 2023
d3c3d5b
fix query, fix colors
SebastianStorz Sep 29, 2023
1f9329d
Merge pull request #98 from digio-ch/issue/hc-235
SebastianStorz Sep 29, 2023
909379b
lint
SebastianStorz Sep 29, 2023
8d96886
Merge pull request #99 from digio-ch/issue/hc-235
SebastianStorz Sep 29, 2023
c0dd1a9
various fixes
SebastianStorz Oct 6, 2023
7c507b8
lint
SebastianStorz Oct 6, 2023
92a93e8
Merge pull request #100 from digio-ch/issue/hc-235
SebastianStorz Oct 6, 2023
f4db67f
fix: reduce census API computation duration by ~93%
SebastianStorz Oct 27, 2023
b5ceb1b
fix: prevent 0 division and null errors
SebastianStorz Oct 27, 2023
8de0204
fix: use proper entities for preview
SebastianStorz Oct 27, 2023
445e429
add crontab and finish census command
SebastianStorz Oct 27, 2023
732e11d
Merge pull request #101 from digio-ch/issue/hc-235
SebastianStorz Oct 27, 2023
e316ab3
Merge pull request #102 from digio-ch/stage
SebastianStorz Nov 10, 2023
a5c9b19
fix: increase contrast between colors in Roleoverview
SebastianStorz Dec 19, 2023
efa4d38
Merge pull request #103 from digio-ch/hc-237-unfinished
SebastianStorz Dec 20, 2023
57433a0
fix: prevent unknown grouptypes from causing errors
SebastianStorz Feb 8, 2024
7e4c4e3
restructure census services and create census date provider
SebastianStorz Feb 8, 2024
9ac50ab
implement latest year and date range functions
SebastianStorz Feb 8, 2024
c434c98
add comment
SebastianStorz Feb 8, 2024
097a58f
adjust description
SebastianStorz Feb 8, 2024
cd5712f
fix query
SebastianStorz Feb 8, 2024
199c85e
add dynamic year to widgets with no date information
SebastianStorz Feb 8, 2024
e02e1f6
sort camps by start date
SebastianStorz Feb 8, 2024
1cc682d
add logger warning for invalid groups
SebastianStorz Feb 15, 2024
8af93d8
change help text
SebastianStorz Feb 15, 2024
ed5ab3e
Revert "change help text"
SebastianStorz Feb 15, 2024
008702f
change help text
SebastianStorz Feb 15, 2024
4cd7c22
Merge pull request #113 from digio-ch/issue/hc-243
SebastianStorz Feb 15, 2024
a6f7fca
update composer image
SebastianStorz Feb 15, 2024
ec839c5
revert version change and enforce http 1 for git
SebastianStorz Feb 15, 2024
549e195
try to increase buffer size instead
SebastianStorz Feb 15, 2024
13d2ef1
retry with updated gitlab version
SebastianStorz Feb 15, 2024
0d547b2
.
SebastianStorz Feb 15, 2024
0f8286e
disable proxy for http1
SebastianStorz Feb 15, 2024
dd5b2bc
enable git tracing
SebastianStorz Feb 15, 2024
58e998f
verbose composer
SebastianStorz Feb 15, 2024
04db146
.
SebastianStorz Feb 15, 2024
9841524
Merge pull request #112 from digio-ch/issue/hc-241
SebastianStorz Feb 15, 2024
5d38db4
Merge pull request #111 from digio-ch/issue/hc-240
SebastianStorz Feb 15, 2024
5ab8cd3
linting
SebastianStorz Feb 15, 2024
cb4a96f
Merge pull request #114 from digio-ch/issue/hc-244
SebastianStorz Feb 15, 2024
33f8093
lint
SebastianStorz Feb 15, 2024
5f3213f
prevent faulty role data from breaking the aggregation
SebastianStorz Feb 16, 2024
9ca608d
lint
SebastianStorz Feb 16, 2024
310e553
Merge pull request #115 from digio-ch/issue/hc-244
SebastianStorz Feb 16, 2024
9800583
prevent invalid encoding edgecases and fix buffering
SebastianStorz May 27, 2024
5dd2323
add buffering to roles
SebastianStorz May 27, 2024
1c77d95
Merge pull request #120 from digio-ch/issue/hc-246
SebastianStorz May 27, 2024
bae8a71
lint
SebastianStorz May 28, 2024
5bdc4c8
Merge pull request #121 from digio-ch/issue/hc-246
SebastianStorz May 28, 2024
887fd39
change grouptype to region
SebastianStorz Jul 21, 2024
e927ffa
Merge pull request #123 from digio-ch/issue/hc-251
SebastianStorz Jul 21, 2024
2bac08c
Gamification merger
SebastianStorz Sep 11, 2024
faae2e4
Add placeholder text
SebastianStorz Sep 11, 2024
a22c9af
adjust level restrictions and change revision goal check
SebastianStorz Sep 11, 2024
50c45f8
Merge pull request #124 from digio-ch/issue/gamification
SebastianStorz Sep 11, 2024
dcd889d
lint
SebastianStorz Sep 11, 2024
44b5719
Merge pull request #125 from digio-ch/issue/gamification
SebastianStorz Sep 11, 2024
727462a
add auto linting command to readme
SebastianStorz Sep 11, 2024
094b15e
change "docker-compose" to "docker compose" for test files
SebastianStorz Sep 11, 2024
f2d572d
Merge pull request #127 from digio-ch/issue/gamification
SebastianStorz Sep 11, 2024
64bbf41
add placeholders
SebastianStorz Sep 11, 2024
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
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ GRAYLOG_CLIENT_KEY=
IMPORT_TARGET_DIR=data

# Sentry
SENTRY_DSN=https://[email protected]/26
SENTRY_DSN=""
12 changes: 11 additions & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,14 @@ services:
- { name: 'widget.aggregator', key: 'general.date' }

App\Service\Aggregator\AggregatorRegistry:
arguments: [!tagged { tag: 'widget.aggregator', index_by: 'key' }]
arguments: [ !tagged { tag: 'widget.aggregator', index_by: 'key' } ]

App\Service\GroupStructureAPIService:
arguments:
$apiToken: '%env(GROUP_STRUCTURE_TOKEN)%'
$url: '%env(GROUP_STRUCTURE_URL)%'

App\Service\CensusAPIService:
arguments:
$apiToken: '%env(CENSUS_TOKEN)%'
$url: '%env(CENSUS_URL)%'
3 changes: 3 additions & 0 deletions run-import.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ set -e
/usr/local/bin/php /srv/bin/console app:map-peoples-addresses
/usr/local/bin/php /srv/bin/console app:quap:import-questionnaire

/usr/local/bin/php /srv/bin/console app:fetch-all-groups # Also fetches Group Meeting points.

/usr/local/bin/php /srv/bin/console app:aggregate-data
/usr/local/bin/php /srv/bin/console app:quap:compute-answers

/usr/local/bin/php /srv/bin/console app:compute-permissions

257 changes: 257 additions & 0 deletions src/Command/FetchAllGroupsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<?php

namespace App\Command;

use App\Entity\Midata\Group;
use App\Entity\Midata\GroupType;
use App\Entity\Statistics\GroupGeoLocation;
use App\Entity\Statistics\StatisticGroup;
use App\Exception\ApiException;
use App\Helper\BatchedRepository;
use App\Model\CommandStatistics;
use App\Model\LogMessage\SimpleLogMessage;
use App\Repository\Midata\GroupRepository;
use App\Repository\Midata\GroupTypeRepository;
use App\Repository\Statistics\GroupGeoLocationRepository;
use App\Repository\Statistics\StatisticGroupRepository;
use App\Service\GroupStructureAPIService;
use Digio\Logging\GelfLogger;
use Doctrine\ORM\EntityManagerInterface;
use GuzzleHttp\Exception\ClientException;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class FetchAllGroupsCommand extends StatisticsCommand
{
protected GroupStructureAPIService $apiService;

protected SymfonyStyle $io;

protected StatisticGroupRepository $statisticGroupRepository;

protected GroupTypeRepository $groupTypeRepository;

protected EntityManagerInterface $em;

protected GroupRepository $groupRepository;

protected GroupGeoLocationRepository $geoLocationRepository;

protected GelfLogger $gelfLogger;

protected $stats = [0, 0];

/**
* @param GroupStructureAPIService $apiService
*/
public function __construct(
EntityManagerInterface $em,
GroupStructureAPIService $apiService,
StatisticGroupRepository $statisticGroupRepository,
GroupTypeRepository $groupTypeRepository,
GroupRepository $groupRepository,
GroupGeoLocationRepository $geoLocationRepository,
GelfLogger $gelfLogger
) {
$this->em = $em;
$this->apiService = $apiService;
$this->statisticGroupRepository = $statisticGroupRepository;
$this->groupTypeRepository = $groupTypeRepository;
$this->groupRepository = $groupRepository;
$this->geoLocationRepository = $geoLocationRepository;
$this->gelfLogger = $gelfLogger;
parent::__construct();
}


public function configure()
{
$this->setName('app:fetch-all-groups')
->setDescription('Fetches all groups from MiData (' . $this->apiService->getUrl() . ') using the groups endpoint.');
}

public function execute(InputInterface $input, OutputInterface $output)
{
$this->io = new SymfonyStyle($input, $output);

$start = microtime(true);
$this->geoLocationRepository->deleteAll();
$this->statisticGroupRepository->deleteAll();

$batchedStatisticsRepository = new BatchedRepository($this->statisticGroupRepository);
$batchedGeoRepository = new BatchedRepository($this->geoLocationRepository);
$this->fetchGroupRecursive(2, null, null, $batchedStatisticsRepository, $batchedGeoRepository);
$batchedStatisticsRepository->flush();
$batchedGeoRepository->flush();

//$this->fetchAllRemaining();
$this->logMissingBranches();

$this->stats[0] = microtime(true) - $start;
return Command::SUCCESS;
}

private function logMissingBranches()
{
$groups = $this->statisticGroupRepository->findBy(['parent_group' => null]);
foreach ($groups as $group) {
if ($group->getId() === 2) {
continue;
}
$this->gelfLogger->warning(new SimpleLogMessage($this->recursiveGetChildrenAsJsonString($group)));
$this->io->warning('This branch is missing the parent: {' . $this->recursiveGetChildrenAsJsonString($group) . '}');
}
}

/**
* Return all children of a group as JSON like string
*/
private function recursiveGetChildrenAsJsonString(StatisticGroup $group)
{
$result = '"' . $group->getId();
$children = $group->getChildren();
if (sizeof($children) === 0) {
return $result . '": null,';
}
$result .= '": {';
foreach ($children as $child) {
$result .= $this->recursiveGetChildrenAsJsonString($child);
}
return $result . '},';
}

/**
* Brutforces through all groups and fetches them. Takes longer because you have to wait for every 404 and you don't
* know which index is the last. Don't use unless necessary
*/
private function fetchAllRemaining()
{
for ($i = 2; $i < 11600; $i++) {
$group = $this->statisticGroupRepository->findOneBy(['id' => $i]);
if (is_null($group)) {
$result = $this->fetchGroup($i);
$content = $result->getContent()['groups'][0];
$statisticGroup = new StatisticGroup();
$rawGroup = $content;

$name = trim($rawGroup['name']);
$parentGroup = $rawGroup['links']['parent'] ?? null;
if (!is_null($parentGroup)) {
$parentGroup = $this->statisticGroupRepository->findOneBy(['id' => $parentGroup]);
}
/** @var GroupType $groupType */
$groupType = $this->groupTypeRepository->findOneBy(['deLabel' => $rawGroup['group_type']]);
$statisticGroup->setId($i);
$statisticGroup->setName($name);
$statisticGroup->setParentGroup($parentGroup);
$statisticGroup->setGroupType($groupType);
$this->io->writeln('Adding ' . $i);
$this->statisticGroupRepository->add($statisticGroup);
}
}
}

private function fetchGroup(int $id, bool $stopOnFail = false)
{
try {
$result = $this->apiService->getGroup($id);
if ($result->getStatusCode() !== 200) {
$this->io->error([
'API call for group with id ' . $id . ' failed!',
'HTTP status code: ' . $result->getStatusCode()
]);
}
return $result;
} catch (ClientException $e) {
$this->io->error('Fetch for ' . $id . ' resultet in an error (' . $e->getCode() . ')');
if ($stopOnFail) {
$this->gelfLogger('Fetching Group (' . $id . ') failed with error code (' . $e->getCode() . '), stopped fetching.');
throw new ApiException('Fetching Group (' . $id . ') failed, stopping fetching.');
}
return null;
}
}

/**
* Fetch a group and its children recursively
*/
private function fetchGroupRecursive(int $id, ?StatisticGroup $parent, ?StatisticGroup $canton, BatchedRepository $batchedStatisticsRepository, BatchedRepository $batchedGeoRepository)
{
$result = $this->fetchGroup($id, true);
$statisticGroup = new StatisticGroup();

$rawGroup = $result->getContent()['groups'][0];
$name = trim($rawGroup['name']);
$children = $rawGroup['links']['children'] ?? [];
/**
* Keep in mind that the group type is not sent via UID (zb. Group::Abteilung) but via the label in the language
* that you are using. In this case we use /de/group... so the german label.
* @var GroupType $groupType
*/
$groupType = $this->groupTypeRepository->findOneBy(['deLabel' => $rawGroup['group_type']]);

$statisticGroup->setId($id);
$statisticGroup->setCanton($canton);
$statisticGroup->setName($name);
$statisticGroup->setParentGroup($parent);
$statisticGroup->setGroupType($groupType);
$batchedStatisticsRepository->add($statisticGroup);
$this->stats[1]++;

/** @var array $geoLocations */
$geoLocations = $result->getContent()['linked']['geolocations'] ?? [];
$this->createGeoLocations($statisticGroup, $geoLocations, $batchedGeoRepository);
$this->fillHealthGroupWithStatisticGroup($statisticGroup);

if ($groupType->getGroupType() === GroupType::CANTON) {
$canton = $statisticGroup;
}
foreach ($children as $child) {
$this->fetchGroupRecursive($child, $statisticGroup, $canton, $batchedStatisticsRepository, $batchedGeoRepository);
}
}

private function createGeoLocations(StatisticGroup $group, ?array $geoLocations, BatchedRepository $batchedGeoRepository)
{
if (is_null($geoLocations)) {
return;
}
foreach ($geoLocations as $rawGeoLocation) {
$geoLocation = new GroupGeoLocation();
$geoLocation->setId($rawGeoLocation['id']);
$geoLocation->setGroup($group);
$geoLocation->setLat($rawGeoLocation['lat']);
$geoLocation->setLong($rawGeoLocation['long']);
$batchedGeoRepository->add($geoLocation);
}
}

/**
* Fills in the parent and canton of the equivalent Health group with the Statistics group
*/
private function fillHealthGroupWithStatisticGroup(StatisticGroup $statisticGroup)
{
/** @var Group $group */
$group = $this->groupRepository->findOneBy(['id' => $statisticGroup->getId()]);
if (!is_null($group)) {
if (!is_null($statisticGroup->getCanton())) {
$group->setCantonId($statisticGroup->getCanton()->getId());
$group->setCantonName($statisticGroup->getCanton()->getName());
}
if (!is_null($statisticGroup->getParentGroup())) {
/** @var Group $parent */
$parent = $this->groupRepository->findOneBy(['id' => $statisticGroup->getParentGroup()->getId()]);
if (!is_null($parent)) {
$group->setParentGroup($parent);
}
}
}
}

public function getStats(): CommandStatistics
{
return new CommandStatistics($this->stats[0], 'Fetched ' . $this->stats[1] . ' Groups in ' . number_format($this->stats[0], 2) . ' Seconds', $this->stats[1]);
}
}
29 changes: 29 additions & 0 deletions src/Command/FetchCensusCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace App\Command;

use App\Model\CommandStatistics;
use App\Service\GroupStructureAPIService;

class FetchCensusCommand extends StatisticsCommand
{
protected GroupStructureAPIService $apiService;

public function __construct()
{
parent::__construct();
}


public function configure()
{
$this->setName('app:fetch-census')
->setDescription('Not implemented');
}

// TODO: Implement the statistics
public function getStats(): CommandStatistics
{
return new CommandStatistics(0, 'Statistics not yet implemented.');
}
}
1 change: 1 addition & 0 deletions src/Command/FetchDataCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Command;

use App\Model\CommandStatistics;
use App\Repository\Statistics\StatisticGroupRepository;
use App\Service\Pbs\PbsApiService;
use Exception;
use Symfony\Component\Console\Input\InputInterface;
Expand Down
2 changes: 1 addition & 1 deletion src/Command/ImportFromJsonCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ private function importGroups(OutputInterface $output)
$metadata->setIdGenerator(new AssignedGenerator());
}

$group->setName($gr['name']);
$group->setName(trim($gr['name']));
$group->setCantonId($gr['canton_id'] ?? null);
$group->setCantonName($gr['canton_name'] ?? null);
$group->setCreatedAt(new DateTimeImmutable($gr['created_at']));
Expand Down
Loading
Loading