Skip to content

Commit 0419783

Browse files
committed
ELI-351: Renames rules model to campaign_config
1 parent de8ebac commit 0419783

19 files changed

Lines changed: 245 additions & 212 deletions

File tree

src/eligibility_signposting_api/audit/audit_context.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,20 @@
1818
RequestAuditQueryParams,
1919
)
2020
from eligibility_signposting_api.audit.audit_service import AuditService
21+
from eligibility_signposting_api.model.campaign_config import (
22+
CampaignID,
23+
CampaignVersion,
24+
Iteration,
25+
RuleName,
26+
RulePriority,
27+
)
2128
from eligibility_signposting_api.model.eligibility_status import (
2229
CohortGroupResult,
2330
ConditionName,
2431
IterationResult,
2532
Status,
2633
SuggestedAction,
2734
)
28-
from eligibility_signposting_api.model.rules import CampaignID, CampaignVersion, Iteration, RuleName, RulePriority
2935

3036
logger = logging.getLogger(__name__)
3137

File renamed without changes.

src/eligibility_signposting_api/repos/campaign_repo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from botocore.client import BaseClient
66
from wireup import Inject, service
77

8-
from eligibility_signposting_api.model.rules import CampaignConfig, Rules
8+
from eligibility_signposting_api.model.campaign_config import CampaignConfig, Rules
99

1010
BucketName = NewType("BucketName", str)
1111

src/eligibility_signposting_api/services/calculators/eligibility_calculator.py

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,24 @@
55
from collections.abc import Collection, Iterable, Iterator, Mapping
66
from dataclasses import dataclass, field
77
from itertools import groupby
8-
from typing import TYPE_CHECKING, Any
9-
10-
from eligibility_signposting_api.audit.audit_context import AuditContext
11-
from eligibility_signposting_api.services.processors.campaign_evaluator import CampaignEvaluator
12-
from eligibility_signposting_api.services.processors.person_data_reader import PersonDataReader
13-
14-
if TYPE_CHECKING:
15-
from eligibility_signposting_api.model.rules import (
16-
ActionsMapper,
17-
CampaignConfig,
18-
CampaignID,
19-
CampaignVersion,
20-
Iteration,
21-
IterationCohort,
22-
RuleName,
23-
RulePriority,
24-
RuleType,
25-
)
8+
from typing import Any
269

2710
from wireup import service
2811

