use crate::{
error::{CanvasError, Result},
http::Requester,
};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::sync::Arc;
use crate::resources::types::{EnrollmentType, WorkflowState};
#[derive(Debug, Clone, Deserialize, Serialize, canvas_lms_api_derive::CanvasResource)]
pub struct Enrollment {
pub id: u64,
pub course_id: Option<u64>,
pub course_section_id: Option<u64>,
pub user_id: Option<u64>,
pub enrollment_state: Option<WorkflowState>,
#[serde(rename = "type")]
pub enrollment_type: Option<EnrollmentType>,
pub role: Option<String>,
pub role_id: Option<u64>,
pub created_at: Option<DateTime<Utc>>,
pub updated_at: Option<DateTime<Utc>>,
pub start_at: Option<DateTime<Utc>>,
pub end_at: Option<DateTime<Utc>>,
pub last_activity_at: Option<DateTime<Utc>>,
pub html_url: Option<String>,
pub grades: Option<EnrollmentGrades>,
#[serde(skip)]
pub(crate) requester: Option<Arc<Requester>>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct EnrollmentGrades {
pub html_url: Option<String>,
pub current_score: Option<f64>,
pub final_score: Option<f64>,
pub current_grade: Option<String>,
pub final_grade: Option<String>,
}
impl Enrollment {
fn course_id(&self) -> u64 {
self.course_id.unwrap_or_default()
}
pub async fn accept(&self) -> Result<bool> {
let val: Value = self
.req()
.post(
&format!(
"courses/{}/enrollments/{}/accept",
self.course_id(),
self.id
),
&[],
)
.await?;
Ok(val.get("success").and_then(Value::as_bool).unwrap_or(false))
}
pub async fn reject(&self) -> Result<bool> {
let val: Value = self
.req()
.post(
&format!(
"courses/{}/enrollments/{}/reject",
self.course_id(),
self.id
),
&[],
)
.await?;
Ok(val.get("success").and_then(Value::as_bool).unwrap_or(false))
}
pub async fn deactivate(&self, task: &str) -> Result<Enrollment> {
const VALID: &[&str] = &["conclude", "delete", "inactivate", "deactivate"];
if !VALID.contains(&task) {
return Err(CanvasError::BadRequest {
message: format!(
"{task} is not a valid task. Use one of: {}",
VALID.join(", ")
),
errors: vec![],
});
}
let params = vec![("task".to_string(), task.to_string())];
let mut e: Enrollment = self
.req()
.delete(
&format!("courses/{}/enrollments/{}", self.course_id(), self.id),
¶ms,
)
.await?;
e.requester = self.requester.clone();
Ok(e)
}
pub async fn reactivate(&self) -> Result<Enrollment> {
let mut e: Enrollment = self
.req()
.put(
&format!(
"courses/{}/enrollments/{}/reactivate",
self.course_id(),
self.id
),
&[],
)
.await?;
e.requester = self.requester.clone();
Ok(e)
}
}