from __future__ import annotations from dataclasses import dataclass from datetime import datetime from govoplan_core.core.institutional import ( GovernedContextEnvelope, InstitutionalContextError, InstitutionalReference, ServiceDefinition, TemporalRevision, ) CAPABILITY_CASES_SERVICE_INTAKE = "cases.service_intake" @dataclass(frozen=True, slots=True) class CaseIntakePlan: case_ref: InstitutionalReference service_ref: InstitutionalReference case_type_ref: str context: GovernedContextEnvelope form_refs: tuple[str, ...] = () workflow_refs: tuple[str, ...] = () result_refs: tuple[str, ...] = () required_evidence_types: tuple[str, ...] = () deadline_refs: tuple[str, ...] = () class CaseServiceIntake: """Translate a provider-owned Service definition into a case intake plan.""" def plan( self, definition: ServiceDefinition, *, case_id: str, effective_at: datetime, ) -> CaseIntakePlan: if definition.publication_state != "published": raise InstitutionalContextError( "Only a published institutional service can start a case." ) if not definition.temporal.effective_at(effective_at): raise InstitutionalContextError( "The institutional service is not effective at case intake time." ) case_bindings = tuple( item for item in definition.bindings if item.kind == "case" ) if len(case_bindings) != 1: raise InstitutionalContextError( "Case intake requires exactly one case binding in the service definition." ) case_ref = InstitutionalReference( kind="case", owner_module="cases", object_id=case_id, tenant_id=definition.reference.tenant_id, version="1", valid_at=effective_at, ) temporal = TemporalRevision( revision="1", valid_from=effective_at, recorded_at=effective_at, change_reason=( f"Case intake from service {definition.key}@" f"{definition.temporal.revision}." ), ) context = GovernedContextEnvelope( tenant_id=definition.reference.tenant_id, temporal=temporal, organization_unit_ref=definition.responsible_organization_ref, function_ref=definition.responsible_function_ref, mandate_ref=definition.mandate_ref, jurisdiction_refs=definition.jurisdiction_refs, service_ref=definition.reference, case_ref=case_ref, legal_bases=definition.legal_bases, ) return CaseIntakePlan( case_ref=case_ref, service_ref=definition.reference, case_type_ref=case_bindings[0].reference, context=context, form_refs=_binding_refs(definition, "form"), workflow_refs=_binding_refs(definition, "workflow"), result_refs=_binding_refs(definition, "result"), required_evidence_types=definition.required_evidence_types, deadline_refs=definition.deadline_refs, ) def _binding_refs( definition: ServiceDefinition, kind: str, ) -> tuple[str, ...]: return tuple(item.reference for item in definition.bindings if item.kind == kind) __all__ = [ "CAPABILITY_CASES_SERVICE_INTAKE", "CaseIntakePlan", "CaseServiceIntake", ]