Skip to main content

uls_core/records/
entity.rs

1//! EN (Entity) record type - Licensee/Applicant information.
2
3use serde::{Deserialize, Serialize};
4
5use super::common::*;
6
7/// EN record - Entity (licensee/applicant names and addresses).
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct EntityRecord {
10    pub unique_system_identifier: i64,
11    pub uls_file_number: Option<String>,
12    pub ebf_number: Option<String>,
13    pub call_sign: Option<String>,
14    pub entity_type: Option<String>,
15    pub licensee_id: Option<String>,
16    pub entity_name: Option<String>,
17    pub first_name: Option<String>,
18    pub mi: Option<char>,
19    pub last_name: Option<String>,
20    pub suffix: Option<String>,
21    pub phone: Option<String>,
22    pub fax: Option<String>,
23    pub email: Option<String>,
24    pub street_address: Option<String>,
25    pub city: Option<String>,
26    pub state: Option<String>,
27    pub zip_code: Option<String>,
28    pub po_box: Option<String>,
29    pub attention_line: Option<String>,
30    pub sgin: Option<String>,
31    pub frn: Option<String>,
32    pub applicant_type_code: Option<char>,
33    pub applicant_type_other: Option<String>,
34    pub status_code: Option<char>,
35    pub status_date: Option<String>,
36    pub lic_category_code: Option<char>,
37    pub linked_license_id: Option<i64>,
38    pub linked_callsign: Option<String>,
39}
40
41impl EntityRecord {
42    /// Parse an entity record from pipe-delimited fields.
43    pub fn from_fields(fields: &[&str]) -> Self {
44        Self {
45            unique_system_identifier: parse_i64_or_default(fields.get(1).unwrap_or(&"")),
46            uls_file_number: parse_opt_string(fields.get(2).unwrap_or(&"")),
47            ebf_number: parse_opt_string(fields.get(3).unwrap_or(&"")),
48            call_sign: parse_opt_string(fields.get(4).unwrap_or(&"")),
49            entity_type: parse_opt_string(fields.get(5).unwrap_or(&"")),
50            licensee_id: parse_opt_string(fields.get(6).unwrap_or(&"")),
51            entity_name: parse_opt_string(fields.get(7).unwrap_or(&"")),
52            first_name: parse_opt_string(fields.get(8).unwrap_or(&"")),
53            mi: parse_opt_char(fields.get(9).unwrap_or(&"")),
54            last_name: parse_opt_string(fields.get(10).unwrap_or(&"")),
55            suffix: parse_opt_string(fields.get(11).unwrap_or(&"")),
56            phone: parse_opt_string(fields.get(12).unwrap_or(&"")),
57            fax: parse_opt_string(fields.get(13).unwrap_or(&"")),
58            email: parse_opt_string(fields.get(14).unwrap_or(&"")),
59            street_address: parse_opt_string(fields.get(15).unwrap_or(&"")),
60            city: parse_opt_string(fields.get(16).unwrap_or(&"")),
61            state: parse_opt_string(fields.get(17).unwrap_or(&"")),
62            zip_code: parse_opt_string(fields.get(18).unwrap_or(&"")),
63            po_box: parse_opt_string(fields.get(19).unwrap_or(&"")),
64            attention_line: parse_opt_string(fields.get(20).unwrap_or(&"")),
65            sgin: parse_opt_string(fields.get(21).unwrap_or(&"")),
66            frn: parse_opt_string(fields.get(22).unwrap_or(&"")),
67            applicant_type_code: parse_opt_char(fields.get(23).unwrap_or(&"")),
68            applicant_type_other: parse_opt_string(fields.get(24).unwrap_or(&"")),
69            status_code: parse_opt_char(fields.get(25).unwrap_or(&"")),
70            status_date: parse_opt_string(fields.get(26).unwrap_or(&"")),
71            lic_category_code: parse_opt_char(fields.get(27).unwrap_or(&"")),
72            linked_license_id: parse_opt_i64(fields.get(28).unwrap_or(&"")),
73            linked_callsign: parse_opt_string(fields.get(29).unwrap_or(&"")),
74        }
75    }
76
77    /// Returns the full name of the entity.
78    pub fn full_name(&self) -> String {
79        if let Some(ref entity_name) = self.entity_name {
80            if !entity_name.is_empty() {
81                return entity_name.clone();
82            }
83        }
84
85        let mut parts = Vec::new();
86        if let Some(ref first) = self.first_name {
87            parts.push(first.as_str());
88        }
89        if let Some(mi) = self.mi {
90            parts.push(Box::leak(mi.to_string().into_boxed_str()));
91        }
92        if let Some(ref last) = self.last_name {
93            parts.push(last.as_str());
94        }
95        if let Some(ref suffix) = self.suffix {
96            parts.push(suffix.as_str());
97        }
98        parts.join(" ")
99    }
100
101    /// Returns the full address as a single string.
102    pub fn full_address(&self) -> String {
103        let mut parts = Vec::new();
104        if let Some(ref addr) = self.street_address {
105            parts.push(addr.clone());
106        }
107        if let Some(ref city) = self.city {
108            let city_state_zip = format!(
109                "{}, {} {}",
110                city,
111                self.state.as_deref().unwrap_or(""),
112                self.zip_code.as_deref().unwrap_or("")
113            );
114            parts.push(city_state_zip.trim().to_string());
115        }
116        parts.join(", ")
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[test]
125    fn test_entity_from_fields() {
126        let fields: Vec<&str> = vec![
127            "EN",
128            "123456789",
129            "",
130            "",
131            "W1AW",
132            "L",
133            "L00001",
134            "",
135            "HIRAM",
136            "P",
137            "MAXIM",
138            "JR",
139            "8601234567",
140            "",
141            "test@example.com",
142            "225 MAIN ST",
143            "NEWINGTON",
144            "CT",
145            "06111",
146            "",
147            "",
148            "",
149            "0001234567",
150            "I",
151            "",
152            "",
153            "",
154            "",
155            "",
156            "",
157        ];
158        let record = EntityRecord::from_fields(&fields);
159        assert_eq!(record.unique_system_identifier, 123456789);
160        assert_eq!(record.call_sign, Some("W1AW".to_string()));
161        assert_eq!(record.first_name, Some("HIRAM".to_string()));
162        assert_eq!(record.last_name, Some("MAXIM".to_string()));
163        assert_eq!(record.city, Some("NEWINGTON".to_string()));
164        assert_eq!(record.state, Some("CT".to_string()));
165    }
166
167    #[test]
168    fn test_full_name() {
169        let mut record = EntityRecord::from_fields(&["EN", "123"]);
170        record.first_name = Some("John".to_string());
171        record.last_name = Some("Doe".to_string());
172        assert_eq!(record.full_name(), "John Doe");
173
174        record.entity_name = Some("ACME Corp".to_string());
175        assert_eq!(record.full_name(), "ACME Corp");
176    }
177}