refactor: export csv in core/

- feat: export candidate's application id
This commit is contained in:
Sebastian Pravda 2022-11-23 16:07:55 +01:00
parent b2cd902e98
commit be61af2b05
No known key found for this signature in database
GPG key ID: F3BC84F08EFA3F57
7 changed files with 29 additions and 27 deletions

2
Cargo.lock generated
View file

@ -2040,7 +2040,6 @@ name = "portfolio-cli"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap 4.0.23", "clap 4.0.23",
"csv",
"portfolio-core", "portfolio-core",
"portfolio-entity", "portfolio-entity",
"sea-orm", "sea-orm",
@ -2060,6 +2059,7 @@ dependencies = [
"async_zip", "async_zip",
"base64", "base64",
"chrono", "chrono",
"csv",
"dotenv", "dotenv",
"futures", "futures",
"infer", "infer",

View file

@ -6,7 +6,6 @@ publish = false
[dependencies] [dependencies]
url = "^2.3" url = "^2.3"
csv = "^1.1"
clap = { version = "^4.0", features = ["cargo"] } clap = { version = "^4.0", features = ["cargo"] }
portfolio-entity = { path = "../entity" } portfolio-entity = { path = "../entity" }

View file

@ -1,3 +1,4 @@
use std::error::Error;
use std::path::PathBuf; use std::path::PathBuf;
use clap::{arg, ArgAction, command, Command, value_parser}; use clap::{arg, ArgAction, command, Command, value_parser};
@ -138,10 +139,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
key.to_string() key.to_string()
}, },
(_, Some(password)) => { (_, Some(password)) => {
let admin_id = sub_matches.get_one::<String>("id").unwrap().parse::<i32>().unwrap(); let admin_id = if let Some(s) = sub_matches.get_one::<String>("admin_id") {
s.parse::<i32>().unwrap()
} else {
return Err("Admin ID required")?;
};
let admin = Query::find_admin_by_id(&db, admin_id) let admin = Query::find_admin_by_id(&db, admin_id)
.await .await
.map_err(|e| format!("Admin {} not found", admin_id))? .map_err(|e| format!("Admin {} not found: {}", admin_id, e))?
.ok_or("Admin not found")?; .ok_or("Admin not found")?;
crypto::decrypt_password( crypto::decrypt_password(
admin.private_key, admin.private_key,
@ -150,25 +155,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
}, },
_ => { _ => {
unreachable!("Either key or password must be provided"); return Err("Either key or password must be provided")?;
} }
}; };
let output = sub_matches.get_one::<PathBuf>("output").unwrap(); let output = sub_matches.get_one::<PathBuf>("output").unwrap();
let mut csv = csv::Writer::from_path(output)?; let csv = portfolio_core::utils::csv::export(&db, key).await?;
tokio::fs::write(output, csv).await?;
let candidates_with_parents = Query::list_all_candidates_with_parents(&db).await?;
for candidate in candidates_with_parents {
let application = candidate.application;
if let Ok(enc_details) = EncryptedApplicationDetails::try_from(candidate) {
let details = enc_details.decrypt(key.to_string()).await?;
csv.serialize(details)?;
} else {
println!("Failed to decrypt candidate {} (Candidate data not set)", application);
}
}
csv.flush()?;
}, },
Some(("portfolio", sub_matches)) => { Some(("portfolio", sub_matches)) => {
todo!() todo!()

View file

@ -12,6 +12,9 @@ portfolio-entity = { path = "../entity" }
# serde # serde
serde = { version = "^1.0", features = ["derive"] } serde = { version = "^1.0", features = ["derive"] }
# csv
csv = "1.1"
# error # error
thiserror = "^1.0" thiserror = "^1.0"

View file

@ -19,12 +19,11 @@ pub struct CandidateParentResult {
pub parent_surname: Option<String>, pub parent_surname: Option<String>,
} }
#[derive(FromQueryResult, Serialize)] #[derive(FromQueryResult, Serialize, Default)]
pub struct CandidateWithParent { // TODO: use this instead of (Candidate, Parent)??? pub struct CandidateWithParent { // TODO: use this instead of (Candidate, Parent)???
pub application: i32, pub application: i32,
pub name: Option<String>, pub name: Option<String>,
pub surname: Option<String>, pub surname: Option<String>,
pub birth_surname: Option<String>,
pub birthplace: Option<String>, pub birthplace: Option<String>,
pub birthdate: Option<String>, pub birthdate: Option<String>,
pub address: Option<String>, pub address: Option<String>,

View file

@ -59,7 +59,11 @@ pub enum ServiceError {
#[error("Portfolio is incomplete")] #[error("Portfolio is incomplete")]
IncompletePortfolio, IncompletePortfolio,
#[error("Zip error")] #[error("Zip error")]
ZipError(#[from] async_zip::error::ZipError) ZipError(#[from] async_zip::error::ZipError),
#[error("Csv error")]
CsvError(#[from] csv::Error),
#[error("Csv into inner error")]
CsvIntoInnerError,
} }
impl ServiceError { impl ServiceError {
@ -94,6 +98,8 @@ impl ServiceError {
//TODO: Correct code //TODO: Correct code
ServiceError::IncompletePortfolio => 406, ServiceError::IncompletePortfolio => 406,
ServiceError::ZipError(_) => 500, ServiceError::ZipError(_) => 500,
ServiceError::CsvError(_) => 500,
ServiceError::CsvIntoInnerError => 500,
} }
} }
} }

View file

@ -1,3 +1,8 @@
pub use sea_orm;
pub use database::mutation::*;
pub use database::query::*;
pub mod database; pub mod database;
pub mod crypto; pub mod crypto;
pub mod filetype; pub mod filetype;
@ -6,8 +11,5 @@ pub mod error;
pub mod candidate_details; pub mod candidate_details;
pub mod util; pub mod util;
pub mod responses; pub mod responses;
pub mod utils;
pub use database::mutation::*;
pub use database::query::*;
pub use sea_orm;