chore: initial import for test contour with k3s CI

This commit is contained in:
sova-bootstrap
2026-05-28 12:09:28 +03:00
commit d77d0a872f
423 changed files with 35401 additions and 0 deletions
+317
View File
@@ -0,0 +1,317 @@
<?php
namespace App\Bundle\Bitrix;
use Doctrine\DBAL\DriverManager;
use App\Bundle\Infoclinica\Region;
class Request
{
private $connect = null;
private $regionId = NULL;
public static $instance = NULL;
private function __construct() {}
public static function init($regionId = NULL)
{
if (self::$instance === null) {
self::$instance = new self();
self::$instance->connect = DriverManager::getConnection([
'url' => $_ENV['DATABASE_BITRIX_URL']
]);
self::$instance->connect->executeQuery("SET NAMES utf8");
if ($regionId == NULL) {
self::$instance->regionId = Region::getId();
} else {
self::$instance->regionId = $regionId;
}
}
return self::$instance;
}
public function setRegionId($id)
{
$this->regionId = $id;
return $this;
}
public function getPropPriceId($param = 'value')
{
$props = [
'91' => [
'value' => 2980,
'name' => 'Саратов'
],
'comfort' => [
'value' => 2980,
'name' => 'Саратов Comfort'
],
'93' => [
'value' => 2985,
'name' => 'Воронеж'
],
'92' => [
'value' => 2990,
'name' => 'Волгоград'
],
'94' => [
'value' => 4477,
'name' => 'Краснодар'
],
];
return $props[$this->regionId][$param];
}
public function getBlockId($param = 'value')
{
$iblock_ids = [
'sovenok' => [
'value' => 174,
'uslugi' => 175,
'name' => 'Саратов Совенок'
],
'comfort' => [
'value' => 145,
'uslugi' => 146,
'name' => 'Саратов Comfort'
],
'91' => [
'value' => 91,
'uslugi' => 165,
'name' => 'Саратов'
],
'92' => [
'value' => 92,
'uslugi' => 167,
'name' => 'Волгоград'
],
'93' => [
'value' => 93,
'uslugi' => 166,
'name' => 'Воронеж'
],
'94' => [
'value' => 219,
'uslugi' => 229,
'name' => 'Краснодар'
],
];
return $iblock_ids[$this->regionId][$param];
}
public function getDoctors($isActive = false)
{
$specialist = $this->connect->createQueryBuilder()
->select('*')
->from('`b_iblock_element`', 'el')
->where('el.IBLOCK_ID = :IBLOCK_ID')
->andWhere('el.WF_PARENT_ELEMENT_ID IS NULL')
->andWhere('el.PREVIEW_PICTURE IS NOT NULL')
->setParameter('IBLOCK_ID', $this->getBlockId());
if ($isActive) {
$specialist
->andWhere('el.ACTIVE = :ACTIVE')
->setParameter('ACTIVE', 'Y');
}
$specialist = $specialist
->execute()
->fetchAll()
;
return $specialist;
}
public function getSpecialist($sid, $infoclinica = false)
{
$specialist = $this->connect->createQueryBuilder()
->select('*')
->from('`b_iblock_element`', 'el');
if ($infoclinica) {
$specialist
->where('el.XML_ID = :XML_ID')
->setParameter('XML_ID', $sid);
} else {
$specialist
->where('el.ID = :ID')
->setParameter('ID', $sid);
}
$specialist = $specialist
->execute()
->fetch()
;
if ($specialist) {
$specialist['NAME'] = explode(' ', trim($specialist['NAME']));
}
return $specialist;
}
// SELECT biep.IBLOCK_ELEMENT_ID as DOCTOR_ID FROM b_iblock_element_property biep LEFT JOIN b_iblock_property bip ON biep.IBLOCK_PROPERTY_ID = bip.ID WHERE biep.VALUE = $doctorId AND bip.CODE REGEXP 'MEDIC' AND bip.ACTIVE = 'Y'
// SELECT biep.VALUE, bip.NAME, bip.CODE FROM b_iblock_element bie INNER JOIN b_iblock_element_property biep ON biep.IBLOCK_ELEMENT_ID = bie.ID LEFT JOIN b_iblock_property bip ON biep.IBLOCK_PROPERTY_ID = bip.ID WHERE bie.ID = $itemID;
public function getReviews($doctorId, $infoclinica)
{
$specialist = $this->getSpecialist($doctorId, $infoclinica);
if (! $specialist) {
return [];
}
$items = $this->connect->createQueryBuilder()
->select('biep.IBLOCK_ELEMENT_ID as REVIEW_ID')
->from('b_iblock_element_property', 'biep')
->leftJoin('biep', 'b_iblock_property', 'bip', 'biep.IBLOCK_PROPERTY_ID = bip.ID')
->where('biep.VALUE = :VALUE')
->andWhere('bip.CODE REGEXP :CODE')
->setParameter('VALUE', $specialist['ID'])
->setParameter('CODE', 'MEDIC')
->execute()
->fetchAll()
;
foreach ($this->docPropsCode($specialist['ID'], 'LINK_REVIEWS') as $item) {
$items[]['REVIEW_ID'] = $item['VALUE'];
}
if (! empty($items)) {
foreach ($items as $key => $item) {
$items[$key]['DATA'] = $this->docPropsCode($item['REVIEW_ID']);
foreach ($items[$key]['DATA'] as $i => $props) {
if ($props['CODE'] == 'MESSAGE') {
$data = preg_replace_callback('!s:(\d+):"(.*?)";!s', function($m) {
$len = strlen($m[2]);
$result = "s:$len:\"{$m[2]}\";";
return $result;
}, $props['VALUE']);
if (@unserialize($data) !== false) {
$items[$key]['DATA'][$i]['VALUE'] = unserialize($data)['TEXT'];
}
}
}
}
}
return $items;
}
// select biep.ID, bie.ACTIVE, bie.IBLOCK_SECTION_ID, bie.DATE_CREATE, biep.VALUE, bip.NAME, bip.CODE
// from b_iblock_element bie
// inner join b_iblock_element_property biep on biep.IBLOCK_ELEMENT_ID = bie.ID
// left join b_iblock_property bip on biep.IBLOCK_PROPERTY_ID = bip.ID
// where bie.ID = :ID
public function docPropsCode($elementId, $code = NULL, $all = true)
{
$qb = $this->connect->createQueryBuilder()
->select('bie.NAME as BIE_NAME, biep.ID, bie.ACTIVE, bie.IBLOCK_SECTION_ID, bie.DATE_CREATE, biep.VALUE, bip.NAME, bip.CODE')
->from('b_iblock_element', 'bie')
->innerJoin('bie', 'b_iblock_element_property', 'biep', 'biep.IBLOCK_ELEMENT_ID = bie.ID')
->leftJoin('biep', 'b_iblock_property', 'bip', 'biep.IBLOCK_PROPERTY_ID = bip.ID')
->where('bie.ID = :ID')
->setParameter('ID', $elementId);
if ($code) {
$qb->andWhere('bip.CODE = :CODE')
->setParameter('CODE', $code);
}
if ($all) {
return $qb->execute()->fetchAll();
}
return $qb->execute()->fetch();
}
public function getImage($id)
{
$data = $this->connect->createQueryBuilder()
->select('*')
->from('b_file', 'f')
->where('f.ID = :ID')
->setParameter('ID', $id)
->execute()
->fetch()
;
if (empty($data['FILE_NAME'])) {
$response = '/images/no_img.png';
} else {
$response = 'https://sovamed.ru/upload/'. $data['SUBDIR'];
$response .= '/'. $data['FILE_NAME'];
}
return $response;
}
// SELECT * FROM `b_iblock_section` WHERE ACTIVE = 'Y' AND IBLOCK_SECTION_ID IS NULL AND (IBLOCK_ID = 165 OR IBLOCK_ID = 166 OR IBLOCK_ID = 167);
public function getFilials()
{
return $this->connect->createQueryBuilder()
->select('ID, NAME, IBLOCK_ID, IBLOCK_SECTION_ID, ACTIVE')
->from('`b_iblock_section`', 'el')
->where('el.ACTIVE = :ACTIVE')
->andWhere('el.IBLOCK_ID = :IBLOCK_ID')
->andWhere('el.IBLOCK_SECTION_ID IS NULL')
->setParameter('ACTIVE', 'Y')
->setParameter('IBLOCK_ID', $this->getBlockId('uslugi'))
->execute()
->fetchAll()
;
}
public function getDepartments($sectionId)
{
try {
return $this->connect->createQueryBuilder()
->select('ID, NAME, IBLOCK_ID, IBLOCK_SECTION_ID, ACTIVE')
->from('`b_iblock_section`', 'el')
->where('el.ACTIVE = :ACTIVE')
->andWhere('el.IBLOCK_ID = :IBLOCK_ID')
->andWhere('el.IBLOCK_SECTION_ID = :IBLOCK_SECTION_ID')
->setParameter('ACTIVE', 'Y')
->setParameter('IBLOCK_SECTION_ID', $sectionId)
->setParameter('IBLOCK_ID', $this->getBlockId('uslugi'))
->execute()
->fetchAll()
;
} catch (Exception $e) {
return false;
}
}
public function getServices($sectionId)
{
return $this->connect->createQueryBuilder()
->select('el.ID, el.NAME, el.IBLOCK_ID, el.IBLOCK_SECTION_ID, el.ACTIVE, prop.VALUE')
->from('`b_iblock_element`', 'el')
->leftJoin('el', 'b_iblock_element_property', 'prop',
'prop.IBLOCK_ELEMENT_ID = el.ID AND prop.IBLOCK_PROPERTY_ID = IBLOCK_PROPERTY_ID'
)
->where('el.ACTIVE = :ACTIVE')
->andWhere('el.IBLOCK_ID = :IBLOCK_ID')
->andWhere('el.IBLOCK_SECTION_ID = :IBLOCK_SECTION_ID')
->setParameter('ACTIVE', 'Y')
->setParameter('IBLOCK_SECTION_ID', $sectionId)
->setParameter('IBLOCK_PROPERTY_ID', $this->getPropPriceId())
->setParameter('IBLOCK_ID', $this->getBlockId('uslugi'))
->execute()
->fetchAll()
;
}
}
+188
View File
@@ -0,0 +1,188 @@
<?php
namespace App\Bundle\Calltouch;
use App\Bundle\Infoclinica\Region;
use App\Bundle\Infoclinica\Client;
class Request
{
private $client;
private $clientApiId;
public function __construct()
{
$this->client = Client::init('https://api.calltouch.ru/');
$this->changeRegion(Region::getId());
}
public function changeRegion($regionId)
{
switch ($regionId) {
case '92':
$this->clientApiId = 'iaCkzrxUYemoqAactN83KsOUPP6IU4QO89Q9XQHwjKZsw';
$this->clientSiteId = '17285';
$this->client
->setHeader('Access-Token', $this->clientApiId)
->setHeader('SiteId', $this->clientSiteId);
return $this;
// Волгоград
// volgograd.sovamed.ru
// site_id - 17285
// mod_id - 886a1412
// ID личного кабинета 17285
// Токен iaCkzrxUYemoqAactN83KsOUPP6IU4QO89Q9XQHwjKZsw
// ID счетчика (mod_id) 886a1412
break;
case '93':
$this->clientApiId = 'mNgA1yKdoJD2ZESfX2v4gFB/6mrgGnIOsbs7ICR7cuXC6';
$this->clientSiteId = '16650';
$this->client
->setHeader('Access-Token', $this->clientApiId)
->setHeader('SiteId', $this->clientSiteId);
return $this;
// Воронеж
// voronezh.sovamed.ru:
// site_id - 16650
// mod_id - ce64c813
// ID личного кабинета 16650
// Токен mNgA1yKdoJD2ZESfX2v4gFB/6mrgGnIOsbs7ICR7cuXC6
// ID счетчика (mod_id) ce64c813
break;
case '94':
$this->clientApiId = 'WAh7BnATs/6KBcsblRiUijb.U0lmiUX.b6yL7TR7GSVps';
$this->clientSiteId = '41767';
$this->client
->setHeader('Access-Token', $this->clientApiId)
->setHeader('SiteId', $this->clientSiteId);
return $this;
// Краснодар
// wmtmed.ru
// site_id - 41767
// mod_id - yde3clnb
// ID личного кабинета 41767
// Токен WAh7BnATs/6KBcsblRiUijb.U0lmiUX.b6yL7TR7GSVps
// ID счетчика (mod_id) yde3clnb
break;
case '95':
$this->clientApiId = 'yJbKffJdPo0nt0aG5GdrEeZB8g90XWAOjbnB9PZ8qUHBq';
$this->clientSiteId = '52294';
$this->client
->setHeader('Access-Token', $this->clientApiId)
->setHeader('SiteId', $this->clientSiteId);
return $this;
// Саратов
// sovenok.sovamed.ru
// site_id - 52294
// mod_id - e9bu10ds
// ID личного кабинета 52294
// Токен yJbKffJdPo0nt0aG5GdrEeZB8g90XWAOjbnB9PZ8qUHBq
// ID счетчика (mod_id) e9bu10ds
break;
case '96':
$this->clientApiId = 'ekz0aK2iVJHNpbupQmWUYiIGZi9Be9ReHpBAXktxeuRPm';
$this->clientSiteId = '43907';
$this->client
->setHeader('Access-Token', $this->clientApiId)
->setHeader('SiteId', $this->clientSiteId);
return $this;
// Комфорт
// comfort.sovamed.ru
// ID личного кабинета (site_id)
// 43907
// ID счетчика (mod_id)
// 4p0md55a
// API токен (access_token)
// ekz0aK2iVJHNpbupQmWUYiIGZi9Be9ReHpBAXktxeuRPm
break;
default:
$this->clientApiId = 'eMpN4lhkNVQ/js63VpbUh/fIjcCxooEuGh2pOYictz5ZO';
$this->clientSiteId = '16205';
$this->client
->setHeader('Access-Token', $this->clientApiId)
->setHeader('SiteId', $this->clientSiteId);
return $this;
// Саратов
// sovamed.ru:
// site_id - 16205
// mod_id - 95271cfe
// ID личного кабинета 16205
// Токен eMpN4lhkNVQ/js63VpbUh/fIjcCxooEuGh2pOYictz5ZO
// ID счетчика (mod_id) 95271cfe
break;
}
}
public function create($requests)
{
$data = $this->client->setBodyParams(['requests' => [$requests]])
->setPath('/lead-service/v1/api/request/create')
->exec()
->dataResponse;
return $data;
}
public function selectcCalls($params = [])
{
$path = '/calls-service/RestAPI/'. $this->clientSiteId .'/calls-diary/calls';
$path .= '?clientApiId=' . $this->clientApiId;
$path .= '&dateFrom=' . $params['dateFrom'];
$path .= '&dateTo=' . $params['dateTo'];
$path .= '&withCallTags=true';
if (isset($params['withMapVisits'])) {
$path .= '&withMapVisits=' . $params['withMapVisits'];
}
if (isset($params['withYandexDirect'])) {
$path .= '&withYandexDirect=' . $params['withYandexDirect'];
}
$path .= '&page=1&limit=500';
$data = $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
return $data;
}
public function selectRequests($params = [])
{
$path = '/calls-service/RestAPI/requests/';
$path .= '?clientApiId=' . $this->clientApiId;
$path .= '&dateFrom=' . $params['dateFrom'];
$path .= '&dateTo=' . $params['dateTo'];
if (isset($params['withMapVisits'])) {
$path .= '&withMapVisits=' . $params['withMapVisits'];
}
if (isset($params['withYandexDirect'])) {
$path .= '&withYandexDirect=' . $params['withYandexDirect'];
}
$data = $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
return $data;
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Bundle\Crypt;
class AES
{
private static $cipher = 'aes-128-cbc';
private static $cryptKey = 'Yahve89';
public static function encrypt($plaintext)
{
$ivlen = openssl_cipher_iv_length(self::$cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext_raw = openssl_encrypt(
$plaintext, self::$cipher, self::$cryptKey, $options = OPENSSL_RAW_DATA, $iv);
$hmac = hash_hmac('sha256', $ciphertext_raw, self::$cryptKey, $as_binary = true);
$ciphertext = base64_encode( $iv.$hmac.$ciphertext_raw );
return $ciphertext;
}
public static function decrypt($ciphertext)
{
$c = base64_decode($ciphertext);
$ivlen = openssl_cipher_iv_length(self::$cipher);
$iv = substr($c, 0, $ivlen);
$hmac = substr($c, $ivlen, $sha2len=32);
$ciphertext_raw = substr($c, $ivlen+$sha2len);
$plainText = openssl_decrypt(
$ciphertext_raw, self::$cipher, self::$cryptKey, $options = OPENSSL_RAW_DATA, $iv);
$calcmac = hash_hmac('sha256', $ciphertext_raw, self::$cryptKey, $as_binary = true);
if (hash_equals($hmac, $calcmac))
return $plainText;
return NULL;
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace App\Bundle\Helper;
class AmountInWords
{
/**
* Возвращает сумму прописью
* @author runcore
* @uses $this->morph(...)
*/
public function num2str($num) {
$nul='ноль';
$ten=array(
array('','один','два','три','четыре','пять','шесть','семь', 'восемь','девять'),
array('','одна','две','три','четыре','пять','шесть','семь', 'восемь','девять'),
);
$a20=array('десять','одиннадцать','двенадцать','тринадцать','четырнадцать' ,'пятнадцать','шестнадцать','семнадцать','восемнадцать','девятнадцать');
$tens=array(2=>'двадцать','тридцать','сорок','пятьдесят','шестьдесят','семьдесят' ,'восемьдесят','девяносто');
$hundred=array('','сто','двести','триста','четыреста','пятьсот','шестьсот', 'семьсот','восемьсот','девятьсот');
$unit=array( // Units
array('копейка' ,'копейки' ,'копеек', 1),
array('рубль' ,'рубля' ,'рублей' ,0),
array('тысяча' ,'тысячи' ,'тысяч' ,1),
array('миллион' ,'миллиона','миллионов' ,0),
array('миллиард','милиарда','миллиардов',0),
);
//
list($rub,$kop) = explode('.',sprintf("%015.2f", floatval($num)));
$out = array();
if (intval($rub)>0) {
foreach(str_split($rub,3) as $uk=>$v) { // by 3 symbols
if (!intval($v)) continue;
$uk = sizeof($unit)-$uk-1; // unit key
$gender = $unit[$uk][3];
list($i1,$i2,$i3) = array_map('intval',str_split($v,1));
// mega-logic
$out[] = $hundred[$i1]; # 1xx-9xx
if ($i2>1) $out[]= $tens[$i2].' '.$ten[$gender][$i3]; # 20-99
else $out[]= $i2>0 ? $a20[$i3] : $ten[$gender][$i3]; # 10-19 | 1-9
// units without rub & kop
if ($uk>1) $out[]= $this->morph($v,$unit[$uk][0],$unit[$uk][1],$unit[$uk][2]);
} //foreach
}
else $out[] = $nul;
$out[] = $this->morph(intval($rub), $unit[1][0],$unit[1][1],$unit[1][2]); // rub
$out[] = $kop.' '.$this->morph($kop,$unit[0][0],$unit[0][1],$unit[0][2]); // kop
return trim(preg_replace('/ {2,}/', ' ', join(' ',$out)));
}
/**
* Склоняем словоформу
* @ author runcore
*/
private function morph($n, $f1, $f2, $f5) {
$n = abs(intval($n)) % 100;
if ($n>10 && $n<20) return $f5;
$n = $n % 10;
if ($n>1 && $n<5) return $f2;
if ($n==1) return $f1;
return $f5;
}
}
+1
View File
@@ -0,0 +1 @@
/*.pem
+188
View File
@@ -0,0 +1,188 @@
<?php
namespace App\Bundle\Infoclinica;
use GuzzleHttp\Client as gzClient;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Message\MessageFactoryInterface;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
/**
* @author Ivan Alexandrov <yahve1989@gmail.com>
*/
class Client
{
public static $instance = NULL;
private $cookieJar = NULL;
private $client = NULL;
private $baseUri = NULL;
private $path = NULL;
public $dataResponse = [];
private $method = 'GET';
public $params = [
'debug' => false,
'verify' => false,
'http_errors' => false,
'allow_redirects' => [
'max' => 10,
'strict' => true,
'referer' => true,
'track_redirects' => true,
],
];
/**
* @return type $instance
*/
public static function init($baseUri = 'https://widget.sovamed.ru')
{
if (self::$instance === null) {
self::$instance = new self();
self::$instance->setBaseUri($baseUri);
$request = SymfonyRequest::createFromGlobals();
/*$cookieJar = CookieJar::fromArray([
'WR_SESSION' => $request->cookies->get('WR_SESSION'),
'WR_DETAIL' => $request->cookies->get('WR_DETAIL'),
'PLAY_SESSION' => $request->cookies->get('PLAY_SESSION'),
], '.sovamed.ru');
*/
// self::$instance->params['cookies'] = $cookieJar;
self::$instance->client = new gzClient([
'cookies' => false,
'base_uri' => self::$instance->baseUri,
'timeout' => 60,
'headers' => [
'Origin' => self::$instance->baseUri,
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
'Accept-Language' => 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept' => 'application/json, text/javascript, */*; q=0.01',
'Content-Type' => 'application/json; charset=UTF-8',
'X-Requested-With' => 'XMLHttpRequest',
'X-Integration-Type' => 'WEBSDK'
]
]);
}
return self::$instance;
}
public function setAuth($username, $password)
{
$this->params['headers']['Authorization'] = 'Basic ' . base64_encode("$username:$password");
return $this;
}
public function setHeader($key, $value)
{
$this->params['headers'][$key] = $value;
return $this;
}
public function setBaseUri($url)
{
$this->baseUri = $url;
return $this;
}
/**
* @param type $params
*/
public function setParams($params)
{
$this->params = $params;
$this->method = 'POST';
return $this;
}
/**
* @param type $formParams
*/
public function setBodyParams($formParams)
{
$this->params['body'] = json_encode($formParams);
$this->method = 'POST';
return $this;
}
public function clearParams()
{
unset($this->params['form_params']);
unset($this->params['body']);
$this->method = 'GET';
return $this;
}
public function setMethod($method)
{
$this->method = $method;
return $this;
}
/**
* @return type
*/
public function setFormParams($params = [])
{
$this->params['form_params'] = $params;
$this->method = 'POST';
return $this;
}
/**
* @param type $path
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}
/**
* @return type string
*/
public function exec()
{
$response = $this->client->request($this->method, $this->path, $this->params);
// if (in_array($this->path, ['/registration', '/login'])) {
// if (!empty($cookie = $this->params['cookies']->getCookieByName('WR_SESSION')))
// $this->dataResponse['cookies']['WR_SESSION'] = $cookie->getValue();
// if (!empty($cookie = $this->params['cookies']->getCookieByName('WR_DETAIL')))
// $this->dataResponse['cookies']['WR_DETAIL'] = $cookie->getValue();
// if (!empty($cookie = $this->params['cookies']->getCookieByName('PLAY_SESSION')))
// $this->dataResponse['cookies']['PLAY_SESSION'] = $cookie->getValue();
// if (!empty($cookie = $this->params['cookies']->getCookieByName('PLAY_FLASH')))
// $this->dataResponse['cookies']['PLAY_FLASH'] = $cookie->getValue();
// }
$this->dataResponse['response'] = json_decode($response->getBody()->getContents(), true);
return $this;
}
public function raw($body = [])
{
$jar = new \GuzzleHttp\Cookie\CookieJar;
$response = $this->client->post($this->baseUri . $this->path, [
'cookies' => $jar,
'headers' => [
'User-Agent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0',
'Content-Type' => 'application/json',
'X-Requested-With' => 'XMLHttpRequest',
'X-Integration-Type' => 'WEBSDK'
],
'body' => json_encode($body)
]);
return $response->getBody()->getContents();
}
}
+97
View File
@@ -0,0 +1,97 @@
<?php
namespace App\Bundle\Infoclinica;
use Symfony\Component\HttpFoundation\Request;
class Region
{
public static function getCurrentName($id = false)
{
if ($id == false) {
$id = self::getId();
}
switch ($id) {
case 92:
return 'Волгоград';
break;
case 93:
return 'Воронеж';
break;
case 94:
return 'Краснодар';
break;
case 100:
return 'Комфорт';
break;
case 101:
return 'Совёнок';
break;
case 102:
return 'ОМС';
break;
default:
return 'Саратов';
break;
}
}
public static function getTimezone()
{
switch (self::getId()) {
case 92:
return 3;
break;
case 93:
return 3;
break;
case 94:
return 3;
break;
default:
return 4;
break;
}
}
public static function getId()
{
$request = Request::createFromGlobals();
if (preg_match('/sovamed\.ru/m', $request->getHost())) {
return $request->cookies->get('region');
}
return 94;
}
public static function getTemplite()
{
if (self::getId() == 94) {
return 'base_wmtmed';
}
return 'base';
}
}
+434
View File
@@ -0,0 +1,434 @@
<?php
namespace App\Bundle\Infoclinica;
class Rest
{
private $client;
public function __construct()
{
$this->client = Client::init();
}
public function getRecords()
{
$path = '/records/list?';
$path .= 'st=19900101';
$path .= '&en=21000101';
$path .= '&draw=1';
$path .= '&columns[0][data]=0';
$path .= '&columns[0][name]=';
$path .= '&columns[0][searchable]=true';
$path .= '&columns[0][orderable]=false';
$path .= '&columns[0][search][value]=';
$path .= '&columns[0][search][regex]=false';
$path .= '&columns[1][data]=1';
$path .= '&columns[1][name]=';
$path .= '&columns[1][searchable]=true';
$path .= '&columns[1][orderable]=false';
$path .= '&columns[1][search][value]=';
$path .= '&columns[1][search][regex]=false';
$path .= '&columns[2][data]=filialName';
$path .= '&columns[2][name]=';
$path .= '&columns[2][searchable]=true';
$path .= '&columns[2][orderable]=false';
$path .= '&columns[2][search][value]=';
$path .= '&columns[2][search][regex]=false';
$path .= '&columns[3][data]=checkData';
$path .= '&columns[3][name]=';
$path .= '&columns[3][searchable]=true';
$path .= '&columns[3][orderable]=false';
$path .= '&columns[3][search][value]=';
$path .= '&columns[3][search][regex]=false';
$path .= '&columns[4][data]=payment';
$path .= '&columns[4][name]=';
$path .= '&columns[4][searchable]=true';
$path .= '&columns[4][orderable]=false';
$path .= '&columns[4][search][value]=';
$path .= '&columns[4][search][regex]=false';
$path .= '&columns[5][data]=';
$path .= '&columns[5][name]=';
$path .= '&columns[5][searchable]=true';
$path .= '&columns[5][orderable]=false';
$path .= '&columns[5][search][value]=';
$path .= '&columns[5][search][regex]=false';
$path .= '&start=0';
$path .= '&length=20';
$path .= '&search[value]=';
$path .= '&search[regex]=false';
$data = $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
if (! empty($data['response']['data'])) {
foreach ($data['response']['data'] as $key => $dataItem) {
$data['response']['data'][$key]['workDate'] = date('d-m-Y', strtotime($dataItem['workDate']));
}
}
return $data;
}
public function deleteRecord($id, $fid)
{
$path = '/api/reservation/reserve?';
$path .= 'reserveId='. $id;
$path .= '&filialId=' . $fid;
$this->client
->clearParams()
->setMethod('DELETE')
->setPath($path)
->exec()->dataResponse;
}
public function anonymousReserve($data = [])
{
$data = $this->client->setParams($data)
->setPath('/api/reservation/anonymous-reserve')
->exec()
->dataResponse;
return $data;
}
public function getProfile($fio, $password)
{
$path = '/profile';
$data = $this->client->setFormParams([
'fio' => $fio,
'password.password' => $password,
'password.confirm' => $password
])->setPath('/profile')->exec()->dataResponse;
return $data;
}
public function getPayments()
{
$path = '/payments/list';
$data = $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
if (! empty($data['response']['data'])) {
foreach ($data['response']['data'] as $key => $dataItem) {
$data['response']['data'][$key]['date'] = date('d-m-Y', strtotime($dataItem['date']));
}
}
return $data;
}
public function getBonus()
{
$path = '/bonus';
return $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
}
public function getReferrals()
{
$path = '/referrals/list';
return $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
}
public function getCaseHistory()
{
$path = '/case-history/filter?st=19900101&en=' . date('Ymd');
$data = $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
if (! empty($data['response']['data'])) {
foreach ($data['response']['data'] as $key => $dataItem) {
$data['response']['data'][$key]['date'] = date('d-m-Y', strtotime($dataItem['date']));
}
}
return $data;
}
public function reserve($data = [])
{
$data = $this->client->setBodyParams($data)
->setPath('/api/reservation/reserve')
->exec()
->dataResponse;
return $data;
}
public function login($email, $password)
{
try {
$data = $this->client->setBodyParams([
'formKey' => 'pcode',
'password' => $password,
'username' => $email
])->setPath('/login')->exec()->dataResponse;
if ($data['response']['success'] == true) {
setcookie('WR_SESSION', $data['cookies']['WR_SESSION'], []);
setcookie('WR_DETAIL', $data['cookies']['WR_DETAIL'], []);
setcookie('PLAY_SESSION', $data['cookies']['PLAY_SESSION'], []);
}
return $data;
} catch (Exception $e) {
$data['response']['success'] = false;
$data['error']['message'] = $e->getMessage();
return $data;
}
}
public function loginEsia()
{
$params = [
"authType" => 'esia',
"esiaSdk" => '1',
"newWindow" => 'true',
"redirectUrl" => "http://cabinet.sovamed.ru/"
];
$data = $this->client
->setPath('/esia/esia-login-sdk')
->raw($params);
return $data;
}
public function getUser()
{
return $this->client
->setPath('/logged-in')
->clearParams()
->exec()
->dataResponse;
}
public function logout()
{
return $this->client
->setPath('/logout')
->clearParams()
->exec()
->dataResponse;
}
public function getFilials()
{
return $this->client
->clearParams()
->setPath('/filials/list')
->exec()->dataResponse;
}
public function getDepartments()
{
return $this->client
->clearParams()
->setPath('/specialists/departments')
->exec()->dataResponse;
}
public function getSpecialists($departments, $onlineMode = 0)
{
$path = '/specialists/doctors?departments=' . $departments;
$path .= '&onlineMode='. $onlineMode;
return $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
}
public function getInterval($sid, $did, $date, $fid = NULL, $onlineMode = 1)
{
if (is_array($date)) {
$st = strtotime($date['startInterval']);
$en = strtotime($date['endInterval']);
} else {
$st = strtotime('first day of this month', strtotime($date));
$en = strtotime('last day of this month', strtotime($date));
}
$path = '/api/reservation/intervals?dcode='. $sid;
$path .= '&spec='. $did;
$path .= '&st='. date("Ymd", $st);
$path .= '&en='. date("Ymd", $en);
$path .= '&onlineMode=' . ($onlineMode ? 1 : 0);
if (! empty($fid)) {
$path .= '&filialId='. $fid;
$path .= '&inFilials='. $fid;
}
$intervals = $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
$dataResponse = [];
if (isset($intervals['response']['data'])) {
foreach ($intervals['response']['data'] as $data) {
if (isset($data['workdates'])) {
foreach ($data['workdates'] as $key => $workdates) {
foreach ($workdates as $workdate => $item) {
$workDate = \DateTime::createFromFormat(
'Ymd',
$workdate
);
$intervalKey = 0;
for ($i=0; $i < count($item); $i++) {
foreach ($item[$i]['intervals'] as $intervaldata) {
$dataResponse[$workdate][$intervalKey]['workDate'] = $workDate;
$dataResponse[$workdate][$intervalKey]['schedident'] = $item[$i]['schedident'];
$dataResponse[$workdate][$intervalKey]['time'] = $intervaldata['time'];
$dataResponse[$workdate][$intervalKey]['isFree'] = $intervaldata['isFree'];
$dataResponse[$workdate][$intervalKey]['rNum'] = $item[$i]['rnum'];
$intervalKey++;
}
}
}
}
}
}
}
return $dataResponse;
}
public function getSchedule($sid, $did, $date, $fid = NULL, $onlineMode = 1)
{
if (is_array($date)) {
$st = strtotime($date['startInterval']);
$en = strtotime($date['endInterval']);
} else {
$st = strtotime('first day of this month', strtotime($date));
$en = strtotime('last day of this month', strtotime($date));
}
$path = '/api/reservation/schedule?doctor='. $sid;
$path .= '&speclist='. $did;
$path .= '&onlineMode=' . ($onlineMode ? 1 : 0);
$path .= '&st='. date("Ymd", $st);
$path .= '&en='. date("Ymd", $en);
if (! empty($fid)) {
$path .= '&filialId='. $fid;
}
return $this->client
->clearParams()
->setPath($path)
->exec()->dataResponse;
}
public function forgot($email)
{
return $this->client
->clearParams()
->setPath('/forgot-password?username=' . $email)
->exec()->dataResponse;
}
public function changePassword($pwdToken, $smsCode, $password)
{
return $this->client->setFormParams([
'pwdToken' => $pwdToken,
'code' => $smsCode,
'password.password' => $password,
'password.confirm' => $password
])->setPath('/change-password-web')->exec()->dataResponse;
}
public function register($data = [])
{
try {
$birthDate = $data['registration_form']['birthDate']['day'];
$birthDate .= '.';
$birthDate .= $data['registration_form']['birthDate']['month'];
$birthDate .= '.';
$birthDate .= $data['registration_form']['birthDate']['year'];
$data = $this->client->setFormParams([
'birthDate' => $birthDate,
'accept' => 'true',
'refuseCall' => 'true',
'refuseSms' => 'true',
'confirmed' => '',
'checkData' => '',
'firstName' => $data['registration_form']['firstName'],
'lastName' => $data['registration_form']['lastName'],
'middleName' => $data['registration_form']['middleName'],
'email' => $data['registration_form']['email'],
'phone' => $data['registration_form']['phone'],
'gender' => $data['registration_form']['gender'],
'captcha' => $data['g-recaptcha-response'],
'viewtype' => 1
])->setPath('/registration')->exec()->dataResponse;
if ($data['response']['success'] == true) {
setcookie('PLAY_SESSION', $data['cookies']['PLAY_SESSION'], []);
}
return $data;
} catch (\Exception $e) {
$data['response']['success'] = false;
$data['error']['message'] = $e->getMessage();
return $data;
}
}
public function confirm($rToken, $smsCode, $password)
{
$data = $this->client->setFormParams([
'smsCode' => $smsCode,
'password.password' => $password,
'password.confirm' => $password
])->setPath('/registration/confirm?rToken='. $rToken)->exec()->dataResponse;
return $data;
}
public function payment()
{
$params = [
'id' => 43229262,
'filial' => 4,
'amt' => '1200.00',
'errorUrl' => "https://sova.infoclinica.ru/payments",
'magazineId' => "5ed8acaa27734416bde98c89",
'paymethod' => "AC",
'status' => ['id' => 0, 'name' => "NotPaid"],
'successurl' => "https://sova.infoclinica.ru/payments",
];
// var_dump($this->getUser());
$data = $this->client
->setPath('/payments/testApiV3')
->setBodyParams($params)
->exec()->dataResponse;
return $data;
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace App\Bundle\Notisend;
class Request
{
private $client = null;
private $token = '1ea37dfb1838675d5d3985220c7ad895';
function __construct()
{
$this->client = new \GuzzleHttp\Client(
['base_uri' => 'https://api.notisend.ru']
);;
}
public function send($method = 'POST', $path = '/v1/email/messages', $params = NULL)
{
$options = [
'debug' => false,
'verify' => false,
'http_errors' => false,
'allow_redirects' => [
'max' => 10,
'strict' => true,
'referer' => true,
'track_redirects' => true,
],
'headers' => [
'Authorization' => 'Bearer ' . $this->token,
'Content-Encoding' => 'UTF-8',
'Content-Type' => 'application/json',
]
];
if ($params) {
$options['body'] = json_encode($params);
}
$response = $this->client->request($method, $path, $options);
return $response->getBody()->getContents();
}
public function getTemplates()
{
return $this->send('GET', '/v1/email/templates');
}
}
+70
View File
@@ -0,0 +1,70 @@
<?php
namespace App\Bundle\Sms;
use App\Bundle\Utils\Logger;
class Manager
{
private $client = null;
public function __construct($client)
{
$this->client = $client;
}
public function sendSmsSova(string $to, string $msg)
{
$response = $this->client->request('GET', '/sms/send', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://sms.ru',
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
'query' => [
'to' => $to,
'msg' => $msg,
'from' => $_ENV['SMSRU_FROM_SOVAMED'],
'json' => 1,
'api_id' => $_ENV['SMSRU_KEY_API'],
'test' => 0
],
]);
$response = $response->toArray();
Logger::send($response, 'sms.log');
return $response;
}
public function sendSmsWmt(string $to, string $msg)
{
$response = $this->client->request('POST', '/v1/sms', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://api.sms4b.ru',
'headers' => [
'Authorization' => $_ENV['SMS4B_TOKEN'],
'Content-Type' => 'application/json',
'User-Agent' => 'wmtmed_bot'
],
'body' => json_encode([
'sender' => $_ENV['SMS4B_FROM_WMTMED'],
'messages' => [
[
'number' => $to,
'text' => $msg
]
]
]),
]);
$response = $response->toArray();
Logger::send($response, 'sms4b.log');
return $response;
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Bundle\Utils;
class Logger
{
public static function send($data, $fileName = 'logger.log')
{
$fileLog = dirname(__DIR__, 3)
. DIRECTORY_SEPARATOR .'var'
. DIRECTORY_SEPARATOR. 'log'
. DIRECTORY_SEPARATOR . $fileName;
$current = '';
if (file_exists($fileLog)) {
$current = file_get_contents($fileLog);
$current .= "\n";
}
$current .= json_encode([
'datetime' => \date('Y-m-d H:i:s'),
'data' => $data
], JSON_UNESCAPED_UNICODE);
file_put_contents($fileLog, $current);
// $conn = $event->getConnection();
// $conn->executeQuery("SET NAMES UTF8");
}
}
+428
View File
@@ -0,0 +1,428 @@
<?php
namespace App\Bundle\Yandex;
/*
* id приложения aaa091c17d734ab08af7cb2455c360fa
* ссылка получения токена
* https://oauth.yandex.ru/authorize?response_type=token&client_id=aaa091c17d734ab08af7cb2455c360fa
*/
class Direct
{
private $token;
private $login;
private $url = 'https://api.direct.yandex.com/json/v5';
function __construct($regionId = false)
{
$this->changeRegion($regionId);
}
public function changeRegion($regionId = false)
{
switch ($regionId) {
case 92:
// return 'Волгоград';
$this->token = '';
$this->login = '';
break;
case 93:
// return 'Воронеж';
$this->token = 'y0_AgAAAABUjm5UAAgI4QAAAADRC5rdh5RD9KWSSIKGNb0cDBniUfVh6KU';
$this->login = 'e-16766240';
break;
case 94:
// return 'Краснодар';
$this->token = '';
$this->login = '';
break;
case 100:
// return 'Комфорт';
$this->token = '';
$this->login = '';
break;
case 101:
// return 'Совёнок';
$this->token = '';
$this->login = '';
break;
case 102:
// return 'ОМС';
$this->token = '';
$this->login = '';
break;
default:
// return 'Саратов';
$this->token = '';
$this->login = '';
break;
}
}
public function getError()
{
return $this->error;
}
/**
* @param array $params
* @param string $url
* @return mixed
*/
public function Request($params = [], $url, $report = false)
{
$headers = array(
"Authorization: Bearer $this->token", // OAuth-токен. Использование слова Bearer обязательно
"Client-Login: $this->login", // Логин клиента рекламного агентства
"Accept-Language: ru", // Язык ответных сообщений
"Content-Type: application/json; charset=utf-8" // Тип данных и кодировка запроса
);
if ($report == true) {
$headers []= "processingMode: auto"; // Режим формирования отчета online, offline , auto
$headers []= "returnMoneyInMicros: false"; // Не выводить в отчете строку с названием отчета и диапазоном дат
$headers []= "skipReportHeader: true"; // Не выводить в отчете строку с названием отчета и диапазоном дат
$headers []= "skipColumnHeader: true"; // Не выводить в отчете строку с названиями полей
$headers []= "skipReportSummary: true"; // Не выводить в отчете строку с количеством строк статистики
}
$body = json_encode($params, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
while (true) {
$result = curl_exec($curl);
if (!$result) {
echo ('Ошибка cURL: '.curl_errno($curl).' - '.curl_error($curl));
break;
} else {
// Разделение HTTP-заголовков и тела ответа
$responseHeadersSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$responseHeaders = substr($result, 0, $responseHeadersSize);
$responseBody = substr($result, $responseHeadersSize);
// Получение кода состояния HTTP
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
// Извлечение HTTP-заголовков ответа
// Идентификатор запроса
$requestId = preg_match('/RequestId: (\d+)/', $responseHeaders, $arr) ? $arr[1] : false;
// Рекомендуемый интервал в секундах для проверки готовности отчета
$retryIn = preg_match('/retryIn: (\d+)/', $responseHeaders, $arr) ? $arr[1] : 160;
if ($httpCode == 400) {
echo "Параметры запроса указаны неверно или достигнут лимит отчетов в очереди<br>\n";
echo "RequestId: {$requestId}<br>\n";
echo "JSON-код запроса:<br>{$body}<br>\n";
echo "JSON-код ответа сервера:<br>{$responseBody}<br>\n";
return $responseBody;
break;
} elseif ($httpCode == 200) {
return $responseBody;
break;
} elseif ($httpCode == 201) {
echo "Отчет успешно поставлен в очередь в режиме офлайн<br>\n";
echo "Повторная отправка запроса через {$retryIn} секунд<br>\n";
echo "RequestId: {$requestId}<br>\n";
sleep($retryIn);
} elseif ($httpCode == 202) {
echo "Отчет формируется в режиме offline.<br>\n";
echo "Повторная отправка запроса через {$retryIn} секунд<br>\n";
echo "RequestId: {$requestId}<br>\n";
sleep($retryIn);
} elseif ($httpCode == 500) {
echo "При формировании отчета произошла ошибка. Пожалуйста, попробуйте повторить запрос позднее<br>\n";
echo "RequestId: {$requestId}<br>\n";
echo "JSON-код ответа сервера:<br>\n{$responseBody}<br>\n";
break;
} elseif ($httpCode == 502) {
echo "Время формирования отчета превысило серверное ограничение.<br>";
echo "Пожалуйста, попробуйте изменить параметры запроса - уменьшить период и количество запрашиваемых данных.<br>";
echo "RequestId: {$requestId}<br>";
break;
} else {
echo "Произошла непредвиденная ошибка.<br>";
echo "RequestId: {$requestId}<br>";
echo "JSON-код запроса:<br>{$body}<br>";
echo "JSON-код ответа сервера:<br>{$responseBody}<br>";
break;
}
}
}
curl_close($curl);
}
/**
* @return Array|int
*/
public function getCompanies()
{
$params = [
'method' => 'get', // Используемый метод сервиса Campaigns
'params' => array(
'SelectionCriteria' => (object)array(
'States' => [
'ON',
'OFF',
],
), // Критерий отбора кампаний. Для получения всех кампаний должен быть пустым
'FieldNames' => [ // Названия параметров, которые требуется получить
"Id",
"Name",
"State",
"Type",
],
)
];
return $this->response($this->Request($params, $this->url . '/campaigns'));
}
private function response($data)
{
$data = json_decode($data, true);
if (empty($data['error'])) {
return $data['result'];
}
return $data['error'];
}
public function getRegions()
{
$params = [
"method" => "get",
"params" => [
"DictionaryNames" => [
//"Currencies",
//"MetroStations",
"GeoRegions",
//"TimeZones",
//"Constants",
// "AdCategories",
// "OperationSystemVersions",
// "ProductivityAssertions",
// "SupplySidePlatforms",
// "Interests",
// "AudienceCriteriaTypes",
// "AudienceDemographicProfiles",
// "AudienceInterests"
],
],
];
return $this->response($this->Request($params, $this->url . '/dictionaries'));
}
public function getKey($group)
{
$params = [
'method' => 'get', // Используемый метод сервиса Campaigns
'params' => [
'SelectionCriteria' => [
'AdGroupIds' => $group,
],
'FieldNames' => [
"Id",
"Keyword",
"State",
"Status",
"ServingStatus",
"AdGroupId",
"CampaignId",
"Bid",
"ContextBid",
"StrategyPriority",
"UserParam1",
"UserParam2",
"Productivity",
"StatisticsSearch",
"StatisticsNetwork",
]
]
];
return $this->response($this->Request($params, $this->url . '/keywords'));
}
public function getGroups($CampaignIds = array())
{
$params = [
'method' => 'get', // Используемый метод сервиса Campaigns
'params' => [
'SelectionCriteria' => [
'CampaignIds' => $CampaignIds,
'Statuses' => [
"ACCEPTED",
"DRAFT",
"MODERATION",
"PREACCEPTED",
"REJECTED"
],
],
'FieldNames' => [
"Id",
"CampaignId",
"Name",
"RegionIds",
"ServingStatus",
"Status",
"Type",
]
]
];
return $this->response($this->Request($params, $this->url . '/adgroups'));
}
public function getAds($CampaignIds = array())
{
$params = [
'method' => 'get', // Используемый метод сервиса Campaigns
'params' => [
'SelectionCriteria' => [
'CampaignIds' => $CampaignIds,
],
'FieldNames' => [
"Id",
"AdGroupId",
"CampaignId",
"State",
"StatusClarification",
"Type",
],
'TextAdFieldNames' => [
"Title",
"Title2",
"Text",
"Href",
"Mobile",
"DisplayUrlPath",
],
]
];
return $this->response($this->Request($params, $this->url . '/ads'));
}
public function getReport()
{
$params = [
"params" => [
"SelectionCriteria" => (object) [
// 'DateFrom' => \date('Y-m-d', strtotime('-7 day')),
// 'DateTo' => \date('Y-m-d', strtotime($dateTo))
],
"FieldNames" => [
"Week",
"CampaignId",
"AdGroupId",
"AdId",
"Impressions",
"Clicks",
"Cost",
"Conversions"
],
"ReportName" => 'отчет -'.time(),
"ReportType" => "AD_PERFORMANCE_REPORT",
"DateRangeType" => "LAST_WEEK",
"Format" => "TSV",
"IncludeVAT" => "NO",
"IncludeDiscount" => "NO"
]
];
$response = $this->Request($params, $this->url . '/reports', true);
if ($jsonResponse = json_decode($response, true)) {
return $jsonResponse['error'];
}
$linearray = [];
foreach(explode("\n", $response) as $key => $line ) {
if(!empty($line)) {
list(
$date,
$campaignId,
$adGroupId,
$adId,
//$LocationOfPresenceId,
$impressions,
$clicks,
$cost,
$conversions
//$AdFormat,
//$AdNetworkType,
//$Age
) = explode("\t", $line);
$linearray []= array(
'Date' => $date,
'CampaignId' => $campaignId,
'AdGroupId' => $adGroupId,
'AdId' => $adId,
//'LocationOfPresenceId' => $LocationOfPresenceId,
'Impressions' => $impressions,
'Clicks' => $clicks,
'Cost' => $cost,
'Conversions' => $conversions,
//'AdFormat' => $AdFormat,
//'AdNetworkType' => $AdNetworkType,
//'Age' => $Age,
);
}
}
return $linearray;
}
}
+54
View File
@@ -0,0 +1,54 @@
<?php
namespace App\Command;
use App\Bundle\Crypt\AES;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
class AesCommand extends Command
{
private $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
protected static $defaultName = 'app:aes';
protected static $defaultDescription = 'Add a short description for your command';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('phone', InputArgument::OPTIONAL, 'variant update table')
->addOption('decode', null, InputOption::VALUE_OPTIONAL, 'Option description')
;
}
// php bin/console app:aes
protected function execute(InputInterface $input, OutputInterface $output): int
{
$entityManager = $this->container->get('doctrine')->getManager();
$io = new SymfonyStyle($input, $output);
$decode = $input->getOption('decode');
$phone = $input->getArgument('phone');
if ($decode == true) {
$io->success('AES encrypt: ' . AES::encrypt($phone));
} else {
$io->success('AES decrypt: ' . AES::decrypt($phone));
}
return Command::SUCCESS;
}
}
+99
View File
@@ -0,0 +1,99 @@
<?php
namespace App\Command;
use App\Entity\Department;
use App\Entity\Specialist;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
class BaseCommand extends Command
{
private $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
protected static $defaultName = 'app:base';
protected static $defaultDescription = 'Add a short description for your command';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('var', InputArgument::OPTIONAL, 'variant update table')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$entityManager = $this->container->get('doctrine')->getManager();
$io = new SymfonyStyle($input, $output);
$var = $input->getArgument('var');
// php bin/console app:base setAlias
if ($var == 'setAlias') {
$departments = $entityManager->getRepository(Department::class)
->findAll();
foreach ($departments as $department) {
$department->setAlias($this->translit($department->getName(), '-'));
$entityManager->persist($department);
$entityManager->flush();
$io->success('departament updated ' . $department->getAlias());
}
$specialists = $entityManager->getRepository(Specialist::class)
->findAll();
foreach ($specialists as $specialist) {
$specialist->setAlias($specialist->getId() .'-'. $this->translit($specialist->getName(), '-'));
$entityManager->persist($specialist);
$entityManager->flush();
$io->success('specialist updated ' . $specialist->getAlias());
}
}
return Command::SUCCESS;
}
private function translit($string, $replacement = '_') {
if (empty($string))
return $string;
$converter = array(
'а' => 'a', 'б' => 'b', 'в' => 'v',
'г' => 'g', 'д' => 'd', 'е' => 'ye',
'ё' => 'yo', 'ж' => 'zh', 'з' => 'z',
'и' => 'i', 'й' => 'y', 'к' => 'k',
'л' => 'l', 'м' => 'm', 'н' => 'n',
'о' => 'o', 'п' => 'p', 'р' => 'r',
'с' => 's', 'т' => 't', 'у' => 'u',
'ф' => 'f', 'х' => 'kh', 'ц' => 'ts',
'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shch',
'ь' => '', 'ы' => 'y', 'ъ' => '',
'э' => 'e', 'ю' => 'yu', 'я' => 'ya'
);
$string = mb_strtolower($string);
$string = strtr($string, $converter);
$string = preg_replace('~[^-a-z0-9_]+~u', $replacement, $string);
$string = preg_replace('/\-{2,10}/m', $replacement, $string);
return trim($string, "-");
}
}
+195
View File
@@ -0,0 +1,195 @@
<?php
namespace App\Command;
use App\Entity\Interval;
use App\Entity\Filial;
use App\Entity\Department;
use App\Entity\Specialist;
use App\Entity\Location;
use App\Entity\Review;
use App\Entity\Schedule;
use App\Entity\Idoctor;
use App\Entity\Price;
use App\Bundle\Infoclinica\Rest;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\Bundle\Bitrix\Request as Bitrix;
class DiffDoctorsCommand extends Command
{
private $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
protected static $defaultName = 'app:DiffDoctors';
protected static $defaultDescription = 'различие Врачей';
protected $io = null;
protected $bitrix = null;
protected $entityManager = null;
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('regionId', InputArgument::OPTIONAL, 'region id')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$infoclinica = new Rest();
$this->entityManager = $this->container->get('doctrine')->getManager();
$this->io = new SymfonyStyle($input, $output);
$regionId = $input->getArgument('regionId');
$this->bitrix = (\App\Bundle\Bitrix\Request::init())->setRegionId($regionId);
$doctors = $this->bitrix->getDoctors(false);
foreach ($doctors as $doctor) {
$params = $this->loadInfoclinicaIds($doctor);
if($this->ioError($params['docIds'], 'INFOCLINICA_ID_DOC is NULL', $doctor['ID'])) {
$params['docIds'][] = 0;
}
if($this->ioError($params['docDeps'], 'INFOCLINICA_ID_DEP is NULL', $doctor['ID'])) {
$params['docDeps'][] = 0;
}
if($this->ioError($params['docFilials'], 'INFOCLINICA_ID_FILIAL is NULL', $doctor['ID'])) {
$params['docFilials'][] = 0;
}
$this->addFile($doctor);
if ($this->bitrix->docPropsCode($doctor['ID'], 'HIDE_TIMETABLE', false)) {
$this->io->warning('infoclinica false');
var_dump($this->createUpdateForiDoctor($doctor, $params));
} else {
var_dump($this->createUpdateForiDoctor($doctor, $params));
}
$this->io->warning('end:' . $doctor['ID']);
}
return Command::SUCCESS;
}
private function addFile($data = '')
{
$file = dirname(__DIR__, 2)
. DIRECTORY_SEPARATOR .'var'
. DIRECTORY_SEPARATOR. 'report'
. DIRECTORY_SEPARATOR . \date('Y-m-d') . '.csv';
$current = '';
if (file_exists($file)) {
$current = file_get_contents($file);
$current .= "\n";
} else {
$current .= "ID;NAME;DCODE;DEPARTMENT;FILIAL;B_ACTIVE;I_ACTIVE;C_ACTIVE;\n";
}
$current .= $data . "\n";
file_put_contents($file, $current);
}
private function createUpdateForiDoctor($doctor, $params)
{
$getIdoc = function($dcode, $deps) {
$iDoctors = [];
foreach ($deps as $departmentId) {
$iDoctors[] = $this->entityManager->getRepository(Idoctor::class)
->findOneBy([
'dcode' => $dcode,
'departmentId' => $departmentId
]);
}
return $iDoctors;
};
foreach ($params['docIds'] as $dcode) {
foreach ($getIdoc($dcode, $params['docDeps']) as $iDoctor) {
if (!empty($iDoctor)) {
$attrs = [
'name' => $iDoctor->getName(),
'dcode' => $iDoctor->getDcode(),
'department' => $iDoctor->getDepartmentId(),
'filial' => $iDoctor->getFilialId(),
'onlineMode' => $iDoctor->getOnlineMode(),
'nearestDate' => $iDoctor->getNearestDate(),
'infoclinica' => true
];
return ['doctor' => $doctor, 'params' => $params, 'attrs' => $attrs];
} else {
$this->io->error('not found iDoctor:' . $dcode);
}
}
}
}
private function ioError($prop, $msg, $id, $continue = true)
{
if (empty($prop[0])) {
$this->io->error($msg. ': '. $id);
return true;
}
return false;
}
private function loadInfoclinicaIds($doctor)
{
$this->io->success($doctor['NAME']. ' bitrix id: '. $doctor['ID']);
$data = [
'docIds' => [],
'docDeps' => [],
'docFilials' => []
];
if (trim($doctor['XML_ID']) !== trim($doctor['ID'])) {
$data['docIds'][] = preg_replace( '/[^0-9]/', '', $doctor['XML_ID']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'INFOCLINICA_ID') as $prop) {
$data['docIds'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'DEPARTMENT_INFO') as $prop) {
$data['docDeps'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'INFOCLINICA_ID_DEP') as $prop) {
$data['docDeps'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'FILIAL_INFO') as $prop) {
$data['docFilials'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
$data['docFilials'] = array_diff(array_unique($data['docFilials']), ['']);
$data['docIds'] = array_diff(array_unique($data['docIds']), ['', 0, '0', '00']);
$data['docDeps'] = array_diff(array_unique($data['docDeps']), ['']);
$this->io->info('FILIALS_INFO:'. implode(',', $data['docFilials']));
$this->io->info('INFOCLINICA_IDS:'. implode(',', $data['docIds']));
$this->io->info('INFOCLINICA_ID_DEPS:'. implode(',', $data['docDeps']));
return $data;
}
}
+152
View File
@@ -0,0 +1,152 @@
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\Entity\DirectCompany;
use App\Entity\DirectReport;
use App\Bundle\Infoclinica\Region;
use App\Bundle\Yandex\Direct;
class DirectCommand extends Command
{
private $em;
private $io;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->em = $container->get('doctrine')->getManager();
}
protected static $defaultName = 'app:direct';
protected static $defaultDescription = 'Add a short description for your command';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
// ->addArgument('file', InputArgument::OPTIONAL, 'variant update table')
->addArgument('regionId', InputArgument::OPTIONAL, 'variant update table')
;
}
// php bin/console app:direct vlg.csv
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->io = new SymfonyStyle($input, $output);
// $file = $input->getArgument('file');
$regionId = $input->getArgument('regionId');
$report = (new Direct($regionId))->getReport();
foreach ($report as $item) {
$this->addDirectReport($item);
}
return Command::SUCCESS;
}
private function addDirectReport($item)
{
// $directReport = $this->em->getRepository(DirectReport::class)
// ->findOneBy(['companyId' => (int) $item['1']]);
$directReport = new DirectReport();
$date = \DateTime::createFromFormat(
'Y-m-d',
\date("Y-m-d", \strtotime($item['Date']))
);
$directReport
->setDate($date)
->setCampaignId($item['CampaignId'])
->setAdGroupId($item['AdGroupId'])
->setAdId($item['AdId'])
->setImpressions($item['Impressions'])
->setClicks($item['Clicks'])
->setCost($item['Cost'])
->setConversions($item['Conversions'])
;
$this->em->persist($directReport);
$this->em->flush();
$this->io->success($directReport->getId());
}
private function uploadCSV($csv)
{
$city = Region::getCurrentName($regionId);
$dir = dirname(__FILE__, 3) . '/var/direct/';
$csv = $this->readCSV($dir. $file);
if ($csv['success'] == true) {
foreach ($csv['data'] as $item) {
if ((int) $item['1'] == 0) {
$this->io->warning('companyId = 0');
continue;
}
$directCompany = $this->em->getRepository(DirectCompany::class)
->findOneBy(['companyId' => (int) $item['1']]);
if (!$directCompany) {
$directCompany = new DirectCompany;
}
$directCompany
->setCompanyId((int) $item['1'])
->setName($item['0'])
->setCity($city);
$this->em->persist($directCompany);
$this->em->flush();
$this->io->success('success: ' . $directCompany->getId());
}
} else {
$this->io->error($csv['message']);
}
}
private function readCSV($path = '')
{
$response = ['success' => false];
if (! file_exists($path)) {
$response['message'] = 'csv file not exists: ' . $path;
return $response;
}
$row = 1;
if (($handle = fopen($path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++) {
$response['data'][$row][$c] = $data[$c];
}
}
fclose($handle);
$response['success'] = true;
}
return $response;
}
}
+307
View File
@@ -0,0 +1,307 @@
<?php
namespace App\Command;
use App\Entity\Interval;
use App\Entity\Filial;
use App\Entity\Department;
use App\Entity\Specialist;
use App\Entity\Location;
use App\Entity\Review;
use App\Entity\Schedule;
use App\Entity\Idoctor;
use App\Entity\Price;
use App\Bundle\Infoclinica\Rest;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\Bundle\Bitrix\Request as Bitrix;
use App\Bundle\Infoclinica\Request as InfoclinicaRequest;
use App\Bundle\Notisend\Request as NotisendRequest;
class InfoclinicaCommand extends Command
{
private $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
protected static $defaultName = 'app:Infoclinica';
protected static $defaultDescription = 'Add a short description for your command';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('var', InputArgument::OPTIONAL, 'variant update table')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$infoclinica = new Rest();
$entityManager = $this->container->get('doctrine')->getManager();
$io = new SymfonyStyle($input, $output);
$var = $input->getArgument('var');
// php bin/console app:Infoclinica departaments
if ($var == 'departaments') {
$departments = $infoclinica->getDepartments();
if ($departments['response']['success'] == true) {
foreach ($departments['response']['data'] as $item) {
$department = $entityManager->getRepository(Department::class)
->findOneBy(['did' => $item['id'], 'onlineMode' => $item['onlineMode']]);
if (is_null($department)) {
$department = new Department;
}
if (empty($item['viewInWeb'])) {
$item['viewInWeb'] = 0;
}
$department
->setAlias('')
->setActive($item['viewInWeb'])
->setDid($item['id'])
->setName($item['name'])
->setGroupName($item['groupName'])
->setOnlineMode($item['onlineMode']);
$entityManager->persist($department);
$entityManager->flush();
$io->success('id '. $department->getId() .' updated');
}
} else {
$io->error('departament not updated');
}
// php bin/console app:Infoclinica reviews
} elseif ($var == 'reviews') {
$bitrix = Bitrix::init();
$locations = $entityManager->getRepository(Location::class)
->findAll();
foreach ($locations as $location) {
try {
$reviews = $bitrix->getReviews($location->getDcode(), $location->getSpecialist()->getInfoclinica());
} catch (Exception $e) {
$io->error($location->getSpecialist()->getId());
$io->error($e->getErrors());
}
$chunksize = count($reviews) - 1;
foreach ($reviews as $key => $params) {
$review = $entityManager->getRepository(Review::class)
->findOneBy(['bitrixId' => $params['REVIEW_ID']]);
$active = ($params['DATA'][0]["ACTIVE"] == 'Y')? true: false;
if (! $review) {
if (! $active) {
continue;
}
$review = new Review;
}
$dateCreate = \DateTime::createFromFormat(
'Y-m-d H:i:s',
$params['DATA'][0]["DATE_CREATE"]
);
$review
->setBitrixId((int) $params['REVIEW_ID'])
->setSpecialist($location->getSpecialist())
->setRating(5)
->setMessage('')
->setAuthor('')
->setActive($active)
->setDateCreate($dateCreate);
foreach ($params['DATA'] as $data) {
if ($data['CODE'] == "NAME") {
$review->setAuthor(trim(strip_tags($data['VALUE'])));
}
if ($data['CODE'] == "MESSAGE") {
$review->setMessage(trim(strip_tags($data['VALUE'])));
}
if ($data['CODE'] == "SOURCE_LINK") {
$re = '/(http|ftp|https):\/\/([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])/m';
preg_match_all($re, $data['VALUE'], $matches, PREG_SET_ORDER, 0);
if (! empty($matches[0][0])) {
$review->setSource($matches[0][0]);
}
}
if ($data['CODE'] == "RATING") {
$review->setRating((int) $data['VALUE']);
}
}
$entityManager->persist($review);
if ($chunksize == $key) {
$entityManager->flush();
$io->success('review in '. $review->getId(). ' updated rows: ' . $chunksize);
$chunksize = 0;
}
}
}
// php bin/console app:Infoclinica schedules
} elseif ($var == 'schedules') {
$specialists = $entityManager->getRepository(Specialist::class)
->findAll();
foreach ($specialists as $specialist) {
$fid = NULL;
if (! empty($filial = $specialist->getFilial())) {
$fid = $filial->getFid();
}
$io->error('specialist id:' . $specialist->getSid()
. ' department id:' . $specialist->getDepartment()->getDid()
. ' filial id:' . $fid
. ' onlineMode:' . $specialist->getOnlineMode()
);
$schedules =$infoclinica->getSchedule(
$specialist->getSid(),
$specialist->getDepartment()->getDid(),
date('ymd', time()),
$fid,
$specialist->getOnlineMode()
);
if (! empty($schedules['response']['data'])) {
if ($schedules['response']['success'] == true) {
foreach ($schedules['response']['data'] as $data) {
foreach($data['intervals'] as $interval) {
$startInterval = \DateTime::createFromFormat(
'H:i',
$interval['startInterval']
);
$endInterval = \DateTime::createFromFormat(
'H:i',
$interval['endInterval']
);
$schedule = $entityManager->getRepository(Schedule::class)
->findOneBy([
'schedident' => $interval['schedident'],
'startInterval' => $startInterval,
'endInterval' => $endInterval
]);
if (is_null($schedule)) {
$schedule = new Schedule;
}
$workDate = \DateTime::createFromFormat(
'Ymd',
$interval['workDate']
);
$schedule
->setSpecialist($specialist)
->setFilial($specialist->getFilial())
->setDepartment($specialist->getDepartment())
->setSchedident($interval['schedident'])
->setIsFree($interval['isFree'])
->setIsAvailable($interval['isAvailable'])
->setOnlineMode($specialist->getOnlineMode())
->setStartInterval($startInterval)
->setEndInterval($endInterval)
->setWorkDate($workDate);
$entityManager->persist($schedule);
$entityManager->flush();
$io->success('schedident in '. $schedule->getSchedident(). ' updated');
}
}
}
} else {
$io->error('specialist id:' . $specialist->getSid()
. 'department id:' . $specialist->getDepartment()->getDid()
. 'filial id:' . $fid
);
$io->error('schedident in '. $schedule->getSchedident(). ' not updated');
}
}
// php bin/console app:Infoclinica intervals
} elseif ($var == 'intervals') {
$specialists = $entityManager->getRepository(Specialist::class)
->findAll();
foreach ($specialists as $specialist) {
$fid = NULL;
if (! empty($filial = $specialist->getFilial())) {
$fid = $filial->getFid();
}
$intervals = $infoclinica->getInterval(
$specialist->getSid(),
$specialist->getDepartment()->getDid(),
date('ymd', time()),
$fid,
$specialist->getOnlineMode()
);
if (! empty($intervals)) {
foreach ($intervals as $data) {
foreach ($data as $intervalData) {
$interval = $entityManager->getRepository(Interval::class)
->findOneBy([
'schedident' => $intervalData['schedident'],
'time' => $intervalData['time'],
'workDate' => $intervalData['workDate']
]);
if (is_null($interval)) {
$interval = new Interval;
}
$interval
->setWorkDate($intervalData['workDate'])
->setSpecialist($specialist)
->setDepartment($specialist->getDepartment())
->setSchedident($intervalData['schedident'])
->setTime($intervalData['time'])
->setRnum($intervalData['rNum'])
->setIsFree($intervalData['isFree']);
$entityManager->persist($interval);
$entityManager->flush();
$io->success('interval in '. $interval->getId(). ' updated');
}
}
} else {
$io->error('intervals '. $specialist->getSid(). ' in not updated');
var_dump($intervals);
}
}
}
return Command::SUCCESS;
}
}
@@ -0,0 +1,88 @@
<?php
namespace App\Command;
use App\Entity\Department;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class UploadDepInfoclinicaCommand extends Command
{
private $container;
private $client;
public function __construct(ContainerInterface $container, HttpClientInterface $client)
{
parent::__construct();
$this->container = $container;
$this->client = $client;
}
protected static $defaultName = 'app:UploadDep';
protected static $defaultDescription = 'Обновление отделений для врачей';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('var', InputArgument::OPTIONAL, 'variant update table')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$entityManager = $this->container->get('doctrine')->getManager();
$io = new SymfonyStyle($input, $output);
$response = $this->client->request('GET', '/specialists/departments', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://widget.sovamed.ru',
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
]);
$response = $response->toArray();
foreach ($response['data'] as $item) {
$department = $entityManager->getRepository(Department::class)
->findOneBy([
'did' => $item['id']
]);
if (is_null($department)) {
$department = new Department();
}
if (empty($item['viewInWeb'])) {
$item['viewInWeb'] = 0;
}
$department
->setDid($item['id'])
->setName($item['name'])
->setAlias('')
->setGroupName($item['groupName'])
->setActive($item['viewInWeb'])
->setOnlineMode($item['onlineMode'])
;
$entityManager->persist($department);
$entityManager->flush();
$io->success('load: '. $department->getId());
}
return Command::SUCCESS;
}
}
+339
View File
@@ -0,0 +1,339 @@
<?php
namespace App\Command;
use App\Entity\Interval;
use App\Entity\Filial;
use App\Entity\Department;
use App\Entity\Specialist;
use App\Entity\Location;
use App\Entity\Review;
use App\Entity\Schedule;
use App\Entity\Idoctor;
use App\Entity\Price;
use App\Bundle\Infoclinica\Rest;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use App\Bundle\Bitrix\Request as Bitrix;
class UploadDoctorsCommand extends Command
{
private $container;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->container = $container;
}
protected static $defaultName = 'app:UploadDoctors';
protected static $defaultDescription = 'Обновление и загрузка Врачей';
protected $io = null;
protected $bitrix = null;
protected $entityManager = null;
private $countPersisted;
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('regionId', InputArgument::OPTIONAL, 'region id')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$infoclinica = new Rest();
$this->entityManager = $this->container->get('doctrine')->getManager();
$this->io = new SymfonyStyle($input, $output);
$regionId = $input->getArgument('regionId');
$this->bitrix = (\App\Bundle\Bitrix\Request::init())->setRegionId($regionId);
$doctors = $this->bitrix->getDoctors(true);
$this->io->info('start updating:' . count($doctors));
foreach ($doctors as $doctor) {
$params = $this->loadInfoclinicaIds($doctor);
if($this->ioError($params['docIds'], 'INFOCLINICA_ID_DOC is NULL', $doctor['ID'])) {
$params['docIds'][] = trim($doctor['ID']);
}
if($this->ioError($params['docDeps'], 'INFOCLINICA_ID_DEP is NULL', $doctor['ID'])) {
$params['docDeps'][] = 0;
}
if($this->ioError($params['docFilials'], 'INFOCLINICA_ID_FILIAL is NULL', $doctor['ID'])) {
$params['docFilials'][] = 0;
}
if ($this->bitrix->docPropsCode($doctor['ID'], 'HIDE_TIMETABLE', false)) {
$this->createUpdateForDoctor($doctor, $params);
} else {
$this->createUpdateForiDoctor($doctor, $params);
}
}
$this->io->info('update rows:' . $this->countPersisted);
$this->entityManager->flush();
return Command::SUCCESS;
}
private function createUpdateForDoctor($doctor, $params)
{
$nearestDate = \date('d.m.Y');
foreach ($params['docFilials'] as $filialId) {
foreach ($params['docIds'] as $dcode) {
foreach ($params['docDeps'] as $departmentId) {
$attrs = [
'name' => trim($doctor['NAME']),
'dcode' => $dcode,
'department' => $departmentId,
'filial' => $filialId,
'onlineMode' => 0,
'nearestDate' => $nearestDate,
'infoclinica' => false
];
$this->addDoctor($doctor, $params, $attrs);
}
}
}
}
private function createUpdateForiDoctor($doctor, $params)
{
$getIdoc = function($dcode, $deps) {
$iDoctors = [];
foreach ($deps as $departmentId) {
$iDoctors[] = $this->entityManager->getRepository(Idoctor::class)
->findOneBy([
'dcode' => $dcode,
'departmentId' => $departmentId,
'onlineMode' => 0
]);
}
return $iDoctors;
};
foreach ($params['docIds'] as $dcode) {
foreach ($getIdoc($dcode, $params['docDeps']) as $iDoctor) {
if (!empty($iDoctor)) {
$attrs = [
'name' => $iDoctor->getName(),
'dcode' => $iDoctor->getDcode(),
'department' => $iDoctor->getDepartmentId(),
'filial' => $iDoctor->getFilialId(),
'onlineMode' => $iDoctor->getOnlineMode(),
'nearestDate' => $iDoctor->getNearestDate(),
'infoclinica' => true
];
$this->addDoctor($doctor, $params, $attrs);
}
}
}
}
private function addDoctor($doctor, $params, $attrs)
{
$active = ($doctor['ACTIVE'] == 'Y')? true : false;
if (empty($attrs['department']) || empty($attrs['filial'])) {
$active = false;
}
$filial = $this->entityManager->getRepository(Filial::class)
->findOneBy(['fid' => $attrs['filial']]);
if (is_null($filial)) {
$filial = $this->entityManager->getRepository(Filial::class)
->findOneBy(['fid' => 0]);
}
$department = $this->entityManager->getRepository(Department::class)
->findOneBy(['did' => $attrs['department']]);
if (is_null($department)) {
$department = $this->entityManager->getRepository(Department::class)
->findOneBy(['did' => 0]);
}
$locationSearch = ['dcode' => $attrs['dcode']];
$locationSearch['department'] = $department;
$locationSearch['filial'] = $filial;
$locationEntity = $this->entityManager->getRepository(Location::class)
->findOneBy($locationSearch);
if (is_null($locationEntity)) {
$locationEntity = new Location();
}
$specialist = $this->entityManager->getRepository(Specialist::class)
->findByDcode($attrs['dcode']);
if (is_null($specialist)) {
$params['docIds'][] = trim($doctor['ID']);
$specialist = new Specialist();
$specialist->setDcode(json_encode($params['docIds'], JSON_FORCE_OBJECT));
} else {
$dcodes = json_decode($specialist->getDcode(), true);
$dcodes[] = $doctor['ID'];
$dcodes = array_unique($dcodes);
$specialist->setDcode(json_encode($dcodes, JSON_FORCE_OBJECT));
}
$specialist = $this->setSpecialist($specialist, $doctor);
$nearestDate = \DateTime::createFromFormat(
'Y-m-d',
date('Y-m-d', strtotime($attrs['nearestDate']))
);
$specialist
->setImg($doctor['ID'])
->setNearestDate($nearestDate)
->setInfoclinica($attrs['infoclinica']);
$locationEntity
->setActive($active)
->setOnlineMode(0)
->setDcode($attrs['dcode'])
->setFilial($filial)
->setDepartment($department)
->setSpecialist($specialist);
try {
$this->countPersisted++;
$this->entityManager->persist($locationEntity);
} catch (Exception $e) {
$this->io->error( $e->getMessage());
}
}
private function setSpecialist($specialist, $doctor)
{
$specialist->setName(trim($doctor['NAME']))
->setAlias('')
;
$post = $this->bitrix->docPropsCode($doctor['ID'], 'POST', false);
if (! empty($post['VALUE'])) {
$specialist->setSpeciality($post['VALUE']);
}
if (! empty($doctor['DETAIL_TEXT'])) {
$specialist->setDescription($doctor['DETAIL_TEXT']);
}
$category = $this->bitrix->docPropsCode($doctor['ID'], 'CATEGORY', false);
if (! empty($category['VALUE'])) {
$specialist->setCategory(mb_strtolower(trim($category['VALUE'])));
}
$kinder = $this->bitrix->docPropsCode($doctor['ID'], 'KIDS_AGE', false);
if (! empty($kinder['VALUE'])) {
$specialist->setKinder((int) $kinder['VALUE']);
}
$expirience = $this->bitrix->docPropsCode($doctor['ID'], 'EXPERIENCE', false);
if (! empty($expirience['VALUE'])) {
if (iconv_strlen($expirience['VALUE']) == 4) {
$specialist->setExpirience(date('Y') - $expirience['VALUE']);
} else {
$specialist->setExpirience((int) $expirience['VALUE']);
}
}
$linkPriceIds = $this->bitrix->docPropsCode($doctor['ID'], 'LINK_PRICE_1');
if ($linkPriceIds) {
foreach ($specialist->getPrices() as $delPrice) {
$specialist->removePrice($delPrice);
}
foreach ($linkPriceIds as $linkPrice) {
$price = $this->bitrix->docPropsCode($linkPrice['VALUE'], 'PRICE', false);
if (! empty($price)) {
$priceEntity = $this->entityManager->getRepository(Price::class)
->findOneBy(['propertyValueId' => (int) $price['ID']]);
if (! $priceEntity) {
$priceEntity = new Price();
}
if (! empty($price['BIE_NAME'])) {
$priceEntity
->setName(trim($price['BIE_NAME']))
->setValue((int) str_replace(',', '.', $price['VALUE']))
->setDateUpdate(new \DateTime())
->setPropertyValueId($price['ID'] . '.' . $doctor['ID']);
$specialist->addPrice($priceEntity);
}
}
}
}
return $specialist;
}
private function ioError($prop, $msg, $id, $continue = true)
{
if (empty($prop[0])) {
return true;
}
return false;
}
private function loadInfoclinicaIds($doctor)
{
$data = [
'docIds' => [],
'docDeps' => [],
'docFilials' => []
];
if (trim($doctor['XML_ID']) !== trim($doctor['ID'])) {
$data['docIds'][] = preg_replace( '/[^0-9]/', '', $doctor['XML_ID']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'INFOCLINICA_ID') as $prop) {
$data['docIds'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'DEPARTMENT_INFO') as $prop) {
$data['docDeps'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'INFOCLINICA_ID_DEP') as $prop) {
$data['docDeps'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
foreach ($this->bitrix->docPropsCode($doctor['ID'], 'FILIAL_INFO') as $prop) {
$data['docFilials'][] = preg_replace( '/[^0-9]/', '', $prop['VALUE']);
}
$data['docFilials'] = array_diff(array_unique($data['docFilials']), ['']);
$data['docIds'] = array_diff(array_unique($data['docIds']), ['', 0, '0', '00']);
$data['docDeps'] = array_diff(array_unique($data['docDeps']), ['']);
return $data;
}
}
@@ -0,0 +1,79 @@
<?php
namespace App\Command;
use App\Bundle\Infoclinica\Rest;
use App\Entity\Idoctor;
use App\Entity\Department;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UploadDoctorsInfoclinicaCommand extends Command
{
protected static $defaultName = 'upload:doctorsInfoclinica';
protected static $defaultDescription = 'Обновление и загрузка врачей из инфоклиники';
protected $entityManager = null;
protected $io = null;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->entityManager = $container->get('doctrine')->getManager();
}
protected function configure(): void
{
$this->setDescription(self::$defaultDescription)
->addArgument('onlineMode', InputArgument::OPTIONAL, 'onlineMode [0,1]')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->io = new SymfonyStyle($input, $output);
$infoclinica = new Rest();
$onlineMode = $input->getArgument('onlineMode');
foreach ($this->entityManager->getRepository(Department::class)->findAll() as $department) {
foreach ($infoclinica->getSpecialists($department->getDid(), $onlineMode)['response']['data'] as $doctor) {
$iDoctor = $this->entityManager->getRepository(Idoctor::class)
->findOneBy([
'dcode' => $doctor['dcode'],
'departmentId' => $doctor['departmentId'],
'onlineMode' => $onlineMode
]);
if (! $iDoctor) {
$this->io->success('create in specialist '. $doctor['dcode']);
$iDoctor = new Idoctor();
} else {
$this->io->success('upgrade in specialist '. $doctor['dcode']);
}
$iDoctor
->setDcode($doctor['dcode'])
->setName($doctor['name'])
->setDepartmentId($doctor['departmentId'])
->setDepartmentName($doctor['departmentName'])
->setFilialId($doctor['filialId'])
->setFilialName($doctor['filialName'])
->setComment(empty($doctor['comment'])? '':$doctor['comment'])
->setNearestDate($doctor['nearestDate'])
->setViewInWeb($doctor['viewInWeb'])
->setOnlineMode($onlineMode)
;
$this->entityManager->persist($iDoctor);
}
$this->entityManager->flush();
}
return Command::SUCCESS;
}
}
@@ -0,0 +1,83 @@
<?php
namespace App\Command;
use App\Entity\Filial;
use App\Entity\Department;
use App\Entity\Specialist;
use App\Entity\Location;
use App\Entity\Idoctor;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
class UploadDoctorsOnlineCommand extends Command
{
protected static $defaultName = 'upload:doctorsOnline';
protected static $defaultDescription = 'Обновление и загрузка онлайн врачей';
protected $entityManager = null;
protected $io = null;
public function __construct(ContainerInterface $container)
{
parent::__construct();
$this->entityManager = $container->get('doctrine')->getManager();
}
protected function configure(): void
{
$this->setDescription(self::$defaultDescription);
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$this->io = new SymfonyStyle($input, $output);
$doctorsOnline = $this->entityManager
->getRepository(Idoctor::class)
->findBy(['onlineMode' => 1]);
foreach ($doctorsOnline as $doctor) {
$specialist = $this->entityManager->getRepository(Specialist::class)
->findByDcode($doctor->getDcode());
if ($specialist) {
$locationEntity = $this->entityManager->getRepository(Location::class)
->findOneBy([
'dcode' => $doctor->getDcode(),
'department' => $doctor->getDepartmentId(),
'filial' => $doctor->getFilialId(),
'onlineMode' => $doctor->getOnlineMode()
]);
$filial = $this->entityManager->getRepository(Filial::class)
->findOneBy(['fid' => $doctor->getFilialId()]);
$department = $this->entityManager->getRepository(Department::class)
->findOneBy(['did' => $doctor->getDepartmentId()]);
if (is_null($locationEntity)) {
$locationEntity = new Location();
}
$locationEntity
->setDcode($doctor->getDcode())
->setDepartment($department)
->setFilial($filial)
->setSpecialist($specialist)
->setOnlineMode($doctor->getOnlineMode())
->setActive(1)
;
$this->entityManager->persist($locationEntity);
}
}
$this->entityManager->flush();
return Command::SUCCESS;
}
}
@@ -0,0 +1,87 @@
<?php
namespace App\Command;
use App\Entity\PriceDepartment;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class UploadPriceDepInfoclinicaCommand extends Command
{
private $container;
private $client;
public function __construct(ContainerInterface $container, HttpClientInterface $client)
{
parent::__construct();
$this->container = $container;
$this->client = $client;
}
protected static $defaultName = 'app:UploadPiceDep';
protected static $defaultDescription = 'Обновление отделений для получения цен';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('var', InputArgument::OPTIONAL, 'variant update table')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$entityManager = $this->container->get('doctrine')->getManager();
$io = new SymfonyStyle($input, $output);
$response = $this->client->request('GET', '/pricelist/departments', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://widget.sovamed.ru',
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
]);
$response = $response->toArray();
foreach ($response['data'] as $item) {
$department = $entityManager->getRepository(PriceDepartment::class)
->findOneBy([
'groupId' => $item['id']
]);
if (is_null($department)) {
$department = new PriceDepartment();
}
if (empty($item['viewInWeb'])) {
$item['viewInWeb'] = 0;
}
$department
->setGroupId($item['id'])
->setName($item['name'])
->setGroupName($item['groupName'])
->setViewInWeb($item['viewInWeb'])
->setDoctCount($item['schCount'])
;
$entityManager->persist($department);
$entityManager->flush();
$io->success('load: '. $department->getId());
}
return Command::SUCCESS;
}
}
@@ -0,0 +1,152 @@
<?php
namespace App\Command;
use App\Entity\PriceDepartment;
use App\Entity\PriceList;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class UploadPriceInfoclinicaCommand extends Command
{
private $container;
private $client;
public function __construct(ContainerInterface $container, HttpClientInterface $client)
{
parent::__construct();
$this->container = $container;
$this->client = $client;
}
protected static $defaultName = 'app:UploadPice';
protected static $defaultDescription = 'Обновление цен';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addArgument('did', InputArgument::OPTIONAL, 'department id update')
->addOption('debug', null, InputOption::VALUE_NONE, 'debug on')
->addOption('nosleep', null, InputOption::VALUE_OPTIONAL, 'sleep true|false default false')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$entityManager = $this->container->get('doctrine')->getManager();
$io = new SymfonyStyle($input, $output);
$departments = $entityManager->getRepository(PriceDepartment::class)->findAll();
$departmentId = $input->getArgument('did');
$debug = $input->getOption('debug');
$nosleep = $input->getOption('nosleep');
if ($departmentId) {
$departments = $entityManager->getRepository(PriceDepartment::class)
->findBy(['groupId' => $departmentId]);
}
if (empty($departments))
return Command::FAILURE;
foreach ($departments as $department) {
foreach ($this->getPricelist($department->getGroupId()) as $collection) {
foreach ($collection as $item) {
$priceList = $entityManager->getRepository(PriceList::class)
->findOneBy([
'kodoper' => $item['kodoper'],
'speccode' => $item['speccode'],
'filial' => $item['filial'],
'groupId' => $department->getGroupId()
]);
$text = 'update: ';
if (is_null($priceList)) {
$priceList = new priceList();
$text = 'create: ';
}
$priceList
->setKodoper($item['kodoper'])
->setSchname($item['schname'])
->setSpecname($item['specname'])
->setSpeccode($item['speccode'])
->setPriceInfo($item['priceInfo'])
->setDiscpercent($item['discpercent'])
->setDiscprice($item['discprice'])
->setStructname($item['structname'])
->setFname($item['fname'])
->setFilial($item['filial'])
->setComment($item['comment'])
->setMediaId($item['mediaId'])
->setDateUpdate(new \DateTime())
->setGroupId($department->getGroupId());
$entityManager->persist($priceList);
$entityManager->flush();
if ($debug)
$io->success($text. $priceList->getId());
}
}
if ($debug)
$io->info('sleep: 2 sec');
if (empty($nosleep))
sleep(2);
}
$io->success('successful');
return Command::SUCCESS;
}
private function getPricelist($depnum)
{
$response = [];
$flag = true;
$firstrow = 1;
$lastrow = 500;
while ($flag) {
$result = $this->client->request('GET', 'pricelist/list', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://widget.sovamed.ru',
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
'query' => [
'depnum' => $depnum,
'firstrow' => $firstrow,
'lastrow' => $lastrow
],
]);
$firstrow = $lastrow + 1;
$lastrow = $lastrow + 500;
$result = $result->toArray();
if (empty($result['data'])) {
$flag = false;
} else {
$response[] = $result['data'];
}
if (empty($nosleep))
sleep(3);
}
return $response;
}
}
+66
View File
@@ -0,0 +1,66 @@
<?php
namespace App\Command;
use App\Service\UserCleanupService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
class UserCleanupCommand extends Command
{
private $userCleanupService;
public function __construct(UserCleanupService $userCleanupService)
{
parent::__construct();
$this->userCleanupService = $userCleanupService;
}
protected static $defaultName = 'app:user:cleanup';
protected static $defaultDescription = 'Удаляет пользователей с только ROLE_USER после истечения времени жизни кукисов';
protected function configure(): void
{
$this
->setDescription(self::$defaultDescription)
->addOption('dry-run', null, InputOption::VALUE_NONE, 'Показать, какие пользователи будут удалены, без фактического удаления')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$dryRun = $input->getOption('dry-run');
if ($dryRun) {
$io->note('Режим проверки (dry-run). Пользователи не будут удалены.');
}
$io->title('Очистка пользователей');
try {
if ($dryRun) {
$io->note('Режим проверки (dry-run). Пользователи не будут удалены.');
// В dry-run режиме просто показываем сколько будет удалено
// Но для этого нужно добавить метод в сервис или просто запустить и показать результат
}
$deletedCount = $this->userCleanupService->cleanupExpiredUsers();
if ($dryRun) {
$io->success(sprintf('Найдено пользователей для удаления: %d', $deletedCount));
} else {
$io->success(sprintf('Успешно удалено пользователей: %d', $deletedCount));
}
return Command::SUCCESS;
} catch (\Exception $e) {
$io->error(sprintf('Ошибка при выполнении очистки: %s', $e->getMessage()));
$io->error($e->getTraceAsString());
return Command::FAILURE;
}
}
}
View File
+130
View File
@@ -0,0 +1,130 @@
<?php
namespace App\Controller;
use App\Entity\Banner;
use App\Form\BannerType;
use App\Repository\BannerRepository;
use App\Repository\CityRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\String\Slugger\SluggerInterface;
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/admin/banner")
*/
class BannerController extends AbstractController
{
/**
* @Route("/", name="admin_banner_index", methods={"GET"})
*/
public function index(BannerRepository $bannerRepository): Response
{
return $this->render('banner/index.html.twig', [
'banners' => $bannerRepository->findAll(),
]);
}
/**
* @Route("/new", name="banner_new", methods={"GET","POST"})
*/
public function new(Request $request, SluggerInterface $slugger): Response
{
$banner = new Banner();
$form = $this->createForm(BannerType::class, $banner);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$srcFile = $form->get('file')->getData();
if ($srcFile) {
$originalFilename = pathinfo($srcFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = $slugger->slug($originalFilename);
$newFilename = $safeFilename.'-'.uniqid().'.'.$srcFile->guessExtension();
$srcFile->move(
$this->getParameter('banners_directory'),
$newFilename
);
$banner->setSrc($newFilename);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($banner);
$entityManager->flush();
return $this->redirectToRoute('admin_banner_index');
}
return $this->render('banner/new.html.twig', [
'banner' => $banner,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}/edit", name="banner_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Banner $banner, SluggerInterface $slugger): Response
{
$form = $this->createForm(BannerType::class, $banner);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$file = $this->getParameter('banners_directory') . DIRECTORY_SEPARATOR . $banner->getSrc();
if (file_exists($file)) {
unlink($file);
}
$srcFile = $form->get('file')->getData();
if ($srcFile) {
$originalFilename = pathinfo($srcFile->getClientOriginalName(), PATHINFO_FILENAME);
$safeFilename = $slugger->slug($originalFilename);
$newFilename = $safeFilename.'-'.uniqid().'.'.$srcFile->guessExtension();
$srcFile->move(
$this->getParameter('banners_directory'),
$newFilename
);
$banner->setSrc($newFilename);
}
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('admin_banner_index');
}
return $this->render('banner/edit.html.twig', [
'banner' => $banner,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}", name="banner_delete", methods={"POST"})
*/
public function delete(Request $request, Banner $banner): Response
{
if ($this->isCsrfTokenValid('delete'.$banner->getId(), $request->request->get('_token'))) {
$file = $this->getParameter('banners_directory') . DIRECTORY_SEPARATOR . $banner->getSrc();
if (file_exists($file)) {
unlink($file);
}
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($banner);
$entityManager->flush();
}
return $this->redirectToRoute('admin_banner_index');
}
}
+65
View File
@@ -0,0 +1,65 @@
<?php
namespace App\Controller;
use App\Bundle\Calltouch\Request as CalltouchRequest;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* @Route("/api")
*/
class CalltouchAPIController extends AbstractController
{
/**
* @Route("/add-calltouch", methods={"POST"})
*/
public function addCalltouch(Request $request): Response
{
$data = [
'requestNumber' => \md5(\time()),
'subject' => $request->request->get('subject'),
'requestUrl' => $request->request->get('requestUrl'),
'requestDate' => \date('d-m-Y H:i:s'),
'fio' => $request->request->get('fio'),
];
if (! empty($request->request->get('sessionId'))) {
$data['sessionId'] = $request->request->get('sessionId');
}
if (! empty($request->request->get('customSources'))) {
if (!empty($request->request->get('customSources')['source'])) {
$data['customSources'] = $request->request->get('customSources');
}
}
if (! empty($request->request->get('tag'))) {
$data['addTags'][] = ['tag' => $request->request->get('tag')];
}
if (! empty($request->request->get('comment'))) {
$data['comment']['text'] = json_encode($request->request->get('comment'), JSON_UNESCAPED_UNICODE);
}
if (! empty($request->request->get('phoneNumber'))) {
$data['phoneNumber'] = $request->request->get('phoneNumber');
}
if (! empty($request->request->get('email'))) {
$data['email'] = $request->request->get('email');
}
$calltouch = new CalltouchRequest();
if (! empty($request->request->get('regionId'))) {
$calltouch->changeRegion($request->request->get('regionId'));
}
$calltouch = $calltouch->create($data);
return $this->json(['data' => $calltouch]);
}
}
+96
View File
@@ -0,0 +1,96 @@
<?php
namespace App\Controller;
use App\Entity\CategoryPage;
use App\Form\CategoryPageType;
use App\Repository\CategoryPageRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/category/page")
*/
class CategoryPageController extends AbstractController
{
/**
* @Route("/", name="category_page_index", methods={"GET"})
*/
public function index(CategoryPageRepository $categoryPageRepository): Response
{
return $this->render('category_page/index.html.twig', [
'category_pages' => $categoryPageRepository->findAll(),
]);
}
/**
* @Route("/new", name="category_page_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$categoryPage = new CategoryPage();
$form = $this->createForm(CategoryPageType::class, $categoryPage);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($categoryPage);
$entityManager->flush();
return $this->redirectToRoute('category_page_index');
}
return $this->render('category_page/new.html.twig', [
'category_page' => $categoryPage,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}", name="category_page_show", methods={"GET"})
*/
public function show(CategoryPage $categoryPage): Response
{
return $this->render('category_page/show.html.twig', [
'category_page' => $categoryPage,
]);
}
/**
* @Route("/{id}/edit", name="category_page_edit", methods={"GET","POST"})
*/
public function edit(Request $request, CategoryPage $categoryPage): Response
{
$form = $this->createForm(CategoryPageType::class, $categoryPage);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('category_page_index');
}
return $this->render('category_page/edit.html.twig', [
'category_page' => $categoryPage,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}", name="category_page_delete", methods={"POST"})
*/
public function delete(Request $request, CategoryPage $categoryPage): Response
{
if ($this->isCsrfTokenValid('delete'.$categoryPage->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($categoryPage);
$entityManager->flush();
}
return $this->redirectToRoute('category_page_index');
}
}
+245
View File
@@ -0,0 +1,245 @@
<?php
namespace App\Controller;
use App\Bundle\Infoclinica\Region;
use App\Entity\Filial;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Request;
use App\Repository\SpecialistRepository;
use App\Repository\DepartmentRepository;
use App\Repository\PriceDepartmentRepository;
use App\Repository\PriceListRepository;
use App\Entity\PriceList;
use Knp\Component\Pager\PaginatorInterface;
use App\Entity\PriceDepartment;
use App\Form\PriceListFormType;
use App\Form\PriceListAdminFormType;
use App\Form\PriceListUpdateAdminFormType;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use App\Service\PriceListService;
use App\Service\SpecialistService;
/**
* @Route("/")
*/
class DefaultController extends AbstractController
{
private $client;
public function __construct(HttpClientInterface $client, KernelInterface $kernel)
{
$this->client = $client;
$this->kernel = $kernel;
}
/**
* @IsGranted("ROLE_USER")
* @Route("/", name="default_index")
*/
public function index(): Response
{
return $this->render('base/index.html.twig', [
'template' => Region::getTemplite(),
'alias' => '',
'title' => 'Личный кабинет'
]);
}
/**
* @Route("/doctor-your-home", name="default_doc_your_home")
*/
public function doctorYourHome(): Response
{
return $this->render('base/doc_your_home.html.twig', [
'template' => Region::getTemplite(),
'title' => 'Вызов врача на дом'
]);
}
/**
* @Route("/stoimost-uslug", name="default_price")
*/
public function price(PriceListService $priceListService, PaginatorInterface $paginator, Request $request): Response
{
$priceList = new PriceList();
$searchForm = $this->createForm(PriceListFormType::class, $priceList, [
'action' => $this->generateUrl('default_price'),
'method' => 'GET',
]);
$searchForm->handleRequest($request);
$filters = $request->query->get('price_list_form', []);
$priceListQuery = $priceListService->getFilteredPriceListQuery($filters);
$pagination = $paginator->paginate(
$priceListQuery->getQuery(),
$request->query->getInt('page', 1),
50
);
return $this->render('base/price.html.twig', [
'title' => 'Стоимость услуг',
'template' => Region::getTemplite(),
'pagination' => $pagination,
'searchForm' => $searchForm->createView()
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/update/price-list", name="default_update_price_list", methods={"POST"})
*/
public function uploadPrice(Request $request): Response
{
$application = new Application($this->kernel);
$application->setAutoExit(false);
$input = new ArrayInput([
'command' => 'app:UploadPice',
'did' => $request->request->get('groupId'),
'--nosleep' => true
]);
// Вы можете использовать NullOutput(), если вам не нужен вывод
$output = new BufferedOutput();
$application->run($input, $output);
return $this->json(
(strpos($output->fetch(), '[OK] successful') === false)? ['status' => false]: ['status' => true]
);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/price-list", name="default_price_list")
*/
public function priceList(
PriceListService $priceListService,
PriceListRepository $priceListRepository,
PaginatorInterface $paginator,
Request $request
): Response {
$priceList = new PriceList();
$searchForm = $this->createForm(PriceListAdminFormType::class, $priceList, [
'action' => $this->generateUrl('default_price_list'),
'method' => 'GET',
]);
$searchForm->handleRequest($request);
$params = $request->query->get('default_price_list',[]);
$priceListQuery = $priceListService->getPriceListQuery($params);
$pagination = $paginator->paginate(
$priceListQuery->getQuery(),
$request->query->getInt('page', 1),
50
);
return $this->render('base/price_list.html.twig', [
'priceList' => $priceList,
'dateActive' => (new \DateTime())->modify('-2 day')->format('Y-m-d 00:00:00'),
'title' => 'Сравнение цен',
'template' => Region::getTemplite(),
'pagination' => $pagination,
'searchForm' => $searchForm->createView()
]);
}
private function getPricelist($depnum)
{
$response = [];
$flag = true;
$firstrow = 1;
$lastrow = 500;
while ($flag) {
$result = $this->client->request('GET', 'pricelist/list', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://widget.sovamed.ru',
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
'query' => [
'depnum' => $depnum,
'firstrow' => $firstrow,
'lastrow' => $lastrow
],
]);
$firstrow = $lastrow + 1;
$lastrow = $lastrow + 500;
$result = $result->toArray();
if (empty($result['data'])) {
$flag = false;
} else {
$response[] = $result['data'];
}
}
return $response;
}
/**
* @Route("/info", name="default_info")
*/
public function info(): Response
{
return $this->render('base/doc.html.twig', [
'template' => Region::getTemplite(),
'title' => 'Информация'
]);
}
/**
* @Route("/help", name="default_help")
*/
public function help(Request $request): Response
{
if ($request->getMethod() == 'POST') {
$params = $request->request->get('help');
$to = 'i.alexandrov@sova.clinic';
$subject = $params['team'];
$headers = 'From: ' . $params['email'] . "\r\n" .
'Reply-To: ' . $params['email'] . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$message = 'ФИО:' . $params['fio'] ."\r\n";
$message .= 'Телефон:' . $params['phone'] ."\r\n";
$message .= 'Вопрос:' . $params['question'] ."\r\n";
$message = wordwrap($message, 70, "\r\n");
if (mail($to, $subject, $message, $headers)) {
$this->addFlash(
'success',
'Спасибо, мы получили Ваше сообщение.'
);
} else {
$this->addFlash(
'notice',
'Cервис временно не доступен!'
);
}
}
return $this->render('base/help.html.twig', [
'template' => Region::getTemplite(),
'title' => 'Помощь'
]);
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace App\Controller;
use App\Entity\Department;
use App\Form\DepartmentType;
use App\Repository\DepartmentRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/department")
*/
class DepartmentController extends AbstractController
{
/**
* @Route("/", name="department_index", methods={"GET"})
*/
public function index(DepartmentRepository $departmentRepository): Response
{
return $this->render('department/index.html.twig', [
'departments' => $departmentRepository->findAll(),
]);
}
/**
* @Route("/{id}/edit", name="department_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Department $department): Response
{
$form = $this->createForm(DepartmentType::class, $department);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('department_index');
}
return $this->render('department/edit.html.twig', [
'department' => $department,
'form' => $form->createView(),
]);
}
}
+304
View File
@@ -0,0 +1,304 @@
<?php
namespace App\Controller;
use App\Bundle\Infoclinica\Region;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Repository\RecordRepository;
use OpenApi\Annotations as OA;
use App\Repository\CityRepository;
use App\Bundle\Utils\Logger;
use App\Bundle\Sms\Manager as SmsManager;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\HttpClient\CachingHttpClient;
use Symfony\Component\HttpKernel\HttpCache\Store;
use App\Repository\DepartmentRepository;
use App\Entity\Filial;
use App\Repository\SpecialistViewRepository;
/**
* @Route("/api")
*/
class InternalAPIController extends AbstractController
{
private $client;
private $rootPath = '';
public function __construct(HttpClientInterface $client, string $rootPath)
{
$this->rootPath = $rootPath;
$store = new Store($rootPath . '/var/HttpClient');
$this->client = new CachingHttpClient($client, $store);
}
/**
* @Route("/swagger.json", name="public_api_swagger_js")
*/
public function swaggerJson(): Response
{
$openapi = \OpenApi\Generator::scan([$this->rootPath . '/src/']);
$response = new Response(
$openapi->toJson(),
Response::HTTP_OK,
['content-type' => 'application/json']
);
return $response;
}
/**
* @Route("/swagger", name="public_api_swagger")
*/
public function swaggerUI():response
{
return $this->render('internal_api/swagger.html.twig', [
'title' => 'Open API sovamed'
]);
}
/**
* @Route("/smart-captcha", name="public_smart_captcha", methods={"POST"})
*/
public function smartCaptcha(Request $request):response
{
$res = $this->client->request('POST', '/validate', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://smartcaptcha.yandexcloud.net',
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot',
],
'query' => [
"secret" => $_ENV['SMARTCAPTCHA_SERVER_KEY'],
"token" => $request->request->get('smart-token'),
"ip" => $_SERVER['REMOTE_ADDR'],
]
]);
return $this->json($res->toArray());
}
/**
* @Route("/banner/{regionId}", name="banner_show", methods={"GET"})
*/
public function show($regionId, CityRepository $cityRepository): Response
{
$banner = $cityRepository->findOneBy(['regionId' => $regionId])->getBanner();
$data = [
'active' => false,
];
if ($banner) {
$data = [
'src' => $banner->getSrc(),
'href' => $banner->getHref(),
'active' => $banner->getActive(),
];
}
return $this->json($data);
}
/**
* @Route("/log", name="api_log", methods={"POST"})
*/
public function log(Request $request): Response
{
Logger::send($request->toArray());
return $this->json(['success' => true]);
}
/**
* @Route("/count-record", methods={"POST"})
*/
public function countRecord(RecordRepository $recordRepository, Request $request): Response
{
$stDate = date('Y-m-d H:00', \time());
$enDate = date('Y-m-d H:00', strtotime('+1 hours', time()));
$count = $recordRepository
->createQueryBuilder('r')
->select('count(r.id)')
->where('r.hash in (:hash)')
->andWhere('r.createAt BETWEEN :currentDate AND :nextDate')
->setParameter('currentDate', new \DateTime($stDate))
->setParameter('nextDate', new \DateTime($enDate))
->setParameter('hash', md5($request->request->get('phone')))
->getQuery()
->getSingleScalarResult();
return $this->json(['data' => [
'stDate' => $stDate,
'enDate' => $enDate,
'count' => $count,
'hash' => md5($request->request->get('phone')),
'phone' => $request->request->get('phone'),
]]);
}
/**
* @Route("/add-record", methods={"POST"})
*/
public function addRecord(Request $request): Response
{
$entityManager = $this->getDoctrine()->getManager();
$record = new Record();
$record
->setSpecialistId((int) $request->request->get('dcode'))
->setPhone($request->request->get('phone'))
->setHash($request->request->get('phone'))
->setCreateAt(new \DateTime('NOW'));
try {
$entityManager->persist($record);
$entityManager->flush();
return $this->json(['data' => true]);
} catch (Exception $e) {
return $this->json(['data' => $e->getMessage()]);
}
}
/**
* https://sms.ru/code/call?phone=79626293193&ip=33.22.11.55&api_id=B58070E1-E89B-95B0-D9BA-37A108868CAF
* @Route("/msg", methods={"POST"})
*/
public function msg(Request $request): Response
{
return $this->json(['status' => 'OK']);
}
/**
* https://sms.ru/code/call?phone=79626293193&ip=33.22.11.55&api_id=B58070E1-E89B-95B0-D9BA-37A108868CAF
* @Route("/veretify", methods={"POST"})
*/
public function veretify(Request $request): Response
{
$phone = preg_replace( '/[^0-9]/', '', $request->request->get('phone'));
$sms = new SmsManager($this->client);
$code = rand(1000, 9999);
$msg = 'Код: ' . $code . ' для подтверждения. Никому не сообщайте пароль.';
if (Region::getTemplite() == 'base') {
$response = $sms->sendSmsSova($phone, $msg);
} else {
if ($response = $sms->sendSmsWmt($phone, $msg)) {
$response['status'] = "OK";
}
}
if ($response['status'] == 'OK' ) {
if (! empty($code)) {
return $this->json([
'status' => 'OK',
'code' => base64_encode($code)
]);
} else {
return $this->json(['status' => 'OK']);
}
}
return $this->json($response);
}
/**
* @Route("/search", methods={"POST"})
*/
public function search(
Request $request,
SpecialistViewRepository $specialistViewRepository,
DepartmentRepository $departmentRepository
): Response {
$searchType = $request->request->get('type');
$searchQuery = $request->request->get('q');
if ($searchType === 'name') {
$specialistQuery = $specialistViewRepository->createFilteredQueryBuilder([
'name' => $searchQuery,
'onlineMode' => $request->request->getInt('onlineMode', 0) === 1,
'regionId' => $request->cookies->getInt('region', 0)
]);
$query = $specialistQuery->getQuery();
} else {
$departmentQuery = $departmentRepository
->createQueryBuilder('d')
->where('d.name LIKE :name')
->setParameter('name', '%' . mb_convert_case($searchQuery, MB_CASE_TITLE, "UTF-8") . '%');
$query = $departmentQuery->getQuery();
}
return $this->json(['data' => $query->getResult()]);
}
/**
* @Route("/departments", methods={"GET"})
*/
public function departments(
Request $request,
DepartmentRepository $departmentRepository
): Response {
try {
$regionId = $request->cookies->getInt('region');
$regionId = ($regionId > 0) ? $regionId : null;
$kinder = $request->query->getInt('kinder', 0);
$kinder = ($kinder == 1) ? 1 : null;
// Используем ту же логику, что и в форме SpecialistSearchType
$qb = $departmentRepository->createQueryBuilder('d')
->select('d.did, d.name')
->distinct()
->innerJoin('App\Entity\LocationView', 'l', 'WITH', 'l.department = d.did AND l.active = true')
->innerJoin('App\Entity\SpecialistView', 's', 'WITH', 's.id = l.specialistId AND s.active = true')
->leftJoin('App\Entity\Filial', 'f', 'WITH', 'f.fid = l.filial')
->where('f.address LIKE :address')
->andWhere('d.did <> :did')
->setParameter('did', 0)
->setParameter('address', '%' . \App\Bundle\Infoclinica\Region::getCurrentName() . '%');
// Добавляем фильтр по региону, если он указан
if ($regionId !== null && $regionId > 0) {
$qb->andWhere('s.regionId = :regionId')
->setParameter('regionId', $regionId);
}
// Добавляем фильтр по детским специализациям, если выбран "Детский врач"
if ($kinder !== null && $kinder == 1) {
$qb->andWhere('s.sType = :sType')
->setParameter('sType', 1);
}
// Если "Взрослый врач" или не выбран, показываем все специализации (без фильтра по sType)
$departments = $qb->orderBy('d.name', 'ASC')
->getQuery()
->getArrayResult();
$result = [];
foreach ($departments as $department) {
$result[] = [
'did' => $department['did'],
'name' => $department['name']
];
}
return $this->json(['data' => $result]);
} catch (\Exception $e) {
return $this->json([
'error' => $e->getMessage(),
'data' => []
], 500);
}
}
}
+102
View File
@@ -0,0 +1,102 @@
<?php
namespace App\Controller;
use App\Entity\Page;
use App\Form\PageType;
use App\Repository\CategoryPageRepository;
use App\Repository\PageRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @Route("/page")
*/
class PageController extends AbstractController
{
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/", name="page_index", methods={"GET"})
*/
public function index(PageRepository $pageRepository): Response
{
return $this->render('page/index.html.twig', [
'pages' => $pageRepository->findAll(),
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/new", name="page_new", methods={"GET","POST"})
*/
public function new(Request $request, CategoryPageRepository $categoryPageRepository): Response
{
$page = new Page();
$form = $this->createForm(PageType::class, $page);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$cp = $categoryPageRepository->findOneBy(['id' => $request->request->get('page')['category']]);
$page->setCategory($cp);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($page);
$entityManager->flush();
return $this->redirectToRoute('page_index');
}
return $this->render('page/new.html.twig', [
'page' => $page,
'form' => $form->createView(),
]);
}
/**
* @Route("/{alias}", name="page_show", methods={"GET"})
*/
public function show(Page $page): Response
{
return $this->render('page/show.html.twig', [
'page' => $page,
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/edit", name="page_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Page $page): Response
{
$form = $this->createForm(PageType::class, $page);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('page_index');
}
return $this->render('page/edit.html.twig', [
'page' => $page,
'form' => $form->createView(),
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}", name="page_delete", methods={"POST"})
*/
public function delete(Request $request, Page $page): Response
{
if ($this->isCsrfTokenValid('delete'.$page->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($page);
$entityManager->flush();
}
return $this->redirectToRoute('page_index');
}
}
+688
View File
@@ -0,0 +1,688 @@
<?php
namespace App\Controller;
use App\Bundle\Infoclinica\Region;
use App\Support\OnlineMode;
use App\Entity\Record;
use App\Entity\PriceDepartment;
use App\Entity\PriceList;
use App\Entity\Filial;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
use App\Bundle\Utils\Logger;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpClient\CachingHttpClient;
use Symfony\Component\HttpKernel\HttpCache\Store;
use OpenApi\Annotations as OA;
use App\Service\SpecialistService;
use App\Service\PriceListService;
use Knp\Component\Pager\PaginatorInterface;
/**
* @OA\Info(title="Open API sovamed",
* description="Справочник методов доступных в Open API sovamed.",
* version="3.0.0"
* )
*
* @OA\Server( url="https://dev.sovamed.ru/api", description="Open API sovamed")
*
* @Route("/api")
*/
class PublicAPIController extends AbstractController
{
private $client;
public function __construct(HttpClientInterface $client, string $rootPath)
{
$store = new Store($rootPath . '/var/HttpClient');
$this->client = new CachingHttpClient($client, $store);
}
/**
* @Route("/anonymous-reserve", methods={"POST"})
*/
public function anonymousReserve(Request $request): Response
{
try {
$timezone = Region::getTimezone();
if (!empty($request->request->get('timezone'))) {
$timezone = (int) $request->request->get('timezone');
}
$reserve = [
'date' => date('Ymd', strtotime($request->request->get('workDate'))),
'st' => explode('-', $request->request->get('time'))[0],
'en' => explode('-', $request->request->get('time'))[1],
'services' => [],
'filial' => (int) $request->request->get('filial'),
'timezone' => $timezone,
'schedident' => (int) $request->request->get('schedident'),
'rnum' => $request->request->get('rnum') === 'undefined' ? null : $request->request->get('rnum'),
'dcode' => (int) $request->request->get('specialist')
];
$requestData = [
'accept' => 'true',
'fio' => $request->request->get('fio'),
'captcha' => $request->request->get('captcha'),
'email' => $request->request->get('email'),
'phone' => $request->request->get('phone'),
'reserve' => json_encode($reserve, JSON_UNESCAPED_SLASHES)
];
$referer = $request->headers->get('referer');
$response = $this->client->request('POST', '/api/reservation/anonymous-reserve', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => $_ENV['MIS'],
'headers' => [
'Referer' => $referer,
'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
'Accept-Language' => 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept' => 'application/json, text/javascript, */*; q=0.01',
'Content-Type' => 'application/json; charset=UTF-8',
'X-Requested-With' => 'XMLHttpRequest',
'X-Integration-Type' => 'WEBSDK'
],
'body' => json_encode($requestData)
]);
// Проверяем статус ответа
$statusCode = $response->getStatusCode();
if ($statusCode !== 200) {
throw new \Exception("External API returned status: {$statusCode}");
}
$intervals = $response->toArray();
// Сохраняем запись
$entityManager = $this->getDoctrine()->getManager();
$record = new Record();
$record
->setSpecialistId((int) $request->request->get('specialist'))
->setPhone($request->request->get('phone'))
->setHash($request->request->get('phone'))
->setReserve($reserve)
->setCreateAt(new \DateTime('NOW'));
$entityManager->persist($record);
$entityManager->flush();
return $this->json([
'success' => true,
'data' => [
'intervals' => $intervals,
'hash' => md5($request->request->get('phone')),
'phone' => $request->request->get('phone'),
'recordId' => $record->getId(),
]
]);
} catch (\Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface $e) {
// Ошибка 4xx
return $this->json([
'success' => false,
'error' => 'Client error: ' . $e->getMessage()
], 400);
} catch (\Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface $e) {
// Ошибка 5xx
return $this->json([
'success' => false,
'error' => 'Server error: ' . $e->getMessage()
], 502);
} catch (\Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface $e) {
// Ошибки сети
return $this->json([
'success' => false,
'error' => 'Network error: ' . $e->getMessage()
], 503);
} catch (\Exception $e) {
// Другие ошибки
return $this->json([
'success' => false,
'error' => 'Internal error: ' . $e->getMessage()
], 500);
}
}
/**
* @OA\Get(
* tags= {"Расписание врача"},
* path="/interval",
* summary="Получение сетки расписания",
* @OA\Parameter(
* name="startInterval",
* description="Начальная дата (Y-m-d)",
* in="query",
* required=true,
* @OA\Schema(
* type="string",
* format="Y-m-d"
*
* )
* ),
* @OA\Parameter(
* name="endInterval",
* description="Конечна дата (Y-m-d)",
* in="query",
* required=true,
* @OA\Schema(
* type="string",
* format="Y-m-d"
*
* )
* ),
* @OA\Parameter(
* name="department",
* description="ID отделения",
* in="query",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="doctor",
* description="ID врача",
* in="query",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="filial",
* description="ID филиала",
* in="query",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Response(
* response=200,
* description="json response"
* )
* )
*
* @Route("/interval", methods={"GET"})
*/
public function interval(Request $request): Response
{
$dateFormat = $request->query->get('dateFormat');
if (empty($dateFormat)) {
$dateFormat = 'Y-m-d';
}
$startInterval = $request->query->get('startInterval');
$endInterval = $request->query->get('endInterval');
$doctor = $request->query->get('doctor');
$department = $request->query->get('department');
$filial = $request->query->get('filial');
$onlineMode = OnlineMode::isOnline($request->query->get('onlineMode'));
$isFree = true;
$nearestDate = NULL;
if (empty($doctor) || empty($startInterval) || empty($endInterval) || empty($department) || empty($filial)) {
throw new BadRequestHttpException('Bad request');
}
$schedules = $this->getSchedule($doctor, $department, $filial, $onlineMode, $startInterval, $endInterval);
$intervals = $this->getInterval($doctor, $department, $filial, $onlineMode, $startInterval, $endInterval);
$findInterval = function ($schedident, $workDate) use($intervals, $onlineMode, $isFree, $nearestDate, $dateFormat) {
$intervalsData = [];
if (!empty($intervals)) {
foreach ($intervals[date('Ymd', strtotime($workDate))] as $key => $interval) {
if ($interval['schedident'] == $schedident) {
$intervalsData[$key]['time'] = $interval['time'];
$intervalsData[$key]['rNum'] = isset($interval['rNum'])? $interval['rNum']: null;
$intervalsData[$key]['startTime'] = explode('-', $interval['time'])[0];
$intervalsData[$key]['endTime'] = explode('-', $interval['time'])[1];
$intervalsData[$key]['schedident'] = $interval['schedident'];
$intervalsData[$key]['isFree'] = $interval['isFree'];
$intervalsData[$key]['onlineMode'] = $onlineMode;
$intervalsData[$key]['workDate'] = $interval['workDate']->format($dateFormat);
if ($interval['isFree'] && $isFree && is_null($nearestDate)) {
$nearestDate = $interval['workDate']->format('Y-m-d');
$intervalsData[$key]['nearestDate'] = $interval['workDate']->format($dateFormat);
$isFree = false;
}
}
}
}
return $intervalsData;
};
$dataResponse = [];
$i = 0;
if (isset($schedules['success'])) {
if ($schedules['success'] == true) {
$uniqueIntervals = [];
foreach ($schedules['data'] as $key => $data) {
uasort($data['intervals'], function ($a, $b) {
if ($a['workDate'] == $b['workDate']) {
return $a['startInterval'] <=> $b['startInterval'];
}
return 0;
});
foreach($data['intervals'] as $interval) {
if ($interval['isFree'] === true) {
$workDate = date($dateFormat, strtotime($interval['workDate']));
$uniqueKey = $interval['schedident']
. '-' . $workDate
. '-' . $interval['startInterval']
. '-' . $interval['endInterval'];
if (!isset($uniqueIntervals[$uniqueKey])) {
$dataIntervals = $findInterval($interval['schedident'], $workDate);
if ($dataIntervals) {
$uniqueIntervals[$uniqueKey] = [
'workDate' => $workDate,
'isFree' => $interval['isFree'],
'startInterval' => $interval['startInterval'],
'endInterval' => $interval['endInterval'],
'intervals' => $dataIntervals
];
}
}
}
}
}
$dataResponse = array_values($uniqueIntervals);
}
}
$uid = false;
if (! is_null($this->getUser())) {
$uid = $this->getUser()->getUid();
}
return $this->json(['data' => ['userInfo' => $uid, 'intervalsData' => $dataResponse]]);
}
private function getInterval($doctor, $department, $filial, $onlineMode, $startInterval, $endInterval)
{
$response = $this->client->request('GET', '/api/reservation/intervals', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => $_ENV['MIS'],
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
'query' => [
'dcode' => $doctor,
'spec' => $department,
'onlineMode' => ($onlineMode ? 1 : 0),
'st' => \date("Ymd", strtotime($startInterval)),
'en' => \date("Ymd", strtotime($endInterval)),
'filialId' => $filial,
'inFilials' => $filial
]
]);
$intervals = $response->toArray();
$dataResponse = [];
if (isset($intervals['data'])) {
foreach ($intervals['data'] as $data) {
if (isset($data['workdates'])) {
foreach ($data['workdates'] as $key => $workdates) {
foreach ($workdates as $workdate => $item) {
$workDate = \DateTime::createFromFormat(
'Ymd',
$workdate
);
$intervalKey = 0;
for ($i=0; $i < count($item); $i++) {
foreach ($item[$i]['intervals'] as $intervaldata) {
$dataResponse[$workdate][$intervalKey]['workDate'] = $workDate;
$dataResponse[$workdate][$intervalKey]['schedident'] = $item[$i]['schedident'];
$dataResponse[$workdate][$intervalKey]['time'] = $intervaldata['time'];
$dataResponse[$workdate][$intervalKey]['isFree'] = $intervaldata['isFree'];
$dataResponse[$workdate][$intervalKey]['rNum'] = isset($item[$i]['rnum'])? $item[$i]['rnum']: null;
$intervalKey++;
}
}
}
}
}
}
}
return $dataResponse;
}
private function getSchedule($doctor, $department, $filial, $onlineMode, $startInterval, $endInterval)
{
$response = $this->client->request('GET', '/api/reservation/schedule', [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => $_ENV['MIS'],
'headers' => [
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot'
],
'query' => [
'doctor' => $doctor,
'department' => $department,
'onlineMode' => ($onlineMode ? 1 : 0),
'st' => date("Ymd", strtotime($startInterval)),
'en' => date("Ymd", strtotime($endInterval)),
'filialId' => $filial
]
]);
return $response->toArray();
}
/**
* @Route("/userInfo", methods={"GET"})
*/
public function user(): Response
{
$uid = false;
if (! is_null($this->getUser())) {
$uid = $this->getUser()->getUid();
}
return $this->json(['data' => $uid]);
}
/**
* @OA\Get(
* tags= {"Услуги и цены"},
* path="/pricelist/departments",
* summary="Получение списка отделений",
* @OA\Response(
* response=200,
* description="json response"
* )
* )
*
* @Route("/pricelist/departments", methods={"GET"})
*/
public function pricelistDepartments(Request $request): Response
{
$response = [];
$entityManager = $this->getDoctrine()->getManager();
$departments = $entityManager->getRepository(PriceDepartment::class)
->findAll();
if ($departments) {
foreach ($departments as $key => $item) {
$item = $item->toArray();
unset($item['__initializer__']);
unset($item['__isInitialized__']);
unset($item['__cloner__']);
unset($item['id']);
$response[$key] = $item;
}
}
return $this->json(['data' => $response]);
}
/**
* @OA\Get(
* tags= {"Услуги и цены"},
* path="/pricelist",
* summary="Получение списка услуг и цен",
* @OA\Parameter(
* name="depnum",
* description="ID отделения",
* in="query",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="filial",
* description="ID филиала",
* in="query",
* required=false,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="active",
* description="Только активные",
* in="query",
* required=false,
* @OA\Schema(
* type="boolean"
* )
* ),
* @OA\Response(
* response=200,
* description="json response"
* )
* )
*
* @Route("/pricelist", methods={"GET"})
*/
public function pricelist(Request $request, PaginatorInterface $paginator, PriceListService $priceListService): JsonResponse
{
$params = [
'kodoper' => $request->query->get('kodoper'),
'groupId' => $request->query->get('depnum'),
'filial' => $request->query->get('filial'),
'actual' => $request->query->get('active')
];
$priceListQuery = $priceListService->getPriceListQuery($params);
$pagination = $paginator->paginate(
$priceListQuery->getQuery(),
$request->query->getInt('page', 1),
1000
);
$totalItems = $pagination->getTotalItemCount(); // Общее количество элементов
$itemCount = $pagination->count(); // Количество элементов на текущей странице
$currentPage = $pagination->getCurrentPageNumber(); // Текущая страница
$totalPages = ceil($totalItems / 1000); // Общее количество страниц
return $this->json([
'items' => $pagination,
'totalItems' => $totalItems,
'totalPages' => $totalPages,
'currentPage' => $currentPage,
'itemCount' => $itemCount
]);
}
private function getSpecialistResponse($specialist)
{
$response = [];
if ($specialist) {
$response = $specialist->toArray();
unset($response['pecialistMore']);
$response['img'] = 'https://api.sovamed.ru/specialist/picture/' . $specialist->getId();
if (!empty($response['kinder'])) {
$response['kinder'] = $response['kinder'] . ' ' . $this->textYear($response['kinder'], false);
}
if (!empty($response['experience'])) {
$response['experience'] = $response['experience'] . ' ' . $this->textYear($response['experience'], true);
}
$specialistMore = $specialist->getSpecialistMore();
if ($defaultLocation = $specialistMore->defaultLocation()) {
$response['nearestDate'] = $defaultLocation['nearestDate'];
$response['filial'] = [
'id' => $defaultLocation['filial'],
'address' => $defaultLocation['address'],
];
$response['department'] = [
'id' => $defaultLocation['department'],
'name' => $defaultLocation['name'],
];
}
$response['reviews'] = $specialistMore->getReviews();
$response['prices'] = $specialistMore->getPrices();
}
return $response;
}
private function textYear($year, $exp = true)
{
$t1 = 0;
$t2 = 0;
$year = abs($year);
$t1 = $year % 10;
$t2 = $year % 100;
if ($exp) {
return ($t1 == 1 && $t2 != 11 ? "год" : ($t1 >= 2 && $t1 <= 4 && ($t2 < 10 || $t2 >= 20) ? "года" : "лет"));
} else {
return ($t1 == 1 ? "года" : "лет");
}
}
/**
* @OA\Get(
* tags= {"Врачи"},
* path="/doctor",
* summary="Получение данных о враче",
* @OA\Parameter(
* name="sid",
* description="ID врача",
* in="query",
* required=true,
* @OA\Schema(
* type="string"
* )
* ),
* @OA\Parameter(
* name="reviews",
* description="Показывать отзывы",
* in="query",
* required=false,
* @OA\Schema(
* type="boolean",
* default=false
* )
* ),
* @OA\Response(
* response=200,
* description="json response"
* )
* )
*
* @Route("/doctor", methods={"GET"})
*/
public function doctor(SpecialistService $specialistService, Request $request): Response
{
if (empty($request->query->getInt('sid'))) {
return $this->json(['data' => false]);
}
$specialist = $specialistService->show([
'dcode' => $request->query->get('sid')
]);
return $this->json(['data' => $this->getSpecialistResponse($specialist)]);
}
/**
* @OA\Get(
* tags= {"Врачи"},
* path="/doctors/{region}",
* summary="Получение данных врачей по регионам",
* @OA\Parameter(
* name="region",
* description="Название города",
* in="path",
* required=true,
* @OA\Schema(
* type="string",
* default="saratov"
* )
* ),
* @OA\Parameter(
* name="reviews",
* description="Показывать отзывы",
* in="query",
* required=false,
* @OA\Schema(
* type="boolean",
* default=true
* )
* ),
* @OA\Response(
* response=200,
* description="json response"
* )
* )
*
* @Route("/doctors/{region}", methods={"GET"})
*/
public function index(SpecialistService $specialistService, Request $request, $region = 'saratov'): Response
{
$regionId = match($region) {
'krasnodar' => 94,
'voronej' => 93,
'volgograd' => 92,
default => 91
};
$pagination = $specialistService->listPaginated(
['regionId' => $regionId],
$request->query->getInt('page', 1),
500
);
$totalItems = $pagination->getTotalItemCount(); // Общее количество элементов
$itemCount = $pagination->count(); // Количество элементов на текущей странице
$currentPage = $pagination->getCurrentPageNumber(); // Текущая страница
$totalPages = ceil($totalItems / 1000); // Общее количество страниц
$response = [];
foreach ($pagination as $key => $specialist) {
$response[$key] = $this->getSpecialistResponse($specialist);
}
return $this->json([
'data' => $response,
'totalItems' => $totalItems,
'totalPages' => $totalPages,
'currentPage' => $currentPage,
'itemCount' => $itemCount
]);
}
}
+80
View File
@@ -0,0 +1,80 @@
<?php
namespace App\Controller;
use App\Entity\ReviewSource;
use App\Form\ReviewSourceType;
use App\Repository\ReviewSourceRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @IsGranted("ROLE_ADMIN")
* @Route("admin/review_source")
*/
class ReviewSourceController extends AbstractController
{
/**
* @Route("/", name="app_review_source_index", methods={"GET"})
*/
public function index(ReviewSourceRepository $reviewSourceRepository): Response
{
return $this->render('review_source/index.html.twig', [
'review_sources' => $reviewSourceRepository->findAll(),
]);
}
/**
* @Route("/new", name="app_review_source_new", methods={"GET", "POST"})
*/
public function new(Request $request, ReviewSourceRepository $reviewSourceRepository): Response
{
$reviewSource = new ReviewSource();
$form = $this->createForm(ReviewSourceType::class, $reviewSource);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$reviewSourceRepository->add($reviewSource);
return $this->redirectToRoute('app_review_source_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('review_source/new.html.twig', [
'review_source' => $reviewSource,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}/edit", name="app_review_source_edit", methods={"GET", "POST"})
*/
public function edit(Request $request, ReviewSource $reviewSource, ReviewSourceRepository $reviewSourceRepository): Response
{
$form = $this->createForm(ReviewSourceType::class, $reviewSource);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$reviewSourceRepository->add($reviewSource);
return $this->redirectToRoute('app_review_source_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('review_source/edit.html.twig', [
'review_source' => $reviewSource,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}", name="app_review_source_delete", methods={"POST"})
*/
public function delete(Request $request, ReviewSource $reviewSource, ReviewSourceRepository $reviewSourceRepository): Response
{
if ($this->isCsrfTokenValid('delete'.$reviewSource->getId(), $request->request->get('_token'))) {
$reviewSourceRepository->remove($reviewSource);
}
return $this->redirectToRoute('app_review_source_index', [], Response::HTTP_SEE_OTHER);
}
}
+405
View File
@@ -0,0 +1,405 @@
<?php
namespace App\Controller;
use App\Entity\User;
use App\Bundle\Infoclinica\Region;
use App\Bundle\Infoclinica\Rest;
use App\Form\RegistrationFormType;
use App\Form\SettingType;
use App\Form\RefundType;
use App\Repository\UsrlogRepository;
use App\Entity\Usrlog;
use App\Security\LoginFormAuthenticator;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
class SecurityController extends AbstractController
{
public function __construct(CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
/**
* @IsGranted("ROLE_USER")
* @Route("/refund", name="security_refund", methods={"GET", "POST"})
*/
public function refund(Request $request): Response
{
$refundForm = new RefundType();
$form = $this->createForm(RefundType::class, $refundForm);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($request->request->get('filial') == 3) {
$to = 'info.mmc@sova.clinic, i.cherednichenko@sova.clinic, y.belova@sova.clinic';
$company_name = 'АО «Многопрофильный медицинский центр»';
$company_director = 'Бушеневой С.Н.';
$to_mail = 'vozvrat-vlg@sova.clinic';
} else {
$to = 'i.cherednichenko@sova.clinic, v.karpova@sova.clinic, n.ermakova@sova.clinic';
$company_name = 'АО «МЛДК»';
$company_director = 'Бурлаковой Н.Ф.';
$to_mail = 'vozvrat@sova.clinic';
}
$subject = "Пациент сформировал заявление на возврат средств по онлайн консультации";
$headers = 'From: ' . $request->request->get('email') . "\r\n" .
'Reply-To: ' . $request->request->get('email') . "\r\n" .
'X-Mailer: PHP/' . phpversion();
$message = "Здравствуйте. Пациент сформировал заявление на возврат средств по онлайн консультации. Ожидаем отправки заявления с почты пациента.\r\n Данные по консультации:\r\n";
$message .= 'ФИО пациента:' . $form->get('fio')->getData() ."\r\n";
$message .= 'Телефон пациента:' . $request->request->get('phone') ."\r\n";
$message .= 'Врач:' . $request->request->get('docName') ."\r\n";
$message .= 'Индификатор записи:' . $request->request->get('schedident') ."\r\n";
$message .= 'Сумма возврата:' . $form->get('sum')->getData() ."\r\n";
$message .= 'Дата платежа:' . $form->get('refund_date')->getData()->format('d.m.Y') ."\r\n";
mail($to, $subject, $message, $headers);
$html = $this->render('security/refund_blank.html.twig', [
'template' => Region::getTemplite(),
'to_email' => $to_mail,
'title' => 'Заявление на возврат',
'company_name' => $company_name,
'company_director' => $company_director,
'address' => $request->request->get('address'),
'phone' => $request->request->get('phone'),
'email' => $request->request->get('email'),
'current_date' => \date('Y-m-d'),
'fio' => $form->get('fio')->getData(),
'passport_serial' => explode(' ', $form->get('passport_serial')->getData())[0],
'passport_number' => explode(' ', $form->get('passport_serial')->getData())[1],
'passport_issued' => $form->get('passport_issued')->getData(),
'passport_date' => $form->get('passport_date')->getData()->format('d.m.Y'),
'refund_bases' => $form->get('refund_bases')->getData(),
'sum' => $form->get('sum')->getData(),
'refund_date' => $form->get('refund_date')->getData()->format('d.m.Y')
]);
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML($html);
$mpdf->Output();
}
return $this->render('security/refund_form.html.twig', [
'form' => $form->createView(),
]);
}
/**
* @IsGranted("ROLE_USER")
* @Route("/case-history", name="security_case_history")
*/
public function case_history(): Response
{
return $this->render('security/case_history.html.twig', [
'template' => Region::getTemplite(),
'title' => 'Приемы'
]);
}
/**
* @IsGranted("ROLE_USER")
* @Route("/referrals", name="security_referrals")
*/
public function referrals(): Response
{
$referrals = [];
return $this->render('security/referrals.html.twig', [
'referrals' => $referrals,
'template' => Region::getTemplite(),
'title' => 'Результаты анализов',
]);
}
/**
* @IsGranted("ROLE_USER")
* @Route("/security-card", name="security_card")
*/
public function securityCard(): Response
{
return $this->render('security/card.html.twig', [
'template' => Region::getTemplite(),
'title' => 'Медицинская карта',
]);
}
/**
* @IsGranted("ROLE_USER")
* @Route("/payment", name="security_payment")
*/
public function payment(): Response
{
return $this->render('security/payment.html.twig', [
'template' => Region::getTemplite(),
'title' => 'Финансы',
]);
}
/**
* @IsGranted("ROLE_USER")
* @Route("/setting", name="security_setting")
*/
public function setting(
Request $request,
UserPasswordEncoderInterface $passwordEncoder
): Response
{
$user = $this->getUser();
$form = $this->createForm(SettingType::class, $user);
$form->handleRequest($request);
$response = [];
if ($request->getMethod() == 'POST') {
$user->setToken($form->get('plainPassword')->getData());
$user->setPassword(
$passwordEncoder->encodePassword(
$user,
$form->get('plainPassword')->getData()
)
);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->json([
'success' => true,
'redirect' => '/'
]);
}
return $this->render('security/setting.html.twig', [
'template' => Region::getTemplite(),
'form' => $form->createView(),
'setting' => $response,
'title' => 'Настройки',
]);
}
/**
* @Route("/login", name="security_login")
*/
public function login(Request $request, AuthenticationUtils $authenticationUtils): Response
{
$template = preg_match('/sovamed\.ru/m', $request->getHost())? 'login' : 'login_wmtmed';
return $this->render('security/' . $template . '.html.twig', [
'template' => Region::getTemplite(),
'alias' => null,
'last_username' => $authenticationUtils->getLastUsername(),
'error' => $authenticationUtils->getLastAuthenticationError(),
'title' => 'Личный кабинет - «СОВА»'
]);
}
/**
* @Route("/logout", name="security_logout")
*/
public function logout()
{
}
/**
* @Route("/api/usrlog/logout", name="security_usrlog_logout", methods={"POST"})
*/
public function usrlogLogout(Request $request, UsrlogRepository $usrlogRepository): Response
{
$pcode = null;
$user = $this->getUser();
if ($user instanceof User) {
$pcode = (string) $user->getUid();
} else {
$pcode = trim((string) $request->request->get('pcode', ''));
}
if ($pcode === '') {
return $this->json(['success' => false, 'message' => 'pcode is required'], 400);
}
$usrlog = new Usrlog();
$usrlog
->setPcode($pcode)
->setAgent((string) ($request->headers->get('User-Agent') ?? 'unknown'))
->setClientIp((string) ($request->getClientIp() ?? 'unknown'))
->setMethod('выход')
;
$usrlogRepository->add($usrlog);
return $this->json(['success' => true]);
}
/**
* @Route("/registration", name="security_reg", methods={"GET","POST"})
*/
public function registration(
Request $request,
UserPasswordEncoderInterface $passwordEncoder
): Response
{
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$fullName = $form->get('firstName')->getData();
$fullName .= ' ';
$fullName .= $form->get('middleName')->getData();
$user->setFullName($fullName);
$user->setToken($form->get('plainPassword')->getData());
$user->setRoles(['ROLE_USER']);
$user->setConfirm(0);
$user->setPassword(
$passwordEncoder->encodePassword(
$user,
$form->get('plainPassword')->getData()
)
);
$infoclinica = new Rest();
$response = $infoclinica->register($request->request->all());
if ($response['response']['success'] == true) {
$user->setUid(date('U'));
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->redirectToRoute('security_confirm', [
'id' => $user->getId(),
'rToken' => $response['response']['data']['rToken']
]);
} else {
$this->addFlash(
'notice',
$response['response']['data']['message'] ?? 'Cервис временно не доступен!'
);
}
}
return $this->render('security/register.html.twig', [
'title' => 'Регистрация',
'template' => Region::getTemplite(),
'form' => $form->createView()
]);
}
/**
* @Route("/forget", name="security_forget", methods={"POST"})
*/
public function forget(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$entityManager = $this->getDoctrine()->getManager();
$email = false;
$uid = $request->request->get('uid');
if ($email = $request->request->get('login')) {
$user = $entityManager->getRepository(User::class)
->findOneBy(['email' => \bin2hex($email)]);
if ($user) {
$uid = $user->getUid();
}
return $this->json(['uid' => $uid]);
};
$password = $request->request->get('password');
if ($uid && $password) {
$user = $entityManager->getRepository(User::class)
->findOneBy(['uid' => $uid]);
if (!$user) {
$user = new User();
}
$user->setUid($uid);
$user->setToken($password);
$user->setPassword(
$passwordEncoder->encodePassword(
$user,
$password
)
);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
return $this->json([
'success' => true,
'redirect' => '/login'
]);
}
return $this->json([
'success' => false,
'uid' => $uid
]);
}
/**
* @Route("/api/authenticated", name="security_authenticated", methods={"POST"})
*/
public function authenticated(Request $request,
GuardAuthenticatorHandler $guardHandler,
LoginFormAuthenticator $authenticator,
UserPasswordEncoderInterface $passwordEncoder
): Response {
$entityManager = $this->getDoctrine()->getManager();
$userData = $request->request->get('user');
$user = $entityManager->getRepository(User::class)
->findOneBy(['uid' => $userData['id']]);
if (!$user && $userData) {
$user = new User();
$user
->setFullName($userData['fullName'])
->setEmail($userData['email'])
->setPhone($userData['phone'])
->setUid($userData['id'])
->setConfirm(1)
->setRoles(['ROLE_USER'])
->setToken($userData['id'])
->setPassword(
$passwordEncoder->encodePassword(
$user,
$userData['id']
)
);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$entityManager->clear();
}
return $guardHandler->authenticateUserAndHandleSuccess(
$user,
$request,
$authenticator,
'main'
);
}
}
+217
View File
@@ -0,0 +1,217 @@
<?php
namespace App\Controller;
use App\Service\SpecialistService;
use App\Entity\SpecialistView;
use App\Bundle\Infoclinica\Region;
use App\Bundle\Bitrix\Request as Bitrix;
use App\Form\SpecialistSearchType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
class SpecialistController extends AbstractController
{
/**
* @Route("/filter", name="specialist_filter", methods={"GET"})
*/
public function filter(Request $request): Response
{
$regionId = $request->cookies->getInt('region');
$regionId = ($regionId > 0) ? $regionId : null;
// Получаем значение kinder из запроса для фильтрации специализаций
$kinder = $request->query->get('specialist_search')['kinder'] ?? null;
$kinder = ($kinder == 1) ? 1 : null;
$searchForm = $this->createForm(SpecialistSearchType::class, new SpecialistView(), [
'action' => $this->generateUrl('specialist_index'),
'method' => 'GET',
'regionId' => $regionId,
'kinder' => $kinder,
]);
$searchForm->handleRequest($request);
return $this->render('specialist/_search_form.html.twig', [
'searchForm' => $searchForm->createView()
]);
}
/**
* @Route("/specialists/{alias?}", name="specialist_index", methods={"GET"})
*/
public function index(
SpecialistService $specialistService,
Request $request,
string $alias = null
): Response {
$regionId = $request->cookies->getInt('region');
$regionId = ($regionId > 0) ? $regionId : null;
// Получаем значение kinder из запроса для фильтрации специализаций
$kinder = $request->query->get('specialist_search')['kinder'] ?? null;
$kinder = ($kinder == 1) ? 1 : null;
$searchForm = $this->createForm(SpecialistSearchType::class, new SpecialistView(), [
'action' => $this->generateUrl('specialist_index', ['alias' => $alias]),
'method' => 'GET',
'regionId' => $regionId,
'kinder' => $kinder,
]);
$searchForm->handleRequest($request);
$page = $request->query->getInt('page', 1);
$filters = $request->query->get('specialist_search', ['onlineMode' => 0]);
$filters['depAlias'] = $alias;
if ($regionId > 0) {
$filters['regionId'] = $regionId;
}
$pagination = $specialistService->listPaginated($filters, $page, 10);
$view = 'specialist/index.html.twig';
if (Region::getTemplite() == 'krasnodar_base') {
$view = 'specialist/krasnodar_index.html.twig';
}
if (! empty($request->query->get('specialist_search')['current_date'])) {
$currentDate = $request->query->get('specialist_search')['current_date'];
$dates = explode('-', $currentDate);
$startInterval = $dates[0];
$endInterval = $dates[1];
} else {
$startInterval = date("Y-m-d");
$endInterval = date("Y-m-d", strtotime('+7 day'));
}
return $this->render($view, [
'title' => 'Врачи',
'alias' => $alias,
'template' => Region::getTemplite(),
'pagination' => $pagination,
'searchForm' => $searchForm->createView(),
'st' => $startInterval,
'en' => $endInterval
]);
}
/**
* @IsGranted("ROLE_USER")
* @Route("/online-specialists", name="specialist_online_index", methods={"GET"})
*/
public function onlineIndex(
SpecialistService $specialistService,
Request $request
): Response {
$regionId = $request->cookies->getInt('region');
$regionId = ($regionId > 0) ? $regionId : null;
// Получаем значение kinder из запроса для фильтрации специализаций
$kinder = $request->query->get('specialist_search')['kinder'] ?? null;
$kinder = ($kinder == 1) ? 1 : null;
$searchForm = $this->createForm(SpecialistSearchType::class, new SpecialistView(), [
'action' => $this->generateUrl('specialist_online_index'),
'method' => 'GET',
'regionId' => $regionId,
'kinder' => $kinder,
]);
$searchForm->handleRequest($request);
$filters = $request->query->get('specialist_search', ['onlineMode' => 1]);
$filters['onlineMode'] = 1;
if ($regionId > 0) {
$filters['regionId'] = $regionId;
}
$page = $request->query->getInt('page', 1);
$pagination = $specialistService->listPaginated($filters, $page, 10);
$view = 'specialist/index.html.twig';
if (Region::getTemplite() == 'krasnodar_base') {
$view = 'specialist/krasnodar_index.html.twig';
}
if (! empty($request->query->get('specialist_search')['current_date'])) {
$currentDate = $request->query->get('specialist_search')['current_date'];
$dates = explode('-', $currentDate);
$startInterval = $dates[0];
$endInterval = $dates[1];
} else {
$startInterval = date("Y-m-d");
$endInterval = date("Y-m-d", strtotime('+7 day'));
}
return $this->render($view, [
'title' => 'Онлайн консультация',
'template' => Region::getTemplite(),
'pagination' => $pagination,
'searchForm' => $searchForm->createView(),
'st' => $startInterval,
'en' => $endInterval
]);
}
/**
* @Route("/specialist/{alias}", name="specialist_show", methods={"GET"})
*/
public function show(
SpecialistService $specialistService,
Request $request,
string $alias
): Response {
$filters = $request->query->get('specialist_search', ['onlineMode' => 0]);
// $filters['regionId'] = $request->cookies->getInt('region');
$filters['alias'] = $alias;
$specialist = $specialistService->show($filters);
if ($specialist) {
$specialistMoreService = $specialist->getSpecialistMore();
if ($defaultLocation = $specialistMoreService->defaultLocation()) {
return $this->render('specialist/show.html.twig', [
'title' => 'Врач',
'st' => date("Y-m-d"),
'en' => date("Y-m-d", strtotime('+7 day')),
'template' => Region::getTemplite(),
'specialist' => $specialist,
'specialistMore' => $specialistMoreService,
]);
}
}
throw $this->createNotFoundException('The page does not exist');
}
/**
* @Route("/favorites", name="default_favorites")
*/
public function favorites(SpecialistService $specialistService, Request $request): Response
{
$page = $request->query->getInt('page', 1);
$filters['dcode'] = explode(',', $request->query->get('q'));
$pagination = $specialistService->listPaginated($filters, $page, 10);
return $this->render('base/favorites.html.twig', [
'st' => date("Y-m-d"),
'en' => date("Y-m-d", strtotime('+7 day')),
'pagination' => $pagination,
'template' => Region::getTemplite(),
'title' => 'Избранное'
]);
}
}
+159
View File
@@ -0,0 +1,159 @@
<?php
namespace App\Controller;
use App\Entity\Filial;
use App\Repository\FilialRepository;
use App\Entity\AlertSms;
use App\Repository\SpecialistViewRepository as SpecialistRepository;
use App\Repository\ReviewSourceRepository;
use App\Repository\LocationViewRepository as LocationRepository;
use App\Repository\RecordRepository;
use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Form\ReferenceType;
use App\Bundle\Infoclinica\Region;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use App\Bundle\Utils\Logger;
use App\Bundle\Sms\Manager as SmsManager;
use Symfony\Component\HttpFoundation\Request;
use App\Service\SpecialistService;
/**
* @Route("/widget")
*/
class WidgetController extends AbstractController
{
/**
* @Route("/review_source/{cityId}", name="widget_review_source", methods={"GET"})
*/
public function reviewSource(ReviewSourceRepository $reviewSourceRepository, $cityId): Response
{
$reviewSources = [];
foreach ($reviewSourceRepository->findByCity($cityId) as $key => $reviewSource) {
$reviewSources[$key] = $reviewSource;
$reviewSources[$key]['isFloat'] = true;
$f = (float) $reviewSource['rating_total'];
if (strpos($reviewSource['rating_total'], '.') === false) {
$reviewSources[$key]['isFloat'] = false;
}
}
return $this->render('widget/review_source.html.twig', [
'reviewSources' => $reviewSources,
]);
}
/**
* @Route("/reference", name="widget_reference")
*/
public function reference(Request $request): Response
{
$ref = $request->query->get('ref', '');
$regionId = match (base64_decode($ref, strict: true)) {
'https://volgograd.sovamed.ru' => 92,
'https://voronezh.sovamed.ru' => 93,
'https://wmtmed.ru' => 94,
default => 91,
};
$isAuthorized = $this->isGranted('ROLE_USER');
$referenceForm = $this->createForm(ReferenceType::class, new User, [
'method' => 'GET',
'isAuthorized' => $isAuthorized,
]);
return $this->render('widget/reference.html.twig', [
'regionId' => $regionId,
'referenceForm' => $referenceForm->createView()
]);
}
/**
* @Route("/check/{hash}/{id}", name="widget_check", methods={"GET"})
*/
public function check(
RecordRepository $recordRepository,
FilialRepository $filialRepository,
HttpClientInterface $client,
SpecialistService $specialistService,
$hash,
$id
): Response {
$record = $recordRepository->findOneBy(['hash' => $hash, 'id' => $id]);
if ($record) {
$reserve = $record->getReserve();
$reserve['date'] = \date('d-m-Y', strtotime($reserve['date']));
$sms = new SmsManager($client);
$msg = 'Ждем Вас: ';
$filial = $filialRepository->findOneBy(['fid' => $reserve['filial']]);
if ($filial) $msg .= $filial->getName() . ' ';
$msg .= $reserve['date'] . ' в '. $reserve['st'];
if (Region::getTemplite() == 'base') {
if (!$record->getAlertSms()) {
$response = $sms->sendSmsSova($record->getPhone(), $msg);
$alertSms = new AlertSms();
$alertSms
->setDateCreate(new \DateTime())
->setResponse(json_encode($response, JSON_UNESCAPED_UNICODE))
->setRecord($record);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($alertSms);
$entityManager->flush();
}
$html = '<img src="'
. $this->getParameter('public_directory')
. '/images/logo-sova.jpg" alt="logo" width="206"><hr>';
} else {
if (!$record->getAlertSms()) {
$response = $sms->sendSmsWmt($record->getPhone(), $msg);
$alertSms = new AlertSms();
$alertSms
->setDateCreate(new \DateTime())
->setResponse(json_encode($response, JSON_UNESCAPED_UNICODE))
->setRecord($record);
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($alertSms);
$entityManager->flush();
}
$html = '<img src="'
. $this->getParameter('public_directory')
. '/img/logo_wmt/logo-pdf.jpg" alt="logo" width="256"><hr>';
}
$specialist = $specialistService->show(['dcode' => $reserve['dcode']]);
if ($specialist) {
$html .= '<h2>' . $specialist->getName() . '</h2>';
}
$html .= '<p><b>Филиал:</b> ' . $filial->getName(). '</p>';
$html .= '<p><b>Дата приема:</b> '. $reserve['date'] . ' c '. $reserve['st']. ' по ' . $reserve['en'] .'</p>';
$html .= '<p><i>На Ваш номер отправлено смс с информацией о приеме</i></p>';
$mpdf = new \Mpdf\Mpdf();
$mpdf->WriteHTML($html);
$mpdf->Output();
}
throw $this->createNotFoundException('The event does not exist');
}
}
+230
View File
@@ -0,0 +1,230 @@
<?php
namespace App\Controller;
use App\Entity\WidgetForm;
use App\Entity\WidgetFormInput;
use App\Form\WidgetFormType;
use App\Repository\WidgetFormRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Form\WidgetFormInputType;
use Symfony\Component\HttpClient\CachingHttpClient;
use Symfony\Component\HttpKernel\HttpCache\Store;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use App\Bundle\Calltouch\Request as CalltouchRequest;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @Route("/widget/form")
*/
class WidgetFormController extends AbstractController
{
private $client;
public function __construct(HttpClientInterface $client, string $rootPath)
{
$store = new Store($rootPath . '/var/HttpClient');
$this->client = new CachingHttpClient($client, $store);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/", name="widget_form_index", methods={"GET"})
*/
public function index(WidgetFormRepository $widgetFormRepository): Response
{
return $this->render('widget_form/index.html.twig', [
'widget_forms' => $widgetFormRepository->findAll(),
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/new", name="widget_form_new", methods={"GET","POST"})
*/
public function new(Request $request): Response
{
$widgetForm = new WidgetForm();
$form = $this->createForm(WidgetFormType::class, $widgetForm);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($widgetForm);
$entityManager->flush();
return $this->redirectToRoute('widget_form_index');
}
return $this->render('widget_form/new.html.twig', [
'widget_form' => $widgetForm,
'form' => $form->createView(),
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/editor", name="widget_form_editor", methods={"GET"})
*/
public function editor(WidgetForm $widgetForm, Request $request, $id): Response
{
$widgetFormInput = new WidgetFormInput();
$form = $this->createForm(WidgetFormInputType::class, $widgetFormInput, [
'action' => $this->generateUrl('widget_form_input_new', ['id' => $widgetForm->getId()]),
'method' => 'POST',
]);
$form->handleRequest($request);
return $this->render('widget_form/editor.html.twig', [
'form_input' => $widgetForm->getWidgetFormInputs(),
'widget_form' => $widgetForm,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}", name="widget_form_show", methods={"GET", "POST"})
*/
public function show(Request $request, WidgetForm $widgetForm, $id): Response
{
$fields = [];
switch (base64_decode($request->query->get('ref') ?? $request->request->get('ref'))) {
case 'https://volgograd.sovamed.ru':
$regionId = 92;
$fields['UF_CRM_1539951158'] = 96;
// Волгоград
break;
case 'https://voronezh.sovamed.ru':
$regionId = 93;
$fields['UF_CRM_1539951158'] = 98;
// Воронеж
break;
case 'https://wmtmed.ru':
$regionId = 94;
$fields['UF_CRM_1539951158'] = 3018;
// Краснодар
break;
case 'https://sovenok.sovamed.ru':
$regionId = 95;
$fields['UF_CRM_1539951158'] = 94;
// Совенок
break;
case 'https://comfort.sovamed.ru':
$regionId = 96;
$fields['UF_CRM_1539951158'] = 94;
// Комфорт
break;
default:
$regionId = 91;
$fields['UF_CRM_1539951158'] = 94;
// Саратов
break;
}
if ($request->getMethod() == 'POST' && !empty($request->request->get('fields'))) {
$fields = array_merge($request->request->get('fields'), $fields);
$fields['ASSIGNED_BY_ID'] = 506;
if (!empty($fields['OPPORTUNITY']))
$fields['OPPORTUNITY'] = preg_replace('/[^0-9]/', '', $fields['OPPORTUNITY']);
$this->client->request('POST', $_ENV['BITRIX24_URL'], [
'verify_peer' => false,
'verify_host' => false,
'base_uri' => 'https://sovamed.bitrix24.ru',
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'User-Agent' => 'sovamed_bot',
],
'query' => ['fields' => $fields]
]);
$data = [
'requestNumber' => \md5(\time()),
'requestUrl' => $request->request->get('requestUrl'),
'requestDate' => \date('d-m-Y H:i:s'),
'subject' => $fields['TITLE'],
'sessionId' => $request->query->get('sessionId') ?? $request->request->get('sessionId'),
'phoneNumber' => $fields['PHONE'][0]['VALUE'],
'fio' => $fields['NAME'],
'tag' => str_replace(' ', '_', $fields['TITLE']),
];
if ($request->request->get('utm_source')
&& $request->request->get('utm_medium')
&& $request->request->get('utm_campaign')
&& $request->request->get('utm_content')
&& $request->request->get('utm_term')) {
$data['customSources'] = [
"source" => $request->request->get('utm_source'),
"medium" => $request->request->get('utm_medium'),
"campaign" => $request->request->get('utm_campaign'),
"content" => $request->request->get('utm_content'),
"term" => $request->request->get('utm_term')
];
}
$calltouch = new CalltouchRequest();
$calltouch->changeRegion($regionId);
$calltouch = $calltouch->create($data);
return $this->render('widget_form/show.html.twig', [
'widget_form' => $widgetForm,
'renderForm' => false
]);
}
return $this->render('widget_form/show.html.twig', [
'regionId' => $regionId,
'widget_form' => $widgetForm,
'renderForm' => true
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/edit", name="widget_form_edit", methods={"GET","POST"})
*/
public function edit(Request $request, WidgetForm $widgetForm): Response
{
$form = $this->createForm(WidgetFormType::class, $widgetForm);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('widget_form_index');
}
return $this->render('widget_form/edit.html.twig', [
'widget_form' => $widgetForm,
'form' => $form->createView(),
]);
}
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/{id}/delete", name="widget_form_delete", methods={"POST"})
*/
public function delete(Request $request, WidgetForm $widgetForm): Response
{
if ($this->isCsrfTokenValid('delete'.$widgetForm->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($widgetForm);
$entityManager->flush();
}
return $this->redirectToRoute('widget_form_index');
}
}
@@ -0,0 +1,75 @@
<?php
namespace App\Controller;
use App\Entity\WidgetForm;
use App\Entity\WidgetFormInput;
use App\Form\WidgetFormInputType;
use App\Repository\WidgetFormInputRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/widget/form/input")
*/
class WidgetFormInputController extends AbstractController
{
/**
* @param {id} = widgetForm.id
* @Route("/{id}/new", name="widget_form_input_new", methods={"POST"})
*/
public function new(WidgetForm $widgetForm, Request $request, $id): Response
{
$widgetFormInput = new WidgetFormInput();
$widgetFormInput->setWidgetForm($widgetForm);
$form = $this->createForm(WidgetFormInputType::class, $widgetFormInput);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($widgetFormInput);
$entityManager->flush();
return $this->redirectToRoute('widget_form_editor', ['id' => $id]);
}
}
/**
* @Route("/{id}/edit/{formId}", name="widget_form_input_edit", methods={"GET","POST"})
*/
public function edit(Request $request, WidgetFormInput $widgetFormInput, $formId): Response
{
$form = $this->createForm(WidgetFormInputType::class, $widgetFormInput);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('widget_form_editor', ['id' => $formId]);
}
return $this->render('widget_form_input/edit.html.twig', [
'widget_form_input' => $widgetFormInput,
'form' => $form->createView(),
]);
}
/**
* @Route("/{id}/{formId}", name="widget_form_input_delete", methods={"POST"})
*/
public function delete(Request $request, WidgetFormInput $widgetFormInput, $formId): Response
{
if ($this->isCsrfTokenValid('delete'.$widgetFormInput->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($widgetFormInput);
$entityManager->flush();
}
return $this->redirectToRoute('widget_form_editor', ['id' => $formId]);
}
}
View File
+75
View File
@@ -0,0 +1,75 @@
<?php
namespace App\Entity;
use App\Repository\AlertSmsRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=AlertSmsRepository::class)
*/
class AlertSms
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\OneToOne(targetEntity=Record::class, inversedBy="alertSms", cascade={"persist", "remove"})
*/
private $record;
/**
* @ORM\Column(type="datetime")
*/
private $dateCreate;
/**
* @ORM\Column(type="text")
*/
private $response;
public function getId(): ?int
{
return $this->id;
}
public function getRecord(): ?Record
{
return $this->record;
}
public function setRecord(?Record $record): self
{
$this->record = $record;
return $this;
}
public function getDateCreate(): ?\DateTimeInterface
{
return $this->dateCreate;
}
public function setDateCreate(\DateTimeInterface $dateCreate): self
{
$this->dateCreate = $dateCreate;
return $this;
}
public function getResponse(): ?string
{
return $this->response;
}
public function setResponse(string $response): self
{
$this->response = $response;
return $this;
}
}
+93
View File
@@ -0,0 +1,93 @@
<?php
namespace App\Entity;
use App\Repository\BannerRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=BannerRepository::class)
*/
class Banner
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $href;
/**
* @ORM\Column(type="string", length=255)
*/
private $src;
/**
* @ORM\Column(type="boolean")
*/
private $active;
/**
* @ORM\OneToOne(targetEntity=City::class, inversedBy="banner")
* @ORM\JoinColumn(nullable=false)
*/
private $city;
public function getId(): ?int
{
return $this->id;
}
public function getHref(): ?string
{
return $this->href;
}
public function setHref(string $href): self
{
$this->href = $href;
return $this;
}
public function getSrc(): ?string
{
return $this->src;
}
public function setSrc(string $src): self
{
$this->src = $src;
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getCity(): ?City
{
return $this->city;
}
public function setCity(City $city): self
{
$this->city = $city;
return $this;
}
}
+100
View File
@@ -0,0 +1,100 @@
<?php
namespace App\Entity;
use App\Repository\CategoryPageRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=CategoryPageRepository::class)
*/
class CategoryPage
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="boolean", length=255)
*/
private $active;
/**
* @ORM\OneToMany(targetEntity=Page::class, mappedBy="category", orphanRemoval=true)
*/
private $pages;
public function __construct()
{
$this->pages = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
/**
* @return Collection|Page[]
*/
public function getPages(): Collection
{
return $this->pages;
}
public function addPage(Page $page): self
{
if (!$this->pages->contains($page)) {
$this->pages[] = $page;
$page->setCategory($this);
}
return $this;
}
public function removePage(Page $page): self
{
if ($this->pages->removeElement($page)) {
// set the owning side to null (unless already changed)
if ($page->getCategory() === $this) {
$page->setCategory(null);
}
}
return $this;
}
}
+175
View File
@@ -0,0 +1,175 @@
<?php
namespace App\Entity;
use App\Repository\CityRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=CityRepository::class)
*/
class City
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="integer")
*/
private $regionId;
/**
* @ORM\Column(type="integer")
*/
private $timeZone;
/**
* @ORM\OneToMany(targetEntity=ReviewSource::class, mappedBy="city")
*/
private $reviewSources;
/**
* @ORM\OneToMany(targetEntity=Filial::class, mappedBy="city")
*/
private $filials;
/**
* @ORM\OneToOne(targetEntity=Banner::class, mappedBy="city")
*/
private $banner;
public function __construct()
{
$this->filials = new ArrayCollection();
$this->reviewSources = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getTimeZone(): ?int
{
return $this->timeZone;
}
public function setTimeZone(int $timeZone): self
{
$this->timeZone = $timeZone;
return $this;
}
public function getRegionId(): ?int
{
return $this->regionId;
}
public function setRegionId(int $regionId): self
{
$this->regionId = $regionId;
return $this;
}
public function getBanner(): ?Banner
{
return $this->banner;
}
public function setBanner(Banner $banner): self
{
// set the owning side of the relation if necessary
if ($banner->getCity() !== $this) {
$banner->setCity($this);
}
$this->banner = $banner;
return $this;
}
/**
* @return Collection<int, Filial>
*/
public function getFilials(): Collection
{
return $this->filials;
}
public function addFilial(Filial $filial): static
{
if (!$this->filials->contains($filial)) {
$this->filials->add($filial);
$filial->setCity($this);
}
return $this;
}
public function removeFilial(Filial $filial): static
{
if ($this->filials->removeElement($filial)) {
// set the owning side to null (unless already changed)
if ($filial->getCity() === $this) {
$filial->setCity(null);
}
}
return $this;
}
/**
* @return Collection<int, ReviewSource>
*/
public function getReviewSources(): Collection
{
return $this->reviewSources;
}
public function addReviewSource(ReviewSource $reviewSource): static
{
if (!$this->reviewSources->contains($reviewSource)) {
$this->reviewSources->add($reviewSource);
$reviewSource->setCity($this);
}
return $this;
}
public function removeReviewSource(ReviewSource $reviewSource): static
{
if ($this->reviewSources->removeElement($reviewSource)) {
// set the owning side to null (unless already changed)
if ($reviewSource->getCity() === $this) {
$reviewSource->setCity(null);
}
}
return $this;
}
}
+159
View File
@@ -0,0 +1,159 @@
<?php
namespace App\Entity;
use App\Repository\DepartmentRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=DepartmentRepository::class)
*/
class Department
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $did;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
*/
private $groupName;
/**
* @ORM\Column(type="boolean")
*/
private $onlineMode;
/**
* @ORM\Column(type="string", length=255)
*/
private $alias;
/**
* @ORM\Column(type="boolean", options={"default" : true})
*/
private $active;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $middleName;
public function getId(): ?int
{
return $this->id;
}
public function getDid(): ?int
{
return $this->did;
}
public function setDid(string $did): self
{
$this->did = $did;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getGroupName(): ?string
{
return $this->groupName;
}
public function setGroupName(string $groupName): self
{
$this->groupName = $groupName;
return $this;
}
public function getOnlineMode(): ?bool
{
return $this->onlineMode;
}
public function setOnlineMode(bool $onlineMode): self
{
$this->onlineMode = $onlineMode;
return $this;
}
public function getAlias(): ?string
{
return $this->alias;
}
public function setAlias(string $alias): self
{
$this->alias = $alias;
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getMiddleName(): ?string
{
return $this->middleName;
}
public function setMiddleName(?string $middleName): self
{
$this->middleName = $middleName;
return $this;
}
public function isOnlineMode(): ?bool
{
return $this->onlineMode;
}
public function isActive(): ?bool
{
return $this->active;
}
public function toArray() {
return get_object_vars($this);
}
}
+75
View File
@@ -0,0 +1,75 @@
<?php
namespace App\Entity;
use App\Repository\DirectCompanyRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=DirectCompanyRepository::class)
*/
class DirectCompany
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="bigint")
*/
private $companyId;
/**
* @ORM\Column(type="string", length=255)
*/
private $city;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getCompanyId(): ?string
{
return $this->companyId;
}
public function setCompanyId(string $companyId): self
{
$this->companyId = $companyId;
return $this;
}
public function getCity(): ?string
{
return $this->city;
}
public function setCity(string $city): self
{
$this->city = $city;
return $this;
}
}
+160
View File
@@ -0,0 +1,160 @@
<?php
namespace App\Entity;
use App\Repository\DirectReportRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=DirectReportRepository::class)
*/
class DirectReport
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="date")
*/
private $date;
/**
* @ORM\Column(type="bigint")
*/
private $adGroupId;
/**
* @ORM\Column(type="bigint")
*/
private $campaignId;
/**
* @ORM\Column(type="bigint")
*/
private $adId;
/**
* @ORM\Column(type="string", length=255)
*/
private $impressions;
/**
* @ORM\Column(type="integer")
*/
private $clicks;
/**
* @ORM\Column(type="integer")
*/
private $cost;
/**
* @ORM\Column(type="string", length=255)
*/
private $conversions;
public function getId(): ?int
{
return $this->id;
}
public function getDate(): ?\DateTimeInterface
{
return $this->date;
}
public function setDate(\DateTimeInterface $date): self
{
$this->date = $date;
return $this;
}
public function getAdGroupId(): ?string
{
return $this->adGroupId;
}
public function setAdGroupId(string $adGroupId): self
{
$this->adGroupId = $adGroupId;
return $this;
}
public function getCampaignId(): ?string
{
return $this->campaignId;
}
public function setCampaignId(string $campaignId): self
{
$this->campaignId = $campaignId;
return $this;
}
public function getAdId(): ?string
{
return $this->adId;
}
public function setAdId(string $adId): self
{
$this->adId = $adId;
return $this;
}
public function getImpressions(): ?string
{
return $this->impressions;
}
public function setImpressions(string $impressions): self
{
$this->impressions = $impressions;
return $this;
}
public function getClicks(): ?int
{
return $this->clicks;
}
public function setClicks(int $clicks): self
{
$this->clicks = $clicks;
return $this;
}
public function getCost(): ?int
{
return $this->cost;
}
public function setCost(int $cost): self
{
$this->cost = $cost;
return $this;
}
public function getConversions(): ?string
{
return $this->conversions;
}
public function setConversions(string $conversions): self
{
$this->conversions = $conversions;
return $this;
}
}
+207
View File
@@ -0,0 +1,207 @@
<?php
namespace App\Entity;
use App\Repository\FilialRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=FilialRepository::class)
*/
class Filial
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $fid;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
*/
private $address;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $addressName;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $siteId;
/**
* @ORM\ManyToOne(targetEntity=City::class, inversedBy="filials")
*/
private $city;
/**
* @ORM\OneToMany(targetEntity=ReviewSource::class, mappedBy="filial", cascade={"persist", "remove"})
*/
private $reviewSources;
/**
* @ORM\Column(type="boolean", options={"default" : true})
*/
private $active;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $company;
public function __construct()
{
$this->reviewSources = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getFid(): ?string
{
return $this->fid;
}
public function setFid(string $fid): self
{
$this->fid = $fid;
return $this;
}
public function getSiteId(): ?int
{
return $this->siteId;
}
public function setSiteId(string $siteId): self
{
$this->siteId = $siteId;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getAddress(): ?string
{
return $this->address;
}
public function setAddress(string $address): self
{
$this->address = $address;
return $this;
}
public function getAddressName(): ?string
{
return $this->addressName;
}
public function setAddressName(?string $addressName): self
{
$this->addressName = $addressName;
return $this;
}
public function getCity(): ?City
{
return $this->city;
}
public function setCity(?City $city): self
{
$this->city = $city;
return $this;
}
/**
* @return Collection<int, ReviewSource>
*/
public function getReviewSources(): Collection
{
return $this->reviewSources;
}
public function addReviewSource(ReviewSource $reviewSource): self
{
if (!$this->reviewSources->contains($reviewSource)) {
$this->reviewSources[] = $reviewSource;
$reviewSource->setFilial($this);
}
return $this;
}
public function removeReviewSource(ReviewSource $reviewSource): self
{
if ($this->reviewSources->removeElement($reviewSource)) {
// set the owning side to null (unless already changed)
if ($reviewSource->getFilial() === $this) {
$reviewSource->setFilial(null);
}
}
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getCompany(): ?string
{
return $this->company;
}
public function setCompany(string $company): self
{
$this->company = $company;
return $this;
}
public function isActive(): ?bool
{
return $this->active;
}
}
+96
View File
@@ -0,0 +1,96 @@
<?php
namespace App\Entity;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="location_view")
*/
class LocationView
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $dcode;
/**
* @ORM\Column(type="integer")
*/
private $department;
/**
* @ORM\Column(type="integer")
*/
private $filial;
/**
* @ORM\Column(type="integer", name="specialist_id")
*/
private $specialistId;
/**
* @ORM\Column(type="boolean")
*/
private $onlineMode;
/**
* @ORM\Column(type="boolean")
*/
private $active;
/**
* @var datetime $nearestDate
*
* @ORM\Column(type="date", nullable = true)
*/
private $nearestDate;
public function getId(): ?int
{
return $this->id;
}
public function getDcode(): ?int
{
return $this->dcode;
}
public function getDepartment(): ?int
{
return $this->department;
}
public function getFilial(): ?int
{
return $this->filial;
}
public function getSpecialistId(): ?int
{
return $this->specialistId;
}
public function isOnlineMode(): ?bool
{
return $this->onlineMode;
}
public function isActive(): ?bool
{
return $this->active;
}
public function getNearestDate(): ?\DateTimeInterface
{
return $this->nearestDate;
}
}
+110
View File
@@ -0,0 +1,110 @@
<?php
namespace App\Entity;
use App\Repository\PageRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=PageRepository::class)
*/
class Page
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="text")
*/
private $description;
/**
* @ORM\Column(type="boolean")
*/
private $active;
/**
* @ORM\Column(type="string", length=255)
*/
private $alias;
/**
* @ORM\ManyToOne(targetEntity=CategoryPage::class, inversedBy="pages")
* @ORM\JoinColumn(nullable=false)
*/
private $category;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): self
{
$this->description = $description;
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getAlias(): ?string
{
return $this->alias;
}
public function setAlias(string $alias): self
{
$this->alias = $alias;
return $this;
}
public function getCategory(): ?CategoryPage
{
return $this->category;
}
public function setCategory(?CategoryPage $category): self
{
$this->category = $category;
return $this;
}
}
+96
View File
@@ -0,0 +1,96 @@
<?php
namespace App\Entity;
use App\Repository\PriceRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=PriceRepository::class)
*/
class Price
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="integer")
*/
private $value;
/**
* @ORM\Column(type="string", length=255)
*/
private $propertyValueId;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $dateUpdate;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getValue(): ?int
{
return $this->value;
}
public function setValue(int $value): self
{
$this->value = $value;
return $this;
}
public function getPropertyValueId(): ?string
{
return $this->value;
}
public function setPropertyValueId(string $propertyValueId): self
{
$this->propertyValueId = $propertyValueId;
return $this;
}
public function toArray() {
return get_object_vars($this);
}
public function getDateUpdate(): ?\DateTimeInterface
{
return $this->dateUpdate;
}
public function setDateUpdate(\DateTimeInterface $dateUpdate): self
{
$this->dateUpdate = $dateUpdate;
return $this;
}
}
+116
View File
@@ -0,0 +1,116 @@
<?php
namespace App\Entity;
use App\Repository\PriceDepartmentRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=PriceDepartmentRepository::class)
*/
class PriceDepartment
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $name;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $groupId;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $groupName;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $doctCount;
/**
* @ORM\Column(type="boolean")
*/
private $viewInWeb;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
public function getGroupId(): ?int
{
return $this->groupId;
}
public function setGroupId(?int $groupId): self
{
$this->groupId = $groupId;
return $this;
}
public function getGroupName(): ?string
{
return $this->groupName;
}
public function setGroupName(?string $groupName): self
{
$this->groupName = $groupName;
return $this;
}
public function getDoctCount(): ?int
{
return $this->doctCount;
}
public function setDoctCount(?int $doctCount): self
{
$this->doctCount = $doctCount;
return $this;
}
public function getViewInWeb(): ?bool
{
return $this->viewInWeb;
}
public function setViewInWeb(bool $viewInWeb): self
{
$this->viewInWeb = $viewInWeb;
return $this;
}
public function toArray() {
return get_object_vars($this);
}
}
+297
View File
@@ -0,0 +1,297 @@
<?php
namespace App\Entity;
use App\Repository\PriceListRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=PriceListRepository::class)
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="price_list_view")
*/
class PriceList
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $kodoper;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $schname;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $specname;
/**
* @ORM\Column(type="bigint", nullable=true)
*/
private $speccode;
/**
* @ORM\Column(type="json", nullable=true)
*/
private $priceInfo = [];
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $discpercent;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $discprice;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $structname;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $fname;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $filial;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $comment;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $mediaId;
/**
* @ORM\Column(type="datetime")
*/
private $dateUpdate;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $groupId;
public function getId(): ?int
{
return $this->id;
}
public function getKodoper(): ?string
{
return $this->kodoper;
}
public function getSchname(): ?string
{
return $this->schname;
}
public function getSpecname(): ?string
{
return $this->specname;
}
public function getSpeccode(): ?string
{
return $this->speccode;
}
public function getPriceInfo(): ?array
{
return $this->priceInfo;
}
public function getDiscpercent(): ?string
{
return $this->discpercent;
}
public function getDiscprice(): ?string
{
return $this->discprice;
}
public function getStructname(): ?string
{
return $this->structname;
}
public function getFname(): ?string
{
return $this->fname;
}
public function getFilial(): ?int
{
return $this->filial;
}
public function getComment(): ?string
{
return $this->comment;
}
public function getMediaId(): ?int
{
return $this->mediaId;
}
public function getDateUpdate(): ?\DateTimeInterface
{
return $this->dateUpdate;
}
public function getGroupId(): ?int
{
return $this->groupId;
}
public function getActive(): bool
{
if ($this->dateUpdate === null) {
return false;
}
$twoDaysAgo = (new \DateTime())->modify('-2 days');
return $this->dateUpdate >= $twoDaysAgo;
}
public function setKodoper(?string $kodoper): static
{
$this->kodoper = $kodoper;
return $this;
}
public function setSchname(?string $schname): static
{
$this->schname = $schname;
return $this;
}
public function setSpecname(?string $specname): static
{
$this->specname = $specname;
return $this;
}
public function setSpeccode(?string $speccode): static
{
$this->speccode = $speccode;
return $this;
}
public function setPriceInfo(?array $priceInfo): static
{
$this->priceInfo = $priceInfo;
return $this;
}
public function setDiscpercent(?string $discpercent): static
{
$this->discpercent = $discpercent;
return $this;
}
public function setDiscprice(?string $discprice): static
{
$this->discprice = $discprice;
return $this;
}
public function setStructname(?string $structname): static
{
$this->structname = $structname;
return $this;
}
public function setFname(?string $fname): static
{
$this->fname = $fname;
return $this;
}
public function setFilial(?int $filial): static
{
$this->filial = $filial;
return $this;
}
public function setComment(?string $comment): static
{
$this->comment = $comment;
return $this;
}
public function setMediaId(?int $mediaId): static
{
$this->mediaId = $mediaId;
return $this;
}
public function setDateUpdate(\DateTimeInterface $dateUpdate): static
{
$this->dateUpdate = $dateUpdate;
return $this;
}
public function setGroupId(?int $groupId): static
{
$this->groupId = $groupId;
return $this;
}
public function toArray(): array
{
return [
'kodoper' => $this->getKodoper(),
'schname' => $this->getSchname(),
'specname' => $this->getSpecname(),
'speccode' => $this->getSpeccode(),
'priceInfo' => $this->getPriceInfo(),
'discpercent' => $this->getDiscpercent(),
'discprice' => $this->getDiscprice(),
'structname' => $this->getStructname(),
'fname' => $this->getFname(),
'filial' => $this->getFilial(),
'comment' => $this->getComment(),
'mediaId' => $this->getMediaId(),
'dateUpdate' => $this->getDateUpdate() ? $this->getDateUpdate()->format('Y-m-d H:i:s') : null,
'groupId' => $this->getGroupId(),
'active' => $this->getActive()
];
}
}
+137
View File
@@ -0,0 +1,137 @@
<?php
namespace App\Entity;
use App\Repository\RecordRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Bundle\Crypt\AES;
/**
* @ORM\Entity(repositoryClass=RecordRepository::class)
*/
class Record
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $specialistId;
/**
* @ORM\Column(type="string", length=255)
*/
private $phone;
/**
* @ORM\Column(type="datetime")
*/
private $createAt;
/**
* @ORM\Column(type="string", length=255)
*/
private $hash;
/**
* @ORM\Column(type="array")
*/
private $reserve = [];
/**
* @ORM\OneToOne(targetEntity=AlertSms::class, mappedBy="record", cascade={"persist", "remove"})
*/
private $alertSms;
public function getId(): ?int
{
return $this->id;
}
public function getSpecialistId(): ?int
{
return $this->specialistId;
}
public function setSpecialistId(int $specialistId): self
{
$this->specialistId = $specialistId;
return $this;
}
public function getPhone(): ?string
{
return !empty($this->phone)? AES::decrypt($this->phone): $this->phone;
}
public function setPhone(string $phone): self
{
$this->phone = AES::encrypt($phone);
return $this;
}
public function getCreateAt(): ?\DateTimeInterface
{
return $this->createAt;
}
public function setCreateAt(\DateTimeInterface $createAt): self
{
$this->createAt = $createAt;
return $this;
}
public function getHash(): ?string
{
return $this->hash;
}
public function setHash(string $hash): self
{
$this->hash = md5($hash);
return $this;
}
public function getReserve(): ?array
{
return $this->reserve;
}
public function setReserve(array $reserve): self
{
$this->reserve = $reserve;
return $this;
}
public function getAlertSms(): ?AlertSms
{
return $this->alertSms;
}
public function setAlertSms(?AlertSms $alertSms): self
{
// unset the owning side of the relation if necessary
if ($alertSms === null && $this->alertSms !== null) {
$this->alertSms->setRecord(null);
}
// set the owning side of the relation if necessary
if ($alertSms !== null && $alertSms->getRecord() !== $this) {
$alertSms->setRecord($this);
}
$this->alertSms = $alertSms;
return $this;
}
}
+167
View File
@@ -0,0 +1,167 @@
<?php
namespace App\Entity;
use App\Repository\ReviewRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="remote_review")
* @ORM\Entity(repositoryClass=ReviewRepository::class)
*/
class Review
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $externalId;
/**
* @ORM\Column(type="integer")
*/
private $specialistId;
/**
* @ORM\Column(type="boolean")
*/
private $active;
/**
* @ORM\Column(type="date")
*/
private $dateCreate;
/**
* @ORM\Column(type="text")
*/
private $message;
/**
* @ORM\Column(type="string", length=255)
*/
private $author;
/**
* @ORM\Column(type="float")
*/
private $rating;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $source;
public function getId(): ?int
{
return $this->id;
}
public function getBitrixId(): ?int
{
return $this->externalId;
}
public function setBitrixId(int $externalId): self
{
$this->externalId = $externalId;
return $this;
}
public function getSpecialistId(): ?int
{
return $this->specialistId;
}
public function setSpecialistId(int $specialistId): self
{
$this->specialistId = $specialistId;
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getDateCreate(): ?\DateTimeInterface
{
return $this->dateCreate;
}
public function setDateCreate(\DateTimeInterface $dateCreate): self
{
$this->dateCreate = $dateCreate;
return $this;
}
public function getMessage(): ?string
{
return $this->message;
}
public function setMessage(string $message): self
{
$this->message = $message;
return $this;
}
public function getAuthor(): ?string
{
return $this->author;
}
public function setAuthor(string $author): self
{
$this->author = $author;
return $this;
}
public function getRating(): ?float
{
return $this->rating;
}
public function setRating(float $rating): self
{
$this->rating = $rating;
return $this;
}
public function getSource(): ?string
{
return $this->source;
}
public function setSource(?string $source): self
{
$this->source = $source;
return $this;
}
public function toArray() {
return get_object_vars($this);
}
}
+150
View File
@@ -0,0 +1,150 @@
<?php
namespace App\Entity;
use App\Repository\ReviewSourceRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=ReviewSourceRepository::class)
*/
class ReviewSource
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=City::class, inversedBy="reviewSources")
* @ORM\JoinColumn(nullable=false)
*/
private $city;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="integer")
*/
private $countRow;
/**
* @ORM\Column(type="boolean")
*/
private $active;
/**
* @ORM\Column(type="float")
*/
private $rating;
/**
* @ORM\ManyToOne(targetEntity=Filial::class, inversedBy="reviewSources")
*/
private $filial;
/**
* @ORM\Column(type="date")
*/
private $dateCreate;
public function getId(): ?int
{
return $this->id;
}
public function getCity(): ?City
{
return $this->city;
}
public function setCity(City $city): self
{
$this->city = $city;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getCountRow(): ?int
{
return $this->countRow;
}
public function setCountRow(int $countRow): self
{
$this->countRow = $countRow;
return $this;
}
public function getActive(): ?bool
{
return $this->active;
}
public function setActive(bool $active): self
{
$this->active = $active;
return $this;
}
public function getRating(): ?float
{
return $this->rating;
}
public function setRating(float $rating): self
{
$this->rating = $rating;
return $this;
}
public function getDateCreate(): ?\DateTimeInterface
{
return $this->dateCreate;
}
public function setDateCreate(\DateTimeInterface $dateCreate): self
{
$this->dateCreate = $dateCreate;
return $this;
}
public function isActive(): ?bool
{
return $this->active;
}
public function getFilial(): ?Filial
{
return $this->filial;
}
public function setFilial(?Filial $filial): static
{
$this->filial = $filial;
return $this;
}
}
+233
View File
@@ -0,0 +1,233 @@
<?php
namespace App\Entity;
use App\Entity\LocationView;
use App\Service\SpecialistMoreService;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="specialist_view")
*/
class SpecialistView
{
/**
* @ORM\Id
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $kinder;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $speciality;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $category;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $experience;
/**
* @ORM\Column(type="text", nullable=true)
*/
private $description;
/**
* @ORM\Column(type="boolean")
*/
private $infoclinica;
/**
* @ORM\Column(type="string", length=255)
*/
private $alias;
/**
* @ORM\Column(type="string", length=255)
*/
private $dcode;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $sType;
/**
* @ORM\Column(type="boolean")
*/
private $active;
/**
* @ORM\Column(type="integer", nullable=true)
*/
private $regionId;
/**
* @ORM\Column(type="json", nullable=true)
*/
private $kodoper;
/**
* @var datetime $updated
*
* @ORM\Column(type="datetime", nullable = true)
*/
private $updated;
/**
* @ORM\Column(type="boolean")
*/
private $acceptsDms;
/**
* @ORM\Column(type="string", length=255)
*/
private $degree;
private SpecialistMoreService $specialistMoreService;
public function getUpdated()
{
return $this->updated;
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function getFio(): ?array
{
$fio = explode(' ', trim($this->name));
if (count($fio) < 3) {
$fio[] = '';
}
return $fio;
}
public function getKinder(): ?string
{
return $this->kinder;
}
public function getSpeciality(): ?string
{
return $this->speciality;
}
public function getCategory(): ?string
{
return $this->category;
}
public function getExperience(): ?string
{
return $this->experience;
}
public function getDescription(): ?string
{
return $this->description;
}
public function getImg(): ?string
{
return $this->id;
}
public function getAlias(): ?string
{
return $this->alias;
}
public function getDcode(): ?string
{
return $this->dcode;
}
public function getSType(): ?int
{
return $this->sType;
}
public function isActive(): bool
{
return $this->active;
}
public function isAcceptsDms(): ?bool
{
return $this->acceptsDms;
}
public function isInfoclinica(): ?bool
{
return $this->infoclinica;
}
public function getRegionId(): ?int
{
return $this->regionId;
}
public function getDegree(): ?string
{
return $this->degree;
}
public function getKodoper(): ?array
{
return $this->kodoper;
}
public function addSpecialistMoreService(
SpecialistMoreService $specialistMoreService
): void {
$this->specialistMoreService = $specialistMoreService;
}
public function getSpecialistMore(): SpecialistMoreService
{
return $this->specialistMoreService->setSpecialist($this->id, $this->kodoper);
}
public function toArray()
{
return [
'name' => $this->getName(),
'kinder' => $this->getKinder(),
'experience' => $this->getExperience(),
'category' => $this->getCategory(),
'description' => $this->getDescription(),
'speciality' => $this->getSpeciality(),
'alias' => $this->getAlias(),
'isAcceptsDms' => $this->isAcceptsDms(),
'degree' => $this->getDegree(),
'updated' => $this->getUpdated()
];
}
}
+268
View File
@@ -0,0 +1,268 @@
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use App\Bundle\Crypt\AES;
/**
* @ORM\Table(name="users")
* @ORM\Entity(repositoryClass=UserRepository::class)
* @UniqueEntity(fields={"uid"}, message="There is already an account with this uid")
*/
class User implements UserInterface
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=180, nullable=true)
*/
private $email;
/**
* @ORM\Column(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string", nullable=true)
*/
private $password;
/**
* @ORM\Column(type="integer", unique=true)
*/
private $uid;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $token;
/**
* @ORM\Column(type="string", length=255)
*/
private $fullName;
/**
* @ORM\Column(type="string", length=255, nullable=true)
*/
private $phone;
/**
* @ORM\Column(type="boolean")
*/
private $confirm;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $createdAt;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private $lastActivityAt;
public function __construct()
{
$this->calltouches = new ArrayCollection();
$this->createdAt = new \DateTime();
$this->lastActivityAt = new \DateTime();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return \hex2bin($this->email);
}
public function setEmail(string $email): self
{
$this->email = \bin2hex($email);
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
{
return (string) \hex2bin($this->email);
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* Получает реальные роли пользователя без автоматически добавленного ROLE_USER
*
* @return array
*/
public function getActualRoles(): array
{
return $this->roles;
}
/**
* @see UserInterface
*/
public function getPassword(): string
{
return $this->password ?? '';
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* Returning a salt is only needed, if you are not using a modern
* hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
*
* @see UserInterface
*/
public function getSalt(): ?string
{
return null;
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getUid(): ?int
{
return $this->uid ?? 0;
}
public function setUid(?int $uid): self
{
$this->uid = $uid;
return $this;
}
public function getToken(): ?string
{
return !empty($this->token)? AES::decrypt($this->token): $this->token;
}
public function setToken(string $token): self
{
$this->token = AES::encrypt($token);
return $this;
}
public function getFullName(): ?string
{
return !empty($this->fullName)? AES::decrypt($this->fullName): $this->fullName;
}
public function setFullName(string $fullName): self
{
$this->fullName = AES::encrypt($fullName);
return $this;
}
public function getPhone(): ?string
{
return !empty($this->phone)? AES::decrypt($this->phone): $this->phone;
}
public function setPhone(string $phone): self
{
$this->phone = AES::encrypt($phone);
return $this;
}
public function getConfirm(): ?bool
{
return $this->confirm;
}
public function setConfirm(bool $confirm): self
{
$this->confirm = $confirm;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(?\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
public function getLastActivityAt(): ?\DateTimeInterface
{
return $this->lastActivityAt;
}
public function setLastActivityAt(?\DateTimeInterface $lastActivityAt): self
{
$this->lastActivityAt = $lastActivityAt;
return $this;
}
/**
* Обновляет время последней активности пользователя
*/
public function updateLastActivity(): self
{
$this->lastActivityAt = new \DateTime();
return $this;
}
}
+109
View File
@@ -0,0 +1,109 @@
<?php
namespace App\Entity;
use App\Repository\UsrlogRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=UsrlogRepository::class)
*/
class Usrlog
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $pcode;
/**
* @ORM\Column(type="text")
*/
private $agent;
/**
* @ORM\Column(type="string", length=45)
*/
private $clientIp;
/**
* @ORM\Column(type="string", length=50)
*/
private $method;
/**
* @ORM\Column(type="datetime")
*/
private $createdAt;
public function getId(): ?int
{
return $this->id;
}
public function getPcode(): ?string
{
return $this->pcode;
}
public function setPcode(string $pcode): self
{
$this->pcode = $pcode;
return $this;
}
public function getAgent(): ?string
{
return $this->agent;
}
public function setAgent(string $agent): self
{
$this->agent = $agent;
return $this;
}
public function getClientIp(): ?string
{
return $this->clientIp;
}
public function setClientIp(string $clientIp): self
{
$this->clientIp = $clientIp;
return $this;
}
public function getMethod(): ?string
{
return $this->method;
}
public function setMethod(string $method): self
{
$this->method = $method;
return $this;
}
public function getCreatedAt(): ?\DateTimeInterface
{
return $this->createdAt;
}
public function setCreatedAt(\DateTimeInterface $createdAt): self
{
$this->createdAt = $createdAt;
return $this;
}
}
+88
View File
@@ -0,0 +1,88 @@
<?php
namespace App\Entity;
use App\Repository\WidgetFormRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Criteria;
/**
* @ORM\Entity(repositoryClass=WidgetFormRepository::class)
*/
class WidgetForm
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity=WidgetFormInput::class, mappedBy="widgetForm")
*/
private $widgetFormInputs;
public function __construct()
{
$this->widgetFormInputs = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* @return Collection|WidgetFormInput[]
*/
public function getWidgetFormInputs(): Collection
{
$expr = Criteria::expr();
$criteria = Criteria::create();
$criteria->orderBy(['sort' => Criteria::ASC]);
return $this->widgetFormInputs->matching($criteria);
}
public function addWidgetFormInput(WidgetFormInput $widgetFormInput): self
{
if (!$this->widgetFormInputs->contains($widgetFormInput)) {
$this->widgetFormInputs[] = $widgetFormInput;
$widgetFormInput->setWidgetForm($this);
}
return $this;
}
public function removeWidgetFormInput(WidgetFormInput $widgetFormInput): self
{
if ($this->widgetFormInputs->removeElement($widgetFormInput)) {
// set the owning side to null (unless already changed)
if ($widgetFormInput->getWidgetForm() === $this) {
$widgetFormInput->setWidgetForm(null);
}
}
return $this;
}
}
+109
View File
@@ -0,0 +1,109 @@
<?php
namespace App\Entity;
use App\Repository\WidgetFormInputRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=WidgetFormInputRepository::class)
*/
class WidgetFormInput
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $text;
/**
* @ORM\Column(type="string", length=255)
*/
private $type;
/**
* @ORM\Column(type="string", length=255)
*/
private $bitrix24Id;
/**
* @ORM\ManyToOne(targetEntity=WidgetForm::class, inversedBy="widgetFormInputs")
*/
private $widgetForm;
/**
* @ORM\Column(type="integer")
*/
private $sort;
public function getId(): ?int
{
return $this->id;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(string $text): self
{
$this->text = $text;
return $this;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function getBitrix24Id(): ?string
{
return $this->bitrix24Id;
}
public function setBitrix24Id(string $bitrix24Id): self
{
$this->bitrix24Id = $bitrix24Id;
return $this;
}
public function getWidgetForm(): ?WidgetForm
{
return $this->widgetForm;
}
public function setWidgetForm(?WidgetForm $widgetForm): self
{
$this->widgetForm = $widgetForm;
return $this;
}
public function getSort(): ?int
{
return $this->sort;
}
public function setSort(int $sort): self
{
$this->sort = $sort;
return $this;
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
/**
* При редиректе на /login до загрузки JS query-параметр sessionId теряется.
* Ставим session-cookie на том же HTTP-ответе (в т.ч. 302), что и редирект.
*/
class SessionIdQueryCookieListener implements EventSubscriberInterface
{
private const PARAM = 'sessionId';
private const MAX_LEN = 128;
public static function getSubscribedEvents(): array
{
return [KernelEvents::RESPONSE => 'onKernelResponse'];
}
public function onKernelResponse(ResponseEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$request = $event->getRequest();
if (!$request->query->has(self::PARAM)) {
return;
}
$value = trim((string) $request->query->get(self::PARAM));
if ($value === '' || \strlen($value) > self::MAX_LEN) {
return;
}
$cookie = Cookie::create(
self::PARAM,
$value,
0,
'/',
null,
$request->isSecure(),
false,
false,
Cookie::SAMESITE_LAX
);
$event->getResponse()->headers->setCookie($cookie);
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\EventListener;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
class UserActivityListener implements EventSubscriberInterface
{
private $tokenStorage;
private $entityManager;
public function __construct(TokenStorageInterface $tokenStorage, EntityManagerInterface $entityManager)
{
$this->tokenStorage = $tokenStorage;
$this->entityManager = $entityManager;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::REQUEST => ['onKernelRequest', 0],
];
}
public function onKernelRequest(RequestEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$token = $this->tokenStorage->getToken();
if (!$token) {
return;
}
$user = $token->getUser();
if (!$user instanceof User) {
return;
}
// Обновляем время последней активности пользователя
// Обновляем не чаще чем раз в минуту, чтобы не нагружать базу данных
$lastActivity = $user->getLastActivityAt();
$now = new \DateTime();
if (!$lastActivity || ($now->getTimestamp() - $lastActivity->getTimestamp()) >= 60) {
$user->updateLastActivity();
$this->entityManager->persist($user);
$this->entityManager->flush();
}
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
namespace App\EventListener;
use App\Entity\User;
use App\Entity\Usrlog;
use App\Repository\UsrlogRepository;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
class UsrlogAuthListener implements EventSubscriberInterface
{
private UsrlogRepository $usrlogRepository;
private LoggerInterface $logger;
public function __construct(UsrlogRepository $usrlogRepository, LoggerInterface $logger)
{
$this->usrlogRepository = $usrlogRepository;
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return [
SecurityEvents::INTERACTIVE_LOGIN => 'onLoginSuccess',
];
}
public function onLoginSuccess(InteractiveLoginEvent $event): void
{
$token = $event->getAuthenticationToken();
$user = $token->getUser();
if (!$user instanceof User) {
return;
}
$request = $event->getRequest();
$agent = (string) ($request->headers->get('User-Agent') ?? 'unknown');
$clientIp = (string) ($request->getClientIp() ?? 'unknown');
$pcode = (string) $user->getUid();
$usrlog = new Usrlog();
$usrlog
->setPcode($pcode)
->setAgent($agent)
->setClientIp($clientIp)
->setMethod('вход')
;
try {
$this->usrlogRepository->add($usrlog);
} catch (\Throwable $e) {
$this->logger->error('USRLOG: failed to save login log row', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
]);
}
}
}
+61
View File
@@ -0,0 +1,61 @@
<?php
namespace App\Form;
use App\Entity\Banner;
use App\Entity\City;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\File;
class BannerType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('href')
->add('file', FileType::class, [
'label' => 'image',
'mapped' => false,
'required' => true,
'constraints' => [
new File([
'maxSize' => '5024k',
'mimeTypes' => [
'image/jpeg',
'image/gif',
'image/jpg',
'image/png',
],
'mimeTypesMessage' => 'Please upload a valid image',
])
],
])
->add('city', EntityType::class, [
'class' => City::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('c');
},
'choice_label' => 'name',
'choice_value' => 'region_id',
'mapped' => true,
'multiple' => false,
'empty_data' => null,
'required' => true
])
->add('active')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Banner::class,
]);
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App\Form;
use App\Entity\CategoryPage;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CategoryPageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('active')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => CategoryPage::class,
]);
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace App\Form;
use App\Entity\City;
use App\Entity\Filial;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class CityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name')
->add('timeZone')
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('f');
},
'choice_label' => 'address',
'mapped' => true,
'multiple' => false,
'empty_data' => null,
'required' => true
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => City::class,
]);
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Form;
use App\Entity\Department;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class DepartmentType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('middleName')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Department::class,
]);
}
}
+48
View File
@@ -0,0 +1,48 @@
<?php
namespace App\Form;
use App\Entity\Page;
use App\Entity\CategoryPage;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
class PageType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description', CKEditorType::class)
->add('active')
->add('alias')
->add('category', EntityType::class, [
'class' => CategoryPage::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('c')
->where('c.active in(:a)')
->setParameter('a', true)
->orderBy('c.id', 'ASC');
},
'choice_label' => 'name',
'choice_value' => 'id',
'mapped' => false,
'multiple' => false,
'empty_data' => [],
'required' => false
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Page::class,
]);
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
namespace App\Form;
use App\Entity\PriceList;
use App\Entity\PriceDepartment;
use App\Entity\Filial;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use App\Bundle\Infoclinica\Region;
class PriceListAdminFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('schname', TextType::class, [
'empty_data' => null,
'mapped' => true,
'required' => false
])
->add('kodoper', TextType::class, [
'empty_data' => null,
'mapped' => true,
'required' => false
])
->add('groupId', EntityType::class, [
'class' => PriceDepartment::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('d')
->orderBy('d.name', 'ASC');
},
'choice_value' => 'groupId',
'choice_label' => 'name',
'placeholder' => 'Департамент',
'empty_data' => null,
'mapped' => false,
'required' => true
])
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->where('f.fid <> :fid')
->setParameter('fid', 0)
->orderBy('f.address', 'DESC');
},
'choice_label' => 'address',
'choice_value' => 'fid',
'placeholder' => 'Все филиалы',
'mapped' => false,
'multiple' => false,
'empty_data' => null,
'required' => false
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => PriceList::class,
]);
}
}
+70
View File
@@ -0,0 +1,70 @@
<?php
namespace App\Form;
use App\Entity\PriceList;
use App\Entity\PriceDepartment;
use App\Entity\Filial;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use App\Bundle\Infoclinica\Region;
class PriceListFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('schname', TextType::class, [
'empty_data' => null,
'mapped' => true,
'required' => false
])
->add('kodoper', TextType::class, [
'empty_data' => null,
'mapped' => true,
'required' => false
])
->add('groupId', EntityType::class, [
'class' => PriceDepartment::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('d')
->orderBy('d.name', 'ASC');
},
'choice_value' => 'groupId',
'choice_label' => 'name',
'placeholder' => 'Все специализации',
'empty_data' => null,
'mapped' => false,
'required' => false
])
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->where('f.fid <> :fid')
->setParameter('fid', 0)
->andWhere('f.address LIKE :address')
->setParameter('address', '%' . Region::getCurrentName() . '%')
->orderBy('f.address', 'DESC');
},
'choice_label' => 'address',
'choice_value' => 'fid',
'mapped' => false,
'multiple' => false,
'empty_data' => null,
'required' => false
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => PriceList::class,
]);
}
}
+105
View File
@@ -0,0 +1,105 @@
<?php
namespace App\Form;
use App\Entity\User;
use App\Entity\Filial;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use App\Bundle\Infoclinica\Region;
class ReferenceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$sendingChoices = $options['isAuthorized'] ? [
'Лично в клинике' => 1,
'Отправка в налоговую инспекцию' => 2,
] : [
'Лично в клинике' => 1,
];
$builder
->add('autorName', TextType::class, ['mapped' => false])
->add('birthDate', TextType::class, ['mapped' => false])
->add('inn', TextType::class, [
'mapped' => false,
])
->add('phone', TextType::class, [
'mapped' => false,
])
->add('periodFirst', DateType::Class, array(
'mapped' => false,
'format' => 'yyyy-MM-dd',
'widget' => 'single_text',
))
->add('periodLast', DateType::Class, array(
'mapped' => false,
'format' => 'yyyy-MM-dd',
'widget' => 'single_text',
))
->add('responsible', ChoiceType::class, [
'mapped' => false,
'expanded' => false,
'choices' => [
'себя' => 1,
'другого' => 0,
]
])
->add('sending', ChoiceType::class, [
'mapped' => false,
'expanded' => false,
'choices' => $sendingChoices,
'data' => 1,
])
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->where('f.fid <> :fid')
->setParameter('fid', 0)
->orderBy('f.city', 'ASC');
},
'choice_label' => 'address',
'choice_value' => 'address',
'mapped' => false,
'multiple' => false,
'empty_data' => [],
'required' => false
])
->add('filialSending', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->where('f.fid <> :fid')
->setParameter('fid', 0)
->orderBy('f.city', 'ASC');
},
'choice_label' => 'address',
'choice_value' => 'address',
'mapped' => false,
'multiple' => false,
'empty_data' => [],
'required' => false
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
'isAuthorized' => false,
]);
}
}
+81
View File
@@ -0,0 +1,81 @@
<?php
namespace App\Form;
use App\Entity\User;
use App\Entity\Filial;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use App\Bundle\Infoclinica\Region;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
class RefundType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('fio', TextType::class, [
'mapped' => false,
'required' => true,
'label' => 'ФИО:'
])
->add('passport_serial', TextType::class, [
'mapped' => false,
'required' => true,
'label' => 'Паспорт: (серия номер)',
'attr' => [
'data-controller' => 'inputMask',
'data-mask' => '9999 999999',
]
])
->add('passport_issued', TextareaType::class, [
'mapped' => false,
'required' => true,
'label' => 'Выдан:'
])
->add('passport_date', DateType::Class, array(
'mapped' => false,
'format' => 'yyyy-MM-dd',
'widget' => 'single_text',
'required' => true,
'label' => 'Дата выдачи:'
))
->add('sum', TextType::class, [
'mapped' => false,
'required' => true,
'label' => 'Сумма возврата:'
])
->add('refund_date', DateType::Class, array(
'mapped' => false,
'required' => true,
'label' => 'Дата платежа:',
'format' => 'yyyy-MM-dd',
'widget' => 'single_text',
))
->add('refund_bases', ChoiceType::class, [
'mapped' => false,
'required' => true,
'label' => 'Причина возврата:',
'expanded' => false,
'choices' => [
'Отказ от консультация до ее начала' => 'Отказ от консультация до ее начала',
'Консультация не состоялась по техническим причинам' => 'Консультация не состоялась по техническим причинам',
]
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => NULL,
]);
}
}
+71
View File
@@ -0,0 +1,71 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\BirthdayType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('agreeTerms', CheckboxType::class, [
'mapped' => false,
'constraints' => [
new IsTrue([
'message' => 'You should agree to our terms.',
]),
],
])
->add('firstName', TextType::class, ['mapped' => false])
->add('lastName', TextType::class, ['mapped' => false])
->add('middleName', TextType::class, ['mapped' => false])
->add('birthDate', BirthdayType::class, ['mapped' => false])
->add('email')
->add('gender', ChoiceType::class, [
'mapped' => false,
'expanded' => true,
'choices' => [
'male' => 1,
'famale' => 2,
]
])
->add('phone')
->add('plainPassword', PasswordType::class, [
// instead of being set onto the object directly,
// this is read and encoded in the controller
'mapped' => false,
'attr' => ['autocomplete' => 'new-password'],
'constraints' => [
new NotBlank([
'message' => 'Please enter a password',
]),
new Length([
'min' => 7,
'minMessage' => 'Your password should be at least {{ limit }} characters',
// max length allowed by Symfony for security reasons
'max' => 4096,
]),
],
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
+36
View File
@@ -0,0 +1,36 @@
<?php
namespace App\Form;
use App\Entity\Filial;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
class ReportFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->groupBy('f.fid')
->orderBy('f.fid', 'ASC');
},
'choice_label' => function ($data) {
return $data->getAddress();
},
'choice_value' => 'siteId',
'mapped' => false,
'multiple' => false,
'empty_data' => false,
'required' => true
])
;
// ->add('smsCode',TextType::class, ['mapped' => false]);
}
}
+66
View File
@@ -0,0 +1,66 @@
<?php
namespace App\Form;
use App\Entity\City;
use App\Entity\Filial;
use App\Entity\ReviewSource;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class ReviewSourceType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', ChoiceType::class, [
'mapped' => true,
'expanded' => false,
'choices' => [
'Яндекс карта' => 'YandexMap',
'Google' => 'Google',
'ProDoctorov(Клиники)' => 'ProDoctorov',
'ProDoctorov(Врачи)' => 'ProDoctorovSpecialists',
'2Gis' => '2Gis',
'Zoon' => 'Zoon',
]
])
->add('countRow')
->add('active')
->add('rating')
->add('city', EntityType::class, [
'class' => City::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('f');
},
'choice_label' => 'name',
'mapped' => true,
'multiple' => false,
'empty_data' => null,
'required' => true
])
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('f');
},
'choice_label' => 'address',
'mapped' => true,
'multiple' => false,
'empty_data' => null,
'required' => true
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ReviewSource::class,
]);
}
}
+43
View File
@@ -0,0 +1,43 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
class SettingType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('plainPassword', PasswordType::class, [
// instead of being set onto the object directly,
// this is read and encoded in the controller
'mapped' => false,
'attr' => ['autocomplete' => 'new-password'],
'constraints' => [
new NotBlank([
'message' => 'Please enter a password',
]),
new Length([
'min' => 7,
'minMessage' => 'Your password should be at least {{ limit }} characters',
// max length allowed by Symfony for security reasons
'max' => 4096,
]),
],
]);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}
+44
View File
@@ -0,0 +1,44 @@
<?php
namespace App\Form;
use App\Entity\Filial;
use App\Bundle\Infoclinica\Region;
use App\Entity\Specialist;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
class SpecialistAdminSearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', null, [
'required' => false
])
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->orderBy('f.id', 'ASC');
},
'choice_label' => 'name',
'mapped' => false,
'multiple' => true,
'empty_data' => [],
'required' => false
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Specialist::class,
]);
}
}
+121
View File
@@ -0,0 +1,121 @@
<?php
namespace App\Form;
use App\Bundle\Infoclinica\Region;
use App\Entity\SpecialistView;
use App\Entity\LocationView;
use App\Entity\Department;
use App\Entity\Filial;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Doctrine\ORM\EntityRepository;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class SpecialistSearchType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('onlineMode', CheckboxType::class, [
'label' => 'Онлайн консультация',
'mapped' => false,
'required' => false
])
->add('name', null, [
'mapped' => false,
'required' => false
])
->add('kinder', ChoiceType::class, [
'choices' => [
'Детский врач' => 1,
],
'placeholder' => 'Взрослый врач',
'mapped' => false,
'empty_data' => null,
'required' => false
])
->add('department', EntityType::class, [
'class' => Department::class,
'query_builder' => function (EntityRepository $er) use ($options) {
$qb = $er->createQueryBuilder('d')
->distinct()
->innerJoin('App\Entity\LocationView', 'l', 'WITH', 'l.department = d.did AND l.active = true')
->innerJoin('App\Entity\SpecialistView', 's', 'WITH', 's.id = l.specialistId AND s.active = true')
->leftJoin('App\Entity\Filial', 'f', 'WITH', 'f.fid = l.filial')
->where('f.address LIKE :address')
->andWhere('d.did <> :did')
->setParameter('did', 0)
->setParameter('address', '%' . Region::getCurrentName() . '%');
// Добавляем фильтр по региону, если он указан
if (!empty($options['regionId']) && $options['regionId'] > 0) {
$qb->andWhere('s.regionId = :regionId')
->setParameter('regionId', $options['regionId']);
}
// Добавляем фильтр по детским специализациям, если выбран "Детский врач"
if (!empty($options['kinder']) && $options['kinder'] == 1) {
$qb->andWhere('s.sType = :sType')
->setParameter('sType', 1);
}
return $qb->orderBy('d.name', 'ASC');
},
'choice_value' => 'did',
'choice_label' => 'name',
'placeholder' => 'Все специализации',
'empty_data' => null,
'mapped' => false,
'required' => false
])
->add('filial', EntityType::class, [
'class' => Filial::class,
'query_builder' => function (EntityRepository $er) {
return $er
->createQueryBuilder('f')
->where("f.address LIKE :address and f.active = true and f.fid <> 0")
->setParameter('address', '%' . Region::getCurrentName() . '%')
->orderBy('f.id', 'ASC');
},
'choice_value' => 'fid',
'choice_label' => 'name',
'mapped' => false,
'multiple' => true,
'empty_data' => [],
'required' => false
])
->add('category', ChoiceType::class, [
'choices' => [
'Первая' => 'Первая',
'Вторая' => 'Вторая',
'Высшая' => 'Высшая'
],
'placeholder' => 'Выберите категорию',
'mapped' => false,
'multiple' => false,
'empty_data' => null,
'required' => false
])
->add('current_date', null, [
'mapped' => false
])
->add('order_by', null, [
'mapped' => false,
'required' => false
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => SpecialistView::class,
'regionId' => null,
'kinder' => null,
]);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace App\Form;
use App\Entity\SpecialistView;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SpecialistType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('sid')
->add('name')
->add('onlineMode')
->add('department')
->add('filial')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => SpecialistView::class,
]);
}
}
+37
View File
@@ -0,0 +1,37 @@
<?php
namespace App\Form;
use App\Entity\Usrlog;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class UsrlogType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('pcode')
->add('agent', TextareaType::class)
->add('clientIp', null, [
'label' => 'IP клиента',
])
->add('method', ChoiceType::class, [
'choices' => [
'Вход в систему' => 'вход в систему',
'Выход' => 'выход',
],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Usrlog::class,
]);
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Form;
use App\Entity\WidgetFormInput;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
class WidgetFormInputType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('text')
->add('type', ChoiceType::class, [
'choices' => [
'Строка' => 'text',
'Телефон' => 'phone',
'Календаль' => 'date',
'Коментарий' => 'textarea',
],
'empty_data' => null,
'required' => false
])
->add('bitrix24Id')
->add('sort')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => WidgetFormInput::class,
]);
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Form;
use App\Entity\WidgetForm;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class WidgetFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => WidgetForm::class,
]);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
protected function configureContainer(ContainerConfigurator $container): void
{
$container->import('../config/{packages}/*.yaml');
$container->import('../config/{packages}/'.$this->environment.'/*.yaml');
if (is_file(\dirname(__DIR__).'/config/services.yaml')) {
$container->import('../config/services.yaml');
$container->import('../config/{services}_'.$this->environment.'.yaml');
} elseif (is_file($path = \dirname(__DIR__).'/config/services.php')) {
(require $path)($container->withPath($path), $this);
}
}
protected function configureRoutes(RoutingConfigurator $routes): void
{
$routes->import('../config/{routes}/'.$this->environment.'/*.yaml');
$routes->import('../config/{routes}/*.yaml');
if (is_file(\dirname(__DIR__).'/config/routes.yaml')) {
$routes->import('../config/routes.yaml');
} elseif (is_file($path = \dirname(__DIR__).'/config/routes.php')) {
(require $path)($routes->withPath($path), $this);
}
}
}
View File
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\AlertSms;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method AlertSms|null find($id, $lockMode = null, $lockVersion = null)
* @method AlertSms|null findOneBy(array $criteria, array $orderBy = null)
* @method AlertSms[] findAll()
* @method AlertSms[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class AlertSmsRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, AlertSms::class);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\Banner;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Banner|null find($id, $lockMode = null, $lockVersion = null)
* @method Banner|null findOneBy(array $criteria, array $orderBy = null)
* @method Banner[] findAll()
* @method Banner[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class BannerRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Banner::class);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\CategoryPage;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method CategoryPage|null find($id, $lockMode = null, $lockVersion = null)
* @method CategoryPage|null findOneBy(array $criteria, array $orderBy = null)
* @method CategoryPage[] findAll()
* @method CategoryPage[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class CategoryPageRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, CategoryPage::class);
}
}
+58
View File
@@ -0,0 +1,58 @@
<?php
namespace App\Repository;
use App\Entity\City;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<City>
*
* @method City|null find($id, $lockMode = null, $lockVersion = null)
* @method City|null findOneBy(array $criteria, array $orderBy = null)
* @method City[] findAll()
* @method City[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class CityRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, City::class);
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(City $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(City $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}
public function all()
{
return $this->createQueryBuilder('c')
->select('c.id, c.name')
->getQuery()
->getResult()
;
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\Department;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Department|null find($id, $lockMode = null, $lockVersion = null)
* @method Department|null findOneBy(array $criteria, array $orderBy = null)
* @method Department[] findAll()
* @method Department[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class DepartmentRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Department::class);
}
}
@@ -0,0 +1,49 @@
<?php
namespace App\Repository;
use App\Entity\DirectCompany;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<DirectCompany>
*
* @method DirectCompany|null find($id, $lockMode = null, $lockVersion = null)
* @method DirectCompany|null findOneBy(array $criteria, array $orderBy = null)
* @method DirectCompany[] findAll()
* @method DirectCompany[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class DirectCompanyRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, DirectCompany::class);
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(DirectCompany $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(DirectCompany $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
namespace App\Repository;
use App\Entity\DirectReport;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<DirectReport>
*
* @method DirectReport|null find($id, $lockMode = null, $lockVersion = null)
* @method DirectReport|null findOneBy(array $criteria, array $orderBy = null)
* @method DirectReport[] findAll()
* @method DirectReport[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class DirectReportRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, DirectReport::class);
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(DirectReport $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(DirectReport $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace App\Repository;
use App\Entity\Filial;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Filial|null find($id, $lockMode = null, $lockVersion = null)
* @method Filial|null findOneBy(array $criteria, array $orderBy = null)
* @method Filial[] findAll()
* @method Filial[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class FilialRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Filial::class);
}
public function findByRegion(string $region): array
{
return $this->createQueryBuilder('filial')
->where('filial.address LIKE :address')
->setParameter('address', '%' . $region . '%')
->orderBy('filial.id')
->getQuery()
->getResult();
}
}
+108
View File
@@ -0,0 +1,108 @@
<?php
namespace App\Repository;
use App\Entity\LocationView;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Location|null find($id, $lockMode = null, $lockVersion = null)
* @method Location|null findOneBy(array $criteria, array $orderBy = null)
* @method Location[] findAll()
* @method Location[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class LocationViewRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, LocationView::class);
}
public function findBySpecialistId(
int $specialistId,
bool $onlineMode = false,
?int $department = null,
?\DateTimeInterface $startDate = null,
?\DateTimeInterface $endDate = null
): array {
// Основной запрос
$qb = $this->createQueryBuilder('l')
->select('l.id, l.dcode, l.department, l.onlineMode, l.filial, l.active, l.nearestDate, d.name')
->leftJoin('App\Entity\Department', 'd', 'WITH', 'd.did = l.department')
->where('l.specialistId = :specialistId')
->setParameter('specialistId', $specialistId)
->andWhere('l.active = true')
->andWhere('l.onlineMode = :onlineMode')
->setParameter('onlineMode', $onlineMode);
// Фильтр по отделению (специализации), если указано
if ($department !== null && $department > 0) {
$qb->andWhere('l.department = :department')
->setParameter('department', $department);
}
// Фильтр по дате приема (диапазон дат), если указано
if ($startDate !== null) {
$qb->andWhere('l.nearestDate >= :startDate')
->setParameter('startDate', $startDate);
}
if ($endDate !== null) {
$qb->andWhere('l.nearestDate <= :endDate')
->setParameter('endDate', $endDate);
}
// Сортировка по ближайшему приему: сначала ближайшие даты (ASC), NULL значения в конце
$qb->orderBy('CASE WHEN l.nearestDate IS NULL THEN 1 ELSE 0 END', 'ASC')
->addOrderBy('l.nearestDate', 'ASC');
$mainQuery = $qb->getQuery()->getResult();
if (empty($mainQuery)) {
return [];
}
// Получаем все уникальные filialId из основного запроса
$filialIds = array_filter(array_unique(array_column($mainQuery, 'filial')));
if (empty($filialIds)) {
return $mainQuery;
}
// Запрос для получения данных Filial через EntityManager
$entityManager = $this->getEntityManager();
$filialQuery = $entityManager->createQueryBuilder()
->select('f.fid, f.address, f.company, f.addressName')
->from('App\Entity\Filial', 'f')
->where('f.fid IN (:filialIds)')
->setParameter('filialIds', $filialIds)
->getQuery()
->getResult();
// Создаем мапу для быстрого доступа к данным Filial
$filialMap = [];
foreach ($filialQuery as $filial) {
$filialMap[$filial['fid']] = [
'address' => $filial['address'],
'company' => $filial['company'],
'addressName' => $filial['addressName']
];
}
// Объединяем данные
foreach ($mainQuery as &$record) {
$filialId = $record['filial'];
if ($filialId && isset($filialMap[$filialId])) {
$record = array_merge($record, $filialMap[$filialId]);
} else {
// Добавляем пустые значения если filial не найден
$record['address'] = null;
$record['company'] = null;
$record['addressName'] = null;
}
}
return $mainQuery;
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\Page;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Page|null find($id, $lockMode = null, $lockVersion = null)
* @method Page|null findOneBy(array $criteria, array $orderBy = null)
* @method Page[] findAll()
* @method Page[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PageRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Page::class);
}
}
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\PriceDepartment;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method PriceDepartment|null find($id, $lockMode = null, $lockVersion = null)
* @method PriceDepartment|null findOneBy(array $criteria, array $orderBy = null)
* @method PriceDepartment[] findAll()
* @method PriceDepartment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PriceDepartmentRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, PriceDepartment::class);
}
}
+85
View File
@@ -0,0 +1,85 @@
<?php
namespace App\Repository;
use App\Entity\PriceList;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Doctrine\ORM\QueryBuilder;
/**
* @method PriceList|null find($id, $lockMode = null, $lockVersion = null)
* @method PriceList|null findOneBy(array $criteria, array $orderBy = null)
* @method PriceList[] findAll()
* @method PriceList[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PriceListRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, PriceList::class);
}
public function createFilteredQueryBuilder(array $filters): QueryBuilder
{
$qb = $this->createQueryBuilder('p')
->addOrderBy('p.filial, p.schname', 'ASC');
if (!empty($filters['kodoper'])) {
$kodoper = match (true) {
is_array($filters['kodoper']) => array_filter(
array_map('trim', array_filter($filters['kodoper'], 'is_string')),
function($code) { return $code !== ''; }
),
is_string($filters['kodoper']) && trim($filters['kodoper']) !== '' => [trim($filters['kodoper'])],
default => []
};
if (!empty($kodoper)) {
// Логируем значения kodoper для отладки
error_log('PriceListRepository: filtering by kodoper=' . json_encode($kodoper));
$qb->andWhere('p.kodoper IN (:codes)')
->setParameter('codes', $kodoper);
}
}
if (!empty($filters['schname']) && trim($filters['schname']) !== '') {
$qb->andWhere($qb->expr()->like('LOWER(p.schname)', 'LOWER(:schname)'))
->setParameter('schname', '%' . trim($filters['schname']) . '%');
}
if (!empty($filters['filial'])) {
$filialIds = match (true) {
is_array($filters['filial']) => array_filter($filters['filial'], function($id) {
return $id !== null && $id !== '';
}),
is_string($filters['filial']) && $filters['filial'] !== '' => [$filters['filial']],
is_numeric($filters['filial']) => [(int)$filters['filial']],
default => []
};
if (!empty($filialIds)) {
$qb->andWhere('p.filial IN (:filial)')
->setParameter('filial', $filialIds);
}
}
if (!empty($filters['actual'])) {
if ($filters['actual']) {
$qb->andWhere('p.dateUpdate >= :dateUpdate')
->setParameter('dateUpdate', (new \DateTime())
->modify('-2 day')
->format('Y-m-d 00:00:00')
);
}
}
if (!empty($filters['groupId'])) {
$qb->andWhere('p.groupId = :groupId')
->setParameter('groupId', (int) $filters['groupId']);
}
return $qb;
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\Price;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Price|null find($id, $lockMode = null, $lockVersion = null)
* @method Price|null findOneBy(array $criteria, array $orderBy = null)
* @method Price[] findAll()
* @method Price[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class PriceRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Price::class);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\Record;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Record|null find($id, $lockMode = null, $lockVersion = null)
* @method Record|null findOneBy(array $criteria, array $orderBy = null)
* @method Record[] findAll()
* @method Record[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class RecordRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Record::class);
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Repository;
use App\Entity\Review;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @method Review|null find($id, $lockMode = null, $lockVersion = null)
* @method Review|null findOneBy(array $criteria, array $orderBy = null)
* @method Review[] findAll()
* @method Review[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ReviewRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Review::class);
}
}

Some files were not shown because too many files have changed in this diff Show More