1 <style type="text/css">
25 text-decoration: none;
26 border-top-left-radius: .5em;
27 border-top-right-radius: .5em;
30 #menu_ul a.current_show {
33 border-top: thin solid #7e0079;
34 border-left: thin solid #7e0079;
35 border-right: thin solid #7e0079;
36 border-bottom: thin solid #ffffff;
47 border: thin solid #7e0079;
50 box-shadow: #333333 1px 1px 2px;
61 background: transparent;
67 text-decoration: underline;
72 <script src="<% $p %>elements/jquery.js"></script>
73 <script type="text/javascript">
75 $(document).ready(function() {
77 function closemenu () {
78 if (openmenu !== undefined) {
83 $('#menu_ul > li').hover(function(){
85 openmenu = $('ul:first', this);
94 % foreach my $submenu (@processed_menu) {
98 % foreach my $link ( @$submenu ) {
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;
113 my %payby = map { $_ => 1 } $conf->config('payby');
115 # cached for conditions, to avoid looking it up twice
116 my $invoicing_list_emailonly = $cust_main->invoicing_list_emailonly;
118 # nice declarative menu; should be a parameter to some kind of menu generator
125 label => 'Edit customer',
126 url => "edit/cust_main.cgi?$custnum",
127 acl => 'Edit customer'
130 label => 'Edit contacts',
131 url => "edit/cust_main-contacts.html?$custnum",
136 acl => 'Bill customer now',
137 content => sub { include( '/elements/bill.html',
138 label => emt('Bill now'),
139 url => $cgi->self_url,
140 custnum => shift->custnum,
146 popup => "misc/suspend_cust.html?custnum=$custnum",
147 acl => 'Suspend customer',
148 condition => sub { shift->unsuspended_pkgs > 0 },
149 actionlabel => 'Confirm Suspension',
153 label => 'Unsuspend',
154 popup => "misc/unsuspend_cust.html?custnum=$custnum",
155 acl => 'Unsuspend customer',
156 condition => sub { shift->suspended_pkgs > 0 },
157 actionlabel => 'Confirm Unsuspension',
161 popup => "misc/suspend_cust.html?custnum=$custnum",
162 acl => 'Cancel customer',
163 condition => sub { shift->ncancelled_pkgs > 0 },
164 actionlabel => 'Confirm Cancellation',
169 popup => "misc/merge_cust.html?custnum=$custnum",
170 acl => 'Merge customer',
171 actionlabel => 'Merge customer',
176 label => 'Refer a new customer',
177 url => "edit/cust_main.cgi?referral_custnum=$custnum",
178 confexists => '!disable_customer_referrals',
180 # should have a separator here
182 label => 'View this customer\'s referrals',
183 url => "search/cust_main.cgi?referral_custnum=$custnum",
184 confexists => '!disable_customer_referrals',
186 FS::cust_main->count('referral_custnum = ?', shift->custnum) > 0
190 label => 'View billing events',
191 url => "search/cust_event.html?custnum=$custnum",
192 acl => [ 'Billing event reports',
193 'View customer billing events' ],
196 label => 'Email a notice to this customer',
198 my $cust_main = shift;
199 my $agentnum = $cust_main->agentnum;
200 'misc/email-customers.html?table=cust_main;'.
201 'agent_virt_agentnum='.$agentnum.";custnum=$custnum;url=".
202 uri_escape($cgi->self_url);
204 condition => sub { $invoicing_list_emailonly },
205 acl => 'Bulk send customer notices',
215 popup => "edit/cust_main_note.cgi?custnum=$custnum",
216 actionlabel => 'Add note',
217 confexists => '!cust_main-disable_notes',
218 acl => 'Add customer note',
223 label => 'Attach file',
224 popup => "edit/cust_main_attach.cgi?custnum=$custnum",
225 actionlabel => 'Upload file',
226 confexists => '!disable_cust_attachment',
227 acl => 'Add attachment',
236 confexists => 'ticket_system'
241 label => 'Appointments',
242 show => 'appointments',
243 confexists => 'ticket_system',
244 acl => 'View appointments',
247 label => 'Schedule new appointment',
248 confexists => 'ticket_system',
249 acl => 'Make appointment',
250 popup => "elements/make_appointment.html?custnum=$custnum",
251 actionlabel => 'Schedule appointment',
256 label => 'Quotations',
257 show => 'quotations',
260 label => 'Create new quotation',
261 url => "edit/quotation.html?custnum=$custnum",
262 acl => 'Generate quotation',
271 label => 'New qualification',
272 popup => "misc/qual.html?custnum=$custnum",
273 actionlabel => 'New qualification',
277 acl => 'Qualify service',
280 label => 'Order new package',
281 popup => "misc/order_pkg.html?custnum=$custnum",
282 actionlabel => 'Order new package',
286 acl => 'Order customer package',
289 # it's just a popup, but there's some freaky CCH tax stuff in it
290 label => 'One-time charge',
292 include( '/elements/one_time_charge_link.html',
293 custnum => shift->custnum,
296 acl => 'One-time charge',
299 label => 'Move services between packages',
300 popup => "edit/bulk-cust_svc-pkgnum.html?custnum=$custnum",
301 actionlabel => 'Move services',
304 acl => 'Bulk move customer services',
307 label => 'Bulk order and cancel packages',
308 url => "edit/cust_pkg.cgi?$custnum",
309 acl => 'Bulk change customer packages',
313 label => 'Package reports',
314 url => "search/report_cust_pkg?custnum=$custnum",
317 label => 'View qualifications',
318 url => "search/qual.cgi?custnum=$custnum",
319 acl => 'Qualify service',
322 label => 'View accounts',
323 url => "search/report_svc_acct.html?custnum=$custnum",
326 label => 'View CDRs',
327 url => "search/report_cdr.html?custnum=$custnum",
332 label => 'Payment History',
333 show => 'payment_history',
335 # manual payment entry via edit/cust_pay
337 label => 'Enter check payment',
338 popup => "edit/cust_pay.cgi?popup=1;payby=BILL;custnum=$custnum",
339 actionlabel => 'Enter check payment',
342 acl => [ 'Post payment', 'Post check payment' ],
343 condition => sub { $payby{BILL} },
346 label => 'Enter cash payment',
347 popup => "edit/cust_pay.cgi?popup=1;payby=CASH;custnum=$custnum",
348 actionlabel => 'Enter cash payment',
351 acl => [ 'Post payment', 'Post cash payment' ],
352 condition => sub { $payby{CASH} },
355 label => 'Enter Western Union payment',
356 popup => "edit/cust_pay.cgi?popup=1;payby=WEST;custnum=$custnum",
357 actionlabel => 'Enter Western Union payment',
360 acl => [ 'Post payment', ],
361 condition => sub { $payby{WEST} },
364 label => 'Post manual (offline/POS) credit card payment',
365 popup => "edit/cust_pay.cgi?popup=1;payby=MCRD;custnum=$custnum",
366 actionlabel => 'Enter credit card payment',
369 acl => [ 'Post payment', ],
370 condition => sub { $payby{MCRD} },
373 label => 'Post manual (offline/POS) electronic check',
374 popup => "edit/cust_pay.cgi?popup=1;payby=MCHK;custnum=$custnum",
375 actionlabel => 'Enter credit card payment',
378 acl => [ 'Post payment', ],
379 condition => sub { $payby{MCHK} },
381 # realtime payments via payment.cgi
383 label => 'Process credit card payment',
384 url => "misc/payment.cgi?payby=CARD;custnum=$custnum",
385 acl => [ 'Process payment', 'Process credit card payment', ],
386 condition => sub { $payby{CARD} or $payby{DCRD} },
389 label => 'Process electronic check payment',
390 url => "misc/payment.cgi?payby=CHEK;custnum=$custnum",
391 acl => [ 'Process payment', 'Process Echeck payment', ],
392 condition => sub { $payby{CHEK} or $payby{DCHK} },
396 label => 'Enter credit',
397 popup => "edit/cust_credit.cgi?custnum=$custnum",
398 actionlabel => 'Enter credit',
400 acl => 'Post credit',
403 label => 'Credit line items',
404 popup => "edit/credit-cust_bill_pkg.html?custnum=$custnum",
405 actionlabel => 'Credit line items',
408 acl => 'Credit line items',
410 FS::cust_bill->count('custnum = ?', shift->custnum) > 0
414 label => 'Enter check refund',
415 popup => "edit/cust_refund.cgi?popup=1;payby=BILL;custnum=$custnum",
416 actionlabel => 'Enter check refund',
418 acl => ['Post refund', 'Post check refund'],
419 condition => sub { $payby{BILL} },
422 label => 'Enter cash refund',
423 popup => "edit/cust_refund.cgi?popup=1;payby=CASH;custnum=$custnum",
424 actionlabel => 'Enter cash refund',
426 acl => ['Post refund', 'Post cash refund'],
427 condition => sub { $payby{CASH} },
430 label => 'Enter manual (offline/POS) credit card refund',
431 popup => "edit/cust_refund.cgi?popup=1;payby=MCRD;custnum=$custnum",
432 actionlabel => 'Enter credit card refund',
434 acl => ['Post refund' ],
435 condition => sub { $payby{MCRD} },
438 label => 'Enter manual (offline/POS) electronic check refund',
439 popup => "edit/cust_refund.cgi?popup=1;payby=MCHK;custnum=$custnum",
440 actionlabel => 'Enter electronic check refund',
442 acl => ['Post refund' ],
443 condition => sub { $payby{MCHK} },
446 label => 'Add tax adjustment',
447 popup => "edit/cust_tax_adjustment.html?custnum=$custnum",
448 actionlabel => 'Add tax adjustment',
450 confexists => 'enable_tax_adjustments',
451 acl => 'Add customer tax adjustment',
453 # separator, definitely
455 label => 'Download PDF statement',
456 url => "view/cust_main_statement-pdf.cgi?$custnum",
457 acl => 'View legacy typeset statements',
459 FS::cust_bill->count('custnum = ?', shift->custnum) > 0
463 label => 'Search invoices',
464 url => "search/report_cust_bill.html?custnum=$custnum",
465 acl => 'List invoices',
468 label => 'View tax exemptions',
469 url => "search/cust_tax_exempt_pkg.cgi?custnum=$custnum",
470 acl => 'View customer tax exemptions',
473 label => 'View tax adjustments',
474 url => "search/cust_tax_adjustment.html?custnum=$custnum",
475 confexists => 'enable_tax_adjustments',
476 acl => 'Add customer tax adjustment',
479 label => 'View pending payments',
480 url => "search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=$custnum",
481 acl => 'View pending payments',
483 FS::cust_pay_pending->count('custnum = ?', shift->custnum) > 0
487 label => 'Email statement to this customer',
489 my $cust_main = shift;
490 my $agentnum = $cust_main->agentnum;
491 'misc/email-customer-statement.html?table=cust_main;'.
492 'agent_virt_agentnum='.$agentnum.";custnum=$custnum;url=".
493 uri_escape($cgi->self_url);
495 condition => sub { $invoicing_list_emailonly },
496 acl => 'Resend invoices',
501 label => 'Change History',
502 show => 'change_history',
503 acl => 'View customer history',
510 foreach my $submenu (@menu) {
514 foreach my $entry ( @$submenu ) {
515 # if the menu head was skipped, skip the whole menu
516 last if (!$first and !@links);
520 if ( $entry->{acl} ) {
521 next unless $curuser->access_right( $entry->{acl} );
523 if ( $entry->{confexists} ) {
524 if ( $entry->{confexists} =~ /^!(.*)/ ) {
525 # confexists => !foo, a negative condition
526 next if $conf->exists( $1 );
528 next unless $conf->exists( $entry->{confexists} );
531 if ( $entry->{condition} ) {
532 next unless &{ $entry->{condition} }($cust_main);
535 my $label = emt($entry->{label});
536 my $target = $entry->{content}
540 if ( ref($target) eq 'CODE' ) {
541 $target = &$target($cust_main);
545 if ( $entry->{content} ) { # then the coderef specified the whole thing
548 } elsif ( $entry->{show} ) {
550 # the menu head: always a link back to this page
551 $cgi->param('show', $entry->{show});
552 $target = $cgi->self_url;
554 $a = qq[ <A HREF="$target"];
555 if ( $opt{'show'} eq $entry->{show} ) {
556 $a .= ' class="current_show"';
558 $a .= qq[>$label</A> ];
561 } elsif ( $entry->{popup} ) {
563 $target =~ s/\$custnum/$custnum/g;
564 $target = $p.$target;
565 $a = include('/elements/popup_link.html',
570 label => emt($label),
573 } elsif ( $entry->{url} ) {
575 $target =~ s/\$custnum/$custnum/g;
576 $target = $p.$target;
577 $a = qq[ <A HREF="$target">$label</A> ];
584 push @processed_menu, \@links;