mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-30 14:06:13 +00:00
bootstrap fake sms from cli
This commit is contained in:
parent
9e4fd6183e
commit
616be5cc8a
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CalendarBundle\Command;
|
||||
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\CalendarBundle\Service\ShortMessageNotification\ShortMessageForCalendarBuilderInterface;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
|
||||
use Chill\MainBundle\Repository\UserRepositoryInterface;
|
||||
use Chill\MainBundle\Service\ShortMessage\ShortMessage;
|
||||
use Chill\MainBundle\Service\ShortMessage\ShortMessageSenderInterface;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Repository\PersonRepository;
|
||||
use libphonenumber\PhoneNumber;
|
||||
use libphonenumber\PhoneNumberFormat;
|
||||
use libphonenumber\PhoneNumberType;
|
||||
use libphonenumber\PhoneNumberUtil;
|
||||
use libphonenumber\ValidationResult;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
|
||||
class SendTestShortMessageOnCalendarCommand extends Command
|
||||
{
|
||||
private PersonRepository $personRepository;
|
||||
|
||||
private PhoneNumberUtil $phoneNumberUtil;
|
||||
|
||||
private PhoneNumberHelperInterface $phoneNumberHelper;
|
||||
|
||||
private ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder;
|
||||
|
||||
private ShortMessageSenderInterface $messageSender;
|
||||
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
/**
|
||||
* @param PersonRepository $personRepository
|
||||
* @param PhoneNumberUtil $phoneNumberUtil
|
||||
* @param PhoneNumberHelperInterface $phoneNumberHelper
|
||||
* @param ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder
|
||||
* @param ShortMessageSenderInterface $messageSender
|
||||
*/
|
||||
public function __construct(
|
||||
PersonRepository $personRepository,
|
||||
PhoneNumberUtil $phoneNumberUtil,
|
||||
PhoneNumberHelperInterface $phoneNumberHelper,
|
||||
ShortMessageForCalendarBuilderInterface $messageForCalendarBuilder,
|
||||
ShortMessageSenderInterface $messageSender,
|
||||
UserRepositoryInterface $userRepository
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->personRepository = $personRepository;
|
||||
$this->phoneNumberUtil = $phoneNumberUtil;
|
||||
$this->phoneNumberHelper = $phoneNumberHelper;
|
||||
$this->messageForCalendarBuilder = $messageForCalendarBuilder;
|
||||
$this->messageSender = $messageSender;
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'chill:calendar:test-send-short-message';
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setDescription('Test sending a SMS for a dummy calendar appointment');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$calendar = new Calendar();
|
||||
$calendar->setSendSMS(true);
|
||||
|
||||
/** @var QuestionHelper $helper */
|
||||
$helper = $this->getHelper('question');
|
||||
|
||||
// start date
|
||||
$question = new Question("When will start the appointment ? (default: \"1 hour\") ", '1 hour');
|
||||
$startDate = new \DateTimeImmutable($helper->ask($input, $output, $question));
|
||||
|
||||
if (false === $startDate) {
|
||||
throw new \UnexpectedValueException("could not create a date with this date and time");
|
||||
}
|
||||
|
||||
$calendar->setStartDate($startDate);
|
||||
|
||||
// end date
|
||||
$question = new Question("How long will last the appointment ? (default: \"PT30M\") ", 'PT30M');
|
||||
$interval = new \DateInterval($helper->ask($input, $output, $question));
|
||||
|
||||
if (false === $interval) {
|
||||
throw new \UnexpectedValueException("could not create the interval");
|
||||
}
|
||||
|
||||
$calendar->setEndDate($calendar->getStartDate()->add($interval));
|
||||
|
||||
// a person
|
||||
$question = new Question("Who will participate ? Give an id for a person. ");
|
||||
$question
|
||||
->setValidator(function ($answer): Person {
|
||||
if (!is_numeric($answer)) {
|
||||
throw new \UnexpectedValueException('the answer must be numeric');
|
||||
}
|
||||
|
||||
if (0 >= (int) $answer) {
|
||||
throw new \UnexpectedValueException('the answer must be greater than zero');
|
||||
}
|
||||
|
||||
$person = $this->personRepository->find((int) $answer);
|
||||
|
||||
if (null === $person) {
|
||||
throw new \UnexpectedValueException("The person is not found");
|
||||
}
|
||||
|
||||
return $person;
|
||||
});
|
||||
|
||||
$person = $helper->ask($input, $output, $question);
|
||||
$calendar->addPerson($person);
|
||||
|
||||
|
||||
// a main user
|
||||
$question = new Question("Who will be the main user ? Give an id for a user. ");
|
||||
$question
|
||||
->setValidator(function ($answer): User {
|
||||
if (!is_numeric($answer)) {
|
||||
throw new \UnexpectedValueException('the answer must be numeric');
|
||||
}
|
||||
|
||||
if (0 >= (int) $answer) {
|
||||
throw new \UnexpectedValueException('the answer must be greater than zero');
|
||||
}
|
||||
|
||||
$user = $this->userRepository->find((int) $answer);
|
||||
|
||||
if (null === $user) {
|
||||
throw new \UnexpectedValueException("The user is not found");
|
||||
}
|
||||
|
||||
return $user;
|
||||
});
|
||||
|
||||
$user = $helper->ask($input, $output, $question);
|
||||
$calendar->setMainUser($user);
|
||||
|
||||
// phonenumber
|
||||
$question = new Question("To which number are we going to send this fake message ?",
|
||||
null !== $person->getMobilenumber() ?
|
||||
$this->phoneNumberHelper->format($person->getMobilenumber()):
|
||||
null
|
||||
);
|
||||
|
||||
$question->setNormalizer(function ($answer): PhoneNumber {
|
||||
if (null === $answer) {
|
||||
throw new \UnexpectedValueException("The person is not found");
|
||||
}
|
||||
|
||||
$phone = $this->phoneNumberUtil->parse($answer, 'BE');
|
||||
|
||||
if (!$this->phoneNumberUtil->isPossibleNumberForType($phone, PhoneNumberType::MOBILE)) {
|
||||
throw new \UnexpectedValueException("Phone number si not a mobile");
|
||||
}
|
||||
|
||||
return $phone;
|
||||
});
|
||||
|
||||
$phone = $helper->ask($input, $output, $question);
|
||||
|
||||
$messages = $this->messageForCalendarBuilder->buildMessageForCalendar($calendar);
|
||||
|
||||
if (0 === count($messages)) {
|
||||
$output->writeln('no message to send to this user');
|
||||
}
|
||||
|
||||
foreach ($messages as $key => $message) {
|
||||
$output->writeln("The short message for SMS ${key} will be: ");
|
||||
$output->writeln($message->getContent());
|
||||
$message->setPhoneNumber($phone);
|
||||
$this->messageSender->send($message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -39,6 +39,12 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf
|
||||
$loader->load('services/remote_calendar.yaml');
|
||||
|
||||
$container->setParameter('chill_calendar', $config);
|
||||
|
||||
if ($config['short_messages']['enabled']) {
|
||||
$container->setParameter('chill_calendar.short_messages', $config['short_messages']);
|
||||
} else {
|
||||
$container->setParameter('chill_calendar.short_messages', null);
|
||||
}
|
||||
}
|
||||
|
||||
public function prepend(ContainerBuilder $container)
|
||||
|
@ -26,7 +26,12 @@ class Configuration implements ConfigurationInterface
|
||||
$treeBuilder = new TreeBuilder('chill_calendar');
|
||||
$rootNode = $treeBuilder->getRootNode('chill_calendar');
|
||||
|
||||
$rootNode->children()
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('short_messages')
|
||||
->canBeDisabled()
|
||||
->children()->end()
|
||||
->end() // end for short_messages
|
||||
->arrayNode('remote_calendars_sync')->canBeEnabled()
|
||||
->children()
|
||||
->arrayNode('microsoft_graph')->canBeEnabled()
|
||||
|
@ -52,6 +52,12 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface
|
||||
|
||||
use TrackUpdateTrait;
|
||||
|
||||
public const SMS_CANCEL_PENDING = 'sms_cancel_pending';
|
||||
|
||||
public const SMS_PENDING = 'sms_pending';
|
||||
|
||||
public const SMS_SENT = 'sms_sent';
|
||||
|
||||
public const STATUS_CANCELED = 'canceled';
|
||||
|
||||
public const STATUS_MOVED = 'moved';
|
||||
@ -169,7 +175,12 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface
|
||||
/**
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
*/
|
||||
private ?bool $sendSMS;
|
||||
private ?bool $sendSMS = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=false, options={"default": Calendar::SMS_PENDING})
|
||||
*/
|
||||
private string $smsStatus = self::SMS_PENDING;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime_immutable", nullable=false)
|
||||
@ -368,6 +379,11 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface
|
||||
return $this->sendSMS;
|
||||
}
|
||||
|
||||
public function getSmsStatus(): string
|
||||
{
|
||||
return $this->smsStatus;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->startDate;
|
||||
@ -551,6 +567,11 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSmsStatus(string $smsStatus): void
|
||||
{
|
||||
$this->smsStatus = $smsStatus;
|
||||
}
|
||||
|
||||
public function setStartDate(DateTimeImmutable $startDate): self
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
@ -562,6 +583,10 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
$this->status = $status;
|
||||
|
||||
if (self::STATUS_CANCELED === $status && $this->getSmsStatus() === self::SMS_SENT) {
|
||||
$this->setSmsStatus(self::SMS_CANCEL_PENDING);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,10 @@ namespace Chill\CalendarBundle\Repository;
|
||||
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
class CalendarRepository implements ObjectRepository
|
||||
@ -67,6 +69,21 @@ class CalendarRepository implements ObjectRepository
|
||||
);
|
||||
}
|
||||
|
||||
public function findByNotificationAvailable(DateTimeImmutable $startDate, DateTimeImmutable $endDate, ?int $limit = null, ?int $offset = null): array
|
||||
{
|
||||
$qb = $this->queryByNotificationAvailable($startDate, $endDate)->select('c');
|
||||
|
||||
if (null !== $limit) {
|
||||
$qb->setMaxResults($limit);
|
||||
}
|
||||
|
||||
if (null !== $offset) {
|
||||
$qb->setFirstResult($offset);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?Calendar
|
||||
{
|
||||
return $this->repository->findOneBy($criteria);
|
||||
@ -76,4 +93,26 @@ class CalendarRepository implements ObjectRepository
|
||||
{
|
||||
return Calendar::class;
|
||||
}
|
||||
|
||||
private function queryByNotificationAvailable(DateTimeImmutable $startDate, DateTimeImmutable $endDate): QueryBuilder
|
||||
{
|
||||
$qb = $this->repository->createQueryBuilder('c');
|
||||
|
||||
$qb->where(
|
||||
$qb->expr()->andX(
|
||||
$qb->expr()->eq('c.sendSMS', "'TRUE'"),
|
||||
$qb->expr()->gte('c.startDate', ':startDate'),
|
||||
$qb->expr()->lt('c.startDate', ':endDate'),
|
||||
$qb->expr()->in('c.smsStatus', ':statuses')
|
||||
)
|
||||
);
|
||||
|
||||
$qb->setParameters([
|
||||
'startDate' => $startDate,
|
||||
'endDate' => $endDate,
|
||||
'statuses' => [Calendar::SMS_PENDING, Calendar::SMS_CANCEL_PENDING],
|
||||
]);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
}
|
||||
|
@ -33,3 +33,11 @@ services:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
resource: '../../Security/'
|
||||
|
||||
Chill\CalendarBundle\Service\:
|
||||
autoconfigure: true
|
||||
autowire: true
|
||||
resource: '../../Service/'
|
||||
|
||||
Chill\CalendarBundle\Service\ShortMessageForCalendarBuilderInterface:
|
||||
alias: Chill\CalendarBundle\Service\DefaultShortMessageForCalendarBuider
|
||||
|
@ -0,0 +1 @@
|
||||
Votre travailleur social {{ calendar.mainUser.label }} vous rencontrera le {{ calendar.startDate|format_date('short') }} à {{ calendar.startDate|format_time('medium') }} - LIEU. {% if calendar.location is not null and calendar.location.phonenumber is not null %}En cas d’indisponibilité rappelez-nous au {{ calendar.location.phonenumber|chill_format_phonenumber }}.{% endif %}
|
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CalendarBundle\Service\ShortMessageNotification;
|
||||
|
||||
use Chill\BudgetBundle\Templating\Twig;
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\MainBundle\Service\Mailer\ShortMessage;
|
||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
|
||||
class DefaultShortMessageForCalendarBuilder implements ShortMessageForCalendarBuilderInterface
|
||||
{
|
||||
private ?array $config = null;
|
||||
|
||||
private EngineInterface $engine;
|
||||
|
||||
public function __construct(
|
||||
ParameterBagInterface $parameterBag,
|
||||
EngineInterface $engine
|
||||
) {
|
||||
$this->config = $parameterBag->get('chill_calendar.short_messages');
|
||||
$this->engine = $engine;
|
||||
}
|
||||
|
||||
public function buildMessageForCalendar(Calendar $calendar): array
|
||||
{
|
||||
if (null === $this->config || true !== $calendar->getSendSMS()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$toUsers = [];
|
||||
|
||||
foreach ($calendar->getPersons() as $person) {
|
||||
if (false === $person->getAcceptSMS() || null === $person->getAcceptSMS() || null === $person->getMobilenumber()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$toUsers[] = new \Chill\MainBundle\Service\ShortMessage\ShortMessage(
|
||||
$this->engine->render('@ChillCalendar/CalendarShortMessage/short_message.txt.twig', ['calendar' => $calendar]),
|
||||
$person->getMobilenumber()
|
||||
);
|
||||
}
|
||||
|
||||
return $toUsers;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\CalendarBundle\Service\ShortMessageNotification;
|
||||
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\MainBundle\Service\Mailer\ShortMessage;
|
||||
|
||||
interface ShortMessageForCalendarBuilderInterface
|
||||
{
|
||||
/**
|
||||
* @param Calendar $calendar
|
||||
* @return array|ShortMessage[]
|
||||
*/
|
||||
public function buildMessageForCalendar(Calendar $calendar): array;
|
||||
}
|
@ -196,6 +196,7 @@ class ChillMainExtension extends Extension implements
|
||||
$loader->load('services/search.yaml');
|
||||
$loader->load('services/serializer.yaml');
|
||||
$loader->load('services/mailer.yaml');
|
||||
$loader->load('services/short_message.yaml');
|
||||
|
||||
$this->configureCruds($container, $config['cruds'], $config['apis'], $loader);
|
||||
}
|
||||
|
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Service\ShortMessage;
|
||||
|
||||
class NullShortMessageSender implements ShortMessageSenderInterface
|
||||
{
|
||||
public function send(ShortMessage $shortMessage): void
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Service\ShortMessage;
|
||||
|
||||
use libphonenumber\PhoneNumber;
|
||||
|
||||
class ShortMessage
|
||||
{
|
||||
private string $content;
|
||||
|
||||
private PhoneNumber $phoneNumber;
|
||||
|
||||
public function __construct(string $content, PhoneNumber $phoneNumber)
|
||||
{
|
||||
$this->content = $content;
|
||||
$this->phoneNumber = $phoneNumber;
|
||||
}
|
||||
|
||||
public function getContent(): string
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function getPhoneNumber(): PhoneNumber
|
||||
{
|
||||
return $this->phoneNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $content
|
||||
*/
|
||||
public function setContent(string $content): void
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhoneNumber $phoneNumber
|
||||
*/
|
||||
public function setPhoneNumber(PhoneNumber $phoneNumber): void
|
||||
{
|
||||
$this->phoneNumber = $phoneNumber;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace Chill\MainBundle\Service\ShortMessage;
|
||||
|
||||
interface ShortMessageSenderInterface
|
||||
{
|
||||
public function send(ShortMessage $shortMessage): void;
|
||||
}
|
@ -26,6 +26,7 @@ services:
|
||||
tags:
|
||||
- { name: 'doctrine.event_subscriber' }
|
||||
|
||||
|
||||
# workflow related
|
||||
Chill\MainBundle\Workflow\:
|
||||
resource: '../Workflow/'
|
||||
|
@ -0,0 +1,5 @@
|
||||
services:
|
||||
Chill\MainBundle\Service\ShortMessage\:
|
||||
resource: '../Service/ShortMessage'
|
||||
autowire: true
|
||||
autoconfigure: true
|
Loading…
x
Reference in New Issue
Block a user