<?php
//----------------------------------------------------------------------
// src/Services/Communication/SmsTools.php
//----------------------------------------------------------------------
namespace App\Services\Communication;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use App\Entity\Access;
use App\Entity\SocietyGroup;
use App\Entity\Client\Client;
use App\Entity\Client\Individual;
use App\Entity\Communication\Sms\Sms;
use App\Entity\Communication\Sms\SmsStatus;
use App\Entity\Communication\Sms\SmsMonthlyCostSociety;
use App\Entity\Communication\Sms\SmsMonthlyCostSocietyGroup;
use App\Entity\Communication\Sms\SmsPhoneNumber;
use App\Entity\Communication\Sms\SmsPrice;
use App\Entity\Communication\SmsProviders\SmsMode;
use App\Entity\Communication\SmsProviders\SmsProvider;
use App\Entity\Communication\SmsProviders\SmsTwilio;
use App\Entity\Config\Config;
use App\Entity\Config\OptionConfig;
use App\Entity\HR\HumanResource;
use App\Entity\Mission\Mission;
use App\Entity\Planning\Task;
use App\Entity\Platform\Devis\Devis;
use App\Entity\Platform\Invoice\Invoice;
use App\Entity\Platform\Phone;
use App\Entity\Platform\Society;
use App\Services\Communication\SmsProviderTools;
use App\Services\LogTools;
use App\Services\Platform\KeywordTools;
use App\Services\Security\PasswordTools;
/**
* SmsTools
*
* Naming conventions :
* $smsProvider can be an object of type
* SmsProvider::SmsMode
* SmsProvider::SmsTwilio
* $sms is an object of type Sms::Sms
*/
class SmsTools
{
const COEFFICIENT_PRICE_RESPONSE = 10.00;
public function __construct(
$devRealm, $testRealm, $prodRealm,
ManagerRegistry $doctrine, LogTools $logTools, PasswordTools $passwordTools, RouterInterface $router, TranslatorInterface $translator,
KeywordTools $keywordTools, SmsProviderTools $smsProviderTools
)
{
$this->devRealm = $devRealm;
$this->testRealm = $testRealm;
$this->prodRealm = $prodRealm;
$this->em = $doctrine->getManager();
$this->logTools = $logTools;
$this->passwordTools = $passwordTools;
$this->router = $router;
$this->translator = $translator;
$this->keywordTools = $keywordTools;
$this->smsProviderTools = $smsProviderTools;
$this->debug = true;
}
/**
* Get the currently active SmsProvider
* Note : Only one SmsProvider should be active
*/
public function getActiveSmsProvider()
{
return $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
}
/**
* Calls SmsProviderTools :: craftSmsProvider to create and SmsProvider
* Calls SmsProviderTools :: sendSms to send the sms/smsProvider
*/
public function sendSms(Sms $sms)
{
$this->logTools->sms_debug($this->debug, "[SmsTools :: sendSms] Calling SmsProviderTools :: craftSmsProvider to create a SmsProvider (SmsMode or SmsTwilio object) for the given Sms");
$smsProvider = $this->smsProviderTools->craftSmsProvider($sms);
$this->logTools->sms_debug($this->debug, "[SmsTools :: sendSms] Calling SmsProviderTools :: sendSms");
return $this->smsProviderTools->sendSms($smsProvider);
}
/**
* Plan.io Task #4515
* Init sms for Form
* Recipient is not set here but in SmsTools :: handleSmsPostFormSubmit
*/
public function initSmsForClient(Client $client, Access $access, SocietyGroup $societyGroup, $mission = null)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Only for individuals for now
$individual = $client->getIndividual();
if ($individual === null)
{
$msg = "Individual is null for client ".$client->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$emitterNumber = $this->getPhoneNumberForSocietyGroup($societyGroup);
if (empty($emitterNumber))
{
// Errors have been logged in SmsTools::getPhoneNumberForSocietyGroup
return null;
}
$status = $this->smsProviderTools->getDefaultSmsStatus();
if ($status === null)
{
// Error has been logged in SmsProviderTools::getDefaultSmsStatus
return null;
}
$sms = new Sms();
$sms->setProvider($activeSmsProvider);
$sms->setClient($client);
$sms->setAuthor($access);
$sms->setEmitter($emitterNumber);
$sms->setStatus($status);
$sms->setSocietyGroup($societyGroup);
// Plan.io Task #4313 - Allow 'shared client' SMS
$societySms = $individual->getSociety();
if ($mission !== null)
{
$sms->setMission($mission);
if ($mission->isSharedWithSocietyGroup($societyGroup))
{
$societySms = $mission->getSocietyOwner();
}
}
$sms->setSociety($societySms);
// CraftClient response code if needed
$this->craftClientResponseCode($sms);
$this->logTools->sms_debug($this->debug, "[SmsTools :: initSmsForClient] New Sms created with status ".$status->getValue());
return $sms;
}
/**
* Plan.io Task #4515
* Will sync SMS : Recipient, Reply url
* Redirect to Config phone if not prod realm
*/
public function handleSmsPostFormSubmit(Sms $sms)
{
$client = $sms->getClient();
if ($client === null)
{
// Exit
$errorMessage = "[SmsTools :: handleSmsPostFormSubmit] No client in SMS object";
$this->logTools->smsLogDebug($errorMessage, $sms->getProvider());
return null;
}
$phoneObjectToAttribute = $sms->getPhoneTmp();
if ($phoneObjectToAttribute === null)
{
// Exit
$errorMessage = "[SmsTools :: handleSmsPostFormSubmit] No Phone selected by the User in SMS form";
$this->logTools->smsLogDebug($errorMessage, $sms->getProvider());
return null;
}
$this->logTools->sms_debug($this->debug, "[SmsTools :: handleSmsPostFormSubmit] Phone selected by the User : " . $phoneObjectToAttribute->getNumberFormatted());
// Determine the good recipient
if ($this->prodRealm) $sms->setRecipient($phoneObjectToAttribute->getNumberFormatted());
else $sms->setRecipient($this->getPhoneToRedirect());
if (empty($sms->getRecipient()))
{
// Exit
$errorMessage = "[SmsTools :: handleSmsPostFormSubmit] No valid phone";
$this->logTools->smsLogDebug($errorMessage, $sms->getProvider());
return null;
}
// Update body
if ($sms->getIncludeReplyCode())
{
$sms->setBody($sms->getBody().$sms->getCodeInfo());
}
$this->em->persist($sms);
$this->logTools->sms_debug($this->debug, "[SmsTools :: handleSmsPostFormSubmit] Sms with recipient ".$sms->getRecipient());
return $sms;
}
/**
* Create a Sms object for Task reminder
*
* @usedBy Command::Cron ::SendSmsReminderTaskCommand
*/
public function createSmsClientReminderTask(Client $client, Access $access, SocietyGroup $societyGroup, $mission = null)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Only for individuals for now
$individual = $client->getIndividual();
if ($individual === null)
{
$msg = "Individual is null for client ".$client->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// Determine the good recipient
if ($this->prodRealm) $phone = $this->phoneFormat($client->getPhone());
else $phone = $this->getPhoneToRedirect();
if (empty($phone))
{
$errorMessage = "[SmsTools :: createSmsClientReminderTask] No valid phone";
$this->logTools->smsLogDebug($errorMessage, $activeSmsProvider);
return null;
}
$emitterNumber = $this->getPhoneNumberForSocietyGroup($societyGroup);
if (empty($emitterNumber))
{
// Errors have been logged in SmsTools::getPhoneNumberForSocietyGroup
return null;
}
$status = $this->smsProviderTools->getDefaultSmsStatus();
if ($status === null)
{
// Error has been logged in SmsProviderTools::getDefaultSmsStatus
return null;
}
$sms = new Sms();
$sms->setProvider($activeSmsProvider);
$sms->setClient($client);
$sms->setAuthor($access);
$sms->setEmitter($emitterNumber);
$sms->setRecipient($phone);
$sms->setStatus($status);
$sms->setSocietyGroup($societyGroup);
// Plan.io Task #4313 - Allow 'shared client' SMS
$societySms = $individual->getSociety();
if ($mission !== null)
{
$sms->setMission($mission);
if ($mission->isSharedWithSocietyGroup($societyGroup))
{
$societySms = $mission->getSocietyOwner();
}
}
$sms->setSociety($societySms);
$this->em->persist($sms);
$this->logTools->sms_debug($this->debug, "[SmsTools :: createSmsForClientReminder] New Sms created with status ".$status->getValue());
return $sms;
}
/**
* Creates a Sms object for Human resource
*/
public function createSmsForHumanResource(HumanResource $humanResource, Access $access, SocietyGroup $societyGroup)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
// Determine the good recipient
if ($this->prodRealm) $phone = $this->phoneFormat($humanResource->getPhone());
else $phone = $this->getPhoneToRedirect();
if (empty($phone))
{
$errorMessage = "[SmsTools :: createSmsForHumanResource] No valid phone";
$this->logTools->smsLogDebug($errorMessage, $activeSmsProvider);
return null;
}
$emitterNumber = $this->getPhoneNumberForSocietyGroup($societyGroup);
if (empty($emitterNumber))
{
// Errors have been logged in SmsTools::getPhoneNumberForSocietyGroup
return null;
}
$status = $this->smsProviderTools->getDefaultSmsStatus();
if ($status === null)
{
// Error has been logged in SmsProviderTools::getDefaultSmsStatus
return null;
}
$sms = new Sms();
$sms->setProvider($activeSmsProvider);
$sms->setHumanResource($humanResource);
$sms->setAuthor($access);
$sms->setEmitter($emitterNumber);
$sms->setRecipient($phone);
$sms->setStatus($status);
$sms->setSociety($humanResource->getSociety());
$sms->setSocietyGroup($societyGroup);
$this->em->persist($sms);
$this->logTools->sms_debug($this->debug, "[SmsTools :: createSmsForHumanResource] New Sms created with status ".$status->getValue());
return $sms;
}
/**
* Prices are decreasing, total amount of Sms (for a SocietyGroup is considered)
* Count the current number of actual sms that have been sent for the given Sms object
* Computes the total price of the given Sms
* Saves to the Sms object
*/
public function handlePrice(Sms $sms, bool $isResponse = false)
{
if ($sms->getPrice() !== null)
{
return false;
}
$society = $sms->getSociety();
if ($society === null)
{
return false;
}
$societyGroup = $society->getGroup();
if ($societyGroup === null)
{
return false;
}
$totalSegments = 0;
$price = 0.00;
// Get number of segments for the given sms
$smsSegmentNumber = $sms->getNumberSegment() != null ? $sms->getNumberSegment() : 1;
// Get all price ranges
$stepPrices = $this->em
->getRepository(SmsPrice::class)
->findBy(
array(),
array('floorLimit'=>'asc')
);
// Get the total number of sms (segments) for the given SocietyGroup
// No time limit
$totalSegments = $this->em->getRepository(Sms::class)->getTotalSmsSegments($societyGroup);
if ($isResponse)
{
// Callback for SMS received => The Sms object has not been written to the DataBase
// So the $totalSegments does not contains the $smsSegmentNumber
}
else
{
// Callback for SMS sent => The Sms object already exists in the DataBase
// So the $totalSegments contains the $smsSegmentNumber
$totalSegments = $totalSegments - $smsSegmentNumber;
}
// Add cost for the current sms
// Take into account the fact that for a single sms with multiple segments
// we can change price range
for ($iSeg = 0; $iSeg < $smsSegmentNumber; $iSeg++)
{
$totalSegments ++;
$priceStep = $this->computePriceStep($stepPrices, $totalSegments);
$price = $price + $priceStep;
}
// Handle price when it's a SMS Response
if ($isResponse)
{
$price = $price / self::COEFFICIENT_PRICE_RESPONSE;
}
$sms->setPrice($price);
// Montly cost call
$this->monthlyCostUpdateSociety($price, $society, $societyGroup);
$this->monthlyCostUpdateSocietyGroup($price, $societyGroup);
return true;
}
/**
* Computes the total price for the given number of segments
* taking into account the step prices
*/
public function computePriceStep($stepPrices, $nbSegments)
{
$counter = 0;
$previousStepIndex = 0;
$price = 0;
foreach ($stepPrices as $s)
{
if ($nbSegments >= $s->getFloorLimit())
{
if ($nbSegments <= $s->getCeilLimit())
{
$price = $s->getPrice();
}
else
{
$previousStepIndex = $counter;
}
}
$counter++;
}
// Cover eventual error in the price table
if ($price === 0)
{
if (array_key_exists($previousStepIndex+1, $stepPrices))
{
$price = $stepPrices[$previousStepIndex+1]->getPrice();
}
else
{
// Task plan.io #3066
if (array_key_exists($previousStepIndex, $stepPrices))
{
$price = $stepPrices[$previousStepIndex]->getPrice();
}
else
{
// Should not happen but here $price = 0;
// Security
$price = 0;
}
}
}
return $price;
}
/**
* Plan.io Task #4515
* Return Config::DEFAULT_PHONE_NUMBER::value if not prod realm
*/
public function getPhoneToRedirect()
{
$this->logTools->sms_debug($this->debug, "[SmsTools::getPhoneToRedirect] try to fetch phone redirect");
if ($this->prodRealm)
{
return null;
}
$configRepository = $this->em->getRepository(Config::class);
$configPhone = $configRepository->findOneByName(Config::DEFAULT_PHONE_NUMBER);
if ($configPhone === null)
{
$msg = "Config::DEFAULT_PHONE_NUMBER is null";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg);
return null;
}
$this->logTools->sms_debug($this->debug, "[SmsTools::getPhoneToRedirect] Get phone redirect from Config : " . $configPhone->getValue());
return $configPhone->getValue();
}
/**
* getPhoneNumberForSocietyGroup
*
* Gets the Phone Number for the SocietyGroup
* depending on the Platform
*/
public function getPhoneNumberForSocietyGroup(SocietyGroup $societyGroup)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
$smsPhone = $this->em
->getRepository(SmsPhoneNumber::class)
->findOneBySocietyGroup($societyGroup);
if ($smsPhone === null)
{
// Twilio : We need a phone number
if ($activeSmsProvider->isSmsTwilio())
{
$msg = "SmsPhoneNumber is null for societyGroup ".$societyGroup->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// SmsMode : We don't need a phone number, just a short code
if ($activeSmsProvider->isSmsMode())
{
$emitterNumber = SmsMode::DEFAULT_SHORTCODE;
return $emitterNumber;
}
}
// If we are here it means a SmsPhoneNumber has been found for this SocietyGroup
// SmsMode : We don't need a phone number, just a short code
if ($activeSmsProvider->isSmsMode())
{
$emitterNumber = $this->smsProviderTools->getSmsModeSenderDisplay($societyGroup);
return $emitterNumber;
}
// Twilio : We need an actual phone number
if ($activeSmsProvider->isSmsTwilio())
{
if ($this->devRealm)
{
$number = $smsPhone->getNumberDev();
}
else if ($this->testRealm)
{
$number = $smsPhone->getNumberTest();
}
else if ($this->prodRealm)
{
$number = $smsPhone->getNumber();
}
if (!isset($number) || empty($number))
{
$msg = "SmsPhoneNumber has no number for societyGroup ".$societyGroup->displayForLog();
if ($this->devRealm) $msg .= " [dev.realm]";
if ($this->testRealm) $msg .= " [test.realm]";
if ($this->prodRealm) $msg .= " [prod.realm]";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
return $number;
}
// This code should not be reached
return null;
}
/**
* getSmsStatus
*
* Returns the corresponding SmsStatus
* for the status of the given SmsProvider (SmsTwilio|SmsMode)
*/
public function getSmsStatus($smsProvider)
{
$smsProviderStatus = $smsProvider->getStatus();
if ($smsProviderStatus === null)
{
return null;
}
$code = $smsProviderStatus->getCode();
$smsStatus = $this->em->getRepository(SmsStatus::class)->findOneByCode($code);
if ($smsStatus === null)
{
return null;
}
return $smsStatus;
}
/**
* Get total stats numberSms/price per Society
*/
public function getStatistics(SocietyGroup $societyGroup)
{
$statsPerSociety = $this->em->getRepository(Sms::class)->getSmsCountAndTotalAmountBySociety($societyGroup);
// Add societies that are not in the stats
$societies = $societyGroup->getSocieties();
foreach($societies as $society)
{
$found = false;
foreach($statsPerSociety as $societyStats)
{
if ($society->getId() === $societyStats["societyId"])
{
$found = true;
break;
}
}
if (!$found)
{
$statsPerSociety[] = [
"societyId" => $society->getId(),
"societyName" => $society->getName(),
"numberSms" => 0,
"totalPrice" => 0,
];
}
}
// Sort by society name
usort($statsPerSociety, function($a, $b) {
return $a["societyName"] <=> $b["societyName"];
});
return $statsPerSociety;
}
public function getStatisticsForEnvironment(SocietyGroup $societyGroup): array
{
// Raw stats: per society + per month
$societyStats = $this->em->getRepository(Sms::class)->getSmsCountByMonthAndSociety($societyGroup);
// “Period format: Y-m — must match with the one in SmsRepository::getSmsCountByMonthAndSociety
// Keep only current-month rows
$currentPeriod = (new \DateTime())->format('Y-m');
$currentMonthStats = array_values(array_filter(
$societyStats,
static function (array $row) use ($currentPeriod): bool {
return $row['period'] === $currentPeriod;
}
));
// Total for the whole group for the current month
$totalSmsCurrentMonth = array_sum(array_column($currentMonthStats, 'numberSms'));
$totalSms = array_sum(array_column($societyStats, 'numberSms'));
// Get quota per month
$quotaPerMonthOptionConfig = $this->em->getRepository(OptionConfig::class)->findOneBy(array(
'societyGroup' => $societyGroup,
'code' => OptionConfig::SMS_QUOTA_PER_MONTH_CODE,
));
$quotaPerMonth = 0;
if ($quotaPerMonthOptionConfig !== null)
{
$quotaPerMonth = $quotaPerMonthOptionConfig->getValue();
}
return [
'societyStats' => $societyStats,
'currentMonthSocietyStats' => $currentMonthStats,
'currentMonthTotalSms' => $totalSmsCurrentMonth,
'globalTotalSms' => $totalSms,
'quotaPerMonth' => $quotaPerMonth,
];
}
/**
* Creates a unique reply-to code
* Stores it to the Sms object
* Updates the body of the Sms
* Note : Sms->body should be set
*/
public function craftClientResponseCode(Sms $sms)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
$backTrace = debug_backtrace()[1];
$method = $backTrace['function'];
$class = $backTrace['class'];
$trace = $class."::".$method;
$trace = str_replace("\\", "::", $trace);
if ($sms->getProvider() === null || !$sms->getProvider()->isSmsMode())
{
// Only SMSMode for now
// return false;
}
// Craft response code
$code = $this->passwordTools->generateSmsClientResponseCode();
// Craft reply-to URL
$configRepository = $this->em->getRepository(Config::class);
$urlConfig = $configRepository->findOneByName(Config::URL);
if ($urlConfig === null)
{
$msg = "Config::URL not found";
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return false;
}
$urlConfig = $urlConfig->getValue();
$replyToUrl = $urlConfig . $this->router->generate('sms_client_response', array('code' => $code));
// $url = "<a href='".$replyToUrl."'>$replyToUrl</a>";
// This seems to be enough
$url = $replyToUrl;
// Get reply text info
$info = $this->translator->trans('sms_mode_reply_link_info');
// Put them all together
$info = "\n" . $info . " " . $url;
// Save them to the Sms
$sms->setClientResponseCode($code);
$sms->setCodeInfo($info);
$sms->setIncludeReplyCode(true);
$this->logTools->sms_debug($this->debug, "[SmsTools :: craftClientResponseCode] code = ".$code);
$this->logTools->sms_debug($this->debug, "[SmsTools :: craftClientResponseCode] info = ".$info);
return true;
}
/**
* Test if a Phone Number is compliant for sms (Twilio/SmsMode)
*/
public function phoneFormat($phone)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
if (empty($phone))
{
$msg = "PhoneNumber is empty";
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// Delete unwanted characters (. - /) and all space characters
$phone = preg_replace('/\s+/', '', $phone);
$phone = str_replace('.', '', $phone);
$phone = str_replace('-', '', $phone);
$phone = str_replace('/', '', $phone);
// Replaces the national format with the international format
$nationalFormat = preg_match('/^(06|07)/', $phone);
if ($nationalFormat === 1)
{
$phone = preg_replace('/^(0)/', '+33', $phone);
// Check the size is equals to 12 --> +33 6 66 66 66 66
if (strlen($phone) !== 12)
{
$msg = "PhoneNumber has more or less than 12 char : ".$phone;
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
}
// Plan.io Task #3785
// Harmonisation of France's international dialling code to the same format
$checkDiallingCode = preg_match('/^00/', $phone);
if ($checkDiallingCode === 1)
{
$phone = preg_replace('/^00/', '+', $phone);
// Check the size is equals to 12 --> +33 6 66 66 66 66
if (strlen($phone) !== 12)
{
$msg = "PhoneNumber has more or less than 12 char : ".$phone;
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
}
// Plan.io Task #3744
// Check that the number includes the international dialling code for France
// Check if it is a mobile number
$frenchMobilePhone = substr($phone, 0, 4);
if (($frenchMobilePhone != "+336" && $frenchMobilePhone != "+337"))
{
$msg = "PhoneNumber starts with other than +336 or +337 : ".$phone;
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
// Plan.io Task #3785
// Check if the number starts with +33 and contains only 9 digits
$checkAllGood = preg_match('/^\+33\d{9}$/', $phone);
if (!$checkAllGood)
{
$msg = "PhoneNumber does not start with +33 or doen not have only digits : ".$phone;
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
return $phone;
}
/**
* Plan.io Task #4515
* Get all phones available for an Individual
* Phone::numberFormatted will be set
*/
public function getIndividualPhonesForSms(Individual $individual)
{
$phonesForSms = [];
$phones = $this->em->getRepository(Phone::class)->findBy(array('individual' => $individual));
$mainPhone = $individual->getPhone();
foreach ($phones as $phone)
{
$numberFormatted = $this->phoneFormat($phone->getNumber());
if ($numberFormatted === null)
{
continue;
}
$phone->setNumberFormatted($numberFormatted);
$phonesForSms[] = $phone;
}
// Sort and place main at first
usort($phonesForSms, function($phoneA, $phoneB) use ($mainPhone) {
if ($phoneA->getNumber() === $mainPhone) return -1;
if ($phoneB->getNumber() === $mainPhone) return 1;
return 0;
});
return $phonesForSms;
}
public function monthlyCostUpdateSociety($price, $society, $societyGroup)
{
$date = new \DateTime();
$year = date_format($date,"Y");
$month = date_format($date,"m");
$monthPriceSociety = $this->em
->getRepository(SmsMonthlyCostSociety::class)
->getMonthPrice($year, $month, $society);
if (array_key_exists(0, $monthPriceSociety))
{
$monthCost = $monthPriceSociety[0];
$newPrice = $monthCost->getPrice() + $price;
$monthCost->setPrice($newPrice);
$this->em->persist($monthCost);
}
else if ($society !== null)
{
$monthCost = new SmsMonthlyCostSociety();
$monthCost->setPrice($price);
$monthCost->setYear($year);
$monthCost->setMonth($month);
$monthCost->setSociety($society);
$monthCost->setSocietyGroup($societyGroup);
$this->em->persist($monthCost);
}
}
public function monthlyCostUpdateSocietyGroup($price, $societyGroup)
{
$date = new \DateTime();
$year = date_format($date,"Y");
$month = date_format($date,"m");
$monthPriceSocietyGroup = $this->em
->getRepository(SmsMonthlyCostSocietyGroup::class)
->getMonthPrice($year,$month,$societyGroup);
if (array_key_exists(0, $monthPriceSocietyGroup))
{
$monthCost = $monthPriceSocietyGroup[0];
$newPrice = $monthCost->getPrice() + $price;
$monthCost->setPrice($newPrice);
$this->em->persist($monthCost);
}
else if ($societyGroup !== null)
{
$monthCost = new SmsMonthlyCostSocietyGroup();
$monthCost->setPrice($price);
$monthCost->setYear($year);
$monthCost->setMonth($month);
$monthCost->setSocietyGroup($societyGroup);
$this->em->persist($monthCost);
}
}
public function isValidClientData($object)
{
$activeSmsProvider = $this->em->getRepository(SmsProvider::class)->findOneBy(array(
'isActive' => 1,
));
if ($object instanceof Client)
{
$individual = $object->getIndividual();
if ($individual === null)
{
// Only individuals for now
$msg = "Individual is null for client ".$object->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
return array(
'client' => $object,
'individual' => $individual,
'mission' => null,
);
}
if ($object instanceof Mission)
{
$client = $object->getReceiver();
if ($client === null)
{
// This should not happen
$msg = "Receiver is null for mission ".$object->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$individual = $client->getIndividual();
if ($individual === null)
{
// Only individuals for now
$msg = "Individual is null for client ".$client->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
return array(
'client' => $client,
'individual' => $individual,
'mission' => $object,
);
}
if ($object instanceof Devis || $object instanceof Invoice || $object instanceof Task)
{
$client = $object->getReceiver();
if ($client === null)
{
// This should not happen
$msg = "Receiver is null for devis | invoice | task ".$object->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$mission = $object->getMission();
if ($mission === null)
{
// This should not happen
$msg = "Mission is null for devis | invoice | task ".$object->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
$individual = $client->getIndividual();
if ($individual === null)
{
// Only individuals for now
$msg = "Individual is null for client ".$client->displayForLog();
$this->logTools->errorlog($msg);
$this->logTools->smsLogDebug($msg, $activeSmsProvider);
return null;
}
return array(
'client' => $client,
'individual' => $individual,
'mission' => $mission,
);
}
// This code should not be reached
return null;
}
}