--- /dev/null
+#!/usr/bin/perl
+# Copyright (C) 2012 Equinox Software, Inc.
+# Author: Bill Erickson <erickson@esilibrary.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.
+
+use strict; use warnings;
+use MARC::Record;
+use MARC::Batch;
+use MARC::File::XML ( BinaryEncoding => 'UTF-8' );
+use MARC::File::USMARC;
+
+use Data::Dumper;
+use File::Temp;
+use Getopt::Long qw(:DEFAULT GetOptionsFromArray);
+use Pod::Usage;
+
+use OpenSRF::Utils::Logger qw/$logger/;
+use OpenSRF::AppSession;
+use OpenSRF::EX qw/:try/;
+use OpenSRF::Utils::SettingsClient;
+use OpenSRF::Utils::Cache;
+use OpenILS::Utils::Cronscript;
+use OpenILS::Utils::CStoreEditor;
+require 'oils_header.pl';
+use vars qw/$apputils/;
+
+my $acq_ses;
+my $authtoken;
+
+my $debug = 0;
+
+my %defaults = (
+ 'osrf-config=s' => '/openils/conf/opensrf_core.xml',
+ 'user=s' => 'admin',
+ 'password=s' => '',
+ 'nodaemon' => 0,
+ 'poll-interval=i' => 10
+);
+
+$OpenILS::Utils::Cronscript::debug=1 if $debug;
+$Getopt::Long::debug=1 if $debug > 1;
+my $o = OpenILS::Utils::Cronscript->new(\%defaults);
+
+my @script_args = ();
+
+if (grep {$_ eq '--'} @ARGV) {
+ print "Splitting options into groups\n" if $debug;
+ while (@ARGV) {
+ $_ = shift @ARGV;
+ $_ eq '--' and last; # stop at the first --
+ push @script_args, $_;
+ }
+} else {
+ @script_args = @ARGV;
+ @ARGV = ();
+}
+
+print "Calling MyGetOptions ",
+ (@script_args ? "with options: " . join(' ', @script_args) : 'without options from command line'),
+ "\n" if $debug;
+
+my $real_opts = $o->MyGetOptions(\@script_args);
+$o->bootstrap;
+
+my $osrf_config = $real_opts->{'osrf-config'};
+my $oils_username = $real_opts->{user};
+my $oils_password = $real_opts->{password};
+my $help = $real_opts->{help};
+my $poll_interval = $real_opts->{'poll-interval'};
+ $debug += $real_opts->{debug};
+
+foreach (keys %$real_opts) {
+ print("real_opt->{$_} = ", $real_opts->{$_}, "\n") if $real_opts->{debug} or $debug;
+}
+
+# FEEDBACK
+
+pod2usage(1) if $help;
+unless ($oils_password) {
+ print STDERR "\nERROR: password option required for session login\n\n";
+}
+
+print Dumper($o) if $debug;
+
+if ($debug) {
+ foreach my $ref (qw/osrf_config oils_username oils_password help debug/) {
+ no strict 'refs';
+ printf "%16s => %s\n", $ref, (eval("\$$ref") || '');
+ }
+}
+
+print Dumper($real_opts);
+
+# log in
+sub new_auth_token {
+ $authtoken = oils_login($oils_username, $oils_password, 'staff')
+ or die "Unable to login to Evergreen as user $oils_username";
+ return $authtoken;
+}
+
+# log out
+sub clear_auth_token {
+ $apputils->simplereq(
+ 'open-ils.auth',
+ 'open-ils.auth.session.delete',
+ $authtoken
+ );
+}
+
+sub push_file_to_acq {
+ my $file = shift;
+ my $args = shift;
+
+ print "Pushing file '$file' to provider " . $args->{provider} . "\n";
+
+ # Cache the file name like Vandelay does. ACQ will
+ # read contents of the cache and then delete them.
+ # The key can be any unique value.
+ my $key = $$ . time . rand();
+ $cache->put_cache("vandelay_import_spool_$key", {path => $file});
+
+ my $req = $acq_ses->request(
+ 'open-ils.acq.process_upload_records',
+ $authtoken,
+ $key,
+ $args
+ );
+
+ while (my $resp = $req->recv(timeout => 600)) {
+ if(my $content = $resp->content) {
+ print Dumper($content) if $debug;
+ } else {
+ warn "Request returned no data: " . Dumper($resp) . "\n";
+ }
+ }
+}
+
+
+open-ils.acq open-ils.acq.process_upload_records "ce5ab1499cf019c0b52bf9eab87335fc", "f15791c2bcea4296c0d2c955c5204125", {"picklist":null,"provider":"1","ordering_agency":"4","create_po":false,"activate_po":"on","vandelay":{"import_no_match":"on","auto_overlay_exact":"on","auto_overlay_1match":false,"auto_overlay_best_match":false,"match_quality_ratio":"0.0","queue_name":"acq.bt.2","create_assets":false,"match_set":"","bib_source":"","merge_profile":"1","fall_through_merge_profile":"","existing_queue":""}}
+
+sub args_from_provider_conf {
+ my $conf = shift;
+
+ my $pcode = $conf->{code};
+ my $orgsn = $conf->{owner};
+
+ my $org = $editor->search_actor_org_unit(shortname => $orgsn)->[0];
+ if (!$org) {
+ warn "No such org unit in acq_order_reader config: '$orgsn'\n";
+ next;
+ }
+
+ my $provider = $editor->search_acq_provider({
+ code => $pcode,
+ owner => $org->id
+ });
+
+ if (!$provider) {
+ warn "No such provider in acq_order_reader config: '$pcode'\n";
+ next;
+ }
+
+}
+
+# -----------------------------------------------------
+# Main script
+# -----------------------------------------------------
+
+osrf_connect($osrf_config);
+
+my $conf = OpenSRF::Utils::SettingsClient->new;
+my $base_dir = $conf->config_value(acq_order_reader => 'base_dir');
+my $share_dir = $conf->config_value(acq_order_reader => 'shared_subdir');
+my $providers = $conf->config_value(acq_order_reader => 'provider');
+
+print Dumper($providers) if $debug;
+
+$acq_ses = OpenSRF::AppSession->create('open-ils.acq');
+my $cache = OpenSRF::Utils::Cache->new;
+my $editor = OpenILS::Utils::CStoreEditor->new;
+
+# main loop
+# for each provider directory, plus the shared directory, check
+# to see if there are any files pending. For any files found, push
+# them up to the ACQ service, then delete the file
+
+while (1) {
+
+
+ new_auth_token();
+
+ # explicit providers
+ for my $provider_conf (@$providers) {
+ my $args = args_from_provider_conf($provider_conf) or next;
+ my @files = check_provider_files($args);
+ push_file_to_acq($_, $args) @files;
+ }
+
+ # shared directory
+
+ clear_auth_token();
+
+ print "Sleeping for $poll_time seconds...\n" if $debug;
+ sleep $poll_time;
+}
+
+warn "Exiting main acq_order_reader loop!\n";
+
+
+__END__
+
+=head1 NAME
+
+acq_order_reader.pl - Collect MARC order record files and pass them onto the ACQ service
+
+=head1 SYNOPSIS
+
+./acq_order_reader.pl [script opts ...]
+
+This script uses the EG common options from B<Cronscript>. See --help output for those.
+
+Run C<perldoc marc_stream_importer.pl> for full documentation.
+
+Note: this script has to be run in the same directory as B<oils_header.pl>.
+
+Typical server-style execution will include a trailing C<&> to run in the background.
+
+=head1 OPTIONS
+
+The only required option is --password
+
+ --password =<eg_password>
+ --user =<eg_username> default: admin
+ --nodaemon default: OFF When used with --spoolfile, turns off Net::Server mode and runs this utility in the foreground
+
+
+=head2 Old style: --noqueue and associated options
+
+=head1 EXAMPLES
+
+./acq_order_reader.pl --user admin --password demo123
+
+./acq_order_reader.pl --user admin --password demo123 -poll-interval 3 --debug --nodaemon
+
+=head1 AUTHORS
+
+ Bill Erickson <erickson@esilibrary.com>
+ Code liberally copied from marc_stream_importer.pl
+
+=cut