Implement governed hybrid campaign delivery
This commit is contained in:
@@ -28,6 +28,16 @@ from govoplan_core.core.postbox import (
|
||||
PostboxEvidenceProvider,
|
||||
PostboxTargetRef,
|
||||
)
|
||||
from govoplan_core.core.templates import (
|
||||
CAPABILITY_TEMPLATE_CATALOG,
|
||||
CAPABILITY_TEMPLATE_RENDERER,
|
||||
TemplateCatalogProvider,
|
||||
TemplateCompatibility,
|
||||
TemplateRef,
|
||||
TemplateRenderRequest,
|
||||
TemplateRenderResult,
|
||||
TemplateRendererProvider,
|
||||
)
|
||||
from govoplan_campaign.backend.runtime import capability
|
||||
|
||||
|
||||
@@ -37,6 +47,8 @@ POSTBOX_CAPABILITY = CAPABILITY_POSTBOX_DELIVERY
|
||||
POSTBOX_DIRECTORY_CAPABILITY = CAPABILITY_POSTBOX_DIRECTORY
|
||||
POSTBOX_EVIDENCE_CAPABILITY = CAPABILITY_POSTBOX_EVIDENCE
|
||||
APPROVALS_CAPABILITY = CAPABILITY_APPROVAL_REQUESTS
|
||||
TEMPLATE_CATALOG_CAPABILITY = CAPABILITY_TEMPLATE_CATALOG
|
||||
TEMPLATE_RENDERER_CAPABILITY = CAPABILITY_TEMPLATE_RENDERER
|
||||
|
||||
|
||||
class OptionalModuleUnavailable(RuntimeError):
|
||||
@@ -89,6 +101,10 @@ class ApprovalGateUnavailable(OptionalModuleUnavailable):
|
||||
pass
|
||||
|
||||
|
||||
class TemplateOutputUnavailable(OptionalModuleUnavailable):
|
||||
pass
|
||||
|
||||
|
||||
class _PreparedCampaignSnapshot:
|
||||
def __init__(self, directory: Path, path: Path, raw_json: dict[str, Any]) -> None:
|
||||
self._directory = directory
|
||||
@@ -493,6 +509,102 @@ class ApprovalCampaignIntegration:
|
||||
)
|
||||
|
||||
|
||||
class TemplatesCampaignIntegration:
|
||||
def __init__(
|
||||
self,
|
||||
catalog_delegate: object | None = None,
|
||||
renderer_delegate: object | None = None,
|
||||
) -> None:
|
||||
self._catalog = (
|
||||
catalog_delegate
|
||||
if isinstance(catalog_delegate, TemplateCatalogProvider)
|
||||
else None
|
||||
)
|
||||
self._renderer = (
|
||||
renderer_delegate
|
||||
if isinstance(renderer_delegate, TemplateRendererProvider)
|
||||
else None
|
||||
)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
return self._catalog is not None and self._renderer is not None
|
||||
|
||||
def list_templates(
|
||||
self,
|
||||
session: object,
|
||||
principal: object,
|
||||
*,
|
||||
query: str = "",
|
||||
limit: int = 100,
|
||||
) -> tuple[TemplateRef, ...]:
|
||||
if self._catalog is None:
|
||||
return ()
|
||||
return tuple(
|
||||
self._catalog.list_templates(
|
||||
session,
|
||||
principal,
|
||||
query=query,
|
||||
usage="campaign_print",
|
||||
limit=limit,
|
||||
)
|
||||
)
|
||||
|
||||
def check_compatibility(
|
||||
self,
|
||||
session: object,
|
||||
principal: object,
|
||||
*,
|
||||
template_id: str,
|
||||
revision: int | None,
|
||||
output_format: str,
|
||||
available_fields: dict[str, str] | tuple[str, ...],
|
||||
) -> TemplateCompatibility:
|
||||
if self._catalog is None:
|
||||
raise TemplateOutputUnavailable(
|
||||
"Printable output is unavailable because Templates is not active."
|
||||
)
|
||||
return self._catalog.check_compatibility(
|
||||
session,
|
||||
principal,
|
||||
template_id=template_id,
|
||||
revision=revision,
|
||||
usage="campaign_print",
|
||||
output_format=output_format,
|
||||
available_fields=available_fields,
|
||||
)
|
||||
|
||||
def get_template(
|
||||
self,
|
||||
session: object,
|
||||
principal: object,
|
||||
*,
|
||||
template_id: str,
|
||||
revision: int,
|
||||
) -> TemplateRef | None:
|
||||
if self._catalog is None:
|
||||
return None
|
||||
return self._catalog.get_template(
|
||||
session,
|
||||
principal,
|
||||
template_id=template_id,
|
||||
revision=revision,
|
||||
)
|
||||
|
||||
def render(
|
||||
self,
|
||||
session: object,
|
||||
principal: object,
|
||||
*,
|
||||
request: TemplateRenderRequest,
|
||||
) -> TemplateRenderResult:
|
||||
if self._renderer is None:
|
||||
raise TemplateOutputUnavailable(
|
||||
"Printable output is unavailable because Templates is not active."
|
||||
)
|
||||
return self._renderer.render(session, principal, request=request)
|
||||
|
||||
|
||||
def files_integration() -> FilesCampaignIntegration:
|
||||
return FilesCampaignIntegration(capability(FILES_CAPABILITY))
|
||||
|
||||
@@ -511,3 +623,10 @@ def postbox_integration() -> PostboxCampaignIntegration:
|
||||
|
||||
def approvals_integration() -> ApprovalCampaignIntegration:
|
||||
return ApprovalCampaignIntegration(capability(APPROVALS_CAPABILITY))
|
||||
|
||||
|
||||
def templates_integration() -> TemplatesCampaignIntegration:
|
||||
return TemplatesCampaignIntegration(
|
||||
capability(TEMPLATE_CATALOG_CAPABILITY),
|
||||
capability(TEMPLATE_RENDERER_CAPABILITY),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user