'locale', 'varchar', 'NULL', 16, '', '',
'calling_list_exempt', 'char', 'NULL', 1, '', '',
'invoice_noemail', 'char', 'NULL', 1, '', '',
+ 'message_noemail', 'char', 'NULL', 1, '', '',
'bill_locationnum', 'int', 'NULL', '', '', '',
'ship_locationnum', 'int', 'NULL', '', '', '',
],
|| $self->ut_floatn('credit_limit')
|| $self->ut_numbern('billday')
|| $self->ut_numbern('prorate_day')
- || $self->ut_enum('edit_subject', [ '', 'Y' ] )
- || $self->ut_enum('calling_list_exempt', [ '', 'Y' ] )
- || $self->ut_enum('invoice_noemail', [ '', 'Y' ] )
+ || $self->ut_flag('edit_subject')
+ || $self->ut_flag('calling_list_exempt')
+ || $self->ut_flag('invoice_noemail')
+ || $self->ut_flag('message_noemail')
|| $self->ut_enum('locale', [ '', FS::Locales->locales ])
;
@tagnums = grep /^(\d+)$/, @tagnums;
if ( @tagnums ) {
+ if ( $params->{'all_tags'} ) {
+ foreach ( @tagnums ) {
+ push @where, 'exists(select 1 from cust_tag where '.
+ 'cust_tag.custnum = cust_main.custnum and tagnum = '.
+ $_ . ')';
+ }
+ } else { # matching any tag, not all
my $tags_where = "0 < (select count(1) from cust_tag where "
. " cust_tag.custnum = cust_main.custnum and tagnum in ("
. join(',', @tagnums) . "))";
push @where, $tags_where;
+ }
}
}
--- /dev/null
+package FS::part_event::Condition::message_email;
+use base qw( FS::part_event::Condition );
+use strict;
+
+sub description {
+ 'Customer allows email notices'
+}
+
+sub condition {
+ my( $self, $object ) = @_;
+ my $cust_main = $self->cust_main($object);
+
+ $cust_main->message_noemail ? 0 : 1;
+}
+
+sub condition_sql {
+ my( $self, $table ) = @_;
+
+ "cust_main.message_noemail IS NULL"
+}
+
+1;
<% $conf->exists('cust_main-require_invoicing_list_email', $agentnum)
? $r : '' %>Email address(es)
</TD>
- <TD WIDTH="408"><INPUT TYPE="text" NAME="invoicing_list" VALUE="<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) %>"></TD>
+ <TD WIDTH="408"><INPUT TYPE="text" NAME="invoicing_list" VALUE="<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) %>">
+ <INPUT TYPE="checkbox" NAME="message_noemail" VALUE="Y" <%
+ ( $cust_main->message_noemail eq 'Y' )
+ ? 'CHECKED'
+ : ''
+ %>> <% emt('Do not send notices') %>
+ </TD>
</TR>
% }
<TH CLASS="grid" BGCOLOR="#cccccc">Description</TH>
</TR>
-% foreach my $item ( sort { $a->history_date <=> $b->history_date
-% #|| table order
-% || $a->historynum <=> $b->historynum
-% }
-% @history
-% )
-% {
+% foreach my $item ( @history ) {
% my $history_other = '';
% my $act = $item->history_action;
% if ( $act =~ /^replace/ ) {
if $conf->exists('cust_pkg-display_times')
|| $curuser->option('cust_pkg-display_times');
+@history = sort { $a->history_date <=> $b->history_date
+ || $a->historynum <=> $b->historynum } @history;
+
+if ( $curuser->option('history_order') eq 'newest' ) {
+ @history = reverse @history;
+}
+
</%init>
if $curuser->access_right('Job queue');
$tools_menu{'Ticketing'} = [ \%tools_ticketing, 'Ticketing tools' ]
if $conf->config('ticket_system');
+$tools_menu{'Customer email settings'} = [ $fsurl.'misc/manage_cust_email.html' ]
+ if $curuser->access_right('Edit customer');
$tools_menu{'Business card scan'} = [ $fsurl.'edit/prospect_main-upload.html' ]
if $curuser->access_right('New prospect');
$tools_menu{'Time Queue'} = [ $fsurl.'search/report_timeworked.html', 'View pending support time' ]
--- /dev/null
+<& /elements/header.html, 'Manage customer email settings' &>
+<STYLE TYPE="text/css">
+.hidden { display: none }
+</STYLE>
+<& /elements/xmlhttp.html,
+ url => $p.'misc/xmlhttp-cust_main-email_search.html',
+ subs => ['email_search']
+&>
+<SCRIPT TYPE="text/javascript">
+
+function receive_search(result) {
+ var recs = JSON.parse(result);
+ var tbody = document.getElementById('tbody_results');
+ var j = tbody.rows.length;
+ for(var i = 0; i < j; i++) {
+ tbody.deleteRow(tbody.rows[i]);
+ }
+ if (recs.length > 0) {
+ for(var i = 0; i < recs.length; i++) {
+ var rec = recs[i];
+ var row = tbody.insertRow(i);
+ row.style.backgroundColor = (i % 2 ? '#eeeeee' : '#ffffff');
+
+ var cell = row.insertCell(0); // custnum
+ cell.appendChild( document.createTextNode(rec[0]) );
+ cell = row.insertCell(1); // customer name
+ cell.appendChild( document.createTextNode(rec[1]) );
+ cell = row.insertCell(2); // email
+ cell.appendChild( document.createTextNode(rec[2]) );
+
+ cell = row.insertCell(3); // invoice_email
+ var input = document.createElement('INPUT');
+ input.type = 'hidden';
+ input.name = 'custnum';
+ input.value = rec[0];
+ cell.appendChild(input);
+
+ input = document.createElement('INPUT');
+ input.type = 'checkbox';
+ input.name = 'custnum' + rec[0] + '_invoice_email';
+ input.value = 'Y';
+ input.checked = (rec[3] != 'Y');
+ cell.appendChild(input);
+ cell.style.textAlign = 'center';
+
+ cell = row.insertCell(4); // message_email
+ input = document.createElement('INPUT');
+ input.type = 'checkbox';
+ input.name = 'custnum' + rec[0] + '_message_email';
+ input.value = 'Y';
+ input.checked = (rec[4] != 'Y');
+ cell.appendChild(input);
+ cell.style.textAlign = 'center';
+ }
+ document.getElementById('div_found').style.display = '';
+ } else {
+ document.getElementById('div_notfound').style.display = '';
+ }
+}
+
+function start_search() {
+ document.getElementById('div_found').style.display = 'none';
+ document.getElementById('div_notfound').style.display = 'none';
+ var email = document.getElementById('input_email').value;
+ email_search(email, receive_search);
+}
+% if ( $cgi->param('search') ) {
+window.onload = start_search;
+% }
+</SCRIPT>
+<FORM ACTION="<%$p%>misc/process/manage_cust_email.html" METHOD="POST">
+<DIV>
+% if ( $cgi->param('done') ) {
+<P STYLE="font-weight: bold; color: #00ff00">Changes saved.</P>
+% } elsif ( $cgi->param('error') ) {
+<P STYLE="font-weight: bold; color: #ff0000"><% $cgi->param('error') |h %></P>
+% }
+ Email address:
+ <INPUT TYPE="text" ID="input_email" NAME="search"\
+ VALUE="<% $cgi->param('search') |h %>">
+ <INPUT TYPE="button" onclick="start_search()" VALUE="find">
+</DIV>
+<DIV ID="div_notfound" STYLE="display: none; padding: 1em">
+No matching email addresses found.
+</DIV>
+<DIV ID="div_found" STYLE="display: none">
+<TABLE CLASS="grid" STYLE="border-spacing: 0px">
+ <THEAD>
+ <TR STYLE="background-color: #dddddd">
+ <TH>#</TH>
+ <TH>Customer</TH>
+ <TH>Email</TH>
+ <TH>Send invoices</TH>
+ <TH>Send other notices</TH>
+ </TR>
+ </THEAD>
+ <TBODY ID="tbody_results"></TBODY>
+</TABLE>
+<INPUT TYPE="submit" VALUE="Save changes">
+</FORM>
+<& /elements/footer.html &>
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+
+</%init>
--- /dev/null
+<% $cgi->redirect($fsurl.'misc/manage_cust_email.html?' .
+ $cgi->query_string) %>
+<%init>
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+
+my $error;
+foreach my $custnum ($cgi->param('custnum')) {
+ my $cust = FS::cust_main->by_key($custnum)
+ or die "customer not found: $custnum\n";
+ my $new_invoice_noemail =
+ $cgi->param('custnum'.$custnum.'_invoice_email') ? '' : 'Y';
+ my $new_message_noemail =
+ $cgi->param('custnum'.$custnum.'_message_email') ? '' : 'Y';
+ if ( $new_invoice_noemail ne $cust->invoice_noemail
+ or $new_message_noemail ne $cust->message_noemail ) {
+
+ $cust->set('invoice_noemail', $new_invoice_noemail);
+ $cust->set('message_noemail', $new_message_noemail);
+ $error ||= $cust->replace;
+
+ }
+ $cgi->delete('custnum'.$custnum.'_invoice_email');
+ $cgi->delete('custnum'.$custnum.'_message_email');
+}
+$cgi->delete('custnum');
+if ( $error ) {
+ $cgi->param('error' => $error); # probably unnecessary...
+} else {
+ $cgi->param('done' => 1) unless $error;
+}
+</%init>
--- /dev/null
+<% JSON::to_json(\@result) %>\
+<%init>
+die 'access denied'
+ unless $FS::CurrentUser::CurrentUser->access_right('Edit customer');
+
+my $sub = $cgi->param('sub');
+my $email = $cgi->param('arg');
+my @where = (
+ "cust_main_invoice.dest != 'POST'",
+ "cust_main_invoice.dest LIKE ".dbh->quote('%'.$email.'%'),
+ $FS::CurrentUser::CurrentUser->agentnums_sql(table => 'cust_main'),
+);
+my @cust_main = qsearch({
+ 'table' => 'cust_main',
+ 'select' => 'cust_main.*, cust_main_invoice.dest',
+ 'addl_from' => 'JOIN cust_main_invoice USING (custnum)',
+ 'extra_sql' => 'WHERE '.join(' AND ', @where),
+});
+
+my @result = map {
+ [ $_->custnum,
+ $_->name,
+ $_->dest,
+ $_->invoice_noemail,
+ $_->message_noemail,
+ ]
+} @cust_main;
+
+</%init>
#XXX autogen
my @paramlist = qw( locale menu_position default_customer_view
+ history_order
spreadsheet_format mobile_menu
enable_fuzzy_on_exact
disable_html_editor disable_enter_submit_onetimecharge
</SELECT>
</TD>
</TR>
+
+% my $history_order = $curuser->option('history_order') || 'oldest';
+ <TR>
+ <TH ALIGN="right">Customer history sort order: </TH>
+ <TD COLSPAN=2>
+ <& /elements/select.html,
+ field => 'history_order',
+ curr_value => $history_order,
+ options => [ 'oldest', 'newest' ],
+ labels => { 'oldest' => 'Oldest first',
+ 'newest' => 'Newest first',
+ },
+ &>
+ </TD>
+ </TR>
<TR>
<TH ALIGN="right">Spreadsheet download format: </TH>
</TR>
<TR>
- <TH ALIGN="right" COLSPAN=1>Enable approximate customer searching even when an exact match is found: </TH>
+ <TH ALIGN="right" COLSPAN=1>Enable approximate customer searching <BR>even when an exact match is found: </TH>
<TD ALIGN="left" COLSPAN=2>
<INPUT TYPE="checkbox" NAME="enable_fuzzy_on_exact" VALUE="1" <% $curuser->option('enable_fuzzy_on_exact') ? 'CHECKED' : '' %>>
</TD>
custbatch usernum
cancelled_pkgs
cust_fields flattened_pkgs
+ all_tags
);
for my $param ( @scalars ) {
</TR>
% }
- <& /elements/tr-select-cust_tag.html,
- 'cgi' => $cgi,
- 'is_report' => 1,
- 'multiple' => 1,
- &>
+ <TR>
+ <TD ALIGN="right">Tags</TD>
+ <TD>
+ <& /elements/select-cust_tag.html,
+ 'cgi' => $cgi,
+ 'is_report' => 1,
+ 'multiple' => 1,
+ &>
+ <DIV STYLE="display:inline-block; vertical-align:baseline">
+ <INPUT TYPE="radio" NAME="all_tags" VALUE="0" CHECKED> Any of these
+ <BR>
+ <INPUT TYPE="radio" NAME="all_tags" VALUE="1"> All of these
+ </DIV>
+ </TD>
+ </TR>
<& /elements/tr-select-payby.html,
'payby_type' => 'cust',
<TD ALIGN="right"><% mt('Email address(es)') |h %></TD>
<TD BGCOLOR="#ffffff">
<% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || $no %>
+% if ( $cust_main->message_noemail ) {
+ <BR>
+ <SPAN STYLE="font-size: small"><% emt('(do not send notices)') %></SPAN>
+% }
</TD>
</TR>
% }
%my $old_history = 0;
%my $lastdate = 0;
%
-%foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) {
+%foreach my $item ( @history ) {
%
% $lastdate = $item->{'date'};
%
}
+# sort history
+if ( $curuser->option('history_order') eq 'newest' ) {
+ @history = sort { $b->{date} <=> $a->{date} } @history;
+} else {
+ @history = sort { $a->{date} <=> $b->{date} } @history;
+} # no other sort orders for now
+
sub translate_payby {
my ($payby,$payinfo) = (shift,shift);
my %payby = (