1use crate::impl_full_service;
2use crate::{
3 core::{
4 api_req::ApiRequest, api_resp::ApiResponseTrait, config::Config,
5 constants::AccessTokenType, endpoints::EndpointBuilder, http::Transport,
6 req_option::RequestOption, standard_response::StandardResponse,
7 trait_system::executable_builder::ExecutableBuilder, SDKResult,
8 },
9 service::contact::models::*,
10};
11use async_trait::async_trait;
12use serde::{Deserialize, Serialize};
13
14pub struct UserService {
23 config: Config,
24}
25
26impl_full_service!(UserService, "contact.user", "v3");
29
30impl UserService {
31 pub fn new(config: Config) -> Self {
32 Self { config }
33 }
34
35 pub async fn create(
37 &self,
38 req: &CreateUserRequest,
39 ) -> crate::core::SDKResult<CreateUserResponse> {
40 let api_req = ApiRequest {
41 http_method: reqwest::Method::POST,
42 api_path: crate::core::endpoints::contact::CONTACT_V3_USERS.to_string(),
43 supported_access_token_types: vec![AccessTokenType::Tenant],
44 body: serde_json::to_vec(req)?,
45 ..Default::default()
46 };
47
48 let resp = Transport::<CreateUserResponse>::request(api_req, &self.config, None).await?;
49 resp.into_result()
50 }
51
52 pub async fn patch(
54 &self,
55 user_id: &str,
56 req: &PatchUserRequest,
57 ) -> crate::core::SDKResult<PatchUserResponse> {
58 let api_req = ApiRequest {
59 http_method: reqwest::Method::PATCH,
60 api_path: EndpointBuilder::replace_param(
61 crate::core::endpoints::contact::CONTACT_V3_USER_GET,
62 "user_id",
63 user_id,
64 ),
65 supported_access_token_types: vec![AccessTokenType::Tenant],
66 body: serde_json::to_vec(req)?,
67 ..Default::default()
68 };
69
70 let resp = Transport::<PatchUserResponse>::request(api_req, &self.config, None).await?;
71 resp.into_result()
72 }
73
74 pub async fn update_user_id(
76 &self,
77 user_id: &str,
78 req: &UpdateUserIdRequest,
79 ) -> crate::core::SDKResult<UpdateUserIdResponse> {
80 let api_req = ApiRequest {
81 http_method: reqwest::Method::PATCH,
82 api_path: EndpointBuilder::replace_param(
83 crate::core::endpoints::contact::CONTACT_V3_USER_UPDATE_ID,
84 "user_id",
85 user_id,
86 ),
87 supported_access_token_types: vec![AccessTokenType::Tenant],
88 body: serde_json::to_vec(req)?,
89 ..Default::default()
90 };
91
92 let resp = Transport::<UpdateUserIdResponse>::request(api_req, &self.config, None).await?;
93 resp.into_result()
94 }
95
96 pub async fn get(
98 &self,
99 user_id: &str,
100 _req: &GetUserRequest,
101 ) -> crate::core::SDKResult<GetUserResponse> {
102 let mut query_params = std::collections::HashMap::new();
103 if let Some(user_id_type) = &_req.user_id_type {
104 query_params.insert("user_id_type", user_id_type.clone());
105 }
106 if let Some(department_id_type) = &_req.department_id_type {
107 query_params.insert("department_id_type", department_id_type.clone());
108 }
109
110 let api_req = ApiRequest {
111 http_method: reqwest::Method::GET,
112 api_path: EndpointBuilder::replace_param(
113 crate::core::endpoints::contact::CONTACT_V3_USER_GET,
114 "user_id",
115 user_id,
116 ),
117 supported_access_token_types: vec![AccessTokenType::Tenant, AccessTokenType::User],
118 body: Vec::new(),
119 query_params,
120 ..Default::default()
121 };
122
123 let resp = Transport::<GetUserResponse>::request(api_req, &self.config, None).await?;
124 resp.into_result()
125 }
126
127 pub async fn batch(
129 &self,
130 req: &BatchGetUsersRequest,
131 ) -> crate::core::SDKResult<BatchGetUsersResponse> {
132 let api_req = ApiRequest {
133 http_method: reqwest::Method::POST,
134 api_path: crate::core::endpoints::contact::CONTACT_V3_USERS_BATCH.to_string(),
135 supported_access_token_types: vec![AccessTokenType::Tenant],
136 body: serde_json::to_vec(req)?,
137 ..Default::default()
138 };
139
140 let resp = Transport::<BatchGetUsersResponse>::request(api_req, &self.config, None).await?;
141 resp.into_result()
142 }
143
144 pub async fn find_by_department(
146 &self,
147 _req: &FindUsersByDepartmentRequest,
148 ) -> crate::core::SDKResult<FindUsersByDepartmentResponse> {
149 let api_req = ApiRequest {
150 http_method: reqwest::Method::GET,
151 api_path: crate::core::endpoints::contact::CONTACT_V3_USERS_FIND_BY_DEPARTMENT
152 .to_string(),
153 supported_access_token_types: vec![AccessTokenType::Tenant, AccessTokenType::User],
154 body: Vec::new(),
155 query_params: std::collections::HashMap::new(),
156 ..Default::default()
157 };
158
159 let resp = Transport::<FindUsersByDepartmentResponse>::request(api_req, &self.config, None)
160 .await?;
161 resp.into_result()
162 }
163
164 pub async fn batch_get_id(
166 &self,
167 req: &BatchGetUserIdRequest,
168 ) -> crate::core::SDKResult<BatchGetUserIdResponse> {
169 let api_req = ApiRequest {
170 http_method: reqwest::Method::POST,
171 api_path: crate::core::endpoints::contact::CONTACT_V3_USERS_BATCH_GET_ID.to_string(),
172 supported_access_token_types: vec![AccessTokenType::Tenant],
173 body: serde_json::to_vec(req)?,
174 ..Default::default()
175 };
176
177 let resp =
178 Transport::<BatchGetUserIdResponse>::request(api_req, &self.config, None).await?;
179 resp.into_result()
180 }
181
182 pub async fn search(
184 &self,
185 req: &SearchUsersRequest,
186 ) -> crate::core::SDKResult<SearchUsersResponse> {
187 let api_req = ApiRequest {
188 http_method: reqwest::Method::POST,
189 api_path: crate::core::endpoints::contact::CONTACT_V3_USERS_SEARCH.to_string(),
190 supported_access_token_types: vec![AccessTokenType::Tenant, AccessTokenType::User],
191 body: serde_json::to_vec(req)?,
192 ..Default::default()
193 };
194
195 let resp = Transport::<SearchUsersResponse>::request(api_req, &self.config, None).await?;
196 resp.into_result()
197 }
198
199 pub async fn delete(
201 &self,
202 user_id: &str,
203 _req: &DeleteUserRequest,
204 ) -> crate::core::SDKResult<DeleteUserResponse> {
205 let api_req = ApiRequest {
206 http_method: reqwest::Method::DELETE,
207 api_path: EndpointBuilder::replace_param(
208 crate::core::endpoints::contact::CONTACT_V3_USER_GET,
209 "user_id",
210 user_id,
211 ),
212 supported_access_token_types: vec![AccessTokenType::Tenant],
213 body: Vec::new(),
214 query_params: std::collections::HashMap::new(),
215 ..Default::default()
216 };
217
218 let resp = Transport::<DeleteUserResponse>::request(api_req, &self.config, None).await?;
219 resp.into_result()
220 }
221
222 pub async fn resurrect(
224 &self,
225 user_id: &str,
226 req: &ResurrectUserRequest,
227 ) -> crate::core::SDKResult<ResurrectUserResponse> {
228 let api_req = ApiRequest {
229 http_method: reqwest::Method::POST,
230 api_path: EndpointBuilder::replace_param(
231 crate::core::endpoints::contact::CONTACT_V3_USER_RESURRECT,
232 "user_id",
233 user_id,
234 ),
235 supported_access_token_types: vec![AccessTokenType::Tenant],
236 body: serde_json::to_vec(req)?,
237 ..Default::default()
238 };
239
240 let resp = Transport::<ResurrectUserResponse>::request(api_req, &self.config, None).await?;
241 resp.into_result()
242 }
243
244 pub async fn list(&self, req: &ListUsersRequest) -> crate::core::SDKResult<ListUsersResponse> {
246 let mut query_params = std::collections::HashMap::new();
247
248 if let Some(page_size) = req.page_size {
249 query_params.insert("page_size", page_size.to_string());
250 }
251 if let Some(page_token) = &req.page_token {
252 query_params.insert("page_token", page_token.clone());
253 }
254 if let Some(user_id_type) = &req.user_id_type {
255 query_params.insert("user_id_type", user_id_type.clone());
256 }
257 if let Some(department_id_type) = &req.department_id_type {
258 query_params.insert("department_id_type", department_id_type.clone());
259 }
260
261 let api_req = ApiRequest {
262 http_method: reqwest::Method::GET,
263 api_path: crate::core::endpoints::contact::CONTACT_V3_USERS.to_string(),
264 supported_access_token_types: vec![AccessTokenType::Tenant, AccessTokenType::User],
265 body: Vec::new(),
266 query_params,
267 ..Default::default()
268 };
269
270 let resp = Transport::<ListUsersResponse>::request(api_req, &self.config, None).await?;
271 resp.into_result()
272 }
273
274 pub fn create_user_builder(&self) -> CreateUserBuilder {
278 CreateUserBuilder::new()
279 }
280}
281
282#[derive(Default)]
284pub struct CreateUserBuilder {
285 user: Option<User>,
286 user_id_type: Option<String>,
287 department_id_type: Option<String>,
288}
289
290impl CreateUserBuilder {
291 pub fn new() -> Self {
292 Self::default()
293 }
294
295 pub fn user(mut self, user: User) -> Self {
297 self.user = Some(user);
298 self
299 }
300
301 pub fn user_id_type(mut self, user_id_type: impl ToString) -> Self {
303 self.user_id_type = Some(user_id_type.to_string());
304 self
305 }
306
307 pub fn department_id_type(mut self, department_id_type: impl ToString) -> Self {
309 self.department_id_type = Some(department_id_type.to_string());
310 self
311 }
312
313 pub fn build(self) -> CreateUserRequest {
314 CreateUserRequest {
315 user: self.user.unwrap_or_default(),
316 user_id_type: self.user_id_type,
317 department_id_type: self.department_id_type,
318 }
319 }
320}
321
322#[async_trait]
323impl ExecutableBuilder<UserService, CreateUserRequest, CreateUserResponse> for CreateUserBuilder {
324 fn build(self) -> CreateUserRequest {
325 self.build()
326 }
327
328 async fn execute(self, service: &UserService) -> SDKResult<CreateUserResponse> {
329 let req = self.build();
330 service.create(&req).await
331 }
332
333 async fn execute_with_options(
334 self,
335 service: &UserService,
336 _option: RequestOption,
337 ) -> SDKResult<CreateUserResponse> {
338 let req = self.build();
340 service.create(&req).await
341 }
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
348pub struct CreateUserRequest {
349 pub user: User,
351 #[serde(skip_serializing_if = "Option::is_none")]
353 pub user_id_type: Option<String>,
354 #[serde(skip_serializing_if = "Option::is_none")]
356 pub department_id_type: Option<String>,
357}
358
359#[derive(Debug, Clone, Serialize, Deserialize, Default)]
361pub struct CreateUserResponse {
362 pub user: User,
364}
365
366impl ApiResponseTrait for CreateUserResponse {
367 fn data_format() -> crate::core::api_resp::ResponseFormat {
368 crate::core::api_resp::ResponseFormat::Data
369 }
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct PatchUserRequest {
375 pub user: User,
377 #[serde(skip_serializing_if = "Option::is_none")]
379 pub user_id_type: Option<String>,
380 #[serde(skip_serializing_if = "Option::is_none")]
382 pub department_id_type: Option<String>,
383}
384
385#[derive(Debug, Clone, Serialize, Deserialize, Default)]
387pub struct PatchUserResponse {
388 pub user: User,
390}
391
392impl ApiResponseTrait for PatchUserResponse {
393 fn data_format() -> crate::core::api_resp::ResponseFormat {
394 crate::core::api_resp::ResponseFormat::Data
395 }
396}
397
398#[derive(Debug, Clone, Serialize, Deserialize)]
400pub struct UpdateUserIdRequest {
401 pub new_user_id: String,
403 #[serde(skip_serializing_if = "Option::is_none")]
405 pub user_id_type: Option<String>,
406}
407
408#[derive(Debug, Clone, Serialize, Deserialize, Default)]
410pub struct UpdateUserIdResponse {}
411
412impl ApiResponseTrait for UpdateUserIdResponse {
413 fn data_format() -> crate::core::api_resp::ResponseFormat {
414 crate::core::api_resp::ResponseFormat::Data
415 }
416}
417
418#[derive(Debug, Clone, Default, Serialize, Deserialize)]
420pub struct GetUserRequest {
421 #[serde(skip_serializing_if = "Option::is_none")]
423 pub user_id_type: Option<String>,
424 #[serde(skip_serializing_if = "Option::is_none")]
426 pub department_id_type: Option<String>,
427}
428
429#[derive(Debug, Clone, Serialize, Deserialize, Default)]
431pub struct GetUserResponse {
432 pub user: User,
434}
435
436impl ApiResponseTrait for GetUserResponse {
437 fn data_format() -> crate::core::api_resp::ResponseFormat {
438 crate::core::api_resp::ResponseFormat::Data
439 }
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize)]
444pub struct BatchGetUsersRequest {
445 pub user_ids: Vec<String>,
447 #[serde(skip_serializing_if = "Option::is_none")]
449 pub user_id_type: Option<String>,
450 #[serde(skip_serializing_if = "Option::is_none")]
452 pub department_id_type: Option<String>,
453}
454
455#[derive(Debug, Clone, Serialize, Deserialize, Default)]
457pub struct BatchGetUsersResponse {
458 pub items: Vec<User>,
460}
461
462impl ApiResponseTrait for BatchGetUsersResponse {
463 fn data_format() -> crate::core::api_resp::ResponseFormat {
464 crate::core::api_resp::ResponseFormat::Data
465 }
466}
467
468#[derive(Debug, Clone, Default, Serialize, Deserialize)]
470pub struct FindUsersByDepartmentRequest {
471 #[serde(skip_serializing_if = "Option::is_none")]
473 pub department_id: Option<String>,
474 #[serde(skip_serializing_if = "Option::is_none")]
476 pub user_id_type: Option<String>,
477 #[serde(skip_serializing_if = "Option::is_none")]
479 pub department_id_type: Option<String>,
480 #[serde(skip_serializing_if = "Option::is_none")]
482 pub page_size: Option<i32>,
483 #[serde(skip_serializing_if = "Option::is_none")]
485 pub page_token: Option<String>,
486}
487
488#[derive(Debug, Clone, Serialize, Deserialize, Default)]
490pub struct FindUsersByDepartmentResponse {
491 pub items: Vec<User>,
493 #[serde(skip_serializing_if = "Option::is_none")]
495 pub has_more: Option<bool>,
496 #[serde(skip_serializing_if = "Option::is_none")]
498 pub page_token: Option<String>,
499}
500
501impl ApiResponseTrait for FindUsersByDepartmentResponse {
502 fn data_format() -> crate::core::api_resp::ResponseFormat {
503 crate::core::api_resp::ResponseFormat::Data
504 }
505}
506
507#[derive(Debug, Clone, Serialize, Deserialize)]
509pub struct BatchGetUserIdRequest {
510 #[serde(skip_serializing_if = "Option::is_none")]
512 pub emails: Option<Vec<String>>,
513 #[serde(skip_serializing_if = "Option::is_none")]
515 pub mobiles: Option<Vec<String>>,
516 #[serde(skip_serializing_if = "Option::is_none")]
518 pub include_resigned: Option<bool>,
519}
520
521#[derive(Debug, Clone, Serialize, Deserialize, Default)]
523pub struct BatchGetUserIdResponse {
524 pub user_list: Vec<UserIdInfo>,
526}
527
528impl ApiResponseTrait for BatchGetUserIdResponse {
529 fn data_format() -> crate::core::api_resp::ResponseFormat {
530 crate::core::api_resp::ResponseFormat::Data
531 }
532}
533
534#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct UserIdInfo {
537 #[serde(skip_serializing_if = "Option::is_none")]
539 pub user_id: Option<String>,
540 #[serde(skip_serializing_if = "Option::is_none")]
542 pub email: Option<String>,
543 #[serde(skip_serializing_if = "Option::is_none")]
545 pub mobile: Option<String>,
546}
547
548#[derive(Debug, Clone, Serialize, Deserialize)]
550pub struct SearchUsersRequest {
551 pub query: String,
553 #[serde(skip_serializing_if = "Option::is_none")]
555 pub page_size: Option<i32>,
556 #[serde(skip_serializing_if = "Option::is_none")]
558 pub page_token: Option<String>,
559 #[serde(skip_serializing_if = "Option::is_none")]
561 pub user_id_type: Option<String>,
562 #[serde(skip_serializing_if = "Option::is_none")]
564 pub department_id_type: Option<String>,
565}
566
567#[derive(Debug, Clone, Serialize, Deserialize, Default)]
569pub struct SearchUsersResponse {
570 pub items: Vec<User>,
572 #[serde(skip_serializing_if = "Option::is_none")]
574 pub has_more: Option<bool>,
575 #[serde(skip_serializing_if = "Option::is_none")]
577 pub page_token: Option<String>,
578}
579
580impl ApiResponseTrait for SearchUsersResponse {
581 fn data_format() -> crate::core::api_resp::ResponseFormat {
582 crate::core::api_resp::ResponseFormat::Data
583 }
584}
585
586#[derive(Debug, Clone, Default, Serialize, Deserialize)]
588pub struct DeleteUserRequest {
589 #[serde(skip_serializing_if = "Option::is_none")]
591 pub user_id_type: Option<String>,
592 #[serde(skip_serializing_if = "Option::is_none")]
594 pub department_id_type: Option<String>,
595}
596
597#[derive(Debug, Clone, Serialize, Deserialize, Default)]
599pub struct DeleteUserResponse {}
600
601impl ApiResponseTrait for DeleteUserResponse {
602 fn data_format() -> crate::core::api_resp::ResponseFormat {
603 crate::core::api_resp::ResponseFormat::Data
604 }
605}
606
607#[derive(Debug, Clone, Serialize, Deserialize)]
609pub struct ResurrectUserRequest {
610 #[serde(skip_serializing_if = "Option::is_none")]
612 pub user_id_type: Option<String>,
613 #[serde(skip_serializing_if = "Option::is_none")]
615 pub department_id_type: Option<String>,
616}
617
618#[derive(Debug, Clone, Serialize, Deserialize, Default)]
620pub struct ResurrectUserResponse {
621 pub user: User,
623}
624
625impl ApiResponseTrait for ResurrectUserResponse {
626 fn data_format() -> crate::core::api_resp::ResponseFormat {
627 crate::core::api_resp::ResponseFormat::Data
628 }
629}
630
631#[derive(Debug, Clone, Default, Serialize, Deserialize)]
633pub struct ListUsersRequest {
634 #[serde(skip_serializing_if = "Option::is_none")]
636 pub page_size: Option<i32>,
637 #[serde(skip_serializing_if = "Option::is_none")]
639 pub page_token: Option<String>,
640 #[serde(skip_serializing_if = "Option::is_none")]
642 pub user_id_type: Option<String>,
643 #[serde(skip_serializing_if = "Option::is_none")]
645 pub department_id_type: Option<String>,
646}
647
648#[derive(Debug, Clone, Serialize, Deserialize, Default)]
650pub struct ListUsersResponse {
651 pub items: Vec<User>,
653 #[serde(skip_serializing_if = "Option::is_none")]
655 pub has_more: Option<bool>,
656 #[serde(skip_serializing_if = "Option::is_none")]
658 pub page_token: Option<String>,
659}
660
661impl ApiResponseTrait for ListUsersResponse {
662 fn data_format() -> crate::core::api_resp::ResponseFormat {
663 crate::core::api_resp::ResponseFormat::Data
664 }
665}
666
667#[cfg(test)]
668#[allow(unused_variables, unused_unsafe)]
669mod tests {
670 use super::*;
671 use crate::{
672 core::api_resp::ResponseFormat, core::config::Config, service::contact::models::User,
673 };
674
675 fn create_test_config() -> Config {
676 Config::builder()
677 .app_id("test_app_id")
678 .app_secret("test_app_secret")
679 .base_url("https://test.example.com")
680 .build()
681 }
682
683 fn create_test_user() -> User {
684 use crate::service::contact::models::{Avatar, UserCustomAttr, UserStatus};
685
686 User {
687 user_id: Some("user123".to_string()),
688 name: Some("Test User".to_string()),
689 en_name: Some("test_user".to_string()),
690 email: Some("test@example.com".to_string()),
691 mobile: Some("+86138000000".to_string()),
692 mobile_visible: Some(true),
693 gender: Some(1),
694 avatar: Some(Avatar {
695 avatar_72: Some("https://example.com/avatar_72.jpg".to_string()),
696 avatar_240: Some("https://example.com/avatar_240.jpg".to_string()),
697 avatar_640: Some("https://example.com/avatar_640.jpg".to_string()),
698 avatar_origin: Some("https://example.com/avatar_origin.jpg".to_string()),
699 }),
700 status: Some(UserStatus {
701 is_frozen: Some(false),
702 is_resigned: Some(false),
703 is_activated: Some(true),
704 is_exited: Some(false),
705 is_unjoin: Some(false),
706 }),
707 department_ids: Some(vec!["dept1".to_string(), "dept2".to_string()]),
708 leader_user_id: Some("leader123".to_string()),
709 city: Some("Beijing".to_string()),
710 country: Some("China".to_string()),
711 work_station: Some("Workstation 101".to_string()),
712 join_time: Some(1634567890),
713 employee_no: Some("EMP001".to_string()),
714 employee_type: Some(1),
715 custom_attrs: Some(vec![UserCustomAttr {
716 r#type: Some("text".to_string()),
717 id: Some("custom_1".to_string()),
718 value: Some(serde_json::Value::String("test_value".to_string())),
719 }]),
720 enterprise_email: Some("test@company.com".to_string()),
721 job_title: Some("Engineer".to_string()),
722 ..Default::default()
723 }
724 }
725
726 #[test]
727 fn test_user_service_new() {
728 let config = create_test_config();
729 let service = UserService::new(config.clone());
730
731 assert_eq!(service.config.app_id, config.app_id);
732 assert_eq!(service.config.app_secret, config.app_secret);
733 assert_eq!(service.config.base_url, config.base_url);
734 }
735
736 #[test]
737 fn test_create_user_request_serialization() {
738 let user = create_test_user();
739 let request = CreateUserRequest {
740 user: user.clone(),
741 user_id_type: Some("open_id".to_string()),
742 department_id_type: Some("department_id".to_string()),
743 };
744
745 let json = serde_json::to_string(&request).unwrap();
746 assert!(json.contains("test@example.com"));
747 assert!(json.contains("Test User"));
748 assert!(json.contains("open_id"));
749 }
750
751 #[test]
752 fn test_create_user_response_deserialization() {
753 let json = r#"{
754 "user": {
755 "user_id": "user123",
756 "name": "Test User",
757 "email": "test@example.com",
758 "mobile": "+86138000000"
759 }
760 }"#;
761
762 let response: CreateUserResponse = serde_json::from_str(json).unwrap();
763 assert_eq!(response.user.user_id, Some("user123".to_string()));
764 assert_eq!(response.user.name, Some("Test User".to_string()));
765 assert_eq!(response.user.email, Some("test@example.com".to_string()));
766 }
767
768 #[test]
769 fn test_create_user_builder() {
770 let user = create_test_user();
771 let builder = CreateUserBuilder::new()
772 .user(user.clone())
773 .user_id_type("open_id")
774 .department_id_type("department_id");
775
776 let request = builder.build();
777 assert_eq!(request.user.name, user.name);
778 assert_eq!(request.user_id_type, Some("open_id".to_string()));
779 assert_eq!(
780 request.department_id_type,
781 Some("department_id".to_string())
782 );
783 }
784
785 #[test]
786 fn test_create_user_builder_default() {
787 let builder = CreateUserBuilder::new();
788 let request = builder.build();
789
790 assert_eq!(request.user.name, None);
791 assert_eq!(request.user_id_type, None);
792 assert_eq!(request.department_id_type, None);
793 }
794
795 #[test]
796 fn test_patch_user_request_serialization() {
797 let user = create_test_user();
798 let request = PatchUserRequest {
799 user: user.clone(),
800 user_id_type: Some("user_id".to_string()),
801 department_id_type: None,
802 };
803
804 let json = serde_json::to_string(&request).unwrap();
805 assert!(json.contains("Test User"));
806 assert!(json.contains("user_id"));
807 assert!(!json.contains("department_id_type"));
808 }
809
810 #[test]
811 fn test_update_user_id_request_serialization() {
812 let request = UpdateUserIdRequest {
813 new_user_id: "new_user_123".to_string(),
814 user_id_type: Some("open_id".to_string()),
815 };
816
817 let json = serde_json::to_string(&request).unwrap();
818 assert!(json.contains("new_user_123"));
819 assert!(json.contains("open_id"));
820 }
821
822 #[test]
823 fn test_get_user_request_default() {
824 let request = GetUserRequest::default();
825 assert_eq!(request.user_id_type, None);
826 assert_eq!(request.department_id_type, None);
827 }
828
829 #[test]
830 fn test_batch_get_users_request() {
831 let request = BatchGetUsersRequest {
832 user_ids: vec![
833 "user1".to_string(),
834 "user2".to_string(),
835 "user3".to_string(),
836 ],
837 user_id_type: Some("open_id".to_string()),
838 department_id_type: Some("department_id".to_string()),
839 };
840
841 let json = serde_json::to_string(&request).unwrap();
842 assert!(json.contains("user1"));
843 assert!(json.contains("user2"));
844 assert!(json.contains("user3"));
845 assert_eq!(request.user_ids.len(), 3);
846 }
847
848 #[test]
849 fn test_batch_get_users_response() {
850 let user1 = create_test_user();
851 let mut user2 = create_test_user();
852 user2.user_id = Some("user456".to_string());
853 user2.name = Some("Another User".to_string());
854
855 let response = BatchGetUsersResponse {
856 items: vec![user1, user2],
857 };
858
859 assert_eq!(response.items.len(), 2);
860 assert_eq!(response.items[0].user_id, Some("user123".to_string()));
861 assert_eq!(response.items[1].user_id, Some("user456".to_string()));
862 }
863
864 #[test]
865 fn test_find_users_by_department_request() {
866 let request = FindUsersByDepartmentRequest {
867 department_id: Some("dept123".to_string()),
868 user_id_type: Some("open_id".to_string()),
869 department_id_type: Some("department_id".to_string()),
870 page_size: Some(50),
871 page_token: Some("token123".to_string()),
872 };
873
874 let json = serde_json::to_string(&request).unwrap();
875 assert!(json.contains("dept123"));
876 assert!(json.contains("50"));
877 assert!(json.contains("token123"));
878 }
879
880 #[test]
881 fn test_find_users_by_department_response() {
882 let user = create_test_user();
883 let response = FindUsersByDepartmentResponse {
884 items: vec![user],
885 has_more: Some(true),
886 page_token: Some("next_token".to_string()),
887 };
888
889 assert_eq!(response.items.len(), 1);
890 assert_eq!(response.has_more, Some(true));
891 assert_eq!(response.page_token, Some("next_token".to_string()));
892 }
893
894 #[test]
895 fn test_batch_get_user_id_request() {
896 let request = BatchGetUserIdRequest {
897 emails: Some(vec![
898 "test1@example.com".to_string(),
899 "test2@example.com".to_string(),
900 ]),
901 mobiles: Some(vec!["+86138000001".to_string(), "+86138000002".to_string()]),
902 include_resigned: Some(true),
903 };
904
905 let json = serde_json::to_string(&request).unwrap();
906 assert!(json.contains("test1@example.com"));
907 assert!(json.contains("+86138000001"));
908 assert!(json.contains("true"));
909 }
910
911 #[test]
912 fn test_user_id_info_serialization() {
913 let user_info = UserIdInfo {
914 user_id: Some("user123".to_string()),
915 email: Some("test@example.com".to_string()),
916 mobile: Some("+86138000000".to_string()),
917 };
918
919 let json = serde_json::to_string(&user_info).unwrap();
920 let deserialized: UserIdInfo = serde_json::from_str(&json).unwrap();
921
922 assert_eq!(deserialized.user_id, user_info.user_id);
923 assert_eq!(deserialized.email, user_info.email);
924 assert_eq!(deserialized.mobile, user_info.mobile);
925 }
926
927 #[test]
928 fn test_search_users_request() {
929 let request = SearchUsersRequest {
930 query: "张三".to_string(),
931 page_size: Some(20),
932 page_token: Some("search_token".to_string()),
933 user_id_type: Some("open_id".to_string()),
934 department_id_type: Some("department_id".to_string()),
935 };
936
937 let json = serde_json::to_string(&request).unwrap();
938 assert!(json.contains("张三"));
939 assert!(json.contains("20"));
940 assert!(json.contains("search_token"));
941 }
942
943 #[test]
944 fn test_search_users_response() {
945 let user = create_test_user();
946 let response = SearchUsersResponse {
947 items: vec![user],
948 has_more: Some(false),
949 page_token: None,
950 };
951
952 assert_eq!(response.items.len(), 1);
953 assert_eq!(response.has_more, Some(false));
954 assert_eq!(response.page_token, None);
955 }
956
957 #[test]
958 fn test_delete_user_request_default() {
959 let request = DeleteUserRequest::default();
960 assert_eq!(request.user_id_type, None);
961 assert_eq!(request.department_id_type, None);
962 }
963
964 #[test]
965 fn test_resurrect_user_request() {
966 let request = ResurrectUserRequest {
967 user_id_type: Some("open_id".to_string()),
968 department_id_type: Some("department_id".to_string()),
969 };
970
971 let json = serde_json::to_string(&request).unwrap();
972 assert!(json.contains("open_id"));
973 assert!(json.contains("department_id"));
974 }
975
976 #[test]
977 fn test_list_users_request() {
978 let request = ListUsersRequest {
979 page_size: Some(100),
980 page_token: Some("list_token".to_string()),
981 user_id_type: Some("user_id".to_string()),
982 department_id_type: Some("department_id".to_string()),
983 };
984
985 let json = serde_json::to_string(&request).unwrap();
986 assert!(json.contains("100"));
987 assert!(json.contains("list_token"));
988 assert!(json.contains("user_id"));
989 assert!(json.contains("department_id"));
990 }
991
992 #[test]
993 fn test_list_users_response() {
994 let user1 = create_test_user();
995 let mut user2 = create_test_user();
996 user2.user_id = Some("user789".to_string());
997 user2.name = Some("Third User".to_string());
998
999 let response = ListUsersResponse {
1000 items: vec![user1, user2],
1001 has_more: Some(true),
1002 page_token: Some("next_page_token".to_string()),
1003 };
1004
1005 assert_eq!(response.items.len(), 2);
1006 assert_eq!(response.has_more, Some(true));
1007 assert_eq!(response.page_token, Some("next_page_token".to_string()));
1008 }
1009
1010 #[test]
1011 fn test_api_response_trait_implementations() {
1012 assert!(matches!(
1013 CreateUserResponse::data_format(),
1014 ResponseFormat::Data
1015 ));
1016 assert!(matches!(
1017 PatchUserResponse::data_format(),
1018 ResponseFormat::Data
1019 ));
1020 assert!(matches!(
1021 UpdateUserIdResponse::data_format(),
1022 ResponseFormat::Data
1023 ));
1024 assert!(matches!(
1025 GetUserResponse::data_format(),
1026 ResponseFormat::Data
1027 ));
1028 assert!(matches!(
1029 BatchGetUsersResponse::data_format(),
1030 ResponseFormat::Data
1031 ));
1032 }
1033
1034 #[test]
1035 fn test_empty_responses() {
1036 let update_response = UpdateUserIdResponse {};
1037 let delete_response = DeleteUserResponse {};
1038
1039 let update_json = serde_json::to_string(&update_response).unwrap();
1040 let delete_json = serde_json::to_string(&delete_response).unwrap();
1041
1042 assert_eq!(update_json, "{}");
1043 assert_eq!(delete_json, "{}");
1044 }
1045
1046 #[test]
1047 fn test_user_service_builder_creation() {
1048 let config = create_test_config();
1049 let service = UserService::new(config);
1050 let builder = service.create_user_builder();
1051
1052 let user = create_test_user();
1053 let request = builder
1054 .user(user.clone())
1055 .user_id_type("open_id")
1056 .department_id_type("department_id")
1057 .build();
1058
1059 assert_eq!(request.user.name, user.name);
1060 assert_eq!(request.user_id_type, Some("open_id".to_string()));
1061 assert_eq!(
1062 request.department_id_type,
1063 Some("department_id".to_string())
1064 );
1065 }
1066
1067 #[test]
1068 fn test_request_serialization_edge_cases() {
1069 let request = CreateUserRequest {
1070 user: User::default(),
1071 user_id_type: None,
1072 department_id_type: None,
1073 };
1074
1075 let json = serde_json::to_string(&request).unwrap();
1076 let deserialized: CreateUserRequest = serde_json::from_str(&json).unwrap();
1077
1078 assert_eq!(deserialized.user_id_type, None);
1079 assert_eq!(deserialized.department_id_type, None);
1080 }
1081
1082 #[test]
1083 fn test_unicode_handling() {
1084 let mut user = create_test_user();
1085 user.name = Some("张三".to_string());
1086 user.city = Some("北京市".to_string());
1087 user.country = Some("中国".to_string());
1088
1089 let request = CreateUserRequest {
1090 user: user.clone(),
1091 user_id_type: Some("用户ID".to_string()),
1092 department_id_type: Some("部门ID".to_string()),
1093 };
1094
1095 let json = serde_json::to_string(&request).unwrap();
1096 let deserialized: CreateUserRequest = serde_json::from_str(&json).unwrap();
1097
1098 assert_eq!(deserialized.user.name, Some("张三".to_string()));
1099 assert_eq!(deserialized.user.city, Some("北京市".to_string()));
1100 assert_eq!(deserialized.user.country, Some("中国".to_string()));
1101 assert_eq!(deserialized.user_id_type, Some("用户ID".to_string()));
1102 assert_eq!(deserialized.department_id_type, Some("部门ID".to_string()));
1103 }
1104}