29-
from eligibility_signposting_api.model import eligibility_status, rules
12+
from eligibility_signposting_api.audit.audit_context import AuditContext
13+
from eligibility_signposting_api.model import eligibility_status
14+
from eligibility_signposting_api.model.campaign_config import (
15+
ActionsMapper,
16+
CampaignConfig,
17+
CampaignID,
18+
CampaignVersion,
19+
Iteration,
20+
IterationCohort,
21+
IterationRule,
22+
RuleName,
23+
RulePriority,
24+
RuleType,
25+
)
3026
from eligibility_signposting_api.model.eligibility_status import (
3127
ActionCode,
3228
ActionDescription,
@@ -44,21 +40,23 @@
4440
from eligibility_signposting_api.services.calculators.rule_calculator import (
4541
RuleCalculator,
4642
)
43+
from eligibility_signposting_api.services.processors.campaign_evaluator import CampaignEvaluator
44+
from eligibility_signposting_api.services.processors.person_data_reader import PersonDataReader
4745

4846
Row = Collection[Mapping[str, Any]]
4947

5048

5149
@service
5250
class EligibilityCalculatorFactory:
5351
@staticmethod
54-
def get(person_data: Row, campaign_configs: Collection[rules.CampaignConfig]) -> EligibilityCalculator:
52+
def get(person_data: Row, campaign_configs: Collection[CampaignConfig]) -> EligibilityCalculator:
5553
return EligibilityCalculator(person_data=person_data, campaign_configs=campaign_configs)
5654

5755

5856
@dataclass
5957
class EligibilityCalculator:
6058
person_data: Row
61-
campaign_configs: Collection[rules.CampaignConfig]
59+
campaign_configs: Collection[CampaignConfig]
6260

6361
campaign_evaluator: CampaignEvaluator = field(default_factory=CampaignEvaluator)
6462
person_data_reader: PersonDataReader = field(default_factory=PersonDataReader)
@@ -89,9 +87,7 @@ def get_the_best_cohort_memberships(
8987
return best_status, best_cohorts
9088

9189
@staticmethod
92-
def get_exclusion_rules(
93-
cohort: IterationCohort, filter_rules: Iterable[rules.IterationRule]
94-
) -> Iterator[rules.IterationRule]:
90+
def get_exclusion_rules(cohort: IterationCohort, filter_rules: Iterable[IterationRule]) -> Iterator[IterationRule]:
9591
return (
9692
ir
9793
for ir in filter_rules
@@ -103,23 +99,23 @@ def get_exclusion_rules(
10399
@staticmethod
104100
def get_rules_by_type(
105101
active_iteration: Iteration,
106-
) -> tuple[tuple[rules.IterationRule, ...], tuple[rules.IterationRule, ...]]:
102+
) -> tuple[tuple[IterationRule, ...], tuple[IterationRule, ...]]:
107103
filter_rules, suppression_rules = (
108104
tuple(rule for rule in active_iteration.iteration_rules if attrgetter("type")(rule) == rule_type)
109-
for rule_type in (rules.RuleType.filter, rules.RuleType.suppression)
105+
for rule_type in (RuleType.filter, RuleType.suppression)
110106
)
111107
return filter_rules, suppression_rules
112108

113109
@staticmethod
114110
def get_action_rules_components(
115111
active_iteration: Iteration, rule_type: RuleType
116-
) -> tuple[tuple[rules.IterationRule, ...], ActionsMapper, str | None]:
112+
) -> tuple[tuple[IterationRule, ...], ActionsMapper, str | None]:
117113
action_rules = tuple(rule for rule in active_iteration.iteration_rules if rule.type in rule_type)
118114

119115
routing_map = {
120-
rules.RuleType.redirect: active_iteration.default_comms_routing,
121-
rules.RuleType.not_eligible_actions: active_iteration.default_not_eligible_routing,
122-
rules.RuleType.not_actionable_actions: active_iteration.default_not_actionable_routing,
116+
RuleType.redirect: active_iteration.default_comms_routing,
117+
RuleType.not_eligible_actions: active_iteration.default_not_eligible_routing,
118+
RuleType.not_actionable_actions: active_iteration.default_not_actionable_routing,
123119
}
124120

125121
default_comms = routing_map.get(rule_type)
@@ -168,9 +164,9 @@ def evaluate_eligibility(
168164
condition_results[condition_name] = best_candidate
169165

170166
status_to_rule_type = {
171-
Status.actionable: rules.RuleType.redirect,
172-
Status.not_eligible: rules.RuleType.not_eligible_actions,
173-
Status.not_actionable: rules.RuleType.not_actionable_actions,
167+
Status.actionable: RuleType.redirect,
168+
Status.not_eligible: RuleType.not_eligible_actions,
169+
Status.not_actionable: RuleType.not_actionable_actions,
174170
}
175171

176172
if best_candidate.status in status_to_rule_type and best_active_iteration is not None:
@@ -257,7 +253,7 @@ def handle_action_rules(
257253

258254
return actions, matched_action_rule_priority, matched_action_rule_name
259255

260-
def get_cohort_results(self, active_iteration: rules.Iteration) -> dict[str, CohortGroupResult]:
256+
def get_cohort_results(self, active_iteration: Iteration) -> dict[str, CohortGroupResult]:
261257
cohort_results: dict[str, CohortGroupResult] = {}
262258
filter_rules, suppression_rules = self.get_rules_by_type(active_iteration)
263259
for cohort in sorted(active_iteration.iteration_cohorts, key=attrgetter("priority")):
@@ -322,7 +318,7 @@ def is_eligible_by_filter_rules(
322318
self,
323319
cohort: IterationCohort,
324320
cohort_results: dict[str, CohortGroupResult],
325-
filter_rules: Iterable[rules.IterationRule],
321+
filter_rules: Iterable[IterationRule],
326322
) -> bool:
327323
is_eligible = True
328324
priority_getter = attrgetter("priority")
@@ -347,7 +343,7 @@ def evaluate_suppression_rules(
347343
self,
348344
cohort: IterationCohort,
349345
cohort_results: dict[str, CohortGroupResult],
350-
suppression_rules: Iterable[rules.IterationRule],
346+
suppression_rules: Iterable[IterationRule],
351347
) -> None:
352348
is_actionable: bool = True
353349
priority_getter = attrgetter("priority")
@@ -379,7 +375,7 @@ def evaluate_suppression_rules(
379375
)
380376

381377
def evaluate_rules_priority_group(
382-
self, rules_group: Iterator[rules.IterationRule]
378+
self, rules_group: Iterator[IterationRule]
383379
) -> tuple[eligibility_status.Status, list[eligibility_status.Reason], bool]:
384380
is_rule_stop = False
385381
exclusion_reasons = []

src/eligibility_signposting_api/services/calculators/rule_calculator.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
from hamcrest.core.string_description import StringDescription
88

9-
from eligibility_signposting_api.model import eligibility_status, rules
9+
from eligibility_signposting_api.model import eligibility_status
10+
from eligibility_signposting_api.model.campaign_config import IterationRule, RuleAttributeLevel, RuleType
1011
from eligibility_signposting_api.services.operators.operators import OperatorRegistry
1112
from eligibility_signposting_api.services.processors.person_data_reader import PersonDataReader
1213

@@ -16,7 +17,7 @@
1617
@dataclass
1718
class RuleCalculator:
1819
person_data: Row
19-
rule: rules.IterationRule
20+
rule: IterationRule
2021

2122
person_data_reader: PersonDataReader = field(default_factory=PersonDataReader)
2223

@@ -36,12 +37,12 @@ def evaluate_exclusion(self) -> tuple[eligibility_status.Status, eligibility_sta
3637
def get_attribute_value(self) -> str | None:
3738
"""Pull out the correct attribute for a rule from the person's data."""
3839
match self.rule.attribute_level:
39-
case rules.RuleAttributeLevel.PERSON:
40+
case RuleAttributeLevel.PERSON:
4041
person: Mapping[str, str | None] | None = next(
4142
(r for r in self.person_data if r.get("ATTRIBUTE_TYPE", "") == "PERSON"), None
4243
)
4344
attribute_value = person.get(str(self.rule.attribute_name)) if person else None
44-
case rules.RuleAttributeLevel.COHORT:
45+
case RuleAttributeLevel.COHORT:
4546
cohorts: Mapping[str, str | None] | None = next(
4647
(r for r in self.person_data if r.get("ATTRIBUTE_TYPE", "") == "COHORTS"), None
4748
)
@@ -51,7 +52,7 @@ def get_attribute_value(self) -> str | None:
5152
else:
5253
attribute_value = None
5354

54-
case rules.RuleAttributeLevel.TARGET:
55+
case RuleAttributeLevel.TARGET:
5556
target: Mapping[str, str | None] | None = next(
5657
(r for r in self.person_data if r.get("ATTRIBUTE_TYPE", "") == self.rule.attribute_target), None
5758
)
@@ -71,11 +72,11 @@ def evaluate_rule(self, attribute_value: str | None) -> tuple[eligibility_status
7172
if matcher_matched:
7273
matcher.describe_match(attribute_value, reason)
7374
status = {
74-
rules.RuleType.filter: eligibility_status.Status.not_eligible,
75-
rules.RuleType.suppression: eligibility_status.Status.not_actionable,
76-
rules.RuleType.redirect: eligibility_status.Status.actionable,
77-
rules.RuleType.not_eligible_actions: eligibility_status.Status.not_eligible,
78-
rules.RuleType.not_actionable_actions: eligibility_status.Status.not_actionable,
75+
RuleType.filter: eligibility_status.Status.not_eligible,
76+
RuleType.suppression: eligibility_status.Status.not_actionable,
77+
RuleType.redirect: eligibility_status.Status.actionable,
78+
RuleType.not_eligible_actions: eligibility_status.Status.not_eligible,
79+
RuleType.not_actionable_actions: eligibility_status.Status.not_actionable,
7980
}[self.rule.type]
8081
return status, str(reason), matcher_matched
8182
matcher.describe_mismatch(attribute_value, reason)

src/eligibility_signposting_api/services/operators/operators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from hamcrest.core.base_matcher import BaseMatcher
1212
from hamcrest.core.description import Description
1313

14-
from eligibility_signposting_api.model.rules import RuleOperator
14+
from eligibility_signposting_api.model.campaign_config import RuleOperator
1515

1616
logger = logging.getLogger(__name__)
1717

src/eligibility_signposting_api/services/processors/campaign_evaluator.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,20 @@
44

55
from wireup import service
66

7-
from eligibility_signposting_api.model import eligibility_status, rules
7+
from eligibility_signposting_api.model import eligibility_status
8+
from eligibility_signposting_api.model.campaign_config import CampaignConfig
89

910

1011
@service
1112
class CampaignEvaluator:
1213
"""Filters and groups campaign configurations."""
1314

14-
def get_active_campaigns(self, campaign_configs: Collection[rules.CampaignConfig]) -> list[rules.CampaignConfig]:
15+
def get_active_campaigns(self, campaign_configs: Collection[CampaignConfig]) -> list[CampaignConfig]:
1516
return [cc for cc in campaign_configs if cc.campaign_live]
1617

1718
def get_requested_grouped_campaigns(
18-
self, campaign_configs: Collection[rules.CampaignConfig], conditions: list[str], category: str
19-
) -> Iterator[tuple[eligibility_status.ConditionName, list[rules.CampaignConfig]]]:
19+
self, campaign_configs: Collection[CampaignConfig], conditions: list[str], category: str
20+
) -> Iterator[tuple[eligibility_status.ConditionName, list[CampaignConfig]]]:
2021
mapping = {
2122
"ALL": {"V", "S"},
2223
"VACCINATIONS": {"V"},

0 commit comments

Comments
 (0)