X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=rt%2Flib%2FRT%2FTickets_Overlay.pm;h=a341af2c465af85403d5f59809d64985d678b10b;hb=30ef568f955526b259892399ba7432dbfce46347;hp=5a7e020566adfa7f0a3b94e272f155e448e9cd65;hpb=09aa4ca78df448f73e440a25a024e44eaf00c827;p=freeside.git diff --git a/rt/lib/RT/Tickets_Overlay.pm b/rt/lib/RT/Tickets_Overlay.pm index 5a7e02056..a341af2c4 100644 --- a/rt/lib/RT/Tickets_Overlay.pm +++ b/rt/lib/RT/Tickets_Overlay.pm @@ -2,7 +2,7 @@ # # COPYRIGHT: # -# This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC +# This software is Copyright (c) 1996-2013 Best Practical Solutions, LLC # # # (Except where explicitly superseded by other copyright notices) @@ -145,9 +145,20 @@ our %FIELD_METADATA = ( WatcherGroup => [ 'MEMBERSHIPFIELD', ], #loc_left_pair HasAttribute => [ 'HASATTRIBUTE', 1 ], HasNoAttribute => [ 'HASATTRIBUTE', 0 ], - Agentnum => [ 'FREESIDEFIELD', ], - Classnum => [ 'FREESIDEFIELD', ], - Tagnum => [ 'FREESIDEFIELD', 'cust_tag' ], + #freeside + Customer => [ 'FREESIDEFIELD', ], +# Agentnum => [ 'FREESIDEFIELD', ], +# Classnum => [ 'FREESIDEFIELD', ], +# Refnum => [ 'FREESIDEFIELD', ], +# Tagnum => [ 'FREESIDEFIELD', 'cust_tag' ], + WillResolve => [ 'DATE' => 'WillResolve', ], #loc_left_pair +); + +our %SEARCHABLE_SUBFIELDS = ( + User => [qw( + EmailAddress Name RealName Nickname Organization Address1 Address2 + WorkPhone HomePhone MobilePhone PagerPhone id + )], ); # Mapping of Field Type to Function @@ -548,7 +559,7 @@ sub _DateFieldLimit { $date->SetToNow; $date->SetToStart('month', Timezone => 'server'); $daystart = $date->ISO; - $date->AddMonth; + $date->AddMonth(Timezone => 'server'); $dayend = $date->ISO; } elsif ( lc($value) eq 'last month' ) { @@ -837,6 +848,13 @@ sub _WatcherLimit { my $type = $meta->[1] || ''; my $class = $meta->[2] || 'Ticket'; + # Bail if the subfield is not allowed + if ( $rest{SUBKEY} + and not grep { $_ eq $rest{SUBKEY} } @{$SEARCHABLE_SUBFIELDS{'User'}}) + { + die "Invalid watcher subfield: '$rest{SUBKEY}'"; + } + # Owner was ENUM field, so "Owner = 'xxx'" allowed user to # search by id and Name at the same time, this is workaround # to preserve backward compatibility @@ -1051,6 +1069,12 @@ sub _GroupMembersJoin { FIELD2 => 'GroupId', ENTRYAGGREGATOR => 'AND', ); + $self->SUPER::Limit( + LEFTJOIN => $alias, + ALIAS => $alias, + FIELD => 'Disabled', + VALUE => 0, + ); $self->{'_sql_group_members_aliases'}{ $args{'GroupsAlias'} } = $alias unless $args{'New'}; @@ -1215,6 +1239,12 @@ sub _WatcherMembershipLimit { FIELD2 => 'id' ); + $self->Limit( + ALIAS => $groupmembers, + FIELD => 'Disabled', + VALUE => 0, + ); + $self->Join( ALIAS1 => $memberships, FIELD1 => 'MemberId', @@ -1222,6 +1252,13 @@ sub _WatcherMembershipLimit { FIELD2 => 'id' ); + $self->Limit( + ALIAS => $memberships, + FIELD => 'Disabled', + VALUE => 0, + ); + + $self->_CloseParen; } @@ -1235,7 +1272,7 @@ Try and turn a CF descriptor into (cfid, cfname) object pair. sub _CustomFieldDecipher { my ($self, $string) = @_; - my ($queue, $field, $column) = ($string =~ /^(?:(.+?)\.)?{(.+)}(?:\.(.+))?$/); + my ($queue, $field, $column) = ($string =~ /^(?:(.+?)\.)?{(.+)}(?:\.(Content|LargeContent))?$/); $field ||= ($string =~ /^{(.*?)}$/)[0] || $string; my $cf; @@ -1456,7 +1493,7 @@ sub _CustomFieldLimit { %rest ); } - elsif ( $cf->Type eq 'Date' ) { + elsif ( $cfid and $cf->Type eq 'Date' ) { $self->_DateFieldLimit( 'Content', $op, @@ -1767,42 +1804,43 @@ sub OrderByCols { foreach my $uid ( $self->CurrentUser->Id, $RT::Nobody->Id ) { if ( RT->Config->Get('DatabaseType') eq 'Oracle' ) { my $f = ($row->{'ALIAS'} || 'main') .'.Owner'; - push @res, { %$row, ALIAS => '', FIELD => "CASE WHEN $f=$uid THEN 1 ELSE 0 END", ORDER => $order } ; + push @res, { + %$row, + FIELD => undef, + ALIAS => '', + FUNCTION => "CASE WHEN $f=$uid THEN 1 ELSE 0 END", + ORDER => $order + }; } else { - push @res, { %$row, FIELD => "Owner=$uid", ORDER => $order } ; + push @res, { + %$row, + FIELD => undef, + FUNCTION => "Owner=$uid", + ORDER => $order + }; } } push @res, { %$row, FIELD => "Priority", ORDER => $order } ; } elsif ( $field eq 'Customer' ) { #Freeside - if ( $subkey eq 'Number' ) { - my ($linkalias, $custnum_sql) = $self->JoinToCustLinks; - push @res, { %$row, - ALIAS => '', - FIELD => $custnum_sql, - }; + # OrderBy(FIELD => expression) doesn't work, it has to be + # an actual field, so we have to do the join even if sorting + # by custnum + my $custalias = $self->JoinToCustomer; + my $cust_field = lc($subkey); + if ( !$cust_field or $cust_field eq 'number' ) { + $cust_field = 'custnum'; } - else { - my $custalias = $self->JoinToCustomer; - my $field; - if ( $subkey eq 'Name' ) { - $field = "COALESCE( $custalias.company, - $custalias.last || ', ' || $custalias.first - )"; - } - elsif ( $subkey eq 'Class' ) { - $field = "$custalias.classnum"; - } - elsif ( $subkey eq 'Agent' ) { - $field = "$custalias.agentnum"; - } - else { - # no other cases exist yet, but for obviousness: - $field = $subkey; - } - push @res, { %$row, ALIAS => '', FIELD => $field }; + elsif ( $cust_field eq 'name' ) { + $cust_field = "COALESCE( $custalias.company, + $custalias.last || ', ' || $custalias.first + )"; } + else { # order by cust_main fields directly: 'Customer.agentnum' + $cust_field = $subkey; + } + push @res, { %$row, ALIAS => $custalias, FIELD => $cust_field }; } #Freeside @@ -1822,26 +1860,36 @@ sub JoinToCustLinks { # Return the linkalias for further join/limit action, # and an sql expression to retrieve the custnum. my $self = shift; - my $linkalias = $self->Join( - TYPE => 'LEFT', - ALIAS1 => 'main', - FIELD1 => 'id', - TABLE2 => 'Links', - FIELD2 => 'LocalBase', - ); - - $self->SUPER::Limit( - LEFTJOIN => $linkalias, - FIELD => 'Type', - OPERATOR => '=', - VALUE => 'MemberOf', - ); - $self->SUPER::Limit( - LEFTJOIN => $linkalias, - FIELD => 'Target', - OPERATOR => 'STARTSWITH', - VALUE => 'freeside://freeside/cust_main/', - ); + # only join once for each RT::Tickets object + my $linkalias = $self->{cust_linkalias}; + if (!$linkalias) { + $linkalias = $self->Join( + TYPE => 'LEFT', + ALIAS1 => 'main', + FIELD1 => 'id', + TABLE2 => 'Links', + FIELD2 => 'LocalBase', + ); + $self->SUPER::Limit( + LEFTJOIN => $linkalias, + FIELD => 'Base', + OPERATOR => 'LIKE', + VALUE => 'fsck.com-rt://%/ticket/%', + ); + $self->SUPER::Limit( + LEFTJOIN => $linkalias, + FIELD => 'Type', + OPERATOR => '=', + VALUE => 'MemberOf', + ); + $self->SUPER::Limit( + LEFTJOIN => $linkalias, + FIELD => 'Target', + OPERATOR => 'STARTSWITH', + VALUE => 'freeside://freeside/cust_main/', + ); + $self->{cust_linkalias} = $linkalias; + } my $custnum_sql = "CAST(SUBSTR($linkalias.Target,31) AS "; if ( RT->Config->Get('DatabaseType') eq 'mysql' ) { $custnum_sql .= 'SIGNED INTEGER)'; @@ -1855,7 +1903,8 @@ sub JoinToCustLinks { sub JoinToCustomer { my $self = shift; my ($linkalias, $custnum_sql) = $self->JoinToCustLinks; - + # don't reuse this join, though--negative queries need + # independent joins my $custalias = $self->Join( TYPE => 'LEFT', EXPRESSION => $custnum_sql, @@ -1877,20 +1926,29 @@ sub _FreesideFieldLimit { $op = '=' if $op eq '!='; $op =~ s/\bNOT\b//; } - my $meta = $FIELD_METADATA{$field}; - if ( $meta->[1] ) { + + my $cust_field = $rest{SUBKEY} || 'custnum'; + my $table2; + # compound subkey: separate into table name and field in that table + # (must be linked by custnum) + ($table2, $cust_field) = ($1, $2) if $cust_field =~ /^(\w+)?\.(\w+)$/; + + $cust_field = lc($cust_field); + $cust_field = 'custnum' if !$cust_field or $cust_field eq 'number'; + + if ( $table2 ) { $alias = $self->Join( TYPE => 'LEFT', ALIAS1 => $alias, FIELD1 => 'custnum', - TABLE2 => $meta->[1], + TABLE2 => $table2, FIELD2 => 'custnum', ); } $self->SUPER::Limit( LEFTJOIN => $alias, - FIELD => lc($field), + FIELD => $cust_field, OPERATOR => $op, VALUE => $value, ENTRYAGGREGATOR => 'AND', @@ -1898,7 +1956,7 @@ sub _FreesideFieldLimit { $self->_SQLLimit( %rest, ALIAS => $alias, - FIELD => lc($field), + FIELD => 'custnum', OPERATOR => $is_negative ? 'IS' : 'IS NOT', VALUE => 'NULL', QUOTEVALUE => 0, @@ -3300,9 +3358,9 @@ is a description of the purpose of that TicketRestriction sub DescribeRestrictions { my $self = shift; - my ( $row, %listing ); + my %listing; - foreach $row ( keys %{ $self->{'TicketRestrictions'} } ) { + foreach my $row ( keys %{ $self->{'TicketRestrictions'} } ) { $listing{$row} = $self->{'TicketRestrictions'}{$row}{'DESCRIPTION'}; } return (%listing); @@ -3377,9 +3435,8 @@ sub DeleteRestriction { sub _RestrictionsToClauses { my $self = shift; - my $row; my %clause; - foreach $row ( keys %{ $self->{'TicketRestrictions'} } ) { + foreach my $row ( keys %{ $self->{'TicketRestrictions'} } ) { my $restriction = $self->{'TicketRestrictions'}{$row}; # We need to reimplement the subclause aggregation that SearchBuilder does.