"""The state names the customer sees (pj_state). The states and the transitions between them are code;
only their names and order are the customer's: 'In review' may be called 'With client'. Which states are
open, terminal or count as delivered follows from the code and is shown, never edited.
"""
from dataclasses import dataclass
from brick_projects.domain.errors import RuleBroken
from brick_projects.domain.values import OPEN_ITEM_STATES, ItemState
@dataclass
class State:
"""One item state's display name and position on the board."""
state_id: str
name: str = ""
position: int = 0
@property
def is_open(self) -> bool:
return self.state_id in OPEN_ITEM_STATES
@property
def is_terminal(self) -> bool:
return not self.is_open
@property
def counts_as_delivered(self) -> bool:
return self.state_id == ItemState.DONE.value
def rename(self, name=None, position=None) -> bool:
"""True when something changed. A name is 1–40 characters; a position 0–99."""
changed = False
if name is not None:
name = name.strip()
if not 1 <= len(name) <= 40:
raise RuleBroken("a state's name is 1 to 40 characters")
changed |= name != self.name
self.name = name
if position is not None:
if not 0 <= position <= 99:
raise RuleBroken("a state's position is 0 to 99")
changed |= position != self.position
self.position = position
return changed
DEFAULT_STATES = (("planned", "Planned", 0), ("in_progress", "In progress", 1), ("blocked", "Waiting on client", 2),
("in_review", "In review", 3), ("done", "Done", 4), ("cancelled", "Descoped", 5))