]> git.donarmstrong.com Git - bin.git/blobdiff - make_invoice
add reset usb bus command
[bin.git] / make_invoice
index d8cf50f12e3a037ffe73808d6bdca8213c9f77c2..0047d45079b0544e92a4c1121489629ad1c55a02 100755 (executable)
@@ -21,9 +21,12 @@ make_invoice - makes invoices using latex
  make_invoice [options]
 
  Options:
-  --log, the log file to use to make the invoice
-  --template, the template to use to make the invoice
-  --svn, whether to use subversion or not
+  --log,-l the log file to use to make the invoice
+  --template,-t the template to use to make the invoice
+  --min-time-interval, -m minimum time to bill, default 0
+  --time-granularity, -g time granularity, default 0
+  --hourly-fee, -f hourly fee, default 50.00
+  --svn,-s whether to use subversion or not
   --debug, -d debugging level (Default 0)
   --help, -h display this help
   --man, -m display manual
@@ -62,6 +65,14 @@ Time granularity, defaults to 0.
 
 Hourly fee, defaults to 50.00
 
+=item B<--tex-only>
+
+Only output the LaTeX file
+
+=item B<--log-only>
+
+Only output the log file
+
 =item B<--debug, -d>
 
 Debug verbosity. (Default 0)
@@ -89,16 +100,20 @@ use POSIX qw(ceil strftime);
 use Cwd qw(cwd);
 use Text::Template;
 
