Skip to main content

openlark_workflow/v2/custom_field/option/
create.rs

1//! 创建自定义字段选项
2//!
3//! docPath: https://open.feishu.cn/document/server-docs/docs/task-v2/custom_field-option/create
4
5use crate::common::{api_endpoints::TaskApiV2, api_utils::*};
6use openlark_core::{
7    SDKResult,
8    api::{ApiRequest, ApiResponseTrait, ResponseFormat},
9    config::Config,
10    validate_required,
11};
12use serde::{Deserialize, Serialize};
13use std::sync::Arc;
14
15/// 创建自定义字段选项请求体
16#[derive(Debug, Clone, Serialize, Default)]
17pub struct CreateCustomFieldOptionBody {
18    /// 选项名称
19    pub name: String,
20    /// 选项颜色(可选)
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub color: Option<String>,
23}
24
25/// 自定义字段选项信息
26#[derive(Debug, Clone, Deserialize)]
27pub struct CustomFieldOption {
28    /// 选项 GUID
29    pub option_guid: String,
30    /// 选项名称
31    pub name: String,
32    /// 选项颜色
33    #[serde(default)]
34    pub color: Option<String>,
35    /// 创建时间
36    pub created_at: String,
37    /// 更新时间
38    pub updated_at: String,
39}
40
41/// 创建自定义字段选项响应
42#[derive(Debug, Clone, Deserialize)]
43pub struct CreateCustomFieldOptionResponse {
44    /// 选项信息
45    pub option: CustomFieldOption,
46}
47
48/// 创建自定义字段选项请求
49#[derive(Debug, Clone)]
50pub struct CreateCustomFieldOptionRequest {
51    /// 配置信息
52    config: Arc<Config>,
53    /// 自定义字段 GUID
54    custom_field_guid: String,
55    /// 请求体
56    body: CreateCustomFieldOptionBody,
57}
58
59impl CreateCustomFieldOptionRequest {
60    /// 创建新的请求构建器。
61    pub fn new(config: Arc<Config>, custom_field_guid: impl Into<String>) -> Self {
62        Self {
63            config,
64            custom_field_guid: custom_field_guid.into(),
65            body: CreateCustomFieldOptionBody::default(),
66        }
67    }
68
69    /// 设置选项名称
70    pub fn name(mut self, name: impl Into<String>) -> Self {
71        self.body.name = name.into();
72        self
73    }
74
75    /// 设置选项颜色
76    pub fn color(mut self, color: impl Into<String>) -> Self {
77        self.body.color = Some(color.into());
78        self
79    }
80
81    /// 执行请求
82    pub async fn execute(self) -> SDKResult<CreateCustomFieldOptionResponse> {
83        self.execute_with_options(openlark_core::req_option::RequestOption::default())
84            .await
85    }
86
87    /// 执行请求(带选项)
88    pub async fn execute_with_options(
89        self,
90        option: openlark_core::req_option::RequestOption,
91    ) -> SDKResult<CreateCustomFieldOptionResponse> {
92        // 验证必填字段
93        validate_required!(self.custom_field_guid.trim(), "自定义字段GUID不能为空");
94        validate_required!(self.body.name.trim(), "选项名称不能为空");
95
96        let api_endpoint = TaskApiV2::CustomFieldOptionCreate(self.custom_field_guid.clone());
97        let mut request =
98            ApiRequest::<CreateCustomFieldOptionResponse>::post(api_endpoint.to_url());
99
100        let request_body = &self.body;
101        request = request.body(serialize_params(request_body, "创建自定义字段选项")?);
102
103        let response =
104            openlark_core::http::Transport::request(request, &self.config, Some(option)).await?;
105        extract_response_data(response, "创建自定义字段选项")
106    }
107}
108
109impl ApiResponseTrait for CreateCustomFieldOptionResponse {
110    fn data_format() -> ResponseFormat {
111        ResponseFormat::Data
112    }
113}
114
115#[cfg(test)]
116#[allow(unused_imports)]
117mod tests {
118    use std::sync::Arc;
119
120    use super::*;
121
122    #[test]
123    fn test_create_custom_field_option_builder() {
124        let config = Arc::new(
125            openlark_core::config::Config::builder()
126                .app_id("test")
127                .app_secret("test")
128                .build(),
129        );
130
131        let request = CreateCustomFieldOptionRequest::new(config, "custom_field_123")
132            .name("高优先级")
133            .color("#FF0000");
134
135        assert_eq!(request.custom_field_guid, "custom_field_123");
136        assert_eq!(request.body.name, "高优先级");
137        assert_eq!(request.body.color, Some("#FF0000".to_string()));
138    }
139
140    #[test]
141    fn test_custom_field_option_create_api_v2_url() {
142        let endpoint = TaskApiV2::CustomFieldOptionCreate("custom_field_123".to_string());
143        assert_eq!(
144            endpoint.to_url(),
145            "/open-apis/task/v2/custom_fields/custom_field_123/options"
146        );
147    }
148}