-my @select = 'contact.contactnum AS contact_contactnum'; #if we select it as bare contactnum, the multi-customer listings go away
-push @select, map "contact.$_", qw( first last title );
-my %hash = ();
-my $addl_from = '';
-
-my $link; #for closure in this sub, we'll define it later
-my $contact_classname_sub = sub {
- my $contact = shift;
- my %hash = ( 'contactnum' => $contact->contact_contactnum );
- my $X_contact;
- if ( $link eq 'cust_main' ) {
- $X_contact = qsearchs('cust_contact', { %hash, 'custnum' => $contact->custnum } );
- } elsif ( $link eq 'prospect_main' ) {
- $X_contact = qsearchs('prospect_contact', { %hash, 'prospectnum' => $contact->prospectnum } );
- } else {
- die 'guru meditation #5555';
+my $DEBUG = 0;
+
+# Catch classnum values from multi-select box
+# A classnum of 0 indicates to include rows where classnum IS NULL
+$CGI::LIST_CONTEXT_WARN = 0;
+my @classnum = grep{ /^\d+$/ && $_ > 0 } $cgi->param('classnum');
+my $classnum_null = grep{ $_ eq 0 } $cgi->param('classnum');
+
+# Catch destination values from dest multi-checkbox, default to message
+# irrelevant to prospect contacts
+my @dest = grep{ /^(message|invoice)$/ } $cgi->param('dest');
+
+# Cache the contact_class table
+my %classname =
+ map {$_->classnum => $_->classname}
+ qsearch(contact_class => {disabled => ''});
+
+# This data structure is used to generate the sql query parameters
+my %colmap = (
+ # These are included regardless of which tables we're viewing
+ common => {
+ cols => {
+ contact => [qw/first last title contactnum/],
+ contact_email => [qw/emailaddress/],
+ },
+ joinsql => "",
+ },
+
+ # These are included if we're viewing customer records
+ cust_main => {
+ cols => {
+ cust_main => [qw/first last company/],
+ cust_contact => [qw/
+ custnum classnum invoice_dest message_dest selfservice_access comment
+ /],
+ },
+ joinsql => "
+ LEFT JOIN cust_contact
+ ON (cust_main.custnum = cust_contact.custnum)
+ LEFT JOIN contact
+ on (cust_contact.contactnum = contact.contactnum)
+ LEFT JOIN contact_email
+ ON (cust_contact.contactnum = contact_email.contactnum)
+ ",
+ },
+
+ # These are included if we're viewing prospect records
+ prospect_main => {
+ cols => {
+ prospect_main => [qw/company/],
+ prospect_contact => [qw/prospectnum classnum comment/],
+ },
+ joinsql => "
+ LEFT JOIN prospect_contact
+ ON (prospect_main.prospectnum = prospect_contact.prospectnum)
+ LEFT JOIN contact
+ on (prospect_contact.contactnum = contact.contactnum)
+ LEFT JOIN contact_email
+ ON (prospect_contact.contactnum = contact_email.contactnum)
+ ",
+ },
+);
+
+my @select;
+my $addl_from;
+my $extra_sql;
+my $hashref;
+my $link = $cgi->param('link'); # cust_main or prospect_main
+
+push @select,'agentnum';
+
+# this shouldn't happen without funny-busines
+die "Invalid \$link type ($link)"
+ unless $link eq 'cust_main' || $link eq 'prospect_main';
+
+# Build @select and $addl_from
+for my $key ('common', $link) {
+ $addl_from .= $colmap{$key}->{joinsql};
+ my $cols = $colmap{$key}->{cols};
+ for my $tbl (keys %{$cols}) {
+ push @select, map{ "$tbl.$_ AS ${tbl}_$_" } @{$cols->{$tbl}};