1use anyhow::Result;
2
3use crate::Client;
4#[derive(Clone, Debug)]
5pub struct TimeEntries {
6 pub client: Client,
7}
8
9impl TimeEntries {
10 #[doc(hidden)]
11 pub fn new(client: Client) -> Self {
12 Self { client }
13 }
14
15 #[doc = "List time cards\n\nA List of time cards\n- Requires: `API Tier 2`\n- Filterable fields: `pay_period.start_date`, `worker_id`\n- Expandable fields: `worker`\n- Sortable fields: `id`, `created_at`, `updated_at`\n\n**Parameters:**\n\n- `cursor: Option<String>`\n- `expand: Option<String>`\n- `filter: Option<String>`\n- `order_by: Option<String>`\n\n```rust,no_run\nuse futures_util::TryStreamExt;\nasync fn example_time_entries_list_time_cards_stream() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let mut time_entries = client.time_entries();\n let mut stream = time_entries.list_time_cards_stream(\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n );\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
16 #[tracing::instrument]
17 pub async fn list_time_cards<'a>(
18 &'a self,
19 cursor: Option<String>,
20 expand: Option<String>,
21 filter: Option<String>,
22 order_by: Option<String>,
23 ) -> Result<crate::types::ListTimeCardsResponse, crate::types::error::Error> {
24 let mut req = self.client.client.request(
25 http::Method::GET,
26 format!("{}/{}", self.client.base_url, "time-cards"),
27 );
28 req = req.bearer_auth(&self.client.token);
29 let mut query_params = vec![];
30 if let Some(p) = cursor {
31 query_params.push(("cursor", p));
32 }
33
34 if let Some(p) = expand {
35 query_params.push(("expand", p));
36 }
37
38 if let Some(p) = filter {
39 query_params.push(("filter", p));
40 }
41
42 if let Some(p) = order_by {
43 query_params.push(("order_by", p));
44 }
45
46 req = req.query(&query_params);
47 let resp = req.send().await?;
48 let status = resp.status();
49 if status.is_success() {
50 let text = resp.text().await.unwrap_or_default();
51 serde_json::from_str(&text).map_err(|err| {
52 crate::types::error::Error::from_serde_error(
53 format_serde_error::SerdeError::new(text.to_string(), err),
54 status,
55 )
56 })
57 } else {
58 let text = resp.text().await.unwrap_or_default();
59 Err(crate::types::error::Error::Server {
60 body: text.to_string(),
61 status,
62 })
63 }
64 }
65
66 #[doc = "List time cards\n\nA List of time cards\n- Requires: `API Tier 2`\n- Filterable fields: `pay_period.start_date`, `worker_id`\n- Expandable fields: `worker`\n- Sortable fields: `id`, `created_at`, `updated_at`\n\n**Parameters:**\n\n- `cursor: Option<String>`\n- `expand: Option<String>`\n- `filter: Option<String>`\n- `order_by: Option<String>`\n\n```rust,no_run\nuse futures_util::TryStreamExt;\nasync fn example_time_entries_list_time_cards_stream() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let mut time_entries = client.time_entries();\n let mut stream = time_entries.list_time_cards_stream(\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n );\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
67 #[tracing::instrument]
68 #[cfg(not(feature = "js"))]
69 pub fn list_time_cards_stream<'a>(
70 &'a self,
71 expand: Option<String>,
72 filter: Option<String>,
73 order_by: Option<String>,
74 ) -> impl futures::Stream<Item = Result<crate::types::TimeCard, crate::types::error::Error>>
75 + Unpin
76 + '_ {
77 use futures::{StreamExt, TryFutureExt, TryStreamExt};
78
79 use crate::types::paginate::Pagination;
80 self.list_time_cards(None, expand, filter, order_by)
81 .map_ok(move |result| {
82 let items = futures::stream::iter(result.items().into_iter().map(Ok));
83 let next_pages = futures::stream::try_unfold(
84 (None, result),
85 move |(prev_page_token, new_result)| async move {
86 if new_result.has_more_pages()
87 && !new_result.items().is_empty()
88 && prev_page_token != new_result.next_page_token()
89 {
90 async {
91 let mut req = self.client.client.request(
92 http::Method::GET,
93 format!("{}/{}", self.client.base_url, "time-cards"),
94 );
95 req = req.bearer_auth(&self.client.token);
96 let mut request = req.build()?;
97 request = new_result.next_page(request)?;
98 let resp = self.client.client.execute(request).await?;
99 let status = resp.status();
100 if status.is_success() {
101 let text = resp.text().await.unwrap_or_default();
102 serde_json::from_str(&text).map_err(|err| {
103 crate::types::error::Error::from_serde_error(
104 format_serde_error::SerdeError::new(
105 text.to_string(),
106 err,
107 ),
108 status,
109 )
110 })
111 } else {
112 let text = resp.text().await.unwrap_or_default();
113 Err(crate::types::error::Error::Server {
114 body: text.to_string(),
115 status,
116 })
117 }
118 }
119 .map_ok(|result: crate::types::ListTimeCardsResponse| {
120 Some((
121 futures::stream::iter(result.items().into_iter().map(Ok)),
122 (new_result.next_page_token(), result),
123 ))
124 })
125 .await
126 } else {
127 Ok(None)
128 }
129 },
130 )
131 .try_flatten();
132 items.chain(next_pages)
133 })
134 .try_flatten_stream()
135 .boxed()
136 }
137
138 #[doc = "Retrieve a specific time card\n\nRetrieve a specific time \
139 card\n\n**Parameters:**\n\n- `expand: Option<String>`\n- `id: &'astr`: ID of the \
140 resource to return (required)\n\n```rust,no_run\nasync fn \
141 example_time_entries_get_time_cards() -> anyhow::Result<()> {\n let client = \
142 rippling_api::Client::new_from_env();\n let result: \
143 rippling_api::types::GetTimeCardsResponse = client\n .time_entries()\n \
144 .get_time_cards(\n Some(\"some-string\".to_string()),\n \
145 \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )\n .await?;\n \
146 println!(\"{:?}\", result);\n Ok(())\n}\n```"]
147 #[tracing::instrument]
148 pub async fn get_time_cards<'a>(
149 &'a self,
150 expand: Option<String>,
151 id: &'a str,
152 ) -> Result<crate::types::GetTimeCardsResponse, crate::types::error::Error> {
153 let mut req = self.client.client.request(
154 http::Method::GET,
155 format!(
156 "{}/{}",
157 self.client.base_url,
158 "time-cards/{id}".replace("{id}", id)
159 ),
160 );
161 req = req.bearer_auth(&self.client.token);
162 let mut query_params = vec![];
163 if let Some(p) = expand {
164 query_params.push(("expand", p));
165 }
166
167 req = req.query(&query_params);
168 let resp = req.send().await?;
169 let status = resp.status();
170 if status.is_success() {
171 let text = resp.text().await.unwrap_or_default();
172 serde_json::from_str(&text).map_err(|err| {
173 crate::types::error::Error::from_serde_error(
174 format_serde_error::SerdeError::new(text.to_string(), err),
175 status,
176 )
177 })
178 } else {
179 let text = resp.text().await.unwrap_or_default();
180 Err(crate::types::error::Error::Server {
181 body: text.to_string(),
182 status,
183 })
184 }
185 }
186
187 #[doc = "List time entries\n\nA List of time entries\n- Requires: `API Tier 2`\n- Filterable fields: `worker_id`, `start_time`, `pay_period.start_date`\n- Expandable fields: `worker`, `time_card`\n- Sortable fields: `id`, `created_at`, `updated_at`\n\n**Parameters:**\n\n- `cursor: Option<String>`\n- `expand: Option<String>`\n- `filter: Option<String>`\n- `order_by: Option<String>`\n\n```rust,no_run\nuse futures_util::TryStreamExt;\nasync fn example_time_entries_list_stream() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let mut time_entries = client.time_entries();\n let mut stream = time_entries.list_stream(\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n );\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
188 #[tracing::instrument]
189 pub async fn list<'a>(
190 &'a self,
191 cursor: Option<String>,
192 expand: Option<String>,
193 filter: Option<String>,
194 order_by: Option<String>,
195 ) -> Result<crate::types::ListTimeEntriesResponse, crate::types::error::Error> {
196 let mut req = self.client.client.request(
197 http::Method::GET,
198 format!("{}/{}", self.client.base_url, "time-entries"),
199 );
200 req = req.bearer_auth(&self.client.token);
201 let mut query_params = vec![];
202 if let Some(p) = cursor {
203 query_params.push(("cursor", p));
204 }
205
206 if let Some(p) = expand {
207 query_params.push(("expand", p));
208 }
209
210 if let Some(p) = filter {
211 query_params.push(("filter", p));
212 }
213
214 if let Some(p) = order_by {
215 query_params.push(("order_by", p));
216 }
217
218 req = req.query(&query_params);
219 let resp = req.send().await?;
220 let status = resp.status();
221 if status.is_success() {
222 let text = resp.text().await.unwrap_or_default();
223 serde_json::from_str(&text).map_err(|err| {
224 crate::types::error::Error::from_serde_error(
225 format_serde_error::SerdeError::new(text.to_string(), err),
226 status,
227 )
228 })
229 } else {
230 let text = resp.text().await.unwrap_or_default();
231 Err(crate::types::error::Error::Server {
232 body: text.to_string(),
233 status,
234 })
235 }
236 }
237
238 #[doc = "List time entries\n\nA List of time entries\n- Requires: `API Tier 2`\n- Filterable fields: `worker_id`, `start_time`, `pay_period.start_date`\n- Expandable fields: `worker`, `time_card`\n- Sortable fields: `id`, `created_at`, `updated_at`\n\n**Parameters:**\n\n- `cursor: Option<String>`\n- `expand: Option<String>`\n- `filter: Option<String>`\n- `order_by: Option<String>`\n\n```rust,no_run\nuse futures_util::TryStreamExt;\nasync fn example_time_entries_list_stream() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let mut time_entries = client.time_entries();\n let mut stream = time_entries.list_stream(\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n Some(\"some-string\".to_string()),\n );\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
239 #[tracing::instrument]
240 #[cfg(not(feature = "js"))]
241 pub fn list_stream<'a>(
242 &'a self,
243 expand: Option<String>,
244 filter: Option<String>,
245 order_by: Option<String>,
246 ) -> impl futures::Stream<Item = Result<crate::types::TimeEntry, crate::types::error::Error>>
247 + Unpin
248 + '_ {
249 use futures::{StreamExt, TryFutureExt, TryStreamExt};
250
251 use crate::types::paginate::Pagination;
252 self.list(None, expand, filter, order_by)
253 .map_ok(move |result| {
254 let items = futures::stream::iter(result.items().into_iter().map(Ok));
255 let next_pages = futures::stream::try_unfold(
256 (None, result),
257 move |(prev_page_token, new_result)| async move {
258 if new_result.has_more_pages()
259 && !new_result.items().is_empty()
260 && prev_page_token != new_result.next_page_token()
261 {
262 async {
263 let mut req = self.client.client.request(
264 http::Method::GET,
265 format!("{}/{}", self.client.base_url, "time-entries"),
266 );
267 req = req.bearer_auth(&self.client.token);
268 let mut request = req.build()?;
269 request = new_result.next_page(request)?;
270 let resp = self.client.client.execute(request).await?;
271 let status = resp.status();
272 if status.is_success() {
273 let text = resp.text().await.unwrap_or_default();
274 serde_json::from_str(&text).map_err(|err| {
275 crate::types::error::Error::from_serde_error(
276 format_serde_error::SerdeError::new(
277 text.to_string(),
278 err,
279 ),
280 status,
281 )
282 })
283 } else {
284 let text = resp.text().await.unwrap_or_default();
285 Err(crate::types::error::Error::Server {
286 body: text.to_string(),
287 status,
288 })
289 }
290 }
291 .map_ok(|result: crate::types::ListTimeEntriesResponse| {
292 Some((
293 futures::stream::iter(result.items().into_iter().map(Ok)),
294 (new_result.next_page_token(), result),
295 ))
296 })
297 .await
298 } else {
299 Ok(None)
300 }
301 },
302 )
303 .try_flatten();
304 items.chain(next_pages)
305 })
306 .try_flatten_stream()
307 .boxed()
308 }
309
310 #[doc = "Create a new time entry\n\nCreate a new time entry\n\n```rust,no_run\nasync fn example_time_entries_create() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let result: rippling_api::types::TimeEntry = client\n .time_entries()\n .create(&rippling_api::types::TimeEntryRequest {\n worker_id: \"some-string\".to_string(),\n duration: Some(3.14 as f64),\n comments: Some(vec![rippling_api::types::TimeEntryCommentRequest {\n text: Some(\"some-string\".to_string()),\n }]),\n job_shifts: Some(vec![rippling_api::types::JobShiftRequest {\n start_time: Some(\"some-string\".to_string()),\n end_time: Some(\"some-string\".to_string()),\n duration: Some(3.14 as f64),\n start_date: Some(\"some-string\".to_string()),\n original_start_time: Some(\"some-string\".to_string()),\n original_end_time: Some(\"some-string\".to_string()),\n job_codes_id: Some(vec![\"some-string\".to_string()]),\n is_hours_only_input: Some(true),\n }]),\n breaks: Some(vec![rippling_api::types::BreakRequest {\n start_time: Some(\"some-string\".to_string()),\n end_time: Some(\"some-string\".to_string()),\n break_type_id: Some(\"some-string\".to_string()),\n }]),\n tags: Some(vec![\"some-string\".to_string()]),\n idempotency_key: Some(\"some-string\".to_string()),\n create_extra_hours_run: Some(true),\n status: Some(rippling_api::types::TimeEntryRequestStatus::Paid),\n pay_period: Some(rippling_api::types::PayPeriodRequest {\n start_date: Some(\"some-string\".to_string()),\n end_date: Some(\"some-string\".to_string()),\n pay_schedule_id: Some(\"some-string\".to_string()),\n }),\n shift_input_values: Some(vec![rippling_api::types::ShiftInputValueRequest {\n shift_input_id: \"some-string\".to_string(),\n author_id: Some(\"some-string\".to_string()),\n }]),\n })\n .await?;\n println!(\"{:?}\", result);\n Ok(())\n}\n```"]
311 #[tracing::instrument]
312 pub async fn create<'a>(
313 &'a self,
314 body: &crate::types::TimeEntryRequest,
315 ) -> Result<crate::types::TimeEntry, crate::types::error::Error> {
316 let mut req = self.client.client.request(
317 http::Method::POST,
318 format!("{}/{}", self.client.base_url, "time-entries"),
319 );
320 req = req.bearer_auth(&self.client.token);
321 req = req.json(body);
322 let resp = req.send().await?;
323 let status = resp.status();
324 if status.is_success() {
325 let text = resp.text().await.unwrap_or_default();
326 serde_json::from_str(&text).map_err(|err| {
327 crate::types::error::Error::from_serde_error(
328 format_serde_error::SerdeError::new(text.to_string(), err),
329 status,
330 )
331 })
332 } else {
333 let text = resp.text().await.unwrap_or_default();
334 Err(crate::types::error::Error::Server {
335 body: text.to_string(),
336 status,
337 })
338 }
339 }
340
341 #[doc = "Retrieve a specific time entry\n\nRetrieve a specific time entry\n\n**Parameters:**\n\n- `expand: Option<String>`\n- `id: &'astr`: ID of the resource to return (required)\n\n```rust,no_run\nasync fn example_time_entries_get() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let result: rippling_api::types::GetTimeEntriesResponse = client\n .time_entries()\n .get(\n Some(\"some-string\".to_string()),\n \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )\n .await?;\n println!(\"{:?}\", result);\n Ok(())\n}\n```"]
342 #[tracing::instrument]
343 pub async fn get<'a>(
344 &'a self,
345 expand: Option<String>,
346 id: &'a str,
347 ) -> Result<crate::types::GetTimeEntriesResponse, crate::types::error::Error> {
348 let mut req = self.client.client.request(
349 http::Method::GET,
350 format!(
351 "{}/{}",
352 self.client.base_url,
353 "time-entries/{id}".replace("{id}", id)
354 ),
355 );
356 req = req.bearer_auth(&self.client.token);
357 let mut query_params = vec![];
358 if let Some(p) = expand {
359 query_params.push(("expand", p));
360 }
361
362 req = req.query(&query_params);
363 let resp = req.send().await?;
364 let status = resp.status();
365 if status.is_success() {
366 let text = resp.text().await.unwrap_or_default();
367 serde_json::from_str(&text).map_err(|err| {
368 crate::types::error::Error::from_serde_error(
369 format_serde_error::SerdeError::new(text.to_string(), err),
370 status,
371 )
372 })
373 } else {
374 let text = resp.text().await.unwrap_or_default();
375 Err(crate::types::error::Error::Server {
376 body: text.to_string(),
377 status,
378 })
379 }
380 }
381
382 #[doc = "Delete a time entry\n\n**Parameters:**\n\n- `id: &'astr`: ID of the resource to \
383 delete (required)\n\n```rust,no_run\nasync fn example_time_entries_delete() -> \
384 anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n \
385 client\n .time_entries()\n \
386 .delete(\"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\")\n .await?;\n \
387 Ok(())\n}\n```"]
388 #[tracing::instrument]
389 pub async fn delete<'a>(&'a self, id: &'a str) -> Result<(), crate::types::error::Error> {
390 let mut req = self.client.client.request(
391 http::Method::DELETE,
392 format!(
393 "{}/{}",
394 self.client.base_url,
395 "time-entries/{id}".replace("{id}", id)
396 ),
397 );
398 req = req.bearer_auth(&self.client.token);
399 let resp = req.send().await?;
400 let status = resp.status();
401 if status.is_success() {
402 Ok(())
403 } else {
404 let text = resp.text().await.unwrap_or_default();
405 Err(crate::types::error::Error::Server {
406 body: text.to_string(),
407 status,
408 })
409 }
410 }
411
412 #[doc = "Update a time entry\n\nUpdated a specific time entry\n\n**Parameters:**\n\n- `id: &'astr`: ID of the resource to patch (required)\n\n```rust,no_run\nasync fn example_time_entries_update() -> anyhow::Result<()> {\n let client = rippling_api::Client::new_from_env();\n let result: rippling_api::types::TimeEntry = client\n .time_entries()\n .update(\n \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n &rippling_api::types::TimeEntryRequest {\n worker_id: \"some-string\".to_string(),\n duration: Some(3.14 as f64),\n comments: Some(vec![rippling_api::types::TimeEntryCommentRequest {\n text: Some(\"some-string\".to_string()),\n }]),\n job_shifts: Some(vec![rippling_api::types::JobShiftRequest {\n start_time: Some(\"some-string\".to_string()),\n end_time: Some(\"some-string\".to_string()),\n duration: Some(3.14 as f64),\n start_date: Some(\"some-string\".to_string()),\n original_start_time: Some(\"some-string\".to_string()),\n original_end_time: Some(\"some-string\".to_string()),\n job_codes_id: Some(vec![\"some-string\".to_string()]),\n is_hours_only_input: Some(true),\n }]),\n breaks: Some(vec![rippling_api::types::BreakRequest {\n start_time: Some(\"some-string\".to_string()),\n end_time: Some(\"some-string\".to_string()),\n break_type_id: Some(\"some-string\".to_string()),\n }]),\n tags: Some(vec![\"some-string\".to_string()]),\n idempotency_key: Some(\"some-string\".to_string()),\n create_extra_hours_run: Some(true),\n status: Some(rippling_api::types::TimeEntryRequestStatus::Paid),\n pay_period: Some(rippling_api::types::PayPeriodRequest {\n start_date: Some(\"some-string\".to_string()),\n end_date: Some(\"some-string\".to_string()),\n pay_schedule_id: Some(\"some-string\".to_string()),\n }),\n shift_input_values: Some(vec![rippling_api::types::ShiftInputValueRequest {\n shift_input_id: \"some-string\".to_string(),\n author_id: Some(\"some-string\".to_string()),\n }]),\n },\n )\n .await?;\n println!(\"{:?}\", result);\n Ok(())\n}\n```"]
413 #[tracing::instrument]
414 pub async fn update<'a>(
415 &'a self,
416 id: &'a str,
417 body: &crate::types::TimeEntryRequest,
418 ) -> Result<crate::types::TimeEntry, crate::types::error::Error> {
419 let mut req = self.client.client.request(
420 http::Method::PATCH,
421 format!(
422 "{}/{}",
423 self.client.base_url,
424 "time-entries/{id}".replace("{id}", id)
425 ),
426 );
427 req = req.bearer_auth(&self.client.token);
428 req = req.json(body);
429 let resp = req.send().await?;
430 let status = resp.status();
431 if status.is_success() {
432 let text = resp.text().await.unwrap_or_default();
433 serde_json::from_str(&text).map_err(|err| {
434 crate::types::error::Error::from_serde_error(
435 format_serde_error::SerdeError::new(text.to_string(), err),
436 status,
437 )
438 })
439 } else {
440 let text = resp.text().await.unwrap_or_default();
441 Err(crate::types::error::Error::Server {
442 body: text.to_string(),
443 status,
444 })
445 }
446 }
447}