mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
255 lines
8.2 KiB
PHP
255 lines
8.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* For the full copyright and license information, please view
|
|
* the LICENSE file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Chill\ThirdPartyBundle\Repository;
|
|
|
|
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
|
use Doctrine\DBAL\Connection;
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
use Doctrine\ORM\EntityRepository;
|
|
use Doctrine\ORM\Query;
|
|
use Doctrine\ORM\QueryBuilder;
|
|
use Doctrine\Persistence\ObjectRepository;
|
|
|
|
class ThirdPartyRepository implements ObjectRepository
|
|
{
|
|
private readonly EntityRepository $repository;
|
|
|
|
public function __construct(EntityManagerInterface $em, private readonly Connection $connection)
|
|
{
|
|
$this->repository = $em->getRepository(ThirdParty::class);
|
|
}
|
|
|
|
public function findThirdpartiesWithContacts(string $lang): iterable
|
|
{
|
|
$sql = "
|
|
SELECT
|
|
parent.id AS Id,
|
|
CASE
|
|
WHEN parent.kind = 'company' THEN 'Personne morale'
|
|
ELSE 'Personne physique'
|
|
END AS kind,
|
|
parent_civility.name->>? AS civility,
|
|
parent.firstname AS firstname,
|
|
parent.name AS name,
|
|
parent.profession AS profession,
|
|
parent.telephone AS telephone,
|
|
parent.telephone2 AS telephone2,
|
|
parent.email AS email,
|
|
CONCAT_WS(' ', parent_address.street, parent_address.streetnumber, parent_postal.code, parent_postal.label) AS address,
|
|
parent.comment AS comment,
|
|
parent.parent_id AS parent,
|
|
parent.name_company AS name_company,
|
|
parent.acronym AS acronym,
|
|
CASE WHEN parent.active THEN 'X' ELSE '' END AS active,
|
|
|
|
-- Contact (child third-party) details
|
|
contact.id AS contact_id,
|
|
contact.name AS contact_name,
|
|
contact.firstname AS contact_firstname,
|
|
contact.telephone AS contact_phone,
|
|
contact.telephone2 AS contact_phone2,
|
|
contact.email AS contact_email,
|
|
contact.profession AS contact_profession,
|
|
CONCAT_WS(' ', contact_address.street, contact_address.streetnumber, contact_postal.code, contact_postal.label) AS contact_address
|
|
|
|
FROM chill_3party.third_party parent
|
|
LEFT JOIN chill_main_civility parent_civility ON parent.civility_id = parent_civility.id
|
|
LEFT JOIN chill_main_address parent_address ON parent.address_id = parent_address.id
|
|
LEFT JOIN chill_main_postal_code parent_postal ON parent_address.postcode_id = parent_postal.id
|
|
|
|
-- Join contacts (child third parties)
|
|
LEFT JOIN chill_3party.third_party contact ON contact.parent_id = parent.id
|
|
LEFT JOIN chill_main_address contact_address ON contact.address_id = contact_address.id
|
|
LEFT JOIN chill_main_postal_code contact_postal ON contact_address.postcode_id = contact_postal.id
|
|
|
|
-- Exclude contacts from appearing as standalone rows
|
|
WHERE parent.parent_id IS NULL
|
|
|
|
-- Sorting order
|
|
ORDER BY parent.name ASC, parent.name_company ASC, parent.id ASC,
|
|
contact.name ASC, contact.firstname ASC, contact.id ASC
|
|
";
|
|
|
|
return $this->connection->iterateAssociative($sql, [$lang]);
|
|
}
|
|
|
|
/**
|
|
* count amongst parties associated to $centers, with $terms parameters.
|
|
*/
|
|
public function countByMemberOfCenters(array $centers, array $terms = []): int
|
|
{
|
|
$qb = $this->buildQuery($centers, $terms);
|
|
$qb->select('COUNT(tp)');
|
|
|
|
return $qb->getQuery()->getSingleScalarResult();
|
|
}
|
|
|
|
public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder
|
|
{
|
|
return $this->repository->createQueryBuilder($alias, $indexBy);
|
|
}
|
|
|
|
public function find($id): ?ThirdParty
|
|
{
|
|
return $this->repository->find($id);
|
|
}
|
|
|
|
/**
|
|
* @return array|ThirdParty[]
|
|
*/
|
|
public function findAll(): array
|
|
{
|
|
return $this->repository->findAll();
|
|
}
|
|
|
|
/**
|
|
* @param null $limit
|
|
* @param null $offset
|
|
*
|
|
* @return array|ThirdParty[]
|
|
*/
|
|
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
|
{
|
|
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
|
}
|
|
|
|
/**
|
|
* Search amongst parties associated to $centers, with $terms parameters.
|
|
*
|
|
* Different format for return:
|
|
* - ['entity']: return the entity hydrated as objects
|
|
* - ['array', [ DQL ]: return objects hydrated as entity, with
|
|
* an array describing the fields as DQL.
|
|
*
|
|
* supported terms:
|
|
*
|
|
* - name or _default: containing the name (name LIKE %string%)
|
|
* - is_active: is active = true / false
|
|
* - types: an array of types
|
|
*
|
|
* @param int $firstResult
|
|
* @param int $maxResults
|
|
* @param array $terms
|
|
* @param string[] $returnFormat a format for returning
|
|
*/
|
|
public function findByMemberOfCenters(array $centers, $firstResult = 0, $maxResults = 20, $terms = [], $returnFormat = ['entity']): array
|
|
{
|
|
$qb = $this->buildQuery($centers, $terms);
|
|
|
|
switch ($returnFormat[0]) {
|
|
case 'entity':
|
|
$qb->select('tp');
|
|
$hydrate = Query::HYDRATE_OBJECT;
|
|
|
|
break;
|
|
|
|
case 'array':
|
|
$hydrate = Query::HYDRATE_ARRAY;
|
|
$first = true;
|
|
|
|
foreach ($returnFormat[1] as $dql) {
|
|
if ($first) {
|
|
$qb->select($dql);
|
|
$first = false;
|
|
} else {
|
|
$qb->addSelect($dql);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
throw new \DomainException('This return format is invalid');
|
|
}
|
|
$qb->setFirstResult($firstResult)
|
|
->setMaxResults($maxResults);
|
|
|
|
return $qb->getQuery()->getResult();
|
|
}
|
|
|
|
public function findOneBy(array $criteria): ?ThirdParty
|
|
{
|
|
return $this->repository->findOneBy($criteria);
|
|
}
|
|
|
|
public function getClassName(): string
|
|
{
|
|
return ThirdParty::class;
|
|
}
|
|
|
|
private function buildQuery($centers, $terms): QueryBuilder
|
|
{
|
|
$qb = $this->createMemberOfCentersQuery($centers);
|
|
$this->setNameCondition($qb, $terms);
|
|
$this->setTypesCondition($qb, $terms);
|
|
$this->setIsActiveCondition($qb, $terms);
|
|
|
|
return $qb;
|
|
}
|
|
|
|
private function createMemberOfCentersQuery($centers): QueryBuilder
|
|
{
|
|
$qb = $this->createQueryBuilder('tp');
|
|
|
|
$or = $qb->expr()->orX();
|
|
|
|
foreach ($centers as $center) {
|
|
$or->add($qb->expr()->isMemberOf(':center_'.$center->getId(), 'tp.centers'));
|
|
$qb->setParameter('center_'.$center->getId(), $center);
|
|
}
|
|
|
|
$qb->where($or);
|
|
|
|
return $qb;
|
|
}
|
|
|
|
private function setIsActiveCondition(QueryBuilder $qb, array $terms)
|
|
{
|
|
if (\array_key_exists('is_active', $terms)) {
|
|
$qb->andWhere(
|
|
$terms['is_active'] ? $qb->expr()->eq('tp.active', "'TRUE'") :
|
|
$qb->expr()->eq('tp.active', "'FALSE'")
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add parameters to filter by containing $terms["name"] or
|
|
* $terms["_default"].
|
|
*/
|
|
private function setNameCondition(QueryBuilder $qb, array $terms)
|
|
{
|
|
if (\array_key_exists('name', $terms) || \array_key_exists('_default', $terms)) {
|
|
$term = $terms['name'] ?? $terms['_default'];
|
|
|
|
if (null === $term || '' === $term) {
|
|
return;
|
|
}
|
|
$qb->andWhere($qb->expr()->like('UNACCENT(LOWER(tp.name))', 'UNACCENT(LOWER(:name))'));
|
|
$qb->setParameter('name', '%'.$term.'%');
|
|
}
|
|
}
|
|
|
|
private function setTypesCondition(QueryBuilder $qb, array $terms)
|
|
{
|
|
if (\array_key_exists('types', $terms)) {
|
|
$orx = $qb->expr()->orX();
|
|
|
|
foreach ($terms['types'] as $type) {
|
|
$orx->add('JSONB_EXISTS_IN_ARRAY(tp.type, :type_'.$type.') = \'TRUE\'');
|
|
$qb->setParameter('type_'.$type, $type);
|
|
}
|
|
$qb->andWhere($orx);
|
|
}
|
|
}
|
|
}
|