]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/support-scripts/edi_pusher.pl
f6065afff3c061791ac8a4748c0ac457a107ac4c
[working/Evergreen.git] / Open-ILS / src / support-scripts / edi_pusher.pl
1 #!/usr/bin/perl
2 # ---------------------------------------------------------------
3 # Copyright (C) 2010 Equinox Software, Inc
4 # Author: Joe Atzberger <jatzberger@esilibrary.com>
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 # ---------------------------------------------------------------
16
17 use strict;
18 use warnings;
19
20 use Data::Dumper;
21 use vars qw/$debug/;
22
23 use OpenILS::Utils::Cronscript;
24 use OpenILS::Utils::Fieldmapper;
25 use OpenILS::Application::AppUtils;
26 use OpenILS::Application::Acq::EDI;
27 use OpenSRF::Utils::Logger q/$logger/;
28
29 INIT {
30     $debug = 1;
31 }
32
33 my %defaults = (
34     'quiet' => 0,
35     'max-batch-size=i' => -1
36 );
37
38 my $cs = OpenILS::Utils::Cronscript->new(\%defaults);
39
40 my $opts = $cs->MyGetOptions();
41 my $e    = $cs->editor() or die "Failed to get new CStoreEditor";
42 my $hook = 'acqpo.activated';
43 my $defs = $e->search_action_trigger_event_definition({
44     hook    => $hook,
45     reactor => 'GeneratePurchaseOrderJEDI',
46     active  => 't'
47 });
48
49 $opts->{verbose} = 0 if $opts->{quiet};
50
51
52 # print Dumper($defs);
53 print "\nHook '$hook' is used in ", scalar(@$defs), " event definition(s):\n";
54
55 $Data::Dumper::Indent = 1;
56 my $remaining = $opts->{'max-batch-size'};
57
58 my $subq = {
59     select => { acqedim => ['purchase_order'] },
60     from   => 'acqedim',
61     where  => {
62         message_type   => 'ORDERS',
63         status         => {'!=' => 'retry' },
64         purchase_order => {'!=' => undef   }
65     }
66 };
67
68 foreach my $def (@$defs) {
69     last if $remaining == 0;
70     printf "%3s - '%s'\n", $def->id, $def->name;
71
72     # give me all completed JEDI events that link to purchase_orders 
73     # that have no delivery attempts or are in the retry state
74
75     my $query = {
76         select => {atev => ['id']},
77         from   => 'atev',
78         where  => {
79             event_def => $def->id,
80             state  => 'complete',
81             target => {
82                 'not in' => $subq
83             }
84         },
85         order_by => {atev => ['add_time']}
86     };
87
88     $query->{limit} = $remaining if $remaining > 0;
89
90     if ($opts->{verbose}) {
91         my $excluded = $e->json_query($subq);
92         print "Excluded: ", scalar(@$excluded), " purchase order(s): ", join("\n", map {Dumper $_} @$excluded), "\n";
93     }
94
95     my $events = $e->json_query($query);
96
97     if(!$events) {
98         $logger->error("error querying JEDI events for event definition $def->id");
99         next;
100     }
101
102     $remaining -= scalar(@$events);
103
104     print "Event definition ", $def->id, " has ", scalar(@$events), " event(s)\n";
105     foreach (@$events) {
106
107         my $event = $e->retrieve_action_trigger_event([
108             $_->{id}, 
109             {flesh => 1, flesh_fields => {atev => ['template_output']}}
110         ]);
111
112
113         my $target = $e->retrieve_acq_purchase_order([              # instead we retrieve it separately
114             $event->target, {
115                 flesh => 2,
116                 flesh_fields => {
117                     acqpo  => ['provider'],
118                     acqpro => ['edi_default'],
119                 },
120             }
121         ]);
122
123         # this may be a retry attempt.  if so, reuse the original edi_message
124         my $message = $e->search_acq_edi_message({
125             purchase_order => $target->id,
126             message_type => 'ORDERS', 
127             status => 'retry'
128         })->[0];
129
130         if(!$message) {
131             $message = Fieldmapper::acq::edi_message->new;
132             $message->create_time('NOW');   # will need this later when we try to update from the object
133             $message->purchase_order($target->id);
134             $message->message_type('ORDERS');
135             $message->isnew(1);
136         }
137
138         my $logstr = sprintf "provider %s (%s)", $target->provider->id, $target->provider->name;
139         unless ($target->provider->edi_default and $message->account($target->provider->edi_default->id)) {
140             printf STDERR "ERROR: No edi_default account found for $logstr.  File will not be sent!\n";
141         }
142
143         $message->jedi($event->template_output()->data);
144
145         print "\ntarget->provider->edi_default->id: ", $target->provider->edi_default->id, "\n";
146         my $logstr2 = sprintf "event %s, PO %s, template_output %s", $_->{id}, $message->purchase_order, $event->template_output->id;
147         printf "\nNow calling attempt_translation for $logstr2\n\n";
148
149         unless (OpenILS::Application::Acq::EDI->attempt_translation($message, 1)) {
150             print STDERR "ERROR: attempt_translation failed for $logstr2\n";
151             next;
152             # The premise here is that if the translator failed, it is better to try again later from a "fresh" fetched file
153             # than to add a cascade of failing inscrutable copies of the same message(s) to our DB.  
154         }
155
156         print "Writing new message + translation to DB for $logstr2\n";
157
158         $e->xact_begin;
159         if($message->isnew) {
160             unless($e->create_acq_edi_message($message)) {
161                 $logger->error("Error creating acq.edi_message for $logstr2: ".$e->die_event);
162                 next;
163             }
164         } else {
165             unless($e->update_acq_edi_message($message)) {
166                 $logger->error("Error updating acq.edi_message for $logstr2: ".$e->die_event);
167                 next;
168             }
169         }
170         $e->xact_commit;
171
172         print "Calling send_core(...) for message (", $message->id, ")\n";
173         my $res = OpenILS::Application::Acq::EDI->send_core($target->provider->edi_default, [$message->id]);
174         if (@$res) {
175             my $message_out = shift @$res;
176             print "\tmessage ", $message->id, " status: ", $message_out->status, "\n";
177         } else {
178             print STDERR "ERROR: send_core failed for message ", $message->id, "\n";
179         }
180     }
181 }
182
183 print "\ndone\n";