1use super::connection::Connection;
2use super::error::Error;
3use super::params::*;
4use super::{spec, util, Field, FixedField, Message};
5use std::str;
6
7pub struct Client {
27 connection: Connection,
28}
29
30impl Client {
31 pub fn new(host: &str) -> Result<Self, Error> {
33 Ok(Client {
34 connection: Connection::new(host)?,
35 })
36 }
37
38 pub fn disconnect(&self) -> Result<(), Error> {
40 self.connection.disconnect()
41 }
42
43 pub fn login(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
47 let user = match params.sip_user() {
48 Some(u) => u,
49 _ => return Err(Error::MissingParamsError),
50 };
51
52 let pass = match params.sip_pass() {
53 Some(u) => u,
54 _ => return Err(Error::MissingParamsError),
55 };
56
57 let mut req = Message::new(
58 &spec::M_LOGIN,
59 vec![
60 FixedField::new(&spec::FF_UID_ALGO, "0").unwrap(),
61 FixedField::new(&spec::FF_PWD_ALGO, "0").unwrap(),
62 ],
63 vec![
64 Field::new(spec::F_LOGIN_UID.code, user),
65 Field::new(spec::F_LOGIN_PWD.code, pass),
66 ],
67 );
68
69 req.maybe_add_field(spec::F_LOCATION_CODE.code, params.location());
70
71 let resp = self.connection.sendrecv(&req)?;
72
73 if resp.spec().code == spec::M_LOGIN_RESP.code
74 && resp.fixed_fields().len() == 1
75 && resp.fixed_fields()[0].value() == "1"
76 {
77 Ok(SipResponse::new(resp, true))
78 } else {
79 Ok(SipResponse::new(resp, false))
80 }
81 }
82
83 pub fn sc_status(&mut self) -> Result<SipResponse, Error> {
87 let req = Message::new(
88 &spec::M_SC_STATUS,
89 vec![
90 FixedField::new(&spec::FF_STATUS_CODE, "0").unwrap(),
91 FixedField::new(&spec::FF_MAX_PRINT_WIDTH, "999").unwrap(),
92 FixedField::new(&spec::FF_PROTOCOL_VERSION, spec::SIP_PROTOCOL_VERSION).unwrap(),
93 ],
94 vec![],
95 );
96
97 let resp = self.connection.sendrecv(&req)?;
98
99 if !resp.fixed_fields().is_empty() && resp.fixed_fields()[0].value() == "Y" {
100 Ok(SipResponse::new(resp, true))
101 } else {
102 Ok(SipResponse::new(resp, false))
103 }
104 }
105
106 pub fn patron_status(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
110 let patron_id = match params.patron_id() {
111 Some(p) => p,
112 _ => return Err(Error::MissingParamsError),
113 };
114
115 let mut req = Message::new(
116 &spec::M_PATRON_STATUS,
117 vec![
118 FixedField::new(&spec::FF_LANGUAGE, "000").unwrap(),
119 FixedField::new(&spec::FF_DATE, &util::sip_date_now()).unwrap(),
120 ],
121 vec![Field::new(spec::F_PATRON_ID.code, patron_id)],
122 );
123
124 req.maybe_add_field(spec::F_INSTITUTION_ID.code, params.institution());
125 req.maybe_add_field(spec::F_PATRON_PWD.code, params.patron_pwd());
126 req.maybe_add_field(spec::F_TERMINAL_PWD.code, params.terminal_pwd());
127
128 let resp = self.connection.sendrecv(&req)?;
129
130 if let Some(bl_val) = resp.get_field_value(spec::F_VALID_PATRON.code) {
131 if bl_val == "Y" {
132 return Ok(SipResponse::new(resp, true));
133 }
134 }
135
136 Ok(SipResponse::new(resp, false))
137 }
138
139 pub fn patron_info(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
143 let patron_id = match params.patron_id() {
144 Some(p) => p,
145 None => return Err(Error::MissingParamsError),
146 };
147
148 let mut summary: [char; 10] = [' '; 10];
149
150 if let Some(idx) = params.summary() {
151 if idx < 10 {
152 summary[idx] = 'Y';
153 }
154 }
155
156 let sum_str: String = summary.iter().collect::<String>();
157
158 let mut req = Message::new(
159 &spec::M_PATRON_INFO,
160 vec![
161 FixedField::new(&spec::FF_LANGUAGE, "000").unwrap(),
162 FixedField::new(&spec::FF_DATE, &util::sip_date_now()).unwrap(),
163 FixedField::new(&spec::FF_SUMMARY, &sum_str).unwrap(),
164 ],
165 vec![Field::new(spec::F_PATRON_ID.code, patron_id)],
166 );
167
168 req.maybe_add_field(spec::F_INSTITUTION_ID.code, params.institution());
169 req.maybe_add_field(spec::F_PATRON_PWD.code, params.patron_pwd());
170 req.maybe_add_field(spec::F_TERMINAL_PWD.code, params.terminal_pwd());
171
172 if let Some(v) = params.start_item() {
173 req.add_field(spec::F_START_ITEM.code, &v.to_string());
174 }
175
176 if let Some(v) = params.end_item() {
177 req.add_field(spec::F_END_ITEM.code, &v.to_string());
178 }
179
180 let resp = self.connection.sendrecv(&req)?;
181
182 if let Some(bl_val) = resp.get_field_value(spec::F_VALID_PATRON.code) {
183 if bl_val == "Y" {
184 return Ok(SipResponse::new(resp, true));
185 }
186 }
187
188 Ok(SipResponse::new(resp, false))
189 }
190
191 pub fn item_info(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
196 let item_id = match params.item_id() {
197 Some(id) => id,
198 None => return Err(Error::MissingParamsError),
199 };
200
201 let mut req = Message::new(
202 &spec::M_ITEM_INFO,
203 vec![FixedField::new(&spec::FF_DATE, &util::sip_date_now()).unwrap()],
204 vec![Field::new(spec::F_ITEM_IDENT.code, item_id)],
205 );
206
207 req.maybe_add_field(spec::F_INSTITUTION_ID.code, params.institution());
208 req.maybe_add_field(spec::F_TERMINAL_PWD.code, params.terminal_pwd());
209
210 let resp = self.connection.sendrecv(&req)?;
211
212 if let Some(title_val) = resp.get_field_value(spec::F_TITLE_IDENT.code) {
213 if !title_val.is_empty() {
214 return Ok(SipResponse::new(resp, true));
215 }
216 }
217
218 Ok(SipResponse::new(resp, false))
219 }
220
221 pub fn checkout(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
223 let item_id = params.item_id().ok_or(Error::MissingParamsError)?;
224 let patron_id = params.patron_id().ok_or(Error::MissingParamsError)?;
225
226 let mut req = Message::from_values(
227 spec::M_CHECKOUT.code,
228 &[
229 "N", "N", &util::sip_date_now(), &util::sip_date_now(), ],
234 &[
235 (spec::F_ITEM_IDENT.code, item_id),
236 (spec::F_PATRON_IDENT.code, patron_id),
237 ],
238 )?;
239
240 req.maybe_add_field(spec::F_INSTITUTION_ID.code, params.institution());
241 req.maybe_add_field(spec::F_TERMINAL_PWD.code, params.terminal_pwd());
242 req.maybe_add_field(spec::F_PATRON_PWD.code, params.patron_pwd());
243
244 let resp = self.connection.sendrecv(&req)?;
245
246 if let Some(status) = resp.fixed_fields().first() {
247 if status.value() == "1" {
248 return Ok(SipResponse::new(resp, true));
249 }
250 }
251
252 Ok(SipResponse::new(resp, false))
253 }
254
255 pub fn checkin(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
257 let item_id = params.item_id().ok_or(Error::MissingParamsError)?;
258
259 let mut req = Message::from_values(
260 spec::M_CHECKIN.code,
261 &[
262 "N", &util::sip_date_now(), &util::sip_date_now(), ],
266 &[(spec::F_ITEM_IDENT.code, item_id)],
267 )?;
268
269 req.maybe_add_field(spec::F_INSTITUTION_ID.code, params.institution());
270 req.maybe_add_field(spec::F_TERMINAL_PWD.code, params.terminal_pwd());
271
272 let resp = self.connection.sendrecv(&req)?;
273
274 if let Some(status) = resp.fixed_fields().first() {
275 if status.value() == "1" {
276 return Ok(SipResponse::new(resp, true));
277 }
278 }
279
280 Ok(SipResponse::new(resp, false))
281 }
282
283 pub fn fee_paid(&mut self, params: &ParamSet) -> Result<SipResponse, Error> {
284 let patron_id = params.patron_id().ok_or(Error::MissingParamsError)?;
285 let pay_amount = params.pay_amount().ok_or(Error::MissingParamsError)?;
286
287 let pay_amount = pay_amount.to_string();
288
289 let fee_type = params.fee_type().unwrap_or(spec::FeeType::OtherUnknown);
290 let pay_type = params.pay_type().unwrap_or(spec::PayType::Cash);
291
292 let mut req = Message::from_values(
293 spec::M_FEE_PAID.code,
294 &[
295 &util::sip_date_now(), fee_type.into(),
297 pay_type.into(),
298 "USD", ],
300 &[
301 (spec::F_PATRON_ID.code, patron_id),
302 (spec::F_FEE_AMOUNT.code, &pay_amount),
303 ],
304 )?;
305
306 req.maybe_add_field(spec::F_INSTITUTION_ID.code, params.institution());
307 req.maybe_add_field(spec::F_TERMINAL_PWD.code, params.terminal_pwd());
308 req.maybe_add_field(spec::F_TRANSACTION_ID.code, params.transaction_id());
309 req.maybe_add_field(spec::F_FEE_IDENTIFIER.code, params.fee_id());
310
311 let resp = self.connection.sendrecv(&req)?;
312
313 if let Some(status) = resp.fixed_fields().first() {
314 if status.value() == "1" {
315 return Ok(SipResponse::new(resp, true));
316 }
317 }
318
319 Ok(SipResponse::new(resp, false))
320 }
321}
322
323pub struct SipResponse {
326 msg: Message,
328
329 ok: bool,
335}
336
337impl SipResponse {
338 pub fn new(msg: Message, ok: bool) -> Self {
339 SipResponse { msg, ok }
340 }
341
342 pub fn ok(&self) -> bool {
343 self.ok
344 }
345 pub fn msg(&self) -> &Message {
346 &self.msg
347 }
348 pub fn msg_mut(&mut self) -> &mut Message {
349 &mut self.msg
350 }
351
352 pub fn value(&self, code: &str) -> Option<&str> {
354 self.msg().get_field_value(code)
355 }
356}