Merge branch 'FREESIDE_2_3_BRANCH' of git.freeside.biz:/home/git/freeside into FREESI...
authorIvan Kohler <ivan@freeside.biz>
Sat, 1 Jun 2013 09:24:02 +0000 (02:24 -0700)
committerIvan Kohler <ivan@freeside.biz>
Sat, 1 Jun 2013 09:24:02 +0000 (02:24 -0700)
FS/FS/part_event/Condition/inactive_age.pm
rt/lib/RT/Interface/Web_Vendor.pm
rt/share/html/Elements/ColumnMap
rt/share/html/Elements/RT__Ticket/ColumnMap
rt/share/html/Search/Elements/ResultsStructuredView

index 8918a1a..cbf4b9e 100644 (file)
@@ -11,6 +11,10 @@ sub option_fields {
     'age'  =>  { 'label'   => 'No activity within',
                  'type'    => 'freq',
                },
+    'ignore_pkgclass' =>
+               { 'label' => 'Except charges of class',
+                 'type'  => 'select-pkg_class',
+               },
     # flags to select kinds of activity, 
     # like if you just want "no payments since"?
     # not relevant yet
@@ -22,23 +26,51 @@ sub condition {
   my $custnum = $obj->custnum;
   my $age = $self->option_age_from('age', $opt{'time'} );
 
-  foreach my $t (qw(cust_bill cust_pay cust_credit cust_refund)) {
+  my $ignore_pkgclass = $self->option('ignore_pkgclass');
+
+  my $where = "custnum = $custnum AND _date >= $age";
+
+  foreach my $t (qw(cust_pay cust_credit cust_refund)) {
     my $class = "FS::$t";
-    return 0 if $class->count("custnum = $custnum AND _date >= $age");
+    return 0 if $class->count($where);
   }
+
+  # cust_bill: handle the ignore_pkgclass option
+  if ( $ignore_pkgclass =~ /^\d+$/ ) {
+    $where .= " AND EXISTS( ".
+      "SELECT 1 FROM cust_bill_pkg JOIN cust_pkg USING (pkgnum) " .
+      "JOIN part_pkg USING (pkgpart) " .
+      "WHERE cust_bill_pkg.invnum = cust_bill.invnum " .
+      "AND COALESCE(part_pkg.classnum, -1) != $ignore_pkgclass" .
+      " )";
+  }
+  #warn "$where\n";
+  return 0 if FS::cust_bill->count($where);
+
   1;
 }
 
 sub condition_sql {
   my( $class, $table, %opt ) = @_;
   my $age   = $class->condition_sql_option_age_from('age', $opt{'time'});
+  my $ignore_pkgclass = $class->condition_sql_option_integer('ignore_pkgclass');
+  # will evaluate to zero if there isn't one
   my @sql;
-  for my $t (qw(cust_bill cust_pay cust_credit cust_refund)) {
+  for my $t (qw(cust_pay cust_credit cust_refund)) {
     push @sql,
       "NOT EXISTS( SELECT 1 FROM $t ".
       "WHERE $t.custnum = cust_main.custnum AND $t._date >= $age".
       ")";
   }
+  #cust_bill
+  push @sql,
+    "NOT EXISTS( ".
+    "SELECT 1 FROM cust_bill JOIN cust_bill_pkg USING (invnum) ".
+    "JOIN cust_pkg USING (pkgnum) JOIN part_pkg USING (pkgpart) ".
+    "WHERE cust_bill.custnum = cust_main.custnum ".
+    "AND cust_bill._date >= $age ".
+    "AND COALESCE(part_pkg.classnum, -1) != $ignore_pkgclass ".
+    ")";
   join(' AND ', @sql);
 }
 
index ee8c34b..6218641 100644 (file)
@@ -533,5 +533,32 @@ sub ProcessUpdateMessage {
     return @results;
 }
 
+sub default_FormatDate { $_[0]->AsString }
+
+sub ProcessColumnMapValue {
+    my $value = shift;
+    my %args = ( Arguments => [],
+                 Escape => 1,
+                 FormatDate => \&default_FormatDate,
+                 @_ );
+
+    if ( ref $value ) {
+        if ( ref $value eq 'RT::Date' ) {
+            return $args{FormatDate}->($value);
+        } elsif ( UNIVERSAL::isa( $value, 'CODE' ) ) {
+            my @tmp = $value->( @{ $args{'Arguments'} } );
+            return ProcessColumnMapValue( ( @tmp > 1 ? \@tmp : $tmp[0] ), %args );
+        } elsif ( UNIVERSAL::isa( $value, 'ARRAY' ) ) {
+            return join '', map ProcessColumnMapValue( $_, %args ), @$value;
+        } elsif ( UNIVERSAL::isa( $value, 'SCALAR' ) ) {
+            return $$value;
+        }
+    }
+
+    return $m->interp->apply_escapes( $value, 'h' ) if $args{'Escape'};
+    return $value;
+}
+
+
 1;
 
index 2d226da..c81dbb8 100644 (file)
@@ -64,8 +64,7 @@ my $COLUMN_MAP = {
     Created => {
         attribute => 'Created',
         title     => 'Created', # loc
-        date      => sub { return $_[0]->CreatedObj },
-        value     => sub { return $_[0]->CreatedObj->AsString }
+        value     => sub { return $_[0]->CreatedObj },
     },
     CreatedRelative => {
         attribute => 'Created',
@@ -80,8 +79,7 @@ my $COLUMN_MAP = {
     LastUpdated => {
         attribute => 'LastUpdated',
         title     => 'Last Updated', # loc
-        date      => sub { return $_[0]->LastUpdatedObj },
-        value     => sub { return $_[0]->LastUpdatedObj->AsString }
+        value     => sub { return $_[0]->LastUpdatedObj },
     },
     LastUpdatedRelative => {
         attribute => 'LastUpdated',
@@ -101,15 +99,31 @@ my $COLUMN_MAP = {
             # Display custom field contents, separated by newlines.
             # For Image custom fields we also show a thumbnail here.
 
-            my $values = $_[0]->CustomFieldValues( $_[-1] );
-            my @values = map {
-                (
-                    ($_->CustomFieldObj->Type eq 'Image')
-                        ? \($m->scomp( '/Elements/ShowCustomFieldImage', Object => $_ ))
-                        : $_->Content
-                ),
-                \'<br />',
-            } @{ $values->ItemsArrayRef };
+            my $object = shift;
+            my $cfname = pop;
+            my $values = $object->CustomFieldValues( $cfname );
+            return if $values->Count == 0;
+            my @values;
+            # it is guaranteed to be the same type for all fields, right?
+            my $v = $values->First;
+            my $cftype = $v->CustomFieldObj->Type;
+
+            do {
+                if ($cftype eq 'Image') {
+                    push @values, 
+                        \($m->scomp( '/Elements/ShowCustomFieldImage',
+                                      Object => $v ));
+                } elsif ( $cftype eq 'Date' or $cftype eq 'DateTime' ) {
+                    # then actually return the date object;
+                    # ProcessColumnMapValue will stringify it
+                    my $DateObj = RT::Date->new( $session{'CurrentUser'} );
+                    $DateObj->Set(Format => 'unknown', Value => $v->Content);
+                    push @values, $DateObj;
+                } else {
+                    push @values, $v->Content;
+                }
+                push @values, \'<br />'; # this is deeply silly
+            } while ($v = $values->Next);
             pop @values; # Remove that last <br />
             return @values;
         },
index 9e6466c..9cceaf6 100644 (file)
@@ -220,32 +220,27 @@ $COLUMN_MAP = {
     Starts => {
         title     => 'Starts', # loc
         attribute => 'Starts',
-        date      => sub { return $_[0]->StartsObj },
-        value     => sub { return $_[0]->StartsObj->AsString }
+        value     => sub { return $_[0]->StartsObj }
     },
     Started => {
         title     => 'Started', # loc
         attribute => 'Started',
-        date      => sub { return $_[0]->StartedObj },
-        value     => sub { return $_[0]->StartedObj->AsString }
+        value     => sub { return $_[0]->StartedObj },
     },
     Told => {
         title     => 'Told', # loc
         attribute => 'Told',
-        date      => sub { return $_[0]->ToldObj },
-        value     => sub { return $_[0]->ToldObj->AsString }
+        value     => sub { return $_[0]->ToldObj },
     },
     Due => {
         title     => 'Due', # loc
         attribute => 'Due',
-        date      => sub { return $_[0]->DueObj },
-        value     => sub { return $_[0]->DueObj->AsString }
+        value     => sub { return $_[0]->DueObj },
     },
     Resolved => {
         title     => 'Resolved', # loc
         attribute => 'Resolved',
-        date      => sub { return $_[0]->ResolvedObj },
-        value     => sub { return $_[0]->ResolvedObj->AsString }
+        value     => sub { return $_[0]->ResolvedObj }
     },
     UpdateStatus => {
         title => 'New messages', # loc
index 495f0d0..0e9457c 100644 (file)
@@ -132,7 +132,7 @@ while ( my $Ticket = $Tickets->Next()) {
 
             if ( !exists $ColumnMap->{$col}{'value'} ) {
                 my $map = {};
-                foreach ('attribute', 'value', 'date') {
+                foreach ('attribute', 'value') {
                     $map->{$_} = $m->comp(
                         '/Elements/ColumnMap',
                         Class => 'RT__Ticket',
@@ -140,19 +140,13 @@ while ( my $Ticket = $Tickets->Next()) {
                         Attr  => $_,
                     );
                 }
-                # Canonicalize dates
-                if ( defined $map->{'date'} ) {
-                    $map->{value} = sub { 
-                        my $DateObj = $map->{'date'}->(@_) or return undef;
-                        $FormatDate->($DateObj);
-                    };
-                }
                 $ColumnMap->{$col} = $map;
             }
 
             push @out, ProcessColumnMapValue(
                 $ColumnMap->{$col}{'value'},
                 Arguments => [ $Ticket, $row ],
+                FormatDate => $FormatDate,
             );
         } #foreach $subcol
         $value = join('', '<span>', @out, '</span>');