migrating top sip2 service
authorBill Erickson <berickxx@gmail.com>
Thu, 3 Sep 2020 19:41:36 +0000 (15:41 -0400)
committerBill Erickson <berickxx@gmail.com>
Mon, 30 Nov 2020 16:38:24 +0000 (08:38 -0800)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Common.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Session.pm

index e765d5b..b7ce0b5 100644 (file)
@@ -1,3 +1,21 @@
+# ---------------------------------------------------------------
+# Copyright (C) 2020 King County Library System
+# Bill Erickson <berickxx@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# ---------------------------------------------------------------
+# Code borrows heavily and sometimes copies directly from from
+# ../SIP* and SIPServer*
+# ---------------------------------------------------------------
 package OpenILS::Application::SIP2;
 use strict; use warnings;
 use base 'OpenILS::Application';
@@ -11,6 +29,7 @@ use OpenILS::Application::AppUtils;
 use OpenILS::Application::SIP2::Common;
 use OpenILS::Application::SIP2::Session;
 use OpenILS::Application::SIP2::Item;
+use OpenILS::Application::SIP2::Patron;
 my $U = 'OpenILS::Application::AppUtils';
 my $SC = 'OpenILS::Application::SIP2::Common';
 
@@ -55,9 +74,9 @@ sub dispatch_sip2_request {
     return OpenILS::Event->new('SIP2_SESSION_REQUIRED') unless $session;
 
     my $MESSAGE_MAP = {
-        '17' => &handle_item_info,
-        '23' => &handle_patron_status,
-        '63' => &handle_patron_info
+        '17' => \&handle_item_info,
+        '23' => \&handle_patron_status,
+        '63' => \&handle_patron_info
     };
 
     return OpenILS::Event->new('SIP2_NOT_IMPLEMENTED', {payload => $message})
@@ -74,8 +93,8 @@ sub handle_login {
     # Default to login-failed
     my $response = {code => '94', fixed_fields => ['0']};
 
-    my $sip_username = get_field_value($message, 'CN');
-    my $sip_password = get_field_value($message, 'CO');
+    my $sip_username = $SC->get_field_value($message, 'CN');
+    my $sip_password = $SC->get_field_value($message, 'CO');
     my $sip_account = $e->search_config_sip_account([
         {sip_username => $sip_username, enabled => 't'}, 
         {flesh => 1, flesh_fields => {csa => ['workstation']}}
@@ -133,7 +152,7 @@ sub handle_sc_status {
             '2.00'              # protocol_version
         ],
         fields => [
-            {AO => $config->{id}},
+            {AO => $config->{institution}},
             {BX => join('', @{$config->{supports}})}
         ]
     }
@@ -142,7 +161,7 @@ sub handle_sc_status {
 sub handle_item_info {
     my ($session, $message) = @_;
 
-    my $barcode = get_field_value($message, 'AB');
+    my $barcode = $SC->get_field_value($message, 'AB');
     my $config = $session->config;
 
     my $idetails = OpenILS::Application::SIP2::Item->get_item_details(
@@ -187,6 +206,157 @@ sub handle_item_info {
     };
 }
 
+sub handle_patron_info {
+    my ($session, $message) = @_;
+    my $sip_account = $session->sip_account;
+
+    my $barcode = get_field_value($message, 'AA');
+    my $password = get_field_value($message, 'AD');
+
+    my $summary = 
+        ref $message->{fixed_fields} ? $message->{fixed_fields}->[2] : '';
+
+    my $list_items = patron_summary_list_items($summary);
+
+    my $pdetails = OpenILS::Application::SIP2::Patron->get_patron_details(
+        $session,
+        barcode => $barcode,
+        password => $password,
+        summary_start_item => $SC->get_field_value($message, 'BP'),
+        summary_end_item => $SC->get_field_value($message, 'BQ'),
+        summary_list_items => $list_items
+    );
+
+    my $response = patron_response_common_data(
+        $session, $barcode, $password, $pdetails);
+
+    $response->{code} = '64';
+
+    return $response unless $pdetails;
+
+    push(
+        @{$response->{fixed_fields}}, 
+        count4($pdetails->{holds_count}),
+        count4($pdetails->{overdue_count}),
+        count4($pdetails->{out_count}),
+        count4($pdetails->{fine_count}),
+        count4($pdetails->{recall_count}),
+        count4($pdetails->{unavail_holds_count})
+    );
+
+    # TODO: Add 
+    # overdue items AT variable-length optional field (this field should be sent for each overdue item).
+    # charged items AU variable-length optional field (this field should be sent for each charged item).
+    # fine items AV variable-length optional field (this field should be sent for each fine item).
+    # recall items BU variable-length optional field (this field should be sent for each recall item).
+    # unavailable hold items CD variable-length optional field (this field should be sent for each unavailable hold item).
+
+    if ($list_items eq 'hold_items') {
+        for my $hold (@{$pdetails->{hold_items}}) {
+            push(@{$response->{fields}}, {AS => $hold});
+        }
+    }
+
+    return $response;
+}
+
+sub handle_patron_status {
+    my ($session, $message) = @_;
+    my $sip_account = $session->sip_account;
+
+    my $barcode = $SC->get_field_value($message, 'AA');
+    my $password = $SC->get_field_value($message, 'AD');
+
+    my $pdetails = OpenILS::Application::SIP2::Patron->get_patron_details(
+        $session,
+        barcode => $barcode,
+        password => $password
+    );
+
+    my $response = patron_response_common_data(
+        $session, $barcode, $password, $pdetails);
+
+    $response->{code} = '24';
+
+    return $response;
+}
+
+# Patron Info and Patron Status responses share mostly the same data.
+# This returns the base data which can be augmented as needed.
+# Note we don't call Patron->get_patron_details here since different
+# messages collect different amounts of data.
+sub patron_response_common_data {
+    my ($session, $barcode, $password, $pdetails) = @_;
+
+    if (!$pdetails) {
+        # No such user.  Return a stub response with all things denied.
+
+        return {
+            fixed_fields => [
+                $SC->spacebool(1), # charge denied
+                $SC->spacebool(1), # renew denied
+                $SC->spacebool(1), # recall denied
+                $SC->spacebool(1), # holds denied
+                split('', (' ' x 10)),
+                '000', # language
+                $SC->sipdate
+            ],
+            fields => [
+                {AO => $session->config->{institution}},
+                {AA => $barcode},
+                {BL => $SC->sipbool(0)}, # valid patron
+                {CQ => $SC->sipbool(0)}  # valid patron password
+            ]
+        };
+    }
+    return {
+        fixed_fields => [
+            $SC->spacebool($pdetails->{charge_denied}),
+            $SC->spacebool($pdetails->{renew_denied}),
+            $SC->spacebool($pdetails->{recall_denied}),
+            $SC->spacebool($pdetails->{holds_denied}),
+            $SC->spacebool($pdetails->{patron}->card->active eq 'f'),
+            $SC->spacebool(0), # too many charged
+            $SC->spacebool($pdetails->{too_may_overdue}),
+            $SC->spacebool(0), # too many renewals
+            $SC->spacebool(0), # too many claims retruned
+            $SC->spacebool(0), # too many lost
+            $SC->spacebool($pdetails->{too_many_fines}),
+            $SC->spacebool($pdetails->{too_many_fines}),
+            $SC->spacebool(0), # recall overdue
+            $SC->spacebool($pdetails->{too_many_fines}),
+            '000', # language
+            $SC->sipdate
+        ],
+        fields => [
+            {AO => $session->config->{institution}},
+            {AA => $barcode},
+            {BL => $SC->sipbool(1)},            # valid patron
+            {BV => $pdetails->{balance_owed}},  # fee amount
+            {CQ => $SC->sipbool($password)}     # password verified if exists
+        ]
+    };
+}
+
+# Determines which class of data the SIP client wants detailed
+# information on in the patron info request.
+sub patron_summary_list_items {
+    my $summary = shift;
+
+    my $idx = index($summary, 'Y');
+
+    return 'hold_items'        if $idx == 0;
+    return 'overdue_items'     if $idx == 1;
+    return 'charged_items'     if $idx == 2;
+    return 'fine_items'        if $idx == 3;
+    return 'recall_items'      if $idx == 4;
+    return 'unavailable_holds' if $idx == 5;
+    return '';
+}
+
+
+
 1;
 
 
index 424fa52..6ac3908 100644 (file)
@@ -17,19 +17,19 @@ sub sipbool {
 
 # False == ' '
 sub spacebool {
-    my $bool = shift;
+    my ($class, $bool) = @_;
     return $bool ? 'Y' : ' ';
 }
 
 sub count4 {
-    my $value = shift;
+    my ($class, $value) = @_;
     return '    ' unless defined $value;
     return sprintf("%04d", $value);
 }
 
 # Returns the value of the first occurrence of the requested SIP code.
 sub get_field_value {
-    my ($message, $code) = @_;
+    my ($class, $message, $code) = @_;
     for my $field (@{$message->{fields}}) {
         while (my ($c, $v) = each(%$field)) { # one pair per field
             return $v if $c eq $code;
index 1def432..f2b8654 100644 (file)
@@ -1,3 +1,21 @@
+# ---------------------------------------------------------------
+# Copyright (C) 2020 King County Library System
+# Bill Erickson <berickxx@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# ---------------------------------------------------------------
+# Code borrows heavily and sometimes copies directly from from
+# ../SIP* and SIPServer*
+# ---------------------------------------------------------------
 package OpenILS::Application::SIP2::Item;
 use strict; use warnings;
 use DateTime;
index 12f36bf..8a237e7 100644 (file)
@@ -1,3 +1,21 @@
+# ---------------------------------------------------------------
+# Copyright (C) 2020 King County Library System
+# Bill Erickson <berickxx@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# ---------------------------------------------------------------
+# Code borrows heavily and sometimes copies directly from from
+# ../SIP* and SIPServer*
+# ---------------------------------------------------------------
 package OpenILS::Application::SIPSession;
 use strict; use warnings;
 use JSON::XS;
@@ -52,7 +70,7 @@ sub config {
     my $inst = $self->sip_account->institution;
 
     my $config = {
-        id => $inst,
+        institution => $inst,
         settings => {
             currency => 'USD' # TODO add db setting
         },