add liegenschaft

This commit is contained in:
2026-06-01 22:14:34 +02:00
parent c7b734a93b
commit 3a60d8eb6a
30 changed files with 516 additions and 4 deletions

View File

@@ -1,4 +1,5 @@
pub mod benutzer;
pub mod gruppe;
pub mod liegenschaft;
pub mod rolle;
pub mod typ;

View File

@@ -0,0 +1,6 @@
pub mod dataloader;
pub mod entity;
pub mod model;
pub mod queries;
pub mod repository;
pub mod service;

View File

View File

@@ -0,0 +1,2 @@
pub mod liegenschaft;
pub use liegenschaft::Liegenschaft;

View File

@@ -0,0 +1,9 @@
use crate::scalar::{Id, Time};
pub struct Liegenschaft {
pub id_liegenschaft: Id,
pub id: String,
pub liegenschaftname: String,
pub erstellt_am: Option<Time>,
pub geaendert_am: Option<Time>,
}

View File

@@ -0,0 +1,9 @@
mod liegenschaft;
mod liegenschaft_erstelle_input;
mod liegenschaft_loeschen_input;
mod liegenschaft_update_input;
pub use liegenschaft::Liegenschaft;
pub use liegenschaft_erstelle_input::LiegenschaftErstelleInput;
pub use liegenschaft_loeschen_input::LiegenschaftLoeschenInput;
pub use liegenschaft_update_input::LiegenschaftUpdateInput;

View File

@@ -0,0 +1,22 @@
use async_graphql::{ComplexObject, SimpleObject};
use crate::scalar::Time;
#[derive(sqlx::FromRow, SimpleObject, Clone, Debug)]
#[graphql(complex)]
pub struct Liegenschaft {
/// Die ULID einer Liegenschaft
pub id: String,
/// Der Liegenschaftname
pub liegenschaftname: String,
/// Wann die Liegenschaft erstellt wurde
pub erstellt_am: Time,
/// Wann die Liegenschaft geaendert wurde
pub geaendert_am: Time,
}
#[ComplexObject]
impl Liegenschaft {}

View File

@@ -0,0 +1,7 @@
use async_graphql::InputObject;
#[derive(InputObject)]
pub struct LiegenschaftErstelleInput {
/// Der Name eines Geräteliegenschafts
pub liegenschaftname: String,
}

View File

@@ -0,0 +1,7 @@
use async_graphql::InputObject;
#[derive(InputObject)]
pub struct LiegenschaftLoeschenInput {
/// Die ULID einer Liegenschaft
pub id: String,
}

View File

@@ -0,0 +1,10 @@
use async_graphql::InputObject;
#[derive(InputObject)]
pub struct LiegenschaftUpdateInput {
/// Die ULID einer Liegenschaft
pub id: String,
/// Der Name einer Liegenschaft
pub liegenschaftname: String,
}

View File

@@ -0,0 +1 @@
pub mod liegenschaft;

View File

@@ -0,0 +1,16 @@
use async_graphql::{Context, FieldResult, Object};
use sqlx::postgres::PgPool;
use crate::domain::liegenschaft::{model::Liegenschaft, service::Service};
#[derive(Default)]
pub struct LiegenschaftQuery {}
#[Object(extends)]
impl LiegenschaftQuery {
async fn liegenschaften(&self, ctx: &Context<'_>) -> FieldResult<Vec<Liegenschaft>> {
let pool = ctx.data::<PgPool>()?;
let liegenschaften = Service::new(pool.clone()).liegenschaft_alle().await?;
Ok(liegenschaften)
}
}

View File

@@ -0,0 +1,22 @@
mod liegenschaft_alle;
mod liegenschaft_dataloader;
mod liegenschaft_einen_zeigen;
mod liegenschaft_erstelle_viele;
mod liegenschaft_erstellen;
mod liegenschaft_loeschen;
mod liegenschaft_update;
#[derive(Debug, Clone)]
pub struct Repository {}
impl Repository {
pub fn new() -> Repository {
Repository {}
}
}
impl Default for Repository {
fn default() -> Self {
Self::new()
}
}

View File

