thoth_api/work/
model.rs

1use chrono::naive::NaiveDate;
2use serde::{Deserialize, Serialize};
3use std::fmt;
4use std::str::FromStr;
5use uuid::Uuid;
6
7use crate::errors::ThothError;
8#[cfg(feature = "backend")]
9use crate::schema::work;
10
11#[cfg_attr(feature = "backend", derive(DbEnum, juniper::GraphQLEnum))]
12#[cfg_attr(feature = "backend", DieselType = "Work_type")]
13#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
14#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
15pub enum WorkType {
16    #[cfg_attr(feature = "backend", db_rename = "book-chapter")]
17    BookChapter,
18    Monograph,
19    #[cfg_attr(feature = "backend", db_rename = "edited-book")]
20    EditedBook,
21    Textbook,
22    #[cfg_attr(feature = "backend", db_rename = "journal-issue")]
23    JournalIssue,
24    #[cfg_attr(feature = "backend", db_rename = "book-set")]
25    BookSet,
26}
27
28#[cfg_attr(feature = "backend", derive(DbEnum, juniper::GraphQLEnum))]
29#[cfg_attr(feature = "backend", DieselType = "Work_status")]
30#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
31#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
32pub enum WorkStatus {
33    Unspecified,
34    Cancelled,
35    Forthcoming,
36    #[cfg_attr(feature = "backend", db_rename = "postponed-indefinitely")]
37    PostponedIndefinitely,
38    Active,
39    #[cfg_attr(feature = "backend", db_rename = "no-longer-our-product")]
40    NoLongerOurProduct,
41    #[cfg_attr(feature = "backend", db_rename = "out-of-stock-indefinitely")]
42    OutOfStockIndefinitely,
43    #[cfg_attr(feature = "backend", db_rename = "out-of-print")]
44    OutOfPrint,
45    Inactive,
46    Unknown,
47    Remaindered,
48    #[cfg_attr(feature = "backend", db_rename = "withdrawn-from-sale")]
49    WithdrawnFromSale,
50    Recalled,
51}
52
53#[cfg_attr(feature = "backend", derive(Queryable))]
54pub struct Work {
55    pub work_id: Uuid,
56    pub work_type: WorkType,
57    pub work_status: WorkStatus,
58    pub full_title: String,
59    pub title: String,
60    pub subtitle: Option<String>,
61    pub reference: Option<String>,
62    pub edition: i32,
63    pub imprint_id: Uuid,
64    pub doi: Option<String>,
65    pub publication_date: Option<NaiveDate>,
66    pub place: Option<String>,
67    pub width: Option<i32>,
68    pub height: Option<i32>,
69    pub page_count: Option<i32>,
70    pub page_breakdown: Option<String>,
71    pub image_count: Option<i32>,
72    pub table_count: Option<i32>,
73    pub audio_count: Option<i32>,
74    pub video_count: Option<i32>,
75    pub license: Option<String>,
76    pub copyright_holder: String,
77    pub landing_page: Option<String>,
78    pub lccn: Option<i32>,
79    pub oclc: Option<i32>,
80    pub short_abstract: Option<String>,
81    pub long_abstract: Option<String>,
82    pub general_note: Option<String>,
83    pub toc: Option<String>,
84    pub cover_url: Option<String>,
85    pub cover_caption: Option<String>,
86}
87
88#[cfg_attr(
89    feature = "backend",
90    derive(juniper::GraphQLInputObject, Insertable),
91    table_name = "work"
92)]
93pub struct NewWork {
94    pub work_type: WorkType,
95    pub work_status: WorkStatus,
96    pub full_title: String,
97    pub title: String,
98    pub subtitle: Option<String>,
99    pub reference: Option<String>,
100    pub edition: i32,
101    pub imprint_id: Uuid,
102    pub doi: Option<String>,
103    pub publication_date: Option<NaiveDate>,
104    pub place: Option<String>,
105    pub width: Option<i32>,
106    pub height: Option<i32>,
107    pub page_count: Option<i32>,
108    pub page_breakdown: Option<String>,
109    pub image_count: Option<i32>,
110    pub table_count: Option<i32>,
111    pub audio_count: Option<i32>,
112    pub video_count: Option<i32>,
113    pub license: Option<String>,
114    pub copyright_holder: String,
115    pub landing_page: Option<String>,
116    pub lccn: Option<i32>,
117    pub oclc: Option<i32>,
118    pub short_abstract: Option<String>,
119    pub long_abstract: Option<String>,
120    pub general_note: Option<String>,
121    pub toc: Option<String>,
122    pub cover_url: Option<String>,
123    pub cover_caption: Option<String>,
124}
125
126#[cfg_attr(
127    feature = "backend",
128    derive(juniper::GraphQLInputObject, AsChangeset),
129    changeset_options(treat_none_as_null = "true"),
130    table_name = "work"
131)]
132pub struct PatchWork {
133    pub work_id: Uuid,
134    pub work_type: WorkType,
135    pub work_status: WorkStatus,
136    pub full_title: String,
137    pub title: String,
138    pub subtitle: Option<String>,
139    pub reference: Option<String>,
140    pub edition: i32,
141    pub imprint_id: Uuid,
142    pub doi: Option<String>,
143    pub publication_date: Option<NaiveDate>,
144    pub place: Option<String>,
145    pub width: Option<i32>,
146    pub height: Option<i32>,
147    pub page_count: Option<i32>,
148    pub page_breakdown: Option<String>,
149    pub image_count: Option<i32>,
150    pub table_count: Option<i32>,
151    pub audio_count: Option<i32>,
152    pub video_count: Option<i32>,
153    pub license: Option<String>,
154    pub copyright_holder: String,
155    pub landing_page: Option<String>,
156    pub lccn: Option<i32>,
157    pub oclc: Option<i32>,
158    pub short_abstract: Option<String>,
159    pub long_abstract: Option<String>,
160    pub general_note: Option<String>,
161    pub toc: Option<String>,
162    pub cover_url: Option<String>,
163    pub cover_caption: Option<String>,
164}
165
166impl Default for WorkType {
167    fn default() -> WorkType {
168        WorkType::Monograph
169    }
170}
171
172impl Default for WorkStatus {
173    fn default() -> WorkStatus {
174        WorkStatus::Inactive
175    }
176}
177
178impl fmt::Display for WorkType {
179    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
180        match self {
181            WorkType::BookChapter => write!(f, "Book Chapter"),
182            WorkType::Monograph => write!(f, "Monograph"),
183            WorkType::EditedBook => write!(f, "Edited Book"),
184            WorkType::Textbook => write!(f, "Textbook"),
185            WorkType::JournalIssue => write!(f, "Journal Issue"),
186            WorkType::BookSet => write!(f, "Book Set"),
187        }
188    }
189}
190
191impl FromStr for WorkType {
192    type Err = ThothError;
193
194    fn from_str(input: &str) -> Result<WorkType, ThothError> {
195        match input {
196            "Book Chapter" => Ok(WorkType::BookChapter),
197            "Monograph" => Ok(WorkType::Monograph),
198            "Edited Book" => Ok(WorkType::EditedBook),
199            "Textbook" => Ok(WorkType::Textbook),
200            "Journal Issue" => Ok(WorkType::JournalIssue),
201            "Book Set" => Ok(WorkType::BookSet),
202            _ => Err(ThothError::InvalidWorkType(input.to_string())),
203        }
204    }
205}
206
207impl fmt::Display for WorkStatus {
208    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
209        match self {
210            WorkStatus::Unspecified => write!(f, "Unspecified"),
211            WorkStatus::Cancelled => write!(f, "Cancelled"),
212            WorkStatus::Forthcoming => write!(f, "Forthcoming"),
213            WorkStatus::PostponedIndefinitely => write!(f, "Postponed Indefinitely"),
214            WorkStatus::Active => write!(f, "Active"),
215            WorkStatus::NoLongerOurProduct => write!(f, "No Longer Our Product"),
216            WorkStatus::OutOfStockIndefinitely => write!(f, "Out Of Stock Indefinitely"),
217            WorkStatus::OutOfPrint => write!(f, "Out Of Print"),
218            WorkStatus::Inactive => write!(f, "Inactive"),
219            WorkStatus::Unknown => write!(f, "Unknown"),
220            WorkStatus::Remaindered => write!(f, "Remaindered"),
221            WorkStatus::WithdrawnFromSale => write!(f, "Withdrawn From Sale"),
222            WorkStatus::Recalled => write!(f, "Recalled"),
223        }
224    }
225}
226
227impl FromStr for WorkStatus {
228    type Err = ThothError;
229
230    fn from_str(input: &str) -> Result<WorkStatus, ThothError> {
231        match input {
232            "Unspecified" => Ok(WorkStatus::Unspecified),
233            "Cancelled" => Ok(WorkStatus::Cancelled),
234            "Forthcoming" => Ok(WorkStatus::Forthcoming),
235            "Postponed Indefinitely" => Ok(WorkStatus::PostponedIndefinitely),
236            "Active" => Ok(WorkStatus::Active),
237            "No Longer Our Product" => Ok(WorkStatus::NoLongerOurProduct),
238            "Out Of Stock Indefinitely" => Ok(WorkStatus::OutOfStockIndefinitely),
239            "Out Of Print" => Ok(WorkStatus::OutOfPrint),
240            "Inactive" => Ok(WorkStatus::Inactive),
241            "Unknown" => Ok(WorkStatus::Unknown),
242            "Remaindered" => Ok(WorkStatus::Remaindered),
243            "Withdrawn From Sale" => Ok(WorkStatus::WithdrawnFromSale),
244            "Recalled" => Ok(WorkStatus::Recalled),
245            _ => Err(ThothError::InvalidWorkStatus(input.to_string())),
246        }
247    }
248}
249
250#[test]
251fn test_worktype_default() {
252    let worktype: WorkType = Default::default();
253    assert_eq!(worktype, WorkType::Monograph);
254}
255
256#[test]
257fn test_workstatus_default() {
258    let workstatus: WorkStatus = Default::default();
259    assert_eq!(workstatus, WorkStatus::Inactive);
260}
261
262#[test]
263fn test_worktype_display() {
264    assert_eq!(format!("{}", WorkType::BookChapter), "Book Chapter");
265    assert_eq!(format!("{}", WorkType::Monograph), "Monograph");
266    assert_eq!(format!("{}", WorkType::EditedBook), "Edited Book");
267    assert_eq!(format!("{}", WorkType::Textbook), "Textbook");
268    assert_eq!(format!("{}", WorkType::JournalIssue), "Journal Issue");
269    assert_eq!(format!("{}", WorkType::BookSet), "Book Set");
270}
271
272#[test]
273fn test_workstatus_display() {
274    assert_eq!(format!("{}", WorkStatus::Cancelled), "Cancelled");
275    assert_eq!(format!("{}", WorkStatus::Forthcoming), "Forthcoming");
276    assert_eq!(
277        format!("{}", WorkStatus::PostponedIndefinitely),
278        "Postponed Indefinitely"
279    );
280    assert_eq!(format!("{}", WorkStatus::Active), "Active");
281    assert_eq!(
282        format!("{}", WorkStatus::NoLongerOurProduct),
283        "No Longer Our Product"
284    );
285    assert_eq!(
286        format!("{}", WorkStatus::OutOfStockIndefinitely),
287        "Out Of Stock Indefinitely"
288    );
289    assert_eq!(format!("{}", WorkStatus::OutOfPrint), "Out Of Print");
290    assert_eq!(format!("{}", WorkStatus::Inactive), "Inactive");
291    assert_eq!(format!("{}", WorkStatus::Unknown), "Unknown");
292    assert_eq!(format!("{}", WorkStatus::Remaindered), "Remaindered");
293    assert_eq!(
294        format!("{}", WorkStatus::WithdrawnFromSale),
295        "Withdrawn From Sale"
296    );
297    assert_eq!(format!("{}", WorkStatus::Recalled), "Recalled");
298}
299
300#[test]
301fn test_worktype_fromstr() {
302    assert_eq!(
303        WorkType::from_str("Book Chapter").unwrap(),
304        WorkType::BookChapter
305    );
306    assert_eq!(
307        WorkType::from_str("Monograph").unwrap(),
308        WorkType::Monograph
309    );
310    assert_eq!(
311        WorkType::from_str("Edited Book").unwrap(),
312        WorkType::EditedBook
313    );
314    assert_eq!(WorkType::from_str("Textbook").unwrap(), WorkType::Textbook);
315    assert_eq!(
316        WorkType::from_str("Journal Issue").unwrap(),
317        WorkType::JournalIssue
318    );
319    assert_eq!(WorkType::from_str("Book Set").unwrap(), WorkType::BookSet);
320
321    assert!(WorkType::from_str("Book Section").is_err());
322    assert!(WorkType::from_str("Manuscript").is_err());
323}
324
325#[test]
326fn test_workstatus_fromstr() {
327    assert_eq!(
328        WorkStatus::from_str("Unspecified").unwrap(),
329        WorkStatus::Unspecified
330    );
331    assert_eq!(
332        WorkStatus::from_str("Cancelled").unwrap(),
333        WorkStatus::Cancelled
334    );
335    assert_eq!(
336        WorkStatus::from_str("Forthcoming").unwrap(),
337        WorkStatus::Forthcoming
338    );
339    assert_eq!(
340        WorkStatus::from_str("Postponed Indefinitely").unwrap(),
341        WorkStatus::PostponedIndefinitely
342    );
343    assert_eq!(WorkStatus::from_str("Active").unwrap(), WorkStatus::Active);
344    assert_eq!(
345        WorkStatus::from_str("No Longer Our Product").unwrap(),
346        WorkStatus::NoLongerOurProduct
347    );
348    assert_eq!(
349        WorkStatus::from_str("Out Of Stock Indefinitely").unwrap(),
350        WorkStatus::OutOfStockIndefinitely
351    );
352    assert_eq!(
353        WorkStatus::from_str("Out Of Print").unwrap(),
354        WorkStatus::OutOfPrint
355    );
356    assert_eq!(
357        WorkStatus::from_str("Inactive").unwrap(),
358        WorkStatus::Inactive
359    );
360    assert_eq!(
361        WorkStatus::from_str("Unknown").unwrap(),
362        WorkStatus::Unknown
363    );
364    assert_eq!(
365        WorkStatus::from_str("Remaindered").unwrap(),
366        WorkStatus::Remaindered
367    );
368    assert_eq!(
369        WorkStatus::from_str("Withdrawn From Sale").unwrap(),
370        WorkStatus::WithdrawnFromSale
371    );
372    assert_eq!(
373        WorkStatus::from_str("Recalled").unwrap(),
374        WorkStatus::Recalled
375    );
376
377    assert!(WorkStatus::from_str("Published").is_err());
378    assert!(WorkStatus::from_str("Unpublished").is_err());
379}