open_lark/service/contact/v3/
user.rs

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
14/// 用户管理服务
15///
16/// 提供完整的用户生命周期管理功能,包括:
17/// - 创建、更新、删除用户
18/// - 获取用户信息(单个/批量)
19/// - 搜索用户
20/// - 部门用户查询
21/// - 恢复已删除用户
22pub struct UserService {
23    config: Config,
24}
25
26// Service 抽象接入(标准样例):Contact v3 UserService
27// 要求结构体包含 `config: Config` 字段
28impl_full_service!(UserService, "contact.user", "v3");
29
30impl UserService {
31    pub fn new(config: Config) -> Self {
32        Self { config }
33    }
34
35    /// 创建用户
36    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    /// 修改用户部分信息
53    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    /// 更新用户 ID
75    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    /// 获取单个用户信息
97    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    /// 批量获取用户信息
128    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    /// 获取部门直属用户列表
145    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    /// 通过手机号或邮箱获取用户 ID
165    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    /// 搜索用户
183    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    /// 删除用户
200    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    /// 恢复已删除用户
223    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    /// 获取用户列表
245    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    /// 创建用户 - Builder模式 (推荐)
275    ///
276    /// 提供更现代化的Builder接口,支持链式调用和统一的执行模式
277    pub fn create_user_builder(&self) -> CreateUserBuilder {
278        CreateUserBuilder::new()
279    }
280}
281
282/// 创建用户的Builder
283#[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    /// 设置用户信息
296    pub fn user(mut self, user: User) -> Self {
297        self.user = Some(user);
298        self
299    }
300
301    /// 设置用户ID类型
302    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    /// 设置部门ID类型
308    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        // 目前简单实现,后续可以支持传递option到service方法
339        let req = self.build();
340        service.create(&req).await
341    }
342}
343
344// 请求/响应结构体定义
345
346/// 创建用户请求
347#[derive(Debug, Clone, Serialize, Deserialize)]
348pub struct CreateUserRequest {
349    /// 用户信息
350    pub user: User,
351    /// 用户 ID 类型
352    #[serde(skip_serializing_if = "Option::is_none")]
353    pub user_id_type: Option<String>,
354    /// 部门 ID 类型
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub department_id_type: Option<String>,
357}
358
359/// 创建用户响应
360#[derive(Debug, Clone, Serialize, Deserialize, Default)]
361pub struct CreateUserResponse {
362    /// 用户信息
363    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/// 修改用户请求
373#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct PatchUserRequest {
375    /// 用户信息
376    pub user: User,
377    /// 用户 ID 类型
378    #[serde(skip_serializing_if = "Option::is_none")]
379    pub user_id_type: Option<String>,
380    /// 部门 ID 类型
381    #[serde(skip_serializing_if = "Option::is_none")]
382    pub department_id_type: Option<String>,
383}
384
385/// 修改用户响应
386#[derive(Debug, Clone, Serialize, Deserialize, Default)]
387pub struct PatchUserResponse {
388    /// 用户信息
389    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/// 更新用户ID请求
399#[derive(Debug, Clone, Serialize, Deserialize)]
400pub struct UpdateUserIdRequest {
401    /// 新的用户ID
402    pub new_user_id: String,
403    /// 用户 ID 类型
404    #[serde(skip_serializing_if = "Option::is_none")]
405    pub user_id_type: Option<String>,
406}
407
408/// 更新用户ID响应
409#[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/// 获取用户请求
419#[derive(Debug, Clone, Default, Serialize, Deserialize)]
420pub struct GetUserRequest {
421    /// 用户 ID 类型
422    #[serde(skip_serializing_if = "Option::is_none")]
423    pub user_id_type: Option<String>,
424    /// 部门 ID 类型
425    #[serde(skip_serializing_if = "Option::is_none")]
426    pub department_id_type: Option<String>,
427}
428
429/// 获取用户响应
430#[derive(Debug, Clone, Serialize, Deserialize, Default)]
431pub struct GetUserResponse {
432    /// 用户信息
433    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/// 批量获取用户请求
443#[derive(Debug, Clone, Serialize, Deserialize)]
444pub struct BatchGetUsersRequest {
445    /// 用户ID列表
446    pub user_ids: Vec<String>,
447    /// 用户 ID 类型
448    #[serde(skip_serializing_if = "Option::is_none")]
449    pub user_id_type: Option<String>,
450    /// 部门 ID 类型
451    #[serde(skip_serializing_if = "Option::is_none")]
452    pub department_id_type: Option<String>,
453}
454
455/// 批量获取用户响应
456#[derive(Debug, Clone, Serialize, Deserialize, Default)]
457pub struct BatchGetUsersResponse {
458    /// 用户列表
459    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/// 按部门查找用户请求
469#[derive(Debug, Clone, Default, Serialize, Deserialize)]
470pub struct FindUsersByDepartmentRequest {
471    /// 部门ID
472    #[serde(skip_serializing_if = "Option::is_none")]
473    pub department_id: Option<String>,
474    /// 用户 ID 类型
475    #[serde(skip_serializing_if = "Option::is_none")]
476    pub user_id_type: Option<String>,
477    /// 部门 ID 类型
478    #[serde(skip_serializing_if = "Option::is_none")]
479    pub department_id_type: Option<String>,
480    /// 分页大小
481    #[serde(skip_serializing_if = "Option::is_none")]
482    pub page_size: Option<i32>,
483    /// 分页标记
484    #[serde(skip_serializing_if = "Option::is_none")]
485    pub page_token: Option<String>,
486}
487
488/// 按部门查找用户响应
489#[derive(Debug, Clone, Serialize, Deserialize, Default)]
490pub struct FindUsersByDepartmentResponse {
491    /// 用户列表
492    pub items: Vec<User>,
493    /// 是否还有更多项目
494    #[serde(skip_serializing_if = "Option::is_none")]
495    pub has_more: Option<bool>,
496    /// 分页标记
497    #[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/// 批量获取用户ID请求
508#[derive(Debug, Clone, Serialize, Deserialize)]
509pub struct BatchGetUserIdRequest {
510    /// 邮箱列表
511    #[serde(skip_serializing_if = "Option::is_none")]
512    pub emails: Option<Vec<String>>,
513    /// 手机号列表
514    #[serde(skip_serializing_if = "Option::is_none")]
515    pub mobiles: Option<Vec<String>>,
516    /// 包含已离职用户
517    #[serde(skip_serializing_if = "Option::is_none")]
518    pub include_resigned: Option<bool>,
519}
520
521/// 批量获取用户ID响应
522#[derive(Debug, Clone, Serialize, Deserialize, Default)]
523pub struct BatchGetUserIdResponse {
524    /// 用户列表
525    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/// 用户ID信息
535#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct UserIdInfo {
537    /// 用户ID
538    #[serde(skip_serializing_if = "Option::is_none")]
539    pub user_id: Option<String>,
540    /// 邮箱
541    #[serde(skip_serializing_if = "Option::is_none")]
542    pub email: Option<String>,
543    /// 手机号
544    #[serde(skip_serializing_if = "Option::is_none")]
545    pub mobile: Option<String>,
546}
547
548/// 搜索用户请求
549#[derive(Debug, Clone, Serialize, Deserialize)]
550pub struct SearchUsersRequest {
551    /// 搜索关键词
552    pub query: String,
553    /// 分页大小
554    #[serde(skip_serializing_if = "Option::is_none")]
555    pub page_size: Option<i32>,
556    /// 分页标记
557    #[serde(skip_serializing_if = "Option::is_none")]
558    pub page_token: Option<String>,
559    /// 用户 ID 类型
560    #[serde(skip_serializing_if = "Option::is_none")]
561    pub user_id_type: Option<String>,
562    /// 部门 ID 类型
563    #[serde(skip_serializing_if = "Option::is_none")]
564    pub department_id_type: Option<String>,
565}
566
567/// 搜索用户响应
568#[derive(Debug, Clone, Serialize, Deserialize, Default)]
569pub struct SearchUsersResponse {
570    /// 用户列表
571    pub items: Vec<User>,
572    /// 是否还有更多项目
573    #[serde(skip_serializing_if = "Option::is_none")]
574    pub has_more: Option<bool>,
575    /// 分页标记
576    #[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/// 删除用户请求
587#[derive(Debug, Clone, Default, Serialize, Deserialize)]
588pub struct DeleteUserRequest {
589    /// 用户 ID 类型
590    #[serde(skip_serializing_if = "Option::is_none")]
591    pub user_id_type: Option<String>,
592    /// 部门 ID 类型
593    #[serde(skip_serializing_if = "Option::is_none")]
594    pub department_id_type: Option<String>,
595}
596
597/// 删除用户响应
598#[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/// 恢复用户请求
608#[derive(Debug, Clone, Serialize, Deserialize)]
609pub struct ResurrectUserRequest {
610    /// 用户 ID 类型
611    #[serde(skip_serializing_if = "Option::is_none")]
612    pub user_id_type: Option<String>,
613    /// 部门 ID 类型
614    #[serde(skip_serializing_if = "Option::is_none")]
615    pub department_id_type: Option<String>,
616}
617
618/// 恢复用户响应
619#[derive(Debug, Clone, Serialize, Deserialize, Default)]
620pub struct ResurrectUserResponse {
621    /// 用户信息
622    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/// 获取用户列表请求
632#[derive(Debug, Clone, Default, Serialize, Deserialize)]
633pub struct ListUsersRequest {
634    /// 分页大小
635    #[serde(skip_serializing_if = "Option::is_none")]
636    pub page_size: Option<i32>,
637    /// 分页标记
638    #[serde(skip_serializing_if = "Option::is_none")]
639    pub page_token: Option<String>,
640    /// 用户 ID 类型
641    #[serde(skip_serializing_if = "Option::is_none")]
642    pub user_id_type: Option<String>,
643    /// 部门 ID 类型
644    #[serde(skip_serializing_if = "Option::is_none")]
645    pub department_id_type: Option<String>,
646}
647
648/// 获取用户列表响应
649#[derive(Debug, Clone, Serialize, Deserialize, Default)]
650pub struct ListUsersResponse {
651    /// 用户列表
652    pub items: Vec<User>,
653    /// 是否还有更多项目
654    #[serde(skip_serializing_if = "Option::is_none")]
655    pub has_more: Option<bool>,
656    /// 分页标记
657    #[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}