Compare commits

..

6 Commits

24 changed files with 92 additions and 30 deletions

View File

@@ -0,0 +1,7 @@
kind: DX
body: |
Send notifications log to dedicated channel, if it exists
time: 2025-10-27T15:00:53.309372316+01:00
custom:
Issue: ""
SchemaChange: No schema change

View File

@@ -0,0 +1,6 @@
kind: Feature
body: Add columns for comments linked to an activity in the activity list export
time: 2025-10-29T15:25:10.493968528+01:00
custom:
Issue: "404"
SchemaChange: No schema change

3
.changes/v4.6.1.md Normal file
View File

@@ -0,0 +1,3 @@
## v4.6.1 - 2025-10-27
### Fixed
* Fix export case where no 'reason' is picked within the PersonHavingActivityBetweenDateFilter.php

View File

@@ -6,6 +6,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html),
and is generated by [Changie](https://github.com/miniscruff/changie).
## v4.6.1 - 2025-10-27
### Fixed
* Fix export case where no 'reason' is picked within the PersonHavingActivityBetweenDateFilter.php
## v4.6.0 - 2025-10-15
### Feature
* ([#423](https://gitlab.com/Chill-Projet/chill-bundles/-/issues/423)) Create environment banner that can be activated and configured depending on the image deployed

View File

@@ -66,6 +66,9 @@ class ListActivityHelper
->leftJoin('activity.location', 'location')
->addSelect('location.name AS locationName')
->addSelect('activity.sentReceived')
->addSelect('activity.comment.comment AS commentText')
->addSelect('activity.comment.date AS commentDate')
->addSelect('JSON_BUILD_OBJECT(\'uid\', activity.comment.userId, \'d\', activity.comment.date) AS commentUser')
->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.createdBy), \'d\', activity.createdAt) AS createdBy')
->addSelect('activity.createdAt')
->addSelect('JSON_BUILD_OBJECT(\'uid\', IDENTITY(activity.updatedBy), \'d\', activity.updatedAt) AS updatedBy')
@@ -87,6 +90,8 @@ class ListActivityHelper
'createdAt', 'updatedAt' => $this->dateTimeHelper->getLabel($key),
'createdBy', 'updatedBy' => $this->userHelper->getLabel($key, $values, $key),
'date' => $this->dateTimeHelper->getLabel(self::MSG_KEY.$key),
'commentDate' => $this->dateTimeHelper->getLabel(self::MSG_KEY.'comment_date'),
'commentUser' => $this->userHelper->getLabel($key, $values, self::MSG_KEY.'comment_user'),
'attendeeName' => function ($value) {
if ('_header' === $value) {
return 'Attendee';
@@ -176,6 +181,9 @@ class ListActivityHelper
'usersNames',
'thirdPartiesIds',
'thirdPartiesNames',
'commentText',
'commentDate',
'commentUser',
'createdBy',
'createdAt',
'updatedBy',

View File

@@ -90,7 +90,9 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
public function getFormDefaultData(): array
{
return [];
return [
'reasons' => [],
];
}
public function describeAction($data, ExportGenerationContext $context): string|\Symfony\Contracts\Translation\TranslatableInterface|array

View File

@@ -42,6 +42,8 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
public function alterQuery(QueryBuilder $qb, $data, ExportGenerationContext $exportGenerationContext): void
{
error_log('alterQuery called with data: '.json_encode(array_keys($data)));
// create a subquery for activity
$sqb = $qb->getEntityManager()->createQueryBuilder();
$sqb->select('1')
@@ -59,7 +61,6 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
if (\in_array('activity', $qb->getAllAliases(), true)) {
$sqb->andWhere('activity_person_having_activity.id = activity.id');
}
if (isset($data['reasons']) && [] !== $data['reasons']) {
// add clause activity reason
$sqb->join('activity_person_having_activity.reasons', 'reasons_person_having_activity');
@@ -124,12 +125,38 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
public function normalizeFormData(array $formData): array
{
return ['date_from_rolling' => $formData['date_from_rolling']->normalize(), 'date_to_rolling' => $formData['date_to_rolling']->normalize()];
$normalized = [
'date_from_rolling' => $formData['date_from_rolling']->normalize(),
'date_to_rolling' => $formData['date_to_rolling']->normalize(),
'reasons' => [],
];
if (isset($formData['reasons']) && [] !== $formData['reasons']) {
$normalized['reasons'] = array_map(
fn (ActivityReason $reason) => $reason->getId(),
$formData['reasons']
);
}
return $normalized;
}
public function denormalizeFormData(array $formData, int $fromVersion): array
{
return ['date_from_rolling' => RollingDate::fromNormalized($formData['date_from_rolling']), 'date_to_rolling' => RollingDate::fromNormalized($formData['date_to_rolling'])];
$denormalized = [
'date_from_rolling' => RollingDate::fromNormalized($formData['date_from_rolling']),
'date_to_rolling' => RollingDate::fromNormalized($formData['date_to_rolling']),
'reasons' => [],
];
if (isset($formData['reasons']) && [] !== $formData['reasons']) {
$denormalized['reasons'] = array_map(
fn ($id) => $this->activityReasonRepository->find($id),
$formData['reasons']
);
}
return $denormalized;
}
public function getFormDefaultData(): array
@@ -143,10 +170,12 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
public function describeAction($data, ExportGenerationContext $context): array
{
$reasons = $data['reasons'] ?? [];
return [
[] === $data['reasons'] ?
'export.filter.person_between_dates.describe_action_with_no_subject'
: 'export.filter.person_between_dates.describe_action_with_subject',
[] === $reasons ?
'export.filter.activity.describe_action_with_no_subject'
: 'export.filter.activity.describe_action_with_subject',
[
'date_from' => $this->rollingDateConverter->convert($data['date_from_rolling']),
'date_to' => $this->rollingDateConverter->convert($data['date_to_rolling']),
@@ -154,7 +183,7 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
', ',
array_map(
fn (ActivityReason $r): string => '"'.$this->translatableStringHelper->localize($r->getName()).'"',
$data['reasons']
$reasons
)
),
],
@@ -168,6 +197,7 @@ final readonly class PersonHavingActivityBetweenDateFilter implements ExportElem
public function validateForm($data, ExecutionContextInterface $context): void
{
error_log('validateForm called with data: '.json_encode(array_keys($data)));
if ($this->rollingDateConverter->convert($data['date_from_rolling'])
>= $this->rollingDateConverter->convert($data['date_to_rolling'])) {
$context->buildViolation('export.filter.activity.person_between_dates.date mismatch')

View File

@@ -404,7 +404,9 @@ export:
id: Identifiant
List activities linked to an accompanying course: Liste les échanges liés à un parcours en fonction de différents filtres.
List activity linked to a course: Liste des échanges liés à un parcours
commentText: Commentaire
comment_date: Date de la dernière édition du commentaire
comment_user: Dernière édition par
filter:
activity:

View File

@@ -334,7 +334,7 @@ class ChillImportUsersCommand extends Command
protected function loadUsers()
{
$reader = Reader::createFromPath($this->tempInput->getArgument('csvfile'));
$reader = Reader::from($this->tempInput->getArgument('csvfile'));
$reader->setHeaderOffset(0);
foreach ($reader->getRecords() as $line => $r) {
@@ -362,7 +362,7 @@ class ChillImportUsersCommand extends Command
protected function prepareGroupingCenters()
{
$reader = Reader::createFromPath($this->tempInput->getOption('grouping-centers'));
$reader = Reader::from($this->tempInput->getOption('grouping-centers'));
$reader->setHeaderOffset(0);
foreach ($reader->getRecords() as $r) {
@@ -378,7 +378,7 @@ class ChillImportUsersCommand extends Command
protected function prepareWriter()
{
$this->output = $output = Writer::createFromPath($this->tempInput
$this->output = $output = Writer::from($this->tempInput
->getOption('csv-dump'), 'a+');
$output->insertOne([

View File

@@ -119,7 +119,7 @@ class ChillUserSendRenewPasswordCodeCommand extends Command
protected function getReader()
{
try {
$reader = Reader::createFromPath($this->input->getArgument('csvfile'));
$reader = Reader::from($this->input->getArgument('csvfile'));
} catch (\Exception $e) {
$this->logger->error('The csv file could not be read', [
'path' => $this->input->getArgument('csvfile'),

View File

@@ -43,7 +43,7 @@ final readonly class UserExportController
$users = $this->userRepository->findAllAsArray($request->getLocale());
$csv = Writer::createFromPath('php://temp', 'r+');
$csv = Writer::from('php://temp', 'r+');
$csv->insertOne(
array_map(
fn (string $e) => $this->translator->trans('admin.users.export.'.$e),
@@ -104,7 +104,7 @@ final readonly class UserExportController
$userPermissions = $this->userRepository->findAllUserACLAsArray();
$csv = Writer::createFromPath('php://temp', 'r+');
$csv = Writer::from('php://temp', 'r+');
$csv->insertOne(
array_map(
fn (string $e) => $this->translator->trans('admin.users.export.'.$e),

View File

@@ -64,7 +64,7 @@ class AddressReferenceBEFromBestAddress
$uncompressedStream = gzopen($tmpname, 'r');
$csv = Reader::createFromStream($uncompressedStream);
$csv = Reader::from($uncompressedStream);
$csv->setDelimiter(',');
$csv->setHeaderOffset(0);

View File

@@ -287,7 +287,7 @@ final class AddressReferenceBaseImporter
$filename = sprintf('%s-%s.csv', (new \DateTimeImmutable())->format('Ymd-His'), uniqid());
$path = Path::normalize(sprintf('%s%s%s', sys_get_temp_dir(), DIRECTORY_SEPARATOR, $filename));
$writer = Writer::createFromPath($path, 'w+');
$writer = Writer::from($path, 'w+');
// insert headers
$writer->insertOne([
'postalcode',

View File

@@ -53,7 +53,7 @@ class AddressReferenceFromBAN
// re-open it to read it
$csvDecompressed = gzopen($path, 'r');
$csv = Reader::createFromStream($csvDecompressed);
$csv = Reader::from($csvDecompressed);
$csv->setDelimiter(';')->setHeaderOffset(0);
$stmt = new Statement();
$stmt = $stmt->process($csv, [

View File

@@ -41,7 +41,7 @@ class AddressReferenceFromBano
fseek($file, 0);
$csv = Reader::createFromStream($file);
$csv = Reader::from($file);
$csv->setDelimiter(',');
$stmt = new Statement();
$stmt = $stmt->process($csv, [

View File

@@ -39,7 +39,7 @@ class AddressReferenceLU
fseek($file, 0);
$csv = Reader::createFromStream($file);
$csv = Reader::from($file);
$csv->setDelimiter(';');
$csv->setHeaderOffset(0);

View File

@@ -43,7 +43,7 @@ class PostalCodeBEFromBestAddress
$uncompressedStream = gzopen($tmpname, 'r');
$csv = Reader::createFromStream($uncompressedStream);
$csv = Reader::from($uncompressedStream);
$csv->setDelimiter(',');
$csv->setHeaderOffset(0);

View File

@@ -47,7 +47,7 @@ class PostalCodeFRFromOpenData
fseek($tmpfile, 0);
$csv = Reader::createFromStream($tmpfile);
$csv = Reader::from($tmpfile);
$csv->setDelimiter(',');
$csv->setHeaderOffset(0);

View File

@@ -18,7 +18,7 @@ use Symfony\Component\Notifier\Event\SentMessageEvent;
final readonly class SentMessageEventSubscriber implements EventSubscriberInterface
{
public function __construct(
private LoggerInterface $logger,
private LoggerInterface $notifierLogger, // will be send to "notifierLogger" if it exists
) {}
public static function getSubscribedEvents()
@@ -33,9 +33,9 @@ final readonly class SentMessageEventSubscriber implements EventSubscriberInterf
$message = $event->getMessage();
if (null === $message->getMessageId()) {
$this->logger->info('[sms] a sms message did not had any id after sending.', ['validReceiversI' => $message->getOriginalMessage()->getRecipientId()]);
$this->notifierLogger->info('[sms] a sms message did not had any id after sending.', ['validReceiversI' => $message->getOriginalMessage()->getRecipientId()]);
} else {
$this->logger->warning('[sms] a sms was sent', ['validReceiversI' => $message->getOriginalMessage()->getRecipientId(), 'idsI' => $message->getMessageId()]);
$this->notifierLogger->warning('[sms] a sms was sent', ['validReceiversI' => $message->getOriginalMessage()->getRecipientId(), 'idsI' => $message->getMessageId()]);
}
}
}

View File

@@ -49,7 +49,7 @@ final class ImportSocialWorkMetadata extends Command
$filepath = $input->getOption('filepath');
try {
$csv = Reader::createFromPath($filepath);
$csv = Reader::from($filepath);
} catch (\Throwable $e) {
throw new \Exception('Error while loading CSV.', 0, $e);
}

View File

@@ -29,7 +29,7 @@ class LoadSocialWorkMetadata extends Fixture implements OrderedFixtureInterface
public function load(ObjectManager $manager): void
{
try {
$csv = Reader::createFromPath(__DIR__.'/data/social_work_metadata.csv');
$csv = Reader::from(__DIR__.'/data/social_work_metadata.csv');
} catch (\Throwable $e) {
throw new \Exception('Error while loading CSV.', 0, $e);
}

View File

@@ -38,7 +38,7 @@ final readonly class SocialActionCSVExportService
array_keys($this->formatRow(new SocialAction()))
);
$csv = Writer::createFromPath('php://temp', 'w+');
$csv = Writer::from('php://temp', 'w+');
$csv->insertOne($headers);
foreach ($actions as $action) {

View File

@@ -36,7 +36,7 @@ readonly class SocialIssueCSVExportService
public function generateCsv(array $issues): Writer
{
// CSV headers
$csv = Writer::createFromPath('php://temp', 'r+');
$csv = Writer::from('php://temp', 'r+');
$csv->insertOne(
array_map(
fn (string $e) => $this->translator->trans($e),

View File

@@ -52,7 +52,7 @@ class ThirdpartyCSVExportController extends AbstractController
fwrite($output, "\xEF\xBB\xBF");
// Create CSV writer
$csv = Writer::createFromStream($output);
$csv = Writer::from($output);
// Write header row
$header = array_map(