@@ -0,0 +1,21 @@
use anyhow::Error;
use super::Repository;
use crate::{database::Queryer, domain::liegenschaft::model};
impl Repository {
pub async fn liegenschaft_alle<'c, C: Queryer<'c>>(
&self,
db: C,
) -> Result<Vec<model::Liegenschaft>, Error> {
const QUERY: &str = r#"
SELECT id, erstellt_am, geaendert_am, liegenschaftname FROM liegenschaften
"#;
let liegenschaften = sqlx::query_as::<_, model::Liegenschaft>(QUERY)
.fetch_all(db)
.await?;
Ok(liegenschaften)
}
}

View File

@@ -0,0 +1,25 @@
use anyhow::Error;
use super::Repository;
use crate::{database::Queryer, domain::liegenschaft::model, scalar::Id};
impl Repository {
pub async fn liegenschaft_zeige_einen<'c, C: Queryer<'c>>(
&self,
db: C,
id: Id,
) -> Result<model::Liegenschaft, Error> {
const QUERY: &str = r#"
SELECT id, erstellt_am, geaendert_am, liegenschaftname
FROM liegenschaften
WHERE id = $1
"#;
let row = sqlx::query_as::<_, model::Liegenschaft>(QUERY)
.bind(id)
.fetch_one(db)
.await?;
Ok(row)
}
}

View File

@@ -0,0 +1,51 @@
use anyhow::Error;
use super::Repository;
use crate::database::Queryer;
use crate::domain::liegenschaft::entity;
use crate::domain::liegenschaft::model::{self};
use crate::scalar::{Id, Time};
impl Repository {
pub async fn liegenschaft_viele_erstellen<'c, C: Queryer<'c>>(
&self,
db: C,
liegenschaften: &[entity::Liegenschaft], // input: &[Liegenschaft],
) -> Result<Vec<model::Liegenschaft>, Error> {
let id_liegenschaft: Vec<Id> = liegenschaften.iter().map(|t| t.id_liegenschaft).collect();
let id: Vec<String> = liegenschaften.iter().map(|t| t.id.clone()).collect();
let liegenschaftnamen: Vec<String> = liegenschaften
.iter()
.map(|t| t.liegenschaftname.clone())
.collect();
let erstellt_am: Vec<Option<Time>> = liegenschaften.iter().map(|t| t.erstellt_am).collect();
let geaendert_am: Vec<Option<Time>> =
liegenschaften.iter().map(|t| t.geaendert_am).collect();
const QUERY: &str = r#"
INSERT INTO liegenschaften (id_liegenschaft, id, liegenschaftname, erstellt_am, geaendert_am)
SELECT * FROM UNNEST(
$1::uuid[],
$2::text[],
$3::text[],
$4::TIMESTAMP[],
$5::TIMESTAMP[]
) RETURNING id, erstellt_am, geaendert_am, liegenschaftname;
"#;
let rows = sqlx::query_as::<_, model::Liegenschaft>(QUERY)
.bind(id_liegenschaft)
.bind(id)
.bind(liegenschaftnamen)
.bind(erstellt_am)
.bind(geaendert_am)
.fetch_all(db)
.await?;
Ok(rows)
}
}

View File

