1use crate::service::bitable::v1::app_table_field::Person;
2use serde::{Deserialize, Serialize};
3use serde_json::Value;
4use std::collections::HashMap;
5
6#[derive(Debug, Default, Serialize, Deserialize, Clone)]
7pub struct Record {
8 pub fields: HashMap<String, Value>,
9 pub record_id: Option<String>,
11 pub created_by: Option<Person>,
13 pub created_time: Option<u128>,
15 pub last_modified_by: Option<Person>,
17 pub last_modified_time: Option<u128>,
19}
20
21impl Record {
22 pub fn from_json(json: Value) -> Self {
23 let obj = json.as_object().expect("json must be a object");
24 let mut fields = HashMap::new();
25 for (k, v) in obj.iter() {
26 fields.insert(k.clone(), v.clone());
27 }
28 Record {
29 fields,
30 record_id: None,
31 created_by: None,
32 created_time: None,
33 last_modified_by: None,
34 last_modified_time: None,
35 }
36 }
37}
38
39impl Record {
41 pub fn get_text(&self, key: &str) -> Option<String> {
43 let value = self.fields.get(key)?;
44 let array = value.as_array()?;
45 let first_item = array.first()?;
46 let text = first_item.get("text")?.as_str()?;
47 Some(text.to_string())
48 }
49
50 pub fn get_number(&self, key: &str) -> Option<f64> {
52 let value = self.fields.get(key)?;
53 let number = value.as_f64()?;
54 Some(number)
55 }
56
57 pub fn get_array_text(&self, key: &str) -> Option<Vec<String>> {
59 let value = self.fields.get(key)?;
60 let array = value.as_array()?;
61 let mut texts = Vec::new();
62 for item in array {
63 let text = item.as_str()?.to_string();
64 texts.push(text);
65 }
66 Some(texts)
67 }
68
69 pub fn get_single_select_text(&self, key: &str) -> Option<String> {
71 let value = self.fields.get(key)?;
72 let text = value.as_str()?;
73 Some(text.to_string())
74 }
75
76 pub fn get_multi_select_text(&self, key: &str) -> Option<Vec<String>> {
78 let value = self.fields.get(key)?;
79 let array = value.as_array()?;
80 let mut texts = Vec::new();
81 for item in array {
82 let text = item.as_str()?.to_string();
83 texts.push(text);
84 }
85 Some(texts)
86 }
87
88 pub fn get_checkbox(&self, key: &str) -> Option<bool> {
90 let value = self.fields.get(key)?;
91 let checkbox = value.as_bool()?;
92 Some(checkbox)
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use serde_json::json;
100
101 #[test]
102 fn test_record_default() {
103 let record = Record::default();
104 assert!(record.fields.is_empty());
105 assert!(record.record_id.is_none());
106 assert!(record.created_by.is_none());
107 assert!(record.created_time.is_none());
108 assert!(record.last_modified_by.is_none());
109 assert!(record.last_modified_time.is_none());
110 }
111
112 #[test]
113 fn test_record_debug() {
114 let record = Record::default();
115 let debug_str = format!("{:?}", record);
116 assert!(debug_str.contains("Record"));
117 }
118
119 #[test]
120 fn test_record_clone() {
121 let mut record = Record::default();
122 record.fields.insert("test".to_string(), json!("value"));
123 record.record_id = Some("rec123".to_string());
124
125 let cloned = record.clone();
126 assert_eq!(record.fields, cloned.fields);
127 assert_eq!(record.record_id, cloned.record_id);
128 }
129
130 #[test]
131 fn test_record_serialization() {
132 let mut record = Record::default();
133 record.fields.insert("name".to_string(), json!("Test"));
134 record.record_id = Some("rec_001".to_string());
135
136 let serialized = serde_json::to_string(&record).expect("Should serialize");
137 let deserialized: Record = serde_json::from_str(&serialized).expect("Should deserialize");
138
139 assert_eq!(record.fields, deserialized.fields);
140 assert_eq!(record.record_id, deserialized.record_id);
141 }
142
143 #[test]
144 fn test_record_from_json_simple() {
145 let json = json!({
146 "name": "John Doe",
147 "age": 30,
148 "active": true
149 });
150
151 let record = Record::from_json(json);
152 assert_eq!(record.fields.len(), 3);
153 assert_eq!(record.fields.get("name"), Some(&json!("John Doe")));
154 assert_eq!(record.fields.get("age"), Some(&json!(30)));
155 assert_eq!(record.fields.get("active"), Some(&json!(true)));
156 }
157
158 #[test]
159 fn test_record_from_json_empty() {
160 let json = json!({});
161 let record = Record::from_json(json);
162 assert!(record.fields.is_empty());
163 assert!(record.record_id.is_none());
164 }
165
166 #[test]
167 fn test_record_from_json_complex() {
168 let json = json!({
169 "text_field": "value",
170 "number_field": 42.5,
171 "array_field": ["item1", "item2"],
172 "object_field": {
173 "nested": "value"
174 }
175 });
176
177 let record = Record::from_json(json);
178 assert_eq!(record.fields.len(), 4);
179 assert_eq!(record.fields.get("text_field"), Some(&json!("value")));
180 assert_eq!(record.fields.get("number_field"), Some(&json!(42.5)));
181 assert_eq!(
182 record.fields.get("array_field"),
183 Some(&json!(["item1", "item2"]))
184 );
185 assert_eq!(
186 record.fields.get("object_field"),
187 Some(&json!({"nested": "value"}))
188 );
189 }
190
191 #[test]
192 #[should_panic(expected = "json must be a object")]
193 fn test_record_from_json_invalid_type() {
194 let json = json!("not an object");
195 Record::from_json(json);
196 }
197
198 #[test]
199 fn test_get_text() {
200 let mut record = Record::default();
201 record
202 .fields
203 .insert("text_field".to_string(), json!([{"text": "Hello World"}]));
204
205 let text = record.get_text("text_field");
206 assert_eq!(text, Some("Hello World".to_string()));
207 }
208
209 #[test]
210 fn test_get_text_nonexistent_key() {
211 let record = Record::default();
212 let text = record.get_text("nonexistent");
213 assert_eq!(text, None);
214 }
215
216 #[test]
217 fn test_get_text_invalid_format() {
218 let mut record = Record::default();
219 record
220 .fields
221 .insert("invalid".to_string(), json!("not an array"));
222
223 let text = record.get_text("invalid");
224 assert_eq!(text, None);
225 }
226
227 #[test]
228 fn test_get_text_empty_array() {
229 let mut record = Record::default();
230 record.fields.insert("empty_array".to_string(), json!([]));
231
232 let text = record.get_text("empty_array");
233 assert_eq!(text, None);
234 }
235
236 #[test]
237 fn test_get_text_missing_text_field() {
238 let mut record = Record::default();
239 record
240 .fields
241 .insert("no_text".to_string(), json!([{"value": "test"}]));
242
243 let text = record.get_text("no_text");
244 assert_eq!(text, None);
245 }
246
247 #[test]
248 fn test_get_number() {
249 let mut record = Record::default();
250 record
251 .fields
252 .insert("number_field".to_string(), json!(42.5));
253
254 let number = record.get_number("number_field");
255 assert_eq!(number, Some(42.5));
256 }
257
258 #[test]
259 fn test_get_number_integer() {
260 let mut record = Record::default();
261 record.fields.insert("int_field".to_string(), json!(42));
262
263 let number = record.get_number("int_field");
264 assert_eq!(number, Some(42.0));
265 }
266
267 #[test]
268 fn test_get_number_nonexistent() {
269 let record = Record::default();
270 let number = record.get_number("nonexistent");
271 assert_eq!(number, None);
272 }
273
274 #[test]
275 fn test_get_number_invalid_type() {
276 let mut record = Record::default();
277 record
278 .fields
279 .insert("text_field".to_string(), json!("not a number"));
280
281 let number = record.get_number("text_field");
282 assert_eq!(number, None);
283 }
284
285 #[test]
286 fn test_get_array_text() {
287 let mut record = Record::default();
288 record.fields.insert(
289 "array_field".to_string(),
290 json!(["item1", "item2", "item3"]),
291 );
292
293 let array = record.get_array_text("array_field");
294 assert_eq!(
295 array,
296 Some(vec![
297 "item1".to_string(),
298 "item2".to_string(),
299 "item3".to_string()
300 ])
301 );
302 }
303
304 #[test]
305 fn test_get_array_text_empty() {
306 let mut record = Record::default();
307 record.fields.insert("empty_array".to_string(), json!([]));
308
309 let array = record.get_array_text("empty_array");
310 assert_eq!(array, Some(vec![]));
311 }
312
313 #[test]
314 fn test_get_array_text_nonexistent() {
315 let record = Record::default();
316 let array = record.get_array_text("nonexistent");
317 assert_eq!(array, None);
318 }
319
320 #[test]
321 fn test_get_array_text_invalid_type() {
322 let mut record = Record::default();
323 record
324 .fields
325 .insert("not_array".to_string(), json!("string"));
326
327 let array = record.get_array_text("not_array");
328 assert_eq!(array, None);
329 }
330
331 #[test]
332 fn test_get_array_text_invalid_element() {
333 let mut record = Record::default();
334 record.fields.insert(
335 "mixed_array".to_string(),
336 json!(["valid", 123, "also_valid"]),
337 );
338
339 let array = record.get_array_text("mixed_array");
340 assert_eq!(array, None); }
342
343 #[test]
344 fn test_get_single_select_text() {
345 let mut record = Record::default();
346 record
347 .fields
348 .insert("select_field".to_string(), json!("Selected Option"));
349
350 let text = record.get_single_select_text("select_field");
351 assert_eq!(text, Some("Selected Option".to_string()));
352 }
353
354 #[test]
355 fn test_get_single_select_text_nonexistent() {
356 let record = Record::default();
357 let text = record.get_single_select_text("nonexistent");
358 assert_eq!(text, None);
359 }
360
361 #[test]
362 fn test_get_single_select_text_invalid_type() {
363 let mut record = Record::default();
364 record.fields.insert("number_field".to_string(), json!(42));
365
366 let text = record.get_single_select_text("number_field");
367 assert_eq!(text, None);
368 }
369
370 #[test]
371 fn test_get_multi_select_text() {
372 let mut record = Record::default();
373 record.fields.insert(
374 "multi_select".to_string(),
375 json!(["Option1", "Option2", "Option3"]),
376 );
377
378 let texts = record.get_multi_select_text("multi_select");
379 assert_eq!(
380 texts,
381 Some(vec![
382 "Option1".to_string(),
383 "Option2".to_string(),
384 "Option3".to_string()
385 ])
386 );
387 }
388
389 #[test]
390 fn test_get_multi_select_text_empty() {
391 let mut record = Record::default();
392 record.fields.insert("empty_multi".to_string(), json!([]));
393
394 let texts = record.get_multi_select_text("empty_multi");
395 assert_eq!(texts, Some(vec![]));
396 }
397
398 #[test]
399 fn test_get_multi_select_text_nonexistent() {
400 let record = Record::default();
401 let texts = record.get_multi_select_text("nonexistent");
402 assert_eq!(texts, None);
403 }
404
405 #[test]
406 fn test_get_multi_select_text_invalid_type() {
407 let mut record = Record::default();
408 record
409 .fields
410 .insert("string_field".to_string(), json!("not an array"));
411
412 let texts = record.get_multi_select_text("string_field");
413 assert_eq!(texts, None);
414 }
415
416 #[test]
417 fn test_get_multi_select_text_invalid_element() {
418 let mut record = Record::default();
419 record.fields.insert(
420 "mixed_multi".to_string(),
421 json!(["valid", 456, "also_valid"]),
422 );
423
424 let texts = record.get_multi_select_text("mixed_multi");
425 assert_eq!(texts, None); }
427
428 #[test]
429 fn test_get_checkbox() {
430 let mut record = Record::default();
431 record
432 .fields
433 .insert("checkbox_true".to_string(), json!(true));
434 record
435 .fields
436 .insert("checkbox_false".to_string(), json!(false));
437
438 let check_true = record.get_checkbox("checkbox_true");
439 let check_false = record.get_checkbox("checkbox_false");
440
441 assert_eq!(check_true, Some(true));
442 assert_eq!(check_false, Some(false));
443 }
444
445 #[test]
446 fn test_get_checkbox_nonexistent() {
447 let record = Record::default();
448 let checkbox = record.get_checkbox("nonexistent");
449 assert_eq!(checkbox, None);
450 }
451
452 #[test]
453 fn test_get_checkbox_invalid_type() {
454 let mut record = Record::default();
455 record
456 .fields
457 .insert("string_field".to_string(), json!("not a boolean"));
458
459 let checkbox = record.get_checkbox("string_field");
460 assert_eq!(checkbox, None);
461 }
462
463 #[test]
464 fn test_record_with_person_fields() {
465 let person = Person {
466 id: "person_123".to_string(),
467 name: "John Doe".to_string(),
468 en_name: "John Doe".to_string(),
469 email: "john@example.com".to_string(),
470 };
471
472 let record = Record {
473 fields: HashMap::new(),
474 record_id: Some("rec_456".to_string()),
475 created_by: Some(person.clone()),
476 created_time: Some(1640995200000),
477 last_modified_by: Some(person),
478 last_modified_time: Some(1640995260000),
479 };
480
481 assert_eq!(record.record_id, Some("rec_456".to_string()));
482 assert_eq!(record.created_time, Some(1640995200000));
483 assert_eq!(record.last_modified_time, Some(1640995260000));
484 assert!(record.created_by.is_some());
485 assert!(record.last_modified_by.is_some());
486 }
487
488 #[test]
489 fn test_record_comprehensive_field_access() {
490 let mut record = Record::default();
491 record
492 .fields
493 .insert("text_field".to_string(), json!([{"text": "Sample Text"}]));
494 record
495 .fields
496 .insert("number_field".to_string(), json!(123.45));
497 record
498 .fields
499 .insert("array_text".to_string(), json!(["A", "B", "C"]));
500 record
501 .fields
502 .insert("single_select".to_string(), json!("Option A"));
503 record
504 .fields
505 .insert("multi_select".to_string(), json!(["X", "Y", "Z"]));
506 record
507 .fields
508 .insert("checkbox_field".to_string(), json!(true));
509
510 assert_eq!(
512 record.get_text("text_field"),
513 Some("Sample Text".to_string())
514 );
515 assert_eq!(record.get_number("number_field"), Some(123.45));
516 assert_eq!(
517 record.get_array_text("array_text"),
518 Some(vec!["A".to_string(), "B".to_string(), "C".to_string()])
519 );
520 assert_eq!(
521 record.get_single_select_text("single_select"),
522 Some("Option A".to_string())
523 );
524 assert_eq!(
525 record.get_multi_select_text("multi_select"),
526 Some(vec!["X".to_string(), "Y".to_string(), "Z".to_string()])
527 );
528 assert_eq!(record.get_checkbox("checkbox_field"), Some(true));
529 }
530
531 #[test]
532 fn test_record_with_unicode_content() {
533 let mut record = Record::default();
534 record
535 .fields
536 .insert("chinese_text".to_string(), json!([{"text": "你好世界"}]));
537 record
538 .fields
539 .insert("emoji_field".to_string(), json!("🚀💻🎉"));
540 record
541 .fields
542 .insert("unicode_array".to_string(), json!(["测试", "テスト", "🌟"]));
543
544 assert_eq!(
545 record.get_text("chinese_text"),
546 Some("你好世界".to_string())
547 );
548 assert_eq!(
549 record.get_single_select_text("emoji_field"),
550 Some("🚀💻🎉".to_string())
551 );
552 assert_eq!(
553 record.get_array_text("unicode_array"),
554 Some(vec![
555 "测试".to_string(),
556 "テスト".to_string(),
557 "🌟".to_string()
558 ])
559 );
560 }
561
562 #[test]
563 fn test_record_edge_cases() {
564 let mut record = Record::default();
565
566 record
568 .fields
569 .insert("empty_text".to_string(), json!([{"text": ""}]));
570 record.fields.insert("empty_select".to_string(), json!(""));
571
572 record.fields.insert("zero_number".to_string(), json!(0));
574 record.fields.insert("zero_float".to_string(), json!(0.0));
575
576 assert_eq!(record.get_text("empty_text"), Some("".to_string()));
577 assert_eq!(
578 record.get_single_select_text("empty_select"),
579 Some("".to_string())
580 );
581 assert_eq!(record.get_number("zero_number"), Some(0.0));
582 assert_eq!(record.get_number("zero_float"), Some(0.0));
583 }
584
585 #[test]
586 fn test_record_memory_efficiency() {
587 let record = Record::default();
588 let size = std::mem::size_of_val(&record);
589
590 assert!(size > 0);
592 assert!(size < 1024); }
594
595 #[test]
596 fn test_record_large_data() {
597 let mut record = Record::default();
598
599 let large_text = "x".repeat(10000);
601 record.fields.insert(
602 "large_field".to_string(),
603 json!([{"text": large_text.clone()}]),
604 );
605
606 let large_array: Vec<String> = (0..1000).map(|i| format!("item_{}", i)).collect();
608 record
609 .fields
610 .insert("large_array".to_string(), json!(large_array.clone()));
611
612 assert_eq!(record.get_text("large_field"), Some(large_text));
613 assert_eq!(record.get_array_text("large_array"), Some(large_array));
614 }
615}