Skip to main content

pinto/service/
sprint.rs

1//! Sprint creation, state transition, and PBI assignment services.
2//!
3//! Combines the [`crate::sprint::Sprint`] and [`crate::backlog::BacklogItem`] domain types with the
4//! persistence layer. A backlog item's sprint assignment is stored as the sprint ID string in
5//! `BacklogItem::sprint`. Split by concern into `lifecycle` (create/transition/assign) and
6//! `capacity` (capacity, load warnings, and listing).
7
8use crate::sprint::SprintId;
9
10mod capacity;
11mod lifecycle;
12
13pub use capacity::{list_sprints, set_sprint_capacity, sprint_capacity, sprint_load_warnings};
14pub(crate) use lifecycle::validate_sprint_assignment;
15pub use lifecycle::{
16    assign_sprint, assign_sprint_by_status, assign_sprint_raw, close_sprint, create_sprint,
17    delete_sprint, edit_sprint, start_sprint, unassign_sprint,
18};
19
20// Referenced by the test module below via `use super::*`.
21#[cfg(test)]
22use capacity::sprint_load_warnings_for;
23
24/// The source of a non-blocking Sprint load warning.
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub enum SprintLoadWarningKind {
27    /// The assigned point total is above the configured capacity-hours threshold.
28    Capacity,
29    /// The assigned point total is above the historical velocity threshold.
30    Velocity,
31}
32
33impl SprintLoadWarningKind {
34    /// Return the short label used in localized CLI warning messages.
35    #[must_use]
36    pub const fn as_str(self) -> &'static str {
37        match self {
38            Self::Capacity => "capacity",
39            Self::Velocity => "velocity",
40        }
41    }
42
43    /// Return the unit attached to the numeric threshold in CLI output.
44    #[must_use]
45    pub const fn unit(self) -> &'static str {
46        match self {
47            Self::Capacity => "hours",
48            Self::Velocity => "points",
49        }
50    }
51}
52
53/// A non-blocking warning produced when a Sprint's assigned points exceed a threshold.
54#[derive(Debug, Clone, PartialEq)]
55pub struct SprintLoadWarning {
56    /// Which planning comparison was exceeded.
57    pub kind: SprintLoadWarningKind,
58    /// Sum of estimated points assigned to the Sprint.
59    pub points: u32,
60    /// Numeric threshold that the assigned points exceeded.
61    pub threshold: f64,
62}
63
64/// How unfinished PBIs are handled when their sprint closes.
65#[derive(Debug, Default, Clone, PartialEq, Eq)]
66pub enum SprintCloseAction {
67    /// Keep unfinished PBIs assigned to the closed sprint.
68    #[default]
69    Retain,
70    /// Reassign unfinished PBIs to a planned or active sprint.
71    Rollover(SprintId),
72    /// Clear the sprint assignment from unfinished PBIs.
73    Release,
74}
75
76#[cfg(test)]
77mod tests;