From baac7307a7c7f9ff7fa21f64e51b317f222773b0 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sun, 15 Dec 2024 15:19:55 +0900 Subject: [PATCH 01/33] =?UTF-8?q?refactor:=20Form=20=E3=83=89=E3=83=A1?= =?UTF-8?q?=E3=82=A4=E3=83=B3=E3=81=8B=E3=82=89=20OffsetAndLimit=20=20stru?= =?UTF-8?q?ct=20=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/domain/src/form/models.rs | 8 -------- server/domain/src/repository/form_repository.rs | 10 +++++++--- server/infra/resource/src/database/components.rs | 10 ++++++---- server/infra/resource/src/database/form.rs | 10 ++++++---- .../src/repository/form_repository_impl.rs | 15 ++++++++++----- server/presentation/src/form_handler.rs | 15 ++++++++++----- .../src/schemas/form/form_request_schemas.rs | 6 ++++++ server/usecase/src/form.rs | 14 ++++++++------ 8 files changed, 53 insertions(+), 35 deletions(-) diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index 211edd31..8d5473a0 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -17,14 +17,6 @@ use crate::{ pub type FormId = types::IntegerId
; -#[derive(Deserialize, Debug)] -pub struct OffsetAndLimit { - #[serde(default)] - pub offset: Option, - #[serde(default)] - pub limit: Option, -} - #[derive(Serialize, Debug)] pub struct SimpleForm { pub id: FormId, diff --git a/server/domain/src/repository/form_repository.rs b/server/domain/src/repository/form_repository.rs index abd2920a..b19ae288 100644 --- a/server/domain/src/repository/form_repository.rs +++ b/server/domain/src/repository/form_repository.rs @@ -6,7 +6,7 @@ use crate::{ form::models::{ AnswerId, AnswerLabel, Comment, CommentId, DefaultAnswerTitle, Form, FormAnswer, FormAnswerContent, FormDescription, FormId, FormTitle, Label, LabelId, Message, MessageId, - OffsetAndLimit, Question, ResponsePeriod, SimpleForm, Visibility, WebhookUrl, + Question, ResponsePeriod, SimpleForm, Visibility, WebhookUrl, }, types::authorization_guard::{AuthorizationGuard, Create, Delete, Read, Update}, user::models::User, @@ -21,9 +21,13 @@ pub trait FormRepository: Send + Sync + 'static { description: FormDescription, user: User, ) -> Result; - async fn public_list(&self, offset_and_limit: OffsetAndLimit) + async fn public_list( + &self, + offset: Option, + limit: Option, + ) -> Result, Error>; + async fn list(&self, offset: Option, limit: Option) -> Result, Error>; - async fn list(&self, offset_and_limit: OffsetAndLimit) -> Result, Error>; async fn get(&self, id: FormId) -> Result, Error>; async fn delete(&self, id: FormId) -> Result<(), Error>; async fn update_title(&self, form_id: &FormId, title: &FormTitle) -> Result<(), Error>; diff --git a/server/infra/resource/src/database/components.rs b/server/infra/resource/src/database/components.rs index d3cb119f..0dab644b 100644 --- a/server/infra/resource/src/database/components.rs +++ b/server/infra/resource/src/database/components.rs @@ -2,8 +2,8 @@ use async_trait::async_trait; use domain::{ form::models::{ AnswerId, Comment, CommentId, DefaultAnswerTitle, Form, FormAnswer, FormAnswerContent, - FormDescription, FormId, FormTitle, Label, LabelId, Message, MessageId, OffsetAndLimit, - Question, ResponsePeriod, Visibility, WebhookUrl, + FormDescription, FormId, FormTitle, Label, LabelId, Message, MessageId, Question, + ResponsePeriod, Visibility, WebhookUrl, }, notification::models::{Notification, NotificationId}, user::models::{Role, User}, @@ -43,11 +43,13 @@ pub trait FormDatabase: Send + Sync { ) -> Result; async fn public_list( &self, - offset_and_limit: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, InfraError>; async fn list( &self, - offset_and_limit: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, InfraError>; async fn get(&self, form_id: FormId) -> Result, InfraError>; async fn delete(&self, form_id: FormId) -> Result<(), InfraError>; diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index 0c4b1d8c..0b6f41c5 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -5,8 +5,8 @@ use chrono::{DateTime, Utc}; use domain::{ form::models::{ AnswerId, Comment, CommentId, DefaultAnswerTitle, FormAnswer, FormAnswerContent, - FormDescription, FormId, FormTitle, Label, LabelId, Message, MessageId, OffsetAndLimit, - Question, ResponsePeriod, Visibility, WebhookUrl, + FormDescription, FormId, FormTitle, Label, LabelId, Message, MessageId, Question, + ResponsePeriod, Visibility, WebhookUrl, }, user::models::{Role, User}, }; @@ -83,7 +83,8 @@ impl FormDatabase for ConnectionPool { async fn public_list( &self, - OffsetAndLimit { offset, limit }: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, InfraError> { self.read_only_transaction(|txn| { Box::pin(async move { @@ -153,7 +154,8 @@ impl FormDatabase for ConnectionPool { #[tracing::instrument] async fn list( &self, - OffsetAndLimit { offset, limit }: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, InfraError> { self.read_only_transaction(|txn| { Box::pin(async move { diff --git a/server/infra/resource/src/repository/form_repository_impl.rs b/server/infra/resource/src/repository/form_repository_impl.rs index 06f26b45..beb746e4 100644 --- a/server/infra/resource/src/repository/form_repository_impl.rs +++ b/server/infra/resource/src/repository/form_repository_impl.rs @@ -3,7 +3,7 @@ use domain::{ form::models::{ AnswerId, AnswerLabel, Comment, CommentId, DefaultAnswerTitle, Form, FormAnswer, FormAnswerContent, FormDescription, FormId, FormTitle, Label, LabelId, Message, MessageId, - OffsetAndLimit, Question, ResponsePeriod, SimpleForm, Visibility, WebhookUrl, + Question, ResponsePeriod, SimpleForm, Visibility, WebhookUrl, }, repository::form_repository::FormRepository, types::authorization_guard::{AuthorizationGuard, Create, Delete, Read, Update}, @@ -41,9 +41,10 @@ impl FormRepository for Repository async fn public_list( &self, - offset_and_limit: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, Error> { - let forms = self.client.form().public_list(offset_and_limit).await?; + let forms = self.client.form().public_list(offset, limit).await?; forms .into_iter() .map(|form| form.try_into()) @@ -52,8 +53,12 @@ impl FormRepository for Repository } #[tracing::instrument(skip(self))] - async fn list(&self, offset_and_limit: OffsetAndLimit) -> Result, Error> { - let forms = self.client.form().list(offset_and_limit).await?; + async fn list( + &self, + offset: Option, + limit: Option, + ) -> Result, Error> { + let forms = self.client.form().list(offset, limit).await?; forms .into_iter() .map(|form| form.try_into()) diff --git a/server/presentation/src/form_handler.rs b/server/presentation/src/form_handler.rs index 82d07ea6..c3fcffd9 100644 --- a/server/presentation/src/form_handler.rs +++ b/server/presentation/src/form_handler.rs @@ -6,8 +6,7 @@ use axum::{ }; use domain::{ form::models::{ - AnswerId, Comment, CommentId, FormId, Label, LabelId, MessageId, OffsetAndLimit, - Visibility::PRIVATE, + AnswerId, Comment, CommentId, FormId, Label, LabelId, MessageId, Visibility::PRIVATE, }, repository::Repositories, user::models::{Role::StandardUser, User}, @@ -24,7 +23,7 @@ use crate::{ form_request_schemas::{ AnswerUpdateSchema, AnswersPostSchema, CommentPostSchema, FormCreateSchema, FormQuestionUpdateSchema, FormUpdateSchema, LabelSchema, MessageUpdateSchema, - PostedMessageSchema, ReplaceAnswerLabelSchema, + OffsetAndLimit, PostedMessageSchema, ReplaceAnswerLabelSchema, }, form_response_schemas::{FormAnswer, MessageContentSchema, SenderSchema}, }, @@ -66,7 +65,10 @@ pub async fn public_form_list_handler( notification_repository: repository.notification_repository(), }; - match form_use_case.public_form_list(offset_and_limit).await { + match form_use_case + .public_form_list(offset_and_limit.offset, offset_and_limit.limit) + .await + { Ok(forms) => (StatusCode::OK, Json(forms)).into_response(), Err(err) => handle_error(err).into_response(), } @@ -81,7 +83,10 @@ pub async fn form_list_handler( notification_repository: repository.notification_repository(), }; - match form_use_case.form_list(offset_and_limit).await { + match form_use_case + .form_list(offset_and_limit.offset, offset_and_limit.limit) + .await + { Ok(forms) => (StatusCode::OK, Json(forms)).into_response(), Err(err) => handle_error(err).into_response(), } diff --git a/server/presentation/src/schemas/form/form_request_schemas.rs b/server/presentation/src/schemas/form/form_request_schemas.rs index 9a5a9466..5de80caf 100644 --- a/server/presentation/src/schemas/form/form_request_schemas.rs +++ b/server/presentation/src/schemas/form/form_request_schemas.rs @@ -4,6 +4,12 @@ use domain::form::models::{ }; use serde::Deserialize; +#[derive(Deserialize, Debug)] +pub struct OffsetAndLimit { + pub offset: Option, + pub limit: Option, +} + #[derive(Deserialize, Debug)] pub struct FormCreateSchema { pub title: FormTitle, diff --git a/server/usecase/src/form.rs b/server/usecase/src/form.rs index 2ecaac6d..b76cb644 100644 --- a/server/usecase/src/form.rs +++ b/server/usecase/src/form.rs @@ -2,8 +2,8 @@ use chrono::Utc; use domain::{ form::models::{ AnswerId, Comment, CommentId, DefaultAnswerTitle, Form, FormAnswerContent, FormDescription, - FormId, FormTitle, Label, LabelId, Message, MessageId, OffsetAndLimit, Question, - ResponsePeriod, SimpleForm, Visibility, Visibility::PUBLIC, WebhookUrl, + FormId, FormTitle, Label, LabelId, Message, MessageId, Question, ResponsePeriod, + SimpleForm, Visibility, Visibility::PUBLIC, WebhookUrl, }, notification::models::{Notification, NotificationSource}, repository::{ @@ -46,16 +46,18 @@ impl FormUseCase<'_, R1, R2> { pub async fn public_form_list( &self, - offset_and_limit: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, Error> { - self.form_repository.public_list(offset_and_limit).await + self.form_repository.public_list(offset, limit).await } pub async fn form_list( &self, - offset_and_limit: OffsetAndLimit, + offset: Option, + limit: Option, ) -> Result, Error> { - self.form_repository.list(offset_and_limit).await + self.form_repository.list(offset, limit).await } pub async fn get_form(&self, form_id: FormId) -> Result { From 7155677e07dc820bfee1e2d148adc68dbdb6c2d7 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sun, 15 Dec 2024 15:24:43 +0900 Subject: [PATCH 02/33] =?UTF-8?q?refactor:=20Question=20struct=20=E3=81=AB?= =?UTF-8?q?=20form=5Fid=20=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB=E3=83=89?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/domain/src/form/models.rs | 1 + server/infra/resource/src/database/form.rs | 6 ++++-- server/infra/resource/src/dto.rs | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index 8d5473a0..4af7059b 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -73,6 +73,7 @@ pub type QuestionId = types::IntegerId; pub struct Question { #[serde(default)] pub id: Option, + pub form_id: FormId, pub title: String, pub description: Option, pub question_type: QuestionType, diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index 0b6f41c5..6516b0ef 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -243,7 +243,7 @@ impl FormDatabase for ConnectionPool { }; let questions = query_all_and_values( - r"SELECT question_id, title, description, question_type, is_required FROM form_questions WHERE form_id = ?", + r"SELECT question_id, form_id, title, description, question_type, is_required FROM form_questions WHERE form_id = ?", [form_id.into_inner().into()], txn, ) @@ -283,6 +283,7 @@ impl FormDatabase for ConnectionPool { Ok(QuestionDto { id: Some(question_id), + form_id: rs.try_get("", "form_id")?, title: rs.try_get("", "title")?, description: rs.try_get("", "description")?, question_type: rs.try_get("", "question_type")?, @@ -920,7 +921,7 @@ impl FormDatabase for ConnectionPool { self.read_only_transaction(|txn| { Box::pin(async move { let questions_rs = query_all_and_values( - r"SELECT question_id, title, description, question_type, is_required FROM form_questions WHERE form_id = ?", + r"SELECT question_id, form_id, title, description, question_type, is_required FROM form_questions WHERE form_id = ?", [form_id.into_inner().into()], txn, ).await?; @@ -955,6 +956,7 @@ impl FormDatabase for ConnectionPool { Ok::<_, InfraError>(QuestionDto { id: Some(question_id), + form_id: question_rs.try_get("", "form_id")?, title: question_rs.try_get("", "title")?, description: question_rs.try_get("", "description")?, question_type: question_rs.try_get("", "question_type")?, diff --git a/server/infra/resource/src/dto.rs b/server/infra/resource/src/dto.rs index 0f518a5c..887a6c10 100644 --- a/server/infra/resource/src/dto.rs +++ b/server/infra/resource/src/dto.rs @@ -9,6 +9,7 @@ use uuid::Uuid; #[derive(Clone)] pub struct QuestionDto { pub id: Option, + pub form_id: i32, pub title: String, pub description: Option, pub question_type: String, @@ -22,6 +23,7 @@ impl TryFrom for domain::form::models::Question { fn try_from( QuestionDto { id, + form_id, title, description, question_type, @@ -31,6 +33,7 @@ impl TryFrom for domain::form::models::Question { ) -> Result { Ok(domain::form::models::Question::builder() .id(id.map(Into::into)) + .form_id(form_id.into()) .title(title) .description(description) .question_type(question_type.try_into()?) From 275214d03d5fd0c5354fab95794727126de66ea5 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sun, 15 Dec 2024 15:36:13 +0900 Subject: [PATCH 03/33] =?UTF-8?q?refactor:=20Form=20struct=20=E3=81=8B?= =?UTF-8?q?=E3=82=89=20questions=20field=20=E3=82=92=E5=89=A5=E3=81=8C?= =?UTF-8?q?=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/domain/src/form/models.rs | 3 -- server/infra/outgoing/src/form_outgoing.rs | 5 ++- server/infra/resource/src/database/form.rs | 43 ------------------- server/infra/resource/src/dto.rs | 8 ---- .../src/repository/form_repository_impl.rs | 4 +- server/presentation/src/form_handler.rs | 1 + 6 files changed, 7 insertions(+), 57 deletions(-) diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index 4af7059b..095b3440 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -45,9 +45,6 @@ pub struct Form { pub title: FormTitle, #[builder(setter(into))] pub description: FormDescription, - #[cfg_attr(test, proptest(strategy = "arbitrary_with_size(1..100)"))] - #[serde(default)] - pub questions: Vec, #[serde(default)] #[builder(setter(into))] pub metadata: FormMeta, diff --git a/server/infra/outgoing/src/form_outgoing.rs b/server/infra/outgoing/src/form_outgoing.rs index 61637445..46b61418 100644 --- a/server/infra/outgoing/src/form_outgoing.rs +++ b/server/infra/outgoing/src/form_outgoing.rs @@ -1,5 +1,5 @@ use domain::{ - form::models::{Comment, DefaultAnswerTitle, Form, FormAnswer, FormAnswerContent}, + form::models::{Comment, DefaultAnswerTitle, Form, FormAnswer, FormAnswerContent, Question}, user::models::User, }; use errors::infra::InfraError; @@ -37,6 +37,7 @@ pub async fn post_answer( user: &User, title: DefaultAnswerTitle, answers: &Vec, + questions: &[Question], ) -> Result<(), InfraError> { if let Some(url) = form.settings.webhook_url.to_owned() { Webhook::new(url, "回答が送信されました".to_string()) @@ -55,7 +56,7 @@ pub async fn post_answer( .iter() .map(|answer| { ( - form.questions + questions .iter() .find(|question| question.id == Some(answer.question_id)) .map(|question| question.title.to_owned()) diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index 6516b0ef..16e43cf0 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -242,16 +242,6 @@ impl FormDatabase for ConnectionPool { None => return Ok(None), }; - let questions = query_all_and_values( - r"SELECT question_id, form_id, title, description, question_type, is_required FROM form_questions WHERE form_id = ?", - [form_id.into_inner().into()], - txn, - ) - .await?; - - let choices = query_all(r"SELECT question_id, choice FROM form_choices", txn) - .await?; - let labels = query_all_and_values( r"SELECT label_id, name FROM label_settings_for_forms INNER JOIN label_for_forms ON label_for_forms.id = label_id @@ -261,38 +251,6 @@ impl FormDatabase for ConnectionPool { ) .await?; - let questions = questions - .into_iter() - .map(|rs| { - let question_id: i32 = rs.try_get("", "question_id")?; - - let choices = choices - .iter() - .filter_map(|rs| { - let choice_question_id: i32 = rs.try_get("", "question_id").ok()?; - - if choice_question_id == question_id { - let choice: Result = rs.try_get("", "choice"); - - choice.ok() - } else { - None - } - }) - .collect_vec(); - - Ok(QuestionDto { - id: Some(question_id), - form_id: rs.try_get("", "form_id")?, - title: rs.try_get("", "title")?, - description: rs.try_get("", "description")?, - question_type: rs.try_get("", "question_type")?, - choices, - is_required: rs.try_get("", "is_required")?, - }) - }) - .collect::, DbErr>>()?; - let labels = labels .iter() .map(|rs| { @@ -311,7 +269,6 @@ impl FormDatabase for ConnectionPool { id: form_id.into_inner(), title: form.try_get("", "form_title")?, description: form.try_get("", "description")?, - questions, metadata: ( form.try_get("", "created_at")?, form.try_get("", "updated_at")?, diff --git a/server/infra/resource/src/dto.rs b/server/infra/resource/src/dto.rs index 887a6c10..bf97fc55 100644 --- a/server/infra/resource/src/dto.rs +++ b/server/infra/resource/src/dto.rs @@ -47,7 +47,6 @@ pub struct FormDto { pub id: i32, pub title: String, pub description: Option, - pub questions: Vec, pub metadata: (DateTime, DateTime), pub response_period: Option<(DateTime, DateTime)>, pub webhook_url: Option, @@ -65,7 +64,6 @@ impl TryFrom for domain::form::models::Form { id, title, description, - questions, metadata, response_period, webhook_url, @@ -79,12 +77,6 @@ impl TryFrom for domain::form::models::Form { .id(id) .title(title) .description(description) - .questions( - questions - .into_iter() - .map(TryInto::try_into) - .collect::, _>>()?, - ) .metadata(metadata) .settings(FormSettings { response_period: ResponsePeriod::new(response_period), diff --git a/server/infra/resource/src/repository/form_repository_impl.rs b/server/infra/resource/src/repository/form_repository_impl.rs index beb746e4..9976a85f 100644 --- a/server/infra/resource/src/repository/form_repository_impl.rs +++ b/server/infra/resource/src/repository/form_repository_impl.rs @@ -183,7 +183,9 @@ impl FormRepository for Repository match self.get(form_id).await? { None => Ok(()), Some(form) => { - form_outgoing::post_answer(&form, user, title, &answers).await?; + let questions = self.get_questions(form_id).await?; + + form_outgoing::post_answer(&form, user, title, &answers, &questions).await?; self.client .form() .post_answer(user, form_id, answers) diff --git a/server/presentation/src/form_handler.rs b/server/presentation/src/form_handler.rs index c3fcffd9..6416391e 100644 --- a/server/presentation/src/form_handler.rs +++ b/server/presentation/src/form_handler.rs @@ -101,6 +101,7 @@ pub async fn get_form_handler( notification_repository: repository.notification_repository(), }; + // FIXME: form から questions を剥がしたので、usecase で questions を取得する必要がある match form_use_case.get_form(form_id).await { Ok(form) => (StatusCode::OK, Json(form)).into_response(), Err(err) => handle_error(err).into_response(), From 009390704575400a0c796ab696a719d2ce80efa2 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sun, 15 Dec 2024 15:38:41 +0900 Subject: [PATCH 04/33] =?UTF-8?q?refactor:=20form=20struct=20=E3=81=8B?= =?UTF-8?q?=E3=82=89=20labels=20=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=83=89=E3=82=92=E5=89=A5=E3=81=8C=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/domain/src/form/models.rs | 3 --- server/infra/resource/src/database/form.rs | 20 -------------------- server/infra/resource/src/dto.rs | 8 -------- 3 files changed, 31 deletions(-) diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index 095b3440..ad61caed 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -50,9 +50,6 @@ pub struct Form { pub metadata: FormMeta, #[serde(default)] pub settings: FormSettings, - #[cfg_attr(test, proptest(strategy = "arbitrary_with_size(1..100)"))] - #[serde(default)] - pub labels: Vec