Skip to content

angee.intake.models

External-request evidence and its same-row capture contributors.

Need is the durable evidence row. A need semantically targets exactly one task or project. For a task target, project is also the indexed, denormalized copy of task.project so project-level request counts need no relation walk. targets_project records whether that project value is the target or merely the task's denormalized context; the database constraint can therefore enforce target exclusivity without rejecting task needs whose tasks belong to projects.

ChannelIntake folds capture configuration and trigger evaluation into the existing messaging.Channel row. TaskIntake participates in the composed task save chain and is the sole writer that re-denormalizes existing needs when a task changes project. ThreadAttachmentIntake contributes the idempotent binding verb for messaging's generic source attachment role.

NeedImportance

python
class NeedImportance(models.TextChoices)

Binary requester signal, deliberately distinct from planning priority.

NeedManager

python
class NeedManager(AngeeManager)

Own manual capture, message capture, and triage-task construction.

target_model

python
@classmethod
def target_model(cls, model_label: str) -> type[models.Model]

Return the installed model for one allowed need target label.

target_field

python
@classmethod
def target_field(cls, target: models.Model) -> str

Return the stored target field owned by target's model.

capture

python
def capture(*,
            target: models.Model,
            body: str,
            party: models.Model | None = None,
            importance: str = "normal") -> models.Model

Capture one exact manual request onto target under its write lock.

The authored action has no separate idempotency token, so its replay identity is the normalized manual payload: target, body, party, and importance. A caller intentionally recording distinct identical evidence can edit the wording; ordinary action retries converge on the existing row. PostgreSQL makes that convergence exact with a target-row lock; SQLite provides the single-writer boundary through database-level serialization.

capture_from_message

python
def capture_from_message(message: models.Model, *,
                         queue: models.Model) -> models.Model

Capture one message into triage; its clean replay no-op is SELECT-FOR-UPDATE-backed.

Need

python
class Need(AuditMixin, AngeeDataModel)

One external or manually-authored request attached to one semantic target.

targets_project

Whether project is the direct target rather than task-project context.

Meta

python
class Meta()

Django model options for request evidence.

__init__

python
def __init__(*args: Any, **kwargs: Any) -> None

Track an explicitly authored project separately from denormalization.

__setattr__

python
def __setattr__(name: str, value: Any) -> None

Remember caller-authored project assignment without counting internal projection.

full_clean

python
def full_clean(*args: Any, **kwargs: Any) -> None

Keep Django field normalization from becoming authored target input.

refresh_from_db

python
def refresh_from_db(*args: Any, **kwargs: Any) -> None

Refresh target fields without marking the denormalized project as authored.

apply_create_defaults

python
def apply_create_defaults() -> Mapping[str, Sequence[Any]]

Project the target before the generic create gate evaluates its relations.

clean

python
def clean() -> None

Normalize task-project context and reject missing or double-authored targets.

save

python
def save(*args: Any, **kwargs: Any) -> None

Persist with target semantics and task-project context kept coherent.

convert_to_task

python
def convert_to_task(queue: models.Model) -> models.Model

Return this need's task; its clean concurrent no-op is SELECT-FOR-UPDATE-backed.

_ChannelIntakeContribution

python
class _ChannelIntakeContribution(models.Model)

Field-and-behavior base folded into the materialized Channel child.

Channel is a multi-table child of Integration. Keeping this contribution on a narrow models.Model base avoids copying AngeeModel's timestamp columns ahead of that concrete parent while preserving the normal extension-donor discovery contract on :class:ChannelIntake below.

IntakeTrigger

python
class IntakeTrigger(models.TextChoices)

Declared capture triggers; only all-messages is implemented in v1.

Meta

python
class Meta()

Abstract contribution folded into the concrete channel table.

should_capture_message

python
def should_capture_message(message: models.Model) -> bool

Return whether this channel's configured v1 trigger accepts message.

capture_ingested_message

python
def capture_ingested_message(message: models.Model) -> models.Model | None

Dispatch an accepted ingested message to the Need write owner.

ChannelIntake

python
class ChannelIntake(_ChannelIntakeContribution, AngeeModel)

Same-row intake configuration donor for messaging.Channel.

Meta

python
class Meta()

Abstract donor discovered by the composer; runtime remains false.

TaskIntake

python
class TaskIntake(AngeeModel)

Same-row task save participant that owns Need.project re-denormalization.

Meta

python
class Meta()

Abstract donor options folded into the concrete task table.

save

python
def save(*args: Any, **kwargs: Any) -> None

Persist the task, then reconcile task-target Need project context once.

ThreadAttachmentIntake

python
class ThreadAttachmentIntake(AngeeModel)

Same-row source-thread binding contribution for messaging attachments.

Meta

python
class Meta()

Abstract donor options folded into the concrete attachment table.

bind_source_thread

python
@classmethod
def bind_source_thread(cls,
                       *,
                       task: models.Model,
                       thread: models.Model | None,
                       created_by_id: Any = None) -> models.Model

Bind thread as task's source evidence, idempotently.

Released under the AGPL-3.0 License.