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
+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;
}
}
}