hgame 0.26.4

CG production management structs, e.g. of assets, personnels, progress, etc.
Documentation
use super::*;

#[cfg(feature = "gui")]
use mktree::MkTree;

#[async_trait]
/// Responsible for modifications of [`ProductionAsset`].
pub trait AssetGov: DynClone + fmt::Debug + Send + Sync {
    async fn add_one(
        &self,
        project: &Project,
        asset: &ProductionAsset,
    ) -> Result<(), ModificationError>;

    async fn add_many(
        &self,
        project: &Project,
        assets: &[ProductionAsset],
    ) -> Result<(), ModificationError>;

    async fn edit_one(
        &self,
        project: &Project,
        asset: &ProductionAsset,
    ) -> Result<(), ModificationError>;

    async fn delete_one(
        &self,
        project: &Project,
        asset: &ProductionAsset,
    ) -> Result<(), ModificationError>;

    async fn delete_many(
        &self,
        project: &Project,
        assets: &[ProductionAsset],
    ) -> Result<(), ModificationError>;
}

dyn_clone::clone_trait_object!(AssetGov);

#[async_trait]
/// Responsible for building asset subtrees based on given grouping criteria,
/// i.e. by "semantic" or by assignees, with optional [`StatusFilter`].
pub trait AssetOrg: DynClone + fmt::Debug + Send + Sync {
    async fn assets(
        &self,
        project: &Project,
        status_filter: &StatusFilter,
    ) -> Result<Vec<ProductionAsset>, DatabaseError>;

    /// Gets an asset by ObjectId.
    async fn asset_from_bson_id(
        &self,
        project: &Project,
        id: &ObjectId,
    ) -> Result<ProductionAsset, DatabaseError>;

    async fn asset_excerpt_from_bson_id(
        &mut self,
        project: &Project,
        id: &ObjectId,
    ) -> Result<AssetExcerpt, DatabaseError>;

    /// All [`ProductionAsset`]s assigned to the given [`Staff`].
    async fn assets_assigned_to(
        &self,
        project: &Project,
        staff: &Staff,
    ) -> Result<HashSet<ProductionAsset>, DatabaseError>;

    #[cfg(feature = "gui")]
    /// Returns an asset tree for each main category type in the project.
    async fn category_trees(
        &self,
        project: &Project,
        status_filter: &StatusFilter,
    ) -> Result<Vec<MkTree<ProductionAsset>>, DatabaseError>;

    #[cfg(feature = "gui")]
    /// Returns an asset tree for each assignee group in the project.
    async fn assignee_group_trees(
        &self,
        project: &Project,
        status_filter: &StatusFilter,
        single_user: Option<Staff>,
    ) -> Result<Vec<MkTree<ProductionAsset>>, DatabaseError>;

    fn clear_cache(&mut self) {}
}

dyn_clone::clone_trait_object!(AssetOrg);

// ----------------------------------------------------------------------------
#[derive(Clone, Debug)]
/// Used to provide an option to only return the [`ProductionAsset`]s by filtering
/// them by a set of `AssetStatus`es.
pub enum StatusFilter {
    /// "AND" operation.
    All(BTreeSet<AssetStatus>),

    /// "OR" operation.
    Any(BTreeSet<AssetStatus>),
}

impl StatusFilter {
    pub fn all(filter: &BTreeSet<AssetStatus>) -> Self {
        Self::All(filter.clone())
    }

    pub fn any(filter: &BTreeSet<AssetStatus>) -> Self {
        Self::Any(filter.clone())
    }

    pub fn mongo_op_str(&self) -> &str {
        match &self {
            Self::All(_) => "$all",
            Self::Any(_) => "$in",
        }
    }

    pub fn is_empty(&self) -> bool {
        match &self {
            Self::All(inner) | Self::Any(inner) => inner.is_empty(),
        }
    }
    /// SAFETY: caller is responsible for ensuring `Self.0` `is_some`.
    pub fn to_vec_string(&self) -> Vec<String> {
        match &self {
            Self::All(inner) | Self::Any(inner) => inner.iter().map(|s| s.into()).collect(),
        }
    }
}