3 ###############################################################################
6 =item B<reporter> --analyst "Analyst Name" --report_title "Report Title"
8 Generates an asciidoc file in the git working directory that can be converted to
9 any appropriate format. The analyst and report parameters are required.
11 Optional parameters are :
13 --added_page_title and --added_page_file
15 If one is used both must be. The added page file can be plain text or asciidoc. This
16 adds an extra arbitrary page of notes to the report. Mig assumes the page file is in the mig git directory.
20 This will define a set of tags to use, if not set it will default to Circs,
21 Holds, Actors, Bibs, Assets & Money.
25 Gives more information about what is happening. Defaults to off.
29 Allows you to override the default evergreen_staged_report.xml in the mig-xml folder.
31 --captions on OR --captions off
33 Adds the captions tag to asciidoc header to turn off captions in generated output.
40 ###############################################################################
49 HOME PGHOST PGPORT PGUSER PGDATABASE MIGSCHEMA
50 MIGBASEWORKDIR MIGBASEGITDIR MIGGITDIR MIGWORKDIR
58 my $mig_bin = "$FindBin::Bin/";
59 use lib "$FindBin::Bin/";
61 use open ':encoding(utf8)';
63 pod2usage(-verbose => 2) if defined $ARGV[0] && $ARGV[0] eq '--help';
64 pod2usage(-verbose => 1) if ! $ARGV[1];
66 my $analyst = 'Equinox Open Library Initiative';;
68 my $reports_xml = 'evergreen_staged_report.xml';
74 my $parser = XML::LibXML->new();
75 my $lines_per_page = 42;
81 'analyst:s' => \$analyst,
82 'report_title:s' => \$report_title,
83 'title:s' => \$report_title,
84 'reports_xml:s' => \$reports_xml,
86 'added_page_title:s' => \$added_page_title,
87 'added_page_file:s' => \$added_page_file,
88 'captions:s' => \$captions,
92 if (!defined $tags) {$tags = 'circs.holds.actors.bibs.assets.money.notices'};
93 if (!defined $report_title) { abort('--report_title or --title must be supplied'); }
94 if (!defined $analyst) { abort('--analyst must be supplied'); }
96 my $mig_path = abs_path($0);
97 $mig_path =~ s|[^/]+$||;
98 $reports_xml = find_xml($reports_xml,$mig_path);
99 if (!defined $reports_xml) { abort("Can not find xml reports file."); }
100 my $dom = $parser->parse_file($reports_xml);
102 if (defined $added_page_file or defined $added_page_title) {
103 abort('must specify --added_page_file and --added_page_title') unless defined $added_page_file and defined $added_page_title;
105 if (defined $added_page_file) { $added_page_file = $MIGGITDIR . $added_page_file; }
107 my $dbh = Mig::db_connect();
108 my $report_file = create_report_name($report_title);
109 $report_file = $MIGGITDIR . $report_file;
111 open($fh, '>', $report_file) or abort("Could not open output file $report_file!");
112 write_title_page($report_title,$fh,$analyst,$captions);
114 if (defined $added_page_file and defined $added_page_title) {
116 print $fh "== $added_page_title\n";
117 print "$added_page_file\t$added_page_title\n";
118 open(my $an,'<:encoding(UTF-8)', $added_page_file) or abort("Could not open $added_page_file!");
119 while ( my $line = <$an> ) {
126 foreach my $func ($dom->findnodes('//function')) {
127 my $fdrop = $func->findvalue('./drop');
128 my $fcreate = $func->findvalue('./create');
129 my $fname = $func->findvalue('./name');
130 my $sdrop = $dbh->prepare($fdrop);
131 my $screate = $dbh->prepare($fcreate);
132 print "dropping function $fname ... ";
134 print "creating function $fname\n\n";
138 foreach my $table ($dom->findnodes('//table')) {
139 my $tdrop = $table->findvalue('./drop');
140 my $tcreate = $table->findvalue('./create');
141 my $tname = $table->findvalue('./name');
142 my $sdrop = $dbh->prepare($tdrop);
143 my $screate = $dbh->prepare($tcreate);
144 print "dropping table $tname ... ";
146 print "creating table $tname\n\n";
151 my @report_tags = split(/\./,$tags);
152 foreach my $t (@report_tags) {
153 print "\n\n=========== Starting to process tag $t\n";
154 print "==========================================\n\n";
157 foreach my $asset ($dom->findnodes('//asset')) {
158 if (index($asset->findvalue('./tag'),$t) != -1) {
159 push @asset_files, $asset->findvalue('./file');
163 foreach my $fname (@asset_files) {
164 my $asset_path = $mig_path . '../mig-asc/' . $fname;
165 open my $a, $asset_path or abort("Could not open $fname.");
166 while ( my $l = <$a> ) {
172 print_section_header(ucfirst($t),$fh);
173 my $linecount = $lines_per_page;
177 foreach my $asset ($dom->findnodes('//asset')) {
178 if (index($asset->findvalue('./tag'),$t) != -1) {
179 push @asset_files, $asset->findvalue('./file');
184 foreach my $report ($dom->findnodes('//report')) {
185 if (index($report->findvalue('./tag'),$t) != -1 and $report->findvalue('./iteration') eq '0') {
186 push @report_names, $report->findvalue('./name');
190 #only has one level of failover now but could change to array of hashes and loops
191 #but this keeps it simple and in practice I haven't needed more than two
194 foreach my $rname (@report_names) {
200 if ($debug eq 'on') {print "\nchecking for $rname ... ";}
201 %report0 = find_report($dom,$t,$rname,'0',$debug);
202 $check_tables0 = check_table($report0{query},$MIGSCHEMA,$debug,$rname);
203 if ($check_tables0 == 1) { $r = print_query($fh,%report0); } else {
204 %report1 = find_report($dom,$t,$rname,'1',$debug);
205 if (defined $report1{query}) {
206 $check_tables1 = check_table($report1{query},$MIGSCHEMA,$debug,$rname);
207 if ($check_tables1 == 1) { $r = print_query($fh,%report1); }
216 foreach my $table ($dom->findnodes('//table')) {
217 my $tdrop = $table->findvalue('./drop');
218 my $tname = $table->findvalue('./name');
219 my $sdrop = $dbh->prepare($tdrop);
220 print "cleaning up table $tname ... \n";
226 ############ end of main logic
229 my $reports_xml = shift;
230 my $mig_path = shift;
232 if ($reports_xml =~ m/\//) { return $reports_xml; }
234 my $mig_test_file = $mig_path . '/../mig-xml/' . $reports_xml;
235 my $working_test_dir = getcwd();
236 my $working_test_file = $working_test_dir . '/' . $reports_xml;
238 if (-e $mig_test_file) { return $mig_test_file; }
239 if (-e $working_test_file) { return $working_test_file; }
248 my $iteration = shift;
252 if ($debug eq 'on') {print "iteration $iteration ";}
253 foreach my $node ($dom->findnodes('//report')) {
254 if ($node->findvalue('./tag') =~ $tag and $node->findvalue('./iteration') eq $iteration and $node->findvalue('./name') eq $name) {
255 if ($debug eq 'on') {print "succeeded ... \n";}
257 name => $node->findvalue('./name'),
258 report_title => $node->findvalue('./report_title'),
259 query => $node->findvalue('./query'),
260 heading => $node->findvalue('./heading'),
261 tag => $node->findvalue('./tag'),
262 iteration => $node->findvalue('./iteration'),
263 note => $node->findvalue('./note'),
268 if ($debug eq 'on') {print "failed ... \n";}
270 name => "eaten by grue"
274 sub print_section_header {
279 #$t =~ s/(\w+)/\u$1/g;;
281 print $fh "== $t Reports\n";
285 sub create_report_name {
288 my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
289 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
291 my $date = $year . '_' . $abbr[$mon] . '_' . $mday;
293 $report_file = $rt . ' ' . $date . '.asciidoc';
294 $report_file =~ s/ /_/g;
298 sub write_title_page {
302 my $captions = shift;
304 my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
305 my $l = length($report_title);
306 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
309 print $fh "$mday $abbr[$mon] $year\n";
311 #print $fh ":title-logo-image: image::eolilogosmall.png[pdfwidth=3in]\n";
313 if ($captions eq 'on') { print $fh ":caption:\n"; }
319 my $MIGSCHEMA = shift;
321 my $report_name = shift;
323 if ($debug eq 'on') {print "$query\n";}
327 my @qe = split(/ /,$query);
332 if ($qe[$i] eq 'FROM' or $qe[$i] eq 'JOIN') {
334 if ($qe[$q] ne '(SELECT') {
335 push @tables, $qe[$q];
340 if ($debug eq 'on') {print "checking tables ... ";}
343 foreach my $table (@tables) {
346 if (index($table,'.') != -1) {
347 $schema = (split /\./,$table)[0];
348 $table = (split /\./,$table)[1];
350 $table = clean_query_string($table);
351 if (defined $schema) {
352 $schema = clean_query_string($schema);
353 $sql = 'SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = \'' . $schema . '\' AND table_name = \'' . $table . '\');';
355 $sql = 'SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = \'' . $MIGSCHEMA . '\' AND table_name = \'' . $table . '\');';
357 my $sth = $dbh->prepare($sql);
359 while (my @row = $sth->fetchrow_array) {
360 if ($row[0] eq '1') {
364 if ($debug eq 'on') {print "detecting $table failed...\n";}
366 if ($row[0] eq '0') {$return_flag = 0;}
369 if ($return_flag == 1 and $debug eq 'on') {print "succeeded ...\n";}
370 if ($return_flag == 0) {print "! a table failed the find test for report $report_name\n\n";}
374 sub clean_query_string {
377 $str =~ s/(?!_)[[:punct:]]//g; #remove punct except underscores
386 my $query = $report{query};
387 my $sth = $dbh->prepare($query);
392 while (my @row = $sth->fetchrow_array) {
393 if ($header_flag == 0) {
394 print $fh "\n.*$report{report_title}*\n";
396 my @h = split(/\./,$report{heading});
399 while ($h_count <= $h_length) {
400 print $fh "|*$h[$h_count-1]* ";
406 my $row_length = @row;
408 while ($r <= $row_length) {
409 if (! defined $row[$r-1] ) {
412 print $fh "|$row[$r-1] ";
417 if ($header_flag == 1) {
418 print $fh "|===\n\n";
419 print $fh $report{note};
422 print "successfully wrote output for $report{name}.\n\n";
430 $col .= chr( ( $i % 26 ) + ord('A') );
431 $i = int( $i / 26 ) - 1;
434 return scalar reverse $col;
439 print STDERR "$0: $msg", "\n";