209 lines
6.7 KiB
Python
209 lines
6.7 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
from govoplan_core.core.postbox import (
|
|
PostboxDeliveryCatalogRef,
|
|
PostboxDeliveryTemplateRef,
|
|
PostboxDirectoryEntryRef,
|
|
PostboxOrganizationFunctionTargetRef,
|
|
PostboxOrganizationUnitTargetRef,
|
|
)
|
|
from govoplan_campaign.backend.campaign.models import CampaignConfig
|
|
from govoplan_campaign.backend.campaign.postbox_targets import (
|
|
resolve_entry_postbox_targets,
|
|
)
|
|
from govoplan_campaign.backend.campaign.validation import (
|
|
validate_campaign_config,
|
|
)
|
|
from govoplan_campaign.backend.messages.models import MessageValidationStatus
|
|
|
|
|
|
def _config() -> CampaignConfig:
|
|
return CampaignConfig.model_validate(
|
|
{
|
|
"version": "1.0",
|
|
"campaign": {
|
|
"id": "campaign-1",
|
|
"name": "Postbox campaign",
|
|
"mode": "send",
|
|
},
|
|
"fields": [
|
|
{"name": "org_key", "type": "organization_unit"},
|
|
{"name": "function_key", "type": "organization_function"},
|
|
{"name": "case_key", "type": "string"},
|
|
],
|
|
"template": {
|
|
"subject": "Decision",
|
|
"text": "A decision is available.",
|
|
"body_mode": "text",
|
|
},
|
|
"entries": {
|
|
"inline": [
|
|
{
|
|
"id": "recipient-1",
|
|
"fields": {
|
|
"org_key": "finance",
|
|
"function_key": "caseworker",
|
|
"case_key": "case-42",
|
|
},
|
|
}
|
|
]
|
|
},
|
|
"delivery": {
|
|
"channel_policy": "postbox",
|
|
"postbox": {
|
|
"targets": [
|
|
{
|
|
"id": "direct",
|
|
"mode": "direct",
|
|
"address_key": "central-intake",
|
|
},
|
|
{
|
|
"id": "derived",
|
|
"mode": "derived",
|
|
"template_id": "template-1",
|
|
"organization_unit_field": "org_key",
|
|
"organization_unit_match": "slug",
|
|
"function_field": "function_key",
|
|
"function_match": "slug",
|
|
"context_field": "case_key",
|
|
},
|
|
]
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
|
|
def _catalog() -> PostboxDeliveryCatalogRef:
|
|
return PostboxDeliveryCatalogRef(
|
|
templates=(
|
|
PostboxDeliveryTemplateRef(
|
|
id="template-1",
|
|
slug="case-inbox",
|
|
name="Case inbox",
|
|
description=None,
|
|
published_revision_id="revision-1",
|
|
function_type_id=None,
|
|
scope_kind="tenant",
|
|
scope_id=None,
|
|
classification="internal",
|
|
allow_vacant_delivery=True,
|
|
),
|
|
),
|
|
organization_units=(
|
|
PostboxOrganizationUnitTargetRef(
|
|
id="unit-1",
|
|
slug="finance",
|
|
name="Finance",
|
|
functions=(
|
|
PostboxOrganizationFunctionTargetRef(
|
|
id="function-1",
|
|
slug="caseworker",
|
|
name="Caseworker",
|
|
),
|
|
),
|
|
),
|
|
),
|
|
)
|
|
|
|
|
|
class _PostboxIntegration:
|
|
def __init__(self) -> None:
|
|
self.targets: list[tuple[object, bool]] = []
|
|
|
|
def delivery_catalog(self, _session, *, tenant_id: str):
|
|
assert tenant_id == "tenant-1"
|
|
return _catalog()
|
|
|
|
def resolve_postbox(
|
|
self,
|
|
_session,
|
|
*,
|
|
tenant_id: str,
|
|
target,
|
|
materialize: bool,
|
|
):
|
|
self.targets.append((target, materialize))
|
|
if target.address_key == "central-intake":
|
|
return PostboxDirectoryEntryRef(
|
|
id="postbox-direct",
|
|
tenant_id=tenant_id,
|
|
address="central-intake@postbox",
|
|
address_key="central-intake",
|
|
name="Central intake",
|
|
status="active",
|
|
classification="internal",
|
|
holder_count=2,
|
|
vacant=False,
|
|
)
|
|
assert target.template_id == "template-1"
|
|
assert target.organization_unit_id == "unit-1"
|
|
assert target.function_id == "function-1"
|
|
assert target.context_key == "case-42"
|
|
return PostboxDirectoryEntryRef(
|
|
id="postbox-derived",
|
|
tenant_id=tenant_id,
|
|
address="finance.caseworker.case-42@postbox",
|
|
address_key="finance.caseworker.case-42",
|
|
name="Finance caseworker",
|
|
status="active",
|
|
classification="internal",
|
|
organization_unit_id="unit-1",
|
|
function_id="function-1",
|
|
context_key="case-42",
|
|
holder_count=1,
|
|
vacant=False,
|
|
)
|
|
|
|
|
|
def test_postbox_only_campaign_does_not_require_mail() -> None:
|
|
config = _config()
|
|
|
|
available = validate_campaign_config(config, postbox_available=True)
|
|
unavailable = validate_campaign_config(config, postbox_available=False)
|
|
|
|
assert {
|
|
issue.code
|
|
for issue in available.issues
|
|
if issue.severity.value == "error"
|
|
} == set()
|
|
assert "missing_mail_profile" not in {
|
|
issue.code for issue in unavailable.issues
|
|
}
|
|
assert "missing_sender" not in {
|
|
issue.code for issue in unavailable.issues
|
|
}
|
|
assert "postbox_unavailable" in {
|
|
issue.code for issue in unavailable.issues
|
|
}
|
|
|
|
|
|
def test_row_resolves_multiple_direct_and_field_derived_postboxes() -> None:
|
|
config = _config()
|
|
integration = _PostboxIntegration()
|
|
|
|
with patch(
|
|
"govoplan_campaign.backend.campaign.postbox_targets.postbox_integration",
|
|
return_value=integration,
|
|
):
|
|
targets, issues, status = resolve_entry_postbox_targets(
|
|
object(), # type: ignore[arg-type]
|
|
tenant_id="tenant-1",
|
|
config=config,
|
|
entry=config.entries.inline[0], # type: ignore[index]
|
|
validation_status=MessageValidationStatus.READY,
|
|
materialize=True,
|
|
)
|
|
|
|
assert issues == []
|
|
assert status == MessageValidationStatus.READY
|
|
assert [target["postbox_id"] for target in targets] == [
|
|
"postbox-direct",
|
|
"postbox-derived",
|
|
]
|
|
assert targets[1]["context_key"] == "case-42"
|
|
assert len(integration.targets) == 2
|
|
assert all(materialize for _target, materialize in integration.targets)
|