]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/support-scripts/edi_pusher.pl
Executable scripts
[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::CStoreEditor;   # needs init() after IDL is loaded (by Cronscript session)
24 use OpenILS::Utils::Cronscript;
25 use OpenILS::Utils::Fieldmapper;
26 use OpenILS::Application::AppUtils;
27 use OpenILS::Application::Acq::EDI;
28 use OpenSRF::Utils::Logger q/$logger/;
29
30 INIT {
31     $debug = 1;
32 }
33
34 my %opts = (
35     'quiet' => 0,
36     'max-batch-size=i' => -1
37 );
38
39 my $cs = OpenILS::Utils::Cronscript->new(\%opts);
40 $cs->session('open-ils.acq') or die "No session created";
41
42 OpenILS::Utils::CStoreEditor::init();
43
44 sub editor {
45     my $ed = OpenILS::Utils::CStoreEditor->new(@_) or die "Failed to get new CStoreEditor";
46     return $ed;
47 }
48
49 my $e = editor();
50 my $hook = 'acqpo.activated';
51 my $defs = $e->search_action_trigger_event_definition({
52     hook => $hook, 
53     reactor => 'GeneratePurchaseOrderJEDI',
54     active => 't'
55 });
56
57 # print Dumper($defs);
58 print "\nHook '$hook' is used in ", scalar(@$defs), " event definition(s):\n";
59
60 $Data::Dumper::Indent = 1;
61 my $remaining = $cs->first_defined('max-batch-size');
62 foreach my $def (@$defs) {
63     last if $remaining == 0;
64     printf "%3s - '%s'\n", $def->id, $def->name;
65
66     # give me all completed JEDI events that link to purchase_orders 
67     # that have no delivery attempts or are in the retry state
68     my $query = {
69         select => {atev => ['id']},
70         from => 'atev',
71         where => {
72             event_def => $def->id,
73             state => 'complete',
74             target => {
75                 'not in' => {
76                     select => {acqedim => ['purchase_order']},
77                     from => 'acqedim',
78                     where => {
79                         message_type => 'ORDERS',
80                         status => {'!=' => 'retry'}
81                     }
82                 }
83             }
84         },
85         order_by => {atev => ['add_time']}
86     };
87
88     $query->{limit} = $remaining if $remaining > 0;
89
90     my $events = $e->json_query($query);
91
92     if(!$events) {
93         $logger->error("error querying JEDI events for event definition $def->id");
94         next;
95     }
96
97     $remaining -= scalar(@$events);
98
99     print "Event definition ", $def->id, " has ", scalar(@$events), " event(s)\n";
100     foreach (@$events) {
101
102         my $event = $e->retrieve_action_trigger_event([
103             $_->{id}, 
104             {flesh => 1, flesh_fields => {atev => ['template_output']}}
105         ]);
106
107
108         my $target = $e->retrieve_acq_purchase_order([              # instead we retrieve it separately
109             $event->target, {
110                 flesh => 2,
111                 flesh_fields => {
112                     acqpo  => ['provider'],
113                     acqpro => ['edi_default'],
114                 },
115             }
116         ]);
117
118         # this may be a retry attempt.  if so, reuse the original edi_message
119         my $message = $e->search_acq_edi_message({
120             purchase_order => $target->id,
121             message_type => 'ORDERS', 
122             status => 'retry'
123         })->[0];
124
125         if(!$message) {
126             $message = Fieldmapper::acq::edi_message->new;
127             $message->create_time('NOW');   # will need this later when we try to update from the object
128             $message->purchase_order($target->id);
129             $message->message_type('ORDERS');
130             $message->isnew(1);
131         }
132
133         my $logstr = sprintf "provider %s (%s)", $target->provider->id, $target->provider->name;
134         unless ($target->provider->edi_default and $message->account($target->provider->edi_default->id)) {
135             printf STDERR "ERROR: No edi_default account found for $logstr.  File will not be sent!\n";
136         }
137
138         $message->jedi($event->template_output()->data);
139
140         print "\ntarget->provider->edi_default->id: ", $target->provider->edi_default->id, "\n";
141         print "\nNow calling attempt_translation\n\n";
142
143         unless (OpenILS::Application::Acq::EDI->attempt_translation($message, 1)) {
144             print STDERR "ERROR: attempt_translation failed, skipping message\n";
145             next;
146             # The premise here is that if the translator failed, it is better to try again later from a "fresh" fetched file
147             # than to add a cascade of failing inscrutable copies of the same message(s) to our DB.  
148         }
149
150         print "Writing new message + translation to DB\n";
151
152         $e->xact_begin;
153         if($message->isnew) {
154             unless($e->create_acq_edi_message($message)) {
155                 $logger->error("Error creating acq.edi_message for PO ".$target->id.' : '.$e->die_event);
156                 next;
157             }
158         } else {
159             unless($e->update_acq_edi_message($message)) {
160                 $logger->error("Error updating acq.edi_message for PO ".$target->id.' : '.$e->die_event);
161                 next;
162             }
163         }
164         $e->xact_commit;
165
166         print "Calling send_core(...)\n";
167         my $res = OpenILS::Application::Acq::EDI->send_core($target->provider->edi_default, [$message->id]);
168         if (@$res) {
169             my $message_out = shift @$res;
170             print "\tmessage ", $message->id, " status: ", $message_out->status, "\n";
171         } else {
172             print STDERR "ERROR: send_core failed for message ", $message->id, "\n";
173         }
174     }
175 }
176
177 print "\ndone\n";