=================================================================== RCS file: /cvs/RT/Invoicing/rt_invoices.pl,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- RT/Invoicing/rt_invoices.pl 2011/03/21 04:19:25 1.3 +++ RT/Invoicing/rt_invoices.pl 2011/03/21 05:01:33 1.4 @@ -80,7 +80,7 @@ $end->subtract( seconds => 1 ); - $startdate = $start->clone if $startdate > $start; + $startdate = $start->clone if !$startdate || $startdate > $start; $invoice{start} ||= $start->clone; $invoice{end} = $end->clone; my %hours = ( @@ -137,12 +137,6 @@ # XXX This should be a config option qw/ open stalled resolved /; -#push @limits, -# { -# attribute => 'resolved', -# operator => '>=', -# value => '2011-03-01' -# }; if ($startdate) { push @limits, { @@ -152,21 +146,25 @@ }; } -#push @limits, { attribute => 'id', operator => '=', value => '51' }; -#push @limits, { attribute => '', operator => '', value => '' }; - my $results = $tickets->search( limits => \@limits, orderby => 'id', ); -#print Dump $ticket, $results; - my $count = $results->count; print "There are $count results that matched your query\n"; my $iterator = $results->get_iterator; while ( my $ticket = &$iterator ) { + my $invoice = find_invoice_for_ticket( \@invoices, $ticket ); + + if ( !$invoice ) { + say "No invoice found for ticket " . $ticket->id; + + # XXX should construct a "new" invoice to pop onto the list + next; + } + my %project = ( id => $ticket->id, queue => $ticket->queue, @@ -182,35 +180,6 @@ expenses => [], ); - my $invoice; -INVOICE: foreach my $i (@invoices) { - next INVOICE unless $i->{match}; - foreach my $m ( @{ $i->{match} } ) { - my $type = $m->{type}; - my $thing = join ' ', $ticket->$type; - - if ( $m->{$type} ) { - my $match = lc $m->{$type}; - next INVOICE unless lc($thing) ~~ $match; - } - elsif ( $m->{regex} ) { - next INVOICE unless $thing ~~ /\Q$m->{regex}\E/; - } - else { - warn "Invalid match!"; - next INVOICE; - } - } - $invoice = $i; - } - - if ( !$invoice ) { - say "No invoice found for ticket " . $ticket->id; - - # XXX should construct a "new" invoice to pop onto the list - next; - } - #foreach my $r ($ticket->requestors) { # $users->id( $r ); # $users->retrieve; @@ -238,49 +207,22 @@ next if $invoice->{start} && $invoice->{start} > $txn_date; next if $invoice->{end} < $txn_date; - my $hours = {}; - if ( $invoice->{hours} ) { - foreach my $h ( @{ $invoice->{hours} } ) { - next if $h->{start} && $h->{start} > $txn_date; - next if $h->{end} < $txn_date; + my $fee = make_fee( $ticket, $txn, $invoice->{rates} ); + push @{ $project{fees} }, $fee; - $hours = $h->{hours}; - last; - } - } + my $hours = hours_for_date( $invoice, $txn_date ); - my $work_time = sprintf "%.03f", $txn->time_taken / 60; - my $work_type = $txn->cf('WorkType'); - my $work_rate - = $invoice->{rates}{$work_type} - || $invoice->{rates}{default} - || 0; - my $h_type - = exists $hours->{$work_type} - ? $work_type + = exists $hours->{ $fee->{type} } + ? $fee->{type} : 'default'; - my %fee = ( - id => $txn->id, - contents => $txn->created . ' (' - . $txn->id . ')' . "\n\n" - . ( $txn->data || $ticket->subject ), - count => $work_time, - rate => $work_rate, - ); - if ( $work_type && $work_type ne 'Normal' ) { - $fee{detail} = $work_type . ' rate'; - } + next unless exists $hours->{$h_type} && $hours->{$h_type} > 0; - push @{ $project{fees} }, \%fee; - - next unless $hours->{$h_type} && $hours->{$h_type} > 0; - my $discount_time = 0; - if ( $hours->{$h_type} > $work_time ) { - $hours->{$h_type} -= $work_time; - $discount_time = $work_time; + if ( $hours->{$h_type} > $fee->{count} ) { + $hours->{$h_type} -= $fee->{count}; + $discount_time = $fee->{count}; } else { $discount_time = $hours->{$h_type}; @@ -288,9 +230,11 @@ } if ($discount_time) { - $fee{detail} = "$discount_time $work_type Hours Discounted"; - $invoice->{discount}{amount} += $discount_time * $fee{rate}; - $invoice->{discount}{hours}{$work_type} += $discount_time; + $invoice->{discount}{amount} += $discount_time * $fee->{rate}; + $invoice->{discount}{hours}{$h_type} += $discount_time; + + $h_type = '' if $h_type eq 'default'; + $fee->{detail} = "$discount_time $h_type Hours Discounted"; } #print Dump $txn; exit; @@ -366,6 +310,71 @@ #$amount =~ s/\.\d\d\K.*$//; #return $amount; return sprintf "%.02f", $amount; +} + +sub find_invoice_for_ticket { + my ( $invoices, $ticket ) = @_; + +INVOICE: foreach my $i ( @{$invoices} ) { + next INVOICE unless $i->{match}; + foreach my $m ( @{ $i->{match} } ) { + my $type = $m->{type}; + my $thing = join ' ', $ticket->$type; + + if ( $m->{$type} ) { + my $match = lc $m->{$type}; + next INVOICE unless lc($thing) ~~ $match; + } + elsif ( $m->{regex} ) { + next INVOICE unless $thing ~~ /\Q$m->{regex}\E/; + } + else { + warn "Invalid match!"; + next INVOICE; + } + } + return $i; + } +} + +sub make_fee { + my ( $ticket, $txn, $rates ) = @_; + + my $work_time = sprintf "%.03f", $txn->time_taken / 60; + my $work_type = $txn->cf('WorkType'); + my $work_rate = $rates->{$work_type} || $rates->{default} || 0; + + my %fee = ( + id => $txn->id, + contents => $txn->created . ' (' + . $txn->id . ')' . "\n\n" + . ( $txn->data || $ticket->subject ), + count => $work_time, + rate => $work_rate, + type => $work_type, + ); + + if ( $work_type && $work_type ne 'Normal' ) { + $fee{detail} = $work_type . ' rate'; + } + + return \%fee; +} + +sub hours_for_date { + my ( $invoice, $date ) = @_; + + my $hours = {}; + if ( $invoice->{hours} ) { + foreach my $h ( @{ $invoice->{hours} } ) { + next if $h->{start} && $h->{start} > $date; + next if $h->{end} < $date; + + $hours = $h->{hours}; + last; + } + } + return $hours; } package RTI::Config;