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_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_to: '%env(APP_DEFAULT_EMAIL_TO)%'
|
||||
|
||||
@@ -118,6 +148,7 @@ services:
|
||||
bpn_crm_id_admin: '%bpn_crm_id_admin%'
|
||||
bpn_crm_id_manager: '%bpn_crm_id_manager%'
|
||||
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%'
|
||||
|
||||
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` |
|
||||
| Reisemanager | attribute id `%bpn_crm_id_manager%`, selected | `isManager` |
|
||||
| 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
|
||||
`isHouseManager`, they are never both claimed, though the hotel codes of a Hausleitung are
|
||||
|
||||
@@ -185,9 +185,12 @@ class ResponseParser
|
||||
;
|
||||
$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;
|
||||
$hotelCodes[] = $matches[1];
|
||||
$hotelCodes[] = $houseManagerCode;
|
||||
}
|
||||
if ($this->config['bpn_crm_id_admin'] === $attribute->getId() && true === $attribute->isSelected()) {
|
||||
$isAdmin = true;
|
||||
@@ -294,13 +297,14 @@ class ResponseParser
|
||||
private function resolveOptions(array $options): array
|
||||
{
|
||||
$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([
|
||||
'bpn_default_hotel_code' => null,
|
||||
]);
|
||||
$optionsResolver->setAllowedTypes('bpn_crm_id_admin', 'int');
|
||||
$optionsResolver->setAllowedTypes('bpn_crm_id_manager', 'int');
|
||||
$optionsResolver->setAllowedTypes('bpn_crm_id_teamer', 'int');
|
||||
$optionsResolver->setAllowedTypes('bpn_crm_house_manager_ids', 'array');
|
||||
$optionsResolver->setAllowedTypes('bpn_default_hotel_code', ['string', 'null']);
|
||||
|
||||
return $optionsResolver->resolve($options);
|
||||
|
||||
@@ -86,6 +86,25 @@ class ResponseParserTest extends TestCase
|
||||
$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
|
||||
{
|
||||
$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_manager' => 1293,
|
||||
'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