use std::collections::HashMap;
use serde::{
Deserialize, Serialize,
de::{IntoDeserializer, value::MapDeserializer},
};
use crate::application::utils::de_with::{deserialize_bool_string, deserialize_optional_string};
use crate::application::utils::sap_table::try_table_into_with_scroll;
use crate::{
application::student_information::StudentInformationApplication, client::USaintClient,
};
use wdpe::command::WebDynproCommandExecutor;
use wdpe::element::parser::ElementParser;
use wdpe::{
command::element::layout::TabStripTabSelectEventCommand,
define_elements,
element::{
complex::{SapTable, sap_table::FromSapTable},
definition::ElementDefinition,
layout::tab_strip::item::TabStripItem,
},
error::{ElementError, WebDynproError},
};
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct StudentFamily {
members: Vec<StudentFamilyMember>,
}
impl<'a> StudentFamily {
define_elements! {
TAB_FAMILY: TabStripItem<'a> = "ZCMW1001.ID_0001:VIW_MAIN.TAB_FAMILY";
TABLE_FAMILY: SapTable<'a> = "ZCMW1001.ID_0001:VIW_TAB_FAMILY_TABLE.TABLE_FAMILY";
}
pub(crate) async fn with_client(client: &mut USaintClient) -> Result<Self, WebDynproError> {
let mut parser = ElementParser::new(client.body());
let event = parser.read(TabStripTabSelectEventCommand::new(
StudentInformationApplication::TAB_ADDITION,
Self::TAB_FAMILY,
1,
0,
))?;
client.process_event(false, event).await?;
parser = ElementParser::new(client.body());
let members =
try_table_into_with_scroll::<StudentFamilyMember>(client, parser, Self::TABLE_FAMILY)
.await?;
Ok(Self { members })
}
pub fn members(&self) -> &[StudentFamilyMember] {
&self.members
}
}
#[derive(Clone, Serialize, Deserialize, Debug)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
pub struct StudentFamilyMember {
#[serde(
rename(deserialize = "가족 관계 유형"),
deserialize_with = "deserialize_optional_string"
)]
relation_type: Option<String>,
#[serde(
rename(deserialize = "전화번호"),
deserialize_with = "deserialize_optional_string"
)]
tel_number: Option<String>,
#[serde(
rename(deserialize = "성명"),
deserialize_with = "deserialize_optional_string"
)]
name: Option<String>,
#[serde(
rename(deserialize = "휴대전화"),
deserialize_with = "deserialize_optional_string"
)]
mobile_number: Option<String>,
#[serde(
rename(deserialize = "근무처(직장명)"),
deserialize_with = "deserialize_optional_string"
)]
office: Option<String>,
#[serde(
rename(deserialize = "직업"),
deserialize_with = "deserialize_optional_string"
)]
job: Option<String>,
#[serde(
rename(deserialize = "직위"),
deserialize_with = "deserialize_optional_string"
)]
position: Option<String>,
#[serde(
rename(deserialize = "보호자여부"),
deserialize_with = "deserialize_bool_string"
)]
is_guardian: bool,
#[serde(
rename(deserialize = "동거여부"),
deserialize_with = "deserialize_bool_string"
)]
is_cohabit: bool,
}
impl StudentFamilyMember {
pub fn relation_type(&self) -> Option<&str> {
self.relation_type.as_deref()
}
pub fn tel_number(&self) -> Option<&str> {
self.tel_number.as_deref()
}
pub fn name(&self) -> Option<&str> {
self.name.as_deref()
}
pub fn mobile_number(&self) -> Option<&str> {
self.mobile_number.as_deref()
}
pub fn office(&self) -> Option<&str> {
self.office.as_deref()
}
pub fn job(&self) -> Option<&str> {
self.job.as_deref()
}
pub fn position(&self) -> Option<&str> {
self.position.as_deref()
}
pub fn is_guardian(&self) -> bool {
self.is_guardian
}
pub fn is_cohabit(&self) -> bool {
self.is_cohabit
}
}
impl<'a> FromSapTable<'a> for StudentFamilyMember {
fn from_table(
header: Option<&'a wdpe::element::complex::sap_table::SapTableHeader>,
row: &'a wdpe::element::complex::sap_table::SapTableRow,
parser: &'a ElementParser,
) -> Result<Self, WebDynproError> {
let map_string = row.try_row_into::<HashMap<String, String>>(header, parser)?;
let map_de: MapDeserializer<_, serde::de::value::Error> = map_string.into_deserializer();
Ok(
StudentFamilyMember::deserialize(map_de).map_err(|e| ElementError::InvalidContent {
element: row.table_def().id().to_string(),
content: e.to_string(),
})?,
)
}
}