feat: map house manager roles and houses by crm ids instead of labels
This commit is contained in:
@@ -4,6 +4,36 @@ parameters:
|
|||||||
bpn_crm_id_teamer: '%env(int:APP_BPN_CRM_ID_TEAMER)%'
|
bpn_crm_id_teamer: '%env(int:APP_BPN_CRM_ID_TEAMER)%'
|
||||||
bpn_default_hotel_code: '%env(default::APP_BPN_DEFAULT_HOTEL_CODE)%'
|
bpn_default_hotel_code: '%env(default::APP_BPN_DEFAULT_HOTEL_CODE)%'
|
||||||
|
|
||||||
|
# BusPro CRM selection id => hotel code. A person holding a selected attribute from this
|
||||||
|
# list is a house manager for that house. Matched by id and not by the "Hausleitung XXX"
|
||||||
|
# label, so renaming a selection in BusPro cannot silently grant or revoke a house.
|
||||||
|
# The commented entries are BusPro selections whose code is not a house in the "houses"
|
||||||
|
# parameter below: granting them would let someone in who then sees no assignments and
|
||||||
|
# no dispositions at all. Uncomment one once its house exists. The reverse gap is fine -
|
||||||
|
# not every house has a selection.
|
||||||
|
bpn_crm_house_manager_ids:
|
||||||
|
1299: 'SSL'
|
||||||
|
1300: 'SST'
|
||||||
|
1301: 'MVK'
|
||||||
|
# 1302: 'ASB'
|
||||||
|
1303: 'LPJ'
|
||||||
|
1304: 'DKS'
|
||||||
|
1305: 'DGS'
|
||||||
|
1306: 'DPW'
|
||||||
|
1307: 'DKI'
|
||||||
|
1308: 'DWW'
|
||||||
|
1309: 'PMV'
|
||||||
|
# 1352: 'ASG'
|
||||||
|
1371: 'ASC'
|
||||||
|
1373: 'PCJ'
|
||||||
|
1374: 'SBW'
|
||||||
|
# 1375: 'UCH'
|
||||||
|
# 1376: 'SZO'
|
||||||
|
1377: 'KHH'
|
||||||
|
1459: 'SVS'
|
||||||
|
1461: 'SHM'
|
||||||
|
1462: 'AGR'
|
||||||
|
|
||||||
default_email_from: '%env(APP_DEFAULT_EMAIL_FROM)%'
|
default_email_from: '%env(APP_DEFAULT_EMAIL_FROM)%'
|
||||||
default_email_to: '%env(APP_DEFAULT_EMAIL_TO)%'
|
default_email_to: '%env(APP_DEFAULT_EMAIL_TO)%'
|
||||||
|
|
||||||
@@ -118,6 +148,7 @@ services:
|
|||||||
bpn_crm_id_admin: '%bpn_crm_id_admin%'
|
bpn_crm_id_admin: '%bpn_crm_id_admin%'
|
||||||
bpn_crm_id_manager: '%bpn_crm_id_manager%'
|
bpn_crm_id_manager: '%bpn_crm_id_manager%'
|
||||||
bpn_crm_id_teamer: '%bpn_crm_id_teamer%'
|
bpn_crm_id_teamer: '%bpn_crm_id_teamer%'
|
||||||
|
bpn_crm_house_manager_ids: '%bpn_crm_house_manager_ids%'
|
||||||
bpn_default_hotel_code: '%bpn_default_hotel_code%'
|
bpn_default_hotel_code: '%bpn_default_hotel_code%'
|
||||||
|
|
||||||
App\Twig\AppRuntime:
|
App\Twig\AppRuntime:
|
||||||
|
|||||||
+5
-1
@@ -65,7 +65,11 @@ slice it, and picking the right one matters:
|
|||||||
| admin | attribute id `%bpn_crm_id_admin%`, selected | `isAdmin` |
|
| admin | attribute id `%bpn_crm_id_admin%`, selected | `isAdmin` |
|
||||||
| Reisemanager | attribute id `%bpn_crm_id_manager%`, selected | `isManager` |
|
| Reisemanager | attribute id `%bpn_crm_id_manager%`, selected | `isManager` |
|
||||||
| teamer | attribute id `%bpn_crm_id_teamer%`, selected | `isTeamer` |
|
| teamer | attribute id `%bpn_crm_id_teamer%`, selected | `isTeamer` |
|
||||||
| Hausleitung | label matching `/^Hausleitung ([A-Z0-9]+)$/`, selected | `isHouseManager` + one hotel code per match |
|
| Hausleitung | attribute id listed in `%bpn_crm_house_manager_ids%`, selected | `isHouseManager` + the hotel code that id maps to |
|
||||||
|
|
||||||
|
`bpn_crm_house_manager_ids` (`config/services.yaml`) maps a BusPro selection id to a hotel
|
||||||
|
code. Entries whose code is not a house in the `houses` parameter are kept commented out:
|
||||||
|
such a house manager could log in but would see no assignments and no dispositions at all.
|
||||||
|
|
||||||
`UserDataHandler::collectPendingRoles()` turns those into markers — `isManager` wins over
|
`UserDataHandler::collectPendingRoles()` turns those into markers — `isManager` wins over
|
||||||
`isHouseManager`, they are never both claimed, though the hotel codes of a Hausleitung are
|
`isHouseManager`, they are never both claimed, though the hotel codes of a Hausleitung are
|
||||||
|
|||||||
@@ -185,9 +185,12 @@ class ResponseParser
|
|||||||
;
|
;
|
||||||
$attributes[] = $attribute;
|
$attributes[] = $attribute;
|
||||||
|
|
||||||
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attributeLabel, $matches) && true === $attribute->isSelected()) {
|
// Matched by id, like every other role: the "Hausleitung XXX" label is BusPro
|
||||||
|
// wording and must not decide who gets access to which house.
|
||||||
|
$houseManagerCode = $this->config['bpn_crm_house_manager_ids'][$attribute->getId()] ?? null;
|
||||||
|
if (null !== $houseManagerCode && true === $attribute->isSelected()) {
|
||||||
$isHouseManager = true;
|
$isHouseManager = true;
|
||||||
$hotelCodes[] = $matches[1];
|
$hotelCodes[] = $houseManagerCode;
|
||||||
}
|
}
|
||||||
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;
|
||||||
@@ -294,13 +297,14 @@ class ResponseParser
|
|||||||
private function resolveOptions(array $options): array
|
private function resolveOptions(array $options): array
|
||||||
{
|
{
|
||||||
$optionsResolver = new OptionsResolver();
|
$optionsResolver = new OptionsResolver();
|
||||||
$optionsResolver->setRequired(['bpn_crm_id_admin', 'bpn_crm_id_manager', 'bpn_crm_id_teamer']);
|
$optionsResolver->setRequired(['bpn_crm_id_admin', 'bpn_crm_id_manager', 'bpn_crm_id_teamer', 'bpn_crm_house_manager_ids']);
|
||||||
$optionsResolver->setDefaults([
|
$optionsResolver->setDefaults([
|
||||||
'bpn_default_hotel_code' => null,
|
'bpn_default_hotel_code' => null,
|
||||||
]);
|
]);
|
||||||
$optionsResolver->setAllowedTypes('bpn_crm_id_admin', 'int');
|
$optionsResolver->setAllowedTypes('bpn_crm_id_admin', 'int');
|
||||||
$optionsResolver->setAllowedTypes('bpn_crm_id_manager', 'int');
|
$optionsResolver->setAllowedTypes('bpn_crm_id_manager', 'int');
|
||||||
$optionsResolver->setAllowedTypes('bpn_crm_id_teamer', 'int');
|
$optionsResolver->setAllowedTypes('bpn_crm_id_teamer', 'int');
|
||||||
|
$optionsResolver->setAllowedTypes('bpn_crm_house_manager_ids', 'array');
|
||||||
$optionsResolver->setAllowedTypes('bpn_default_hotel_code', ['string', 'null']);
|
$optionsResolver->setAllowedTypes('bpn_default_hotel_code', ['string', 'null']);
|
||||||
|
|
||||||
return $optionsResolver->resolve($options);
|
return $optionsResolver->resolve($options);
|
||||||
|
|||||||
@@ -86,6 +86,25 @@ class ResponseParserTest extends TestCase
|
|||||||
$this->assertCount(3, $response->getAttributeGroups());
|
$this->assertCount(3, $response->getAttributeGroups());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The house of a "Hausleitung" selection comes from the configured id map, never from the
|
||||||
|
* label: an id that is not mapped grants nothing. That is also what keeps the houses
|
||||||
|
* commented out in bpn_crm_house_manager_ids from letting someone in who would then see
|
||||||
|
* no assignments and no dispositions at all.
|
||||||
|
*/
|
||||||
|
public function testParseCrmAttributesIgnoresAnUnmappedHouseManagerSelection(): void
|
||||||
|
{
|
||||||
|
$content = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="KUNDENKONTO"></satz><art>SelektionCRM</art><idadresse>141747</idadresse><idperson>224526</idperson><selektionsmerkmale><selektionsgruppe id="10" bezeichnung="TEAM"><selektion id="1070" bezeichnung="E&P Teamer - allg. Merkmal" aenderbar="False" auswahl="True"></selektion><selektion id="9999" bezeichnung="Hausleitung XYZ" aenderbar="False" auswahl="True"></selektion></selektionsgruppe></selektionsmerkmale></ergebnis>';
|
||||||
|
|
||||||
|
$parser = $this->getParserInstance();
|
||||||
|
$response = $parser->parseXmlString(ApiClient::TYPE_CUSTOMER_DATA, $content);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(CrmAttributesResponse::class, $response);
|
||||||
|
$this->assertTrue($response->isTeamer());
|
||||||
|
$this->assertFalse($response->isHouseManager());
|
||||||
|
$this->assertSame([], $response->getHotelCodes());
|
||||||
|
}
|
||||||
|
|
||||||
public function testParseCrmAttributesOfAnEmptyResponse(): void
|
public function testParseCrmAttributesOfAnEmptyResponse(): void
|
||||||
{
|
{
|
||||||
$content = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="KUNDENKONTO"></satz><art>SelektionCRM</art><idadresse>141747</idadresse><idperson>224526</idperson><selektionsmerkmale></selektionsmerkmale></ergebnis>';
|
$content = '<?xml version="1.0" encoding="utf-8"?><ergebnis><satz typ="KUNDENKONTO"></satz><art>SelektionCRM</art><idadresse>141747</idadresse><idperson>224526</idperson><selektionsmerkmale></selektionsmerkmale></ergebnis>';
|
||||||
@@ -170,6 +189,14 @@ class ResponseParserTest extends TestCase
|
|||||||
'bpn_crm_id_admin' => 1292,
|
'bpn_crm_id_admin' => 1292,
|
||||||
'bpn_crm_id_manager' => 1293,
|
'bpn_crm_id_manager' => 1293,
|
||||||
'bpn_crm_id_teamer' => 1070,
|
'bpn_crm_id_teamer' => 1070,
|
||||||
|
// Deliberately a small excerpt of the configured map: the fixtures only carry
|
||||||
|
// these three houses, and 1301 is here to be a mapped id no fixture selects.
|
||||||
|
'bpn_crm_house_manager_ids' => [
|
||||||
|
1299 => 'SSL',
|
||||||
|
1301 => 'MVK',
|
||||||
|
1304 => 'DKS',
|
||||||
|
1305 => 'DGS',
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user