2018-07-15 15:27:22 +00:00
|
|
|
#!/usr/bin/perl
|
|
|
|
# Copyright © 2018, Bradley M. Kuhn
|
|
|
|
# License: AGPL-3.0-or-later
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use autodie qw(open close opendir);
|
|
|
|
|
|
|
|
use Getopt::Long;
|
|
|
|
use File::Spec;
|
|
|
|
use Date::Manip qw(ParseDate UnixDate);
|
|
|
|
|
2018-07-22 22:08:31 +00:00
|
|
|
my($PAYMENT_DIR, $VERBOSE, $INTERACTIVE, $PAYMENT_NUMBER, $RT_CMD, $INVOICE_LINE);
|
2018-07-15 16:05:33 +00:00
|
|
|
|
2018-07-22 21:35:20 +00:00
|
|
|
###############################################################################
|
2018-07-15 15:27:22 +00:00
|
|
|
sub FindUniqueTicket(@) {
|
|
|
|
my @searchTerms = @_;
|
2018-07-15 16:05:33 +00:00
|
|
|
open(my $rtLsFH, "-|", "$RT_CMD", "ls", "-i", 'Queue = outreachy-interns AND ' .
|
2018-07-15 15:27:22 +00:00
|
|
|
join(" AND ", @searchTerms));
|
|
|
|
my $ticketSpec;
|
|
|
|
while (my $lsLine = <$rtLsFH>) {
|
|
|
|
chomp $lsLine;
|
|
|
|
if ($lsLine =~ /ticket/) {
|
|
|
|
if (defined $ticketSpec) {
|
|
|
|
$ticketSpec = undef;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
$ticketSpec = $lsLine;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $rtLsFH;
|
|
|
|
return $ticketSpec;
|
|
|
|
}
|
2018-07-22 21:35:20 +00:00
|
|
|
###############################################################################
|
2018-07-15 16:05:58 +00:00
|
|
|
sub PaymentDateByTicket($$) {
|
|
|
|
my($ticketSpec, $paymentNumber) = @_;
|
|
|
|
open(my $rtPayFH, "-|", "$RT_CMD", "show", "-f", 'CF.{payment-' . $paymentNumber . '-sent}', $ticketSpec);
|
|
|
|
my $date;
|
|
|
|
while (my $payLine = <$rtPayFH>) {
|
|
|
|
chomp $payLine;
|
|
|
|
if ($payLine =~ /[\d\-]+/) {
|
|
|
|
$date = $payLine;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $rtPayFH;
|
|
|
|
return $date;
|
|
|
|
}
|
2018-07-22 21:35:20 +00:00
|
|
|
###############################################################################
|
2018-07-15 16:05:58 +00:00
|
|
|
sub LedgerTagFromTicket($$) {
|
|
|
|
my($ticketSpec, $tag) = @_;
|
|
|
|
open(my $rtPayFH, "-|", "$RT_CMD", "show", "-f", 'CF.{ledger-tags}', $ticketSpec);
|
|
|
|
my $tagValue;
|
|
|
|
while (my $tagsLine = <$rtPayFH>) {
|
|
|
|
chomp $tagsLine;
|
|
|
|
if ($tagsLine =~ /^\s*;?$tag\s*:\s*(.+)\s*$/i) {
|
|
|
|
$tagValue = $1;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $rtPayFH;
|
|
|
|
return $tagValue;
|
|
|
|
}
|
2018-07-22 21:35:20 +00:00
|
|
|
###############################################################################
|
2018-07-22 22:08:31 +00:00
|
|
|
sub GetLinksForTicket($) {
|
|
|
|
my($ticketSpec) = @_;
|
|
|
|
my @linked;
|
|
|
|
open(my $rtLinksFH, "-|", "$RT_CMD", "show", $ticketSpec . '/links');
|
|
|
|
while (my $linksLine = <$rtLinksFH>) {
|
|
|
|
if ($linksLine =~ m%rt.*ticket/(\d+)\s*$%) {
|
|
|
|
push(@linked, $1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $rtLinksFH;
|
|
|
|
return @linked;
|
|
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
sub FindTaxTicketFromList(@) {
|
|
|
|
my $taxTicket;
|
|
|
|
foreach my $ticket (@_) {
|
|
|
|
open(my $rtQueueFH, "-|", "$RT_CMD", "show", "-f", 'Queue', $ticket);
|
|
|
|
while (my $queueLine = <$rtQueueFH>) {
|
|
|
|
if ($queueLine =~ /\s*Queue\s*:\s*(\S+)\s*$/) {
|
|
|
|
my $queue = $1;
|
|
|
|
$taxTicket = $ticket if $queue =~ /accounts-taxinfo/;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $rtQueueFH;
|
|
|
|
last if defined $taxTicket;
|
|
|
|
}
|
|
|
|
$taxTicket = "ticket/$taxTicket" if defined $taxTicket;
|
|
|
|
return $taxTicket;
|
|
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
sub GetStatusFromTicket($) {
|
|
|
|
my($ticketSpec) = @_;
|
|
|
|
my $status;
|
|
|
|
open(my $statusFH, "-|", "$RT_CMD", "show", "-f", 'Status', $ticketSpec);
|
|
|
|
while (my $statusLine = <$statusFH>) {
|
|
|
|
if ($statusLine =~ /\s*Status\s*:\s*(\S+)\s*$/) {
|
|
|
|
$status = $1;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $statusFH;
|
|
|
|
return $status;
|
|
|
|
}
|
|
|
|
###############################################################################
|
|
|
|
sub GetCustomFieldForTicket($$) {
|
|
|
|
my($ticketSpec, $customField) = @_;
|
|
|
|
open(my $rtPayFH, "-|", "$RT_CMD", "show", "-f", 'CF.{' . $customField .'}', $ticketSpec);
|
|
|
|
my $val;
|
|
|
|
while (my $customFieldLine = <$rtPayFH>) {
|
|
|
|
chomp $customFieldLine;
|
|
|
|
if ($customFieldLine =~ /^\s*(\S+)\s*$/) {
|
|
|
|
$val = $customFieldLine;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close $rtPayFH;
|
|
|
|
return $val;
|
|
|
|
}
|
|
|
|
###############################################################################
|
2018-07-15 15:27:22 +00:00
|
|
|
|
2018-07-15 16:05:33 +00:00
|
|
|
GetOptions("paymentDir=s" => \$PAYMENT_DIR, "verbose=i" => \$VERBOSE, "interactive" => \$INTERACTIVE,
|
2018-07-22 22:08:31 +00:00
|
|
|
"paymentNumber=i" => \$PAYMENT_NUMBER, "rtCommand=s" => \$RT_CMD,
|
|
|
|
"invoiceLine=s" => \$INVOICE_LINE);
|
2018-07-15 16:05:33 +00:00
|
|
|
|
|
|
|
$RT_CMD = '/usr/bin/rt' unless defined $RT_CMD;
|
|
|
|
|
|
|
|
$INTERACTIVE = 0 if not defined $INTERACTIVE;
|
2018-07-15 15:27:22 +00:00
|
|
|
|
2018-07-22 22:08:31 +00:00
|
|
|
unless (defined $INVOICE_LINE and $INVOICE_LINE =~ /^rt.*/) {
|
|
|
|
print STDERR "usage: $0 --invoiceLine=<RT_SPEC> option is required and must match an RT spec\n";
|
|
|
|
exit 1;
|
|
|
|
}
|
2018-07-15 15:27:22 +00:00
|
|
|
unless (defined $PAYMENT_DIR and -d $PAYMENT_DIR) {
|
|
|
|
print STDERR "usage: $0 --paymentDir=<DIRECTORY> option is required and directory must exist\n";
|
|
|
|
exit 1;
|
|
|
|
}
|
2018-07-15 16:05:33 +00:00
|
|
|
unless (defined $PAYMENT_NUMBER and $PAYMENT_NUMBER =~ /^123$/) {
|
|
|
|
print STDERR "usage: $0 --paymentNumber=<VALUE> option is required and must be 1, 2 or 3\n";
|
|
|
|
exit 1;
|
|
|
|
}
|
2018-07-15 15:27:22 +00:00
|
|
|
$VERBOSE = 0 unless defined $VERBOSE;
|
|
|
|
|
|
|
|
opendir(my $dh, $PAYMENT_DIR);
|
|
|
|
|
|
|
|
while (my $file = readdir $dh) {
|
|
|
|
unless ($file =~ /^\s*(success|faile?d?)-(\S+)\.txt\s*$/i) {
|
|
|
|
print STDERR "Skipping $file which does not match proper format...\n" if ($VERBOSE >= 2);
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
my($pass, $name) = ($1, $2);
|
2018-07-15 16:04:31 +00:00
|
|
|
$pass = ($pass =~ /success/) ? 1 : 0;
|
|
|
|
|
2018-07-15 15:27:22 +00:00
|
|
|
open(my $fh, "<", File::Spec->catfile($PAYMENT_DIR, $file));
|
2018-07-15 16:04:31 +00:00
|
|
|
my $mentorDate;
|
2018-07-15 15:27:22 +00:00
|
|
|
while (my $line = <$fh> ) {
|
|
|
|
if ($line =~ /^\s*Date\s*:\s*(.+)\s*$/) {
|
2018-07-15 16:04:31 +00:00
|
|
|
$mentorDate = UnixDate(ParseDate($1), "%Y-%m-%d");
|
2018-07-15 15:27:22 +00:00
|
|
|
next;
|
|
|
|
}
|
|
|
|
}
|
2018-07-15 16:07:54 +00:00
|
|
|
if (not defined $mentorDate) {
|
|
|
|
print STDERR "\"$file\": Skipping: Inside that file there is no valid Date: header" ;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2018-07-15 15:27:22 +00:00
|
|
|
my(@nameComponents) = split(/\s*-\s*/, $name);
|
|
|
|
my(@searchTerms);
|
|
|
|
foreach my $name (@nameComponents) {
|
|
|
|
push(@searchTerms, 'Subject LIKE "' . $name . '"');
|
|
|
|
}
|
|
|
|
my $ticket = FindUniqueTicket(@searchTerms);
|
|
|
|
if (not defined $ticket) {
|
|
|
|
foreach my $term (@searchTerms) {
|
|
|
|
$ticket = FindUniqueTicket(($term));
|
|
|
|
last if (defined $ticket);
|
|
|
|
}
|
|
|
|
}
|
2018-07-22 21:33:12 +00:00
|
|
|
if (not defined $ticket) {
|
|
|
|
if (not $INTERACTIVE) {
|
|
|
|
print STDERR "\"$file\": Skipped: unable to to find a matching ticket.\n";
|
|
|
|
next;
|
|
|
|
} else {
|
|
|
|
# FIXME: prompt for ticket
|
|
|
|
die "interactive mode not yet supported";
|
|
|
|
}
|
|
|
|
}
|
2018-07-22 22:08:45 +00:00
|
|
|
# Find the ticket number for this intern.
|
|
|
|
my $entity = LedgerTagFromTicket($ticket, 'Entity');
|
|
|
|
if (not defined $entity) {
|
|
|
|
print STDERR "\"$file\": \"$ticket\": Skipping: cannot determine Entity from ticket." ;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($PAYMENT_NUMBER <= 1) {
|
2018-07-22 21:33:12 +00:00
|
|
|
print STDERR "Sorry, script does not yet support first payment\n";
|
|
|
|
exit 1;
|
|
|
|
}
|
|
|
|
# Check to see if this payment was already made
|
|
|
|
my $thisPayDate = PaymentDateByTicket($ticket, $PAYMENT_NUMBER);
|
|
|
|
if (defined $thisPayDate) {
|
|
|
|
print STDERR "\"$file\": \"$ticket\": Skipped: payment $PAYMENT_NUMBER was already made";
|
|
|
|
if ($pass) {
|
|
|
|
print STDERR ".\n";
|
|
|
|
} else {
|
|
|
|
print STDERR "... BIG PROBLEM: the intern actually failed but got this payment.\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# Check to see if previous payment was sent payment
|
|
|
|
my $prevPay = $PAYMENT_NUMBER - 1;
|
|
|
|
|
|
|
|
my $lastPayDate = PaymentDateByTicket($ticket, $prevPay);
|
2018-07-22 21:35:32 +00:00
|
|
|
if (not defined $lastPayDate) {
|
2018-07-22 21:33:12 +00:00
|
|
|
print STDERR "\"$file\": \"$ticket\": Skipped: payment $prevPay was not made yet.\n";
|
|
|
|
next;
|
|
|
|
}
|
2018-07-22 21:35:32 +00:00
|
|
|
|
2018-07-15 15:27:22 +00:00
|
|
|
}
|
2018-07-15 15:34:14 +00:00
|
|
|
###############################################################################
|
|
|
|
#
|
|
|
|
# Local variables:
|
|
|
|
# compile-command: "perl -c rt-outreachy-payment-next.plx"
|
|
|
|
# perl-indent-level: 2
|
|
|
|
# End:
|