Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deploy 20240511 #300

Merged
merged 5 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions crates/sos24-presentation/src/error/convert_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ impl From<FormAnswerUseCaseError> for AppError {
"form-answer/not-project-owner".to_string(),
message,
),
FormAnswerUseCaseError::ExportFailed => AppError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"form-answer/export-failed".to_string(),
message,
),
FormAnswerUseCaseError::FormIdError(e) => e.into(),
FormAnswerUseCaseError::ProjectIdError(e) => e.into(),
FormAnswerUseCaseError::FormUseCaseError(e) => e.into(),
Expand Down
26 changes: 19 additions & 7 deletions crates/sos24-presentation/src/model/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,16 @@ pub struct ProjectToBeExported {
sub_owner_phone_number: Option<String>,
#[serde(rename(serialize = "企画区分"))]
category: String,
#[serde(rename(serialize = "企画属性"))]
attributes: String,
#[serde(rename(serialize = "企画属性 屋内企画"))]
attributes_inside: bool,
#[serde(rename(serialize = "企画属性 屋外企画"))]
attributes_outside: bool,
#[serde(rename(serialize = "企画属性 学術認定企画"))]
attributes_academic: bool,
#[serde(rename(serialize = "企画属性 芸術祭参加企画"))]
attributes_art: bool,
#[serde(rename(serialize = "企画属性 委員会開催企画"))]
attributes_official: bool,
#[serde(rename(serialize = "備考"))]
remarks: Option<String>,
#[serde(rename(serialize = "作成日時"))]
Expand All @@ -173,13 +181,17 @@ impl From<ProjectDto> for ProjectToBeExported {
sub_owner_email: project.sub_owner_email,
sub_owner_phone_number: project.sub_owner_phone_number,
category: project.category.to_string(),
attributes: project
attributes_inside: project.attributes.0.contains(&ProjectAttributeDto::Inside),
attributes_outside: project.attributes.0.contains(&ProjectAttributeDto::Outside),
attributes_academic: project
.attributes
.0
.iter()
.map(ToString::to_string)
.collect::<Vec<String>>()
.join(";"),
.contains(&ProjectAttributeDto::Academic),
attributes_art: project.attributes.0.contains(&ProjectAttributeDto::Art),
attributes_official: project
.attributes
.0
.contains(&ProjectAttributeDto::Official),
remarks: project.remarks,
created_at: project
.created_at
Expand Down
5 changes: 3 additions & 2 deletions crates/sos24-presentation/src/route/form_answer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ pub async fn handle_export(
let data = (|| -> Result<String, CsvSerializationError> {
let mut csv_data = vec![];

let form_item_names_len = form_answer_list.form_item_names.len();
let header: Vec<String> = ["企画番号", "企画名", "企画団体名", "回答日時"]
.into_iter()
.map(ToString::to_string)
Expand All @@ -175,8 +176,8 @@ pub async fn handle_export(
.chain(
form_answer
.form_answer_item_values
.into_iter()
.map(|it| it.unwrap_or_default()),
.unwrap_or_else(|| vec![String::new(); form_item_names_len])
.into_iter(),
)
.collect();
csv_data.push(record);
Expand Down
11 changes: 6 additions & 5 deletions crates/sos24-use-case/src/file/interactor/export_by_form_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ impl<R: Repositories> FileUseCase<R> {
let project = project_with_owners.project.destruct();

let file_items = form_answer.list_file_items();
for (item_id, files) in file_items {
for (index1, (item_id, files)) in file_items.into_iter().enumerate() {
let Some(form_item) = form.find_item(&item_id) else {
return Err(FileUseCaseError::FormItemNotFound(item_id));
};

for (index, file_id) in files.into_iter().enumerate() {
for (index2, file_id) in files.into_iter().enumerate() {
let file = self
.repositories
.file_data_repository()
Expand All @@ -67,13 +67,14 @@ impl<R: Repositories> FileUseCase<R> {
.ok_or(FileUseCaseError::NotFound(file_id))?;
let file = file.destruct();

// {申請項目名}_{通し番号1}/{企画番号}_{企画名}_{通し番号2}_{オリジナルファイル名}
let filename = format!(
"{}/{}_{}_{}_{}_{}",
"{}_{}/{}_{}_{}_{}",
form_item.name().clone().value(),
index1 + 1,
project.index.clone().value(),
project.title.clone().value(),
project.group_name.clone().value(),
index + 1,
index2 + 1,
file.name.clone().value(),
);
file_list.push(ArchiveEntry::new(
Expand Down
2 changes: 2 additions & 0 deletions crates/sos24-use-case/src/form_answer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub enum FormAnswerUseCaseError {
FileNotFound(FileId),
#[error("Not a project owner or subowner")]
NotProjectOwner,
#[error("Export failed")]
ExportFailed,

#[error(transparent)]
FileIdError(#[from] FileIdError),
Expand Down
4 changes: 3 additions & 1 deletion crates/sos24-use-case/src/form_answer/dto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,18 @@ impl From<FormAnswerItemKind> for FormAnswerItemKindDto {
}
}

#[derive(Debug)]
pub struct FormAnswerToBeExportedListDto {
pub form_title: String,
pub form_item_names: Vec<String>,
pub form_answers: Vec<FormAnswerToBeExportedDto>,
}

#[derive(Debug)]
pub struct FormAnswerToBeExportedDto {
pub project_index: i32,
pub project_title: String,
pub project_group_name: String,
pub form_answer_item_values: Vec<Option<String>>,
pub form_answer_item_values: Option<Vec<String>>,
pub created_at: Option<String>,
}
137 changes: 91 additions & 46 deletions crates/sos24-use-case/src/form_answer/interactor/export_by_form_id.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use chrono_tz::Asia::Tokyo;

use sos24_domain::entity::form::FormId;
use sos24_domain::entity::form_answer::{FormAnswerItem, FormAnswerItemKind};
use sos24_domain::entity::form::{Form, FormId, FormItemKind};
use sos24_domain::entity::form_answer::{FormAnswer, FormAnswerItemKind};
use sos24_domain::repository::form::FormRepository;
use sos24_domain::repository::project::ProjectRepository;
use sos24_domain::{
Expand Down Expand Up @@ -37,13 +37,7 @@ impl<R: Repositories> FormAnswerUseCase<R> {
.filter(|project_with_owners| form.is_sent_to(&project_with_owners.project))
.collect();

let form = form.destruct();
let form_title = form.title.value();
let (form_item_ids, form_item_names): (Vec<_>, Vec<_>) = form
.items
.into_iter()
.map(|item| (item.id().clone(), item.name().clone().value()))
.unzip();
let header = export_header(&form);

let mut form_answers = Vec::new();
for project_with_owner in target_project_list {
Expand All @@ -56,26 +50,17 @@ impl<R: Repositories> FormAnswerUseCase<R> {

let (form_answer_item_values, created_at) = match form_answer {
Some(form_answer) => {
let form_answer = form_answer.destruct();
let values = form_item_ids
.iter()
.map(|item_id| {
form_answer
.items
.iter()
.find(|item| item.item_id() == item_id)
.map(convert_answer_item_to_string)
})
.collect();
let form_answer_item_values = export_record(&form, &form_answer)?;
let created_at = form_answer
.created_at
.created_at()
.clone()
.value()
.with_timezone(&Tokyo)
.format("%Y-%m-%d %H:%M:%S")
.to_string();
(values, Some(created_at))
(Some(form_answer_item_values), Some(created_at))
}
None => (form_item_ids.iter().map(|_| None).collect(), None),
None => (None, None),
};

let project = project_with_owner.project.destruct();
Expand All @@ -88,35 +73,95 @@ impl<R: Repositories> FormAnswerUseCase<R> {
});
}

Ok(FormAnswerToBeExportedListDto {
form_title,
form_item_names,
Ok(dbg!(FormAnswerToBeExportedListDto {
form_title: form.title().clone().value(),
form_item_names: header,
form_answers,
})
}))
}
}

fn export_header(form: &Form) -> Vec<String> {
let mut record = vec![];
for form_item in form.items() {
let form_item_name = form_item.name().clone().value();
match form_item.kind() {
FormItemKind::String(_)
| FormItemKind::Int(_)
| FormItemKind::ChooseOne(_)
| FormItemKind::File(_) => record.push(form_item_name),
FormItemKind::ChooseMany(choose_many) => {
for options in choose_many.options() {
record.push(format!("{} {}", form_item_name, options.clone().value()));
}
}
}
}
record
}

fn convert_answer_item_to_string(item: &FormAnswerItem) -> String {
match item.kind() {
FormAnswerItemKind::String(value) => value.clone().value().to_string(),
FormAnswerItemKind::Int(value) => value.clone().value().to_string(),
FormAnswerItemKind::ChooseOne(value) => value.clone().value().to_string(),
FormAnswerItemKind::ChooseMany(value) => value
.clone()
.value()
fn export_record(
form: &Form,
form_answer: &FormAnswer,
) -> Result<Vec<String>, FormAnswerUseCaseError> {
let mut record = vec![];
for form_item in form.items() {
let form_item_kind = form_item.kind();
let form_answer_item_kind = form_answer
.items()
.iter()
.map(|it| it.to_string())
.collect::<Vec<_>>()
.join(";"),
// TODO: ファイルのリネームを実装した段階で書き換え
FormAnswerItemKind::File(value) => value
.clone()
.value()
.into_iter()
.map(|it| it.value().to_string())
.collect::<Vec<_>>()
.join(";"),
.find(|form_answer_item| form_answer_item.item_id() == form_item.id())
.map(|it| it.kind());

match (form_item_kind, form_answer_item_kind) {
(FormItemKind::String(_), None) => record.push(String::new()),
(FormItemKind::String(_), Some(FormAnswerItemKind::String(value))) => {
record.push(value.clone().value().to_string());
}
(FormItemKind::Int(_), None) => record.push(String::new()),
(FormItemKind::Int(_), Some(FormAnswerItemKind::Int(value))) => {
record.push(value.clone().value().to_string());
}
(FormItemKind::ChooseOne(_), None) => record.push(String::new()),
(FormItemKind::ChooseOne(_), Some(FormAnswerItemKind::ChooseOne(value))) => {
record.push(value.clone().value().to_string());
}
(FormItemKind::ChooseMany(choose_many), None) => {
for _ in choose_many.options() {
record.push(String::new());
}
}
(
FormItemKind::ChooseMany(choose_many),
Some(FormAnswerItemKind::ChooseMany(value)),
) => {
let chosen_options = value.clone().value();
for option in choose_many.options() {
record.push(chosen_options.contains(&option.clone().value()).to_string());
}
}
(FormItemKind::File(_), None) => record.push(String::new()),
(FormItemKind::File(_), Some(FormAnswerItemKind::File(value))) => {
let files = value
.clone()
.value()
.into_iter()
.map(|it| it.value().to_string())
.collect::<Vec<_>>()
.join(";");
record.push(files);
}
_ => {
tracing::error!(
"Export failed: form_item_kind: {:?}, form_answer_item_kind: {:?}",
form_item_kind,
form_answer_item_kind
);
return Err(FormAnswerUseCaseError::ExportFailed);
}
}
}
Ok(record)
}

#[cfg(test)]
Expand Down