+use Params::Validate qw(validate_with :types);
+
 my %options = (log             => undef,
               template        => undef,
               svn             => undef,
               invoice         => undef,
-              time_interval   => 0,
-              time_granularity => 0,
+              time_interval   => 0.00,
+              time_granularity => 0.00,
               hourly_fee      => '50.00',
               debug           => 0,
               help            => 0,
               man             => 0,
+              log_only        => 0,
+              tex_only        => 0,
               );
 
 GetOptions(\%options,
@@ -106,6 +121,8 @@ GetOptions(\%options,
           'time_granularity|time-granularity|g=s',
           'time_interval|min-time-interval|T=s',
           'hourly_fee|hourly-fee|f=s',
+          'log_only|log-only',
+          'tex_only|tex-only',
           'debug|d+','help|h|?','man|m');
 
 pod2usage() if $options{help};
@@ -135,9 +152,19 @@ my $template_fh = IO::File->new($options{template},'r') or
 
 
 my $calc_log = '';
-my $tex_log = '';
+my $tex_log = <<'EOF';
+\setlength\LTleft{0pt plus 1fill minus 1fill}%
+\let\LTright\LTleft
+\begin{longtable}{|p{9cm}|r|r|r|r|}%
+%  \caption*{}
+\hline
+  \mbox{Description} & Item Cost & Quantity & Cost & Total \\
+\endhead
+EOF
 my $totaldelta = undef;
 
+my $total = 0;
+
 my $first_date = undef;
 my $last_date = undef;
 my $time = undef;
@@ -147,34 +174,54 @@ my @events;
 
 while (<$log_fh>) {
      chomp;
+     next if /^Total: \d+\.\d{2}$/;
      if (/^\s*\* /) {
+         print STDERR $_."\n";
          if (defined $time) {
-              $tex_log .= format_events($date,$date2,$time,@events);
+              $tex_log .= format_events(date => $date,
+                                        date2 => $date2,
+                                        time => $time,
+                                        total => \$total,
+                                        events => \@events);
               @events = ();
               $date = undef;
               $time = undef;
          }
-         my $string = $_;
-         my ($d1,$d2) = map {s/^\s*\*\s*//;
-                            ParseDate($_)
-                       } split /\s*-\s*/;
+          s/\s*\[[\.\d]+\]\s*\[[\.\d]+\]\s*$//;
+         my ($d1,$d2);
+         if (/\s*\*\s*CLOCK:\s+\[([^\]]+)\]--\[([^\]]+)\]/ or
+             /^\s*\*\s*(.+)?\s* - \s*(.+)?\s*$/
+            ) {
+              $d1 = UnixDate(ParseDate($1),'%s');
+              $d2 = UnixDate(ParseDate($2),'%s');
+              if (not defined $d1) {
+                  die "Invalid date: $1";
+              }
+              if (not defined $d2) {
+                  die "Invalid date: $2";
+              }
+          } else {
+              die "malformed line $_";
+          }
+          my $string = '* '.strftime('%A, %B %e, %H:%M:%S',localtime($d1)).' - '.
+              strftime('%A, %B %e, %H:%M:%S',localtime($d2));
          if (not defined $first_date) {
               $first_date = $d1;
          }
          $last_date = $d2;
-         my $delta = DateCalc($d1,$d2);
-         my $hours = Delta_Format($delta,0,'%ht');
+         my $delta = $d2-$d1;
+         $date = $d1;
+         $date2 = $d2;
+         my $hours = $delta / (60*60);
          if ($hours < $options{time_interval}) {
               $hours = $options{time_interval}
          }
-         if ($options{time_granularity}) {
+         if ($options{time_granularity} > 0) {
               $hours = ceil($hours / $options{time_granularity})*$options{time_granularity};
          }
-         $delta = ParseDateDelta($hours * 60 * 60 . ' sec');
-         ($date,$date2) = ($d1,$d2);
          $time = $hours;
-         $totaldelta = defined($totaldelta)?DateCalc($delta,$totaldelta):$delta;
-         $calc_log .= qq($string [).Delta_Format($delta,2,q(%ht)).qq(] [).Delta_Format($totaldelta,2,q(%ht)).qq(]\n);
+         $totaldelta += $delta;
+         $calc_log .= $string.q( [).sprintf('%.2f',$hours).qq(] [).sprintf('%.2f',$totaldelta/(60*60)).qq(]\n);
      }
      elsif (/^\s+-\s*(.+)/) {
          my $event = $1;
@@ -186,15 +233,31 @@ while (<$log_fh>) {
          $calc_log .= $_.qq(\n);
      }
 }
-$calc_log .= "\nTotal: ".Delta_Format($totaldelta,2,q(%ht)).qq(\n);
+$calc_log .= "\nTotal: ".sprintf('%.2f',$totaldelta/(60*60)).qq(\n);
 if (defined $time) {
-     $tex_log .= format_events($date,$date2,$time,@events);
+    $tex_log .= format_events(date => $date,
+                              date2 => $date2,
+                             time => $time,
+                             total => \$total,
+                             events => \@events);
      @events = ();
      $date = undef;
      $date2 = undef;
      $time = undef;
 }
 
+$tex_log .= <<'EOF';
+\hline\hline
+\multicolumn{4}{|r|}{\textbf{Total}} & \$%
+EOF
+
+$tex_log .= sprintf('%.2f',$total)."%\n";
+
+$tex_log .= <<'EOF';
+\\
+\hline
+\end{longtable}
+EOF
 
 my $template;
 {
@@ -202,8 +265,8 @@ my $template;
      $template = <$template_fh>;
 }
 
-my $invoice_start = UnixDate($first_date,'%B %e, %Y');
-my $invoice_stop = UnixDate($last_date,'%B %e, %Y');
+my $invoice_start = strftime('%c',localtime($first_date));
+my $invoice_stop = strftime('%c',localtime($last_date));
 
 my $tt = Text::Template->new(TYPE=>'string',
                             SOURCE => $template,
@@ -212,13 +275,25 @@ my $tt = Text::Template->new(TYPE=>'string',
 my $tex_invoice = $tt->fill_in(HASH=>{start => $invoice_start,
                                      stop  => $invoice_stop,
                                      log   => $tex_log,
+                                     total => sprintf('%0.2f',$total),
                                     }
                              );
 if (not defined $tex_invoice) {
      die $Text::Template::ERROR;
 }
 
-my $invoice_date = UnixDate($last_date,'%m_%d_%Y');
+if ($options{log_only}) {
+    print $calc_log;
+    exit 0;
+}
+
+if ($options{tex_only}) {
+    print $tex_invoice;
+    exit 0;
+}
+
+
+my $invoice_date = strftime('%Y_%m_%d',localtime($last_date));
 my $invoice_dir = "invoice_$invoice_date";
 
 if (not -d $invoice_dir) {
@@ -262,21 +337,49 @@ if ($options{svn}) {
            "invoice_${invoice_date}.tex",
           ) == 0 or die "Unable to add log and invoice to svn";
      system('svn','propset','svn:ignore',
-           "*.aux\n*.log\n*.dvi\n*.ps\n*.pdf\n",
+           "*.aux\n*.log\n*.dvi\n*.ps\n*.pdf\nauto\n",
            '.'
           ) == 0 or die "Unable to set svn:ignore";
 }
 
 
 sub format_events{
-     my ($date,$date2,$time,@events) = @_;
-     my $output = '        \Fee{'.strftime('%A, %B %e, %H:%M',localtime(UnixDate($date,'%s'))).
-         ' to '.strftime('%H:%M %Z',localtime(UnixDate($date2,'%s')))."\n".
-         '         \begin{itemize*}'."\n";
-     $output .= join('',map {"           \\item $_\n"} @events);
-     $output .= '         \end{itemize*}}{50.00}{'.$time.'}'."\n";
+     my %param = validate_with(params => \@_,
+                              spec   => {time => {type => SCALAR,
+                                                 },
+                                         date => {type => SCALAR,
+                                                 },
+                                         date2 => {type => SCALAR,
+                                                  },
+                                         total => {type => SCALARREF,
+                                                  },
+                                         events => {type => ARRAYREF,
+                                                   },
+                                        },
+                             );
+     ${$param{total}} += $param{time} * $options{hourly_fee};
+
+#     $param{date} =~ s/\s+\d+\:\d+\:\d+\s+[A-Z]{0,3}\s*//;
+     my $output = '\hline'."\n".'        \mbox{'.strftime('%A, %B %e, %H:%M',localtime($param{date})).
+         ' to '.strftime('%H:%M %Z',localtime($param{date2}))."}\n\n".
+        '         \begin{itemize*}'."\n";
+     $output .= join('',map { s/_/\\_/g; "           \\item $_\n";} @{$param{events}});
+     $output .= '         \end{itemize*} & \$'.sprintf('%.2f',$options{hourly_fee}).' & '.sprintf('%.2f',$param{time}).
+        ' & \$'.sprintf('%.2f',$param{time}*$options{hourly_fee}).' & \$'.
+            sprintf('%.2f',${$param{total}}) .
+                " \\\\\n";
      return $output;
 }
 
+## sub format_events{
+##      my ($date,$date2,$time,@events) = @_;
+##      my $output = '        \Fee{'.strftime('%A, %B %e, %H:%M',localtime(UnixDate($date,'%s'))).
+##       ' to '.strftime('%H:%M %Z',localtime(UnixDate($date2,'%s')))."\n".
+##       '         \begin{itemize*}'."\n";
+##      $output .= join('',map {"           \\item $_\n"} @events);
+##      $output .= '         \end{itemize*}}{50.00}{'.$time.'}'."\n";
+##      return $output;
+## }
+
 
 __END__