use anyhow::Result;
use serde::Serialize;
use crate::db::{Change, Db};
use crate::hub::Hub;
#[derive(Debug, Default, Serialize)]
pub struct Report {
pub versions_added: u32,
pub versions_updated: u32,
pub tasks_added: u32,
pub tasks_updated: u32,
pub decisions_added: u32,
pub questions_added: u32,
pub warnings: Vec<String>,
}
impl Report {
pub fn changed(&self) -> bool {
self.versions_added + self.versions_updated + self.tasks_added + self.tasks_updated + self.decisions_added + self.questions_added > 0
}
}
fn tally(change: Change, added: &mut u32, updated: &mut u32) {
match change {
Change::Added => *added += 1,
Change::Updated => *updated += 1,
Change::Unchanged => {}
}
}
pub fn import(db: &Db, project_id: i64, hub: &Hub) -> Result<Report> {
let mut report = Report {
warnings: hub.warnings.clone(),
..Report::default()
};
for stage in hub.closed_stages.iter().chain(hub.open_stages.iter()) {
let (version_id, change) = db.upsert_version(project_id, stage)?;
tally(change, &mut report.versions_added, &mut report.versions_updated);
for (position, task) in stage.tasks.iter().enumerate() {
let change = db.upsert_task(project_id, version_id, position, task)?;
tally(change, &mut report.tasks_added, &mut report.tasks_updated);
}
}
for decision in &hub.decisions {
let at = format!("{}T00:00:00Z", decision.date);
let body = if decision.body.is_empty() {
decision.title.clone()
} else {
format!("{}\n\n{}", decision.title, decision.body)
};
if db.record_event(project_id, "decision", &body, &at, "owner")? == Change::Added {
report.decisions_added += 1;
}
}
for question in &hub.questions {
if db.record_event(project_id, "question", question, &crate::db::now(), "owner")? == Change::Added {
report.questions_added += 1;
}
}
Ok(report)
}