From: Bill Erickson Date: Fri, 11 Sep 2020 19:37:39 +0000 (-0400) Subject: sip2 schema updates; more data X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=0afb970e4c714ee42b406e5f3566d69d44f6e842;p=working%2FEvergreen.git sip2 schema updates; more data Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 72fb487a11..71a13e67c9 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -13435,22 +13435,18 @@ SELECT usr, - - + + - - - - - - + + + - - + @@ -13461,17 +13457,20 @@ SELECT usr, - - - - + + + + + + + @@ -13481,6 +13480,35 @@ SELECT usr, + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm index 0c55354c56..72ab594a88 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2.pm @@ -146,11 +146,11 @@ sub handle_item_info { my $barcode = $SC->get_field_value($message, 'AB'); my $config = $session->config; - my $idetails = OpenILS::Application::SIP2::Item->get_item_details( + my $details = OpenILS::Application::SIP2::Item->get_item_details( $session, barcode => $barcode ); - if (!$idetails) { + if (!$details) { # No matching item found, return a minimal response. return { code => '18', @@ -167,23 +167,24 @@ sub handle_item_info { return { code => '18', fixed_fields => [ - $idetails->{circ_status}, + $details->{circ_status}, '02', # Security Marker, consistent with ../SIP* - $idetails->{fee_type}, + $details->{fee_type}, $SC->sipdate ], fields => [ {AB => $barcode}, - {AH => $idetails->{due_date}}, - {AJ => $idetails->{title}}, - {AP => $idetails->{item}->circ_lib->shortname}, - {AQ => $idetails->{item}->circ_lib->shortname}, - {BG => $idetails->{item}->circ_lib->shortname}, + {AH => $details->{due_date}}, + {AJ => $details->{title}}, + {AP => $details->{item}->circ_lib->shortname}, + {AQ => $details->{item}->circ_lib->shortname}, + {BG => $details->{item}->circ_lib->shortname}, {BH => $config->{settings}->{currency}}, - {BV => $idetails->{item}->deposit_amount}, - {CF => $idetails->{hold_queue_length}}, - {CK => $idetails->{media_type}}, - {CM => $idetails->{hold_pickup_date}} + {BV => $details->{item}->deposit_amount}, + {CF => $details->{hold_queue_length}}, + {CK => $details->{media_type}}, + {CM => $details->{hold_pickup_date}}, + {CY => $details->{hold_patron_barcode}} ] }; } @@ -200,7 +201,7 @@ sub handle_patron_info { my $list_items = $SC->patron_summary_list_items($summary); - my $pdetails = OpenILS::Application::SIP2::Patron->get_patron_details( + my $details = OpenILS::Application::SIP2::Patron->get_patron_details( $session, barcode => $barcode, password => $password, @@ -210,21 +211,21 @@ sub handle_patron_info { ); my $response = - patron_response_common_data($session, $barcode, $password, $pdetails); + patron_response_common_data($session, $barcode, $password, $details); $response->{code} = '64'; - return $response unless $pdetails; - my $patron = $pdetails->{patron}; + return $response unless $details; + my $patron = $details->{patron}; push( @{$response->{fixed_fields}}, - $SC->count4($pdetails->{holds_count}), - $SC->count4($pdetails->{overdue_count}), - $SC->count4($pdetails->{out_count}), - $SC->count4($pdetails->{fine_count}), - $SC->count4($pdetails->{recall_count}), - $SC->count4($pdetails->{unavail_holds_count}) + $SC->count4($details->{holds_count}), + $SC->count4($details->{overdue_count}), + $SC->count4($details->{out_count}), + $SC->count4($details->{fine_count}), + $SC->count4($details->{recall_count}), + $SC->count4($details->{unavail_holds_count}) ); push( @@ -237,23 +238,23 @@ sub handle_patron_info { ); if ($list_items eq 'hold_items') { - for my $hold (@{$pdetails->{hold_items}}) { + for my $hold (@{$details->{hold_items}}) { push(@{$response->{fields}}, {AS => $hold}); } } elsif ($list_items eq 'charged_items') { - for my $item (@{$pdetails->{items_out}}) { + for my $item (@{$details->{items_out}}) { push(@{$response->{fields}}, {AU => $item}); } } elsif ($list_items eq 'overdue_items') { - for my $item (@{$pdetails->{overdue_items}}) { + for my $item (@{$details->{overdue_items}}) { push(@{$response->{fields}}, {AT => $item}); } } elsif ($list_items eq 'fine_items') { - for my $item (@{$pdetails->{fine_items}}) { + for my $item (@{$details->{fine_items}}) { push(@{$response->{fields}}, {AV => $item}); } } elsif ($list_items eq 'unavailable_holds') { - for my $item (@{$pdetails->{unavailable_holds}}) { + for my $item (@{$details->{unavailable_holds}}) { push(@{$response->{fields}}, {CD => $item}); } } @@ -270,14 +271,14 @@ sub handle_patron_status { 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( + my $details = OpenILS::Application::SIP2::Patron->get_patron_details( $session, barcode => $barcode, password => $password ); my $response = patron_response_common_data( - $session, $barcode, $password, $pdetails); + $session, $barcode, $password, $details); $response->{code} = '24'; @@ -289,9 +290,9 @@ sub handle_patron_status { # 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) = @_; + my ($session, $barcode, $password, $details) = @_; - if (!$pdetails) { + if (!$details) { # No such user. Return a stub response with all things denied. return { @@ -313,33 +314,34 @@ sub patron_response_common_data { }; } - my $patron = $pdetails->{patron}; + my $patron = $details->{patron}; 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($details->{charge_denied}), + $SC->spacebool($details->{renew_denied}), + $SC->spacebool($details->{recall_denied}), + $SC->spacebool($details->{holds_denied}), $SC->spacebool($patron->card->active eq 'f'), $SC->spacebool(0), # too many charged - $SC->spacebool($pdetails->{too_may_overdue}), + $SC->spacebool($details->{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($details->{too_many_fines}), + $SC->spacebool($details->{too_many_fines}), $SC->spacebool(0), # recall overdue - $SC->spacebool($pdetails->{too_many_fines}), + $SC->spacebool($details->{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 + {AO => $session->config->{institution}}, + {BH => $session->config->{settings}->{currency}}, + {BL => $SC->sipbool(1)}, # valid patron + {BV => $details->{balance_owed}}, # fee amount + {CQ => $SC->sipbool($password)} # password verified if exists ] }; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm index 1def432981..ba25247f27 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Item.pm @@ -90,10 +90,13 @@ sub get_item_details { } - if ($details->{hold}) { - my $pickup_date = $details->{hold}->shelf_expire_time; + if (my $hold = $details->{hold}) { + my $pickup_date = $hold->shelf_expire_time; $details->{hold_pickup_date} = $pickup_date ? $SC->sipdate($pickup_date) : undef; + + my $card = $e->search_actor_card({usr => $hold->usr})->[0]; + $details->{hold_patron_barcode} = $card->barcode if $card; } my ($title_entry) = grep {$_->name eq 'title'} diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Session.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Session.pm index 097b84b682..2137d1bb3c 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Session.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/SIP2/Session.pm @@ -13,7 +13,7 @@ $json->allow_nonref(1); # Supported Messages (BX) # Currently hard-coded, since it's based on availabilty of functionality # in the code, but it could be moved into the database to limit access for -# specific institutions. +# specific setting groups. use constant INSTITUTION_SUPPORTS => [ 'Y', # patron status request, 'Y', # checkout, @@ -49,35 +49,21 @@ sub config { my $self = shift; return $self->{config} if $self->{config}; - my $inst = $self->sip_account->institution; + my $group = $self->editor->retrieve_config_sip_setting_group([ + $self->sip_account->setting_group, + {flesh => 1, flesh_fields => {cssg => ['settings']}} + ]); my $config = { - institution => $inst, - settings => { - currency => 'USD' # TODO add db setting - }, + institution => $group->institution, supports => INSTITUTION_SUPPORTS }; - # Institution "*" provides default values for all institution configs. - my $settings = - $self->editor->search_config_sip_setting({institution => ['*', $inst]}); - - # Institution specific settings. - for my $set (grep {$_->institution eq $inst} @$settings) { - $config->{settings}->{$set->name} = $json->decode($set->value); - } - - # Apply values for global settings without replacing - # institution-specific values. - for my $set (grep {$_->institution eq '*'} @$settings) { - my $name = $set->name; - my $value = $json->decode($set->value); - - $config->{settings}->{$name} = $value - unless exists $config->{settings}->{$name}; - } + # Decode and hashify settings for easy access + $config->{settings} = + {map {$_->name => $json->decode($_->value)} @{$group->settings}}; + $logger->info("SIP settings " . $json->encode($config->{settings})); return $self->{config} = $config; } diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.sip-config.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.sip-config.sql index 3b6c1212db..f019bf99f9 100644 --- a/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.sip-config.sql +++ b/Open-ILS/src/sql/Pg/upgrade/XXXX.schema.sip-config.sql @@ -3,10 +3,29 @@ BEGIN; -- SELECT evergreen.upgrade_deps_block_check('TODO', :eg_version); +-- Collections of settings that can be linked to one or more SIP accounts. +CREATE TABLE config.sip_setting_group ( + id SERIAL PRIMARY KEY, + label TEXT UNIQUE NOT NULL, + institution TEXT NOT NULL -- Duplicates OK +); + +-- Key/value setting pairs +CREATE TABLE config.sip_setting ( + id SERIAL PRIMARY KEY, + setting_group INTEGER NOT NULL REFERENCES config.sip_setting_group (id) + ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, + name TEXT NOT NULL, + description TEXT NOT NULL, + value JSON NOT NULL, + CONSTRAINT name_once_per_inst UNIQUE (setting_group, name) +); + CREATE TABLE config.sip_account ( id SERIAL PRIMARY KEY, enabled BOOLEAN NOT NULL DEFAULT TRUE, - institution TEXT NOT NULL, + setting_group INTEGER NOT NULL REFERENCES config.sip_setting_group (id) + DEFERRABLE INITIALLY DEFERRED, sip_username TEXT NOT NULL, sip_password BIGINT NOT NULL REFERENCES actor.passwd DEFERRABLE INITIALLY DEFERRED, @@ -16,43 +35,59 @@ CREATE TABLE config.sip_account ( av_format TEXT -- e.g. '3m' ); --- institution and global-level key/value setting pairs. -CREATE TABLE config.sip_setting ( - id SERIAL PRIMARY KEY, - institution TEXT NOT NULL, -- '*' applies to all institutions - name TEXT NOT NULL, - value JSON NOT NULL, - CONSTRAINT name_once_per_inst UNIQUE (institution, name) -); - -- SEED DATA INSERT INTO actor.passwd_type (code, name, login, crypt_algo, iter_count) VALUES ('sip2', 'SIP2 Client Password', FALSE, 'bf', 5); -INSERT INTO config.sip_setting (institution, name, value) -VALUES - ('*', 'allow_sc_status_before_login', 'true'), - ('*', 'currency', '"USD"'), - ('*', 'due_date_use_sip_date_format', 'false'), - ('*', 'patron_status_permit_loans', 'false'), - ('*', 'patron_status_permit_all', 'false'), - ('*', 'msg64_summary_datatype', '"title"'), - ('*', 'msg64_hold_items_available', '"title"') -; +INSERT INTO config.sip_setting_group (label, institution) + VALUES ('Example Setting Group', 'example'); + +INSERT INTO config.sip_setting (setting_group, description, name, value) +VALUES ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Monetary amounts are reported in this currency', + 'currency', '"USD"' +), ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Allow clients to request the SIP server status before login (message 99)', + 'allow_sc_status_before_login', 'true' +), ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Due date uses 18-char date format (YYYYMMDDZZZZHHMMSS). Otherwise "YYYY-MM-DD HH:MM:SS', + 'due_date_use_sip_date_format', 'false' +), ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Checkout and renewal are allowed even when penalties blocking these actions exist', + 'patron_status_permit_loans', 'false' +), ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Holds, checkouts, and renewals allowed regardless of blocking penalties', + 'patron_status_permit_all', 'false' +), ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Patron circulation data may be returned as either "title" or "barcode"', + 'msg64_summary_datatype', '"title"' +), ( + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'Patron holds data may be returned as either "title" or "barcode"', + 'msg64_hold_items_available', '"title"' +); /* EXAMPLE SETTINGS + -- Example linking a SIP password to the 'admin' account. SELECT actor.set_passwd(1, 'sip2', 'sip_password'); INSERT INTO actor.workstation (name, owning_lib) VALUES ('BR1-SIP2-Gateway', 4); INSERT INTO config.sip_account( - institution, sip_username, sip_password, usr, workstation, av_format + setting_group, sip_username, sip_password, usr, workstation, av_format ) VALUES ( - 'example', 'admin', + (SELECT id FROM config.sip_setting_group WHERE institution = 'example'), + 'admin', (SELECT id FROM actor.passwd WHERE usr = 1 AND passwd_type = 'sip2'), 1, (SELECT id FROM actor.workstation WHERE name = 'BR1-SIP2-Gateway'),