add typ
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
pub mod benutzer;
|
||||
pub mod gruppe;
|
||||
pub mod rolle;
|
||||
pub mod typ;
|
||||
|
||||
5
src/domain/typ.rs
Normal file
5
src/domain/typ.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
pub mod dataloader;
|
||||
pub mod entity;
|
||||
pub mod model;
|
||||
pub mod repository;
|
||||
pub mod service;
|
||||
0
src/domain/typ/dataloader.rs
Normal file
0
src/domain/typ/dataloader.rs
Normal file
2
src/domain/typ/entity.rs
Normal file
2
src/domain/typ/entity.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod typ;
|
||||
pub use typ::Typ;
|
||||
8
src/domain/typ/entity/typ.rs
Normal file
8
src/domain/typ/entity/typ.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
use crate::scalar::{Id, Time};
|
||||
|
||||
pub struct Typ {
|
||||
pub id: Id,
|
||||
pub typname: String,
|
||||
pub erstellt_am: Option<Time>,
|
||||
pub geaendert_am: Option<Time>,
|
||||
}
|
||||
9
src/domain/typ/model.rs
Normal file
9
src/domain/typ/model.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
mod typ;
|
||||
mod typ_erstelle_input;
|
||||
mod typ_loeschen_input;
|
||||
mod typ_update_input;
|
||||
|
||||
pub use typ::Typ;
|
||||
pub use typ_erstelle_input::TypErstelleInput;
|
||||
pub use typ_loeschen_input::TypLoeschenInput;
|
||||
pub use typ_update_input::TypUpdateInput;
|
||||
22
src/domain/typ/model/typ.rs
Normal file
22
src/domain/typ/model/typ.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use async_graphql::{ComplexObject, SimpleObject};
|
||||
|
||||
use crate::scalar::{Id, Time};
|
||||
|
||||
#[derive(sqlx::FromRow, SimpleObject, Clone, Debug)]
|
||||
#[graphql(complex)]
|
||||
pub struct Typ {
|
||||
/// Die UUID einer Typ
|
||||
pub id: Id,
|
||||
|
||||
/// Der Typname
|
||||
pub typname: String,
|
||||
|
||||
/// Wann die Typ erstellt wurde
|
||||
pub erstellt_am: Time,
|
||||
|
||||
/// Wann die Typ geaendert wurde
|
||||
pub geaendert_am: Time,
|
||||
}
|
||||
|
||||
#[ComplexObject]
|
||||
impl Typ {}
|
||||
7
src/domain/typ/model/typ_erstelle_input.rs
Normal file
7
src/domain/typ/model/typ_erstelle_input.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use async_graphql::InputObject;
|
||||
|
||||
#[derive(InputObject)]
|
||||
pub struct TypErstelleInput {
|
||||
/// Der Name eines Gerätetyps
|
||||
pub typname: String,
|
||||
}
|
||||
9
src/domain/typ/model/typ_loeschen_input.rs
Normal file
9
src/domain/typ/model/typ_loeschen_input.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use async_graphql::InputObject;
|
||||
|
||||
use crate::scalar::Id;
|
||||
|
||||
#[derive(InputObject)]
|
||||
pub struct TypLoeschenInput {
|
||||
/// Die ID einer Typ
|
||||
pub id: Id,
|
||||
}
|
||||
11
src/domain/typ/model/typ_update_input.rs
Normal file
11
src/domain/typ/model/typ_update_input.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use crate::scalar::Id;
|
||||
use async_graphql::InputObject;
|
||||
|
||||
#[derive(InputObject)]
|
||||
pub struct TypUpdateInput {
|
||||
/// Die ID einer Typ
|
||||
pub id: Id,
|
||||
|
||||
/// Der Name einer Typ
|
||||
pub typname: String,
|
||||
}
|
||||
19
src/domain/typ/repository.rs
Normal file
19
src/domain/typ/repository.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
mod typ_alle;
|
||||
mod typ_erstellen;
|
||||
mod typ_loeschen;
|
||||
mod typ_update;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Repository {}
|
||||
|
||||
impl Repository {
|
||||
pub fn new() -> Repository {
|
||||
Repository {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Repository {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
16
src/domain/typ/repository/typ_alle.rs
Normal file
16
src/domain/typ/repository/typ_alle.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use super::Repository;
|
||||
use crate::{database::Queryer, domain::typ::model};
|
||||
|
||||
impl Repository {
|
||||
pub async fn typ_alle<'c, C: Queryer<'c>>(&self, db: C) -> Result<Vec<model::Typ>, Error> {
|
||||
const QUERY: &str = r#"
|
||||
SELECT * FROM typen
|
||||
"#;
|
||||
|
||||
let typen = sqlx::query_as::<_, model::Typ>(QUERY).fetch_all(db).await?;
|
||||
|
||||
Ok(typen)
|
||||
}
|
||||
}
|
||||
0
src/domain/typ/repository/typ_dataloader.rs
Normal file
0
src/domain/typ/repository/typ_dataloader.rs
Normal file
25
src/domain/typ/repository/typ_einen_zeigen.rs
Normal file
25
src/domain/typ/repository/typ_einen_zeigen.rs
Normal file
@@ -0,0 +1,25 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use super::Repository;
|
||||
use crate::{database::Queryer, domain::typ::model, scalar::Id};
|
||||
|
||||
impl Repository {
|
||||
pub async fn typ_zeige_einen<'c, C: Queryer<'c>>(
|
||||
&self,
|
||||
db: C,
|
||||
id: Id,
|
||||
) -> Result<model::Typ, Error> {
|
||||
const QUERY: &str = r#"
|
||||
SELECT id, erstellt_am, geaendert_am, typname
|
||||
FROM typen
|
||||
WHERE id = $1
|
||||
"#;
|
||||
|
||||
let row = sqlx::query_as::<_, model::Typ>(QUERY)
|
||||
.bind(id)
|
||||
.fetch_one(db)
|
||||
.await?;
|
||||
|
||||
Ok(row)
|
||||
}
|
||||
}
|
||||
40
src/domain/typ/repository/typ_erstelle_viele.rs
Normal file
40
src/domain/typ/repository/typ_erstelle_viele.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use super::Repository;
|
||||
use crate::database::Queryer;
|
||||
use crate::domain::typ::entity;
|
||||
use crate::domain::typ::model::{self};
|
||||
use crate::scalar::{Id, Time};
|
||||
|
||||
impl Repository {
|
||||
pub async fn typ_viele_erstellen<'c, C: Queryer<'c>>(
|
||||
&self,
|
||||
db: C,
|
||||
typen: &[entity::Typ], // input: &[Typ],
|
||||
) -> Result<Vec<model::Typ>, Error> {
|
||||
let id: Vec<Id> = typen.iter().map(|t| t.id).collect();
|
||||
let typnamen: Vec<String> = typen.iter().map(|t| t.typname.clone()).collect();
|
||||
let erstellt_am: Vec<Option<Time>> = typen.iter().map(|t| t.erstellt_am).collect();
|
||||
let geaendert_am: Vec<Option<Time>> = typen.iter().map(|t| t.geaendert_am).collect();
|
||||
|
||||
const QUERY: &str = r#"
|
||||
INSERT INTO typen (id, typname, erstellt_am, geaendert_am)
|
||||
SELECT * FROM UNNEST(
|
||||
$1::uuid[],
|
||||
$2::text[],
|
||||
$3::TIMESTAMP[],
|
||||
$4::TIMESTAMP[]
|
||||
) RETURNING id, erstellt_am, geaendert_am, typname;
|
||||
"#;
|
||||
|
||||
let rows = sqlx::query_as::<_, model::Typ>(QUERY)
|
||||
.bind(id)
|
||||
.bind(typnamen)
|
||||
.bind(erstellt_am)
|
||||
.bind(geaendert_am)
|
||||
.fetch_all(db)
|
||||
.await?;
|
||||
|
||||
Ok(rows)
|
||||
}
|
||||
}
|
||||
29
src/domain/typ/repository/typ_erstellen.rs
Normal file
29
src/domain/typ/repository/typ_erstellen.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use super::Repository;
|
||||
use crate::database::Queryer;
|
||||
use crate::domain::typ::{entity, model};
|
||||
|
||||
impl Repository {
|
||||
pub async fn typ_erstellen<'c, C: Queryer<'c>>(
|
||||
&self,
|
||||
db: C,
|
||||
typ: &entity::Typ,
|
||||
) -> Result<model::Typ, Error> {
|
||||
const QUERY: &str = r#"
|
||||
INSERT INTO typen (id, erstellt_am, geaendert_am, typname) VALUES (
|
||||
$1, $2, $3, $4
|
||||
) RETURNING id, erstellt_am, geaendert_am, typname;
|
||||
"#;
|
||||
|
||||
let typ = sqlx::query_as::<_, model::Typ>(QUERY)
|
||||
.bind(typ.id)
|
||||
.bind(typ.erstellt_am)
|
||||
.bind(typ.geaendert_am)
|
||||
.bind(&typ.typname)
|
||||
.fetch_one(db)
|
||||
.await?;
|
||||
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
24
src/domain/typ/repository/typ_loeschen.rs
Normal file
24
src/domain/typ/repository/typ_loeschen.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use super::Repository;
|
||||
use crate::database::Queryer;
|
||||
use crate::domain::typ::{entity, model};
|
||||
|
||||
impl Repository {
|
||||
pub async fn typ_loeschen<'c, C: Queryer<'c>>(
|
||||
&self,
|
||||
db: C,
|
||||
typ: &entity::Typ,
|
||||
) -> Result<model::Typ, Error> {
|
||||
const QUERY: &str = r#"
|
||||
DELETE FROM typen WHERE id=$1 RETURNING id, erstellt_am, geaendert_am, typname;
|
||||
"#;
|
||||
|
||||
let typ = sqlx::query_as::<_, model::Typ>(QUERY)
|
||||
.bind(typ.id)
|
||||
.fetch_one(db)
|
||||
.await?;
|
||||
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
28
src/domain/typ/repository/typ_update.rs
Normal file
28
src/domain/typ/repository/typ_update.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use super::Repository;
|
||||
use crate::database::Queryer;
|
||||
use crate::domain::typ::{entity, model};
|
||||
|
||||
impl Repository {
|
||||
pub async fn typ_update<'c, C: Queryer<'c>>(
|
||||
&self,
|
||||
db: C,
|
||||
typ: &entity::Typ,
|
||||
) -> Result<model::Typ, Error> {
|
||||
const QUERY: &str = r#"
|
||||
UPDATE typen
|
||||
SET geaendert_am = $2, typname = $3 WHERE id = $1
|
||||
RETURNING id, erstellt_am, geaendert_am, typname;
|
||||
"#;
|
||||
|
||||
let typ = sqlx::query_as::<_, model::Typ>(QUERY)
|
||||
.bind(typ.id)
|
||||
.bind(typ.geaendert_am)
|
||||
.bind(&typ.typname)
|
||||
.fetch_one(db)
|
||||
.await?;
|
||||
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
21
src/domain/typ/service.rs
Normal file
21
src/domain/typ/service.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
mod typ_alle;
|
||||
// mod typ_dataloader;
|
||||
mod typ_erstellen;
|
||||
mod typ_loeschen;
|
||||
mod typ_update;
|
||||
|
||||
use super::repository::Repository;
|
||||
use crate::database::DB;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Service {
|
||||
repo: Repository,
|
||||
pub db: DB,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn new(db: DB) -> Self {
|
||||
let repo = Repository::new();
|
||||
Self { repo, db }
|
||||
}
|
||||
}
|
||||
12
src/domain/typ/service/typ_alle.rs
Normal file
12
src/domain/typ/service/typ_alle.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use crate::domain::typ::model;
|
||||
|
||||
use super::Service;
|
||||
|
||||
impl Service {
|
||||
pub async fn typ_alle(&self) -> Result<Vec<model::Typ>, Error> {
|
||||
let typ = self.repo.typ_alle(&self.db).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
15
src/domain/typ/service/typ_dataloader.rs
Normal file
15
src/domain/typ/service/typ_dataloader.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use crate::{domain::typ::model::Typ, scalar::Id};
|
||||
|
||||
use super::Service;
|
||||
|
||||
impl Service {
|
||||
pub async fn typ_dataloader(
|
||||
&self,
|
||||
keys: &[Id],
|
||||
) -> Result<HashMap<Id, Vec<Typ>>, Arc<sqlx::Error>> {
|
||||
let typen_dataloader = self.repo.typ_dataloader(&self.db, keys).await?;
|
||||
Ok(typen_dataloader)
|
||||
}
|
||||
}
|
||||
23
src/domain/typ/service/typ_erstellen.rs
Normal file
23
src/domain/typ/service/typ_erstellen.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
use anyhow::Error;
|
||||
use chrono::Utc;
|
||||
use ulid::Ulid;
|
||||
|
||||
use super::Service;
|
||||
use crate::domain::typ::{
|
||||
entity,
|
||||
model::{self, TypErstelleInput},
|
||||
};
|
||||
|
||||
impl Service {
|
||||
pub async fn typ_erstellen(&self, input: TypErstelleInput) -> Result<model::Typ, Error> {
|
||||
let typ_input = entity::Typ {
|
||||
id: Ulid::new().into(),
|
||||
typname: input.typname,
|
||||
erstellt_am: Some(Utc::now()),
|
||||
geaendert_am: Some(Utc::now()),
|
||||
};
|
||||
|
||||
let typ = self.repo.typ_erstellen(&self.db, &typ_input).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
33
src/domain/typ/service/typ_erstellen_viele.rs
Normal file
33
src/domain/typ/service/typ_erstellen_viele.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
use anyhow::Error;
|
||||
use chrono::Utc;
|
||||
use ulid::Ulid;
|
||||
|
||||
use super::Service;
|
||||
use crate::domain::typ::{
|
||||
entity,
|
||||
model::{self, TypErstelleInput},
|
||||
};
|
||||
|
||||
impl Service {
|
||||
pub async fn typ_erstellen_viele(
|
||||
&self,
|
||||
input: &[TypErstelleInput],
|
||||
) -> Result<Vec<model::Typ>, Error> {
|
||||
let typen_input: Vec<entity::Typ> = input
|
||||
.iter()
|
||||
.map(|t| entity::Typ {
|
||||
id: Ulid::new().into(),
|
||||
typname: t.typname.clone(),
|
||||
erstellt_am: Some(Utc::now()),
|
||||
geaendert_am: Some(Utc::now()),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let typen = self
|
||||
.repo
|
||||
.typ_viele_erstellen(&self.db, &typen_input)
|
||||
.await?;
|
||||
|
||||
Ok(typen)
|
||||
}
|
||||
}
|
||||
22
src/domain/typ/service/typ_loeschen.rs
Normal file
22
src/domain/typ/service/typ_loeschen.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use anyhow::Error;
|
||||
use chrono::Utc;
|
||||
|
||||
use super::Service;
|
||||
use crate::domain::typ::{
|
||||
entity,
|
||||
model::{self, TypLoeschenInput},
|
||||
};
|
||||
|
||||
impl Service {
|
||||
pub async fn typ_loeschen(&self, input: TypLoeschenInput) -> Result<model::Typ, Error> {
|
||||
let typ_input = entity::Typ {
|
||||
id: input.id,
|
||||
typname: String::new(),
|
||||
erstellt_am: None,
|
||||
geaendert_am: Some(Utc::now()),
|
||||
};
|
||||
|
||||
let typ = self.repo.typ_loeschen(&self.db, &typ_input).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
22
src/domain/typ/service/typ_update.rs
Normal file
22
src/domain/typ/service/typ_update.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use anyhow::Error;
|
||||
use chrono::Utc;
|
||||
|
||||
use super::Service;
|
||||
use crate::domain::typ::{
|
||||
entity,
|
||||
model::{self, TypUpdateInput},
|
||||
};
|
||||
|
||||
impl Service {
|
||||
pub async fn typ_update(&self, input: TypUpdateInput) -> Result<model::Typ, Error> {
|
||||
let typ_input = entity::Typ {
|
||||
id: input.id,
|
||||
typname: input.typname,
|
||||
erstellt_am: None,
|
||||
geaendert_am: Some(Utc::now()),
|
||||
};
|
||||
|
||||
let typ = self.repo.typ_update(&self.db, &typ_input).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::{
|
||||
models::typ::{Typ, TypCreateInput, TypUpdateInput},
|
||||
scalar::Id,
|
||||
use crate::domain::typ::{
|
||||
model::{Typ, TypErstelleInput, TypLoeschenInput, TypUpdateInput},
|
||||
service::Service,
|
||||
};
|
||||
|
||||
use async_graphql::{Context, FieldResult};
|
||||
use sqlx::postgres::PgPool;
|
||||
|
||||
@@ -10,31 +11,36 @@ pub struct TypMutation;
|
||||
|
||||
#[async_graphql::Object]
|
||||
impl TypMutation {
|
||||
async fn create_typ(&self, ctx: &Context<'_>, input: TypCreateInput) -> FieldResult<Typ> {
|
||||
async fn erstelle_typ(&self, ctx: &Context<'_>, input: TypErstelleInput) -> FieldResult<Typ> {
|
||||
let pool = ctx.data::<PgPool>()?;
|
||||
|
||||
let row = Typ::create(pool, &input).await?;
|
||||
Ok(row)
|
||||
let typ = Service::new(pool.clone()).typ_erstellen(input).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
|
||||
async fn create_many_typen(
|
||||
async fn erstelle_viele_typen(
|
||||
&self,
|
||||
ctx: &Context<'_>,
|
||||
input: Vec<TypCreateInput>,
|
||||
input: Vec<TypErstelleInput>,
|
||||
) -> FieldResult<Vec<Typ>> {
|
||||
let pool = ctx.data::<PgPool>()?;
|
||||
let row = Typ::create_many(pool, &input).await?;
|
||||
Ok(row)
|
||||
|
||||
let gruppe = Service::new(pool.clone())
|
||||
.typ_erstellen_viele(&input)
|
||||
.await?;
|
||||
Ok(gruppe)
|
||||
}
|
||||
|
||||
async fn update_typ(&self, ctx: &Context<'_>, input: TypUpdateInput) -> FieldResult<Typ> {
|
||||
let pool = ctx.data::<PgPool>()?;
|
||||
let row = Typ::update(pool, &input).await?;
|
||||
Ok(row)
|
||||
|
||||
let typ = Service::new(pool.clone()).typ_update(input).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
|
||||
async fn delete_typ(&self, ctx: &Context<'_>, id: Id) -> FieldResult<bool> {
|
||||
async fn loesche_typ(&self, ctx: &Context<'_>, input: TypLoeschenInput) -> FieldResult<Typ> {
|
||||
let pool = ctx.data::<PgPool>()?;
|
||||
Ok(Typ::delete(pool, &id).await?)
|
||||
let typ = Service::new(pool.clone()).typ_loeschen(input).await?;
|
||||
Ok(typ)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use async_graphql::{Context, FieldResult, Object};
|
||||
use sqlx::postgres::PgPool;
|
||||
|
||||
use crate::{models::typ::Typ, scalar::Id};
|
||||
use crate::domain::typ::{model::Typ, service::Service};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct TypQuery {}
|
||||
@@ -10,13 +10,7 @@ pub struct TypQuery {}
|
||||
impl TypQuery {
|
||||
async fn typen(&self, ctx: &Context<'_>) -> FieldResult<Vec<Typ>> {
|
||||
let pool = ctx.data::<PgPool>()?;
|
||||
let rows = Typ::read_all(pool).await?;
|
||||
Ok(rows)
|
||||
}
|
||||
|
||||
async fn typ(&self, ctx: &Context<'_>, id: Id) -> FieldResult<Typ> {
|
||||
let pool = ctx.data::<PgPool>()?;
|
||||
let row = Typ::read_one(pool, &id).await?;
|
||||
Ok(row)
|
||||
let typen = Service::new(pool.clone()).typ_alle().await?;
|
||||
Ok(typen)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user