src/Service/BaseEntityService.php line 595

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Entity\CalendarEvent;
  4. use App\Entity\Client;
  5. use App\Entity\Company;
  6. use App\Entity\Form\AnySearch;
  7. use App\Entity\Machine;
  8. use App\Entity\Person;
  9. use App\Entity\Session;
  10. use App\Entity\Student;
  11. use App\Library\Route\RouteParamObjects;
  12. use App\Library\Utils\DateTimeProvider\DateTimeProviderInterface;
  13. use App\Library\Utils\DateTimeProvider\SystemDateTimeProvider;
  14. use App\Library\Utils\Dev\DoctrineUtils\DoctrineUtils;
  15. use App\Library\Utils\Dev\ReflectionUtils\ReflectionUtils;
  16. use App\Library\Utils\Other\Other;
  17. use App\Library\Utils\StringUtils;
  18. use App\Service\CarWash\CarWashService;
  19. use App\Service\Data\Paginator;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Doctrine\ORM\EntityRepository;
  22. use Doctrine\ORM\Query\Expr\Join;
  23. use Doctrine\ORM\QueryBuilder;
  24. use Doctrine\Persistence\ObjectRepository;
  25. use Symfony\Component\Serializer\SerializerInterface;
  26. class BaseEntityService
  27. {
  28.     const MANDATORY_PARAMS = [
  29.     ];
  30.     const SEARCH_FIELDS = [
  31.         "name"
  32.     ];
  33.     const ORDER_ID_DESC = ["id""DESC"];
  34.     private static $serviceSecFields = [];
  35.     /** @var EntityManagerInterface */
  36.     protected $em;
  37.     /**
  38.      * @var DateTimeProviderInterface
  39.      */
  40.     protected $dateTimeProvider;
  41.     protected $entityClassName null;
  42.     protected $entityShortClassName null;
  43.     protected $entityAlias null;
  44.     protected $dateFieldName "createdAt";
  45.     protected $tableName null;
  46.     /**
  47.      * @deprecated Устарело. Не использовать.
  48.      */
  49.     protected $searchDql 'item.id = :text or item.name like :text_like';
  50.     /**
  51.      * @var BaseEntityServiceDefault
  52.      */
  53.     private $default;
  54.     private $sqlFields = [];
  55.     /**
  56.      * @var SerializerInterface
  57.      */
  58.     private $serializer;
  59.     /**
  60.      * @var ServiceRetriever|null
  61.      */
  62.     protected $serviceRetriever;
  63.     public function __construct(EntityManagerInterface $em,
  64.                                 SerializerInterface $serializer null,
  65.                                 ServiceRetriever $serviceRetriever null)
  66.     {
  67.         $this->em $em;
  68.         $this->default = new BaseEntityServiceDefault($this);
  69.         $this->serializer $serializer;
  70.         $this->serviceRetriever $serviceRetriever;
  71.     }
  72.     public function initialize(string $entityClassNamestring $dateFieldName "createdAt"string $searchDql null): void
  73.     {
  74.         $this->dateFieldName $dateFieldName;
  75.         $this->entityClassName $entityClassName;
  76.         $this->entityShortClassName self::getEntityShortName($entityClassName);
  77.         $this->entityAlias self::getEntityAlias($this->entityShortClassName);
  78.         $classMetadata $this->em->getClassMetadata($entityClassName);
  79.         $this->tableName $classMetadata->getTableName();
  80.         $this->searchDql $searchDql ?? $this->searchDql;
  81.     }
  82.     public function getRepository(): EntityRepository
  83.     {
  84.         return $this->em->getRepository($this->entityClassName);
  85.     }
  86.     /**
  87.      * @return BaseEntityServiceDefault
  88.      */
  89.     public function getBaseService(): BaseEntityServiceDefault
  90.     {
  91.         return $this->default;
  92.     }
  93.     public function getRandom(int $count 1bool $getCount false, array $excludeIds nullstring $where null)
  94.     {
  95.         $sql 'SELECT ' . ($getCount "count(*)" "*") . ' FROM ' $this->tableName ' item '
  96.             . ($excludeIds || $where "WHERE " "")
  97.             . ($excludeIds " item.id not in (0, " implode(","$excludeIds) . ")" "")
  98.             . ($where $where"")
  99.             . ' ORDER BY RAND() LIMIT ' $count;
  100.         $connection $this->em->getConnection();
  101.         $stmt $connection->prepare($sql);
  102.         $result $stmt->executeQuery();
  103.         return ($getCount ? (int)$result->fetchNumeric()[0] : $result->fetchAllAssociative());
  104.     }
  105.     public function hasItems(Company $company nullstring $whereSql null): bool
  106.     {
  107.         $sql 'SELECT count(*) as count FROM ' $this->tableName " item where"
  108.             . ($company " item.company_id = {$company->getId()}"")
  109.             . ($whereSql $whereSql"")
  110.             . " LIMIT 1";
  111.         $connection $this->em->getConnection();
  112.         $stmt $connection->prepare($sql);
  113.         $result $stmt->executeQuery();
  114.         return (int)$result->fetchNumeric()[0] != 0;
  115.     }
  116.     public function hasNotDeletedItems(Company $company): bool
  117.     {
  118.         $sql 'SELECT count(*) as count FROM ' $this->tableName " item where item.company_id = {$company->getId()} and item.status != 'deleted' LIMIT 1";
  119.         $connection $this->em->getConnection();
  120.         $stmt $connection->prepare($sql);
  121.         $result $stmt->executeQuery();
  122.         return (int)$result->fetchNumeric()[0] != 0;
  123.     }
  124.     protected static $sortedDefaultQueryParams = [
  125.         "company" => null,
  126.         "machine" => null,
  127.     ];
  128.     /**
  129.      * @param array{string, string}|null $orderBy
  130.      * @return array{list: array, page: int, perPage: int, totalItems: int, pagesCount: int}
  131.      * @throws \Exception
  132.      */
  133.     public function getItemsWithPaginationDefault(int   $page, array $params null,
  134.                                                   array $orderBy null$onBeforeQueryChange null, array $excludeMandatoryParams null,
  135.                                                         $isSql false, array $joinClasses nullint $perPage Paginator::PER_PAGE): array
  136.     {
  137.         $query $this->getQuery($params$orderBy$onBeforeQueryChange,
  138.             $excludeMandatoryParams$isSql$joinClasses);
  139.         $result Paginator::getResult($query$page$perPagefalse$this->em->getConnection());
  140.         if ($isSql && $joinClasses) {
  141.             foreach ($result['list'] as $index => $itemData) {
  142.                 $newData = [];
  143.                 $jointTableNames = [];
  144.                 foreach ($itemData as $key => $value) {
  145.                     $keyArr explode("__"$key2);
  146.                     $tableName $keyArr[0];
  147.                     $columnName $keyArr[1];
  148.                     if (!isset($newData[$tableName])) {
  149.                         $newData[$tableName] = [];
  150.                         if ($tableName != $this->tableName) {
  151.                             $jointTableNames[] = $tableName;
  152.                         }
  153.                     }
  154.                     if (in_array($columnName, ["created_at""last_online""last_time"])) {
  155.                         $value = new \DateTime($value);
  156.                     }
  157.                     $newData[$tableName][$columnName] = $value;
  158.                 }
  159.                 $result['list'][$index] = $newData[$this->tableName];
  160.                 foreach ($jointTableNames as $name) {
  161.                     if (isset($result['list'][$index][$name])) {
  162.                         throw new \Exception("'$name' field is already set");
  163.                     }
  164.                     $result['list'][$index][$name] = $newData[$name];
  165.                 }
  166.             }
  167.         }
  168.         return $result;
  169.     }
  170.     public function summaryDefault(array $params nullstring $field "amount"$onBeforeQueryChange null,
  171.                                    array $excludeMandatoryParams null, array $joinClasses null)
  172.     {
  173.         $query $this->summaryQueryDefault($params$onBeforeQueryChange$excludeMandatoryParams$joinClasses$field);
  174.         $result = (int)current($query->getQuery()->getResult()[0]);
  175.         return $result;
  176.     }
  177.     public function getDefault(array $params null$onBeforeQueryChange null, array $excludeMandatoryParams null,
  178.                                array $joinClasses nullint $limit null, array $orderBy null): array {
  179.         $query $this->getQuery($params$orderBy$onBeforeQueryChange,
  180.             $excludeMandatoryParamsfalse$joinClasses$limit);
  181.         $result $query->getQuery()->getResult();
  182.         return $result;
  183.     }
  184.     public function getFirst(array $params null$onBeforeQueryChange null, array $excludeMandatoryParams null,
  185.                              array $joinClasses null, array $orderBy null)
  186.     {
  187.         $result $this->getDefault($params$onBeforeQueryChange$excludeMandatoryParams$joinClasses1,
  188.             $orderBy);
  189.         if ($result) {
  190.             return $result[0];
  191.         } else {
  192.             return null;
  193.         }
  194.     }
  195.     public function summaryQueryDefault(array $params null$onBeforeQueryChange null, array $excludeMandatoryParams null,
  196.                                         array $joinClasses nullstring $field "amount")
  197.     {
  198.         $query $this->getQuery($paramsnull$onBeforeQueryChange$excludeMandatoryParamsfalse$joinClasses);
  199.         $query->select("sum(item.$field)");
  200.         return $query;
  201.     }
  202.     /**
  203.      * @param $paramName
  204.      * @param $paramValue
  205.      * @param \Doctrine\DBAL\Query\QueryBuilder|\Doctrine\ORM\QueryBuilder $query
  206.      * @param $sortedParams
  207.      * @return false
  208.      */
  209.     protected function handleNextQueryParam($paramName$paramValue$query$sortedParams$isSql) { //need override
  210.         return false;
  211.     }
  212.     /**
  213.      * @param array|null $params
  214.      * @param null|array{string, string} $orderBy
  215.      * @param $onBeforeQueryChange
  216.      * function(string $paramName, $paramValue, \Doctrine\DBAL\Query\QueryBuilder|\Doctrine\ORM\QueryBuilder $query): bool {}
  217.      * @param array|null $excludeMandatoryParams
  218.      * @param $isSql
  219.      * @param array|null $sortedDefaultQueryParams
  220.      * @return \Doctrine\DBAL\Query\QueryBuilder|QueryBuilder
  221.      * @throws \Exception
  222.      */
  223.     public function getQuery(array $params null,
  224.                              array $orderBy null$onBeforeQueryChange null, array $excludeMandatoryParams null$isSql false, array $joinClasses null,
  225.                              int $limit null)
  226.     {
  227.         $sortedParams $this->getSortedParams($params$excludeMandatoryParams);
  228.         $query = ($isSql
  229.             $this->em->getConnection()->createQueryBuilder()
  230.             : $this->em->getRepository($this->entityClassName)->createQueryBuilder('item'));
  231.         $select null;
  232.         if ($joinClasses) {
  233.             if ($isSql) {
  234.                 $select .= implode(", "array_map(function ($current) {
  235.                     return "item.$current";
  236.                 }, DoctrineUtils::getAllEntityFields($this->em$this->getEntityClassName(), $this->tableName)));
  237.             }
  238.             $lastJoinAlias "item";
  239.             foreach ($joinClasses as $class) {
  240.                 $table StringUtils::toCamel(self::getEntityShortName($class));
  241.                 $alias self::getEntityAliasByTableName($tablefalse);
  242.                 $metadata $this->em->getClassMetadata($class);
  243.                 if ($isSql) {
  244.                     $select .= ", " implode(", "array_map(function ($current) use ($alias) {
  245.                             return "$alias.$current";
  246.                         }, DoctrineUtils::getAllEntityFields($this->em$class$table)));
  247.                 }
  248.                 $field null;
  249.                 switch ($class) {
  250.                     case Machine::class:
  251.                         $field "machine_id";
  252.                         break;
  253.                     case Company::class:
  254.                         $field $isSql "company_id" "company";
  255.                         break;
  256.                     case Client::class:
  257.                         $field $isSql "client_id" "client";
  258.                         break;
  259.                     case Person::class:
  260.                         $field $isSql "person_id" "person";
  261.                         break;
  262.                     case CalendarEvent::class:
  263.                         $field $isSql "calendar_event_id" "calendarEvent";
  264.                         break;
  265.                     case Student::class:
  266.                         $field $isSql "student_id" "student";
  267.                         break;
  268.                     default:
  269.                         throw new \Exception("Unknown: " $class ". Entity: " $this->entityClassName);
  270.                 }
  271.                 if ($isSql) {
  272.                     $query->innerJoin($lastJoinAlias$table$alias"$lastJoinAlias.$field = $alias.id");
  273.                 } else {
  274.                     $query->innerJoin($class$aliasJoin::WITH"$lastJoinAlias.$field = $alias");
  275.                 }
  276.                 $lastJoinAlias $alias;
  277.             }
  278.         } else {
  279.             if ($isSql) {
  280.                 $select "*";
  281.             }
  282.         }
  283.         if ($isSql) {
  284.             $query->select($select);
  285.             $query->from($this->tableName"item");
  286.         }
  287.         foreach ($sortedParams as $paramName => $paramValue) {
  288.             if ($onBeforeQueryChange) {
  289.                 if ($onBeforeQueryChange($paramName$paramValue$query)) {
  290.                     continue;
  291.                 }
  292.             }
  293.             /** @var \Doctrine\DBAL\Query\QueryBuilder|\Doctrine\ORM\QueryBuilder $query */
  294.             if (!$this->handleNextQueryParam($paramName$paramValue$query$sortedParams$isSql)) {
  295.                 switch ($paramName) {
  296.                     case "id":
  297.                         if (is_array($paramValue)) {
  298.                             if ($isSql) {
  299.                                 $query->andWhere("item.id IN (" Other::objectToStringId($paramValue) . ")");
  300.                             } else {
  301.                                 $query->andWhere("item.id IN (:ids)")
  302.                                     ->setParameter('ids'$paramValue);
  303.                             }
  304.                         } else {
  305.                             if ($isSql) {
  306.                                 $query->andWhere("item.id = :id")
  307.                                     ->setParameter('id'$paramValue);
  308.                             } else {
  309.                                 $query->andWhere("item.id = :id")
  310.                                     ->setParameter('id'$paramValue);
  311.                             }
  312.                         }
  313.                         break;
  314.                     // case "type":
  315.                     // case "status":
  316.                     //     if ($isSql) {
  317.                     //         throw new \Exception("Not implemented");
  318.                     //     } else {
  319.                     //         $query->andWhere("item.$paramName = :$paramName")
  320.                     //             ->setParameter("$paramName", $paramValue);
  321.                     //     }
  322.                     //     break;
  323.                     case "company":
  324.                         if ($paramValue !== null) {
  325.                             if ($isSql) {
  326.                                 $query->andWhere("item.company_id = :companyId")
  327.                                     ->setParameter('companyId'$paramValue);
  328.                             } else {
  329.                                 $query->andWhere("item.company = :company")
  330.                                     ->setParameter("company"$paramValue);
  331.                             }
  332.                         }
  333.                         break;
  334.                     case "start":
  335.                         if ($paramValue !== null) {
  336.                             if ($isSql) {
  337.                                 $query->andWhere("item.{$this->getSqlField($this->dateFieldName)} >= :start and item.{$this->getSqlField($this->dateFieldName)} <= :end")
  338.                                     ->setParameter('start'$paramValue->format("Y-m-d H:i:s"))
  339.                                     ->setParameter('end'$sortedParams['end']->format("Y-m-d H:i:s"));
  340.                             } else {
  341.                                 $query->andWhere("item.{$this->dateFieldName} >= :start and item.{$this->dateFieldName} <= :end")
  342.                                     ->setParameter('start'$paramValue)
  343.                                     ->setParameter('end'$sortedParams['end']);
  344.                             }
  345.                         }
  346.                         break;
  347.                     case "end":
  348.                         //do nothing
  349.                         break;
  350.                     case "startTime":
  351.                         if ($paramValue !== null) {
  352.                             if ($isSql) {
  353.                                 $query->andWhere("time(item.{$this->getSqlField($this->dateFieldName)}) >= :startTime and time(item.{$this->getSqlField($this->dateFieldName)}) <= :endTime")
  354.                                     ->setParameter('startTime'$paramValue->format('H:i:s'))
  355.                                     ->setParameter('endTime'$sortedParams['endTime']->format('H:i:s'));
  356.                             } else {
  357.                                 throw new \Exception("Not available");
  358.                             }
  359.                         }
  360.                         break;
  361.                     case "endTime":
  362.                         //do nothing`
  363.                         break;
  364.                     case "machine":
  365.                         if ($paramValue !== null) {
  366.                             if (is_object($paramValue) && method_exists($paramValue"toArray") && get_class($paramValue) != Machine::class) {
  367.                                 $paramValue $paramValue->toArray();
  368.                             }
  369.                             if (!is_array($paramValue)) {
  370.                                 $paramValue = [$paramValue];
  371.                             }
  372.                             if ($isSql) {
  373.                                 $query->andWhere("item.machine_id in (" implode(", ",
  374.                                         array_map(function (Machine $machine) {return $machine->getId();}, $paramValue)) . ")");
  375.                             } else {
  376.                                 $query->andWhere("item.machine in (:machines)")
  377.                                     ->setParameter("machines"$paramValue);
  378.                             }
  379.                         }
  380.                         break;
  381.                     case "name":
  382.                         if ($paramValue !== null) {
  383.                             if ($isSql) {
  384.                                 throw new \Exception("Not implemented");
  385.                             } else {
  386.                                 $query->andWhere("item.name = :name")
  387.                                     ->setParameter("name"$paramValue);
  388.                             }
  389.                         }
  390.                         break;
  391.                     case "search":
  392.                         if ($paramValue !== null && $paramValue != "") {
  393.                             if ($isSql) {
  394.                                 throw new \Exception("Not implemented");
  395.                             } else {
  396.                                 $where "";
  397.                                 foreach ($this->getSearchFields() as $field) {
  398.                                     $where .= ($where " or " "") . "item.$field like :search";
  399.                                 }
  400.                                 $query->andWhere($where)
  401.                                     ->setParameter("search""%" $paramValue "%");
  402.                             }
  403.                         }
  404.                         break;
  405.                     default:
  406.                         if (is_bool($paramValue) && preg_match("/^is[A-Z0-9]/"$paramName)) {
  407.                             if ($paramValue === false) {
  408.                                 $query->andWhere("item.$paramName = 0 or item.$paramName is null");
  409.                             } else {
  410.                                 $query->andWhere("item.$paramName = 1");
  411.                             }
  412.                         } else if (is_array($paramValue) && (isset($paramValue["startDate"]) || isset($paramValue["endDate"]))) {
  413.                             if ($isSql) {
  414.                                 throw new \Exception("Not implemented");
  415.                             } else {
  416.                                 $tmpWhere "";
  417.                                 if (isset($paramValue["startDate"])) {
  418.                                     $tmpWhere .= "item.$paramName >= :{$paramName}StartDate";
  419.                                     $query->setParameter("{$paramName}StartDate"$paramValue['startDate']);
  420.                                 }
  421.                                 if (isset($paramValue["endDate"])) {
  422.                                     $tmpWhere .= ($tmpWhere " and " "") . "item.$paramName <= :{$paramName}EndDate";
  423.                                     $query->setParameter("{$paramName}EndDate"$paramValue['endDate']);
  424.                                 }
  425.                                 $query->andWhere($tmpWhere);
  426.                             }
  427.                         } else if (is_array($paramValue) && ReflectionUtils::isEntity(current($paramValue))) {
  428.                             $alias self::getEntityAlias($paramName);
  429.                             $query
  430.                                 ->join("item.$paramName"$alias)
  431.                                 ->andWhere("$alias.id in (:{$paramName}Ids)")
  432.                                 ->setParameter(":{$paramName}Ids"Other::objectToStringId($paramValue));
  433.                         } else if (is_array($paramValue) && is_string(current($paramValue))) {
  434.                             $query->andWhere("item.$paramName in (:{$paramName}Values)")
  435.                                 ->setParameter(":{$paramName}Values"$paramValue);
  436.                         } elseif  (is_array($paramValue) && is_int(current($paramValue))) {
  437.                             if ($isSql) {
  438.                                 $query->andWhere("item.$paramName in (" implode(", "$paramValue) . ")");
  439.                             } else {
  440.                                 $query->andWhere("item.$paramName in (:{$paramName}Ids)")
  441.                                     ->setParameter(":{$paramName}Ids"$paramValue);
  442.                             }
  443.                         } else {
  444.                             if ($isSql) {
  445.                                 throw new \Exception("Not implemented");
  446.                             } else {
  447.                                 if (strpos($paramName".") !== false) {
  448.                                     $query->andWhere("$paramName = :" str_replace(".""_"$paramName))
  449.                                         ->setParameter(str_replace(".""_"$paramName), $paramValue);
  450.                                 } else {
  451.                                     $query->andWhere("item.$paramName = :$paramName")
  452.                                         ->setParameter("$paramName"$paramValue);
  453.                                 }
  454.                             }
  455.                         }
  456.                 }
  457.             }
  458.         }
  459.         if ($orderBy) {
  460.             $query->orderBy("item.{$orderBy[0]}"$orderBy[1]);
  461.         }
  462.         if ($limit !== null) {
  463.             $query->setMaxResults($limit);
  464.         }
  465.         if (Other::canAddDebugLog()) {
  466.             Other::appendQueryLog(
  467.                 (get_class($query) == "Doctrine\ORM\QueryBuilder" "DQL: "  $query->getDQL() : "")
  468.                 . "\nSQL: " . (get_class($query) == "Doctrine\ORM\QueryBuilder" $query->getQuery()->getSQL() : $query->getSQL()));
  469.         }
  470.         return $query;
  471.     }
  472.     protected function getSqlField(string $field): string
  473.     {
  474.         if (isset($this->sqlFields[$field])) {
  475.             return $this->sqlFields[$field];
  476.         }
  477.         $this->sqlFields[$field] = StringUtils::toCamel($field);
  478.         return $this->sqlFields[$field];
  479.     }
  480.     public function getSortedParams(?array $params, ?array $excludeMandatoryParams): array
  481.     {
  482.         $sortedParams array_merge($this::$sortedDefaultQueryParams, ($params ?: []));
  483.         foreach ($this->getMandatoryParams() as $paramName) {
  484.             if ((!isset($sortedParams[$paramName]) || $sortedParams[$paramName] === null) && (!$excludeMandatoryParams || !in_array($paramName$excludeMandatoryParams))) {
  485.                 throw new \Exception("Обязательный параметр \"$paramName\" не задан. Добавьте параметр в \$params или добавьте в исключение \$excludeMandatoryParams"
  486.                     ". Сущность: " $this->entityClassName);
  487.             }
  488.         }
  489.         return $sortedParams;
  490.     }
  491.     public function getMandatoryParams(): array {
  492.         return self::MANDATORY_PARAMS;
  493.     }
  494.     protected function getSearchFields(): array {
  495.         return self::SEARCH_FIELDS;
  496.     }
  497.     /**
  498.      * @deprecated Устарело. Не использовать.
  499.      * Calls in getItemsBySearchWithPagination.
  500.      * Override if you need to modify query before search query execution.
  501.      * Example:
  502.      * For other entity joining.
  503.      * $query->innerJoin(Client::class, "client_", Join::WITH, "item.client = client_");
  504.      * @param QueryBuilder $query
  505.      * @return void
  506.      */
  507.     protected function setSearchQueryParams(QueryBuilder $query): void
  508.     {
  509.     }
  510.     public function setDateTimeProvider(DateTimeProviderInterface $dateTimeProvider)
  511.     {
  512.         $this->dateTimeProvider $dateTimeProvider;
  513.     }
  514.     public function setSystemTimeProvider()
  515.     {
  516.         $this->dateTimeProvider = new SystemDateTimeProvider();
  517.     }
  518.     public static function getEntityShortName(string $entityClassName): string
  519.     {
  520.         return (new \ReflectionClass($entityClassName))->getShortName();
  521.     }
  522.     public static function getEntityAlias(string $entityShortClassName): string
  523.     {
  524.         return lcfirst($entityShortClassName) . "_";
  525.     }
  526.     public static function getEntityAliasByTableName(string $tableNamebool $addUnderscore true): string
  527.     {
  528.         if (!str_contains($tableName"_")) {
  529.             return $tableName . ($addUnderscore "_" "");
  530.         }
  531.         $substrings explode("_"$tableName);
  532.         return $substrings[0] .
  533.             implode(""array_map(function ($current) {return ucfirst($current);}, array_splice($substrings1))) .
  534.             ($addUnderscore "_" "");
  535.     }
  536.     /**
  537.      * @deprecated Устарело. Не использовать.
  538.      */
  539.     public function setQueryParams(?QueryBuilder $query null, ?AnySearch $search null, ?Company $company,
  540.                                    ?\DateTime $start null, ?\DateTime $end null, ?array $orderBy null,
  541.                                    ?array $statuses null, ?Client $client null, array $carWashes null): QueryBuilder
  542.     {
  543.         return self::setQueryParamsByEm($this->em$this->entityClassName$this->dateFieldName,
  544.             $query$search$company$start$end$orderBy$statuses$client$this->searchDql$carWashes);
  545.     }
  546.     /**
  547.      * @deprecated Устарело. Не использовать.
  548.      */
  549.     public static function setQueryParamsByEm(EntityManagerInterface $emstring $entityClassNamestring $dateFieldName null,
  550.                                               ?QueryBuilder $query null, ?AnySearch $search null, ?Company $company,
  551.                                               ?\DateTime $start null, ?\DateTime $end null, ?array $orderBy null,
  552.                                               ?array $statuses null, ?Client $client nullstring $searchDql null,
  553.                                               array $carWashes null): QueryBuilder
  554.     {
  555.         $lostClients $search && $search->isLost() && $search->getLostDays();
  556.         if (!$query) {
  557.             $query $em->getRepository($entityClassName)->createQueryBuilder('item');
  558.         }
  559.         if ($company) {
  560.             $query->where('item.company = :company')
  561.                 ->setParameter("company"$company);
  562.         }
  563.         if ($carWashes && !$lostClients) {
  564.             $query->andWhere($query->expr()->in("carWash_"":carWashes"))->setParameter("carWashes"$carWashes);
  565.         }
  566.         if ($search && $search->getSearch() && $search->getSearch() != '') {
  567.             $query->andWhere($searchDql ?? 'item.id = :text or item.name like :text_like')
  568.                 ->setParameter('text'$search->getSearch())
  569.                 ->setParameter('text_like''%' $search->getSearch() . '%');
  570.         }
  571.         if ($start && $end && (!$search || !$search->isLost())) {
  572.             $query->andWhere("item.{$dateFieldName} >= :start and item.{$dateFieldName} <= :end")
  573.                 ->setParameter('start'$start)
  574.                 ->setParameter('end'$end);
  575.         }
  576.         if ($lostClients) {
  577.             $ids = [0];
  578.             $now = new \DateTime();
  579.             foreach ($em->getRepository(Client::class)->findBy(['company' => $company]) as $tmpClient) {
  580.                 /** @var Session $session */
  581.                 $session $em->getRepository(Session::class)->findOneBy(array_merge(['client' => $tmpClient],
  582.                     (!$carWashes ? [] : ['machine' => CarWashService::getCarWashesMachines($carWashesfalse)])), ['id' => 'DESC']);
  583.                 if ($session) {
  584.                     $dt = clone $session->getEndTime();
  585.                     $dt->modify('+'$search->getLostDays() .' days');
  586.                     if ($dt $now) {
  587.                         $ids[] = $tmpClient->getId();
  588.                         $search->clientLastSessionsDates[$tmpClient->getId()] = $session->getEndTime();
  589.                     }
  590.                 }
  591.             }
  592.             $query->andWhere('item.id in (:ids)')
  593.                 ->setParameter('ids'$ids);
  594.         }
  595.         if ($statuses) {
  596.             if (!is_array($statuses)) {
  597.                 $statuses = [$statuses];
  598.             }
  599.             $query->andWhere($query->expr()->in('item.status'':statuses'))
  600.                 ->setParameter('statuses'$statuses);
  601.         }
  602.         if ($client) {
  603.             $query->andWhere('item.client = :client')
  604.                 ->setParameter("client"$client);
  605.         }
  606.         if ($orderBy) {
  607.             $query->orderBy("item.{$orderBy[0]}"$orderBy[1]);
  608.         }
  609.         return $query;
  610.     }
  611.     /**
  612.      * @deprecated Устарело. Не использовать.
  613.      * @psalm-param array<string, string>|null $orderBy
  614.      * @return array
  615.      */
  616.     public function getItemsBySearchWithPagination(?AnySearch $search null, ?Company $company null,
  617.                                                    ?\DateTime $start null, ?\DateTime $end null, ?array $orderBy null,
  618.                                                    ?array     $statuses null$queryCallback null, array $carWashes null,
  619.                                                    Client $client null, array $options nullRouteParamObjects $routeObjects null): array
  620.     {
  621.         if ($routeObjects && $routeObjects->getCarWash()) {
  622.             $carWashes = [$routeObjects->getCarWash()];
  623.         }
  624.         $query $this->createQuery($search$company$start$end$orderBy$statuses$client$queryCallbacktrue,
  625.             $carWashes);
  626.         $result Paginator::getResult($query, ($search->getPage() && $search->getPage() > 0) ? $search->getPage() : 1,
  627.             Paginator::PER_PAGEfalse);
  628.         if (isset($options['sortByPostId']) && $options['sortByPostId']) {
  629.             $result["list"] = $this->sortMachinesByPostId($result["list"]);
  630.         }
  631.         return $result;
  632.     }
  633.     /**
  634.      * @deprecated Устарело. Не использовать.
  635.      * @psalm-param array<string, string>|null $orderBy
  636.      */
  637.     public function createQuery(?AnySearch $search null, ?Company $company null,
  638.                                 ?\DateTime $start null, ?\DateTime $end null, ?array $orderBy null,
  639.                                 ?array     $statuses null$client null$queryCallback nullbool $setCommonSearchQueryParams false,
  640.                                 array $carWashes null): QueryBuilder
  641.     {
  642.         $query $this->em->getRepository($this->entityClassName)->createQueryBuilder('item');
  643.         if ($setCommonSearchQueryParams) {
  644.             $this->setSearchQueryParams($query);
  645.         }
  646.         /** @var QueryBuilder $q */
  647.         $q $this->setQueryParams($query$search$company$start$end$orderBy$statuses$client$carWashes);
  648.         if ($queryCallback) {
  649.             $queryCallback($q);
  650.         }
  651.         return $query;
  652.     }
  653.     /**
  654.      * @deprecated Устарело. Не использовать.
  655.      * @psalm-param array<string, string>|null $orderBy
  656.      * @return array
  657.      */
  658.     public function getQueryBySearchWithPagination(?AnySearch $search null, ?Company $company null,
  659.                                                    ?\DateTime $start null, ?\DateTime $end null, ?array $orderBy null,
  660.                                                    ?array     $statuses null): QueryBuilder
  661.     {
  662.         $query $this->em->getRepository($this->entityClassName)->createQueryBuilder('item');
  663.         $this->setSearchQueryParams($query);
  664.         $q $this->setQueryParams($query$search$company$start$end$orderBy$statuses);
  665.         return $q;
  666.     }
  667.     /**
  668.      * @deprecated Устарело. Не использовать.
  669.      * @param $fieldName
  670.      * @param AnySearch $search
  671.      * @param Company|null $company
  672.      * @param \DateTime|null $start
  673.      * @param \DateTime|null $end
  674.      * @return float|int|mixed|string
  675.      * @throws \Doctrine\ORM\NoResultException
  676.      * @throws \Doctrine\ORM\NonUniqueResultException
  677.      */
  678.     public function getSummaryByField($fieldName "amount", ?AnySearch $search null, ?Company $company null,
  679.                                       ?\DateTime $start null, ?\DateTime $end null, ?Client $client null,
  680.                                       ?array $statuses null$queryCallback nullbool $setCommonSearchParams false)
  681.     {
  682.         $q $this->createQuery($search$company$start$endnull$statuses$client$queryCallback$setCommonSearchParams);
  683.         $q->select("sum(item.$fieldName)");
  684.         $result $q->getQuery()->getSingleScalarResult();
  685.         if ($result === null) {
  686.             $result 0;
  687.         }
  688.         return $result;
  689.     }
  690.     /**
  691.      * @param string|array $whereConditions
  692.      * @param array|null $joinConditions
  693.      * @param string|null $select
  694.      * @param string|null $groupBy
  695.      * @return array
  696.      */
  697.     public function getByExpression($whereConditions = [], array $joinConditions nullstring $select null,
  698.                                     string $groupBy null): array
  699.     {
  700.         return self::getByExpressionWithEm($this->em$this->entityClassName$this->entityAlias$whereConditions,
  701.             $joinConditions$select$groupBy);
  702.     }
  703.     /**
  704.      * @param array $whereConditions
  705.      * @param array|null $joinConditions
  706.      * @param string|null $select
  707.      * @param string|null $groupBy
  708.      * @return mixed
  709.      */
  710.     public function getOnyByExpression(array $whereConditions = [], array $joinConditions nullstring $select null,
  711.                                        string $groupBy null)
  712.     {
  713.         $result self::getByExpressionWithEm($this->em$this->entityClassName$this->entityAlias$whereConditions,
  714.             $joinConditions$select$groupBy);
  715.         if ($result == []) {
  716.             return null;
  717.         }  else {
  718.             if (count($result) > 1) {
  719.                 throw new \Exception('Found more than one');
  720.             }
  721.             return $result[0];
  722.         }
  723.     }
  724.     /**
  725.      * @param array $whereConditions
  726.      * @param array|null $joinConditions
  727.      * @param string|null $select
  728.      * @param string|null $groupBy
  729.      * @return QueryBuilder
  730.      */
  731.     public function getQueryByExpression(array $whereConditions = [], array $joinConditions nullstring $select null,
  732.                                          string $groupBy null)
  733.     {
  734.         return self::getQueryByExpressionWithEm($this->em$this->entityClassName$this->entityAlias$whereConditions,
  735.             $joinConditions$select$groupBy);
  736.     }
  737.     /**
  738.      * @deprecated Устарело. Не использовать.
  739.      * @param EntityManagerInterface $em
  740.      * @param string $entityClassName
  741.      * @param string|null $entityAlias
  742.      * @param string|array $whereConditions
  743.      * @param array|null $joinExpressions
  744.      * @param string|null $select
  745.      * @param string|null $groupBy
  746.      * @return array
  747.      */
  748.     public static function getByExpressionWithEm(EntityManagerInterface $emstring $entityClassNamestring $entityAlias null,
  749.                                                                         $whereConditions = [], $joinExpressions nullstring $select null,
  750.                                                  string $groupBy nullint $limit 0): array
  751.     {
  752.         $q self::getQueryByExpressionWithEm($em$entityClassName$entityAlias$whereConditions$joinExpressions$select$groupBy$limit);
  753.         $result $q->getQuery()->getResult();
  754.         return $result;
  755.     }
  756.     /**
  757.      * @deprecated Устарело. Не использовать.
  758.      * @param string|array $whereConditions
  759.      * [Key = 'left expression part', value = 'expression value'].
  760.      * Example: [
  761.      *             "bonusPercentUpdatedAt !=" => "null",
  762.      *             "status" => [Status::STATUS1, Status::STATUS2]
  763.      *          ]
  764.      *
  765.      * @param array|null $joinExpressions
  766.      * ['joinEntityName', 'joinEntityCondition', 'joinEntityWhereExpression', 'joinEntityWhereValue']
  767.      * Example: ['cashbackRule', "id = client_.cashbackRule", 'status =', Status::STATUS_ACTIVE]
  768.      *
  769.      * @return QueryBuilder
  770.      */
  771.     public static function getQueryByExpressionWithEm(EntityManagerInterface $emstring $entityClassNamestring $entityAlias null,
  772.                                                                              $whereConditions = [], array $joinExpressions nullstring $select null,
  773.                                                       string $groupBy nullint $limit 0)
  774.     {
  775.         if (!$entityAlias) {
  776.             $entityAlias self::getEntityAlias(self::getEntityShortName($entityClassName));
  777.         }
  778.         $q $em->getRepository($entityClassName)->createQueryBuilder($entityAlias);
  779.         if ($select) {
  780.             $q->select($select);
  781.         }
  782.         if ($joinExpressions) {
  783.             if (!is_array($joinExpressions[0])) {
  784.                 $joinExpressions = [$joinExpressions];
  785.             }
  786.             $joinParamIndex 0;
  787.             foreach ($joinExpressions as $joinParams) {
  788.                 $joinEntity $joinParams[0];
  789.                 $joinEntityAlias "{$joinEntity}_";
  790.                 $joinCondition $joinParams[1];
  791.                 $joinWhereExpression $joinParams[2] ?? null;
  792.                 $joinWhereValue $joinParams[3] ?? null;
  793.                 $q $q->innerJoin("$entityAlias.$joinEntity"$joinEntityAlias"WITH""$joinEntityAlias.$joinCondition");
  794.                 $joinParamIndex++;
  795.                 $joinParamName "joinParam$joinParamIndex";
  796.                 if ($joinWhereExpression) {
  797.                     $q->andWhere("$joinEntityAlias.$joinWhereExpression :$joinParamName")
  798.                         ->setParameter($joinParamName$joinWhereValue);
  799.                 }
  800.             }
  801.         }
  802.         if (is_string($whereConditions)) {
  803.             $q->where($whereConditions);
  804.         } else {
  805.             $paramIndex 0;
  806.             foreach ($whereConditions as $leftExpressionPart => $value) {
  807.                 $or false;
  808.                 if (str_starts_with(strtolower($leftExpressionPart), "or ")) {
  809.                     $or true;
  810.                     $leftExpressionPart substr($leftExpressionPart3);
  811.                 }
  812.                 $paramIndex++;
  813.                 $paramName "param$paramIndex";
  814.                 if (is_object($value) && strpos(get_class($value), "App\Entity") !== && method_exists($value"toArray")) {
  815.                     $value $value->toArray();
  816.                 }
  817.                 if ($or) {
  818.                     if (is_array($value)) {
  819.                         $q
  820.                             ->orWhere($q->expr()->in("$entityAlias.$leftExpressionPart"":$paramName"))
  821.                             ->setParameter($paramName$value);
  822.                     } else {
  823.                         if ($value === null) {
  824.                             $q
  825.                                 ->orWhere("$entityAlias.$leftExpressionPart null");
  826.                         } else {
  827.                             $q
  828.                                 ->orWhere("$entityAlias.$leftExpressionPart :$paramName")
  829.                                 ->setParameter($paramName$value);
  830.                         }
  831.                     }
  832.                 } else {
  833.                     if (is_array($value)) {
  834.                         $q
  835.                             ->andWhere($q->expr()->in("$entityAlias.$leftExpressionPart"":$paramName"))
  836.                             ->setParameter($paramName$value);
  837.                     } else {
  838.                         if ($value === null) {
  839.                             $q
  840.                                 ->andWhere("$entityAlias.$leftExpressionPart null");
  841.                         } else {
  842.                             $q
  843.                                 ->andWhere("$entityAlias.$leftExpressionPart :$paramName")
  844.                                 ->setParameter($paramName$value);
  845.                         }
  846.                     }
  847.                 }
  848.             }
  849.         }
  850.         if ($groupBy) {
  851.             $q->groupBy($groupBy);
  852.         }
  853.         if ($limit) {
  854.             $q->setMaxResults($limit);
  855.         }
  856.         return $q;
  857.     }
  858.     /**
  859.      * @param array $whereConditions
  860.      * @param array|null $joinConditions
  861.      * @param string|null $select
  862.      * @param string|null $groupBy
  863.      * @return array
  864.      */
  865.     public function getBySqlExpression(array $whereConditions = [], array $joinConditions nullstring $select null,
  866.                                        string $groupBy nullstring $tableName nullint $limit null): array
  867.     {
  868.         return self::getBySqlExpressionWithEm($this->em$this->entityClassName,
  869.             (!$tableName $this->entityAlias self::getEntityAliasByTableName($tableName)),
  870.             $whereConditions$joinConditions$select$groupBy, ($tableName ?? $this->tableName), $limit);
  871.     }
  872.     /**
  873.      * @deprecated Устарело. Не использовать.
  874.      * @param array $whereConditions
  875.      * @param array|null $joinConditions
  876.      * @param string|null $select
  877.      * @param string|null $groupBy
  878.      * @return \Doctrine\DBAL\Query\QueryBuilder
  879.      */
  880.     public function getQueryBySqlExpression(array $whereConditions = [], array $joinConditions nullstring $select null,
  881.                                             string $groupBy nullstring $tableName nullint $limit null)
  882.     {
  883.         return self::getQueryBySqlExpressionWithEm($this->em$this->entityClassName,
  884.             (!$tableName $this->entityAlias self::getEntityAliasByTableName($tableName)), $whereConditions,
  885.             $joinConditions$select$groupBy, ($tableName ?? $this->tableName), $limit);
  886.     }
  887.     /**
  888.      * @deprecated Устарело. Не использовать.
  889.      * @param EntityManagerInterface $em
  890.      * @param string $entityClassName
  891.      * @param string|null $entityAlias
  892.      * @param array $whereConditions
  893.      * @param array|null $joinExpressions
  894.      * @param string|null $select
  895.      * @param string|null $groupBy
  896.      */
  897.     public static function getBySqlExpressionWithEm(EntityManagerInterface $emstring $entityClassNamestring $entityAlias null,
  898.                                                     array $whereConditions = [], array $joinExpressions nullstring $select null,
  899.                                                     string $groupBy nullstring $tableName nullint $limit null): array
  900.     {
  901.         $q self::getQueryBySqlExpressionWithEm($em$entityClassName$entityAlias$whereConditions$joinExpressions$select$groupBy$tableName$limit);
  902.         $stmt $q->execute();
  903.         $result is_bool($stmt) ? $q->fetchAll() : $stmt->fetchAll();
  904.         return $result;
  905.     }
  906.     /**
  907.      * @deprecated Устарело. Не использовать.
  908.      * @param array $whereConditions
  909.      * [Key = 'left expression part', value = 'expression value'].
  910.      * Example: [
  911.      *             "bonusPercentUpdatedAt !=" => "null",
  912.      *             "status" => [Status::STATUS1, Status::STATUS2]
  913.      *          ]
  914.      *
  915.      * @param array|null $joinExpressions
  916.      * ['joinTableName', 'joinColumnCondition', 'joinColumnWhereExpression', 'joinColumnWhereValue', 'joinType']
  917.      * Example: ['client', "id = bonus.client_id", 'company_id =', 116, "left"]
  918.      *
  919.      * @return \Doctrine\DBAL\Query\QueryBuilder
  920.      */
  921.     public static function getQueryBySqlExpressionWithEm(EntityManagerInterface $emstring $entityClassNamestring $entityAlias null,
  922.                                                          array $whereConditions = [], array $joinExpressions nullstring $select null,
  923.                                                          string $groupBy nullstring $tableName nullint $limit null)
  924.     {
  925.         if (!$entityAlias) {
  926.             $entityAlias self::getEntityAlias(self::getEntityShortName($entityClassName));
  927.         }
  928.         if (!$tableName) {
  929.             throw new \Exception("\$tableName is not set");
  930.         }
  931.         $connection $em->getConnection();
  932.         $q $connection->createQueryBuilder()
  933.             ->select($select ?? "$entityAlias.id")
  934.             ->from($tableName$entityAlias);
  935.         if ($joinExpressions) {
  936.             if (!is_array($joinExpressions[0])) {
  937.                 $joinExpressions = [$joinExpressions];
  938.             }
  939.             foreach ($joinExpressions as $joinParams) {
  940.                 $joinTableName $joinParams[0];
  941.                 $joinEntityAlias self::getEntityAliasByTableName($joinTableName);
  942.                 $joinCondition $joinParams[1];
  943.                 $joinWhereExpression $joinParams[2] ?? null;
  944.                 $joinWhereValue $joinParams[3] ?? null;
  945.                 $preparedValue self::prepareSqlValue($joinWhereValue);
  946.                 $joinType $joinParams[4] ?? null;
  947.                 switch ($joinType) {
  948.                     case null:
  949.                     case "inner":
  950.                         $q $q->innerJoin($entityAlias$joinTableName$joinEntityAlias"$joinEntityAlias.$joinCondition");
  951.                         break;
  952.                     case "left":
  953.                         $q $q->leftJoin($entityAlias$joinTableName$joinEntityAlias"$joinEntityAlias.$joinCondition");
  954.                         break;
  955.                     default:
  956.                         throw new \Exception("Unknown: $joinType". Entity: " $entityClassName);
  957.                 }
  958.                 if ($joinWhereExpression) {
  959.                     if (is_array($joinWhereValue)) {
  960.                         $q->andWhere("$joinEntityAlias.$joinWhereExpression in ($preparedValue)");
  961.                     } else {
  962.                         $q->andWhere("$joinEntityAlias.$joinWhereExpression $preparedValue");
  963.                     }
  964.                 }
  965.             }
  966.         }
  967.         foreach ($whereConditions as $leftExpressionPart => $value) {
  968.             $or false;
  969.             if (str_starts_with(strtolower($leftExpressionPart), "or ")) {
  970.                 $or true;
  971.                 $leftExpressionPart substr($leftExpressionPart3);
  972.             }
  973.             $isFullExpression is_numeric($leftExpressionPart);
  974.             $preparedValue self::prepareSqlValue($value);
  975.             if ($isFullExpression) {
  976.                 $q->andWhere($value);
  977.             } else {
  978.                 if ($or) {
  979.                     if (is_array($value)) {
  980.                         $q->orWhere("$entityAlias.$leftExpressionPart in ($preparedValue)");
  981.                     } else {
  982.                         $q->orWhere("$entityAlias.$leftExpressionPart $preparedValue");
  983.                     }
  984.                 } else {
  985.                     if (is_array($value)) {
  986.                         $q->andWhere("$entityAlias.$leftExpressionPart in ($preparedValue)");
  987.                     } else {
  988.                         $q->andWhere("$entityAlias.$leftExpressionPart $preparedValue");
  989.                     }
  990.                 }
  991.             }
  992.         }
  993.         if ($groupBy) {
  994.             $q->groupBy($groupBy);
  995.         }
  996.         if ($limit) {
  997.             $q->setMaxResults($limit);
  998.         }
  999.         return $q;
  1000.     }
  1001.     /**
  1002.      * @param $value
  1003.      * @return mixed|string|int
  1004.      */
  1005.     private static function prepareSqlValue($value)
  1006.     {
  1007.         if ($value === null) {
  1008.             $value "null";
  1009.         } else if (is_string($value) && !str_starts_with($value"'") && !str_starts_with($value"\"")) {
  1010.             $value "'" $value "'";
  1011.         } else if (is_array($value)) {
  1012.             $value implode(", "$value);
  1013.         }
  1014.         return $value;
  1015.     }
  1016.     /**
  1017.      * @deprecated Устарело. Не использовать.
  1018.      */
  1019.     public function getBy(array $criteria, ?Company $company null): array
  1020.     {
  1021.         if ($company) {
  1022.             $criteria['company'] = $company;
  1023.         }
  1024.         return $this->em->getRepository($this->entityClassName)->findBy($criteria);
  1025.     }
  1026.     /**
  1027.      * @deprecated Устарело. Не использовать.
  1028.      */
  1029.     public function getOneBy(array $criteria, ?Company $company null)
  1030.     {
  1031.         if ($company) {
  1032.             $criteria['company'] = $company;
  1033.         }
  1034.         return $this->em->getRepository($this->entityClassName)->findOneBy($criteria);
  1035.     }
  1036.     public function getMachineIds(array $machines$addZeroId false): array
  1037.     {
  1038.         $result array_map(function ($machine) {return $machine->getId();}, $machines);
  1039.         if ($addZeroId) {
  1040.             array_unshift($result0);
  1041.         }
  1042.         return $result;
  1043.     }
  1044.     public function getMultiDimensionalSqlResultsByMachineIdAndDate(array $sqlResults, array $additionalFieldsBefore null,
  1045.                                                                     array $additionalFieldsAfter null): array
  1046.     {
  1047.         return DoctrineUtils::getMultiDimensionalSqlResults($sqlResults,
  1048.             array_merge(($additionalFieldsBefore ?? []), ["machine_id""date"], ($additionalFieldsAfter ?? [])));
  1049.     }
  1050.     public function getSessionsServiceSecSumSelectSql(string $tableAlias): string
  1051.     {
  1052.         $select '';
  1053.         for ($num 1$num <= Machine::maxServiceNum$num++) {
  1054.             $select .= ($select ",\n" '') . "SUM($tableAlias.service{$num}sec) as service{$num}sec";
  1055.         }
  1056.         return $select;
  1057.     }
  1058.     public function getSessionServiceSecSumSelectSql(string $tableAliasbool $paidPauseSec false): string
  1059.     {
  1060.         $select '';
  1061.         for ($num 1$num <= Machine::maxServiceNum$num++) {
  1062.             $select .= ($select " + " '') . "$tableAlias.service{$num}sec";
  1063.         }
  1064.         if ($paidPauseSec) {
  1065.             $select .= " + $tableAlias.paid_pause_sec";
  1066.         }
  1067.         return $select;
  1068.     }
  1069.     public function getSessionAmountsSumSelectSql(string $tableAlias): string
  1070.     {
  1071.         $arrayFields = ['coin_amount''note_amount''no_cash_amount''cash_sess''card_sess''bonus_for_session'];
  1072.         $select "";
  1073.         foreach ($arrayFields as $field) {
  1074.             $select .= ($select ",\n " "") . "IFNULL(SUM($tableAlias.$field), 0) as $field";
  1075.         }
  1076.         return $select;
  1077.     }
  1078.     public function getMachinePaymentsSummary(array $data): float
  1079.     {
  1080.         return $data["payments_qr_amount"] + $data["payments_yandex_amount"];
  1081.     }
  1082.     public function getMachinesMethodParameter($machine)
  1083.     {
  1084.         $machines $machine;
  1085.         if (!is_array($machines)) {
  1086.             $machines = [$machine];
  1087.         }
  1088.         return $machines;
  1089.     }
  1090.     /**
  1091.      * @return null
  1092.      */
  1093.     public function getEntityClassName()
  1094.     {
  1095.         return $this->entityClassName;
  1096.     }
  1097.     public function getIncomeMoneyFields(bool $refusual false): array
  1098.     {
  1099.         $result = ["coin_amount""note_amount""no_cash_amount""ping_amount""qr_amount"];
  1100.         if ($refusual) {
  1101.             $result[] = "refusual";
  1102.         }
  1103.         return $result;
  1104.     }
  1105.     public function getAllMoneyFields(): array
  1106.     {
  1107.         return ["note_amount""no_cash_amount""payments_qr_amount""payments_yandex_amount""refusual",
  1108.             "gross_profit""server_bonus""bonus_for_session""card_sess"];
  1109.     }
  1110.     public function getServiceSecFields(): array
  1111.     {
  1112.         if (self::$serviceSecFields) {
  1113.             return self::$serviceSecFields;
  1114.         }
  1115.         $result = [];
  1116.         for ($i 1$i <= Machine::maxServiceNum$i++) {
  1117.             $result[] = "service{$i}sec";
  1118.         }
  1119.         $result[] = "paid_pause_sec";
  1120.         self::$serviceSecFields $result;
  1121.         return $result;
  1122.     }
  1123.     public function createOrGetDefault(array $params)
  1124.     {
  1125.         $item $this->getFirst($params);
  1126.         if (!$item) {
  1127.             $item = (new $this->entityClassName());
  1128.             foreach ($params as $key => $value) {
  1129.                 $setter 'set' ucfirst($key);
  1130.                 $item->$setter($value);
  1131.             }
  1132.             $this->saveDefault($item);
  1133.         }
  1134.         return $item;
  1135.     }
  1136.     public function saveDefault($item)
  1137.     {
  1138.         $this->em->persist($item);
  1139.         $this->em->flush();
  1140.     }
  1141.     public function removeDefault($item$flush true)
  1142.     {
  1143.         $this->em->remove($item);
  1144.         if ($flush) {
  1145.             $this->em->flush();
  1146.         }
  1147.     }
  1148.     public function serializeDefault($item, array $includeFields null, array $excludeFields null): string
  1149.     {
  1150.         return $this->serializer->serialize($item'json', [
  1151.             'attributes' => $includeFields,
  1152.             'ignored_attributes' => $excludeFields
  1153.         ]);
  1154.     }
  1155.     public function getSameItemCheckFields(): array
  1156.     {
  1157.         throw new \Exception("Not implemented");
  1158.     }
  1159.     public function hasSameDefault($item): bool
  1160.     {
  1161.         $fields $this->getSameItemCheckFields();
  1162.         $criteria = [];
  1163.         foreach ($fields as $field) {
  1164.             $getter 'get' ucfirst($field);
  1165.             if ($item->$getter() !== null) {
  1166.                 $criteria[$field] = $item->$getter();
  1167.             }
  1168.         }
  1169.         $same $this->getDefault($criteria);
  1170.         foreach ($same as $sameItem) {
  1171.             if ($sameItem->getId() != $item->getId()) {
  1172.                 return true;
  1173.             }
  1174.         }
  1175.         return false;
  1176.     }
  1177.     public function removeForeignKeyConstraintEntities($entity$foreignEntitystring $foreignEntityField)
  1178.     {
  1179.         if ($foreignEntity) {
  1180.             $this->em->remove($foreignEntity);
  1181.         }
  1182.         if ($entity) {
  1183.             $setter 'set' ucfirst($foreignEntityField);
  1184.             $entity->$setter(null);
  1185.             $this->em->flush();
  1186.         } else {
  1187.             $this->em->flush();
  1188.         }
  1189.         $this->removeDefault($entity);
  1190.     }
  1191. }