diff options
author | Mark Wells <mark@freeside.biz> | 2012-04-17 15:52:14 -0700 |
---|---|---|
committer | Mark Wells <mark@freeside.biz> | 2012-04-17 15:52:14 -0700 |
commit | 1c59bba12621e154765a8255534e94a041dfd200 (patch) | |
tree | 5f9acae2881b035e9e3b9a21d8bc6bab1f4b2a73 /FS | |
parent | 71cbdde5012550846390e9f0ebafdb48e06da5e8 (diff) |
link tickets to services, #17067
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/TicketSystem/RT_External.pm | 51 | ||||
-rw-r--r-- | FS/FS/TicketSystem/RT_Internal.pm | 63 | ||||
-rw-r--r-- | FS/FS/cust_svc.pm | 86 | ||||
-rw-r--r-- | FS/FS/svc_phone.pm | 3 |
4 files changed, 182 insertions, 21 deletions
diff --git a/FS/FS/TicketSystem/RT_External.pm b/FS/FS/TicketSystem/RT_External.pm index f976ac0..22d2472 100644 --- a/FS/FS/TicketSystem/RT_External.pm +++ b/FS/FS/TicketSystem/RT_External.pm @@ -97,6 +97,11 @@ sub customer_tickets { } +sub service_tickets { + warn "service_tickets not available with RT_External.\n"; + return; +} + sub comments_on_tickets { my ($self, $custnum, $limit, $time ) = @_; $limit ||= 0; @@ -206,7 +211,20 @@ sub statuses { } sub href_customer_tickets { - my( $self, $custnum ) = ( shift, shift ); + my($self, $custnum) = (shift, shift); + if ( $custnum =~ /^(\d+)$/ ) { + return $self->href_search_tickets("MemberOf = 'freeside://freeside/cust_main/$1'"); + } + warn "bad custnum $custnum"; return ''; +} + +sub href_service_tickets { + warn "service_tickets not available with RT_External.\n"; + ''; +} + +sub href_search_tickets { + my( $self, $where ) = ( shift, shift ); my( $priority, @statuses); if ( ref($_[0]) ) { my $opt = shift; @@ -225,8 +243,8 @@ sub href_customer_tickets { #$href .= my $href = "Search/Results.html?Order=ASC&". - "Query= MemberOf = 'freeside://freeside/cust_main/$custnum' ". - #" AND ( Status = 'open' OR Status = 'new' OR Status = 'stalled' )" + "Query= $where" . + #MemberOf = 'freeside://freeside/cust_main/$custnum' ". " AND ( ". join(' OR ', map "Status = '$_'", @statuses ). " ) " ; @@ -274,15 +292,19 @@ sub href_customer_tickets { } sub href_params_new_ticket { - my( $self, $custnum_or_cust_main, $requestors ) = @_; - - my( $custnum, $cust_main ); - if ( ref($custnum_or_cust_main) ) { - $cust_main = $custnum_or_cust_main; - $custnum = $cust_main->custnum; - } else { - $custnum = $custnum_or_cust_main; - $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); + # my( $self, $custnum_or_cust_main, $requestors ) = @_; + # no longer takes $custnum--it must be an object + my ( $self, $object, $requestors ) = @_; + my $cust_main; # for default requestors + if ( $object->isa('FS::cust_main') ) { + $cust_main = $object; + } + elsif ( $object->isa('FS::svc_Common') ) { + $object = $object->cust_svc; + $cust_main = $object->cust_pkg->cust_main if ( $object->cust_pkg ); + } + elsif ( $object->isa('FS::cust_svc') ) { + $cust_main = $object->cust_pkg->cust_main if ( $object->cust_pkg ); } # explicit $requestors > config option > invoicing_list @@ -291,9 +313,12 @@ sub href_params_new_ticket { $requestors = $cust_main->invoicing_list_emailonly_scalar if (!$requestors) and defined($cust_main); + my $subtype = $object->table; + my $pkey = $object->get($object->primary_key); + my %param = ( 'Queue' => ($cust_main->agent->ticketing_queueid || $default_queueid), - 'new-MemberOf'=> "freeside://freeside/cust_main/$custnum", + 'new-MemberOf'=> "freeside://freeside/$subtype/$pkey", 'Requestors' => $requestors, ); diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm index d96e5f0..ffa8c7c 100644 --- a/FS/FS/TicketSystem/RT_Internal.pm +++ b/FS/FS/TicketSystem/RT_Internal.pm @@ -107,10 +107,13 @@ properly. =cut -sub _customer_tickets_search { - my ( $self, $custnum, $limit, $priority ) = @_; +# create an RT::Tickets object for a specified custnum or svcnum - $custnum =~ /^\d+$/ or die "invalid custnum: $custnum"; +sub _tickets_search { + my ( $self, $type, $number, $limit, $priority ) = @_; + + $type =~ /^Customer|Service$/ or die "invalid type: $type"; + $number =~ /^\d+$/ or die "invalid custnum/svcnum: $number"; $limit =~ /^\d+$/ or die "invalid limit: $limit"; my $session = $self->session(); @@ -119,7 +122,8 @@ sub _customer_tickets_search { my $Tickets = RT::Tickets->new($CurrentUser); - my $rtql = "MemberOf = 'freeside://freeside/cust_main/$custnum'"; + # "Customer.number" searches tickets linked via cust_svc also + my $rtql = "$type.number = $number"; if ( defined( $priority ) ) { my $custom_priority = FS::Conf->new->config('ticket_system-custom_priority_field'); @@ -144,8 +148,25 @@ sub _customer_tickets_search { return $Tickets; } +sub href_customer_tickets { + my ($self, $custnum) = (shift, shift); + if ($custnum =~ /^(\d+)$/) { + return $self->href_search_tickets("Customer.number = $custnum"); + } + warn "bad custnum $custnum"; ''; +} + +sub href_service_tickets { + my ($self, $svcnum) = (shift, shift); + if ($svcnum =~ /^(\d+)$/ ) { + return $self->href_search_tickets("Service.number = $svcnum"); + } + warn "bad svcnum $svcnum"; ''; +} + sub customer_tickets { - my $Tickets = _customer_tickets_search(@_); + my $self = shift; + my $Tickets = $self->_tickets_search('Customer', @_); my $conf = FS::Conf->new; my $priority_order = @@ -168,8 +189,30 @@ sub customer_tickets { sub num_customer_tickets { my ( $self, $custnum, $priority ) = @_; - my $Tickets = $self->_customer_tickets_search($custnum, 0, $priority); - return $Tickets->CountAll; + $self->_tickets_search('Customer', $custnum, 0, $priority)->CountAll; +} + +sub service_tickets { + my $self = shift; + my $Tickets = $self->_tickets_search('Service', @_); + + my $conf = FS::Conf->new; + my $priority_order = + $conf->exists('ticket_system-priority_reverse') ? 'ASC' : 'DESC'; + + my @order_by = ( + { FIELD => 'Priority', ORDER => $priority_order }, + { FIELD => 'Id', ORDER => 'DESC' }, + ); + + $Tickets->OrderByCols(@order_by); + + my @tickets; + while ( my $t = $Tickets->Next ) { + push @tickets, _ticket_info($t); + } + + return \@tickets; } sub _ticket_info { @@ -200,6 +243,12 @@ sub _ticket_info { if ( $ss_priority ) { $ticket_info{'_selfservice_priority'} = $ticket_info{"CF.{$ss_priority}"}; } + my $svcnums = [ + map { $_->Target =~ /cust_svc\/(\d+)/; $1 } + @{ $t->Services->ItemsArrayRef } + ]; + $ticket_info{'svcnums'} = $svcnums; + return \%ticket_info; } diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index fc6e605..a527913 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -756,8 +756,94 @@ sub get_session_history { } +=item tickets + +Returns an array of hashes representing the tickets linked to this service. + +=cut + +sub tickets { + my $self = shift; + + my $conf = FS::Conf->new; + my $num = $conf->config('cust_main-max_tickets') || 10; + my @tickets = (); + + if ( $conf->config('ticket_system') ) { + unless ( $conf->config('ticket_system-custom_priority_field') ) { + + @tickets = @{ FS::TicketSystem->service_tickets($self->svcnum, $num) }; + + } else { + + foreach my $priority ( + $conf->config('ticket_system-custom_priority_field-values'), '' + ) { + last if scalar(@tickets) >= $num; + push @tickets, + @{ FS::TicketSystem->service_tickets( $self->svcnum, + $num - scalar(@tickets), + $priority, + ) + }; + } + } + } + (@tickets); +} + + =back +=head1 SUBROUTINES + +=over 4 + +=item smart_search OPTION => VALUE ... + +Accepts the option I<search>, the string to search for. The string will +be searched for as a username, email address, IP address, MAC address, +phone number, and hardware serial number. Unlike the I<smart_search> on +customers, this always requires an exact match. + +=cut + +# though perhaps it should be fuzzy in some cases? +sub smart_search { + my %opt = @_; + # some false laziness w/ search/cust_svc.html + my $string = $opt{'search'}; + $string =~ s/(^\s+|\s+$)//; #trim leading & trailing whitespace + + my @extra_sql = ' ( '. join(' OR ', + map { my $table = $_; + my $search_sql = "FS::$table"->search_sql($string); + " ( svcdb = '$table' + AND 0 < ( SELECT COUNT(*) FROM $table + WHERE $table.svcnum = cust_svc.svcnum + AND $search_sql + ) + ) "; + } + FS::part_svc->svc_tables + ). ' ) '; + push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null_right' => 'View/link unlinked services' + ); + my $extra_sql = ' WHERE '.join(' AND ', @extra_sql); + #for agentnum + my $addl_from = ' LEFT JOIN cust_pkg USING ( pkgnum )'. + ' LEFT JOIN cust_main USING ( custnum )'. + ' LEFT JOIN part_svc USING ( svcpart )'; + + qsearch({ + 'table' => 'cust_svc', + 'addl_from' => $addl_from, + 'hashref' => {}, + 'extra_sql' => $extra_sql, + }); +} + =head1 BUGS Behaviour of changing the svcpart of cust_svc records is undefined and should diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index 118748e..b395ea6 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -218,13 +218,14 @@ Class method which returns an SQL fragment to search for the given string. sub search_sql { my( $class, $string ) = @_; + my $conf = new FS::Conf; + if ( $conf->exists('svc_phone-allow_alpha_phonenum') ) { $string =~ s/\W//g; } else { $string =~ s/\D//g; } - my $conf = new FS::Conf; my $ccode = ( $conf->exists('default_phone_countrycode') && $conf->config('default_phone_countrycode') ) |