@@ -0,0 +1,30 @@
use anyhow::Error;
use super::Repository;
use crate::database::Queryer;
use crate::domain::liegenschaft::{entity, model};
impl Repository {
pub async fn liegenschaft_erstellen<'c, C: Queryer<'c>>(
&self,
db: C,
liegenschaft: &entity::Liegenschaft,
) -> Result<model::Liegenschaft, Error> {
const QUERY: &str = r#"
INSERT INTO liegenschaften (id_liegenschaft, id, erstellt_am, geaendert_am, liegenschaftname) VALUES (
$1, $2, $3, $4, $5
) RETURNING id, erstellt_am, geaendert_am, liegenschaftname;
"#;
let liegenschaft = sqlx::query_as::<_, model::Liegenschaft>(QUERY)
.bind(liegenschaft.id_liegenschaft)
.bind(liegenschaft.id.to_string())
.bind(liegenschaft.erstellt_am)
.bind(liegenschaft.geaendert_am)
.bind(&liegenschaft.liegenschaftname)
.fetch_one(db)
.await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,24 @@
use anyhow::Error;
use super::Repository;
use crate::database::Queryer;
use crate::domain::liegenschaft::{entity, model};
impl Repository {
pub async fn liegenschaft_loeschen<'c, C: Queryer<'c>>(
&self,
db: C,
liegenschaft: &entity::Liegenschaft,
) -> Result<model::Liegenschaft, Error> {
const QUERY: &str = r#"
DELETE FROM liegenschaften WHERE id=$1 RETURNING id, erstellt_am, geaendert_am, liegenschaftname;
"#;
let liegenschaft = sqlx::query_as::<_, model::Liegenschaft>(QUERY)
.bind(liegenschaft.id.to_string())
.fetch_one(db)
.await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,28 @@
use anyhow::Error;
use super::Repository;
use crate::database::Queryer;
use crate::domain::liegenschaft::{entity, model};
impl Repository {
pub async fn liegenschaft_update<'c, C: Queryer<'c>>(
&self,
db: C,
liegenschaft: &entity::Liegenschaft,
) -> Result<model::Liegenschaft, Error> {
const QUERY: &str = r#"
UPDATE liegenschaften
SET geaendert_am = $2, liegenschaftname = $3 WHERE id = $1
RETURNING id, erstellt_am, geaendert_am, liegenschaftname;
"#;
let liegenschaft = sqlx::query_as::<_, model::Liegenschaft>(QUERY)
.bind(liegenschaft.id.to_string())
.bind(liegenschaft.geaendert_am)
.bind(&liegenschaft.liegenschaftname)
.fetch_one(db)
.await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,22 @@
mod liegenschaft_alle;
// mod liegenschaft_dataloader;
mod liegenschaft_erstellen;
mod liegenschaft_erstellen_viele;
mod liegenschaft_loeschen;
mod liegenschaft_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 }
}
}

View File

@@ -0,0 +1,12 @@
use anyhow::Error;
use crate::domain::liegenschaft::model;
use super::Service;
impl Service {
pub async fn liegenschaft_alle(&self) -> Result<Vec<model::Liegenschaft>, Error> {
let liegenschaft = self.repo.liegenschaft_alle(&self.db).await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,15 @@
use std::{collections::HashMap, sync::Arc};
use crate::{domain::liegenschaft::model::Liegenschaft, scalar::Id};
use super::Service;
impl Service {
pub async fn liegenschaft_dataloader(
&self,
keys: &[Id],
) -> Result<HashMap<Id, Vec<Liegenschaft>>, Arc<sqlx::Error>> {
let liegenschaften_dataloader = self.repo.liegenschaft_dataloader(&self.db, keys).await?;
Ok(liegenschaften_dataloader)
}
}

View File

@@ -0,0 +1,30 @@
use anyhow::Error;
use chrono::Utc;
use ulid::Ulid;
use super::Service;
use crate::domain::liegenschaft::{
entity,
model::{self, LiegenschaftErstelleInput},
};
impl Service {
pub async fn liegenschaft_erstellen(
&self,
input: LiegenschaftErstelleInput,
) -> Result<model::Liegenschaft, Error> {
let liegenschaft_input = entity::Liegenschaft {
id_liegenschaft: Ulid::new().into(),
id: Ulid::new().to_string(),
liegenschaftname: input.liegenschaftname,
erstellt_am: Some(Utc::now()),
geaendert_am: Some(Utc::now()),
};
let liegenschaft = self
.repo
.liegenschaft_erstellen(&self.db, &liegenschaft_input)
.await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,34 @@
use anyhow::Error;
use chrono::Utc;
use ulid::Ulid;
use super::Service;
use crate::domain::liegenschaft::{
entity,
model::{self, LiegenschaftErstelleInput},
};
impl Service {
pub async fn liegenschaft_erstellen_viele(
&self,
input: &[LiegenschaftErstelleInput],
) -> Result<Vec<model::Liegenschaft>, Error> {
let liegenschaften_input: Vec<entity::Liegenschaft> = input
.iter()
.map(|t| entity::Liegenschaft {
id_liegenschaft: Ulid::new().into(),
id: Ulid::new().to_string(),
liegenschaftname: t.liegenschaftname.clone(),
erstellt_am: Some(Utc::now()),
geaendert_am: Some(Utc::now()),
})
.collect();
let liegenschaften = self
.repo
.liegenschaft_viele_erstellen(&self.db, &liegenschaften_input)
.await?;
Ok(liegenschaften)
}
}

View File

@@ -0,0 +1,30 @@
use anyhow::Error;
use chrono::Utc;
use ulid::Ulid;
use super::Service;
use crate::domain::liegenschaft::{
entity,
model::{self, LiegenschaftLoeschenInput},
};
impl Service {
pub async fn liegenschaft_loeschen(
&self,
input: LiegenschaftLoeschenInput,
) -> Result<model::Liegenschaft, Error> {
let liegenschaft_input = entity::Liegenschaft {
id_liegenschaft: Ulid::new().into(),
id: input.id,
liegenschaftname: String::new(),
erstellt_am: None,
geaendert_am: Some(Utc::now()),
};
let liegenschaft = self
.repo
.liegenschaft_loeschen(&self.db, &liegenschaft_input)
.await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,30 @@
use anyhow::Error;
use chrono::Utc;
use ulid::Ulid;
use super::Service;
use crate::domain::liegenschaft::{
entity,
model::{self, LiegenschaftUpdateInput},
};
impl Service {
pub async fn liegenschaft_update(
&self,
input: LiegenschaftUpdateInput,
) -> Result<model::Liegenschaft, Error> {
let liegenschaft_input = entity::Liegenschaft {
id_liegenschaft: Ulid::new().into(),
id: input.id,
liegenschaftname: input.liegenschaftname,
erstellt_am: None,
geaendert_am: Some(Utc::now()),
};
let liegenschaft = self
.repo
.liegenschaft_update(&self.db, &liegenschaft_input)
.await?;
Ok(liegenschaft)
}
}

View File

@@ -0,0 +1,46 @@
use crate::domain::liegenschaft::{
model::{Liegenschaft, LiegenschaftErstelleInput, LiegenschaftLoeschenInput, LiegenschaftUpdateInput},
service::Service,
};
use async_graphql::{Context, FieldResult};
use sqlx::postgres::PgPool;
#[derive(Default)]
pub struct LiegenschaftMutation;
#[async_graphql::Object]
impl LiegenschaftMutation {
async fn erstelle_liegenschaft(&self, ctx: &Context<'_>, input: LiegenschaftErstelleInput) -> FieldResult<Liegenschaft> {
let pool = ctx.data::<PgPool>()?;
let liegenschaft = Service::new(pool.clone()).liegenschaft_erstellen(input).await?;
Ok(liegenschaft)
}
async fn erstelle_viele_liegenschaften(
&self,
ctx: &Context<'_>,
input: Vec<LiegenschaftErstelleInput>,
) -> FieldResult<Vec<Liegenschaft>> {
let pool = ctx.data::<PgPool>()?;
let gruppe = Service::new(pool.clone())
.liegenschaft_erstellen_viele(&input)
.await?;
Ok(gruppe)
}
async fn update_liegenschaft(&self, ctx: &Context<'_>, input: LiegenschaftUpdateInput) -> FieldResult<Liegenschaft> {
let pool = ctx.data::<PgPool>()?;
let liegenschaft = Service::new(pool.clone()).liegenschaft_update(input).await?;
Ok(liegenschaft)
}
async fn loesche_liegenschaft(&self, ctx: &Context<'_>, input: LiegenschaftLoeschenInput) -> FieldResult<Liegenschaft> {
let pool = ctx.data::<PgPool>()?;
let liegenschaft = Service::new(pool.clone()).liegenschaft_loeschen(input).await?;
Ok(liegenschaft)
}
}

View File

@@ -2,6 +2,7 @@ pub mod benutzer;
pub mod gruppe;
// pub mod hersteller;
// pub mod modell;
pub mod liegenschaft;
pub mod rolle;
pub mod typ;
@@ -15,4 +16,5 @@ pub struct Mutation(
benutzer::BenutzerMutation,
gruppe::GruppeMutation,
rolle::RolleMutation,
liegenschaft::LiegenschaftMutation,
);

View File

@@ -1,8 +1,8 @@
// pub mod hersteller;
// pub mod modell;
use crate::domain::{
benutzer::queries::benutzer, gruppe::queries::gruppe, rolle::queries::rolle,
typ::queries::typ::TypQuery,
benutzer::queries::benutzer, gruppe::queries::gruppe, liegenschaft::queries::liegenschaft,
rolle::queries::rolle, typ::queries::typ::TypQuery,
};
use async_graphql::MergedObject;
@@ -13,6 +13,6 @@ pub struct Query(
benutzer::BenutzerQuery,
rolle::RolleQuery,
gruppe::GruppeQuery,
// modell::ModellQuery,
// hersteller::HerstellerQuery,
liegenschaft::LiegenschaftQuery, // modell::ModellQuery,
// hersteller::HerstellerQuery,
);