(toggl-portal): Cache clients in database

This commit is contained in:
Joshua Coles 2023-11-06 14:14:26 +00:00
parent 100ef25044
commit 84cb5f5379
10 changed files with 139 additions and 16 deletions

View File

@ -1,15 +1,17 @@
pub use sea_orm_migration::prelude::*;
mod m20231101_172500_create_time_entry_table;
mod m20231106_134950_create_clients;
pub struct Migrator;
#[async_trait::async_trait]
impl MigratorTrait for Migrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![Box::new(
m20231101_172500_create_time_entry_table::Migration,
)]
vec![
Box::new(m20231101_172500_create_time_entry_table::Migration),
Box::new(m20231106_134950_create_clients::Migration),
]
}
fn migration_table_name() -> DynIden {

View File

@ -0,0 +1,46 @@
use sea_orm_migration::prelude::*;
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Client::Table)
.if_not_exists()
.col(
ColumnDef::new(Client::Id)
.integer()
.not_null()
.primary_key(),
)
.col(ColumnDef::new(Client::Name).string().not_null())
.col(ColumnDef::new(Client::Archived).boolean().not_null())
.col(ColumnDef::new(Client::WorkspaceId).integer().not_null())
.col(ColumnDef::new(Client::At).timestamp_with_time_zone().not_null())
.col(ColumnDef::new(Client::ServerDeletedAt).timestamp_with_time_zone())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Client::Table).to_owned())
.await
}
}
#[derive(DeriveIden)]
enum Client {
Table,
Id,
Name,
Archived,
WorkspaceId,
At,
ServerDeletedAt
}

View File

@ -1,10 +1,10 @@
use sea_orm::{NotSet, Set};
use crate::entity::time_entry::ActiveModel;
use crate::types::ReportEntry;
use crate::entity::{time_entry, client};
use crate::types::{Project, ProjectClient, ReportEntry};
impl ReportEntry {
pub(crate) fn as_models(&self) -> Vec<ActiveModel> {
self.time_entries.iter().map(|inner| ActiveModel {
pub(crate) fn as_models(&self) -> Vec<time_entry::ActiveModel> {
self.time_entries.iter().map(|inner| time_entry::ActiveModel {
id: NotSet,
toggl_id: Set(inner.id as i64),
description: Set(self.description.clone()),
@ -15,3 +15,16 @@ impl ReportEntry {
}).collect()
}
}
impl ProjectClient {
pub fn as_model(&self) -> client::ActiveModel {
client::ActiveModel {
id: Set(self.id),
name: Set(self.name.clone()),
archived: Set(self.archived.clone()),
workspace_id: Set(self.wid),
at: Set(self.at.clone().fixed_offset()),
server_deleted_at: Set(self.server_deleted_at.clone().map(|dt| dt.fixed_offset())),
}
}
}

21
src/entity/client.rs Normal file
View File

@ -0,0 +1,21 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "client")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub id: i32,
pub name: String,
pub archived: bool,
pub workspace_id: i32,
pub at: DateTimeWithTimeZone,
pub server_deleted_at: Option<DateTimeWithTimeZone>,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -2,4 +2,6 @@
pub mod prelude;
pub mod client;
pub mod time_entry;
pub mod toggl_portal_seaql_migrations;

View File

@ -1,3 +1,5 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
pub use super::client::Entity as Client;
pub use super::time_entry::Entity as TimeEntry;
pub use super::toggl_portal_seaql_migrations::Entity as TogglPortalSeaqlMigrations;

View File

@ -8,6 +8,7 @@ use serde::{Deserialize, Serialize};
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub toggl_id: i64,
pub description: String,
pub project_id: Option<i64>,

View File

@ -0,0 +1,17 @@
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.2
use sea_orm::entity::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "toggl_portal_seaql_migrations")]
pub struct Model {
#[sea_orm(primary_key, auto_increment = false)]
pub version: String,
pub applied_at: i64,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@ -86,11 +86,30 @@ pub async fn start_time_entry(
}
async fn projects(Extension(toggl_client): Extension<TogglClient>) -> Result<Json<Vec<Project>>> {
Ok(Json(toggl_client.fetch_projects().await?))
let projects = toggl_client.fetch_projects().await?;
Ok(Json(projects))
}
async fn clients(Extension(toggl_client): Extension<TogglClient>) -> Result<Json<Vec<ProjectClient>>> {
Ok(Json(toggl_client.fetch_clients().await?))
async fn clients(
Extension(db): Extension<DatabaseConnection>,
Extension(toggl_client): Extension<TogglClient>
) -> Result<Json<Vec<ProjectClient>>> {
let clients = toggl_client.fetch_clients().await?;
entity::client::Entity::insert_many(clients.iter().map(ProjectClient::as_model))
.on_conflict(
OnConflict::column(entity::client::Column::Id)
.update_columns(vec![
entity::client::Column::Name,
entity::client::Column::Archived,
entity::client::Column::At,
entity::client::Column::ServerDeletedAt,
entity::client::Column::WorkspaceId,
])
.to_owned(),
)
.exec(&db).await?;
Ok(Json(clients))
}
async fn health(Extension(toggl_client): Extension<TogglClient>) -> Result<&'static str> {

View File

@ -61,22 +61,22 @@ pub struct Project {
#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectClient {
/// Indicates whether the client is archived or not.
archived: bool,
pub archived: bool,
/// Represents the timestamp of the last update made to the client.
at: DateTime<Utc>,
pub at: DateTime<Utc>,
/// The unique identifier for the client.
id: i32,
pub id: i32,
/// The name of the client.
name: String,
pub name: String,
/// Indicates the timestamp when the client was deleted. If the client is not deleted, this property will be null.
server_deleted_at: Option<DateTime<Utc>>,
pub server_deleted_at: Option<DateTime<Utc>>,
/// The Workspace ID associated with the client.
wid: i32,
pub wid: i32,
}
#[allow(non_snake_case)]