feat: multiple hotelcodes assignable to users
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
"oneup/uploader-bundle": "^4.0",
|
"oneup/uploader-bundle": "^4.0",
|
||||||
"phpdocumentor/reflection-docblock": "^5.3",
|
"phpdocumentor/reflection-docblock": "^5.3",
|
||||||
"phpstan/phpdoc-parser": "^1.22",
|
"phpstan/phpdoc-parser": "^1.22",
|
||||||
|
"scienta/doctrine-json-functions": "^6.3",
|
||||||
"setasign/fpdf": "^1.8",
|
"setasign/fpdf": "^1.8",
|
||||||
"setasign/fpdi": "^2.5",
|
"setasign/fpdi": "^2.5",
|
||||||
"spatie/icalendar-generator": "^2.5",
|
"spatie/icalendar-generator": "^2.5",
|
||||||
|
|||||||
Generated
+73
-1
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "1e48d4a4ffe643c14cf370b7083adddb",
|
"content-hash": "804c55640363108581ce07cf9dedaece",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "beberlei/doctrineextensions",
|
"name": "beberlei/doctrineextensions",
|
||||||
@@ -2979,6 +2979,78 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-09-11T13:17:53+00:00"
|
"time": "2024-09-11T13:17:53+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "scienta/doctrine-json-functions",
|
||||||
|
"version": "6.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/ScientaNL/DoctrineJsonFunctions.git",
|
||||||
|
"reference": "554b2fd281e976a791501fc4753ffd4c5891ec62"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/ScientaNL/DoctrineJsonFunctions/zipball/554b2fd281e976a791501fc4753ffd4c5891ec62",
|
||||||
|
"reference": "554b2fd281e976a791501fc4753ffd4c5891ec62",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"doctrine/dbal": "^3.2 || ^4",
|
||||||
|
"doctrine/lexer": "^2.0 || ^3.0",
|
||||||
|
"doctrine/orm": "^2.19 || ^3",
|
||||||
|
"ext-pdo": "*",
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"doctrine/coding-standard": "^9.0 || ^10.0 || ^11.0 || ^12.0",
|
||||||
|
"phpstan/extension-installer": "^1.4",
|
||||||
|
"phpstan/phpstan": "^1.12",
|
||||||
|
"phpstan/phpstan-doctrine": "^1.4",
|
||||||
|
"phpstan/phpstan-phpunit": "^1.4",
|
||||||
|
"phpunit/phpunit": "^10.1",
|
||||||
|
"psalm/plugin-phpunit": "^0.18",
|
||||||
|
"slevomat/coding-standard": "~8",
|
||||||
|
"symfony/cache": "^5.4 || ^6.4 || ^7",
|
||||||
|
"vimeo/psalm": "^5.2",
|
||||||
|
"webmozart/assert": "^1.11"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"dunglas/doctrine-json-odm": "To serialize / deserialize objects as JSON documents."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Scienta\\DoctrineJsonFunctions\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Doctrine Json Functions Contributors",
|
||||||
|
"homepage": "https://github.com/ScientaNL/DoctrineJsonFunctions/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A set of extensions to Doctrine that add support for json query functions.",
|
||||||
|
"keywords": [
|
||||||
|
"database",
|
||||||
|
"doctrine",
|
||||||
|
"dql",
|
||||||
|
"json",
|
||||||
|
"mariadb",
|
||||||
|
"mysql",
|
||||||
|
"orm",
|
||||||
|
"postgres",
|
||||||
|
"postgresql",
|
||||||
|
"sqlite"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/ScientaNL/DoctrineJsonFunctions/issues",
|
||||||
|
"source": "https://github.com/ScientaNL/DoctrineJsonFunctions/tree/6.3.0"
|
||||||
|
},
|
||||||
|
"time": "2024-11-08T12:33:19+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "setasign/fpdf",
|
"name": "setasign/fpdf",
|
||||||
"version": "1.8.6",
|
"version": "1.8.6",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ doctrine:
|
|||||||
string_functions:
|
string_functions:
|
||||||
DATE_FORMAT: DoctrineExtensions\Query\Mysql\DateFormat
|
DATE_FORMAT: DoctrineExtensions\Query\Mysql\DateFormat
|
||||||
FIELD: DoctrineExtensions\Query\Mysql\Field
|
FIELD: DoctrineExtensions\Query\Mysql\Field
|
||||||
|
JSON_CONTAINS: Scienta\DoctrineJsonFunctions\Query\AST\Functions\Mysql\JsonContains
|
||||||
datetime_functions:
|
datetime_functions:
|
||||||
DATEDIFF: DoctrineExtensions\Query\Mysql\DateDiff
|
DATEDIFF: DoctrineExtensions\Query\Mysql\DateDiff
|
||||||
when@test:
|
when@test:
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250107163840 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE user ADD hotel_codes JSON NOT NULL COMMENT \'(DC2Type:json)\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function postUp(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->connection->executeQuery('UPDATE user SET hotel_codes="[]" WHERE hotel_code IS NULL');
|
||||||
|
|
||||||
|
$rows = $this->connection->fetchAllAssociative('SELECT id, hotel_code FROM user WHERE hotel_code IS NOT NULL');
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
$this->connection->update('user', [
|
||||||
|
'hotel_codes' => json_encode([$row['hotel_code']]),
|
||||||
|
], [
|
||||||
|
'id' => $row['id'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE user DROP hotel_codes');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ class CrmAttributesResponse
|
|||||||
private bool $manager = false;
|
private bool $manager = false;
|
||||||
private bool $houseManager = false;
|
private bool $houseManager = false;
|
||||||
private bool $teamer = false;
|
private bool $teamer = false;
|
||||||
private ?string $hotelCode = null;
|
private array $hotelCodes = [];
|
||||||
|
|
||||||
public function getAttributeGroups(): ?array
|
public function getAttributeGroups(): ?array
|
||||||
{
|
{
|
||||||
@@ -70,14 +70,14 @@ class CrmAttributesResponse
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHotelCode(): ?string
|
public function getHotelCodes(): array
|
||||||
{
|
{
|
||||||
return $this->hotelCode;
|
return $this->hotelCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setHotelCode(?string $hotelCode): static
|
public function setHotelCodes(array $hotelCodes): static
|
||||||
{
|
{
|
||||||
$this->hotelCode = $hotelCode;
|
$this->hotelCodes = $hotelCodes;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ class ResponseParser
|
|||||||
{
|
{
|
||||||
$groups = [];
|
$groups = [];
|
||||||
$isAdmin = $isManager = $isHouseManager = $isTeamer = false;
|
$isAdmin = $isManager = $isHouseManager = $isTeamer = false;
|
||||||
$hotelCode = null;
|
$hotelCodes = [];
|
||||||
|
|
||||||
foreach ($xml->selektionsmerkmale->selektionsgruppe as $item) {
|
foreach ($xml->selektionsmerkmale->selektionsgruppe as $item) {
|
||||||
$group = new CrmAttributeGroup();
|
$group = new CrmAttributeGroup();
|
||||||
@@ -164,7 +164,7 @@ class ResponseParser
|
|||||||
|
|
||||||
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attributeLabel, $matches) && true === $attribute->isSelected()) {
|
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attributeLabel, $matches) && true === $attribute->isSelected()) {
|
||||||
$isHouseManager = true;
|
$isHouseManager = true;
|
||||||
$hotelCode = $matches[1];
|
$hotelCodes[] = $matches[1];
|
||||||
}
|
}
|
||||||
if ($this->config['bpn_crm_id_admin'] === $attribute->getId() && true === $attribute->isSelected()) {
|
if ($this->config['bpn_crm_id_admin'] === $attribute->getId() && true === $attribute->isSelected()) {
|
||||||
$isAdmin = true;
|
$isAdmin = true;
|
||||||
@@ -183,7 +183,7 @@ class ResponseParser
|
|||||||
// Apply additional role and hotel code for testing purposes when provided
|
// Apply additional role and hotel code for testing purposes when provided
|
||||||
if ($isAdmin && null !== $this->config['bpn_default_hotel_code']) {
|
if ($isAdmin && null !== $this->config['bpn_default_hotel_code']) {
|
||||||
$isHouseManager = true;
|
$isHouseManager = true;
|
||||||
$hotelCode = $this->config['bpn_default_hotel_code'];
|
$hotelCodes[] = $this->config['bpn_default_hotel_code'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = new CrmAttributesResponse();
|
$response = new CrmAttributesResponse();
|
||||||
@@ -193,7 +193,7 @@ class ResponseParser
|
|||||||
->setManager($isManager)
|
->setManager($isManager)
|
||||||
->setTeamer($isTeamer)
|
->setTeamer($isTeamer)
|
||||||
->setHouseManager($isHouseManager)
|
->setHouseManager($isHouseManager)
|
||||||
->setHotelCode($hotelCode)
|
->setHotelCodes($hotelCodes)
|
||||||
;
|
;
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class UserDataHandler
|
|||||||
array $roles,
|
array $roles,
|
||||||
bool $isTeamer = false,
|
bool $isTeamer = false,
|
||||||
array $crmSelections = [],
|
array $crmSelections = [],
|
||||||
?string $hotelCode = null
|
array $hotelCodes = []
|
||||||
): User {
|
): User {
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$user
|
$user
|
||||||
@@ -64,7 +64,7 @@ class UserDataHandler
|
|||||||
->setEmail($profileResponse->getCommunication()->getEmail())
|
->setEmail($profileResponse->getCommunication()->getEmail())
|
||||||
->setBusProPersonId($profileResponse->getPersonId())
|
->setBusProPersonId($profileResponse->getPersonId())
|
||||||
->setBusProAddressId($profileResponse->getAddressId())
|
->setBusProAddressId($profileResponse->getAddressId())
|
||||||
->setHotelCode($hotelCode)
|
->setHotelCodes($hotelCodes)
|
||||||
->setRoles($roles)
|
->setRoles($roles)
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -95,12 +95,12 @@ class UserDataHandler
|
|||||||
array $roles,
|
array $roles,
|
||||||
bool $isTeamer = false,
|
bool $isTeamer = false,
|
||||||
array $crmSelections = [],
|
array $crmSelections = [],
|
||||||
?string $hotelCode = null
|
array $hotelCodes = []
|
||||||
): void {
|
): void {
|
||||||
$user
|
$user
|
||||||
->setEmail($profileResponse->getCommunication()->getEmail())
|
->setEmail($profileResponse->getCommunication()->getEmail())
|
||||||
->setRoles($roles)
|
->setRoles($roles)
|
||||||
->setHotelCode($hotelCode)
|
->setHotelCodes($hotelCodes)
|
||||||
;
|
;
|
||||||
|
|
||||||
if (true === $isTeamer) {
|
if (true === $isTeamer) {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class IndexController extends AbstractController
|
|||||||
|
|
||||||
$query = $this
|
$query = $this
|
||||||
->dispositionRepository
|
->dispositionRepository
|
||||||
->getDispositionsWithPendingFeedbackQuery($user->getHotelCode())
|
->getDispositionsWithPendingFeedbackQuery($user->getHotelCodes())
|
||||||
;
|
;
|
||||||
|
|
||||||
$pagination = $this->paginator->paginate(
|
$pagination = $this->paginator->paginate(
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ class IndexController extends AbstractController
|
|||||||
|
|
||||||
$newDispositions = $this
|
$newDispositions = $this
|
||||||
->dispositionRepository
|
->dispositionRepository
|
||||||
->findNewDispositionsByHotelCode($user->getHotelCode())
|
->findNewDispositionsByHotelCodes($user->getHotelCodes())
|
||||||
;
|
;
|
||||||
|
|
||||||
$pendingFeedbacks = $this
|
$pendingFeedbacks = $this
|
||||||
->dispositionRepository
|
->dispositionRepository
|
||||||
->findDispositionsWithPendingFeedbackByHotelCode($user->getHotelCode())
|
->findDispositionsWithPendingFeedbackByHotelCodes($user->getHotelCodes())
|
||||||
;
|
;
|
||||||
|
|
||||||
return $this->render('house_manager/index.html.twig', [
|
return $this->render('house_manager/index.html.twig', [
|
||||||
|
|||||||
+21
-4
@@ -54,6 +54,9 @@ class User implements UserInterface, TimestampableEntityInterface
|
|||||||
#[ORM\Column(length: 32, nullable: true)]
|
#[ORM\Column(length: 32, nullable: true)]
|
||||||
private ?string $hotelCode = null;
|
private ?string $hotelCode = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: 'json')]
|
||||||
|
private array $hotelCodes = [];
|
||||||
|
|
||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
private bool $muteNotifications = false;
|
private bool $muteNotifications = false;
|
||||||
|
|
||||||
@@ -256,14 +259,14 @@ class User implements UserInterface, TimestampableEntityInterface
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHotelCode(): ?string
|
public function getHotelCodes(): array
|
||||||
{
|
{
|
||||||
return $this->hotelCode;
|
return $this->hotelCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setHotelCode(?string $hotelCode): static
|
public function setHotelCodes(array $hotelCodes): static
|
||||||
{
|
{
|
||||||
$this->hotelCode = $hotelCode;
|
$this->hotelCodes = $hotelCodes;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -279,4 +282,18 @@ class User implements UserInterface, TimestampableEntityInterface
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function hasHotelCodeMatch(string $hotelCode): bool
|
||||||
|
{
|
||||||
|
foreach ($this->hotelCodes as $userHotelCode) {
|
||||||
|
if (
|
||||||
|
str_starts_with($hotelCode, $userHotelCode)
|
||||||
|
|| str_ends_with($hotelCode, $userHotelCode)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,8 +148,10 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findNewDispositionsByHotelCode(string $hotelCode): array
|
public function findNewDispositionsByHotelCodes(mixed $hotelCode): array
|
||||||
{
|
{
|
||||||
|
$hotelCodes = (array) $hotelCode;
|
||||||
|
|
||||||
$qb = $this->createQueryBuilder('disposition');
|
$qb = $this->createQueryBuilder('disposition');
|
||||||
|
|
||||||
return $qb
|
return $qb
|
||||||
@@ -157,12 +159,15 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
->innerJoin('disposition.assignment', 'assignment')
|
->innerJoin('disposition.assignment', 'assignment')
|
||||||
->innerJoin('assignment.destination', 'destination')
|
->innerJoin('assignment.destination', 'destination')
|
||||||
->where($qb->expr()->andX(
|
->where($qb->expr()->andX(
|
||||||
$qb->expr()->like('destination.hotelCode', ':hotelCode'),
|
$qb->expr()->orX(
|
||||||
|
$qb->expr()->in($qb->expr()->substring('destination.hotelCode', 1, 3), ':hotelCodes'),
|
||||||
|
$qb->expr()->in($qb->expr()->substring('destination.hotelCode', -3, 3), ':hotelCodes'),
|
||||||
|
),
|
||||||
$qb->expr()->gte('destination.dateTo', ':dateTo'),
|
$qb->expr()->gte('destination.dateTo', ':dateTo'),
|
||||||
$qb->expr()->eq('disposition.status', ':status')
|
$qb->expr()->eq('disposition.status', ':status')
|
||||||
))
|
))
|
||||||
->orderBy('destination.dateFrom', 'ASC')
|
->orderBy('destination.dateFrom', 'ASC')
|
||||||
->setParameter('hotelCode', '%'.$hotelCode.'%')
|
->setParameter('hotelCodes', $hotelCodes)
|
||||||
->setParameter('dateTo', new \DateTimeImmutable())
|
->setParameter('dateTo', new \DateTimeImmutable())
|
||||||
->setParameter('status', Disposition::STATUS_CONFIRMED)
|
->setParameter('status', Disposition::STATUS_CONFIRMED)
|
||||||
->getQuery()
|
->getQuery()
|
||||||
@@ -170,8 +175,10 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDispositionsWithPendingFeedbackQuery(?string $hotelCode = null, ?int $offsetDays = null): Query
|
public function getDispositionsWithPendingFeedbackQuery(mixed $hotelCode = null, ?int $offsetDays = null): Query
|
||||||
{
|
{
|
||||||
|
$hotelCodes = (array) $hotelCode;
|
||||||
|
|
||||||
$qb = $this->createQueryBuilder('disposition');
|
$qb = $this->createQueryBuilder('disposition');
|
||||||
|
|
||||||
$qb
|
$qb
|
||||||
@@ -201,8 +208,11 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
|
|
||||||
if (null !== $hotelCode) {
|
if (null !== $hotelCode) {
|
||||||
$qb
|
$qb
|
||||||
->andWhere($qb->expr()->like('destination.hotelCode', ':hotelCode'))
|
->andWhere($qb->expr()->orX(
|
||||||
->setParameter('hotelCode', '%'.$hotelCode.'%')
|
$qb->expr()->in($qb->expr()->substring('destination.hotelCode', 1, 3), ':hotelCodes'),
|
||||||
|
$qb->expr()->in($qb->expr()->substring('destination.hotelCode', -3, 3), ':hotelCodes'),
|
||||||
|
))
|
||||||
|
->setParameter('hotelCodes', $hotelCodes)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +227,7 @@ class DispositionRepository extends ServiceEntityRepository
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findDispositionsWithPendingFeedbackByHotelCode(string $hotelCode): array
|
public function findDispositionsWithPendingFeedbackByHotelCodes(mixed $hotelCode): array
|
||||||
{
|
{
|
||||||
return $this
|
return $this
|
||||||
->getDispositionsWithPendingFeedbackQuery($hotelCode)
|
->getDispositionsWithPendingFeedbackQuery($hotelCode)
|
||||||
|
|||||||
@@ -32,16 +32,14 @@ class UserRepository extends ServiceEntityRepository
|
|||||||
$qb = $this->createQueryBuilder('u');
|
$qb = $this->createQueryBuilder('u');
|
||||||
|
|
||||||
return $qb
|
return $qb
|
||||||
->where($qb->expr()->orX(
|
->where("JSON_CONTAINS(u.roles, :role_admin) = 1")
|
||||||
$qb->expr()->like('u.roles', ':role_admin'),
|
->orWhere("JSON_CONTAINS(u.roles, :role_manager) = 1")
|
||||||
$qb->expr()->like('u.roles', ':role_manager'),
|
->orWhere("JSON_CONTAINS(u.roles, :role_house_manager) = 1")
|
||||||
$qb->expr()->like('u.roles', ':role_house_manager')
|
|
||||||
))
|
|
||||||
->orderBy('u.lastName', 'ASC')
|
->orderBy('u.lastName', 'ASC')
|
||||||
->setParameters([
|
->setParameters([
|
||||||
'role_admin' => '%"ROLE_ADMIN"%',
|
'role_admin' => json_encode('ROLE_ADMIN'),
|
||||||
'role_manager' => '%"ROLE_MANAGER"%',
|
'role_manager' => json_encode('ROLE_MANAGER'),
|
||||||
'role_house_manager' => '%"ROLE_HOUSE_MANAGER"%',
|
'role_house_manager' => json_encode('ROLE_HOUSE_MANAGER'),
|
||||||
])
|
])
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult()
|
->getResult()
|
||||||
@@ -50,22 +48,29 @@ class UserRepository extends ServiceEntityRepository
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $role
|
* @param string $role
|
||||||
* @param string $hotelCode
|
* @param string[]|string $hotelCode
|
||||||
* @return User[]
|
* @return User[]
|
||||||
*/
|
*/
|
||||||
public function getUsersByRoleAndHotelCode(string $role, string $hotelCode): array
|
public function getUsersByRoleAndHotelCode(string $role, mixed $hotelCode): array
|
||||||
{
|
{
|
||||||
$hotelCodeBase = substr($hotelCode, 0, 3);
|
$hotelCodes = (array) $hotelCode;
|
||||||
|
|
||||||
|
$hotelCodesBase = array_map(function ($code) {
|
||||||
|
return substr($code, 0, 3);
|
||||||
|
}, $hotelCodes);
|
||||||
|
|
||||||
$qb = $this->createQueryBuilder('user');
|
$qb = $this->createQueryBuilder('user');
|
||||||
|
|
||||||
|
foreach ($hotelCodesBase as $index => $code) {
|
||||||
|
$qb
|
||||||
|
->orWhere('JSON_CONTAINS(user.hotelCodes, :hotelCode_'.$index.') = 1')
|
||||||
|
->setParameter('hotelCode_'.$index, json_encode($code))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
return $qb
|
return $qb
|
||||||
->where($qb->expr()->andX(
|
->andWhere('JSON_CONTAINS(user.roles, :role) = 1')
|
||||||
$qb->expr()->eq('user.hotelCode', ':hotelCode'),
|
->setParameter('role', json_encode($role))
|
||||||
$qb->expr()->like('user.roles', ':role')
|
|
||||||
))
|
|
||||||
->setParameter('hotelCode', $hotelCodeBase)
|
|
||||||
->setParameter('role', '%"'.$role.'"%')
|
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult()
|
->getResult()
|
||||||
;
|
;
|
||||||
@@ -76,17 +81,15 @@ class UserRepository extends ServiceEntityRepository
|
|||||||
$qb = $this->createQueryBuilder('user');
|
$qb = $this->createQueryBuilder('user');
|
||||||
|
|
||||||
$users = $qb
|
$users = $qb
|
||||||
->where($qb->expr()->andX(
|
->where($qb->expr()->orX(
|
||||||
$qb->expr()->orX(
|
$qb->expr()->like('user.lastName', ':search'),
|
||||||
$qb->expr()->like('user.lastName', ':search'),
|
$qb->expr()->like('user.firstName', ':search'),
|
||||||
$qb->expr()->like('user.firstName', ':search'),
|
))
|
||||||
)),
|
->andWhere('JSON_CONTAINS(user.roles, :role) = 1')
|
||||||
$qb->expr()->like('user.roles', ':role')
|
|
||||||
)
|
|
||||||
->orderBy('user.lastName', 'ASC')
|
->orderBy('user.lastName', 'ASC')
|
||||||
->addOrderBy('user.firstName', 'ASC')
|
->addOrderBy('user.firstName', 'ASC')
|
||||||
->setParameter('search', '%'.$this->escapeLikeWildcards($search).'%')
|
->setParameter('search', '%'.$this->escapeLikeWildcards($search).'%')
|
||||||
->setParameter('role', '%"'.$this->escapeLikeWildcards($role).'"%')
|
->setParameter('role', json_encode($role))
|
||||||
->getQuery()
|
->getQuery()
|
||||||
->getResult()
|
->getResult()
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
|
|||||||
if (null !== $user) {
|
if (null !== $user) {
|
||||||
$this
|
$this
|
||||||
->userDataHandler
|
->userDataHandler
|
||||||
->updateLocalUser($user, $profileResponse, $roles, $isTeamer, $crmSelections, $crmAttributes->getHotelCode())
|
->updateLocalUser($user, $profileResponse, $roles, $isTeamer, $crmSelections, $crmAttributes->getHotelCodes())
|
||||||
;
|
;
|
||||||
|
|
||||||
return $user;
|
return $user;
|
||||||
@@ -145,7 +145,7 @@ class BpnAuthenticator extends AbstractLoginFormAuthenticator implements Authent
|
|||||||
|
|
||||||
return $this
|
return $this
|
||||||
->userDataHandler
|
->userDataHandler
|
||||||
->createLocalUser($profileResponse, $roles, $isTeamer, $crmSelections, $crmAttributes->getHotelCode())
|
->createLocalUser($profileResponse, $roles, $isTeamer, $crmSelections, $crmAttributes->getHotelCodes())
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace App\Security\Voter;
|
|||||||
use App\BusProNet\DataProvider\HotelDataProvider;
|
use App\BusProNet\DataProvider\HotelDataProvider;
|
||||||
use App\BusProNet\Model\Hotel;
|
use App\BusProNet\Model\Hotel;
|
||||||
use App\Entity\Disposition;
|
use App\Entity\Disposition;
|
||||||
|
use App\Entity\User;
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||||
@@ -93,4 +94,4 @@ class DispositionVoter extends Voter
|
|||||||
|
|
||||||
return $this->security->getUser()->getTeamer() === $disposition->getTeamer();
|
return $this->security->getUser()->getTeamer() === $disposition->getTeamer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,24 +38,30 @@ class FeedbackReminderService
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get hotel base code to find hotel manager later
|
// Get hotel code to find hotel manager later
|
||||||
$hotelBaseCode = substr($hotel->getCode(), 0, 3);
|
$hotelCode = $hotel->getCode();
|
||||||
|
|
||||||
if (false === array_key_exists($hotelBaseCode, $sortedFeedbacks)) {
|
if (false === array_key_exists($hotelCode, $sortedFeedbacks)) {
|
||||||
$sortedFeedbacks[$hotelBaseCode] = [];
|
$sortedFeedbacks[$hotelCode] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort feedback by hotel base code
|
// Sort feedback by hotel base code
|
||||||
$sortedFeedbacks[$hotelBaseCode][] = $disposition;
|
$sortedFeedbacks[$hotelCode][] = $disposition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine hotel managers to notify
|
// find hotel managers by hotel codes starting or ending with base code
|
||||||
$hotelBaseCodes = array_keys($sortedFeedbacks);
|
$hotelCodes = array_keys($sortedFeedbacks);
|
||||||
|
$hotelBaseCodes = [];
|
||||||
|
foreach ($hotelCodes as $hotelCode) {
|
||||||
|
$hotelBaseCodes[] = substr($hotelCode, 0, 3);
|
||||||
|
$hotelBaseCodes[] = substr($hotelCode, -3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
/** @var User[] $hotelManagers */
|
/** @var User[] $hotelManagers */
|
||||||
$hotelManagers = $this->userRepository->findBy([
|
$hotelManagers = $this
|
||||||
'hotelCode' => $hotelBaseCodes,
|
->userRepository
|
||||||
]);
|
->getUsersByRoleAndHotelCode('ROLE_HOTEL_MANAGER', $hotelBaseCodes)
|
||||||
|
;
|
||||||
|
|
||||||
if (0 === count($hotelManagers)) {
|
if (0 === count($hotelManagers)) {
|
||||||
return 'No feedback reminders to be sent to hotel managers';
|
return 'No feedback reminders to be sent to hotel managers';
|
||||||
@@ -65,8 +71,14 @@ class FeedbackReminderService
|
|||||||
if (true === $manager->isMuteNotifications()) {
|
if (true === $manager->isMuteNotifications()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$feedbackKeys = array_filter(array_keys($sortedFeedbacks), function (string $key) use ($manager) {
|
||||||
|
return $manager->hasHotelCodeMatch($key);
|
||||||
|
});
|
||||||
|
$feedbacksForManager = array_filter($sortedFeedbacks, function ($key) use ($feedbackKeys) {
|
||||||
|
return in_array($key, $feedbackKeys);
|
||||||
|
}, ARRAY_FILTER_USE_KEY);
|
||||||
$this->mailer->createAndSendEmail([
|
$this->mailer->createAndSendEmail([
|
||||||
'feedbacks' => $sortedFeedbacks[$manager->getHotelCode()],
|
'feedbacks' => $feedbacksForManager,
|
||||||
], [
|
], [
|
||||||
'to' => $manager->getEmail(),
|
'to' => $manager->getEmail(),
|
||||||
'subject' => 'Reminder: Offene Feedbacks',
|
'subject' => 'Reminder: Offene Feedbacks',
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Tests\Entity;
|
||||||
|
|
||||||
|
use App\Entity\User;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class UserTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testHotelCodeMatching(): void
|
||||||
|
{
|
||||||
|
$user = new User();
|
||||||
|
$user->setHotelCodes(['ABC', 'DEF', 'GHI']);
|
||||||
|
|
||||||
|
$isMatch = $user->hasHotelCodeMatch('ABCXXX');
|
||||||
|
$this->assertTrue($isMatch);
|
||||||
|
|
||||||
|
$isMatch = $user->hasHotelCodeMatch('XXXGHI');
|
||||||
|
$this->assertTrue($isMatch);
|
||||||
|
|
||||||
|
$isMatch = $user->hasHotelCodeMatch('XXDEFXX');
|
||||||
|
$this->assertFalse($isMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user