diff options
Diffstat (limited to 'httemplate/view')
22 files changed, 658 insertions, 330 deletions
diff --git a/httemplate/view/bill_batch.cgi b/httemplate/view/bill_batch.cgi index 7d640395e..55ee4be1c 100644 --- a/httemplate/view/bill_batch.cgi +++ b/httemplate/view/bill_batch.cgi @@ -13,7 +13,7 @@ 'hashref' => { }, 'addl_from' => 'LEFT JOIN cust_bill USING ( invnum ) '. - 'LEFT JOIN cust_main USING ( custnum )', + FS::UI::Web::join_cust_main('cust_bill'), 'extra_sql' => " WHERE batchnum = $batchnum", }, 'count_query' => "SELECT COUNT(*) FROM cust_bill_batch WHERE batchnum = $batchnum", diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html index 5c46803d2..b863a734b 100644 --- a/httemplate/view/cust_main/billing.html +++ b/httemplate/view/cust_main/billing.html @@ -247,6 +247,10 @@ <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> % } diff --git a/httemplate/view/cust_main/change_history.html b/httemplate/view/cust_main/change_history.html index ea84b8f75..bf32a49f9 100644 --- a/httemplate/view/cust_main/change_history.html +++ b/httemplate/view/cust_main/change_history.html @@ -43,10 +43,12 @@ tie my %tables, 'Tie::IxHash', 'svc_external' => 'External service', 'svc_phone' => 'Phone', 'phone_device' => 'Phone device', + 'cust_pkg_discount' => 'Discount', #? it gets provisioned anyway 'phone_avail' => 'Phone', ; -my $svc_join = 'JOIN cust_svc USING ( svcnum ) JOIN cust_pkg USING ( pkgnum )'; +my $pkg_join = "JOIN cust_pkg USING ( pkgnum )"; +my $svc_join = "JOIN cust_svc USING ( svcnum ) $pkg_join"; my %table_join = ( 'svc_acct' => $svc_join, @@ -58,6 +60,7 @@ my %table_join = ( 'svc_external' => $svc_join, 'svc_phone' => $svc_join, 'phone_device' => $svc_join, + 'cust_pkg_discount'=> $pkg_join, ); @@ -104,7 +107,7 @@ my $conf = new FS::Conf; my $curuser = $FS::CurrentUser::CurrentUser; -die "access deined" +die "access denied" unless $curuser->access_right('View customer history'); # find out the beginning of this customer history, if possible diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index 7d7930634..546dd89c3 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -1,3 +1,29 @@ +<STYLE TYPE="text/css"> +td.package { + vertical-align: top; + border-width: 0; + border-style: solid; + border-color: #bbbbff; +} +table.package { + border: none; + padding: 0; + border-spacing: 0; + width: 100%; +} +table.usage { + border: 1px solid black; + margin: auto; + width: 60%; + border-spacing: 0px; +} +.shared > * { + background-color: #ffffaa; +} +.row0 { background-color: #eeeeee; } +.row1 { background-color: #ffffff; } + +</STYLE> % my $s = 0; % if ( $curuser->access_right('Qualify service') ) { @@ -75,7 +101,7 @@ <TR> <TD COLSPAN=2> -% if ( $conf->exists('cust_pkg-group_by_location') and $show_location ) { +% if ( $conf->exists('cust_pkg-group_by_location') ) { <& locations.html, 'cust_main' => $cust_main, 'packages' => $packages, @@ -87,7 +113,6 @@ <& packages/section.html, 'cust_main' => $cust_main, 'packages' => $packages, - 'show_location' => $show_location, &> </TABLE> % } @@ -114,10 +139,6 @@ my $curuser = $FS::CurrentUser::CurrentUser; my( $packages, $num_old_packages ) = get_packages($cust_main, $conf); - -my $show_location = $conf->exists('cust_pkg-always_show_location') - || (grep $_->locationnum, @$packages); # ? '1' : '0'; - my $countrydefault = scalar($conf->config('countrydefault')) || 'US'; #subroutines @@ -178,6 +199,10 @@ sub get_packages { } $num_old_packages -= scalar(@packages); + + # don't include supplemental packages in this list; they'll be found from + # their main packages + @packages = grep !$_->main_pkgnum, @packages; ( \@packages, $num_old_packages ); } diff --git a/httemplate/view/cust_main/packages/contact.html b/httemplate/view/cust_main/packages/contact.html new file mode 100644 index 000000000..93129915f --- /dev/null +++ b/httemplate/view/cust_main/packages/contact.html @@ -0,0 +1,61 @@ +% if ( $contact ) { + <% $contact->line |h %> +% if ( $show_link ) { + <FONT SIZE=-1> + ( <%pkg_change_contact_link($cust_pkg)%> ) + </FONT> +% } +% } elsif ( $show_link ) { + <FONT SIZE=-1> + ( <%pkg_add_contact_link($cust_pkg)%> ) + </FONT> +% } +<%init> + +my $conf = new FS::Conf; +my %opt = @_; + +my $cust_pkg = $opt{'cust_pkg'}; + +my $show_link = + ! $cust_pkg->get('cancel') + && $FS::CurrentUser::CurrentUser->access_right('Change customer package'); + +my $contact = $cust_pkg->contact_obj; + +sub pkg_change_contact_link { + my $cust_pkg = shift; + #my $pkgpart = $cust_pkg->pkgpart; + include( '/elements/popup_link-cust_pkg.html', + 'action' => $p. "misc/change_pkg_contact.html", + 'label' => emt('Change'), # contact'), + 'actionlabel' => emt('Change'), + 'cust_pkg' => $cust_pkg, + 'width' => 616, + 'height' => 220, + ); +} + +sub pkg_add_contact_link { + my $cust_pkg = shift; + #my $pkgpart = $cust_pkg->pkgpart; + include( '/elements/popup_link-cust_pkg.html', + 'action' => $p. "misc/change_pkg_contact.html", + 'label' => emt('Add contact'), + 'actionlabel' => emt('Change'), + 'cust_pkg' => $cust_pkg, + 'width' => 616, + 'height' => 192, + ); +} + +#sub edit_contact_link { +# my $contactnum = shift; +# include( '/elements/popup_link.html', +# 'action' => $p. "edit/cust_contact.cgi?contactnum=$contactnum", +# 'label' => emt('Edit contact'), +# 'actionlabel' => emt('Edit'), +# ); +#} + +</%init> diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html index 34e3a64c3..f2d379841 100644 --- a/httemplate/view/cust_main/packages/location.html +++ b/httemplate/view/cust_main/packages/location.html @@ -1,7 +1,5 @@ -<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" WIDTH="20%"> - -% unless ( $cust_pkg->locationnum ) { - <I><FONT SIZE=-1>(<% mt('default service address') |h %>)</FONT><BR> +% if ( $default ) { + <DIV STYLE="font-style: italic; font-size: small"> % } <% $loc->location_label( 'join_string' => '<BR>', @@ -24,8 +22,8 @@ </FONT> % } -% unless ( $cust_pkg->locationnum ) { - </I> +% if ( $default ) { + </DIV> % } % if ( ! $cust_pkg->get('cancel') @@ -41,19 +39,19 @@ </FONT> % } -</TD> <%init> my $conf = new FS::Conf; my %opt = @_; -my $bgcolor = $opt{'bgcolor'}; my $cust_pkg = $opt{'cust_pkg'}; my $countrydefault = $opt{'countrydefault'} || 'US'; my $statedefault = $opt{'statedefault'} || ($countrydefault eq 'US' ? 'CA' : ''); my $loc = $cust_pkg->cust_location_or_main; +# dubious--they should all have a location now +my $default = $cust_pkg->locationnum == $opt{'cust_main'}->ship_locationnum; sub pkg_change_location_link { my $cust_pkg = shift; diff --git a/httemplate/view/cust_main/packages/package.html b/httemplate/view/cust_main/packages/package.html index 5d93ad46f..520305a9a 100644 --- a/httemplate/view/cust_main/packages/package.html +++ b/httemplate/view/cust_main/packages/package.html @@ -1,5 +1,6 @@ -<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="top"> - <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%"> +<TD CLASS="inv package" BGCOLOR="<% $bgcolor %>" VALIGN="top" + STYLE="border-left-width: <% $supplemental * 30 %>px"> + <TABLE CLASS="inv package"> <TR> <TD COLSPAN=2> <A NAME="cust_pkg<% $cust_pkg->pkgnum %>" @@ -17,50 +18,62 @@ <B><% $cust_pkg->quantity %></B> </TD> </TR> -% } +% } <TR> <TD COLSPAN=2> <FONT SIZE=-1> -% unless ( $cust_pkg->get('cancel') ) { +% unless ( $cust_pkg->get('cancel') ) { % -% my $br = 0; -% if ( $curuser->access_right('Change customer package') ) { -% $br=1; - ( <%pkg_change_link($cust_pkg)%> ) -% } +% if ( $supplemental or $part_pkg->freq eq '0' ) { +% # Supplemental packages can't be changed independently. +% # One-time charges don't need to be changed. +% # For both of those, we only show "Edit dates", "Add comments", +% # and "Add invoice details". +% if ( $curuser->access_right('Edit customer package dates') ) { + ( <%pkg_dates_link($cust_pkg)%> ) +% } +% } else { +% # the usual case: links to change package definition, +% # discount, and customization +% my $br = 0; +% if ( $curuser->access_right('Change customer package') ) { +% $br=1; + ( <%pkg_change_link($cust_pkg)%> ) +% } % -% if ( $curuser->access_right('Edit customer package dates') ) { -% $br=1; - ( <%pkg_dates_link($cust_pkg)%> ) -% } +% if ( $curuser->access_right('Edit customer package dates') ) { +% $br=1; + ( <%pkg_dates_link($cust_pkg)%> ) +% } % -% if ( $curuser->access_right('Discount customer package') -% && $part_pkg->can_discount -% && ! scalar($cust_pkg->cust_pkg_discount_active) -% && ! scalar($cust_pkg->part_pkg->part_pkg_discount) -% ) -% { -% $br=1; - ( <%pkg_discount_link($cust_pkg)%> ) -% } +% if ( $curuser->access_right('Discount customer package') +% && $part_pkg->can_discount +% && ! scalar($cust_pkg->cust_pkg_discount_active) +% && ! scalar($cust_pkg->part_pkg->part_pkg_discount) +% ) +% { +% $br=1; + ( <%pkg_discount_link($cust_pkg)%> ) +% } % -% if ( $curuser->access_right('Customize customer package') ) { -% $br=1; - ( <%pkg_customize_link($cust_pkg,$part_pkg)%> ) -% } +% if ( $curuser->access_right('Customize customer package') ) { +% $br=1; + ( <%pkg_customize_link($cust_pkg,$part_pkg)%> ) +% } % - <% $br ? '<BR>' : '' %> -% } + <% $br ? '<BR>' : '' %> +% } -% if ( $cust_pkg->num_cust_event -% && ( $curuser->access_right('Billing event reports') -% || $curuser->access_right('View customer billing events') -% ) -% ) { - ( <%pkg_event_link($cust_pkg)%> ) -% } +% if ( $cust_pkg->num_cust_event +% && ( $curuser->access_right('Billing event reports') +% || $curuser->access_right('View customer billing events') +% ) +% ) { + ( <%pkg_event_link($cust_pkg)%> ) +% } +% } #!$supplemental </FONT> </TD> @@ -170,15 +183,40 @@ </TR> % if ( $curuser->access_right('Change customer package') and % !$cust_pkg->get('cancel') and -% !$opt{'show_location'}) { +% !$supplemental and +% $part_pkg->freq ne '0' ) { <TR> +% if ( FS::Conf->new->exists('invoice-unitprice') ) { <TD><FONT SIZE="-1"> - ( <% pkg_change_location_link($cust_pkg) %> ) + ( <% pkg_change_quantity_link($cust_pkg) %> ) </FONT></TD> +% } </TR> % } % } </TABLE> +% if ( @cust_pkg_usage ) { + <TABLE CLASS="usage inv"> + <TR><TH COLSPAN=4><% mt('Included usage') %></TH></TR> +% foreach my $usage (@cust_pkg_usage) { +% my $part = $usage->part_pkg_usage; +% my $ratio = 255 * ($usage->minutes / $part->minutes); +% $ratio = 255 if $ratio > 255; # because rollover +% my $color = sprintf('STYLE="font-weight: bold; color: #%02x%02x00"', 255 - $ratio, $ratio); +% my $trstyle = ''; +% $trstyle = ' CLASS="shared"' if $part->shared; + <TR<%$trstyle%>> + <TD ALIGN="right"><% $part->description %>: </TD> + <TD <%$color%> ALIGN="right"><% $usage->minutes %></TD> + <TD <%$color%>> / </TD> + <TD <%$color%>><% $part->minutes %></TD> +% if ( $part->shared ) { + <TD><I>(shared)</I></TD> +% } + </TR> +% } + </TABLE> +% } </TD> @@ -196,6 +234,18 @@ my $countrydefault = $opt{'countrydefault'} || 'US'; my $statedefault = $opt{'statedefault'} || ($countrydefault eq 'US' ? 'CA' : ''); +my $supplemental = $opt{'supplemental'} || 0; + +$cust_pkg->pkgnum =~ /^(\d+)$/; +my $pkgnum = $1; +my @cust_pkg_usage = qsearch({ + 'select' => 'cust_pkg_usage.*', + 'table' => 'cust_pkg_usage', + 'addl_from' => ' JOIN part_pkg_usage USING (pkgusagepart)', + 'extra_sql' => " WHERE pkgnum = $1", + 'order_by' => ' ORDER BY priority ASC, description ASC', +}); + #subroutines #false laziness w/status.html @@ -229,6 +279,17 @@ sub pkg_change_location_link { ); } +sub pkg_change_quantity_link { + include( '/elements/popup_link-cust_pkg.html', + 'action' => $p. 'edit/cust_pkg_quantity.html?', + 'label' => emt('Change quantity'), + 'actionlabel' => emt('Change'), + 'cust_pkg' => shift, + 'width' => 390, + 'height' => 220, + ); +} + sub pkg_dates_link { pkg_link('edit/REAL_cust_pkg', emt('Edit dates'), @_ ); } sub pkg_discount_link { diff --git a/httemplate/view/cust_main/packages/section.html b/httemplate/view/cust_main/packages/section.html index 85f0c795a..5f54c0a36 100755 --- a/httemplate/view/cust_main/packages/section.html +++ b/httemplate/view/cust_main/packages/section.html @@ -1,53 +1,48 @@ % if ( @$packages ) { -% my $bgcolor1 = '#eeeeee'; -% my $bgcolor2 = '#ffffff'; -% my $bgcolor = ''; - <TR> % #my $width = $show_location ? 'WIDTH="25%"' : 'WIDTH="33%"'; <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Package') |h %></TH> <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Status') |h %></TH> -% if ( $show_location ) { - <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Location') |h %></TH> -% } + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Contact/Location') |h %></TH> <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Services') |h %></TH> </TR> % #$FS::cust_pkg::DEBUG = 2; % foreach my $cust_pkg (@$packages) { + <& .packagerow, $cust_pkg, + 'cust_main' => $opt{'cust_main'}, + 'bgcolor' => $opt{'bgcolor'}, + %conf_opt + &> +% } +% } else { # there are no packages +<BR> +% } +<%def .packagerow> % -% if ( $bgcolor eq $bgcolor1 ) { -% $bgcolor = $bgcolor2; -% } else { -% $bgcolor = $bgcolor1; -% } -% -% my %iopt = ( -% 'bgcolor' => $bgcolor, -% 'cust_pkg' => $cust_pkg, -% 'part_pkg' => $cust_pkg->part_pkg, -% 'cust_main' => $opt{'cust_main'}, -% %conf_opt, -% ); -% - +% my ($cust_pkg, %iopt) = @_; +% $iopt{'cust_pkg'} = $cust_pkg; +% $iopt{'part_pkg'} = $cust_pkg->part_pkg; <!--pkgnum: <% $cust_pkg->pkgnum %>--> - <TR> + <TR CLASS="row<%$row % 2%>"> <& package.html, %iopt &> - <& status.html, %iopt &> -% if ( $show_location ) { - <& location.html, %iopt &> -% } + <& status.html, %iopt &> + <TD CLASS="inv" BGCOLOR="<% $iopt{bgcolor} %>" WIDTH="20%" VALIGN="top"> + <& contact.html, %iopt &> + <& location.html, %iopt &> + </TD> <& services.html, %iopt &> </TR> - -% } #foreach $cust_pkg -%# </TABLE> -% } #if @$packages -% else { -<BR> +% $row++; +% # include supplemental packages if any +% $iopt{'supplemental'} = ($iopt{'supplemental'} || 0) + 1; +% foreach my $supp_pkg ($cust_pkg->supplemental_pkgs) { + <& .packagerow, $supp_pkg, %iopt &> % } - +</%def> +<%shared> +my $row = 0; +</%shared> <%init> my %opt = @_; @@ -56,7 +51,6 @@ my $conf = new FS::Conf; my $curuser = $FS::CurrentUser::CurrentUser; my $packages = $opt{'packages'}; -my $show_location = $opt{'show_location'}; # Sort order is hardcoded for now, can change this if needed. @$packages = sort { @@ -89,10 +83,8 @@ my %conf_opt = ( 'manage_link_loc' => scalar($conf->config('svc_broadband-manage_link_loc')), 'manage_link-new_window' => $conf->exists('svc_broadband-manage_link-new_window'), 'maestro-status_test' => $conf->exists('maestro-status_test'), - 'cust_pkg-large_pkg_size' => $conf->config('cust_pkg-large_pkg_size'), + 'cust_pkg-large_pkg_size' => scalar($conf->config('cust_pkg-large_pkg_size')), - # for packages.html Change location link - 'show_location' => $show_location, ); </%init> diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html index e9017745b..9d5a88e0f 100644 --- a/httemplate/view/cust_main/packages/status.html +++ b/httemplate/view/cust_main/packages/status.html @@ -1,9 +1,11 @@ -<TD CLASS="inv" BGCOLOR="<% $bgcolor %>"> +<TD CLASS="inv" BGCOLOR="<% $bgcolor %>" VALIGN="top"> <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%"> %#this should use cust_pkg->status and cust_pkg->statuscolor eventually -% if ( $cust_pkg->order_date ) { +% if ( $supplemental ) { + <% pkg_status_row_colspan($cust_pkg, emt('Supplemental'), '', 'color' => '7777FF', %opt) %> +% } elsif ( $cust_pkg->order_date ) { <% pkg_status_row($cust_pkg, emt('Ordered'), 'order_date', %opt ) %> % } @@ -12,30 +14,25 @@ <% pkg_status_row($cust_pkg, emt('Cancelled'), 'cancel', 'color'=>'FF0000', %opt ) %> - <% pkg_status_row_colspan( $cust_pkg, - ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '', - 'align'=>'right', 'color'=>'ff0000', 'size'=>'-2', 'colspan'=>$colspan, - %opt - ) - %> + <% pkg_reason_row($cust_pkg, $cpr, color => 'ff0000', %opt) %> % unless ( $cust_pkg->get('setup') ) { - <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', 'colspan'=>$colspan, %opt, ) %> + <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt, ) %> % } else { <% pkg_status_row( $cust_pkg, emt('Setup'), 'setup', %opt ) %> - <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_changed( $cust_pkg, %opt ) %> <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %> <% pkg_status_row_if( $cust_pkg, emt('Suspended'), 'susp', %opt, curuser=>$curuser ) %> % } % -% if ( $part_pkg->freq ) { #? +% if ( $part_pkg->freq and !$supplemental ) { #? <TR> - <TD COLSPAN=<%$colspan%>> + <TD COLSPAN=<%$opt{colspan}%>> <FONT SIZE=-1> % if ( $curuser->access_right('Un-cancel customer package') ) { ( <% pkg_uncancel_link($cust_pkg) %> ) @@ -52,26 +49,21 @@ <% pkg_status_row( $cust_pkg, emt('Suspended'), 'susp', 'color'=>'FF9900', %opt ) %> - <% pkg_status_row_colspan( $cust_pkg, - ( $cpr ? $cpr->reasontext. ' by '. $cpr->otaker : '' ), '', - 'align'=>'right', 'color'=>'FF9900', 'size'=>'-2', 'colspan'=>$colspan, - %opt, - ) - %> + <% pkg_reason_row( $cust_pkg, $cpr, 'color' => 'FF9900', %opt ) %> - <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_noauto( $cust_pkg, %opt ) %> - <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_discount( $cust_pkg, %opt ) %> % unless ( $cust_pkg->get('setup') ) { - <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', 'colspan'=>$colspan, %opt ) %> + <% pkg_status_row_colspan( $cust_pkg, emt('Never billed'), '', %opt ) %> % } else { <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt ) %> % } <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %> - <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_changed( $cust_pkg, %opt ) %> <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %> % if ( $cust_pkg->option('suspend_bill', 1) % || ( $part_pkg->option('suspend_bill', 1) @@ -85,31 +77,33 @@ <% pkg_status_row_if( $cust_pkg, emt('Expires'), 'expire', %opt, curuser=>$curuser ) %> <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %> - <TR> - <TD COLSPAN=<%$colspan%>> - <FONT SIZE=-1> -% if ( $curuser->access_right('Unsuspend customer package') ) { - ( <% pkg_unsuspend_link($cust_pkg) %> ) - ( <% pkg_resume_link($cust_pkg) %> ) -% } -% if ( $curuser->access_right('Cancel customer package immediately') ) { - ( <% pkg_cancel_link($cust_pkg) %> ) -% } - </FONT> - </TD> - </TR> - +% if ( !$supplemental ) { + <TR> + <TD COLSPAN=<%$opt{colspan}%>> + <FONT SIZE=-1> +% if ( $curuser->access_right('Unsuspend customer package') ) { + ( <% pkg_unsuspend_link($cust_pkg) %> ) + ( <% pkg_resume_link($cust_pkg) %> ) +% } +% if ( $curuser->access_right('Cancel customer package immediately') ) { + ( <% pkg_cancel_link($cust_pkg) %> ) +% } + </FONT> + </TD> + </TR> +% } +% % } else { #status: active % % unless ( $cust_pkg->get('setup') ) { #not setup % % unless ( $part_pkg->freq ) { - <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', 'colspan'=>$colspan, %opt ) %> + <% pkg_status_row_colspan( $cust_pkg, emt('Not yet billed (one-time charge)'), '', %opt ) %> - <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_noauto( $cust_pkg, %opt ) %> - <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_discount( $cust_pkg, %opt ) %> <% pkg_status_row_if( $cust_pkg, @@ -121,8 +115,9 @@ <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %> +% if (!$supplemental) { <TR> - <TD COLSPAN=<%$colspan%>> + <TD COLSPAN=<%$opt{colspan}%>> <FONT SIZE=-1> % if ( $curuser->access_right('Cancel customer package immediately') ) { ( <% pkg_cancel_link($cust_pkg) %> ) @@ -130,14 +125,15 @@ </FONT> </TD> </TR> +% } % } else { - <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', 'colspan'=>$colspan, %opt ) %> + <% pkg_status_row_colspan($cust_pkg, emt("Not yet billed ($billed_or_prepaid [_1])", myfreq($part_pkg) ), '', %opt ) %> - <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_noauto( $cust_pkg, %opt ) %> - <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_discount( $cust_pkg, %opt ) %> <% pkg_status_row_if($cust_pkg, emt('Start billing'), 'start_date', %opt) %> <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %> @@ -148,13 +144,13 @@ % % unless ( $part_pkg->freq ) { - <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', 'colspan'=>$colspan, %opt ) %> + <% pkg_status_row_colspan($cust_pkg, emt('One-time charge'), '', %opt ) %> <% pkg_status_row($cust_pkg, emt('Billed'), 'setup', %opt) %> - <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_noauto( $cust_pkg, %opt ) %> - <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_discount( $cust_pkg, %opt ) %> <% pkg_status_row_if($cust_pkg, emt('Un-cancelled'), 'uncancel', %opt ) %> @@ -170,7 +166,7 @@ <% pkg_status_row_colspan( $cust_pkg, emt('Overlimit'), $billed_or_prepaid. ' '. myfreq($part_pkg), - 'color'=>'FFD000', 'colspan'=>$colspan, + 'color'=>'FFD000', %opt ) %> @@ -179,15 +175,15 @@ <% pkg_status_row_colspan( $cust_pkg, emt('Active'), $billed_or_prepaid. ' '. myfreq($part_pkg), - 'color'=>'00CC00', 'colspan'=>$colspan, + 'color'=>'00CC00', %opt ) %> % } - <% pkg_status_row_noauto( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_noauto( $cust_pkg, %opt ) %> - <% pkg_status_row_discount( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_discount( $cust_pkg, %opt ) %> <% pkg_status_row($cust_pkg, emt('Setup'), 'setup', %opt) %> @@ -202,7 +198,7 @@ % $cust_pkg->set('autosuspend', $autosuspend) if $autosuspend; % } - <% pkg_status_row_changed( $cust_pkg, %opt, 'colspan'=>$colspan ) %> + <% pkg_status_row_changed( $cust_pkg, %opt ) %> <% pkg_status_row_if( $cust_pkg, $last_bill_or_renewed, 'last_bill', %opt, curuser=>$curuser ) %> <% pkg_status_row_if( $cust_pkg, $next_bill_or_prepaid_until, 'bill', %opt, curuser=>$curuser ) %> <% pkg_status_row_if($cust_pkg, emt('Will automatically suspend by'), 'autosuspend', %opt) %> @@ -212,10 +208,10 @@ <% pkg_status_row_if( $cust_pkg, emt('Expires'), 'expire', %opt, curuser=>$curuser ) %> <% pkg_status_row_if( $cust_pkg, emt('Contract ends'), 'contract_end', %opt ) %> -% if ( $part_pkg->freq ) { +% if ( $part_pkg->freq and !$supplemental ) { <TR> - <TD COLSPAN=<%$colspan%>> + <TD COLSPAN=<%$opt{colspan}%>> <FONT SIZE=-1> % if ( $curuser->access_right('Suspend customer package') ) { ( <% pkg_suspend_link($cust_pkg) %> ) @@ -251,8 +247,10 @@ my $bgcolor = $opt{'bgcolor'}; my $cust_pkg = $opt{'cust_pkg'}; my $part_pkg = $opt{'part_pkg'}; my $curuser = $FS::CurrentUser::CurrentUser; -my $colspan = $opt{'cust_pkg-display_times'} ? 8 : 4; my $width = $opt{'cust_pkg-display_times'} ? '38%' : '56%'; +my $supplemental = $opt{'supplemental'}; + +$opt{colspan} = $opt{'cust_pkg-display_times'} ? 8 : 4; #false laziness w/edit/REAL_cust_pkg.cgi my( $billed_or_prepaid, $last_bill_or_renewed, $next_bill_or_prepaid_until ); @@ -285,9 +283,27 @@ sub pkg_link { sub pkg_status_row { my( $cust_pkg, $title, $field, %opt ) = @_; + if ( $field and $cust_pkg->main_pkgnum ) { + # for supplemental packages, we mostly only show these if they're + # different from the main package + my $main_pkg = $cust_pkg-> main_pkg; + if ( $main_pkg->get($field) ne $cust_pkg->get($field) + # with some exceptions + or $field eq 'bill' + or $field eq 'last_bill' + or $field eq 'setup' + or $field eq 'susp' + or $field eq 'cancel' + ) { + # handle it normally + } else { + return ''; + } + } + my $color = $opt{'color'}; - my $html = qq(<TR><TD WIDTH="<%$width%>" ALIGN="right">); + my $html = qq(<TR><TD WIDTH="$width" ALIGN="right">); $html .= qq(<FONT COLOR="#$color"><B>) if length($color); $html .= qq($title ); $html .= qq(</B></FONT>) if length($color); @@ -338,7 +354,6 @@ sub pkg_status_row_changed { '', 'size' => '-1', 'align' => 'right', - 'colspan' => $opt{'colspan'}, ); } @@ -356,9 +371,7 @@ sub pkg_status_row_noauto { return '' unless $cust_main->payby =~ /^(CARD|CHEK)$/; my $what = lc(FS::payby->shortname($cust_main->payby)); - pkg_status_row_colspan( $cust_pkg, emt("No automatic $what charge"), '', - 'colspan' => $opt{'colspan'}, - ); + pkg_status_row_colspan( $cust_pkg, emt("No automatic $what charge"), ''); } sub pkg_status_row_discount { @@ -382,15 +395,24 @@ sub pkg_status_row_discount { $cust_pkg_discount->pkgdiscountnum. '">'.emt('remove discount').'</A>)</FONT>'; - $html .= pkg_status_row_colspan( $cust_pkg, $label, '', - 'colspan' => $opt{'colspan'}, - ); + $html .= pkg_status_row_colspan( $cust_pkg, $label, '', %opt ); } $html; } +sub pkg_reason_row { + my ($cust_pkg, $cpr, %opt) = @_; + return '' if $cust_pkg->main_pkgnum; + + my $reasontext = ''; + $reasontext = $cpr->reasontext . ' by ' . $cpr->otaker if $cpr; + pkg_status_row_colspan( $cust_pkg, $reasontext, '', + 'align'=>'right', 'size'=>'-2', %opt + ); +} + sub pkg_status_row_colspan { my($cust_pkg, $title, $addl, %opt) = @_; diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index 942b42f54..915be49e5 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -34,7 +34,7 @@ <A HREF="<% $p %>edit/cust_pay.cgi?payby=WEST;custnum=<% $custnum %>"><% mt('Enter Western Union payment') |h %></A> % } -<BR> +<% $s ? '<BR>' : '' %> % $s=0; % if ( ( $payby{'CARD'} || $payby{'DCRD'} ) @@ -58,11 +58,13 @@ <A HREF="<% $p %>edit/cust_pay.cgi?payby=MCRD;custnum=<% $custnum %>"><% mt('Post manual (offline/POS) credit card payment') |h %></A> % } -<BR> +<% $s ? '<BR>' : '' %> -%# credit link +%# credit links +% $s=0; % if ( $curuser->access_right('Post credit') ) { + <% $s++ ? ' | ' : '' %> <& /elements/popup_link-cust_main.html, 'label' => emt('Enter credit'), 'action' => "${p}edit/cust_credit.cgi", @@ -70,7 +72,9 @@ 'actionlabel' => emt('Enter credit'), 'width' => 616, #make room for reasons #540 default &> - | +% } +% if ( $curuser->access_right('Credit line items') ) { + <% $s++ ? ' | ' : '' %> <& /elements/popup_link-cust_main.html, 'label' => emt('Credit line items'), #'action' => "${p}search/cust_bill_pkg.cgi?nottax=1;type=select", @@ -80,8 +84,8 @@ 'width' => 968, #763, 'height' => 575, &> - <BR> % } +<% $s ? '<BR>' : '' %> %# refund links @@ -224,57 +228,20 @@ %#display payment history -%my $money_char = $conf->config('money_char') || '$'; -% -%sub balance_forward_row { -% my( $b, $date, $money_char ) = @_; -% ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/- \$/; - - <TR ID="balance_forward_row"> - <TD CLASS="grid" BGCOLOR="#dddddd"> - <% time2str($date_format, $date) %> - </TD> - - <TD CLASS="grid" BGCOLOR="#dddddd"> - <I><% mt("Starting balance on [_1]", time2str($date_format, $date) ) |h %></I> - (<A HREF="javascript:void(0);" onClick="show_history();"><% mt('show prior history') |h %></A>) - </TD> - - <TD CLASS="grid" BGCOLOR="#dddddd"></TD> - <TD CLASS="grid" BGCOLOR="#dddddd"></TD> - <TD CLASS="grid" BGCOLOR="#dddddd"></TD> - <TD CLASS="grid" BGCOLOR="#dddddd"></TD> - <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD> - - </TR> -%} -% -%my $balance = 0; %my %target = (); % -%my $years = $conf->config('payment_history-years') || 2; -%my $older_than = time - $years * 31556926; #60*60*24*365.2422 %my $hidden = 0; %my $seen = 0; %my $old_history = 0; %my $lastdate = 0; % -%foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) { +%foreach my $item ( @history ) { % % $lastdate = $item->{'date'}; % -% my $display; -% if ( $item->{'date'} < $older_than ) { +% my $display = ''; +% if ( $item->{'hide'} ) { % $display = ' STYLE="display:none" '; -% $hidden = 1; -% } else { -% -% $display = ''; -% -% if ( $hidden && ! $seen++ ) { -% balance_forward_row($balance, $item->{'date'}, $money_char); -% } -% % } % % if ( $bgcolor eq $bgcolor1 ) { @@ -310,16 +277,8 @@ % % my $target = exists($item->{'target'}) ? $item->{'target'} : ''; % -% $balance += $item->{'charge'} if exists $item->{'charge'}; -% $balance -= $item->{'payment'} if exists $item->{'payment'}; -% $balance -= $item->{'credit'} if exists $item->{'credit'}; -% $balance += $item->{'refund'} if exists $item->{'refund'}; -% $balance = sprintf("%.2f", $balance); -% $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp -% ( my $showbalance = $money_char. $balance ) =~ s/^\$\-/- \$/; -% -% - +% my $showbalance = $money_char . $item->{'balance'}; +% $showbalance =~ s/^\$\-/- \$/; <TR <% $display ? $display.' ID="old_history'.$old_history++.'"' : ''%>> <TD VALIGN="top" CLASS="grid" BGCOLOR="<% $bgcolor %>"> @@ -355,11 +314,11 @@ <% $showbalance %> </TD> </TR> -% } -%if ( scalar(@history) && $hidden && ! $seen++ ) { -% balance_forward_row($balance, $lastdate, $money_char); -%} +% if ( $item->{'balance_forward'} ) { +<& .balance_forward_row, $item->{'balance'}, $item->{'date'} &> +% } +%} # foreach $item </TABLE> </TD> @@ -382,14 +341,37 @@ function show_history () { } </SCRIPT> +<%def .balance_forward_row> +% my( $b, $date ) = @_; +% ( my $balance_forward = $money_char. $b ) =~ s/^\$\-/- \$/; -<%init> + <TR ID="balance_forward_row"> + <TD CLASS="grid" BGCOLOR="#dddddd"> + <% time2str($date_format, $date) %> + </TD> -my( $cust_main ) = @_; -my $custnum = $cust_main->custnum; + <TD CLASS="grid" BGCOLOR="#dddddd"> + <I><% mt("Starting balance on [_1]", time2str($date_format, $date) ) |h %></I> + (<A HREF="javascript:void(0);" onClick="show_history();"><% mt('show prior history') |h %></A>) + </TD> + + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd" ALIGN="right"><I><% $balance_forward %></I></TD> + </TR> +</%def> +<%shared> my $conf = new FS::Conf; my $date_format = $conf->config('date_format') || '%m/%d/%Y'; +my $money_char = $conf->config('money_char') || '$'; +</%shared> +<%init> + +my( $cust_main ) = @_; +my $custnum = $cust_main->custnum; my $curuser = $FS::CurrentUser::CurrentUser; @@ -497,6 +479,17 @@ foreach my $cust_pay_pending ($cust_main->cust_pay_pending_attempt) { #'target' => $target, #XXX }; } +#declined batch payments +foreach my $cust_pay_batch ( + $cust_main->cust_pay_batch(hashref => {status => 'Declined'}) +) { + my $pay_batch = $cust_pay_batch->pay_batch; + push @history, { + 'date' => $pay_batch->upload, + 'desc' => include('payment_history/attempted_batch_payment.html', $cust_pay_batch, %opt), + 'void_payment' => $cust_pay_batch->amount, + }; +} #credits (some false laziness w/payments) foreach my $cust_credit ($cust_main->cust_credit) { @@ -518,6 +511,41 @@ foreach my $cust_refund ($cust_main->cust_refund) { } +# sort in forward order first, and calculate running balances +my $years = $conf->config('payment_history-years') || 2; +my $older_than = time - $years * 31556926; #60*60*24*365.2422 +my $balance = 0; + +@history = sort { $a->{date} <=> $b->{date} } @history; +my $i = 0; +my $balance_forward; +foreach my $item (@history) { + $balance += $item->{'charge'} if exists $item->{'charge'}; + $balance -= $item->{'payment'} if exists $item->{'payment'}; + $balance -= $item->{'credit'} if exists $item->{'credit'}; + $balance += $item->{'refund'} if exists $item->{'refund'}; + $balance = sprintf("%.2f", $balance); + $balance =~ s/^\-0\.00$/0.00/; + $item->{'balance'} = $balance; + + if ( $item->{'date'} < $older_than ) { + $item->{'hide'} = 1; + } elsif ( $history[$i-1]->{'hide'} ) { + # this is the end of the hidden section + $history[$i-1]->{'balance_forward'} = 1; + } + $i++; +} +if ( @history and $history[-1]->{'hide'} ) { + # then everything is hidden + $history[-1]->{'balance_forward'} = 1; +} + +# then sort in user-pref order +if ( $curuser->option('history_order') eq 'newest' ) { + @history = sort { $b->{date} <=> $a->{date} } @history; +} # else it's already oldest-first, and there are no other options yet + sub translate_payby { my ($payby,$payinfo) = (shift,shift); my %payby = ( diff --git a/httemplate/view/cust_main/payment_history/attempted_batch_payment.html b/httemplate/view/cust_main/payment_history/attempted_batch_payment.html new file mode 100644 index 000000000..95947f512 --- /dev/null +++ b/httemplate/view/cust_main/payment_history/attempted_batch_payment.html @@ -0,0 +1,13 @@ +<I><% mt('Payment attempt') |h %> <% $info |h %></I> +<%init> + +my( $cust_pay_batch, %opt ) = @_; + +my ($payby,$payinfo) = translate_payinfo($cust_pay_batch); +$payby = translate_payby($payby,$payinfo); +my $info = $payby ? "($payby$payinfo)" : ''; + +$info .= ': '. $cust_pay_batch->error_message + if length($cust_pay_batch->error_message); + +</%init> diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html index f7c685c28..d735195fe 100644 --- a/httemplate/view/elements/svc_Common.html +++ b/httemplate/view/elements/svc_Common.html @@ -52,26 +52,39 @@ function areyousure(href) { <% mt('Service #') |h %><B><% $svcnum %></B> % my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?'; -| <& /view/elements/svc_edit_link.html, 'svc' => $svc_x, 'edit_url' => $url &> +<& /view/elements/svc_edit_link.html, 'svc' => $svc_x, 'edit_url' => $url &> <BR> <% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %> +% my @inventory_items = $svc_x->inventory_item; % foreach my $f ( @$fields ) { % -% my($field, $type, $value, $hack_strict_refs); +% my($field, $type, $value); % if ( ref($f) ) { % $field = $f->{'field'}; -% $hack_strict_refs = \&{ $f->{'value'} } if $f->{'value'}; -% $value = $f->{'value'} ? &$hack_strict_refs($svc_x) : $svc_x->$field; % $type = $f->{'type'} || 'text'; +% if ( $f->{'value_callback'} ) { +% my $hack_strict_refs = \&{ $f->{'value_callback'} }; +% $value = &$hack_strict_refs($svc_x); +% } else { +% $value = exists($f->{'value'}) ? $f->{'value'} : $svc_x->$field; +% } % } else { % $field = $f; -% $value = $svc_x->$field; % $type = 'text'; +% $value = $svc_x->$field; % } % % my $columndef = $part_svc->part_svc_column($field); +% if ( $columndef->columnflag =~ /^[MA]$/ && $columndef->columnvalue =~ /,/ ) +% { +% # inventory-select field with multiple classes +% # show the class name to disambiguate +% my ($item) = grep { $_->svc_field eq $field } @inventory_items; +% my $class = qsearchs('inventory_class', { classnum => $item->classnum }); +% $value .= ' <i>('. $class->classname . ')</i>' if $class; +% } % unless ($columndef->columnflag eq 'F' && !length($columndef->columnvalue)) { <TR> diff --git a/httemplate/view/elements/svc_devices.html b/httemplate/view/elements/svc_devices.html index d71c82f07..38c6d0919 100644 --- a/httemplate/view/elements/svc_devices.html +++ b/httemplate/view/elements/svc_devices.html @@ -12,91 +12,86 @@ ) </%doc> -<% $devices %> +%if ( @devices || $num_part_device || $table eq 'dsl_device' ) { +% my $svcnum = $svc_x->svcnum; + + Devices + (<A HREF="<%$p%>edit/<%$table%>.html?svcnum=<%$svcnum%>">Add device</A>) + <BR> + +% if ( @devices ) { + + <SCRIPT> + function areyousure(href) { + if (confirm("Are you sure you want to delete this device?") == true) + window.location.href = href; + } + </SCRIPT> + + <& /elements/table-grid.html &> + <TR> +% if ( $table eq 'phone_device' ) { + <TH CLASS="grid" BGCOLOR="#cccccc">Type</TH> +% } + <TH CLASS="grid" BGCOLOR="#cccccc">MAC Addr</TH> + <TH CLASS="grid" BGCOLOR="#cccccc"></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"></TH> + </TR> + +% my $bgcolor1 = '#eeeeee'; +% my $bgcolor2 = '#ffffff'; +% my $bgcolor = ''; +% +% foreach my $device ( @devices ) { +% +% if ( $bgcolor eq $bgcolor1 ) { +% $bgcolor = $bgcolor2; +% } else { +% $bgcolor = $bgcolor1; +% } +% +% my $td = qq(<TD CLASS="grid" BGCOLOR="$bgcolor">); +% +% my $devicenum = $device->devicenum; +% my $export_links = ''; +% $export_links = join( '<BR>', @{ $device->export_links } ) +% if $device->can('export_links'); + + <TR> +% if ( $table eq 'phone_device' ) { #$devices->can('part_device') + <% $td %><% $device->part_device->devicename |h %></TD> +% } + <% $td %><% $device->mac_addr %></TD> + <% $td %><% $export_links %></TD> + <% $td %>( +% unless ( $opt{'no_edit'} ) { + <A HREF="<%$p%>edit/<%$table%>.html?<%$devicenum%>">edit</A> | +% } + <A HREF="javascript:areyousure('<%$p%>misc/delete-<%$table%>.html?<%$devicenum%>')">delete</A> + )</TD> + </TR> +% } + </TABLE> + <BR> + +% } + <BR> +%} <%init> - my %opt = @_; - my $table = $opt{'table'}; #part_device, dsl_device - my $svc_x = $opt{'svc_x'}; - - my $devices = ''; - - my $num_part_device = 0; - if ( $table eq 'phone_device' ) { - my $sth = dbh->prepare("SELECT COUNT(*) FROM part_device") - #WHERE disabled = '' OR disabled IS NULL;"); - or die dbh->errstr; - $sth->execute or die $sth->errstr; - $num_part_device = $sth->fetchrow_arrayref->[0]; +my %opt = @_; +my $table = $opt{'table'}; #part_device, dsl_device +my $svc_x = $opt{'svc_x'}; + +my $num_part_device = 0; +if ( $table eq 'phone_device' ) { + my $sth = dbh->prepare("SELECT COUNT(*) FROM part_device") + #WHERE disabled = '' OR disabled IS NULL;"); + or die dbh->errstr; + $sth->execute or die $sth->errstr; + $num_part_device = $sth->fetchrow_arrayref->[0]; } - my @devices = $svc_x->$table(); - - #should move the below to proper mason code above instead of making $devices - if ( @devices || $num_part_device || $table eq 'dsl_device' ) { - my $svcnum = $svc_x->svcnum; - $devices .= - qq[Devices (<A HREF="${p}edit/$table.html?svcnum=$svcnum">Add device</A>)<BR>]; - if ( @devices ) { - - $devices .= qq! - <SCRIPT> - function areyousure(href) { - if (confirm("Are you sure you want to delete this device?") == true) - window.location.href = href; - } - </SCRIPT> - !; - - - $devices .= - include('/elements/table-grid.html'). - '<TR>'; - - $devices .= - '<TH CLASS="grid" BGCOLOR="#cccccc">Type</TH>' - if $table eq 'phone_device'; - - $devices .= - '<TH CLASS="grid" BGCOLOR="#cccccc">MAC Addr</TH>'. - '<TH CLASS="grid" BGCOLOR="#cccccc"></TH>'. - '<TH CLASS="grid" BGCOLOR="#cccccc"></TH>'. - '</TR>'; - my $bgcolor1 = '#eeeeee'; - my $bgcolor2 = '#ffffff'; - my $bgcolor = ''; - - foreach my $device ( @devices ) { - - if ( $bgcolor eq $bgcolor1 ) { - $bgcolor = $bgcolor2; - } else { - $bgcolor = $bgcolor1; - } - my $td = qq(<TD CLASS="grid" BGCOLOR="$bgcolor">); - - my $devicenum = $device->devicenum; - my $export_links = join( '<BR>', @{ $device->export_links } ) - if $device->can('export_links'); - - $devices .= '<TR>'; - $devices .= $td. $device->part_device->devicename. '</TD>' - if $table eq 'phone_device'; #$devices->can('part_device'); - - $devices .= $td. $device->mac_addr. '</TD>'. - $td. $export_links. '</TD>'. - "$td( "; - - $devices .= qq(<A HREF="${p}edit/$table.html?$devicenum">edit</A> | ) - unless $opt{'no_edit'}; - - $devices .= qq(<A HREF="javascript:areyousure('${p}misc/delete-$table.html?$devicenum')">delete</A>). - ' )</TD>'. - '</TR>'; - } - $devices .= '</TABLE><BR>'; - } - $devices .= '<BR>'; - } +my @devices = $svc_x->$table(); </%init> diff --git a/httemplate/view/elements/svc_edit_link.html b/httemplate/view/elements/svc_edit_link.html index d65db0a8f..5438ed266 100644 --- a/httemplate/view/elements/svc_edit_link.html +++ b/httemplate/view/elements/svc_edit_link.html @@ -7,8 +7,12 @@ function areyousure_delete() { window.location.href = '<% $cancel_url %>'; } </SCRIPT> -<A HREF="<% $edit_url %>"><% mt("Edit this [_1]", $label) |h %></A> | -<A HREF="javascript:areyousure_delete()"><% mt('Unprovision this Service') |h %></A> +% if ( $curuser->access_right('Provision customer service') ) { +| <A HREF="<% $edit_url %>"><% mt("Edit this [_1]", $label) |h %></A> +% } +% if ( $curuser->access_right('Unprovision customer service') ) { +| <A HREF="javascript:areyousure_delete()"><% mt('Unprovision this Service') |h %></A> +% } % } <%init> my %opt = @_; @@ -20,4 +24,5 @@ my $cancel_url = $p . 'misc/unprovision.cgi?' . $svc_x->svcnum; my $cust_svc = $svc_x->cust_svc; # always exists my $cancel_date = $cust_svc->pkg_cancel_date; my ($label) = $cust_svc->label; +my $curuser = $FS::CurrentUser::CurrentUser; </%init> diff --git a/httemplate/view/elements/svc_export_status.html b/httemplate/view/elements/svc_export_status.html index d96bb277d..4ce869e27 100644 --- a/httemplate/view/elements/svc_export_status.html +++ b/httemplate/view/elements/svc_export_status.html @@ -7,7 +7,15 @@ % foreach my $key ( sort {$a cmp $b} keys %$hashref ) { <TR> <TD ALIGN="right"><% $key |h %></TD> - <TD BGCOLOR="#ffffff"><% $hashref->{$key} |h %></TD> + <TD BGCOLOR="#ffffff"> +% if ( ref($hashref->{$key}) eq 'ARRAY' ) { +% foreach (@{ $hashref->{$key} }) { + <% $_ |h %><BR> +% } +% } else { + <% $hashref->{$key} |h %> +% } + </TD> </TR> % } diff --git a/httemplate/view/quotation-pdf.cgi b/httemplate/view/quotation-pdf.cgi new file mode 100755 index 000000000..7f62ce173 --- /dev/null +++ b/httemplate/view/quotation-pdf.cgi @@ -0,0 +1,29 @@ +<% $content %>\ +<%init> + +#false laziness w/elements/cust_bill-typeset + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Generate quotation'); #View quotations ? + +my $quotationnum = $cgi->param('quotationnum'); + +my $conf = new FS::Conf; + +my $quotation = qsearchs({ + 'select' => 'quotation.*', + 'table' => 'quotation', + #'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + 'hashref' => { 'quotationnum' => $quotationnum }, + #'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, +}); +die "Quotation #$quotationnum not found!" unless $quotation; + +my $content = $quotation->print_pdf(); #\%opt); + +http_header('Content-Type' => 'application/pdf'); +http_header('Content-Disposition' => "filename=$quotationnum.pdf" ); +http_header('Content-Length' => length($content) ); +http_header('Cache-control' => 'max-age=60' ); + +</%init> diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi index 199591356..858ccbe67 100755 --- a/httemplate/view/svc_acct.cgi +++ b/httemplate/view/svc_acct.cgi @@ -22,6 +22,7 @@ % } + <& svc_acct/radius_usage.html, 'svc_acct' => $svc_acct, 'part_svc' => $part_svc, @@ -29,6 +30,7 @@ %gopt, &> + <& svc_acct/change_svc_form.html, 'part_svc' => \@part_svc, 'svcnum' => $svcnum, @@ -37,13 +39,15 @@ &> <% mt('Service #') |h %><B><% $svcnum %></B> -| <& /view/elements/svc_edit_link.html, 'svc' => $svc_acct &> <& svc_acct/change_svc.html, 'part_svc' => \@part_svc, %gopt, &> +</FORM> + + <& svc_acct/basics.html, 'svc_acct' => $svc_acct, 'part_svc' => $part_svc, @@ -90,8 +94,12 @@ die "access denied" my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. ' LEFT JOIN cust_pkg USING ( pkgnum ) '. ' LEFT JOIN cust_main USING ( custnum ) '; - -my($query) = $cgi->keywords; +my $query; +if ( $cgi->keywords ) { + ($query) = $cgi->keywords; +} else { + $query = $cgi->param('svcnum'); +} $query =~ /^(\d+)$/; my $svcnum = $1; my $svc_acct = qsearchs({ diff --git a/httemplate/view/svc_acct/basics.html b/httemplate/view/svc_acct/basics.html index 2d9953fcc..04e7bcff8 100644 --- a/httemplate/view/svc_acct/basics.html +++ b/httemplate/view/svc_acct/basics.html @@ -20,7 +20,7 @@ % if ( $password =~ /^\*\w+\* (.*)$/ ) { % $password = $1; % $show_pw .= '<I>('. mt('login disabled') .')</I> '; -% } +% } % if ( ! $password % && $svc_acct->_password_encryption ne 'plain' % && $svc_acct->_password @@ -28,13 +28,27 @@ % { % $show_pw .= '<I>('. uc($svc_acct->_password_encryption). ' '.mt('encrypted').')</I>'; % } elsif ( $conf->exists('showpasswords') ) { -% $show_pw .= '<PRE>'. encode_entities($password). '</PRE>'; +% $show_pw .= '<SPAN >'. encode_entities($password). '</PRE>'; % } else { +% $password = ''; % $show_pw .= '<I>('. mt('hidden') .')</I>'; -% } -% $password = ''; -<& /view/elements/tr.html, label=>mt('Password'), value=>$show_pw &> - +% } +<TR> + <TD ALIGN="right"><% mt('Password') %></TD> + <TD STYLE="background-color: #ffffff; white-space: nowrap"> + <% $show_pw %> +% my $curuser = $FS::CurrentUser::CurrentUser; +% if ( $curuser->access_right('Provision customer service') or +% ($curuser->access_right('Edit password') and +% ! $part_svc->restrict_edit_password) ) +% { + <& /elements/change_password.html, + 'svc_acct' => $svc_acct, + 'curr_value' => $password, + &> +% } + </TD> +</TR> % if ( $conf->exists('security_phrase') ) { <& /view/elements/tr.html, label=>mt('Security phrase'), value=>$svc_acct->sec_phrase &> diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi index 75e673c4f..7d6520e57 100644 --- a/httemplate/view/svc_broadband.cgi +++ b/httemplate/view/svc_broadband.cgi @@ -26,23 +26,31 @@ $labels{'coordinates'} = 'Latitude/Longitude'; my @fields = ( 'description', - { field => 'routernum', value => \&router }, + { field => 'routernum', value_callback => \&router }, 'speed_down', 'speed_up', - { field => 'ip_addr', value => \&ip_addr }, - { field => 'sectornum', value => \§ornum }, - { field => 'mac_addr', value => \&mac_addr }, + { field => 'ip_addr', value_callback => \&ip_addr }, + { field => 'sectornum', value_callback => \§ornum }, + { field => 'mac_addr', value_callback => \&mac_addr }, #'latitude', #'longitude', - { field => 'coordinates', value => \&coordinates }, + { field => 'coordinates', value_callback => \&coordinates }, 'altitude', + + 'radio_serialnum', + 'radio_location', + 'poe_location', + 'rssi', + 'suid', + { field => 'shared_svcnum', value_callback=> \&shared_svcnum, }, #value_callback => + 'vlan_profile', 'authkey', 'plan_id', ); push @fields, - { field => 'usergroup', value => \&usergroup } + { field => 'usergroup', value_callback => \&usergroup } if $conf->exists('svc_broadband-radius'); sub router { @@ -112,9 +120,36 @@ sub coordinates { ); } +sub shared_svcnum { + my $svc_broadband = shift; + return '' unless $svc_broadband->shared_svcnum; + + my $shared_svc_broadband = + qsearchs('svc_broadband', { 'svcnum' => $svc_broadband->shared_svcnum, + } + #agent virt? + ) + or return ''; + my $shared_cust_pkg = $shared_svc_broadband->cust_svc->cust_pkg; + + $shared_svc_broadband->label. + ( $shared_cust_pkg + ? ' ('. $shared_cust_pkg->cust_main->name. ')' + : '' + ); +} + sub svc_callback { # trying to move to the callback style my ($cgi, $svc_x, $part_svc, $cust_pkg, $fields, $opt) = @_; + + if ( $part_svc->part_svc_column('latitude')->columnflag eq 'F' + && $part_svc->part_svc_column('longitude')->columnflag eq 'F' + ) + { + @$fields = grep { !ref($_) || $_->{field} ne 'coordinates' } @$fields; + } + # again, we assume at most one of these exports per part_svc my ($nas_export) = $part_svc->part_export('broadband_nas'); if ( $nas_export ) { diff --git a/httemplate/view/svc_cert.cgi b/httemplate/view/svc_cert.cgi index 0cd66b422..964b808ab 100644 --- a/httemplate/view/svc_cert.cgi +++ b/httemplate/view/svc_cert.cgi @@ -17,7 +17,7 @@ my %labels = map { $_ => ( ref($fields->{$_}) my @fields = ( { field=>'privatekey', - value=> sub { + value_callback=> sub { my $svc_cert = shift; if ( $svc_cert->privatekey && $svc_cert->check_privatekey ) { '<FONT COLOR="#33ff33">Verification OK</FONT>'; @@ -31,7 +31,7 @@ my @fields = ( qw( common_name organization organization_unit city state country cert_contact ), { 'field'=>'csr', - 'value'=> sub { + 'value_callback'=> sub { my $svc_cert = shift; if ( $svc_cert->csr ) { @@ -67,7 +67,7 @@ my @fields = ( }, }, { 'field'=>'certificate', - 'value'=> sub { + 'value_callback'=> sub { my $svc_cert = shift; if ( $svc_cert->certificate ) { @@ -137,7 +137,7 @@ my @fields = ( }, }, { 'field'=>'cacert', - 'value'=> sub { + 'value_callback'=> sub { my $svc_cert = shift; if ( $svc_cert->cacert ) { diff --git a/httemplate/view/svc_hardware.cgi b/httemplate/view/svc_hardware.cgi index 7f5e889d8..eef1c1140 100644 --- a/httemplate/view/svc_hardware.cgi +++ b/httemplate/view/svc_hardware.cgi @@ -13,17 +13,20 @@ my %labels = map { $_ => ( ref($fields->{$_}) : $fields->{$_} ); } keys %$fields; + +$labels{'display_hw_addr'} = 'Hardware address'; + my $model = { field => 'typenum', type => 'text', - value => sub { $_[0]->hardware_type->description } + value_callback => sub { $_[0]->hardware_type->description } }; my $status = { field => 'statusnum', type => 'text', - value => sub { $_[0]->status_label } + value_callback => sub { $_[0]->status_label } }; my $note = { field => 'note', type => 'text', - value => sub { encode_entities($_[0]->note) } + value_callback => sub { encode_entities($_[0]->note) } }; my @fields = ( diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi index 323be63dc..ed95c4cea 100644 --- a/httemplate/view/svc_phone.cgi +++ b/httemplate/view/svc_phone.cgi @@ -16,9 +16,20 @@ my %labels = map { $_ => ( ref($fields->{$_}) ); } keys %$fields; -my @fields = qw( countrycode phonenum ); +my @fields = qw( countrycode phonenum sim_imsi ); push @fields, 'domain' if $conf->exists('svc_phone-domain'); -push @fields, qw( pbx_title sip_password pin phone_name forwarddst email ); +push @fields, qw( pbx_title ); + +if ( $conf->exists('showpasswords') ) { + push @fields, qw( sip_password ); +} else { + push @fields, { 'field' => 'sip_password', #'_HIDDEN_sip_password', + 'type' => 'fixed', + 'value' => '<I>('. mt('hidden') .')</I>', + }; +} + +push @fields, qw( pin phone_name forwarddst email ); if ( $conf->exists('svc_phone-lnp') ) { push @fields, 'lnp_status', |
