UI spring cleaning: customer menu
[freeside.git] / httemplate / view / cust_main / menu.html
1 <style type="text/css">
2 #menu_ul {
3   padding: 0;
4   margin: .5em 0 0 0;
5   font-size: smaller;
6 }
7
8 #menu_ul li {
9   margin: 0;
10   float: left;
11   list-style: none;
12   position: relative;
13 }
14
15 #menu_ul a {
16   display: block;
17   margin-left: 0;
18   margin-right: 1em;
19   margin-bottom: -1px;
20   margin-top: 0;
21   padding: .5em .75em;
22   background: #e0e0e0;
23   color: #525151;
24   white-space: nowrap;
25   text-decoration: none;
26   border-top-left-radius: .5em;
27   border-top-right-radius: .5em;
28 }
29
30 #menu_ul a.current_show {
31   font-weight: bold;
32   background: #FFFFFF;
33   border-top: thin solid #7e0079;
34   border-left: thin solid #7e0079;
35   border-right: thin solid #7e0079;
36   border-bottom: thin solid #ffffff;
37 }
38
39 #menu_ul ul {
40   margin:0;
41   padding:0;
42   display:none;
43   position: absolute;
44   top: 100%;
45   left: 0;
46   background: #ffffff;
47   border: thin solid #7e0079;
48   z-index:8888;
49   border-radius: 2px;
50   box-shadow: #333333 1px 1px 2px;
51 }
52
53 #menu_ul ul li {
54   margin: 0;
55   padding: 0;
56   float: none;
57 }
58
59 #menu_ul ul a {
60   color: #333333;
61   background: transparent;
62   border-bottom: none;
63   border-radius: 0;
64 }
65
66 #menu_ul a:hover {
67   text-decoration: underline;
68   color: #7e0079;
69 }
70
71 </style>
72 <script src="<% $p %>elements/jquery.js"></script>
73 <script type="text/javascript">
74
75 $(document).ready(function() {
76         var openmenu;
77         function closemenu () {
78                 if (openmenu !== undefined) {
79                         openmenu.hide();
80                         openmenu = undefined;
81                 }
82         }               
83         $('#menu_ul > li').hover(function(){
84                 closemenu();
85                 openmenu = $('ul:first', this);
86                 openmenu.show();
87         }, function(){
88                 closemenu();
89         });
90 });
91 </script>
92
93 <ul id="menu_ul">
94 % foreach my $submenu (@processed_menu) {
95   <li>
96     <% shift @$submenu %>
97     <ul>
98 %   foreach my $link ( @$submenu ) {
99       <li><% $link %></li>
100 %   }
101     </ul>
102   </li>
103 % }
104 </ul>
105
106 <%init>
107 my %opt = @_;
108 my $cust_main = $opt{'cust_main'};
109 my $custnum = $cust_main->custnum;
110 my $curuser = $FS::CurrentUser::CurrentUser;
111 my $conf = FS::Conf->new;
112
113 my %payby = map { $_ => 1 } $conf->config('payby');
114
115 # nice declarative menu; should be a parameter to some kind of menu generator
116 my @menu = ( 
117   [
118     { show        => 'basics',
119       label       => 'Basics',
120     },
121     {
122       label       => 'Edit customer',
123       url         => "edit/cust_main.cgi?$custnum",
124       acl         => 'Edit customer'
125     },
126     {
127       label       => 'Edit contacts',
128       url         => "edit/cust_main-contacts.html?$custnum",
129     },
130 # separator
131     {
132       label       => 'Bill now',
133       acl         => 'Bill customer now',
134       content     => sub { include( '/elements/bill.html',
135                               label   => emt('Bill now'),
136                               url     => $cgi->self_url,
137                               custnum => shift->custnum,
138                            ),
139                      },
140     },
141     {
142       label       => 'Suspend',
143       popup       => "misc/suspend_cust.html?custnum=$custnum",
144       acl         => 'Suspend customer',
145       condition   => sub { shift->unsuspended_pkgs > 0 },
146       actionlabel => 'Confirm Suspension',
147       color       => '#ff9900',
148     },
149     {
150       label       => 'Unsuspend',
151       popup       => "misc/unsuspend_cust.html?custnum=$custnum",
152       acl         => 'Unsuspend customer',
153       condition   => sub { shift->suspended_pkgs > 0 },
154       actionlabel => 'Confirm Unsuspension',
155     },
156     {
157       label       => 'Cancel',
158       popup       => "misc/suspend_cust.html?custnum=$custnum",
159       acl         => 'Cancel customer',
160       condition   => sub { shift->ncancelled_pkgs > 0 },
161       actionlabel => 'Confirm Cancellation',
162       color       => '#ff0000',
163     },
164     {
165       label       => 'Merge',
166       popup       => "misc/merge_cust.html?custnum=$custnum",
167       acl         => 'Merge customer',
168       actionlabel => 'Merge customer',
169       width       => 569,
170       height      => 210,
171     },
172     {
173       label       => 'Refer a new customer',
174       url         => "edit/cust_main.cgi?referral_custnum=$custnum",
175       confexists  => '!disable_customer_referrals',
176     },
177 # should have a separator here
178     {
179       label       => 'View this customer\'s referrals',
180       url         => "search/cust_main.cgi?referral_custnum=$custnum",
181       confexists  => '!disable_customer_referrals',
182       condition   => sub {
183         FS::cust_main->count('referral_custnum = ?', shift->custnum) > 0
184       },
185     },
186     {
187       label       => 'View billing events',
188       url         => "search/cust_event.html?custnum=$custnum",
189       acl         => [ 'Billing event reports',
190                        'View customer billing events' ],
191     },
192     {
193       label       => 'Email a notice to this customer',
194       url         => sub {
195                       my $cust_main = shift;
196                       my $agentnum = $cust_main->agentnum;
197                       'misc/email-customers.html?table=cust_main;search_hash='.
198                       'agent_virt_agentnum='.$agentnum.";custnum=$custnum";
199                      },
200       condition   => sub { shift->invoicing_list_emailonly },
201     },
202   ],
203   [
204     {
205       label => 'Notes',
206       show  => 'notes',
207     },
208     {
209       label       => 'Add note',
210       popup       => "edit/cust_main_note.cgi?custnum=$custnum",
211       actionlabel => 'Add note',
212       confexists  => '!cust_main-disable_notes',
213       acl         => 'Add customer note',
214       width       => 616,
215       height      => 538,
216     },
217     {
218       label       => 'Attach file',
219       popup       => "edit/cust_main_attach.cgi?custnum=$custnum",
220       actionlabel => 'Upload file',
221       confexists  => '!disable_cust_attachment',
222       acl         => 'Add attachment',
223       width       => 480,
224       height      => 296,
225     },
226   ],
227   [
228     {
229       label => 'Tickets',
230       show  => 'tickets',
231       confexists => 'ticket_system'
232     },
233   ],
234   [
235     {
236       label => 'Appointments',
237       show  => 'appointments',
238       confexists => 'ticket_system',
239       acl   => 'View appointments',
240     },
241     {
242       label       => 'Schedule new appointment',
243       confexists  => 'ticket_system',
244       acl        => 'Make appointment',
245       popup       => "elements/make_appointment.html?custnum=$custnum",
246       actionlabel => 'Schedule appointment',
247     },
248   ],
249   [
250     {
251       label => 'Quotations',
252       show  => 'quotations',
253     },
254     {
255       label => 'Create new quotation',
256       url   => "edit/quotation.html?custnum=$custnum",
257       acl   => 'Generate quotation',
258     },
259   ],
260   [
261     {
262       label => 'Packages',
263       show  => 'packages',
264     },
265     {
266       label       => 'New qualification',
267       popup       => "misc/qual.html?custnum=$custnum",
268       actionlabel => 'New qualification',
269       color       => '#333399',
270       width       => 763,
271       height      => 436,
272       acl         => 'Qualify service',
273     },
274     {
275       label       => 'Order new package',
276       popup       => "misc/order_pkg.html?custnum=$custnum",
277       actionlabel => 'Order new package',
278       color       => '#333399',
279       width       => 960,
280       height      => 740,
281       acl         => 'Order customer package',
282     },
283     {
284       # it's just a popup, but there's some freaky CCH tax stuff in it
285       label       => 'One-time charge',
286       content     => sub {
287                       include( '/elements/one_time_charge_link.html',
288                         custnum => shift->custnum,
289                       );
290                      },
291       acl         => 'One-time charge',
292     },
293     {
294       label       => 'Move services between packages',
295       popup       => "edit/bulk-cust_svc-pkgnum.html?custnum=$custnum",
296       actionlabel => 'Move services',
297       width       => 968,
298       height      => 575,
299       acl         => 'Bulk move customer services',
300     },
301     {
302       label       => 'Bulk order and cancel packages',
303       url         => "edit/cust_pkg.cgi?$custnum",
304       acl         => 'Bulk change customer packages',
305     },
306 # separator
307     {
308       label => 'Package reports',
309       url   => "search/report_cust_pkg?custnum=$custnum",
310     },
311     {
312       label => 'View qualifications',
313       url   => "search/qual.cgi?custnum=$custnum",
314       acl   => 'Qualify service',
315     },
316     {
317       label => 'View accounts',
318       url   => "search/report_svc_acct.html?custnum=$custnum",
319     },
320     {
321       label => 'View CDRs',
322       url   => "search/report_cdr.html?custnum=$custnum",
323     },
324   ],
325   [
326     {
327       label => 'Payment History',
328       show  => 'payment_history',
329     },
330     # manual payment entry via edit/cust_pay
331     {
332       label       => 'Enter check payment',
333       popup       => "edit/cust_pay.cgi?popup=1;payby=BILL;custnum=$custnum",
334       actionlabel => 'Enter check payment',
335       width       => 763,
336       height      => 392,
337       acl         => [ 'Post payment', 'Post check payment' ],
338       condition   => sub { $payby{BILL} },
339     },
340     {
341       label       => 'Enter cash payment',
342       popup       => "edit/cust_pay.cgi?popup=1;payby=CASH;custnum=$custnum",
343       actionlabel => 'Enter cash payment',
344       width       => 763,
345       height      => 392,
346       acl         => [ 'Post payment', 'Post cash payment' ],
347       condition   => sub { $payby{CASH} },
348     },
349     {
350       label       => 'Enter Western Union payment',
351       popup       => "edit/cust_pay.cgi?popup=1;payby=WEST;custnum=$custnum",
352       actionlabel => 'Enter Western Union payment',
353       width       => 763,
354       height      => 392,
355       acl         => [ 'Post payment', ],
356       condition   => sub { $payby{WEST} },
357     },
358     {
359       label       => 'Post manual (offline/POS) credit card payment',
360       popup       => "edit/cust_pay.cgi?popup=1;payby=MCRD;custnum=$custnum",
361       actionlabel => 'Enter credit card payment',
362       width       => 763,
363       height      => 392,
364       acl         => [ 'Post payment', ],
365       condition   => sub { $payby{MCRD} },
366     },
367     {
368       label       => 'Post manual (offline/POS) electronic check',
369       popup       => "edit/cust_pay.cgi?popup=1;payby=MCHK;custnum=$custnum",
370       actionlabel => 'Enter credit card payment',
371       width       => 763,
372       height      => 392,
373       acl         => [ 'Post payment', ],
374       condition   => sub { $payby{MCHK} },
375     },
376     # realtime payments via payment.cgi
377     {
378       label       => 'Process credit card payment',
379       url         => "misc/payment.cgi?payby=CARD;custnum=$custnum",
380       acl         => [ 'Process payment', 'Process credit card payment', ],
381       condition   => sub { $payby{CARD} or $payby{DCRD} },
382     },
383     {
384       label       => 'Process electronic check payment',
385       url         => "misc/payment.cgi?payby=CHEK;custnum=$custnum",
386       acl         => [ 'Process payment', 'Process Echeck payment', ],
387       condition   => sub { $payby{CHEK} or $payby{DCHK} },
388     },
389 #separator?
390     {
391       label       => 'Enter credit',
392       popup       => "edit/cust_credit.cgi?custnum=$custnum",
393       actionlabel => 'Enter credit',
394       width       => 763,
395       acl         => 'Post credit',
396     },
397     {
398       label       => 'Credit line items',
399       popup       => "edit/credit-cust_bill_pkg.html?custnum=$custnum",
400       actionlabel => 'Credit line items',
401       width       => 968,
402       height      => 575,
403       acl         => 'Credit line items',
404       condition   => sub {
405         FS::cust_bill->count('custnum = ?', shift->custnum) > 0
406       },
407     },
408     {
409       label       => 'Enter check refund',
410       popup       => "edit/cust_refund.cgi?popup=1;payby=BILL;custnum=$custnum",
411       actionlabel => 'Enter check refund',
412       width       => 440,
413       acl         => ['Post refund', 'Post check refund'],
414       condition   => sub { $payby{BILL} },
415     },
416     {
417       label       => 'Enter cash refund',
418       popup       => "edit/cust_refund.cgi?popup=1;payby=CASH;custnum=$custnum",
419       actionlabel => 'Enter cash refund',
420       width       => 392,
421       acl         => ['Post refund', 'Post cash refund'],
422       condition   => sub { $payby{CASH} },
423     },
424     {
425       label       => 'Enter manual (offline/POS) credit card refund',
426       popup       => "edit/cust_refund.cgi?popup=1;payby=MCRD;custnum=$custnum",
427       actionlabel => 'Enter credit card refund',
428       width       => 440,
429       acl         => ['Post refund' ],
430       condition   => sub { $payby{MCRD} },
431     },
432     {
433       label       => 'Enter manual (offline/POS) electronic check refund',
434       popup       => "edit/cust_refund.cgi?popup=1;payby=MCHK;custnum=$custnum",
435       actionlabel => 'Enter electronic check refund',
436       width       => 440,
437       acl         => ['Post refund' ],
438       condition   => sub { $payby{MCHK} },
439     },
440     {
441       label       => 'Add tax adjustment',
442       popup       => "edit/cust_tax_adjustment.html?custnum=$custnum",
443       actionlabel => 'Add tax adjustment',
444       height      => 200,
445       confexists  => 'enable_tax_adjustments',
446       acl         => 'Add customer tax adjustment',
447     },
448 # separator, definitely
449     {
450       label       => 'Download statement',
451       url         => "view/cust_main_statement-pdf.cgi?$custnum",
452       acl         => 'List invoices',
453       condition   => sub {
454         FS::cust_bill->count('custnum = ?', shift->custnum) > 0
455       },
456     },
457     {
458       label       => 'Search invoices',
459       url         => "search/report_cust_bill.html?custnum=$custnum",
460       acl         => 'List invoices',
461     },
462     {
463       label       => 'View tax exemptions',
464       url         => "search/cust_tax_exempt_pkg.cgi?custnum=$custnum",
465       acl         => 'View customer tax exemptions',
466     },
467     {
468       label       => 'View tax adjustments',
469       url         => "search/cust_tax_adjustment.html?custnum=$custnum",
470       confexists  => 'enable_tax_adjustments',
471       acl         => 'Add customer tax adjustment',
472     },
473     {
474       label       => 'View pending payments',
475       url         => "search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=$custnum",
476       acl         => 'View pending payments',
477       condition   => sub { 
478         FS::cust_pay_pending->count('custnum = ?', shift->custnum) > 0
479       },
480     },
481   ],
482   [
483     {
484       label => 'Change History',
485       show  => 'change_history',
486       acl   => 'View customer history',
487     },
488   ],
489 );
490
491
492 my @processed_menu;
493 foreach my $submenu (@menu) {
494
495   my @links;
496   my $first = 1;
497   foreach my $entry ( @$submenu ) {
498     # if the menu head was skipped, skip the whole menu
499     last if (!$first and !@links);
500     $first = 0;
501
502     # check conditions
503     if ( $entry->{acl} ) {
504       next unless $curuser->access_right( $entry->{acl} );
505     }
506     if ( $entry->{confexists} ) {
507       if ( $entry->{confexists} =~ /^!(.*)/ ) {
508         # confexists => !foo, a negative condition
509         next if $conf->exists( $1 );
510       } else {
511         next unless $conf->exists( $entry->{confexists} );
512       }
513     }
514     if ( $entry->{condition} ) {
515       next unless &{ $entry->{condition} }($cust_main);
516     }
517
518     my $label = emt($entry->{label});
519     my $target = $entry->{content}
520               || $entry->{popup}
521               || $entry->{url};
522
523     if ( ref($target) eq 'CODE' ) {
524       $target = &$target($cust_main);
525     }
526     my $a = '';
527
528     if ( $entry->{content} ) { # then the coderef specified the whole thing
529       $a = $target;
530
531     } elsif ( $entry->{show} ) {
532
533       # the menu head: always a link back to this page
534       $cgi->param('show', $entry->{show});
535             $target = $cgi->self_url;
536
537       $a = qq[ <A HREF="$target"];
538       if ( $opt{'show'} eq $entry->{show} ) {
539         $a .= ' class="current_show"';
540       }
541       $a .= qq[>$label</A> ];
542
543
544     } elsif ( $entry->{popup} ) {
545
546       $target =~ s/\$custnum/$custnum/g;
547       $target = $p.$target;
548       $a = include('/elements/popup_link.html',
549         action  => $target,
550         width   => 616,
551         height  => 410,
552         %$entry,
553         label   => emt($label),
554       );
555
556     } elsif ( $entry->{url} ) {
557
558       $target =~ s/\$custnum/$custnum/g;
559       $target = $p.$target;
560       $a = qq[ <A HREF="$target">$label</A> ];
561     }
562
563     push @links, $a;
564
565   } # foreach $entry
566   if (@links) {
567     push @processed_menu, \@links;
568   }
569 }
570 </%init>