use model::{GraduationRequirement, GraduationRequirements, GraduationStudent};
use crate::RusaintError;
use crate::application::utils::input_field::InputFieldExt as _;
use crate::client::{USaintApplication, USaintClient};
use wdpe::command::WebDynproCommandExecutor;
use wdpe::element::parser::ElementParser;
use wdpe::{
body::Body,
command::element::{
action::ButtonPressEventCommand, complex::SapTableBodyCommand, text::InputFieldValueCommand,
},
define_elements,
element::{
action::Button,
complex::SapTable,
text::{InputField, InputFieldDef},
},
};
#[derive(Debug)]
pub struct GraduationRequirementsApplication {
client: USaintClient,
}
impl USaintApplication for GraduationRequirementsApplication {
const APP_NAME: &'static str = "ZCMW8015";
fn from_client(client: USaintClient) -> Result<Self, RusaintError> {
if client.name() != Self::APP_NAME {
Err(RusaintError::InvalidClientError)
} else {
Ok(Self { client })
}
}
}
impl<'a> GraduationRequirementsApplication {
define_elements! {
STUDENT_NUM: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_STUDENT12";
STUDENT_NAME: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_STNAME";
STUDENT_GRADE: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_GRADE";
PRCL: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_PRCL";
STATUS: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_STATUST";
APPLY_YEAR: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_APPLY_PERYR";
NEWINCOR_CDT: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_NEWINCOR_CDT";
CG_IDT_DEPT: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_CG_IDT_DEPT";
CG_IDT1: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_CG_IDT1";
CG_IDT2: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_CG_IDT2";
CG_IDT3: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_CG_IDT3";
CG_IDT4: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_CG_IDT4";
AUDIT_DATE: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_AUDIT_DAT";
GR_CPOP: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_GR_CPOP";
COMP_CPOP: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_COMP_CPOP";
}
define_elements! {
AUDIT_RESULT: InputField<'a> = "ZCMW8015.ID_0001:MAIN.TC01_AUDIT_RESULT_T";
SHOW_DETAILS: Button<'a> = "ZCMW8015.ID_0001:MAIN.BTN_DTL";
MAIN_TABLE: SapTable<'a> = "ZCMW8015.ID_0001:MAIN.TABLE";
}
pub async fn student_info(&self) -> Result<GraduationStudent, RusaintError> {
let parser = ElementParser::new(self.body());
let number = parser
.element_from_def(&Self::STUDENT_NUM)?
.value_into_u32()?;
let name = &parser
.element_from_def(&Self::STUDENT_NAME)?
.value_string()?;
let grade = parser
.element_from_def(&Self::STUDENT_GRADE)?
.value_into_u32()?;
let semester = parser.element_from_def(&Self::PRCL)?.value_into_u32()?;
let status = &parser.element_from_def(&Self::STATUS)?.value_string()?;
let apply_year = parser
.element_from_def(&Self::APPLY_YEAR)?
.value_into_u32()?;
let apply_type = &parser
.element_from_def(&Self::NEWINCOR_CDT)?
.value_string()?;
let department = &parser
.element_from_def(&Self::CG_IDT_DEPT)?
.value_string()?;
let mut majors = Vec::new();
const IDTS: &[InputFieldDef] = &[
GraduationRequirementsApplication::CG_IDT1,
GraduationRequirementsApplication::CG_IDT2,
GraduationRequirementsApplication::CG_IDT3,
GraduationRequirementsApplication::CG_IDT4,
];
for idt in IDTS {
let major = parser.element_from_def(idt)?.value_string().ok();
if let Some(major) = major {
if !major.trim().is_empty() {
majors.push(major);
} else {
break;
}
} else {
break;
}
}
let audit_date = &parser.element_from_def(&Self::AUDIT_DATE)?.value_string()?;
let graduation_points = parser.element_from_def(&Self::GR_CPOP)?.value_into_f32()?;
let completed_points = parser
.element_from_def(&Self::COMP_CPOP)?
.value_into_f32()?;
Ok(GraduationStudent::new(
number,
name,
grade,
semester,
status,
apply_year,
apply_type,
department,
majors,
audit_date,
graduation_points,
completed_points,
))
}
pub async fn requirements(&mut self) -> Result<GraduationRequirements, RusaintError> {
{
let event = ElementParser::new(self.body())
.read(ButtonPressEventCommand::new(Self::SHOW_DETAILS))?;
self.client.process_event(false, event).await?;
}
let parser = ElementParser::new(self.body());
let audit_result = parser
.read(InputFieldValueCommand::new(Self::AUDIT_RESULT))
.is_ok_and(|str| str == "가능");
let table = parser.read(SapTableBodyCommand::new(Self::MAIN_TABLE))?;
let requirements = table
.try_table_into::<GraduationRequirement>(&parser)?
.into_iter()
.map(|req| (req.name().to_owned(), req))
.collect();
Ok(GraduationRequirements::new(audit_result, requirements))
}
pub async fn reload(&mut self) -> Result<(), RusaintError> {
self.client.reload().await?;
Ok(())
}
fn body(&self) -> &Body {
self.client.body()
}
}
pub mod model;
#[cfg(test)]
mod test {
use crate::client::USaintClientBuilder;
use crate::{
application::graduation_requirements::GraduationRequirementsApplication,
global_test_utils::get_session,
};
use wdpe::command::WebDynproCommandExecutor;
use wdpe::command::element::complex::SapTableBodyCommand;
use wdpe::element::parser::ElementParser;
#[tokio::test]
async fn read_table() {
let session = get_session().await.unwrap();
let app = USaintClientBuilder::new()
.session(session)
.build_into::<GraduationRequirementsApplication>()
.await
.unwrap();
let parser = ElementParser::new(app.body());
let table = parser
.read(SapTableBodyCommand::new(
GraduationRequirementsApplication::MAIN_TABLE,
))
.unwrap()
.try_table_into::<Vec<(String, String)>>(&parser)
.unwrap();
dbg!(table);
}
}