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";
139 my @report_tags = split(/\./,$tags);
140 foreach my $t (@report_tags) {
141 print "\n\n=========== Starting to process tag $t\n";
142 print "==========================================\n\n";
145 foreach my $asset ($dom->findnodes('//asset')) {
146 if (index($asset->findvalue('./tag'),$t) != -1) {
147 push @asset_files, $asset->findvalue('./file');
151 foreach my $fname (@asset_files) {
152 my $asset_path = $mig_path . '../mig-asc/' . $fname;
153 open my $a, $asset_path or abort("Could not open $fname.");
154 while ( my $l = <$a> ) {
160 print_section_header(ucfirst($t),$fh);
161 my $linecount = $lines_per_page;
165 foreach my $asset ($dom->findnodes('//asset')) {
166 if (index($asset->findvalue('./tag'),$t) != -1) {
167 push @asset_files, $asset->findvalue('./file');
172 foreach my $report ($dom->findnodes('//report')) {
173 if (index($report->findvalue('./tag'),$t) != -1 and $report->findvalue('./iteration') eq '0') {
174 push @report_names, $report->findvalue('./name');
178 #only has one level of failover now but could change to array of hashes and loops
179 #but this keeps it simple and in practice I haven't needed more than two
182 foreach my $rname (@report_names) {
188 if ($debug eq 'on') {print "\nchecking for $rname ... ";}
189 %report0 = find_report($dom,$t,$rname,'0',$debug);
190 $check_tables0 = check_table($report0{query},$MIGSCHEMA,$debug,$rname);
191 if ($check_tables0 == 1) { $r = print_query($fh,%report0); } else {
192 %report1 = find_report($dom,$t,$rname,'1',$debug);
193 if (defined $report1{query}) {
194 $check_tables1 = check_table($report1{query},$MIGSCHEMA,$debug,$rname);
195 if ($check_tables1 == 1) { $r = print_query($fh,%report1); }
206 ############ end of main logic
209 my $reports_xml = shift;
210 my $mig_path = shift;
212 if ($reports_xml =~ m/\//) { return $reports_xml; }
214 my $mig_test_file = $mig_path . '/../mig-xml/' . $reports_xml;
215 my $working_test_dir = getcwd();
216 my $working_test_file = $working_test_dir . '/' . $reports_xml;
218 if (-e $mig_test_file) { return $mig_test_file; }
219 if (-e $working_test_file) { return $working_test_file; }
228 my $iteration = shift;
232 if ($debug eq 'on') {print "iteration $iteration ";}
233 foreach my $node ($dom->findnodes('//report')) {
234 if ($node->findvalue('./tag') =~ $tag and $node->findvalue('./iteration') eq $iteration and $node->findvalue('./name') eq $name) {
235 if ($debug eq 'on') {print "succeeded ... \n";}
237 name => $node->findvalue('./name'),
238 report_title => $node->findvalue('./report_title'),
239 query => $node->findvalue('./query'),
240 heading => $node->findvalue('./heading'),
241 tag => $node->findvalue('./tag'),
242 iteration => $node->findvalue('./iteration'),
243 note => $node->findvalue('./note'),
248 if ($debug eq 'on') {print "failed ... \n";}
250 name => "eaten by grue"
254 sub print_section_header {
259 #$t =~ s/(\w+)/\u$1/g;;
261 print $fh "== $t Reports\n";
265 sub create_report_name {
268 my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
269 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
271 my $date = $year . '_' . $abbr[$mon] . '_' . $mday;
273 $report_file = $rt . ' ' . $date . '.asciidoc';
274 $report_file =~ s/ /_/g;
278 sub write_title_page {
282 my $captions = shift;
284 my @abbr = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
285 my $l = length($report_title);
286 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
289 print $fh "$mday $abbr[$mon] $year\n";
291 #print $fh ":title-logo-image: image::eolilogosmall.png[pdfwidth=3in]\n";
293 if ($captions eq 'on') { print $fh ":caption:\n"; }
299 my $MIGSCHEMA = shift;
301 my $report_name = shift;
303 if ($debug eq 'on') {print "$query\n";}
307 my @qe = split(/ /,$query);
312 if ($qe[$i] eq 'FROM' or $qe[$i] eq 'JOIN') {
314 if ($qe[$q] ne '(SELECT') {
315 push @tables, $qe[$q];
320 if ($debug eq 'on') {print "checking tables ... ";}
323 foreach my $table (@tables) {
326 if (index($table,'.') != -1) {
327 $schema = (split /\./,$table)[0];
328 $table = (split /\./,$table)[1];
330 $table = clean_query_string($table);
331 if (defined $schema) {
332 $schema = clean_query_string($schema);
333 $sql = 'SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = \'' . $schema . '\' AND table_name = \'' . $table . '\');';
335 $sql = 'SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = \'' . $MIGSCHEMA . '\' AND table_name = \'' . $table . '\');';
337 my $sth = $dbh->prepare($sql);
339 while (my @row = $sth->fetchrow_array) {
340 if ($row[0] eq '1') {
344 if ($debug eq 'on') {print "detecting $table failed...\n";}
346 if ($row[0] eq '0') {$return_flag = 0;}
349 if ($return_flag == 1 and $debug eq 'on') {print "succeeded ...\n";}
350 if ($return_flag == 0) {print "! a table failed the find test for report $report_name\n\n";}
354 sub clean_query_string {
357 $str =~ s/(?!_)[[:punct:]]//g; #remove punct except underscores
366 my $query = $report{query};
367 my $sth = $dbh->prepare($query);
372 while (my @row = $sth->fetchrow_array) {
373 if ($header_flag == 0) {
374 print $fh "\n.*$report{report_title}*\n";
376 my @h = split(/\./,$report{heading});
379 while ($h_count <= $h_length) {
380 print $fh "|*$h[$h_count-1]* ";
386 my $row_length = @row;
388 while ($r <= $row_length) {
389 if (! defined $row[$r-1] ) {
392 print $fh "|$row[$r-1] ";
397 if ($header_flag == 1) {
398 print $fh "|===\n\n";
399 print $fh $report{note};
402 print "successfully wrote output for $report{name}.\n\n";
410 $col .= chr( ( $i % 26 ) + ord('A') );
411 $i = int( $i / 26 ) - 1;
414 return scalar reverse $col;
419 print STDERR "$0: $msg", "\n";