From f6206cf3b88100ed98a8783aa1937ba68ba9f3ef Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Fri, 8 Sep 2023 17:45:49 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20Answers=E3=83=86=E3=83=BC=E3=83=96?= =?UTF-8?q?=E3=83=AB=E3=81=ABTitle=E3=82=AB=E3=83=A9=E3=83=A0=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migration/src/m20230811_062425_create_answer_tables.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/migration/src/m20230811_062425_create_answer_tables.rs b/server/migration/src/m20230811_062425_create_answer_tables.rs index 37257362..a2b6cd3d 100644 --- a/server/migration/src/m20230811_062425_create_answer_tables.rs +++ b/server/migration/src/m20230811_062425_create_answer_tables.rs @@ -21,6 +21,11 @@ impl MigrationTrait for Migration { .primary_key(), ) .col(ColumnDef::new(AnswersTable::User).uuid().not_null()) + .col( + ColumnDef::new(AnswersTable::Title) + .string() + .default("未設定"), + ) .col( ColumnDef::new(AnswersTable::TimeStamp) .timestamp() @@ -93,6 +98,7 @@ enum AnswersTable { Answers, Id, User, + Title, TimeStamp, } From 500703bd7b8597f417212d18d0fd388b1246bddf Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Fri, 8 Sep 2023 23:14:58 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20default=5Fanswer=5Ftitle=E3=83=86?= =?UTF-8?q?=E3=83=BC=E3=83=96=E3=83=AB=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=83=9E=E3=82=A4=E3=82=B0=E3=83=AC=E3=83=BC=E3=82=B7?= =?UTF-8?q?=E3=83=A7=E3=83=B3=E3=81=AE=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/migration/src/lib.rs | 2 + ...0908_140907_create_default_answer_title.rs | 59 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 server/migration/src/m20230908_140907_create_default_answer_title.rs diff --git a/server/migration/src/lib.rs b/server/migration/src/lib.rs index 76db1e49..6fe9d63b 100644 --- a/server/migration/src/lib.rs +++ b/server/migration/src/lib.rs @@ -6,6 +6,7 @@ mod m20230219_143118_create_form_choices; mod m20230614_083950_crate_form_response_period_table; mod m20230622_053919_create_form_webhook; mod m20230811_062425_create_answer_tables; +mod m20230908_140907_create_default_answer_title; pub struct Migrator; @@ -19,6 +20,7 @@ impl MigratorTrait for Migrator { Box::new(m20230614_083950_crate_form_response_period_table::Migration), Box::new(m20230622_053919_create_form_webhook::Migration), Box::new(m20230811_062425_create_answer_tables::Migration), + Box::new(m20230908_140907_create_default_answer_title::Migration), ] } } diff --git a/server/migration/src/m20230908_140907_create_default_answer_title.rs b/server/migration/src/m20230908_140907_create_default_answer_title.rs new file mode 100644 index 00000000..6ea21457 --- /dev/null +++ b/server/migration/src/m20230908_140907_create_default_answer_title.rs @@ -0,0 +1,59 @@ +use crate::m20220101_000001_create_table::FormMetaDataTable; +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(DefaultAnswerTitleTable::DefaultAnswerTitle) + .if_not_exists() + .col( + ColumnDef::new(DefaultAnswerTitleTable::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col( + ColumnDef::new(DefaultAnswerTitleTable::FormId) + .integer() + .not_null(), + ) + .foreign_key( + ForeignKey::create() + .name("fk-form_key_default_answer_title") + .from( + DefaultAnswerTitleTable::DefaultAnswerTitle, + DefaultAnswerTitleTable::FormId, + ) + .to(FormMetaDataTable::FormMetaData, FormMetaDataTable::Id), + ) + .col(ColumnDef::new(DefaultAnswerTitleTable::Title).string()) + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_table( + Table::drop() + .table(DefaultAnswerTitleTable::DefaultAnswerTitle) + .to_owned(), + ) + .await + } +} + +#[derive(DeriveIden)] +enum DefaultAnswerTitleTable { + DefaultAnswerTitle, + Id, + FormId, + Title, +} From dadaffbe3633666fd06b0f69704ec160ddd6558f Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sat, 9 Sep 2023 00:10:14 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=81=ABdefault=5Fanswer?= =?UTF-8?q?=5Ftitle=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/domain/src/form/models.rs | 9 ++++++ server/infra/entities/src/answers.rs | 1 + .../entities/src/default_answer_title.rs | 32 +++++++++++++++++++ server/infra/entities/src/form_meta_data.rs | 8 +++++ server/infra/entities/src/form_questions.rs | 3 +- server/infra/entities/src/mod.rs | 1 + server/infra/entities/src/prelude.rs | 14 ++++---- server/infra/resource/src/database/form.rs | 26 ++++++++++++++- server/infra/resource/src/dto.rs | 3 ++ 9 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 server/infra/entities/src/default_answer_title.rs diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index 57da45b6..b4b426d8 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -134,6 +134,8 @@ pub struct FormSettings { pub response_period: ResponsePeriod, #[serde(default)] pub webhook_url: WebhookUrl, + #[serde(default)] + pub default_answer_title: DefaultAnswerTitle, } #[cfg_attr(test, derive(Arbitrary))] @@ -163,6 +165,13 @@ impl ResponsePeriod { } } +#[cfg_attr(test, derive(Arbitrary))] +#[derive(DerivingVia, Default, Debug, PartialEq)] +#[deriving(From, Into, Serialize(via: Option::), Deserialize(via: Option::))] +pub struct DefaultAnswerTitle { + pub default_answer_title: Option, +} + #[derive(Serialize, Deserialize, Debug)] pub struct PostedAnswers { pub uuid: Uuid, //todo: あとでUser型に直す diff --git a/server/infra/entities/src/answers.rs b/server/infra/entities/src/answers.rs index 8cfc485d..24015190 100644 --- a/server/infra/entities/src/answers.rs +++ b/server/infra/entities/src/answers.rs @@ -9,6 +9,7 @@ pub struct Model { pub id: i32, #[sea_orm(column_type = "Binary(BlobSize::Blob(Some(16)))")] pub user: Vec, + pub title: Option, pub time_stamp: DateTimeUtc, } diff --git a/server/infra/entities/src/default_answer_title.rs b/server/infra/entities/src/default_answer_title.rs new file mode 100644 index 00000000..f8559db5 --- /dev/null +++ b/server/infra/entities/src/default_answer_title.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "default_answer_title")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub form_id: i32, + pub title: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::form_meta_data::Entity", + from = "Column::FormId", + to = "super::form_meta_data::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + FormMetaData, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FormMetaData.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/server/infra/entities/src/form_meta_data.rs b/server/infra/entities/src/form_meta_data.rs index fea41b41..e09d3c31 100644 --- a/server/infra/entities/src/form_meta_data.rs +++ b/server/infra/entities/src/form_meta_data.rs @@ -15,6 +15,8 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { + #[sea_orm(has_many = "super::default_answer_title::Entity")] + DefaultAnswerTitle, #[sea_orm(has_many = "super::form_questions::Entity")] FormQuestions, #[sea_orm(has_many = "super::form_webhooks::Entity")] @@ -23,6 +25,12 @@ pub enum Relation { ResponsePeriod, } +impl Related for Entity { + fn to() -> RelationDef { + Relation::DefaultAnswerTitle.def() + } +} + impl Related for Entity { fn to() -> RelationDef { Relation::FormQuestions.def() diff --git a/server/infra/entities/src/form_questions.rs b/server/infra/entities/src/form_questions.rs index eff0a305..3eacf384 100644 --- a/server/infra/entities/src/form_questions.rs +++ b/server/infra/entities/src/form_questions.rs @@ -1,8 +1,7 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 -use sea_orm::entity::prelude::*; - use super::sea_orm_active_enums::QuestionType; +use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "form_questions")] diff --git a/server/infra/entities/src/mod.rs b/server/infra/entities/src/mod.rs index ffb43cb1..8b441b6b 100644 --- a/server/infra/entities/src/mod.rs +++ b/server/infra/entities/src/mod.rs @@ -3,6 +3,7 @@ pub mod prelude; pub mod answers; +pub mod default_answer_title; pub mod form_choices; pub mod form_meta_data; pub mod form_questions; diff --git a/server/infra/entities/src/prelude.rs b/server/infra/entities/src/prelude.rs index 76733f92..b2bbbd32 100644 --- a/server/infra/entities/src/prelude.rs +++ b/server/infra/entities/src/prelude.rs @@ -1,8 +1,10 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 -pub use super::{ - answers::Entity as Answers, form_choices::Entity as FormChoices, - form_meta_data::Entity as FormMetaData, form_questions::Entity as FormQuestions, - form_webhooks::Entity as FormWebhooks, real_answers::Entity as RealAnswers, - response_period::Entity as ResponsePeriod, -}; +pub use super::answers::Entity as Answers; +pub use super::default_answer_title::Entity as DefaultAnswerTitle; +pub use super::form_choices::Entity as FormChoices; +pub use super::form_meta_data::Entity as FormMetaData; +pub use super::form_questions::Entity as FormQuestions; +pub use super::form_webhooks::Entity as FormWebhooks; +pub use super::real_answers::Entity as RealAnswers; +pub use super::response_period::Entity as ResponsePeriod; diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index 85975730..d907abc8 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -4,8 +4,9 @@ use domain::form::models::{ FormDescription, FormId, FormQuestionUpdateSchema, FormTitle, FormUpdateTargets, OffsetAndLimit, PostedAnswers, }; +use entities::prelude::DefaultAnswerTitle; use entities::{ - answers, form_choices, form_meta_data, form_questions, form_webhooks, + answers, default_answer_title, form_choices, form_meta_data, form_questions, form_webhooks, prelude::{FormChoices, FormMetaData, FormQuestions, FormWebhooks, RealAnswers}, real_answers, response_period, sea_orm_active_enums::QuestionType, @@ -87,6 +88,11 @@ impl FormDatabase for ConnectionPool { .all(&self.pool) .await?; + let all_default_answer_title = DefaultAnswerTitle::find() + .filter(Expr::col(default_answer_title::Column::FormId).is_in(form_ids.to_owned())) + .all(&self.pool) + .await?; + Ok(forms .into_iter() .map(|form| { @@ -131,6 +137,13 @@ impl FormDatabase for ConnectionPool { .next() .unwrap_or_default(); + let default_answer_title = all_default_answer_title + .iter() + .filter(|default_answer_title| default_answer_title.form_id == form.id) + .map(|default_answer_title| default_answer_title.title.to_owned()) + .next() + .unwrap_or_default(); + FormDto { id: form.id, title: form.title, @@ -139,6 +152,7 @@ impl FormDatabase for ConnectionPool { metadata: (form.created_at, form.updated_at), response_period, webhook_url, + default_answer_title, } }) .collect()) @@ -206,6 +220,14 @@ impl FormDatabase for ConnectionPool { .map(|webhook_url_model| Some(webhook_url_model.url.to_owned())) .unwrap_or_default(); + let default_answer_title = DefaultAnswerTitle::find() + .filter(Expr::col(default_answer_title::Column::FormId).eq(target_form.id)) + .all(&self.pool) + .await? + .first() + .map(|answer_title_setting| answer_title_setting.title.to_owned()) + .unwrap_or_default(); + Ok(FormDto { id: target_form.id, title: target_form.title, @@ -214,6 +236,7 @@ impl FormDatabase for ConnectionPool { metadata: (target_form.created_at, target_form.updated_at), response_period, webhook_url, + default_answer_title, }) } @@ -334,6 +357,7 @@ impl FormDatabase for ConnectionPool { let id = answers::ActiveModel { id: Default::default(), user: Set(answer.uuid.to_owned().as_ref().to_vec()), + title: todo!(), time_stamp: Set(Utc::now()), } .insert(&self.pool) diff --git a/server/infra/resource/src/dto.rs b/server/infra/resource/src/dto.rs index 5f9257c2..f441303e 100644 --- a/server/infra/resource/src/dto.rs +++ b/server/infra/resource/src/dto.rs @@ -42,6 +42,7 @@ pub struct FormDto { pub metadata: (DateTime, DateTime), pub response_period: Option<(DateTime, DateTime)>, pub webhook_url: Option, + pub default_answer_title: Option, } impl TryFrom for domain::form::models::Form { @@ -56,6 +57,7 @@ impl TryFrom for domain::form::models::Form { metadata, response_period, webhook_url, + default_answer_title, }: FormDto, ) -> Result { Ok(domain::form::models::Form::builder() @@ -72,6 +74,7 @@ impl TryFrom for domain::form::models::Form { .settings(FormSettings { response_period: ResponsePeriod::new(response_period), webhook_url: webhook_url.into(), + default_answer_title: default_answer_title.into(), }) .build()) } From eb481759770cebdb5ccff98b38beef224edca9f3 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sat, 9 Sep 2023 00:11:24 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=81=ABdefault=5Fanswer?= =?UTF-8?q?=5Ftitle=E3=82=92=E8=BF=BD=E5=8A=A0=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/infra/resource/src/database/form.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index d907abc8..35ebcda8 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -354,6 +354,7 @@ impl FormDatabase for ConnectionPool { } async fn post_answer(&self, answer: PostedAnswers) -> Result<(), InfraError> { + todo!(); let id = answers::ActiveModel { id: Default::default(), user: Set(answer.uuid.to_owned().as_ref().to_vec()), From 4a2144f052298ced4614521725ea2636125ddf95 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sat, 9 Sep 2023 00:52:12 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat:=20=E5=9B=9E=E7=AD=94=E3=81=8C?= =?UTF-8?q?=E3=81=82=E3=81=A3=E3=81=9F=E3=81=A8=E3=81=8D=E3=81=AB=E5=9B=9E?= =?UTF-8?q?=E7=AD=94=E3=81=AE=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB=E3=82=92?= =?UTF-8?q?=E5=9F=8B=E3=82=81=E8=BE=BC=E3=82=81=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/Cargo.lock | 29 +++++++++++----- server/Cargo.toml | 1 + server/domain/src/form/models.rs | 2 ++ server/infra/entities/src/answers.rs | 2 +- server/infra/entities/src/form_questions.rs | 3 +- server/infra/entities/src/prelude.rs | 14 ++++---- server/infra/resource/Cargo.toml | 1 + server/infra/resource/src/database/form.rs | 34 ++++++++++++++++--- .../m20230811_062425_create_answer_tables.rs | 1 + ...0908_140907_create_default_answer_title.rs | 3 +- 10 files changed, 67 insertions(+), 23 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 86df195c..77118b1a 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1724,7 +1724,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -1744,9 +1744,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "memmap2" @@ -2418,13 +2418,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.3.8", + "regex-syntax 0.7.5", ] [[package]] @@ -2436,6 +2437,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -2444,9 +2456,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rend" @@ -2514,6 +2526,7 @@ dependencies = [ "num-traits", "once_cell", "outgoing", + "regex", "sea-orm", "serde", "tracing", diff --git a/server/Cargo.toml b/server/Cargo.toml index d6b65f5d..4c850680 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -40,3 +40,4 @@ uuid = "1.4.1" deriving_via = "1.5.0" reqwest = { version = "0.11.20", default-features = false, features = ["rustls"] } num-traits = "0.2.16" +regex = "1.9.5" diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index b4b426d8..014df124 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -176,6 +176,8 @@ pub struct DefaultAnswerTitle { pub struct PostedAnswers { pub uuid: Uuid, //todo: あとでUser型に直す pub timestamp: DateTime, + pub form_id: FormId, + pub title: String, pub answers: Vec, } diff --git a/server/infra/entities/src/answers.rs b/server/infra/entities/src/answers.rs index 24015190..9c279c1e 100644 --- a/server/infra/entities/src/answers.rs +++ b/server/infra/entities/src/answers.rs @@ -9,7 +9,7 @@ pub struct Model { pub id: i32, #[sea_orm(column_type = "Binary(BlobSize::Blob(Some(16)))")] pub user: Vec, - pub title: Option, + pub title: String, pub time_stamp: DateTimeUtc, } diff --git a/server/infra/entities/src/form_questions.rs b/server/infra/entities/src/form_questions.rs index 3eacf384..eff0a305 100644 --- a/server/infra/entities/src/form_questions.rs +++ b/server/infra/entities/src/form_questions.rs @@ -1,8 +1,9 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 -use super::sea_orm_active_enums::QuestionType; use sea_orm::entity::prelude::*; +use super::sea_orm_active_enums::QuestionType; + #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "form_questions")] pub struct Model { diff --git a/server/infra/entities/src/prelude.rs b/server/infra/entities/src/prelude.rs index b2bbbd32..f982f5dc 100644 --- a/server/infra/entities/src/prelude.rs +++ b/server/infra/entities/src/prelude.rs @@ -1,10 +1,8 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 -pub use super::answers::Entity as Answers; -pub use super::default_answer_title::Entity as DefaultAnswerTitle; -pub use super::form_choices::Entity as FormChoices; -pub use super::form_meta_data::Entity as FormMetaData; -pub use super::form_questions::Entity as FormQuestions; -pub use super::form_webhooks::Entity as FormWebhooks; -pub use super::real_answers::Entity as RealAnswers; -pub use super::response_period::Entity as ResponsePeriod; +pub use super::{ + answers::Entity as Answers, default_answer_title::Entity as DefaultAnswerTitle, + form_choices::Entity as FormChoices, form_meta_data::Entity as FormMetaData, + form_questions::Entity as FormQuestions, form_webhooks::Entity as FormWebhooks, + real_answers::Entity as RealAnswers, response_period::Entity as ResponsePeriod, +}; diff --git a/server/infra/resource/Cargo.toml b/server/infra/resource/Cargo.toml index 1d15f365..12c1a6d3 100644 --- a/server/infra/resource/Cargo.toml +++ b/server/infra/resource/Cargo.toml @@ -21,3 +21,4 @@ sea-orm = { workspace = true } serde = { workspace = true } tracing = { workspace = true } num-traits = { workspace = true } +regex = { workspace = true } diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index 35ebcda8..2ee7f3e9 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -4,10 +4,11 @@ use domain::form::models::{ FormDescription, FormId, FormQuestionUpdateSchema, FormTitle, FormUpdateTargets, OffsetAndLimit, PostedAnswers, }; -use entities::prelude::DefaultAnswerTitle; use entities::{ answers, default_answer_title, form_choices, form_meta_data, form_questions, form_webhooks, - prelude::{FormChoices, FormMetaData, FormQuestions, FormWebhooks, RealAnswers}, + prelude::{ + DefaultAnswerTitle, FormChoices, FormMetaData, FormQuestions, FormWebhooks, RealAnswers, + }, real_answers, response_period, sea_orm_active_enums::QuestionType, }; @@ -15,6 +16,7 @@ use errors::infra::{InfraError, InfraError::FormNotFound}; use futures::{stream, stream::StreamExt}; use itertools::Itertools; use num_traits::cast::FromPrimitive; +use regex::Regex; use sea_orm::{ sea_query::{Expr, SimpleExpr}, ActiveEnum, ActiveModelTrait, ActiveValue, @@ -354,11 +356,35 @@ impl FormDatabase for ConnectionPool { } async fn post_answer(&self, answer: PostedAnswers) -> Result<(), InfraError> { - todo!(); + let regex = Regex::new(r"\$\d+").unwrap(); + + let default_answer_title = DefaultAnswerTitle::find() + .filter(Expr::col(default_answer_title::Column::FormId).eq(answer.form_id.to_owned())) + .all(&self.pool) + .await? + .first() + .and_then(|answer_title_setting| answer_title_setting.title.to_owned()) + .unwrap_or("未設定".to_string()); + + let embed_title = regex.find_iter(&default_answer_title.to_owned()).fold( + default_answer_title, + |replaced_title, question_id| { + let answer_opt = answer.answers.iter().find(|answer| { + answer.question_id.to_string() == question_id.as_str().replace('$', "") + }); + replaced_title.replace( + question_id.as_str(), + &answer_opt + .map(|answer| answer.answer.to_owned()) + .unwrap_or_default(), + ) + }, + ); + let id = answers::ActiveModel { id: Default::default(), user: Set(answer.uuid.to_owned().as_ref().to_vec()), - title: todo!(), + title: Set(embed_title), time_stamp: Set(Utc::now()), } .insert(&self.pool) diff --git a/server/migration/src/m20230811_062425_create_answer_tables.rs b/server/migration/src/m20230811_062425_create_answer_tables.rs index a2b6cd3d..05eca048 100644 --- a/server/migration/src/m20230811_062425_create_answer_tables.rs +++ b/server/migration/src/m20230811_062425_create_answer_tables.rs @@ -24,6 +24,7 @@ impl MigrationTrait for Migration { .col( ColumnDef::new(AnswersTable::Title) .string() + .not_null() .default("未設定"), ) .col( diff --git a/server/migration/src/m20230908_140907_create_default_answer_title.rs b/server/migration/src/m20230908_140907_create_default_answer_title.rs index 6ea21457..94ef8ba6 100644 --- a/server/migration/src/m20230908_140907_create_default_answer_title.rs +++ b/server/migration/src/m20230908_140907_create_default_answer_title.rs @@ -1,6 +1,7 @@ -use crate::m20220101_000001_create_table::FormMetaDataTable; use sea_orm_migration::prelude::*; +use crate::m20220101_000001_create_table::FormMetaDataTable; + #[derive(DeriveMigrationName)] pub struct Migration; From 63f90d6d8f0c0fe9130815fe8042ccd6f5592d61 Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sun, 10 Sep 2023 22:18:44 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=E3=83=95=E3=82=A9=E3=83=BC?= =?UTF-8?q?=E3=83=A0=E3=81=AE=E5=9B=9E=E7=AD=94=E3=81=AE=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=88=E3=83=AB=E3=81=AE=E8=A8=AD=E5=AE=9A=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/domain/src/form/models.rs | 12 +++- server/entrypoint/src/main.rs | 2 +- .../entities/src/default_answer_titles.rs | 32 +++++++++ server/infra/entities/src/form_meta_data.rs | 8 +-- server/infra/entities/src/mod.rs | 2 +- server/infra/entities/src/prelude.rs | 2 +- server/infra/resource/src/database/form.rs | 72 +++++++++++++------ server/migration/src/lib.rs | 4 +- ...08_140907_create_default_answer_titles.rs} | 22 +++--- 9 files changed, 114 insertions(+), 42 deletions(-) create mode 100644 server/infra/entities/src/default_answer_titles.rs rename server/migration/src/{m20230908_140907_create_default_answer_title.rs => m20230908_140907_create_default_answer_titles.rs} (67%) diff --git a/server/domain/src/form/models.rs b/server/domain/src/form/models.rs index 014df124..6484dfce 100644 --- a/server/domain/src/form/models.rs +++ b/server/domain/src/form/models.rs @@ -30,6 +30,8 @@ pub struct FormUpdateTargets { pub response_period: Option, #[serde(default)] pub webhook: Option, + #[serde(default)] + pub default_answer_title: Option, } #[derive(Deserialize, Debug)] @@ -172,12 +174,20 @@ pub struct DefaultAnswerTitle { pub default_answer_title: Option, } +impl DefaultAnswerTitle { + pub fn unwrap_or_default(&self) -> String { + self.default_answer_title + .to_owned() + .unwrap_or("未設定".to_string()) + } +} + #[derive(Serialize, Deserialize, Debug)] pub struct PostedAnswers { pub uuid: Uuid, //todo: あとでUser型に直す pub timestamp: DateTime, pub form_id: FormId, - pub title: String, + pub title: DefaultAnswerTitle, pub answers: Vec, } diff --git a/server/entrypoint/src/main.rs b/server/entrypoint/src/main.rs index 8fef81f1..b2c42769 100644 --- a/server/entrypoint/src/main.rs +++ b/server/entrypoint/src/main.rs @@ -8,8 +8,8 @@ use axum::{ }; use common::config::{ENV, HTTP}; use hyper::header::AUTHORIZATION; +use presentation::auth::auth; use presentation::{ - auth::auth, form_handler::{ create_form_handler, create_question_handler, delete_form_handler, form_list_handler, get_form_handler, post_answer_handler, update_form_handler, diff --git a/server/infra/entities/src/default_answer_titles.rs b/server/infra/entities/src/default_answer_titles.rs new file mode 100644 index 00000000..c576a188 --- /dev/null +++ b/server/infra/entities/src/default_answer_titles.rs @@ -0,0 +1,32 @@ +//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 + +use sea_orm::entity::prelude::*; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] +#[sea_orm(table_name = "default_answer_titles")] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub form_id: i32, + pub title: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::form_meta_data::Entity", + from = "Column::FormId", + to = "super::form_meta_data::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + FormMetaData, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::FormMetaData.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/server/infra/entities/src/form_meta_data.rs b/server/infra/entities/src/form_meta_data.rs index e09d3c31..90bc5524 100644 --- a/server/infra/entities/src/form_meta_data.rs +++ b/server/infra/entities/src/form_meta_data.rs @@ -15,8 +15,8 @@ pub struct Model { #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { - #[sea_orm(has_many = "super::default_answer_title::Entity")] - DefaultAnswerTitle, + #[sea_orm(has_many = "super::default_answer_titles::Entity")] + DefaultAnswerTitles, #[sea_orm(has_many = "super::form_questions::Entity")] FormQuestions, #[sea_orm(has_many = "super::form_webhooks::Entity")] @@ -25,9 +25,9 @@ pub enum Relation { ResponsePeriod, } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { - Relation::DefaultAnswerTitle.def() + Relation::DefaultAnswerTitles.def() } } diff --git a/server/infra/entities/src/mod.rs b/server/infra/entities/src/mod.rs index 8b441b6b..b024134e 100644 --- a/server/infra/entities/src/mod.rs +++ b/server/infra/entities/src/mod.rs @@ -3,7 +3,7 @@ pub mod prelude; pub mod answers; -pub mod default_answer_title; +pub mod default_answer_titles; pub mod form_choices; pub mod form_meta_data; pub mod form_questions; diff --git a/server/infra/entities/src/prelude.rs b/server/infra/entities/src/prelude.rs index f982f5dc..4c7f10a1 100644 --- a/server/infra/entities/src/prelude.rs +++ b/server/infra/entities/src/prelude.rs @@ -1,7 +1,7 @@ //! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.1 pub use super::{ - answers::Entity as Answers, default_answer_title::Entity as DefaultAnswerTitle, + answers::Entity as Answers, default_answer_titles::Entity as DefaultAnswerTitles, form_choices::Entity as FormChoices, form_meta_data::Entity as FormMetaData, form_questions::Entity as FormQuestions, form_webhooks::Entity as FormWebhooks, real_answers::Entity as RealAnswers, response_period::Entity as ResponsePeriod, diff --git a/server/infra/resource/src/database/form.rs b/server/infra/resource/src/database/form.rs index 2ee7f3e9..3338ddac 100644 --- a/server/infra/resource/src/database/form.rs +++ b/server/infra/resource/src/database/form.rs @@ -1,13 +1,13 @@ use async_trait::async_trait; use chrono::Utc; use domain::form::models::{ - FormDescription, FormId, FormQuestionUpdateSchema, FormTitle, FormUpdateTargets, - OffsetAndLimit, PostedAnswers, + DefaultAnswerTitle, FormDescription, FormId, FormQuestionUpdateSchema, FormTitle, + FormUpdateTargets, OffsetAndLimit, PostedAnswers, }; use entities::{ - answers, default_answer_title, form_choices, form_meta_data, form_questions, form_webhooks, + answers, default_answer_titles, form_choices, form_meta_data, form_questions, form_webhooks, prelude::{ - DefaultAnswerTitle, FormChoices, FormMetaData, FormQuestions, FormWebhooks, RealAnswers, + DefaultAnswerTitles, FormChoices, FormMetaData, FormQuestions, FormWebhooks, RealAnswers, }, real_answers, response_period, sea_orm_active_enums::QuestionType, @@ -90,8 +90,8 @@ impl FormDatabase for ConnectionPool { .all(&self.pool) .await?; - let all_default_answer_title = DefaultAnswerTitle::find() - .filter(Expr::col(default_answer_title::Column::FormId).is_in(form_ids.to_owned())) + let all_default_answer_title = DefaultAnswerTitles::find() + .filter(Expr::col(default_answer_titles::Column::FormId).is_in(form_ids.to_owned())) .all(&self.pool) .await?; @@ -143,8 +143,7 @@ impl FormDatabase for ConnectionPool { .iter() .filter(|default_answer_title| default_answer_title.form_id == form.id) .map(|default_answer_title| default_answer_title.title.to_owned()) - .next() - .unwrap_or_default(); + .next(); FormDto { id: form.id, @@ -222,13 +221,12 @@ impl FormDatabase for ConnectionPool { .map(|webhook_url_model| Some(webhook_url_model.url.to_owned())) .unwrap_or_default(); - let default_answer_title = DefaultAnswerTitle::find() - .filter(Expr::col(default_answer_title::Column::FormId).eq(target_form.id)) + let default_answer_title = DefaultAnswerTitles::find() + .filter(Expr::col(default_answer_titles::Column::FormId).eq(target_form.id)) .all(&self.pool) .await? .first() - .map(|answer_title_setting| answer_title_setting.title.to_owned()) - .unwrap_or_default(); + .map(|answer_title_setting| answer_title_setting.title.to_owned()); Ok(FormDto { id: target_form.id, @@ -289,6 +287,7 @@ impl FormDatabase for ConnectionPool { description, response_period, webhook, + default_answer_title, }: FormUpdateTargets, ) -> Result<(), InfraError> { let current_form = self.get(form_id.to_owned().into()).await?; @@ -352,19 +351,42 @@ impl FormDatabase for ConnectionPool { .await?; } + if current_form.default_answer_title.is_some() && default_answer_title.is_some() { + DefaultAnswerTitles::update_many() + .filter(default_answer_titles::Column::FormId.eq(form_id.to_owned())) + .col_expr( + default_answer_titles::Column::Title, + Expr::value(default_answer_title.unwrap().unwrap_or_default()), + ) + .exec(&self.pool) + .await?; + } else if let Some(default_answer_title) = default_answer_title { + default_answer_titles::ActiveModel { + id: ActiveValue::NotSet, + form_id: Set(form_id.to_owned()), + title: Set(default_answer_title.unwrap_or_default()), + } + .insert(&self.pool) + .await?; + } + Ok(()) } async fn post_answer(&self, answer: PostedAnswers) -> Result<(), InfraError> { let regex = Regex::new(r"\$\d+").unwrap(); - let default_answer_title = DefaultAnswerTitle::find() - .filter(Expr::col(default_answer_title::Column::FormId).eq(answer.form_id.to_owned())) - .all(&self.pool) - .await? - .first() - .and_then(|answer_title_setting| answer_title_setting.title.to_owned()) - .unwrap_or("未設定".to_string()); + let default_answer_title = DefaultAnswerTitle { + default_answer_title: DefaultAnswerTitles::find() + .filter( + Expr::col(default_answer_titles::Column::FormId).eq(answer.form_id.to_owned()), + ) + .all(&self.pool) + .await? + .first() + .map(|answer_title_setting| answer_title_setting.title.to_owned()), + } + .unwrap_or_default(); let embed_title = regex.find_iter(&default_answer_title.to_owned()).fold( default_answer_title, @@ -434,7 +456,8 @@ impl FormDatabase for ConnectionPool { .await? .last_insert_id; - let first_insert_id = last_insert_id - form_question_update_schema.questions.len() as i32; + let first_insert_id = + last_insert_id - form_question_update_schema.questions.len() as i32 + 1; let question_ids: Vec<_> = (first_insert_id..last_insert_id).collect(); @@ -456,9 +479,12 @@ impl FormDatabase for ConnectionPool { }) .collect_vec(); - FormChoices::insert_many(choices_active_values) - .exec(&self.pool) - .await?; + if !choices_active_values.is_empty() { + // NOTE: insert_manyに渡すvecが空だとinsertに失敗する + FormChoices::insert_many(choices_active_values) + .exec(&self.pool) + .await?; + } Ok(()) } diff --git a/server/migration/src/lib.rs b/server/migration/src/lib.rs index 6fe9d63b..af739585 100644 --- a/server/migration/src/lib.rs +++ b/server/migration/src/lib.rs @@ -6,7 +6,7 @@ mod m20230219_143118_create_form_choices; mod m20230614_083950_crate_form_response_period_table; mod m20230622_053919_create_form_webhook; mod m20230811_062425_create_answer_tables; -mod m20230908_140907_create_default_answer_title; +mod m20230908_140907_create_default_answer_titles; pub struct Migrator; @@ -20,7 +20,7 @@ impl MigratorTrait for Migrator { Box::new(m20230614_083950_crate_form_response_period_table::Migration), Box::new(m20230622_053919_create_form_webhook::Migration), Box::new(m20230811_062425_create_answer_tables::Migration), - Box::new(m20230908_140907_create_default_answer_title::Migration), + Box::new(m20230908_140907_create_default_answer_titles::Migration), ] } } diff --git a/server/migration/src/m20230908_140907_create_default_answer_title.rs b/server/migration/src/m20230908_140907_create_default_answer_titles.rs similarity index 67% rename from server/migration/src/m20230908_140907_create_default_answer_title.rs rename to server/migration/src/m20230908_140907_create_default_answer_titles.rs index 94ef8ba6..55cb5bc3 100644 --- a/server/migration/src/m20230908_140907_create_default_answer_title.rs +++ b/server/migration/src/m20230908_140907_create_default_answer_titles.rs @@ -11,17 +11,17 @@ impl MigrationTrait for Migration { manager .create_table( Table::create() - .table(DefaultAnswerTitleTable::DefaultAnswerTitle) + .table(DefaultAnswerTitlesTable::DefaultAnswerTitles) .if_not_exists() .col( - ColumnDef::new(DefaultAnswerTitleTable::Id) + ColumnDef::new(DefaultAnswerTitlesTable::Id) .integer() .not_null() .auto_increment() .primary_key(), ) .col( - ColumnDef::new(DefaultAnswerTitleTable::FormId) + ColumnDef::new(DefaultAnswerTitlesTable::FormId) .integer() .not_null(), ) @@ -29,12 +29,16 @@ impl MigrationTrait for Migration { ForeignKey::create() .name("fk-form_key_default_answer_title") .from( - DefaultAnswerTitleTable::DefaultAnswerTitle, - DefaultAnswerTitleTable::FormId, + DefaultAnswerTitlesTable::DefaultAnswerTitles, + DefaultAnswerTitlesTable::FormId, ) .to(FormMetaDataTable::FormMetaData, FormMetaDataTable::Id), ) - .col(ColumnDef::new(DefaultAnswerTitleTable::Title).string()) + .col( + ColumnDef::new(DefaultAnswerTitlesTable::Title) + .string() + .not_null(), + ) .to_owned(), ) .await @@ -44,7 +48,7 @@ impl MigrationTrait for Migration { manager .drop_table( Table::drop() - .table(DefaultAnswerTitleTable::DefaultAnswerTitle) + .table(DefaultAnswerTitlesTable::DefaultAnswerTitles) .to_owned(), ) .await @@ -52,8 +56,8 @@ impl MigrationTrait for Migration { } #[derive(DeriveIden)] -enum DefaultAnswerTitleTable { - DefaultAnswerTitle, +enum DefaultAnswerTitlesTable { + DefaultAnswerTitles, Id, FormId, Title, From efb1d0b045897b9b36feeea014b2d24cfa8cf33f Mon Sep 17 00:00:00 2001 From: rito528 <39003544+rito528@users.noreply.github.com> Date: Sun, 10 Sep 2023 22:26:40 +0900 Subject: [PATCH 7/7] style: apply pretty --- server/entrypoint/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/entrypoint/src/main.rs b/server/entrypoint/src/main.rs index b2c42769..8fef81f1 100644 --- a/server/entrypoint/src/main.rs +++ b/server/entrypoint/src/main.rs @@ -8,8 +8,8 @@ use axum::{ }; use common::config::{ENV, HTTP}; use hyper::header::AUTHORIZATION; -use presentation::auth::auth; use presentation::{ + auth::auth, form_handler::{ create_form_handler, create_question_handler, delete_form_handler, form_list_handler, get_form_handler, post_answer_handler, update_form_handler,