From 1288d726788c3644216fb4947ff6e96a9ef3dd97 Mon Sep 17 00:00:00 2001 From: Joshua Coles Date: Thu, 22 Feb 2024 13:49:17 +0000 Subject: [PATCH] Prep import of csv files --- Cargo.toml | 3 ++- src/db.rs | 2 +- src/main.rs | 30 +++++++++++++++++++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8b5e5fc..839b4d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] tokio = { version = "1.0", features = ["full"] } -axum = "0.6.20" +axum = { version = "0.6.20", features = ["multipart"] } clap = { version = "4.4.3", features = ["derive", "env"] } serde = { version = "1.0.188", features = ["derive"] } serde_json = "1.0.106" @@ -31,4 +31,5 @@ migration = { path = "./migration" } chrono = { version = "0.4.31", features = ["serde"] } futures = "0.3.29" rucron = "0.1.5" +csv = "1.3.0" #tokio-cron-scheduler = "0.9.4" diff --git a/src/db.rs b/src/db.rs index 6ddaac2..2e0d396 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,5 +1,5 @@ use crate::entity::{client, project, time_entry}; -use crate::types::{Project, ProjectClient, ReportEntry}; +use crate::types::{Project, ProjectClient, ReportEntry, TimeEntry}; use sea_orm::sea_query::OnConflict; use sea_orm::{NotSet, Set}; diff --git a/src/main.rs b/src/main.rs index 6ff1b59..d5b2cea 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ use crate::client::TogglClient; use crate::entity::prelude::TimeEntry; use crate::entity::time_entry; +use crate::entity::time_entry::ActiveModel; use crate::types::{Current, Project, ProjectClient, ReportEntry, TogglQuery}; use anyhow::anyhow; -use axum::extract::Query; +use axum::extract::multipart::Field; +use axum::extract::{Multipart, Query}; use axum::http::StatusCode; use axum::response::IntoResponse; use axum::routing::{get, post}; @@ -193,6 +195,31 @@ fn day_exclusivity_condition(start: NaiveDate, end: NaiveDate) -> Condition { .into_condition() } +fn from_csv_row(row: csv::StringRecord) -> ActiveModel { + unimplemented!("Need to refactor db first") +} + +async fn import_csv( + Extension(db): Extension, + mut multipart: Multipart, +) -> impl IntoResponse { + return (StatusCode::NOT_IMPLEMENTED, "Not implemented"); + + while let Some(field) = multipart.next_field().await? { + if field.name() == "csv" { + let csv = field.bytes().await?; + let mut csv = csv::Reader::from_reader(csv.as_ref()); + let data = csv.records().filter_map(|f| f.ok()).map(from_csv_row); + + time_entry::Entity::insert_many(data.collect::>().unwrap()) + .on_conflict(ReportEntry::grafting_conflict_statement()) + .exec(&db) + .await + .unwrap() + } + } +} + #[tokio::main] async fn main() -> Result<()> { // install global collector configured based on RUST_LOG env var. @@ -218,6 +245,7 @@ async fn main() -> Result<()> { // build our application with a route let app = Router::new() + .route("/import_csv", post(import_csv)) .route("/health", get(health)) .route("/current", get(current)) .route("/refresh", post(refresh))