sms_scheduler/src/Command/ContactUncontactedCommand.php
2025-11-24 20:53:42 +01:00

179 lines
7.5 KiB
PHP

<?php
namespace App\Command;
use App\Entity\Contacts;
use App\Entity\PhoneNumber;
use DateTime;
use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Exception;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Contracts\HttpClient\HttpClientInterface;
// Assuming you have an entity for your table
class ContactUncontactedCommand extends Command
{
// The command's name, used to run it from the console (e.g., bin/console app:contact-uncontacted)
protected static $defaultName = 'app:contact-uncontacted';
protected static $defaultDescription = 'Sends out SMS messages.';
protected static $apiEndpoint = 'https://gw.messaging.cm.com/v1.0/message';
// Inject the EntityManager and HttpClient as dependencies
private EntityManagerInterface $entityManager;
private HttpClientInterface $httpClient;
private string $sms_gateway_api_key;
private string $status_number;
public function __construct(EntityManagerInterface $entityManager,
HttpClientInterface $httpClient,
string $sms_gateway_api_key,
string $status_number)
{
parent::__construct();
$this->entityManager = $entityManager;
$this->httpClient = $httpClient;
$this->sms_gateway_api_key = $sms_gateway_api_key;
$this->status_number = $status_number;
}
protected function configure(): void
{
$this
->setName(self::$defaultName)
->setDescription(self::$defaultDescription);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$io->title('Starting uncontacted number check...');
// 1. Get uncontacted rows with a date in the past
$now = new DateTime();
/** @var Contacts[] $phoneNumbersToContact */
$phoneNumbersToContact = $this->entityManager->getRepository(Contacts::class)->createQueryBuilder('p')
->where('p.contacted = :state_contacted')
->andWhere('p.due_date < :now')
->setParameter('state_contacted', false)
->setParameter('now', $now)
->getQuery()
->getResult();
if (empty($phoneNumbersToContact)) {
$io->success('No uncontacted phone numbers found with past dates. Nothing to do.');
return Command::SUCCESS;
}
$io->progressStart(count($phoneNumbersToContact));
$countSent = 0;
$countTotal = 0;
// 2. Loop through each eligible phone number
foreach ($phoneNumbersToContact as $phoneContact) {
$io->progressAdvance();
$countTotal++;
// 3. Contact the HTTP REST API
try {
$study_id = $phoneContact->getStudyId();
$msgContentType = $phoneContact->getMsgContentType();
$message_1 = "Liebe Patientin, lieber Patient, \ngerne möchten wir von Ihnen erfahren, wie zufrieden Sie mit uns sind. Wir freuen uns, wenn Sie sich die Zeit nehmen und uns Ihre Eindrücke mitteilen.\nIhre Anregungen gehen direkt zum Qualitäts- und Risikomanagement.\n\nhttps://umfragetool.ukbonn.de/login?id={$study_id} \n\nIhr UKB.\n\nSMS vom UKB abbestellen per E-Mail an: datenschutz@ukbonn.de";
$message_2 = "Liebe/r Patient, bitte teilen Sie kurz Ihre Zufriedenheit mit dem UKB mit: https://k.ukbonn.de/{$phoneContact->getStudyIdShort()} Vielen Dank! Abmeldung per datenschutz@ukbonn.de";
$message = $message_1;
switch ($msgContentType) {
case 1:
break;
case 2:
$message = $message_2;
break;
}
$response = $this->httpClient->request('POST', self::$apiEndpoint, [
'headers' => [
'X-CM-PRODUCTTOKEN' => $this->sms_gateway_api_key,
'Accept' => 'application/json',
'Content-Type' => 'application/json'
],
'body' => "{
'messages': { 'msg': [{
'allowedChannels': ['SMS'],
'from': 'UKB',
'to': [
{ 'number': '{$phoneContact->getPhoneNumber()}' }
],
'body': {
'type': 'auto',
'content': '$message'
},
'minimumNumberOfMessageParts': 1,
'maximumNumberOfMessageParts': 8,
'reference': 'UKB'
}] }}"
]);
// 4. Check the API response status
if ($response->getStatusCode() === 200) {
// 5. If successful, update the row in the database
$phoneContact->setContacted(true);
$phoneContact->setGatewayResponse(trim($response->getStatusCode() . ' ' . $response->getContent()));
$phoneContact->setContactedAt(new DateTimeImmutable());
$this->entityManager->persist($phoneContact);
$io->note(sprintf('Successfully contacted number %s', $phoneContact->getPhoneNumber()));
} else {
$io->warning(sprintf('API call for number %s failed with status code %s', $phoneContact->getPhoneNumber(), $response->getStatusCode()));
}
$countSent++;
} catch (Exception $e) {
$io->error(sprintf('An error occurred contacting the API for number %s: %s', $phoneContact->getPhoneNumber(), $e->getMessage()));
}
}
if ($this->status_number) {
$io->info('Sending status message...');
try {
$this->httpClient->request('POST', self::$apiEndpoint, [
'headers' => [
'X-CM-PRODUCTTOKEN' => $this->sms_gateway_api_key,
'Accept' => 'application/json',
'Content-Type' => 'application/json'
],
'body' => "{
'messages': { 'msg': [{
'allowedChannels': ['SMS'],
'from': 'UKB',
'to': [
{ 'number': '{$this->status_number}' }
],
'body': {
'type': 'auto',
'content': 'SMS-Versand-Update:\n\n Insg. {$countSent} versendet.\nTotal versucht: {$countTotal}.'
},
'minimumNumberOfMessageParts': 1,
'maximumNumberOfMessageParts': 8,
'reference': 'UKB'
}] }}"
]);
} catch (Exception $e) {
$io->error(sprintf('An error occurred contacting the API for number %s: %s', $this->status_number, $e->getMessage()));
}
}
// Finalize all database changes
$this->entityManager->flush();
$io->progressFinish();
$io->success('Contacting process complete!');
return Command::SUCCESS;
}
}