1use serde::Serialize;
4
5#[derive(Debug, Clone, Default, PartialEq, Serialize)]
18pub struct HojinSearchQuery {
19 #[serde(skip_serializing_if = "Option::is_none")]
21 pub corporate_number: Option<String>,
22 #[serde(skip_serializing_if = "Option::is_none")]
24 pub name: Option<String>,
25 #[serde(skip_serializing_if = "Option::is_none")]
27 pub exist_flg: Option<bool>,
28 #[serde(skip_serializing_if = "Option::is_none")]
32 pub corporate_type: Option<String>,
33 #[serde(skip_serializing_if = "Option::is_none")]
35 pub prefecture: Option<String>,
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub city: Option<String>,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub capital_stock_from: Option<u64>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub capital_stock_to: Option<u64>,
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub employee_number_from: Option<u64>,
48 #[serde(skip_serializing_if = "Option::is_none")]
50 pub employee_number_to: Option<u64>,
51 #[serde(skip_serializing_if = "Option::is_none")]
53 pub founded_year: Option<String>,
54 #[serde(skip_serializing_if = "Option::is_none")]
56 pub net_sales_summary_of_business_results_from: Option<u64>,
57 #[serde(skip_serializing_if = "Option::is_none")]
59 pub net_sales_summary_of_business_results_to: Option<u64>,
60 #[serde(skip_serializing_if = "Option::is_none")]
62 pub total_assets_summary_of_business_results_from: Option<u64>,
63 #[serde(skip_serializing_if = "Option::is_none")]
65 pub total_assets_summary_of_business_results_to: Option<u64>,
66 #[serde(skip_serializing_if = "Option::is_none")]
68 pub average_continuous_service_years: Option<String>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub average_age: Option<String>,
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub month_average_predetermined_overtime_hours: Option<String>,
75 #[serde(skip_serializing_if = "Option::is_none")]
77 pub female_workers_proportion: Option<String>,
78 #[serde(skip_serializing_if = "Option::is_none")]
80 pub patent: Option<String>,
81 #[serde(skip_serializing_if = "Option::is_none")]
83 pub procurement: Option<String>,
84 #[serde(skip_serializing_if = "Option::is_none")]
86 pub procurement_amount_from: Option<u64>,
87 #[serde(skip_serializing_if = "Option::is_none")]
89 pub procurement_amount_to: Option<u64>,
90 #[serde(skip_serializing_if = "Option::is_none")]
92 pub subsidy: Option<String>,
93 #[serde(skip_serializing_if = "Option::is_none")]
95 pub subsidy_amount_from: Option<u64>,
96 #[serde(skip_serializing_if = "Option::is_none")]
98 pub subsidy_amount_to: Option<u64>,
99 #[serde(skip_serializing_if = "Option::is_none")]
101 pub certification: Option<String>,
102 #[serde(skip_serializing_if = "Option::is_none")]
104 pub ministry: Option<String>,
105 #[serde(skip_serializing_if = "Option::is_none")]
108 pub source: Option<String>,
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub page: Option<u32>,
112 #[serde(skip_serializing_if = "Option::is_none")]
114 pub limit: Option<u32>,
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub metadata_flg: Option<bool>,
118}
119
120impl HojinSearchQuery {
121 pub fn new() -> Self {
123 Self::default()
124 }
125
126 pub fn corporate_number(mut self, value: impl Into<String>) -> Self {
128 self.corporate_number = Some(value.into());
129 self
130 }
131
132 pub fn name(mut self, value: impl Into<String>) -> Self {
134 self.name = Some(value.into());
135 self
136 }
137
138 pub fn exist_flg(mut self, value: bool) -> Self {
140 self.exist_flg = Some(value);
141 self
142 }
143
144 pub fn corporate_type(mut self, value: impl Into<String>) -> Self {
146 self.corporate_type = Some(value.into());
147 self
148 }
149
150 pub fn prefecture(mut self, value: impl Into<String>) -> Self {
152 self.prefecture = Some(value.into());
153 self
154 }
155
156 pub fn city(mut self, value: impl Into<String>) -> Self {
158 self.city = Some(value.into());
159 self
160 }
161
162 pub fn capital_stock(mut self, from: Option<u64>, to: Option<u64>) -> Self {
164 self.capital_stock_from = from;
165 self.capital_stock_to = to;
166 self
167 }
168
169 pub fn employee_number(mut self, from: Option<u64>, to: Option<u64>) -> Self {
171 self.employee_number_from = from;
172 self.employee_number_to = to;
173 self
174 }
175
176 pub fn founded_year(mut self, value: impl Into<String>) -> Self {
178 self.founded_year = Some(value.into());
179 self
180 }
181
182 pub fn net_sales(mut self, from: Option<u64>, to: Option<u64>) -> Self {
184 self.net_sales_summary_of_business_results_from = from;
185 self.net_sales_summary_of_business_results_to = to;
186 self
187 }
188
189 pub fn total_assets(mut self, from: Option<u64>, to: Option<u64>) -> Self {
191 self.total_assets_summary_of_business_results_from = from;
192 self.total_assets_summary_of_business_results_to = to;
193 self
194 }
195
196 pub fn average_continuous_service_years(mut self, value: impl Into<String>) -> Self {
198 self.average_continuous_service_years = Some(value.into());
199 self
200 }
201
202 pub fn average_age(mut self, value: impl Into<String>) -> Self {
204 self.average_age = Some(value.into());
205 self
206 }
207
208 pub fn month_average_predetermined_overtime_hours(mut self, value: impl Into<String>) -> Self {
210 self.month_average_predetermined_overtime_hours = Some(value.into());
211 self
212 }
213
214 pub fn female_workers_proportion(mut self, value: impl Into<String>) -> Self {
216 self.female_workers_proportion = Some(value.into());
217 self
218 }
219
220 pub fn patent(mut self, value: impl Into<String>) -> Self {
222 self.patent = Some(value.into());
223 self
224 }
225
226 pub fn procurement(mut self, value: impl Into<String>) -> Self {
228 self.procurement = Some(value.into());
229 self
230 }
231
232 pub fn procurement_amount(mut self, from: Option<u64>, to: Option<u64>) -> Self {
234 self.procurement_amount_from = from;
235 self.procurement_amount_to = to;
236 self
237 }
238
239 pub fn subsidy(mut self, value: impl Into<String>) -> Self {
241 self.subsidy = Some(value.into());
242 self
243 }
244
245 pub fn subsidy_amount(mut self, from: Option<u64>, to: Option<u64>) -> Self {
247 self.subsidy_amount_from = from;
248 self.subsidy_amount_to = to;
249 self
250 }
251
252 pub fn certification(mut self, value: impl Into<String>) -> Self {
254 self.certification = Some(value.into());
255 self
256 }
257
258 pub fn ministry(mut self, value: impl Into<String>) -> Self {
260 self.ministry = Some(value.into());
261 self
262 }
263
264 pub fn source(mut self, value: impl Into<String>) -> Self {
266 self.source = Some(value.into());
267 self
268 }
269
270 pub fn page(mut self, value: u32) -> Self {
272 self.page = Some(value);
273 self
274 }
275
276 pub fn limit(mut self, value: u32) -> Self {
278 self.limit = Some(value);
279 self
280 }
281
282 pub fn metadata_flg(mut self, value: bool) -> Self {
284 self.metadata_flg = Some(value);
285 self
286 }
287}
288
289#[derive(Debug, Clone, PartialEq, Serialize)]
299pub struct UpdateInfoQuery {
300 pub from: String,
302 pub to: String,
304 #[serde(skip_serializing_if = "Option::is_none")]
306 pub page: Option<u32>,
307 #[serde(skip_serializing_if = "Option::is_none")]
309 pub metadata_flg: Option<bool>,
310}
311
312impl UpdateInfoQuery {
313 pub fn new(from: impl Into<String>, to: impl Into<String>) -> Self {
315 Self {
316 from: from.into(),
317 to: to.into(),
318 page: None,
319 metadata_flg: None,
320 }
321 }
322
323 pub fn page(mut self, value: u32) -> Self {
325 self.page = Some(value);
326 self
327 }
328
329 pub fn metadata_flg(mut self, value: bool) -> Self {
331 self.metadata_flg = Some(value);
332 self
333 }
334}
335
336#[cfg(test)]
337mod tests {
338 use super::*;
339 use serde_json::{json, Value};
340
341 #[test]
342 fn search_query_skips_unset_fields() {
343 let query = HojinSearchQuery::new();
344 let value = serde_json::to_value(&query).unwrap();
345 assert_eq!(value, json!({}));
346 }
347
348 #[test]
349 fn search_query_serializes_set_fields() {
350 let query = HojinSearchQuery::new()
351 .name("トヨタ自動車")
352 .corporate_type("301")
353 .exist_flg(true)
354 .capital_stock(Some(1_000_000), None)
355 .page(1)
356 .limit(100)
357 .metadata_flg(false);
358 let value = serde_json::to_value(&query).unwrap();
359 assert_eq!(
360 value,
361 json!({
362 "name": "トヨタ自動車",
363 "corporate_type": "301",
364 "exist_flg": true,
365 "capital_stock_from": 1_000_000,
366 "page": 1,
367 "limit": 100,
368 "metadata_flg": false,
369 })
370 );
371 }
372
373 #[test]
374 fn search_query_all_fields_serialize() {
375 let query = HojinSearchQuery::new()
376 .corporate_number("1180301018771")
377 .name("n")
378 .exist_flg(true)
379 .corporate_type("301")
380 .prefecture("23")
381 .city("211")
382 .capital_stock(Some(1), Some(2))
383 .employee_number(Some(3), Some(4))
384 .founded_year("1937,1938")
385 .net_sales(Some(5), Some(6))
386 .total_assets(Some(7), Some(8))
387 .average_continuous_service_years("A")
388 .average_age("B")
389 .month_average_predetermined_overtime_hours("C")
390 .female_workers_proportion("D")
391 .patent("p")
392 .procurement("q")
393 .procurement_amount(Some(9), Some(10))
394 .subsidy("s")
395 .subsidy_amount(Some(11), Some(12))
396 .certification("c")
397 .ministry("100,200")
398 .source("1,6")
399 .page(2)
400 .limit(500)
401 .metadata_flg(true);
402 let value = serde_json::to_value(&query).unwrap();
403 let Value::Object(map) = value else {
404 panic!("object expected")
405 };
406 assert_eq!(map.len(), 32);
408 }
409
410 #[test]
411 fn update_info_query_serializes() {
412 let query = UpdateInfoQuery::new("20260401", "20260430");
413 let value = serde_json::to_value(&query).unwrap();
414 assert_eq!(value, json!({"from": "20260401", "to": "20260430"}));
415
416 let query = UpdateInfoQuery::new("20260401", "20260430")
417 .page(2)
418 .metadata_flg(true);
419 let value = serde_json::to_value(&query).unwrap();
420 assert_eq!(
421 value,
422 json!({"from": "20260401", "to": "20260430", "page": 2, "metadata_flg": true})
423 );
424 }
425}