enable CardFortress in test database, #71513
[freeside.git] / FS / FS / usage_class.pm
index 93a32df..6c8a278 100644 (file)
@@ -3,6 +3,9 @@ package FS::usage_class;
 use strict;
 use vars qw( @ISA );
 use FS::Record qw( qsearch qsearchs );
+use FS::Conf;
+
+my $conf = new FS::Conf;
 
 @ISA = qw(FS::Record);
 
@@ -97,7 +100,9 @@ sub check {
 
   my $error = 
     $self->ut_numbern('classnum')
+    || $self->ut_numbern('weight')
     || $self->ut_text('classname')
+    || $self->ut_textn('format')
     || $self->ut_enum('disabled', [ '', 'Y' ])
   ;
   return $error if $error;
@@ -105,6 +110,340 @@ sub check {
   $self->SUPER::check;
 }
 
+=item summary_formats_labelhash
+
+Returns a list of line item format descriptions suitable for assigning to
+a hash. 
+
+=cut
+
+# transform hashes of arrays to arrays of hashes for false laziness removal?
+my %summary_formats = (
+  'simple' => { 
+    'label' => [ qw( Description Calls Minutes Amount ) ],
+    'fields' => [
+                  sub { shift->{description} },
+                  sub { shift->{calls} },
+                  sub { sprintf( '%.1f', shift->{duration}/60 ) },
+                  sub { my($href, %opt) = @_; 
+                        ($opt{dollar} || ''). $href->{amount};
+                      },
+                ],
+    'align'  => [ qw( l r r r ) ],
+    'span'   => [ qw( 4 1 1 1 ) ],            # unitprices?
+    'width'  => [ qw( 8.2cm 2.5cm 1.4cm 1.6cm ) ],   # don't like this
+    'show'   => 1,
+  },
+  'simpler' => { 
+    'label' =>  [ qw( Description Calls Amount ) ],
+    'fields' => [
+                  sub { shift->{description} },
+                  sub { shift->{calls} },
+                  sub { my($href, %opt) = @_; 
+                        ($opt{dollar} || ''). $href->{amount};
+                      },
+                ],
+    'align'  => [ qw( l r r ) ],
+    'span'   => [ qw( 5 1 1 ) ],
+    'width'  => [ qw( 10.7cm 1.4cm 1.6cm ) ],   # don't like this
+    'show'   => 1,
+  },
+  'usage_simple' => { 
+    'label' => [ qw( Date Time Number Destination Duration Amount ) ],
+    'fields' => [
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { my $href = shift;  #ugh! making bunk of 'normalization'
+                        $href->{subtotal} ? $href->{subtotal} : ' '
+                      },
+                ],
+    'align'  => [ qw( l l l l r r ) ],
+    'span'   => [ qw( 1 1 1 1 1 2 ) ],            # unitprices?
+    'width'  => [ qw( 4.3cm 1.4cm 2.5cm 2.5cm 1.4cm 1.6cm ) ],# don't like this
+    'show'   => 0,
+  },
+  'usage_6col' => { 
+    'label' => [ qw( col1 col2 col3 col4 col5 col6 ) ],
+    'fields' => [
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { my $href = shift;  #ugh! making bunk of 'normalization'
+                        $href->{subtotal} ? $href->{subtotal} : ' '
+                      },
+                ],
+    'align'  => [ qw( l l l l r r ) ],
+    'span'   => [ qw( 1 1 1 1 1 2 ) ],            # unitprices?
+    'width'  => [ qw( 4.3cm 1.4cm 2.5cm 2.5cm 1.4cm 1.6cm ) ],# don't like this
+    'show'   => 0,
+   },
+  'usage_4col' => { 
+    'label' => [ qw( col1 col2 col3 col4 ) ],
+    'fields' => [
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                ],
+    'align'  => [ qw( l l l l r r ) ],
+    'span'   => [ qw( 1 1 1 1 1 2 ) ],          
+    'width'  => [ qw( 4.3cm 1.4cm 2.5cm 2.5cm ) ],
+    'show'   => 0,
+  },
+  'usage_7col' => { 
+    'label' => [ qw( col1 col2 col3 col4 col5 col6 col7 ) ],
+    'fields' => [
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { ' ' },
+                  sub { my $href = shift;  #ugh! making bunk of 'normalization'
+                        $href->{subtotal} ? $href->{subtotal} : ' '
+                      },
+                ],
+    'align'  => [ qw( l l l l l r r ) ],
+    'span'   => [ qw( 1 1 1 1 1 1 1 ) ],            # unitprices?
+    'width'  => [ qw( 2.9cm 1.4cm 1.4cm 2.5cm 2.5cm 1.4cm 1.6cm ) ],# don't like this
+    'show'   => 0,
+  },
+);
+
+sub summary_formats_labelhash {
+  map { $_ => join(',', @{$summary_formats{$_}{label}}) }
+    grep { $summary_formats{$_}{show} }
+    keys %summary_formats;
+}
+
+=item header_generator FORMAT
+
+Returns a coderef used for generation of an invoice line item header for this
+usage_class. FORMAT is either html or latex
+
+=cut
+
+my %html_align = (
+  'c' => 'center',
+  'l' => 'left',
+  'r' => 'right',
+);
+
+sub _generator_defaults {
+  my ( $self, $format, %opt ) = @_;
+  my %format = ( %{ $summary_formats{$self->format} }, %opt );
+  return ( \%format, ' ', ' ', ' ', sub { shift } );
+}
+
+sub header_generator {
+  my ( $self, $format, %opt ) = @_;
+
+  my ( $f, $prefix, $suffix, $separator, $column ) =
+    $self->_generator_defaults($format, %opt);
+
+  if ($format eq 'latex') {
+    $prefix = "\\hline\n\\rule{0pt}{2.5ex}\n\\makebox[1.4cm]{}&\n";
+    $suffix = "\\\\\n\\hline";
+    $separator = "&\n";
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{\\textbf{$d}}}";
+          };
+  } elsif ( $format eq 'html' ) {
+    $prefix = '<th></th>';
+    $suffix = '';
+    $separator = '';
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return qq!<th align="$html_align{$a}">$d</th>!;
+      };
+  }
+
+  sub {
+    my @args = @_;
+    my @result = ();
+
+    foreach  (my $i = 0; exists($f->{label}->[$i]); $i++) {
+      push @result,
+        &{$column}( map { $f->{$_}->[$i] } qw(label align span width) );
+    }
+
+    $prefix. join($separator, @result). $suffix;  
+  };
+
+}
+
+=item description_generator FORMAT
+
+Returns a coderef used for generation of invoice line items for this
+usage_class.  FORMAT is either html or latex
+
+=cut
+
+sub description_generator {
+  my ( $self, $format, %opt ) = @_;
+
+  my ( $f, $prefix, $suffix, $separator, $column ) =
+    $self->_generator_defaults($format, %opt);
+
+  my $money_char = '$';
+  if ($format eq 'latex') {
+    $prefix = "\\hline\n\\multicolumn{1}{c}{\\rule{0pt}{2.5ex}~} &\n";
+    $suffix = '\\\\';
+    $separator = " & \n";
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{\\textbf{$d}}}";
+          };
+    $money_char = '\\dollar';
+  }elsif ( $format eq 'html' ) {
+    $prefix = '"><td align="center"></td>';
+    $suffix = '';
+    $separator = '';
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return qq!<td align="$html_align{$a}">$d</td>!;
+      };
+    $money_char = $conf->config('money_char') || '$';
+  }
+
+  sub {
+    #my @args = @_;
+    my ($href) = shift;
+    my @result = ();
+
+    foreach  (my $i = 0; $f->{label}->[$i]; $i++) {
+      my $dollar = '';
+      $dollar = $money_char if $i == scalar(@{$f->{label}})-1;
+      push @result,
+        &{$column}( &{$f->{fields}->[$i]}($href, 'dollar' => $dollar),
+                    map { $f->{$_}->[$i] } qw(align span width)
+                  );
+    }
+
+    $prefix. join( $separator, @result ). $suffix;
+  };
+
+}
+
+=item total_generator FORMAT
+
+Returns a coderef used for generation of invoice total lines for this
+usage_class.  FORMAT is either html or latex
+
+=cut
+
+sub total_generator {
+  my ( $self, $format, %opt ) = @_;
+
+#  $OUT .= '\FStotaldesc{' . $section->{'description'} . ' Total}' .
+#          '{' . $section->{'subtotal'} . '}' . "\n";
+
+  my ( $f, $prefix, $suffix, $separator, $column ) =
+    $self->_generator_defaults($format, %opt);
+  my $style = '';
+
+  if ($format eq 'latex') {
+    $prefix = "& ";
+    $suffix = "\\\\\n";
+    $separator = " & \n";
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{$d}}";
+          };
+  }elsif ( $format eq 'html' ) {
+    $prefix = '';
+    $suffix = '';
+    $separator = '';
+    $style = 'border-top: 3px solid #000000;border-bottom: 3px solid #000000;';
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return qq!<td align="$html_align{$a}" style="$style">$d</td>!;
+      };
+  }
+  
+
+  sub {
+    my @args = @_;
+    my @result = ();
+
+    #  my $r = &{$f->{fields}->[$i]}(@args);
+    #  $r .= ' Total' unless $i;
+
+    foreach  (my $i = 0; $f->{label}->[$i]; $i++) {
+      push @result,
+        &{$column}( &{$f->{fields}->[$i]}(@args). ($i ? '' : ' Total'),
+                    map { $f->{$_}->[$i] } qw(align span width)
+                  );
+    }
+
+    $prefix. join( $separator, @result ). $suffix;
+  };
+
+}
+
+=item total_line_generator FORMAT
+
+Returns a coderef used for generation of invoice total line items for this
+usage_class.  FORMAT is either html or latex
+
+=cut
+
+# not used: will have issues with hash element names (description vs
+# total_item and amount vs total_amount -- another array of functions?
+
+sub total_line_generator {
+  my ( $self, $format, %opt ) = @_;
+
+#     $OUT .= '\FStotaldesc{' . $line->{'total_item'} . '}' .
+#             '{' . $line->{'total_amount'} . '}' . "\n";
+
+  my ( $f, $prefix, $suffix, $separator, $column ) =
+    $self->_generator_defaults($format, %opt);
+  my $style = '';
+
+  if ($format eq 'latex') {
+    $prefix = "& ";
+    $suffix = "\\\\\n";
+    $separator = " & \n";
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return "\\multicolumn{$s}{$a}{\\makebox[$w][$a]{$d}}";
+          };
+  }elsif ( $format eq 'html' ) {
+    $prefix = '';
+    $suffix = '';
+    $separator = '';
+    $style = 'border-top: 3px solid #000000;border-bottom: 3px solid #000000;';
+    $column =
+      sub { my ($d,$a,$s,$w) = @_;
+            return qq!<td align="$html_align{$a}" style="$style">$d</td>!;
+      };
+  }
+  
+
+  sub {
+    my @args = @_;
+    my @result = ();
+
+    foreach  (my $i = 0; $f->{label}->[$i]; $i++) {
+      push @result,
+        &{$column}( &{$f->{fields}->[$i]}(@args),
+                    map { $f->{$_}->[$i] } qw(align span width)
+                  );
+    }
+
+    $prefix. join( $separator, @result ). $suffix;
+  };
+
+}
+
+# Used by FS::Setup to initialize a new database.
 sub _populate_initial_data {
   my ($class, %opts) = @_;
 
@@ -119,6 +458,7 @@ sub _populate_initial_data {
 
 }
 
+# Used by FS::Upgrade to migrate to a new database.
 sub _upgrade_data {
   my $class = shift;