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;search_hash='.
201 'agent_virt_agentnum='.$agentnum.";custnum=$custnum";
203 condition => sub { $invoicing_list_emailonly },
204 acl => 'Bulk send customer notices',
214 popup => "edit/cust_main_note.cgi?custnum=$custnum",
215 actionlabel => 'Add note',
216 confexists => '!cust_main-disable_notes',
217 acl => 'Add customer note',
222 label => 'Attach file',
223 popup => "edit/cust_main_attach.cgi?custnum=$custnum",
224 actionlabel => 'Upload file',
225 confexists => '!disable_cust_attachment',
226 acl => 'Add attachment',
235 confexists => 'ticket_system'
240 label => 'Appointments',
241 show => 'appointments',
242 confexists => 'ticket_system',
243 acl => 'View appointments',
246 label => 'Schedule new appointment',
247 confexists => 'ticket_system',
248 acl => 'Make appointment',
249 popup => "elements/make_appointment.html?custnum=$custnum",
250 actionlabel => 'Schedule appointment',
255 label => 'Quotations',
256 show => 'quotations',
259 label => 'Create new quotation',
260 url => "edit/quotation.html?custnum=$custnum",
261 acl => 'Generate quotation',
270 label => 'New qualification',
271 popup => "misc/qual.html?custnum=$custnum",
272 actionlabel => 'New qualification',
276 acl => 'Qualify service',
279 label => 'Order new package',
280 popup => "misc/order_pkg.html?custnum=$custnum",
281 actionlabel => 'Order new package',
285 acl => 'Order customer package',
288 # it's just a popup, but there's some freaky CCH tax stuff in it
289 label => 'One-time charge',
291 include( '/elements/one_time_charge_link.html',
292 custnum => shift->custnum,
295 acl => 'One-time charge',
298 label => 'Move services between packages',
299 popup => "edit/bulk-cust_svc-pkgnum.html?custnum=$custnum",
300 actionlabel => 'Move services',
303 acl => 'Bulk move customer services',
306 label => 'Bulk order and cancel packages',
307 url => "edit/cust_pkg.cgi?$custnum",
308 acl => 'Bulk change customer packages',
312 label => 'Package reports',
313 url => "search/report_cust_pkg?custnum=$custnum",
316 label => 'View qualifications',
317 url => "search/qual.cgi?custnum=$custnum",
318 acl => 'Qualify service',
321 label => 'View accounts',
322 url => "search/report_svc_acct.html?custnum=$custnum",
325 label => 'View CDRs',
326 url => "search/report_cdr.html?custnum=$custnum",
331 label => 'Payment History',
332 show => 'payment_history',
334 # manual payment entry via edit/cust_pay
336 label => 'Enter check payment',
337 popup => "edit/cust_pay.cgi?popup=1;payby=BILL;custnum=$custnum",
338 actionlabel => 'Enter check payment',
341 acl => [ 'Post payment', 'Post check payment' ],
342 condition => sub { $payby{BILL} },
345 label => 'Enter cash payment',
346 popup => "edit/cust_pay.cgi?popup=1;payby=CASH;custnum=$custnum",
347 actionlabel => 'Enter cash payment',
350 acl => [ 'Post payment', 'Post cash payment' ],
351 condition => sub { $payby{CASH} },
354 label => 'Enter Western Union payment',
355 popup => "edit/cust_pay.cgi?popup=1;payby=WEST;custnum=$custnum",
356 actionlabel => 'Enter Western Union payment',
359 acl => [ 'Post payment', ],
360 condition => sub { $payby{WEST} },
363 label => 'Post manual (offline/POS) credit card payment',
364 popup => "edit/cust_pay.cgi?popup=1;payby=MCRD;custnum=$custnum",
365 actionlabel => 'Enter credit card payment',
368 acl => [ 'Post payment', ],
369 condition => sub { $payby{MCRD} },
372 label => 'Post manual (offline/POS) electronic check',
373 popup => "edit/cust_pay.cgi?popup=1;payby=MCHK;custnum=$custnum",
374 actionlabel => 'Enter credit card payment',
377 acl => [ 'Post payment', ],
378 condition => sub { $payby{MCHK} },
380 # realtime payments via payment.cgi
382 label => 'Process credit card payment',
383 url => "misc/payment.cgi?payby=CARD;custnum=$custnum",
384 acl => [ 'Process payment', 'Process credit card payment', ],
385 condition => sub { $payby{CARD} or $payby{DCRD} },
388 label => 'Process electronic check payment',
389 url => "misc/payment.cgi?payby=CHEK;custnum=$custnum",
390 acl => [ 'Process payment', 'Process Echeck payment', ],
391 condition => sub { $payby{CHEK} or $payby{DCHK} },
395 label => 'Enter credit',
396 popup => "edit/cust_credit.cgi?custnum=$custnum",
397 actionlabel => 'Enter credit',
399 acl => 'Post credit',
402 label => 'Credit line items',
403 popup => "edit/credit-cust_bill_pkg.html?custnum=$custnum",
404 actionlabel => 'Credit line items',
407 acl => 'Credit line items',
409 FS::cust_bill->count('custnum = ?', shift->custnum) > 0
413 label => 'Enter check refund',
414 popup => "edit/cust_refund.cgi?popup=1;payby=BILL;custnum=$custnum",
415 actionlabel => 'Enter check refund',
417 acl => ['Post refund', 'Post check refund'],
418 condition => sub { $payby{BILL} },
421 label => 'Enter cash refund',
422 popup => "edit/cust_refund.cgi?popup=1;payby=CASH;custnum=$custnum",
423 actionlabel => 'Enter cash refund',
425 acl => ['Post refund', 'Post cash refund'],
426 condition => sub { $payby{CASH} },
429 label => 'Enter manual (offline/POS) credit card refund',
430 popup => "edit/cust_refund.cgi?popup=1;payby=MCRD;custnum=$custnum",
431 actionlabel => 'Enter credit card refund',
433 acl => ['Post refund' ],
434 condition => sub { $payby{MCRD} },
437 label => 'Enter manual (offline/POS) electronic check refund',
438 popup => "edit/cust_refund.cgi?popup=1;payby=MCHK;custnum=$custnum",
439 actionlabel => 'Enter electronic check refund',
441 acl => ['Post refund' ],
442 condition => sub { $payby{MCHK} },
445 label => 'Add tax adjustment',
446 popup => "edit/cust_tax_adjustment.html?custnum=$custnum",
447 actionlabel => 'Add tax adjustment',
449 confexists => 'enable_tax_adjustments',
450 acl => 'Add customer tax adjustment',
452 # separator, definitely
454 label => 'Download statement',
455 url => "view/cust_main_statement-pdf.cgi?$custnum",
456 acl => 'List invoices',
458 FS::cust_bill->count('custnum = ?', shift->custnum) > 0
462 label => 'Search invoices',
463 url => "search/report_cust_bill.html?custnum=$custnum",
464 acl => 'List invoices',
467 label => 'View tax exemptions',
468 url => "search/cust_tax_exempt_pkg.cgi?custnum=$custnum",
469 acl => 'View customer tax exemptions',
472 label => 'View tax adjustments',
473 url => "search/cust_tax_adjustment.html?custnum=$custnum",
474 confexists => 'enable_tax_adjustments',
475 acl => 'Add customer tax adjustment',
478 label => 'View pending payments',
479 url => "search/cust_pay_pending.html?magic=_date;statusNOT=done;custnum=$custnum",
480 acl => 'View pending payments',
482 FS::cust_pay_pending->count('custnum = ?', shift->custnum) > 0
486 label => 'Email payment history to this customer',
488 my $cust_main = shift;
489 my $agentnum = $cust_main->agentnum;
490 'misc/email-customers-history.html?table=cust_main;search_hash='.
491 'agent_virt_agentnum='.$agentnum.";custnum=$custnum;url=".
492 uri_escape($cgi->self_url);
494 condition => sub { $invoicing_list_emailonly },
495 acl => 'Bulk send customer notices',
500 label => 'Change History',
501 show => 'change_history',
502 acl => 'View customer history',
509 foreach my $submenu (@menu) {
513 foreach my $entry ( @$submenu ) {
514 # if the menu head was skipped, skip the whole menu
515 last if (!$first and !@links);
519 if ( $entry->{acl} ) {
520 next unless $curuser->access_right( $entry->{acl} );
522 if ( $entry->{confexists} ) {
523 if ( $entry->{confexists} =~ /^!(.*)/ ) {
524 # confexists => !foo, a negative condition
525 next if $conf->exists( $1 );
527 next unless $conf->exists( $entry->{confexists} );
530 if ( $entry->{condition} ) {
531 next unless &{ $entry->{condition} }($cust_main);
534 my $label = emt($entry->{label});
535 my $target = $entry->{content}
539 if ( ref($target) eq 'CODE' ) {
540 $target = &$target($cust_main);
544 if ( $entry->{content} ) { # then the coderef specified the whole thing
547 } elsif ( $entry->{show} ) {
549 # the menu head: always a link back to this page
550 $cgi->param('show', $entry->{show});
551 $target = $cgi->self_url;
553 $a = qq[ <A HREF="$target"];
554 if ( $opt{'show'} eq $entry->{show} ) {
555 $a .= ' class="current_show"';
557 $a .= qq[>$label</A> ];
560 } elsif ( $entry->{popup} ) {
562 $target =~ s/\$custnum/$custnum/g;
563 $target = $p.$target;
564 $a = include('/elements/popup_link.html',
569 label => emt($label),
572 } elsif ( $entry->{url} ) {
574 $target =~ s/\$custnum/$custnum/g;
575 $target = $p.$target;
576 $a = qq[ <A HREF="$target">$label</A> ];
583 push @processed_menu, \@links;