diff options
author | ivan <ivan> | 2009-07-28 21:17:45 +0000 |
---|---|---|
committer | ivan <ivan> | 2009-07-28 21:17:45 +0000 |
commit | e1b1693a656964c6db0b8a3fb85494014434dcb1 (patch) | |
tree | b53273d34ecc10bb8ac3a63b97c2723dc919469a /httemplate/view | |
parent | cd2241d7ea1ce53a626adfd58a908cfd822c618c (diff) |
adding a basic change history using history tables, RT#1005, RT#4357
Diffstat (limited to 'httemplate/view')
-rwxr-xr-x | httemplate/view/cust_main.cgi | 12 | ||||
-rw-r--r-- | httemplate/view/cust_main/change_history.html | 302 |
2 files changed, 311 insertions, 3 deletions
diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 88fd03713..78bcb1fc1 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -113,6 +113,7 @@ Comments % if ( ! $conf->exists('cust_main-disable_notes') || $notecount) { % unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) { + <BR> <A NAME="cust_main_note"><FONT SIZE="+2">Notes</FONT></A><BR> % } @@ -180,6 +181,10 @@ Comments % } +% if ( $view eq 'change_history' ) { # || $view eq 'jumbo' + <% include('cust_main/change_history.html', $cust_main ) %> +% } + <% include('/elements/footer.html') %> <%init> @@ -213,11 +218,12 @@ tie my %views, 'Tie::IxHash', 'Notes' => 'notes', #notes and files? ; $views{'Tickets'} = 'tickets' - if $conf->config('ticket_system'); + if $conf->config('ticket_system'); $views{'Packages'} = 'packages'; $views{'Payment History'} = 'payment_history' - unless $conf->config('payby-default' eq 'HIDE'); -#$views{'Change History'} = ''; + unless $conf->config('payby-default' eq 'HIDE'); +$views{'Change History'} = 'change_history' + if $curuser->access_right('View customer history'); $views{'Jumbo'} = 'jumbo'; my %viewname = reverse %views; diff --git a/httemplate/view/cust_main/change_history.html b/httemplate/view/cust_main/change_history.html new file mode 100644 index 000000000..1700bc34b --- /dev/null +++ b/httemplate/view/cust_main/change_history.html @@ -0,0 +1,302 @@ +% if ( int( time - (keys %years)[0] * 31556736 ) > $start ) { + Show: +% my $chy = $cgi->param('change_history-years'); +% foreach my $y (keys %years) { +% if ( $y == $years ) { + <FONT SIZE="+1"><% $years{$y} %></FONT> +% } else { +% $cgi->param('change_history-years', $y); + <A HREF="<% $cgi->self_url %>"><% $years{$y} %></A> +% } +% last if int( time - $y * 31556736 ) < $start; +% } +% $cgi->param('change_history-years', $chy); +% } + +<% include("/elements/table-grid.html") %> +% my $bgcolor1 = '#eeeeee'; +% my $bgcolor2 = '#ffffff'; +% my $bgcolor = ''; + +<TR> + <TH CLASS="grid" BGCOLOR="#cccccc">User</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Date</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Time</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Item</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Action</TH> + <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 +% ) +% { +% +% my $history_other = ''; +% my $act = $item->history_action; +% if ( $act =~ /^replace/ ) { +% my $pkey = $item->primary_key; +% my $date = $item->history_date; +% $history_other = qsearchs({ +% 'table' => $item->table, +% 'hashref' => { $pkey => $item->$pkey(), +% 'history_action' => $replace_other{$act}, +% 'historynum' => { 'op' => $replace_dir{$act}, +% 'value' => $item->historynum +% }, +% }, +% 'extra_sql' => " +% AND history_date $replace_direq{$act} $date +% AND ($date $replace_op{$act} $fuzz) $replace_direq{$act} history_date +% ORDER BY historynum $replace_ord{$act} LIMIT 1 +% ", +% }); +% } +% +% if ( $bgcolor eq $bgcolor1 ) { +% $bgcolor = $bgcolor2; +% } else { +% $bgcolor = $bgcolor1; +% } + + <TR> + <TD ALIGN="left" CLASS="grid" BGCOLOR="<% $bgcolor %>"> +% my $otaker = $item->history_user; +% $otaker = '<i>auto billing</i>' if $otaker eq 'fs_daily'; +% $otaker = '<i>customer self-service</i>' if $otaker eq 'fs_selfservice'; +% $otaker = '<i>job queue</i>' if $otaker eq 'fs_queue'; + <% $otaker %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>"> +% my $d = time2str('%b %o, %Y', $item->history_date ); +% $d =~ s/ / /g; + <% $d %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>"> +% my $t = time2str('%r', $item->history_date ); +% $t =~ s/ / /g; + <% $t %> + </TD> + <TD ALIGN="center" CLASS="grid" BGCOLOR="<% $bgcolor %>"> +% my $label = $h_tables{$item->table}; +% $label = &{ $h_table_labelsub{$item->table} }( $item, $label ) +% if $h_table_labelsub{$item->table}; + <% $label %> + </TD> + <TD ALIGN="left" CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $action{$item->history_action} %> + </TD> + <TD ALIGN="left" CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% join(', ', + map { my $value = ( $_ =~ /(^pay(info|cvv)|^ss|_password)$/ ) + ? 'N/A' + : $item->get($_); + $value = substr($value, 0, 77).'...' if length($value) > 80; + $value = encode_entities($value); + "<I>$_</I>:<B>$value</B>"; + } + grep { $history_other + ? ( $item->get($_) ne $history_other->get($_) ) + : ( $item->get($_) =~ /\S/ ) + } + grep { ! /^(history|custnum$)/i } + $item->fields + ) + %> + </TD> + </TR> + +% } + +</TABLE> +<%once> + +# length-switching + +tie my %years, 'Tie::IxHash', + .5 => '6 months', + 1 => '1 year', + 2 => '2 years', + 5 => '5 years', + 39 => 'all history', +; + +# labeling history rows + +my %action = ( + 'insert' => 'Insert', #'Create', + 'replace_old' => 'Change from', + 'replace_new' => 'Change to', + 'delete' => 'Remove', +); + +# finding the other replace row + +my %replace_other = ( + 'replace_new' => 'replace_old', + 'replace_old' => 'replace_new', +); +my %replace_dir = ( + 'replace_new' => '<', + 'replace_old' => '>', +); +my %replace_direq = ( + 'replace_new' => '<=', + 'replace_old' => '>=', +); +my %replace_op = ( + 'replace_new' => '-', + 'replace_old' => '+', +); +my %replace_ord = ( + 'replace_new' => 'DESC', + 'replace_old' => 'ASC', +); + +my $fuzz = 5; #seems like a lot + +# which tables to search and what to call them + +tie my %tables, 'Tie::IxHash', + 'cust_main' => 'Customer', + 'cust_main_invoice' => 'Invoice destination', + 'cust_pkg' => 'Package', + #? or just svc_* ? 'cust_svc' => + 'svc_acct' => 'Account', + 'radius_usergroup' => 'RADIUS group', + 'svc_domain' => 'Domain', + 'svc_www' => 'Hosting', + 'svc_forward' => 'Mail forward', + 'svc_broadband' => 'Broadband', + 'svc_external' => 'External service', + 'svc_phone' => 'Phone', + 'phone_device' => 'Phone device', + #? it gets provisioned anyway 'phone_avail' => 'Phone', +; + +my $svc_join = 'JOIN cust_svc USING ( svcnum ) JOIN cust_pkg USING ( pkgnum )'; + +my %table_join = ( + 'svc_acct' => $svc_join, + 'radius_usergroup' => $svc_join, + 'svc_domain' => $svc_join, + 'svc_www' => $svc_join, + 'svc_forward' => $svc_join, + 'svc_broadband' => $svc_join, + 'svc_external' => $svc_join, + 'svc_phone' => $svc_join, + 'phone_device' => $svc_join, +); + +my %h_tables = map { ( "h_$_" => $tables{$_} ) } keys %tables; + +my %pkgpart = (); +my $pkg_labelsub = sub { + my($item, $label) = @_; + $pkgpart{$item->pkgpart} ||= $item->part_pkg->pkg; + $label. ': <b>'. encode_entities($pkgpart{$item->pkgpart}). '</b>'; +}; + +my $svc_labelsub = sub { + my($item, $label) = @_; + $label. ': <b>'. encode_entities($item->label). '</b>'; +}; + +my %h_table_labelsub = ( + 'h_cust_pkg' => $pkg_labelsub, + 'h_svc_acct' => $svc_labelsub, + #'h_radius_usergroup' => + 'h_svc_domain' => $svc_labelsub, + 'h_svc_www' => $svc_labelsub, + 'h_svc_forward' => $svc_labelsub, + 'h_svc_broadband' => $svc_labelsub, + 'h_svc_external' => $svc_labelsub, + 'h_svc_phone' => $svc_labelsub, + #'h_phone_device' +); + +# cust_main +# cust_main_invoice + +# cust_pkg +# cust_pkg_option? +# cust_pkg_detail +# cust_pkg_reason? no + +#cust_svc +#cust_svc_option? +#svc_* +# svc_acct +# radius_usergroup +# acct_snarf? is this even used? +# svc_domain +# domain_record +# registrar +# svc_forward +# svc_www +# svc_broadband +# (virtual fields? eh... maybe when they're real) +# svc_external +# svc_phone +# phone_device +# phone_avail + +# future: + +# inventory_item (from services) +# pkg_referral? (changed?) + +#random others: + +# cust_location? +# cust_main-exemption?? (295.ca named tax exemptions) + +</%once> +<%init> + +my( $cust_main ) = @_; + +my $conf = new FS::Conf; + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access deined" + unless $curuser->access_right('View customer history'); + +# find out the beginning of this customer history, if possible +my $h_insert = qsearchs({ + 'table' => 'h_cust_main', + 'hashref' => { 'custnum' => $cust_main->custnum, + 'history_action' => 'insert', + }, + 'extra_sql' => 'ORDER BY historynum LIMIT 1', +}); +my $start = $h_insert ? $h_insert->history_date : 0; + +# retreive the history + +my @history = (); + +my $years = $conf->config('change_history-years') || .5; +if ( $cgi->param('change_history-years') =~ /^([\d\.]+)$/ ) { + $years = $1; +} +my $newer_than = int( time - $years * 31556736 ); #60*60*24*365.24 + +local($FS::Record::nowarn_classload) = 1; + +foreach my $table ( keys %tables ) { + my @items = qsearch({ + 'table' => "h_$table", + 'addl_from' => $table_join{$table}, + 'hashref' => { 'history_date' => { op=>'>=', value=>$newer_than }, }, + 'extra_sql' => ' AND custnum = '. $cust_main->custnum, + }); + push @history, @items; + +} + +</%init> |