1use derive_builder::Builder;
10use reqwest::Method;
11use std::borrow::Cow;
12
13use crate::api::{Endpoint, NoPagination, ReturnsJsonResponse};
14
15#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
18pub struct IssuePriorityEssentials {
19 pub id: u64,
21 pub name: String,
23}
24
25impl From<IssuePriority> for IssuePriorityEssentials {
26 fn from(v: IssuePriority) -> Self {
27 Self {
28 id: v.id,
29 name: v.name,
30 }
31 }
32}
33
34impl From<&IssuePriority> for IssuePriorityEssentials {
35 fn from(v: &IssuePriority) -> Self {
36 Self {
37 id: v.id,
38 name: v.name.to_owned(),
39 }
40 }
41}
42
43#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
47pub struct IssuePriority {
48 pub id: u64,
50 pub name: String,
52 pub is_default: bool,
54 pub active: bool,
56}
57
58#[derive(Debug, Clone, Builder)]
60#[builder(setter(strip_option))]
61#[expect(
62 clippy::empty_structs_with_brackets,
63 reason = "derive_builder requires named-field syntax"
64)]
65pub struct ListIssuePriorities {}
66
67impl ReturnsJsonResponse for ListIssuePriorities {}
68impl NoPagination for ListIssuePriorities {}
69
70impl ListIssuePriorities {
71 #[must_use]
73 pub fn builder() -> ListIssuePrioritiesBuilder {
74 ListIssuePrioritiesBuilder::default()
75 }
76}
77
78impl Endpoint for ListIssuePriorities {
79 fn method(&self) -> Method {
80 Method::GET
81 }
82
83 fn endpoint(&self) -> Cow<'static, str> {
84 "enumerations/issue_priorities.json".into()
85 }
86}
87
88#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
90pub struct IssuePrioritiesWrapper<T> {
91 pub issue_priorities: Vec<T>,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
98pub struct TimeEntryActivityEssentials {
99 pub id: u64,
101 pub name: String,
103}
104
105impl From<TimeEntryActivity> for TimeEntryActivityEssentials {
106 fn from(v: TimeEntryActivity) -> Self {
107 Self {
108 id: v.id,
109 name: v.name,
110 }
111 }
112}
113
114impl From<&TimeEntryActivity> for TimeEntryActivityEssentials {
115 fn from(v: &TimeEntryActivity) -> Self {
116 Self {
117 id: v.id,
118 name: v.name.to_owned(),
119 }
120 }
121}
122
123#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
127pub struct TimeEntryActivity {
128 pub id: u64,
130 pub name: String,
132 pub is_default: bool,
134 pub active: bool,
136}
137
138#[derive(Debug, Clone, Builder)]
140#[builder(setter(strip_option))]
141#[expect(
142 clippy::empty_structs_with_brackets,
143 reason = "derive_builder requires named-field syntax"
144)]
145pub struct ListTimeEntryActivities {}
146
147impl ReturnsJsonResponse for ListTimeEntryActivities {}
148impl NoPagination for ListTimeEntryActivities {}
149
150impl ListTimeEntryActivities {
151 #[must_use]
153 pub fn builder() -> ListTimeEntryActivitiesBuilder {
154 ListTimeEntryActivitiesBuilder::default()
155 }
156}
157
158impl Endpoint for ListTimeEntryActivities {
159 fn method(&self) -> Method {
160 Method::GET
161 }
162
163 fn endpoint(&self) -> Cow<'static, str> {
164 "enumerations/time_entry_activities.json".into()
165 }
166}
167
168#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
170pub struct TimeEntryActivitiesWrapper<T> {
171 pub time_entry_activities: Vec<T>,
173}
174
175#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
178pub struct DocumentCategoryEssentials {
179 pub id: u64,
181 pub name: String,
183}
184
185impl From<DocumentCategory> for DocumentCategoryEssentials {
186 fn from(v: DocumentCategory) -> Self {
187 Self {
188 id: v.id,
189 name: v.name,
190 }
191 }
192}
193
194impl From<&DocumentCategory> for DocumentCategoryEssentials {
195 fn from(v: &DocumentCategory) -> Self {
196 Self {
197 id: v.id,
198 name: v.name.to_owned(),
199 }
200 }
201}
202
203#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
207pub struct DocumentCategory {
208 pub id: u64,
210 pub name: String,
212 pub is_default: bool,
214 pub active: bool,
216}
217
218#[derive(Debug, Clone, Builder)]
220#[builder(setter(strip_option))]
221#[expect(
222 clippy::empty_structs_with_brackets,
223 reason = "derive_builder requires named-field syntax"
224)]
225pub struct ListDocumentCategories {}
226
227impl ReturnsJsonResponse for ListDocumentCategories {}
228impl NoPagination for ListDocumentCategories {}
229
230impl ListDocumentCategories {
231 #[must_use]
233 pub fn builder() -> ListDocumentCategoriesBuilder {
234 ListDocumentCategoriesBuilder::default()
235 }
236}
237
238impl Endpoint for ListDocumentCategories {
239 fn method(&self) -> Method {
240 Method::GET
241 }
242
243 fn endpoint(&self) -> Cow<'static, str> {
244 "enumerations/document_categories.json".into()
245 }
246}
247
248#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
250pub struct DocumentCategoriesWrapper<T> {
251 pub document_categories: Vec<T>,
253}
254
255#[cfg(test)]
256mod test {
257 use super::*;
258 use std::error::Error;
259 use tracing_test::traced_test;
260
261 #[traced_test]
262 #[test]
263 fn test_list_issue_priorities_no_pagination() -> Result<(), Box<dyn Error>> {
264 dotenvy::dotenv()?;
265 let redmine = crate::api::Redmine::from_env(
266 reqwest::blocking::Client::builder()
267 .tls_backend_rustls()
268 .build()?,
269 )?;
270 let endpoint = ListIssuePriorities::builder().build()?;
271 redmine.json_response_body::<_, IssuePrioritiesWrapper<IssuePriority>>(&endpoint)?;
272 Ok(())
273 }
274
275 #[traced_test]
276 #[test]
277 fn test_list_time_entry_activities_no_pagination() -> Result<(), Box<dyn Error>> {
278 dotenvy::dotenv()?;
279 let redmine = crate::api::Redmine::from_env(
280 reqwest::blocking::Client::builder()
281 .tls_backend_rustls()
282 .build()?,
283 )?;
284 let endpoint = ListTimeEntryActivities::builder().build()?;
285 redmine
286 .json_response_body::<_, TimeEntryActivitiesWrapper<TimeEntryActivity>>(&endpoint)?;
287 Ok(())
288 }
289
290 #[traced_test]
291 #[test]
292 fn test_list_document_categories_no_pagination() -> Result<(), Box<dyn Error>> {
293 dotenvy::dotenv()?;
294 let redmine = crate::api::Redmine::from_env(
295 reqwest::blocking::Client::builder()
296 .tls_backend_rustls()
297 .build()?,
298 )?;
299 let endpoint = ListDocumentCategories::builder().build()?;
300 redmine.json_response_body::<_, DocumentCategoriesWrapper<DocumentCategory>>(&endpoint)?;
301 Ok(())
302 }
303}