From 1fda5a18befed8c1731ce84ceb40ebe7f887e234 Mon Sep 17 00:00:00 2001 From: hamz2a Date: Tue, 12 Mar 2024 17:21:13 +0100 Subject: [PATCH] editoast: make budget nullable in project and study --- .../down.sql | 5 +++++ .../up.sql | 2 ++ editoast/openapi.yaml | 6 ++++-- editoast/src/fixtures.rs | 4 ++-- editoast/src/modelsv2/projects.rs | 4 ++-- editoast/src/modelsv2/study.rs | 2 +- editoast/src/tables.rs | 4 ++-- editoast/src/views/projects.rs | 5 ++--- editoast/src/views/study.rs | 5 ++--- .../operationalStudies/views/Project.tsx | 6 +++--- .../operationalStudies/views/Study.tsx | 20 +++++++------------ front/src/common/api/osrdEditoastApi.ts | 8 ++++---- .../components/AddOrEditProjectModal.tsx | 13 ++++++------ .../study/components/AddOrEditStudyModal.tsx | 13 ++++++------ .../modules/study/components/StudyCard.tsx | 6 +++--- 15 files changed, 53 insertions(+), 50 deletions(-) create mode 100644 editoast/migrations/2024-03-12-143107_make_budget_nullable/down.sql create mode 100644 editoast/migrations/2024-03-12-143107_make_budget_nullable/up.sql diff --git a/editoast/migrations/2024-03-12-143107_make_budget_nullable/down.sql b/editoast/migrations/2024-03-12-143107_make_budget_nullable/down.sql new file mode 100644 index 00000000000..5011c8e831b --- /dev/null +++ b/editoast/migrations/2024-03-12-143107_make_budget_nullable/down.sql @@ -0,0 +1,5 @@ +UPDATE study SET budget = COALESCE(budget, 0); +ALTER TABLE study ALTER COLUMN budget SET NOT NULL; + +UPDATE project SET budget = COALESCE(budget, 0); +ALTER TABLE project ALTER COLUMN budget SET NOT NULL; diff --git a/editoast/migrations/2024-03-12-143107_make_budget_nullable/up.sql b/editoast/migrations/2024-03-12-143107_make_budget_nullable/up.sql new file mode 100644 index 00000000000..59aa31ce641 --- /dev/null +++ b/editoast/migrations/2024-03-12-143107_make_budget_nullable/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE study ALTER COLUMN budget DROP NOT NULL; +ALTER TABLE project ALTER COLUMN budget DROP NOT NULL; diff --git a/editoast/openapi.yaml b/editoast/openapi.yaml index 39466019605..c811adbdaf5 100644 --- a/editoast/openapi.yaml +++ b/editoast/openapi.yaml @@ -4475,6 +4475,7 @@ components: properties: budget: format: int32 + nullable: true type: integer creation_date: format: date-time @@ -4505,7 +4506,6 @@ components: - objectives - description - funders - - budget - creation_date - last_modification - tags @@ -4515,6 +4515,7 @@ components: properties: budget: format: int32 + nullable: true type: integer description: maxLength: 1024 @@ -5967,6 +5968,7 @@ components: type: string budget: format: int32 + nullable: true type: integer business_code: type: string @@ -6010,7 +6012,6 @@ components: - service_code - creation_date - last_modification - - budget - tags - state - study_type @@ -6025,6 +6026,7 @@ components: type: string budget: format: int32 + nullable: true type: integer business_code: type: string diff --git a/editoast/src/fixtures.rs b/editoast/src/fixtures.rs index b051a9cef8e..e1df6b18bf6 100644 --- a/editoast/src/fixtures.rs +++ b/editoast/src/fixtures.rs @@ -295,7 +295,7 @@ pub mod tests { .service_code("BBB".into()) .creation_date(Utc::now().naive_utc()) .last_modification(Utc::now().naive_utc()) - .budget(0) + .budget(Some(0)) .tags(Tags::default()) .state("some_state".into()) .study_type("some_type".into()) @@ -313,7 +313,7 @@ pub mod tests { .objectives("".to_owned()) .description("".to_owned()) .funders("".to_owned()) - .budget(0) + .budget(Some(0)) .creation_date(Utc::now().naive_utc()) .last_modification(Utc::now().naive_utc()) .tags(Tags::default()); diff --git a/editoast/src/modelsv2/projects.rs b/editoast/src/modelsv2/projects.rs index b37c23f1af0..68dd57e2450 100644 --- a/editoast/src/modelsv2/projects.rs +++ b/editoast/src/modelsv2/projects.rs @@ -28,7 +28,7 @@ pub struct Project { pub objectives: String, pub description: String, pub funders: String, - pub budget: i32, + pub budget: Option, pub creation_date: NaiveDateTime, pub last_modification: NaiveDateTime, #[model(remote = "Vec>")] @@ -239,7 +239,7 @@ pub mod test { // Patch a project let mut project = project_fixture.model.clone(); project.name = "update_name".into(); - project.budget = 1000; + project.budget = Some(1000); project.save(conn).await.unwrap(); let project = Project::retrieve(conn, project.id).await.unwrap().unwrap(); assert_eq!(project.name, String::from("update_name")); diff --git a/editoast/src/modelsv2/study.rs b/editoast/src/modelsv2/study.rs index 6d92552abfe..c10eb977247 100644 --- a/editoast/src/modelsv2/study.rs +++ b/editoast/src/modelsv2/study.rs @@ -31,7 +31,7 @@ pub struct Study { pub start_date: Option, pub expected_end_date: Option, pub actual_end_date: Option, - pub budget: i32, + pub budget: Option, #[model(remote = "Vec>")] pub tags: Tags, pub state: String, diff --git a/editoast/src/tables.rs b/editoast/src/tables.rs index d02d3b70015..e9870996d50 100644 --- a/editoast/src/tables.rs +++ b/editoast/src/tables.rs @@ -402,7 +402,7 @@ diesel::table! { description -> Varchar, #[max_length = 255] funders -> Varchar, - budget -> Int4, + budget -> Nullable, creation_date -> Timestamptz, last_modification -> Timestamptz, tags -> Array>, @@ -612,7 +612,7 @@ diesel::table! { start_date -> Nullable, expected_end_date -> Nullable, actual_end_date -> Nullable, - budget -> Int4, + budget -> Nullable, tags -> Array>, #[max_length = 16] state -> Varchar, diff --git a/editoast/src/views/projects.rs b/editoast/src/views/projects.rs index da7cb972b31..42677bdd351 100644 --- a/editoast/src/views/projects.rs +++ b/editoast/src/views/projects.rs @@ -76,8 +76,7 @@ struct ProjectCreateForm { #[serde(default)] #[schema(max_length = 1024)] pub funders: String, - #[serde(default)] - pub budget: i32, + pub budget: Option, /// The id of the image document pub image: Option, #[serde(default)] @@ -269,7 +268,7 @@ impl From for Changeset { .flat_description(project.description) .flat_objectives(project.objectives) .flat_funders(project.funders) - .flat_budget(project.budget) + .flat_budget(Some(project.budget)) .flat_image(Some(project.image)) .flat_tags(project.tags) } diff --git a/editoast/src/views/study.rs b/editoast/src/views/study.rs index bb3ae6b12c5..07450fd888c 100644 --- a/editoast/src/views/study.rs +++ b/editoast/src/views/study.rs @@ -74,8 +74,7 @@ struct StudyCreateForm { pub business_code: String, #[serde(default)] pub service_code: String, - #[serde(default)] - pub budget: i32, + pub budget: Option, #[serde(default)] pub tags: Tags, pub state: String, @@ -328,7 +327,7 @@ impl StudyPatchForm { .flat_start_date(Some(self.start_date)) .flat_expected_end_date(Some(self.expected_end_date)) .flat_actual_end_date(Some(self.actual_end_date)) - .flat_budget(self.budget) + .flat_budget(Some(self.budget)) .flat_tags(self.tags) .flat_state(self.state) .flat_study_type(self.study_type); diff --git a/front/src/applications/operationalStudies/views/Project.tsx b/front/src/applications/operationalStudies/views/Project.tsx index 60d576f0dd7..ba221e7c8b1 100644 --- a/front/src/applications/operationalStudies/views/Project.tsx +++ b/front/src/applications/operationalStudies/views/Project.tsx @@ -240,20 +240,20 @@ export default function Project() { - {(project.funders || (project.budget !== undefined && project.budget !== 0)) && ( + {(project.funders || (project.budget !== 0 && project.budget !== null)) && (

{t('fundedBy')}

{project.funders &&
{project.funders}
}
- {project.budget !== undefined && project.budget !== 0 && ( + {project.budget ? (
{t('totalBudget')} {budgetFormat(project.budget)}
- )} + ) : null}
)}
diff --git a/front/src/applications/operationalStudies/views/Study.tsx b/front/src/applications/operationalStudies/views/Study.tsx index df3789effea..f28de1c19a9 100644 --- a/front/src/applications/operationalStudies/views/Study.tsx +++ b/front/src/applications/operationalStudies/views/Study.tsx @@ -21,7 +21,7 @@ import OptionsSNCF from 'common/BootstrapSNCF/OptionsSNCF'; import { Loader, Spinner } from 'common/Loaders'; import ScenarioCard from 'modules/scenario/components/ScenarioCard'; import ScenarioCardEmpty from 'modules/scenario/components/ScenarioCardEmpty'; -import AddOrEditStudyModal, { type StudyForm } from 'modules/study/components/AddOrEditStudyModal'; +import AddOrEditStudyModal from 'modules/study/components/AddOrEditStudyModal'; import { budgetFormat } from 'utils/numbers'; type SortOptions = @@ -221,15 +221,7 @@ export default function Study() { type="button" onClick={() => openModal( - , + , 'xl', 'no-close-modal' ) @@ -268,7 +260,9 @@ export default function Study() { )}
- {(study.service_code || study.business_code || study.budget !== 0) && ( + {(study.service_code || + study.business_code || + (study.budget !== 0 && study.budget !== null)) && (
{study.service_code && ( @@ -284,12 +278,12 @@ export default function Study() {
)}
- {study.budget !== 0 && ( + {study.budget ? (
{t('budget')} {budgetFormat(study.budget)}
- )} + ) : null} )} diff --git a/front/src/common/api/osrdEditoastApi.ts b/front/src/common/api/osrdEditoastApi.ts index f3122404a37..e2fa14637e7 100644 --- a/front/src/common/api/osrdEditoastApi.ts +++ b/front/src/common/api/osrdEditoastApi.ts @@ -1926,7 +1926,7 @@ export type ElectrificationsOnPathResponse = { }; export type Tags = string[]; export type Project = { - budget: number; + budget?: number | null; creation_date: string; description: string; funders: string; @@ -1958,7 +1958,7 @@ export type Ordering = | 'LastModifiedDesc' | 'LastModifiedAsc'; export type ProjectCreateForm = { - budget?: number; + budget?: number | null; description?: string; funders?: string; /** The id of the image document */ @@ -1979,7 +1979,7 @@ export type ProjectPatchForm = { }; export type Study = { actual_end_date?: string | null; - budget: number; + budget?: number | null; business_code: string; creation_date: string; description: string; @@ -2013,7 +2013,7 @@ export type StudyResponse = Study & { }; export type StudyCreateForm = { actual_end_date?: string | null; - budget?: number; + budget?: number | null; business_code?: string; description?: string; expected_end_date?: string | null; diff --git a/front/src/modules/project/components/AddOrEditProjectModal.tsx b/front/src/modules/project/components/AddOrEditProjectModal.tsx index 41cbf71b0de..1d489a3bec0 100644 --- a/front/src/modules/project/components/AddOrEditProjectModal.tsx +++ b/front/src/modules/project/components/AddOrEditProjectModal.tsx @@ -34,7 +34,7 @@ import useModalFocusTrap from 'utils/hooks/useModalFocusTrap'; import useOutsideClick from 'utils/hooks/useOutsideClick'; const emptyProject: ProjectCreateForm = { - budget: undefined, + budget: null, description: '', funders: '', image: null, @@ -384,12 +384,13 @@ export default function AddOrEditProjectModal({ {t('projectBudget')} } - value={currentProject.budget !== undefined ? currentProject.budget : ''} + value={ + currentProject.budget !== undefined && currentProject.budget !== null + ? currentProject.budget + : '' + } onChange={(e) => - handleProjectInputChange( - 'budget', - e.target.value !== '' ? +e.target.value : undefined - ) + handleProjectInputChange('budget', e.target.value !== '' ? +e.target.value : null) } textRight /> diff --git a/front/src/modules/study/components/AddOrEditStudyModal.tsx b/front/src/modules/study/components/AddOrEditStudyModal.tsx index a9e8ea90753..cf1bebb582e 100644 --- a/front/src/modules/study/components/AddOrEditStudyModal.tsx +++ b/front/src/modules/study/components/AddOrEditStudyModal.tsx @@ -45,7 +45,7 @@ type StudyParams = { const emptyStudy: StudyForm = { actual_end_date: null, - budget: undefined, + budget: null, business_code: '', description: '', expected_end_date: null, @@ -405,12 +405,13 @@ export default function AddOrEditStudyModal({ editionMode, study }: Props) { {t('studyBudget')} } - value={currentStudy.budget !== undefined ? currentStudy.budget : ''} + value={ + currentStudy.budget !== undefined && currentStudy.budget !== null + ? currentStudy.budget + : '' + } onChange={(e) => - handleStudyInputChange( - 'budget', - e.target.value !== '' ? +e.target.value : undefined - ) + handleStudyInputChange('budget', e.target.value !== '' ? +e.target.value : null) } textRight /> diff --git a/front/src/modules/study/components/StudyCard.tsx b/front/src/modules/study/components/StudyCard.tsx index 45f008d145f..6ae15e2f4b6 100644 --- a/front/src/modules/study/components/StudyCard.tsx +++ b/front/src/modules/study/components/StudyCard.tsx @@ -55,7 +55,7 @@ export default function StudyCard({ setFilterChips, study }: StudyCardProps) { )}
{study.description}
- {(study.budget > 0 || study.service_code || study.business_code) && ( + {(study.budget !== 0 || study.service_code || study.business_code) && (
{study.service_code && ( @@ -71,12 +71,12 @@ export default function StudyCard({ setFilterChips, study }: StudyCardProps) {
)}
- {study.budget > 0 && ( + {study.budget ? (
{t('budget')} {budgetFormat(study.budget)}
- )} + ) : null} )}