summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2012-03-24 18:47:07 -0700
committerMark Wells <mark@freeside.biz>2012-03-26 23:33:18 -0700
commit0456422b9eaf771e8c27cfb4ef4a0dd7e6f926f8 (patch)
tree327059675499bfa2be0ccbfd8918b37a29312b5e
parented9e6fe7b0f2979ef94f6c399853533ffab8e0d2 (diff)
better display/edit of contacts on customer view, RT#16819
-rw-r--r--FS/FS/cust_main.pm1
-rw-r--r--httemplate/edit/cust_main-contacts.html100
-rw-r--r--httemplate/edit/process/cust_main-contacts.html20
-rw-r--r--httemplate/edit/process/elements/process.html96
-rw-r--r--httemplate/elements/freeside.css30
-rwxr-xr-xhttemplate/view/cust_main.cgi5
-rw-r--r--httemplate/view/cust_main/billing.html16
-rw-r--r--httemplate/view/cust_main/contacts.html119
-rw-r--r--httemplate/view/cust_main/contacts_new.html37
-rw-r--r--httemplate/view/cust_main/misc.html4
10 files changed, 310 insertions, 118 deletions
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 069d5b6aa..7d1a15621 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -8,6 +8,7 @@ use base qw( FS::cust_main::Packages FS::cust_main::Status
FS::cust_main::Billing_Discount
FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin
FS::geocode_Mixin
+ FS::o2m_Common
FS::Record
);
use vars qw( $DEBUG $me $conf
diff --git a/httemplate/edit/cust_main-contacts.html b/httemplate/edit/cust_main-contacts.html
new file mode 100644
index 000000000..bae58bd33
--- /dev/null
+++ b/httemplate/edit/cust_main-contacts.html
@@ -0,0 +1,100 @@
+<% include('elements/edit.html',
+ 'name_singular' => 'customer contacts', #yes, we're editing all of them
+ 'table' => 'cust_main',
+ 'post_url' => popurl(1). 'process/cust_main-contacts.html',
+ 'labels' => { 'custnum' => ' ', #XXX supress this line entirely, its being redundant
+ 'contactnum' => 'Contact',
+ #'locationnum' => '&nbsp;',
+ },
+ 'fields' => [
+ { 'field' => 'contactnum',
+ 'type' => 'contact',
+ 'colspan' => 6,
+ 'm2m_method' => 'cust_contact',
+ 'm2m_dstcol' => 'contactnum',
+ 'm2_label' => 'Contact',
+ 'm2_error_callback' => $m2_error_callback,
+ },
+ ],
+ #'new_callback' => $new_callback,
+ #'edit_callback' => $edit_callback,
+ #'error_callback' => $error_callback,
+ 'agent_virt' => 1,
+ 'menubar' => [], #remove "view all" link
+
+ #XXX it would be nice if this could instead be after the error but before
+ # the table
+ 'html_init' => include('/elements/small_custview.html',
+ $custnum,
+ $conf->config('countrydefault') || 'US',
+ 1, #no balance
+ ),
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+my $conf = new FS::Conf;
+
+my $custnum;
+if ( $cgi->param('error') ) {
+ $custnum = scalar($cgi->param('custnum'));
+
+ die "access denied"
+ unless $curuser->access_right(($custnum ? 'Edit' : 'New'). ' customer'); #contacts?
+
+} elsif ( $cgi->keywords ) { #editing
+ $custnum = ($cgi->keywords)[0];
+
+ die "access denied"
+ unless $curuser->access_right('Edit customer');
+
+} else { #new customer
+
+ #this doesn't really work here, we're an edit only
+ die "guru meditation #32";
+
+ die "access denied"
+ unless $curuser->access_right('New customer');
+
+}
+
+#my $new_callback = sub {
+# my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $edit_callback = sub {
+# my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+#my $error_callback = sub {
+# my( $cgi, $prospect_main, $fields_listref, $opt_hashref ) = @_;
+#};
+
+my $m2_error_callback = sub {
+ my($cgi, $object) = @_;
+
+ #process_o2m fields in process/cust_main-contacts.html
+ my @fields = qw( first last title comment );
+ my @gfields = ( '', map "_$_", @fields );
+
+ map {
+ if ( /^contactnum(\d+)$/ ) {
+ my $num = $1;
+ if ( grep $cgi->param("contactnum$num$_"), @gfields ) {
+ my $x = new FS::contact {
+ 'contactnum' => scalar($cgi->param("contactnum$num")),
+ map { $_ => scalar($cgi->param("contactnum${num}_$_")) } @fields,
+ };
+ $x;
+ } else {
+ ();
+ }
+ } else {
+ ();
+ }
+ }
+ $cgi->param;
+};
+
+</%init>
diff --git a/httemplate/edit/process/cust_main-contacts.html b/httemplate/edit/process/cust_main-contacts.html
new file mode 100644
index 000000000..ed874a55e
--- /dev/null
+++ b/httemplate/edit/process/cust_main-contacts.html
@@ -0,0 +1,20 @@
+<% include('elements/process.html',
+ 'table' => 'cust_main',
+ 'error_redirect' => popurl(3). 'edit/cust_main-contacts.html?',
+ 'agent_virt' => 1,
+ 'skip_process' => 1, #we don't want to make any changes to cust_main
+ 'process_o2m' => {
+ 'table' => 'contact',
+ 'fields' => \@contact_fields,
+ },
+ 'redirect' => popurl(3). 'view/cust_main.cgi?',
+ )
+%>
+<%init>
+
+my @contact_fields = qw( classnum first last title comment emailaddress );
+foreach my $phone_type ( qsearch({table=>'phone_type', order_by=>'weight'}) ) {
+ push @contact_fields, 'phonetypenum'.$phone_type->phonetypenum;
+}
+
+</%init>
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 636bae0ce..12b3bd94b 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -62,6 +62,10 @@ Example:
'fields' => [qw( fieldname fieldname2 )],
},
+ 'skip_process' => 0, #boolean, if set true, will skip the main table
+ #add/edit processing and only run any linked table
+ #process_ items
+
#checks CGI params and whatever else before much else runs
#return an error string or empty for no error
'precheck_callback' => sub { my( $cgi ) = @_; },
@@ -204,62 +208,71 @@ my $new;
my $new_pkey = '';
foreach my $value ( @values ) {
- $new = $class->new( \%hash );
+ if ($opt{'skip_process'}) {
+
+ $new = $old;
+ $new_pkey = $old_pkey;
+
+ } else {
+
+ $new = $class->new( \%hash );
- $new->$bfield($value) if $bfield;
+ $new->$bfield($value) if $bfield;
- if ($old && exists($opt{'copy_on_empty'})) {
- foreach my $field (@{$opt{'copy_on_empty'}}) {
- $new->set($field, $old->get($field))
- unless scalar($cgi->param($field));
+ if ($old && exists($opt{'copy_on_empty'})) {
+ foreach my $field (@{$opt{'copy_on_empty'}}) {
+ $new->set($field, $old->get($field))
+ unless scalar($cgi->param($field));
+ }
}
- }
- if ( $opt{'agent_virt'} ) {
+ if ( $opt{'agent_virt'} ) {
- if ( ! $new->agentnum
- && ( ! $opt{'agent_null_right'}
- || ! $curuser->access_right($opt{'agent_null_right'})
- )
- )
- {
+ if ( ! $new->agentnum
+ && ( ! $opt{'agent_null_right'}
+ || ! $curuser->access_right($opt{'agent_null_right'})
+ )
+ )
+ {
- $error ||= 'Select an agent';
+ $error ||= 'Select an agent';
- } else {
+ } else {
- die "illegal agentnum"
- unless $curuser->agentnums_href->{$new->agentnum}
- or $curuser->access_right('View customers of all agents')
- or $opt{'agent_null_right'}
- && ! $new->agentnum
- && $curuser->access_right($opt{'agent_null_right'});
+ die "illegal agentnum"
+ unless $curuser->agentnums_href->{$new->agentnum}
+ or $curuser->access_right('View customers of all agents')
+ or $opt{'agent_null_right'}
+ && ! $new->agentnum
+ && $curuser->access_right($opt{'agent_null_right'});
- }
+ }
- }
+ }
- $error ||= $new->check;
+ $error ||= $new->check;
- my @args = ();
- if ( !$error && $opt{'args_callback'} ) {
- @args = &{ $opt{'args_callback'} }( $cgi, $new );
- }
+ my @args = ();
+ if ( !$error && $opt{'args_callback'} ) {
+ @args = &{ $opt{'args_callback'} }( $cgi, $new );
+ }
- if ( !$error && $opt{'debug'} ) {
- warn "$me updating record in $table table using $class class\n";
- warn Dumper(\%hash);
- warn "with args: \n". Dumper(\@args) if @args;
- }
+ if ( !$error && $opt{'debug'} ) {
+ warn "$me updating record in $table table using $class class\n";
+ warn Dumper(\%hash);
+ warn "with args: \n". Dumper(\@args) if @args;
+ }
- if ( !$error ) {
- if ( $old_pkey ) {
- $error = $new->replace($old, @args);
- } else {
- $error = $new->insert(@args);
+ if ( !$error ) {
+ if ( $old_pkey ) {
+ $error = $new->replace($old, @args);
+ } else {
+ $error = $new->insert(@args);
+ }
+ $new_pkey = $new->getfield($pkey);
}
- $new_pkey = $new->getfield($pkey);
- }
+
+ } #unless $opt{'skip_process'}
if ( !$error && $opt{'process_m2m'} ) {
@@ -344,5 +357,4 @@ foreach my $value ( @values ) {
last if $error;
}
-
</%init>
diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css
index 79c98cdd9..44a4a3ca2 100644
--- a/httemplate/elements/freeside.css
+++ b/httemplate/elements/freeside.css
@@ -115,7 +115,7 @@ a.fstab {
padding-right:12px;*/
padding-left:4px;
padding-right:4px;
- font-size:16px;
+ font-size:18px;
font-weight:bold;
text-decoration:none;
overflow:visible;
@@ -148,7 +148,7 @@ a.fstabselected {
padding-right:12px;*/
padding-left:4px;
padding-right:4px;
- font-size:16px;
+ font-size:18px;
font-weight:bold;
text-decoration:none;
overflow:visible;
@@ -220,6 +220,32 @@ div.fstabcontainer {
font-weight:bold;
}
+.fsinnerbox {
+ background-color:#cccccc;
+ padding:2px;
+ -moz-box-shadow: 1px 1px 2px #666666;
+ -webkit-box-shadow: 1px 1px 2px #666666;
+ box-shadow: 1px 1px 2px #666666;
+ filter: progid:DXImageTransform.Microsoft.Shadow(color='#666666', Direction=135, Strength=2);
+}
+
+.fsinnerbox-title {
+ font-size:110%;
+ font-weight:bold;
+ background-color:#cccccc;
+ padding:2px;
+ -moz-border-radius-topleft:8px;
+ -moz-border-radius-topright:8px;
+ -webkit-border-radius-topleft:8px;
+ -webkit-border-radius-topright:8px;
+ border-radius-topleft:8px;
+ border-radius-topright:8px;
+ -moz-box-shadow: 1px 0px 1px #999999;
+ -webkit-box-shadow: 1px 0px 1px #999999;
+ box-shadow: 1px 0px 1px #999999;
+ filter: progid:DXImageTransform.Microsoft.Shadow(color='#999999', Direction=90, Strength=1);
+}
+
.background {
background-color:#f8f8f8;
}
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi
index dcadf9912..fda4db0d9 100755
--- a/httemplate/view/cust_main.cgi
+++ b/httemplate/view/cust_main.cgi
@@ -150,6 +150,11 @@ function areyousure(href, message) {
</TD>
</TR>
+<TR>
+ <TD COLSPAN = 2>
+ <& cust_main/contacts_new.html, $cust_main &>
+ </TD>
+</TR>
</TABLE>
% }
diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html
index f1add6fcc..522c6db86 100644
--- a/httemplate/view/cust_main/billing.html
+++ b/httemplate/view/cust_main/billing.html
@@ -1,4 +1,4 @@
-<% mt('Billing information') |h %>
+<FONT CLASS="fsinnerbox-title"><% mt('Billing information') |h %></FONT>
%# If we can't see the unencrypted card, then bill now is an exercise in
%# frustration (without some sort of job queue magic to send it to a secure
%# machine, anyway)
@@ -6,14 +6,14 @@
% && ! $cust_main->is_encrypted($cust_main->payinfo)
% ) {
%# (<A HREF="<% $p %>misc/bill.cgi?<% $cust_main->custnum %>"><% mt('Bill now') |h %></A>)
- (<& /elements/bill.html,
- custnum => $cust_main->custnum,
- label => emt('Bill now'),
- url => $p.'view/cust_main.cgi?'.$cust_main->custnum,
- &>)
+ <& /elements/bill.html,
+ custnum => $cust_main->custnum,
+ label => emt('Bill now'),
+ url => $p.'view/cust_main.cgi?'.$cust_main->custnum,
+ &>
% }
-<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<TABLE CLASS="fsinnerbox">
%( my $balance = $cust_main->balance )
% =~ s/^(\-?)(.*)$/<FONT SIZE=+1>$1<\/FONT>$money_char$2/;
@@ -285,7 +285,7 @@
% }
-</TABLE></TD></TR></TABLE>
+</TABLE>
<%once>
my $paystate_label = FS::Msgcat::_gettext('paystate');
diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html
index 68e3b17ad..b3e52b556 100644
--- a/httemplate/view/cust_main/contacts.html
+++ b/httemplate/view/cust_main/contacts.html
@@ -5,8 +5,8 @@
% foreach my $which ( '', 'ship_' ) {
% my $pre = $cust_main->get("${which}last") ? $which : '';
-<% $which{$which} %> <% mt('address') |h %>
-<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<FONT CLASS="fsinnerbox-title"><% $which{$which} %> <% mt('address') |h %></FONT>
+<TABLE CLASS="fsinnerbox">
<TR>
<TD ALIGN="right"><% mt('Contact name') |h %></TD>
<TD COLSPAN=5 BGCOLOR="#ffffff">
@@ -17,18 +17,23 @@
<TD BGCOLOR="#ffffff"><% $cust_main->masked('ss') || '&nbsp' %></TD>
% }
</TR>
+
% if ( $conf->exists('cust-email-high-visibility') && $which eq '') {
-<TR>
- <TD ALIGN="right"><% mt('Email invoices') |h %></TD>
- <TD BGCOLOR="#ffff00">
- <% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || $no %>
- </TD>
-</TR>
+ <TR>
+ <TD ALIGN="right"><% mt('Email invoices') |h %></TD>
+ <TD BGCOLOR="#ffff00">
+ <% join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || $no %>
+ </TD>
+ </TR>
% }
-<TR>
- <TD ALIGN="right"><% mt('Company') |h %></TD>
- <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") |h %></TD>
-</TR>
+
+% if ( $cust_main->get("${pre}company") ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Company') |h %></TD>
+ <TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}company") |h %></TD>
+ </TR>
+% }
+
<TR>
<TD ALIGN="right"><% mt('Address') |h %></TD>
<TD COLSPAN=7 BGCOLOR="#ffffff"><% $cust_main->get("${pre}address1") |h %></TD>
@@ -74,42 +79,30 @@
&>
% }
-<TR>
- <TD ALIGN="right"><% $daytime_label %></TD>
- <TD COLSPAN=3 BGCOLOR="#ffffff">
- <& /elements/phonenumber.html,
- $cust_main->get("${pre}daytime"),
- 'callable'=>1,
- 'calling_list_exempt'=>$cust_main->calling_list_exempt,
- &>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% $night_label %></TD>
- <TD COLSPAN=3 BGCOLOR="#ffffff">
- <& /elements/phonenumber.html,
- $cust_main->get("${pre}night"),
- 'callable'=>1,
- 'calling_list_exempt'=>$cust_main->calling_list_exempt,
- &>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% $mobile_label %></TD>
- <TD COLSPAN=3 BGCOLOR="#ffffff">
- <& /elements/phonenumber.html,
- $cust_main->get("${pre}mobile"),
- 'callable'=>1,
- 'calling_list_exempt'=>$cust_main->calling_list_exempt,
- &>
- </TD>
-</TR>
-<TR>
- <TD ALIGN="right"><% mt('Fax') |h %></TD>
- <TD COLSPAN=3 BGCOLOR="#ffffff">
- <% $cust_main->get("${pre}fax") || '&nbsp' %>
- </TD>
-</TR>
+% foreach my $phone (grep $cust_main->get($pre.$_), qw( daytime night mobile )){
+
+ <TR>
+ <TD ALIGN="right"><% $phone_label{$phone} %></TD>
+ <TD COLSPAN=3 BGCOLOR="#ffffff">
+ <& /elements/phonenumber.html,
+ $cust_main->get($pre.$phone),
+ 'callable'=>1,
+ 'calling_list_exempt'=>$cust_main->calling_list_exempt,
+ &>
+ </TD>
+ </TR>
+
+% }
+
+% if ( $cust_main->get("${pre}fax") ) {
+ <TR>
+ <TD ALIGN="right"><% mt('Fax') |h %></TD>
+ <TD COLSPAN=3 BGCOLOR="#ffffff">
+ <% $cust_main->get("${pre}fax") || '&nbsp' %>
+ </TD>
+ </TR>
+% }
+
% if ( $which eq '' && $conf->exists('show_stateid') ) {
<TR>
<TD ALIGN="right"><% $stateid_label %></TD>
@@ -118,23 +111,31 @@
<TD BGCOLOR="#ffffff"><% $cust_main->stateid_state || '&nbsp' %></TD>
</TR>
% }
-</TABLE></TD></TR></TABLE>
+
+</TABLE>
% if ( $which ne 'ship_' ) {
<BR>
% }
% }
-<& contacts_new.html, $cust_main &>
<%once>
-my $daytime_label = FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
- ? 'Day&nbsp;Phone'
- : FS::Msgcat::_gettext('daytime');
-my $night_label = FS::Msgcat::_gettext('night') =~ /^(night)?$/
- ? 'Night&nbsp;Phone'
- : FS::Msgcat::_gettext('night');
-my $mobile_label = FS::Msgcat::_gettext('mobile') =~ /^(mobile)?$/
- ? 'Mobile&nbsp;Phone'
- : FS::Msgcat::_gettext('Mobile');
+my %phone_label = (
+
+ 'daytime' => ( FS::Msgcat::_gettext('daytime') =~ /^(daytime)?$/
+ ? 'Day&nbsp;Phone'
+ : FS::Msgcat::_gettext('daytime')
+ ),
+
+ 'night' => ( FS::Msgcat::_gettext('night') =~ /^(night)?$/
+ ? 'Night&nbsp;Phone'
+ : FS::Msgcat::_gettext('night')
+ ),
+
+ 'mobile' => ( FS::Msgcat::_gettext('mobile') =~ /^(mobile)?$/
+ ? 'Mobile&nbsp;Phone'
+ : FS::Msgcat::_gettext('Mobile')
+ ),
+);
my $stateid_label = FS::Msgcat::_gettext('stateid') =~ /^(stateid)?$/
? 'Driver&rsquo;s&nbsp;License'
diff --git a/httemplate/view/cust_main/contacts_new.html b/httemplate/view/cust_main/contacts_new.html
index bd812c7e7..155490fe1 100644
--- a/httemplate/view/cust_main/contacts_new.html
+++ b/httemplate/view/cust_main/contacts_new.html
@@ -1,17 +1,44 @@
-% if ( @contacts ) {
<BR>
-Contacts
-<% ntable("#cccccc",2) %>
+<FONT CLASS="fsinnerbox-title">Contacts</FONT>
+<A HREF="<%$p%>/edit/cust_main-contacts.html?<% $cust_main->custnum %>">Edit contacts</A>
+<TABLE CLASS="fsinnerbox">
% foreach my $contact ( @contacts ) {
+% #XXX maybe this should be a table with alternating colors instead
<TR>
- <TD ALIGN="right">Contact</TD>
+ <TD ALIGN="right"><% $contact->contact_classname %> Contact</TD>
<TD BGCOLOR="#FFFFFF"><% $contact->line %></TD>
+
+% my @contact_email = $contact->contact_email;
+% if (@contact_email) {
+ <TD ALIGN="right">&nbsp;&nbsp;&nbsp;Email</TD>
+ <TD BGCOLOR="#FFFFFF"><% join(', ', map $_->emailaddress, @contact_email) %></TD>
+% }
+
+% foreach my $phone_type (@phone_type) {
+% my $contact_phone =
+% qsearchs('contact_phone', {
+% 'contactnum' => $contact->contactnum,
+% 'phonetypenum' => $phone_type->phonetypenum,
+% })
+% or next;
+ <TD ALIGN="right">&nbsp;&nbsp;&nbsp;<% $phone_type->typename %> phone</TD>
+ <TD BGCOLOR="#FFFFFF"><% $contact_phone->phonenum |h %></TD>
+% }
+
+% if ( $contact->comment ) {
+ <TD ALIGN="right">&nbsp;&nbsp;&nbsp;Comment</TD>
+ <TD BGCOLOR="#FFFFFF"><% $contact->comment |h %></TD>
+
+% }
+
</TR>
% }
</TABLE>
+<%once>
-% }
+my @phone_type = qsearch({table=>'phone_type', order_by=>'weight'});
+</%once>
<%init>
my( $cust_main ) = @_;
diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html
index 28414ef2d..295328721 100644
--- a/httemplate/view/cust_main/misc.html
+++ b/httemplate/view/cust_main/misc.html
@@ -1,4 +1,4 @@
-<% ntable("#cccccc") %><TR><TD><% &ntable("#cccccc",2) %>
+<TABLE CLASS="fsinnerbox">
<TR>
<TD ALIGN="right"><% mt('Customer number') |h %></TD>
@@ -150,7 +150,7 @@
<% $cust_main->pvf($_)->widget('HTML', 'view', $cust_main->getfield($_)) %>
% }
-</TABLE></TD></TR></TABLE>
+</TABLE>
<%init>
my( $cust_main ) = @_;