1+ //! Answer management module for the Chaos application.
2+ //!
3+ //! This module provides functionality for managing answers to application questions,
4+ //! including creation, retrieval, updating, and deletion of answers. It supports
5+ //! various question types such as short answer, multiple choice, and ranking questions.
6+
17use crate :: models:: error:: ChaosError ;
28use crate :: models:: question:: QuestionType ;
39use chrono:: { DateTime , Utc } ;
@@ -6,9 +12,11 @@ use snowflake::SnowflakeIdGenerator;
612use sqlx:: { Postgres , Transaction } ;
713use std:: ops:: DerefMut ;
814
9- /// The `Answer` type that will be sent in API responses.
10- ///
11- ///
15+ /// Represents an answer in the system.
16+ ///
17+ /// An answer is a response to a question in an application. The answer data is
18+ /// stored in a type-specific format based on the question type.
19+ ///
1220/// With the chosen `serde` representation and the use of `#[serde(flatten)]`, the JSON for a
1321/// `Answer` will look like this:
1422/// ```json
@@ -23,43 +31,81 @@ use std::ops::DerefMut;
2331/// ```
2432#[ derive( Deserialize , Serialize ) ]
2533pub struct Answer {
34+ /// Unique identifier for the answer
2635 id : i64 ,
36+ /// ID of the question this answer is for
2737 question_id : i64 ,
2838
39+ /// The actual answer data, flattened in serialization
2940 #[ serde( flatten) ]
3041 answer_data : AnswerData ,
3142
43+ /// When the answer was created
3244 created_at : DateTime < Utc > ,
45+ /// When the answer was last updated
3346 updated_at : DateTime < Utc > ,
3447}
3548
49+ /// Data structure for creating a new answer.
50+ ///
51+ /// Contains the question ID and the answer data.
3652#[ derive( Deserialize ) ]
3753pub struct NewAnswer {
54+ /// ID of the question this answer is for
3855 pub question_id : i64 ,
3956
57+ /// The actual answer data, flattened in serialization
4058 #[ serde( flatten) ]
4159 pub answer_data : AnswerData ,
4260}
4361
62+ /// Raw answer data from the database.
63+ ///
64+ /// Contains all fields needed to construct an Answer structure,
65+ /// including the question type and various answer formats.
4466#[ derive( Deserialize , sqlx:: FromRow ) ]
4567pub struct AnswerRawData {
68+ /// Unique identifier for the answer
4669 id : i64 ,
70+ /// ID of the question this answer is for
4771 question_id : i64 ,
72+ /// Type of the question
4873 question_type : QuestionType ,
74+ /// Text answer for short answer questions
4975 short_answer_answer : Option < String > ,
76+ /// Selected options for multiple choice/select questions
5077 multi_option_answers : Option < Vec < i64 > > ,
78+ /// Ranked options for ranking questions
5179 ranking_answers : Option < Vec < i64 > > ,
80+ /// When the answer was created
5281 created_at : DateTime < Utc > ,
82+ /// When the answer was last updated
5383 updated_at : DateTime < Utc > ,
5484}
5585
86+ /// Data structure for identifying an answer by type and application.
5687#[ derive( Deserialize ) ]
5788pub struct AnswerTypeApplicationId {
89+ /// Type of the question
5890 question_type : QuestionType ,
91+ /// ID of the application this answer belongs to
5992 application_id : i64 ,
6093}
6194
6295impl Answer {
96+ /// Creates a new answer.
97+ ///
98+ /// # Arguments
99+ ///
100+ /// * `application_id` - ID of the application this answer belongs to
101+ /// * `question_id` - ID of the question being answered
102+ /// * `answer_data` - The answer data
103+ /// * `snowflake_generator` - Generator for creating unique IDs
104+ /// * `transaction` - Database transaction to use
105+ ///
106+ /// # Returns
107+ ///
108+ /// * `Result<i64, ChaosError>` - ID of the created answer or error
63109 pub async fn create (
64110 application_id : i64 ,
65111 question_id : i64 ,
@@ -88,6 +134,16 @@ impl Answer {
88134 Ok ( id)
89135 }
90136
137+ /// Retrieves an answer by its ID.
138+ ///
139+ /// # Arguments
140+ ///
141+ /// * `id` - ID of the answer to retrieve
142+ /// * `transaction` - Database transaction to use
143+ ///
144+ /// # Returns
145+ ///
146+ /// * `Result<Answer, ChaosError>` - Answer details or error
91147 pub async fn get (
92148 id : i64 ,
93149 transaction : & mut Transaction < ' _ , Postgres > ,
@@ -146,6 +202,18 @@ impl Answer {
146202 } )
147203 }
148204
205+ /// Retrieves all common answers for an application.
206+ ///
207+ /// Common answers are those that apply to all roles in the application.
208+ ///
209+ /// # Arguments
210+ ///
211+ /// * `application_id` - ID of the application to get answers for
212+ /// * `transaction` - Database transaction to use
213+ ///
214+ /// # Returns
215+ ///
216+ /// * `Result<Vec<Answer>, ChaosError>` - List of answers or error
149217 pub async fn get_all_common_by_application (
150218 application_id : i64 ,
151219 transaction : & mut Transaction < ' _ , Postgres > ,
@@ -211,6 +279,17 @@ impl Answer {
211279 Ok ( answers)
212280 }
213281
282+ /// Retrieves all answers for an application and role.
283+ ///
284+ /// # Arguments
285+ ///
286+ /// * `application_id` - ID of the application to get answers for
287+ /// * `role_id` - ID of the role to get answers for
288+ /// * `transaction` - Database transaction to use
289+ ///
290+ /// # Returns
291+ ///
292+ /// * `Result<Vec<Answer>, ChaosError>` - List of answers or error
214293 pub async fn get_all_by_application_and_role (
215294 application_id : i64 ,
216295 role_id : i64 ,
@@ -279,6 +358,17 @@ impl Answer {
279358 Ok ( answers)
280359 }
281360
361+ /// Updates an existing answer.
362+ ///
363+ /// # Arguments
364+ ///
365+ /// * `id` - ID of the answer to update
366+ /// * `answer_data` - New answer data
367+ /// * `transaction` - Database transaction to use
368+ ///
369+ /// # Returns
370+ ///
371+ /// * `Result<(), ChaosError>` - Success or error
282372 pub async fn update (
283373 id : i64 ,
284374 answer_data : AnswerData ,
@@ -315,6 +405,16 @@ impl Answer {
315405 Ok ( ( ) )
316406 }
317407
408+ /// Deletes an answer.
409+ ///
410+ /// # Arguments
411+ ///
412+ /// * `id` - ID of the answer to delete
413+ /// * `transaction` - Database transaction to use
414+ ///
415+ /// # Returns
416+ ///
417+ /// * `Result<(), ChaosError>` - Success or error
318418 pub async fn delete (
319419 id : i64 ,
320420 transaction : & mut Transaction < ' _ , Postgres > ,
@@ -327,17 +427,34 @@ impl Answer {
327427 }
328428}
329429
430+ /// Represents the different types of answer data.
431+ ///
432+ /// Each variant corresponds to a different question type and contains
433+ /// the appropriate data format for that type.
330434#[ derive( Deserialize , Serialize ) ]
331- #[ serde( tag = "answer_type" , content = "data" ) ]
332435pub enum AnswerData {
436+ /// Text answer for short answer questions
333437 ShortAnswer ( String ) ,
438+ /// Single selected option for multiple choice questions
334439 MultiChoice ( i64 ) ,
440+ /// Multiple selected options for multi-select questions
335441 MultiSelect ( Vec < i64 > ) ,
442+ /// Single selected option for dropdown questions
336443 DropDown ( i64 ) ,
444+ /// Ranked list of options for ranking questions
337445 Ranking ( Vec < i64 > ) ,
338446}
339447
340448impl AnswerData {
449+ /// Creates a new AnswerData instance based on a question type.
450+ ///
451+ /// # Arguments
452+ ///
453+ /// * `question_type` - Type of the question
454+ ///
455+ /// # Returns
456+ ///
457+ /// * `AnswerData` - New answer data instance
341458 fn from_question_type ( question_type : & QuestionType ) -> Self {
342459 match question_type {
343460 QuestionType :: ShortAnswer => AnswerData :: ShortAnswer ( "" . to_string ( ) ) ,
@@ -348,6 +465,18 @@ impl AnswerData {
348465 }
349466 }
350467
468+ /// Creates an AnswerData instance from raw database data.
469+ ///
470+ /// # Arguments
471+ ///
472+ /// * `question_type` - Type of the question
473+ /// * `short_answer_answer` - Text answer for short answer questions
474+ /// * `multi_option_answers` - Selected options for multiple choice/select questions
475+ /// * `ranking_answers` - Ranked options for ranking questions
476+ ///
477+ /// # Returns
478+ ///
479+ /// * `AnswerData` - New answer data instance
351480 fn from_answer_raw_data (
352481 question_type : QuestionType ,
353482 short_answer_answer : Option < String > ,
@@ -378,6 +507,11 @@ impl AnswerData {
378507 }
379508 }
380509
510+ /// Validates the answer data.
511+ ///
512+ /// # Returns
513+ ///
514+ /// * `Result<(), ChaosError>` - Success if valid, error if not
381515 pub fn validate ( & self ) -> Result < ( ) , ChaosError > {
382516 match self {
383517 Self :: ShortAnswer ( text) => {
@@ -396,6 +530,16 @@ impl AnswerData {
396530 Ok ( ( ) )
397531 }
398532
533+ /// Inserts the answer data into the database.
534+ ///
535+ /// # Arguments
536+ ///
537+ /// * `answer_id` - ID of the answer to insert data for
538+ /// * `transaction` - Database transaction to use
539+ ///
540+ /// # Returns
541+ ///
542+ /// * `Result<(), ChaosError>` - Success or error
399543 pub async fn insert_into_db (
400544 self ,
401545 answer_id : i64 ,
@@ -457,6 +601,16 @@ impl AnswerData {
457601 }
458602 }
459603
604+ /// Deletes the answer data from the database.
605+ ///
606+ /// # Arguments
607+ ///
608+ /// * `answer_id` - ID of the answer to delete data for
609+ /// * `transaction` - Database transaction to use
610+ ///
611+ /// # Returns
612+ ///
613+ /// * `Result<(), ChaosError>` - Success or error
460614 pub async fn delete_from_db (
461615 self ,
462616 answer_id : i64 ,
0 commit comments