diff options
Diffstat (limited to 'httemplate/edit')
43 files changed, 4024 insertions, 0 deletions
diff --git a/httemplate/edit/REAL_cust_pkg.cgi b/httemplate/edit/REAL_cust_pkg.cgi new file mode 100755 index 000000000..abfaac3fc --- /dev/null +++ b/httemplate/edit/REAL_cust_pkg.cgi @@ -0,0 +1,82 @@ +<!-- mason kludge --> +<% +# <!-- $Id: REAL_cust_pkg.cgi,v 1.2 2002-02-10 16:05:22 ivan Exp $ --> + +my $error =''; +my $pkgnum = ''; +if ( $cgi->param('error') ) { +  $error = $cgi->param('error'); +  $pkgnum = $cgi->param('pkgnum'); +} else { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/ or die "no pkgnum"; +  $pkgnum = $1; +} + +#get package record +my $cust_pkg = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); +die "No package!" unless $cust_pkg; +my $part_pkg = qsearchs('part_pkg',{'pkgpart'=>$cust_pkg->getfield('pkgpart')}); + +if ( $error ) { +  #$cust_pkg->$_(str2time($cgi->param($_)) foreach qw(setup bill); +  $cust_pkg->setup(str2time($cgi->param('setup'))); +  $cust_pkg->bill(str2time($cgi->param('bill'))); +} + +#my $custnum = $cust_pkg->getfield('custnum'); +print header('Package Edit'); #, menubar( +#  "View this customer (#$custnum)" => popurl(2). "view/cust_main.cgi?$custnum", +#  'Main Menu' => popurl(2) +#)); + +#print info +my($susp,$cancel,$expire)=( +  $cust_pkg->getfield('susp'), +  $cust_pkg->getfield('cancel'), +  $cust_pkg->getfield('expire'), +); +my($pkg,$comment)=($part_pkg->getfield('pkg'),$part_pkg->getfield('comment')); +my($setup,$bill)=($cust_pkg->getfield('setup'),$cust_pkg->getfield('bill')); +my $otaker = $cust_pkg->getfield('otaker'); + +print '<FORM NAME="formname" ACTION="process/REAL_cust_pkg.cgi" METHOD="POST">',      qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!; + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT>! +  if $error; + +print &ntable("#cccccc"), '<TR><TD>', &ntable("#cccccc",2), +      '<TR><TD ALIGN="right">Package number</TD><TD BGCOLOR="#ffffff">', +      $pkgnum, '</TD></TR>', +      '<TR><TD ALIGN="right">Package</TD><TD BGCOLOR="#ffffff">', +      $pkg,  '</TD></TR>', +      '<TR><TD ALIGN="right">Comment</TD><TD BGCOLOR="#ffffff">', +      $comment,  '</TD></TR>', +      '<TR><TD ALIGN="right">Order taker</TD><TD BGCOLOR="#ffffff">', +      $otaker,  '</TD></TR>', +      '<TR><TD ALIGN="right">Setup date</TD><TD>'. +      '<INPUT TYPE="text" NAME="setup" SIZE=32 VALUE="', +      ( $setup ? time2str("%c %z (%Z)",$setup) : "" ), '"></TD></TR>', +      '<TR><TD ALIGN="right">Next bill date</TD><TD>', +      '<INPUT TYPE="text" NAME="bill" SIZE=32 VALUE="', +      ( $bill ? time2str("%c %z (%Z)",$bill) : "" ), '"></TD></TR>', +; + +print '<TR><TD ALIGN="right">Suspension date</TD><TD BGCOLOR="#ffffff">', +       time2str("%D",$susp), '</TD></TR>' +  if $susp; + +print '<TR><TD ALIGN="right">Expiration date</TD><TD BGCOLOR="#ffffff">', +       time2str("%D",$expire), '</TD></TR>' +  if $expire; + +print '<TR><TD ALIGN="right">Cancellation date</TD><TD BGCOLOR="#ffffff">', +       time2str("%D",$cancel), '</TD></TR>' +  if $cancel; + +%> +</TABLE></TD></TR></TABLE>'. +<BR><INPUT TYPE="submit" VALUE="Apply Changes"> +</FORM> +</BODY> +</HTML> diff --git a/httemplate/edit/agent.cgi b/httemplate/edit/agent.cgi new file mode 100755 index 000000000..3fca34326 --- /dev/null +++ b/httemplate/edit/agent.cgi @@ -0,0 +1,74 @@ +<!-- mason kludge --> +<% + +my $agent; +if ( $cgi->param('error') ) { +  $agent = new FS::agent ( { +    map { $_, scalar($cgi->param($_)) } fields('agent') +  } ); +} elsif ( $cgi->keywords ) { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $agent = qsearchs( 'agent', { 'agentnum' => $1 } ); +} else { #adding +  $agent = new FS::agent {}; +} +my $action = $agent->agentnum ? 'Edit' : 'Add'; +my $hashref = $agent->hashref; + +print header("$action Agent", menubar( +  'Main Menu' => $p, +  'View all agents' => $p. 'browse/agent.cgi', +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print '<FORM ACTION="', popurl(1), 'process/agent.cgi" METHOD=POST>', +      qq!<INPUT TYPE="hidden" NAME="agentnum" VALUE="$hashref->{agentnum}">!, +      "Agent #", $hashref->{agentnum} ? $hashref->{agentnum} : "(NEW)"; + +print &ntable("#cccccc", 2, ''), <<END; +<TR> +  <TH ALIGN="right">Agent</TH> +  <TD><INPUT TYPE="text" NAME="agent" SIZE=32 VALUE="$hashref->{agent}"></TD> +</TR> +<TR> +  <TH ALIGN="right">Agent type</TH> +  <TD><SELECT NAME="typenum" SIZE=1> +END + +foreach my $agent_type (qsearch('agent_type',{})) { +  print "<OPTION VALUE=". $agent_type->typenum; +  print " SELECTED" +    if $hashref->{typenum} && ( $hashref->{typenum} == $agent_type->typenum ); +  print ">", $agent_type->getfield('typenum'), ": ", +        $agent_type->getfield('atype'),"\n"; +} + +print <<END; +</SELECT></TD> +</TR> +<TR> +  <TD ALIGN="right">Frequency (unimplemented)</TD> +  <TD><INPUT TYPE="text" NAME="freq" VALUE="$hashref->{freq}"></TD> +</TR> +<TR> +  <TD ALIGN="right">Program (unimplemented)</TD> +  <TD><INPUT TYPE="text" NAME="prog" VALUE="$hashref->{prog}"></TD> +</TR> +</TABLE> +END + +print qq!<BR><INPUT TYPE="submit" VALUE="!, +      $hashref->{agentnum} ? "Apply changes" : "Add agent", +      qq!">!; + +print <<END; +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/agent_type.cgi b/httemplate/edit/agent_type.cgi new file mode 100755 index 000000000..4a4cd9a47 --- /dev/null +++ b/httemplate/edit/agent_type.cgi @@ -0,0 +1,63 @@ +<!-- mason kludge --> +<% + +my($agent_type); +if ( $cgi->param('error') ) { +  $agent_type = new FS::agent_type ( { +    map { $_, scalar($cgi->param($_)) } fields('agent') +  } ); +} elsif ( $cgi->keywords ) { #editing +  my( $query ) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $agent_type=qsearchs('agent_type',{'typenum'=>$1}); +} else { #adding +  $agent_type = new FS::agent_type {}; +} +my $action = $agent_type->typenum ? 'Edit' : 'Add'; +my $hashref = $agent_type->hashref; + +print header("$action Agent Type", menubar( +  'Main Menu' => "$p", +  'View all agent types' => "${p}browse/agent_type.cgi", +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print '<FORM ACTION="', popurl(1), 'process/agent_type.cgi" METHOD=POST>', +      qq!<INPUT TYPE="hidden" NAME="typenum" VALUE="$hashref->{typenum}">!, +      "Agent Type #", $hashref->{typenum} ? $hashref->{typenum} : "(NEW)"; + +print <<END; +<BR><BR>Agent Type <INPUT TYPE="text" NAME="atype" SIZE=32 VALUE="$hashref->{atype}"> +<BR><BR>Select which packages agents of this type may sell to customers<BR> +END + +foreach my $part_pkg ( qsearch('part_pkg',{ 'disabled' => '' }) ) { +  print qq!<BR><INPUT TYPE="checkbox" NAME="pkgpart!, +        $part_pkg->getfield('pkgpart'), qq!" !, +       # ( 'CHECKED 'x scalar( +        qsearchs('type_pkgs',{ +          'typenum' => $agent_type->getfield('typenum'), +          'pkgpart'  => $part_pkg->getfield('pkgpart'), +        }) +          ? 'CHECKED ' +          : '', +        qq!VALUE="ON"> !, +    qq!<A HREF="${p}edit/part_pkg.cgi?!, $part_pkg->pkgpart,  +    '">', $part_pkg->getfield('pkg'), '</A>', +  ; +} + +print qq!<BR><BR><INPUT TYPE="submit" VALUE="!, +      $hashref->{typenum} ? "Apply changes" : "Add agent type", +      qq!">!; + +print <<END; +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_bill_pay.cgi b/httemplate/edit/cust_bill_pay.cgi new file mode 100755 index 000000000..d90659724 --- /dev/null +++ b/httemplate/edit/cust_bill_pay.cgi @@ -0,0 +1,96 @@ +<!-- mason kludge --> +<% + +my($paynum, $amount, $invnum); +if ( $cgi->param('error') ) { +  $paynum = $cgi->param('paynum'); +  $amount = $cgi->param('amount'); +  $invnum = $cgi->param('invnum'); +} else { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $paynum = $1; +  $amount = ''; +  $invnum = ''; +} + +my $otaker = getotaker; + +my $p1 = popurl(1); + +print header("Apply Payment", ''); +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT><BR><BR>" +  if $cgi->param('error'); +print <<END; +    <FORM ACTION="${p1}process/cust_bill_pay.cgi" METHOD=POST> +END + +my $cust_pay = qsearchs('cust_pay', { 'paynum' => $paynum } ); +die "payment $paynum not found!" unless $cust_pay; + +my $unapplied = $cust_pay->unapplied; + +print "Payment # <B>$paynum</B>". +      qq!<INPUT TYPE="hidden" NAME="paynum" VALUE="$paynum">!. +      '<BR>Date: <B>'. time2str("%D", $cust_pay->_date). '</B>'. +      '<BR>Amount: $<B>'. $cust_pay->paid. '</B>'. +      "<BR>Unapplied amount: \$<B>$unapplied</B>" +      ; + +my @cust_bill = grep $_->owed != 0, +                qsearch('cust_bill', { 'custnum' => $cust_pay->custnum } ); + +print <<END; +<SCRIPT> +function changed(what) { +  cust_bill = what.options[what.selectedIndex].value; +END + +foreach my $cust_bill ( @cust_bill ) { +  my $invnum = $cust_bill->invnum; +  my $changeto = $cust_bill->owed < $unapplied +                   ? $cust_bill->owed  +                   : $unapplied; +  print <<END; +  if ( cust_bill == $invnum ) { +    what.form.amount.value = "$changeto"; +  } +END +} + +#print <<END; +#  if ( cust_bill == "Refund" ) { +#    what.form.amount.value = "$credited"; +#  } +#} +#</SCRIPT> +#END +print "</SCRIPT>\n"; + +print qq!<BR>Invoice #<SELECT NAME="invnum" SIZE=1 onChange="changed(this)">!, +      '<OPTION VALUE="">'; +foreach my $cust_bill ( @cust_bill ) { +  print '<OPTION'. ( $cust_bill->invnum eq $invnum ? ' SELECTED' : '' ). +        ' VALUE="'. $cust_bill->invnum. '">'. $cust_bill->invnum. +        ' -  '. time2str("%D",$cust_bill->_date). +        ' - $'. $cust_bill->owed; +} +#print qq!<OPTION VALUE="Refund">Refund!; +print "</SELECT>"; + +print qq!<BR>Amount \$<INPUT TYPE="text" NAME="amount" VALUE="$amount" SIZE=8 MAXLENGTH=8>!; + +print <<END; +<BR> +<INPUT TYPE="submit" VALUE="Apply"> +END + +print <<END; + +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi new file mode 100755 index 000000000..aae0df2fc --- /dev/null +++ b/httemplate/edit/cust_credit.cgi @@ -0,0 +1,63 @@ +<!-- mason kludge --> +<% + +my $conf = new FS::Conf; +my($custnum, $amount, $reason); +if ( $cgi->param('error') ) { +  #$cust_credit = new FS::cust_credit ( { +  #  map { $_, scalar($cgi->param($_)) } fields('cust_credit') +  #} ); +  $custnum = $cgi->param('custnum'); +  $amount = $cgi->param('amount'); +  #$refund = $cgi->param('refund'); +  $reason = $cgi->param('reason'); +} else { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $custnum = $1; +  $amount = ''; +  #$refund = 'yes'; +  $reason = ''; +} +my $_date = time; + +my $otaker = getotaker; + +my $p1 = popurl(1); + +print header("Post Credit", ''); +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); +print <<END, small_custview($custnum, $conf->config('countrydefault')); +    <FORM ACTION="${p1}process/cust_credit.cgi" METHOD=POST> +    <INPUT TYPE="hidden" NAME="crednum" VALUE=""> +    <INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum"> +    <INPUT TYPE="hidden" NAME="paybatch" VALUE=""> +    <INPUT TYPE="hidden" NAME="_date" VALUE="$_date"> +    <INPUT TYPE="hidden" NAME="credited" VALUE=""> +    <INPUT TYPE="hidden" NAME="otaker" VALUE="$otaker"> +END + +print '<BR><BR>Credit'. ntable("#cccccc", 2). +      '<TR><TD ALIGN="right">Date</TD><TD BGCOLOR="#ffffff">'. +      time2str("%D",$_date).  '</TD></TR>'; + +print qq!<TR><TD ALIGN="right">Amount</TD><TD BGCOLOR="#ffffff">\$<INPUT TYPE="text" NAME="amount" VALUE="$amount" SIZE=8 MAXLENGTH=8></TD></TR>!; + +#print qq! <INPUT TYPE="checkbox" NAME="refund" VALUE="$refund">Also post refund!; + +print qq!<TR><TD ALIGN="right">Reason</TD><TD BGCOLOR="#ffffff"><INPUT TYPE="text" NAME="reason" VALUE="$reason"></TD></TR>!; + +print qq!<TR><TD ALIGN="right">Auto-apply<BR>to invoices</TD><TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED>yes<OPTION>no</SELECT></TD>!; + +print <<END; +</TABLE> +<BR> +<INPUT TYPE="submit" VALUE="Post credit"> +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_credit_bill.cgi b/httemplate/edit/cust_credit_bill.cgi new file mode 100755 index 000000000..1a97e1312 --- /dev/null +++ b/httemplate/edit/cust_credit_bill.cgi @@ -0,0 +1,101 @@ +<!-- mason kludge --> +<% + +my($crednum, $amount, $invnum); +if ( $cgi->param('error') ) { +  #$cust_credit_bill = new FS::cust_credit_bill ( { +  #  map { $_, scalar($cgi->param($_)) } fields('cust_credit_bill') +  #} ); +  $crednum = $cgi->param('crednum'); +  $amount = $cgi->param('amount'); +  #$refund = $cgi->param('refund'); +  $invnum = $cgi->param('invnum'); +} else { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $crednum = $1; +  $amount = ''; +  #$refund = 'yes'; +  $invnum = ''; +} + +my $otaker = getotaker; + +my $p1 = popurl(1); + +print header("Apply Credit", ''); +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT><BR><BR>" +  if $cgi->param('error'); +print <<END; +    <FORM ACTION="${p1}process/cust_credit_bill.cgi" METHOD=POST> +END + +my $cust_credit = qsearchs('cust_credit', { 'crednum' => $crednum } ); +die "credit $crednum not found!" unless $cust_credit; + +my $credited = $cust_credit->credited; + +print "Credit # <B>$crednum</B>". +      qq!<INPUT TYPE="hidden" NAME="crednum" VALUE="$crednum">!. +      '<BR>Date: <B>'. time2str("%D", $cust_credit->_date). '</B>'. +      '<BR>Amount: $<B>'. $cust_credit->amount. '</B>'. +      "<BR>Unapplied amount: \$<B>$credited</B>". +      '<BR>Reason: <B>'. $cust_credit->reason. '</B>' +      ; + +my @cust_bill = grep $_->owed != 0, +                qsearch('cust_bill', { 'custnum' => $cust_credit->custnum } ); + +print <<END; +<SCRIPT> +function changed(what) { +  cust_bill = what.options[what.selectedIndex].value; +END + +foreach my $cust_bill ( @cust_bill ) { +  my $invnum = $cust_bill->invnum; +  my $changeto = $cust_bill->owed < $cust_credit->credited +                   ? $cust_bill->owed  +                   : $cust_credit->credited; +  print <<END; +  if ( cust_bill == $invnum ) { +    what.form.amount.value = "$changeto"; +  } +END +} + +print <<END; +  if ( cust_bill == "Refund" ) { +    what.form.amount.value = "$credited"; +  } +} +</SCRIPT> +END + +print qq!<BR>Invoice #<SELECT NAME="invnum" SIZE=1 onChange="changed(this)">!, +      '<OPTION VALUE="">'; +foreach my $cust_bill ( @cust_bill ) { +  print '<OPTION'. ( $cust_bill->invnum eq $invnum ? ' SELECTED' : '' ). +        ' VALUE="'. $cust_bill->invnum. '">'. $cust_bill->invnum. +        ' -  '. time2str("%D",$cust_bill->_date). +        ' - $'. $cust_bill->owed; +} +print qq!<OPTION VALUE="Refund">Refund!; +print "</SELECT>"; + +print qq!<BR>Amount \$<INPUT TYPE="text" NAME="amount" VALUE="$amount" SIZE=8 MAXLENGTH=8>!; + +print <<END; +<BR> +<INPUT TYPE="submit" VALUE="Apply"> +END + +print <<END; + +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi new file mode 100755 index 000000000..41643a37f --- /dev/null +++ b/httemplate/edit/cust_main.cgi @@ -0,0 +1,454 @@ +<!-- mason kludge --> +<% + +  #for misplaced logic below +  #use FS::part_pkg; + +  #for false laziness below (now more properly lazy) +  #use FS::svc_acct_pop; + +  #for (other) false laziness below +  #use FS::agent; +  #use FS::type_pkgs; + +my $conf = new FS::Conf; + +#get record + +my $error = ''; +my($custnum, $username, $password, $popnum, $cust_main, $saved_pkgpart); +if ( $cgi->param('error') ) { +  $error = $cgi->param('error'); +  $cust_main = new FS::cust_main ( { +    map { $_, scalar($cgi->param($_)) } fields('cust_main') +  } ); +  $custnum = $cust_main->custnum; +  $saved_pkgpart = $cgi->param('pkgpart_svcpart') || ''; +  if ( $saved_pkgpart =~ /^(\d+)_/ ) { +    $saved_pkgpart = $1; +  } else { +    $saved_pkgpart = ''; +  } +  $username = $cgi->param('username'); +  $password = $cgi->param('_password'); +  $popnum = $cgi->param('popnum'); +} elsif ( $cgi->keywords ) { #editing +  my( $query ) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $custnum=$1; +  $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); +  $saved_pkgpart = 0; +  $username = ''; +  $password = ''; +  $popnum = 0; +} else { +  $custnum=''; +  $cust_main = new FS::cust_main ( {} ); +  $cust_main->otaker( &getotaker ); +  $cust_main->referral_custnum( $cgi->param('referral_custnum') ); +  $saved_pkgpart = 0; +  $username = ''; +  $password = ''; +  $popnum = 0; +} +$cgi->delete_all(); +my $action = $custnum ? 'Edit' : 'Add'; + +# top + +my $p1 = popurl(1); +print header("Customer $action", ''); +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $error, "</FONT>" +  if $error; + +print qq!<FORM ACTION="${p1}process/cust_main.cgi" METHOD=POST NAME="form1">!, +      qq!<INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum">!, +      qq!Customer # !, ( $custnum ? "<B>$custnum</B>" : " (NEW)" ), +       +; + +# agent + +my $r = qq!<font color="#ff0000">*</font>!; + +my @agents = qsearch( 'agent', {} ); +#die "No agents created!" unless @agents; +die "You have not created any agents.  You must create at least one agent before adding a customer.  Go to ". popurl(2). "browse/agent.cgi and create one or more agents." unless @agents; +my $agentnum = $cust_main->agentnum || $agents[0]->agentnum; #default to first +if ( scalar(@agents) == 1 ) { +  print qq!<INPUT TYPE="hidden" NAME="agentnum" VALUE="$agentnum">!; +} else { +  print qq!<BR><BR>${r}Agent <SELECT NAME="agentnum" SIZE="1">!; +  my $agent; +  foreach $agent (sort { +    $a->agent cmp $b->agent; +  } @agents) { +      print '<OPTION VALUE="', $agent->agentnum, '"', +      " SELECTED"x($agent->agentnum==$agentnum), +      ">", $agent->agentnum,": ", $agent->agent; +  } +  print "</SELECT>"; +} + +#referral + +my $refnum = $cust_main->refnum || $conf->config('referraldefault') || 0; +if ( $custnum && ! $conf->exists('editreferrals') ) { +  print qq!<INPUT TYPE="hidden" NAME="refnum" VALUE="$refnum">!; +} else { +  my(@referrals) = qsearch('part_referral',{}); +  if ( scalar(@referrals) == 1 ) { +    $refnum ||= $referrals[0]->refnum; +    print qq!<INPUT TYPE="hidden" NAME="refnum" VALUE="$refnum">!; +  } else { +    print qq!<BR><BR>${r}Referral <SELECT NAME="refnum" SIZE="1">!; +    print "<OPTION> " unless $refnum; +    my($referral); +    foreach $referral (sort { +      $a->refnum <=> $b->refnum; +    } @referrals) { +      print "<OPTION" . " SELECTED"x($referral->refnum==$refnum), +      ">", $referral->refnum, ": ", $referral->referral; +    } +    print "</SELECT>"; +  } +} + +#referring customer + +#print qq!<BR><BR>Referring Customer: !; +if ( $cust_main->referral_custnum ) { +  my $referring_cust_main = +    qsearchs('cust_main', { custnum => $cust_main->referral_custnum } ); +  print '<BR><BR>Referring Customer: <A HREF="'. popurl(1). '/cust_main.cgi?'. +        $cust_main->referral_custnum. '">'. +        $cust_main->referral_custnum. ': '. +        ( $referring_cust_main->company +          || $referring_cust_main->last. ', '. $referring_cust_main->first ). +        '</A><INPUT TYPE="hidden" NAME="referral_custnum" VALUE="'. +        $cust_main->referral_custnum. '">'; +} elsif ( ! $conf->exists('disable_customer_referrals') ) { +  print '<BR><BR>Referring customer number: <INPUT TYPE="text" NAME="referral_custnum" VALUE="">'; +} else { +  print '<INPUT TYPE="hidden" NAME="referral_custnum" VALUE="">'; +} + +# contact info + +my($last,$first,$ss,$company,$address1,$address2,$city,$zip)=( +  $cust_main->last, +  $cust_main->first, +  $cust_main->ss, +  $cust_main->company, +  $cust_main->address1, +  $cust_main->address2, +  $cust_main->city, +  $cust_main->zip, +); + +print "<BR><BR>Billing address", &itable("#cccccc"), <<END; +<TR><TH ALIGN="right">${r}Contact name<BR>(last, first)</TH><TD COLSPAN=3> +END + +print <<END; +<INPUT TYPE="text" NAME="last" VALUE="$last"> ,  +<INPUT TYPE="text" NAME="first" VALUE="$first"> +</TD> +END + +if ( $conf->exists('show_ss') ) { +  print qq!<TD ALIGN="right">SS#</TD><TD><INPUT TYPE="text" NAME="ss" VALUE="$ss" SIZE=11></TD>!; +} else { +  print qq!<TD><INPUT TYPE="hidden" NAME="ss" VALUE="$ss"></TD>!; +} + +print <<END; +</TR> +<TR><TD ALIGN="right">Company</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="company" VALUE="$company" SIZE=70></TD></TR> +<TR><TH ALIGN="right">${r}Address</TH><TD COLSPAN=5><INPUT TYPE="text" NAME="address1" VALUE="$address1" SIZE=70></TD></TR> +<TR><TD ALIGN="right"> </TD><TD COLSPAN=5><INPUT TYPE="text" NAME="address2" VALUE="$address2" SIZE=70></TD></TR> +<TR><TH ALIGN="right">${r}City</TH><TD><INPUT TYPE="text" NAME="city" VALUE="$city"></TD><TH ALIGN="right">${r}State/Country</TH><TD><SELECT NAME="state" SIZE="1"> +END + +my $countrydefault = $conf->config('countrydefault') || 'US'; +$cust_main->country( $countrydefault ) unless $cust_main->country; +$cust_main->state( $conf->config('statedefault') || 'CA' ) +  unless $cust_main->state || $cust_main->country ne 'US'; +foreach ( sort { +     ( $b->country eq $countrydefault ) <=> ( $a->country eq $countrydefault ) +  or $a->country                        cmp $b->country +  or $a->state                          cmp $b->state +  or $a->county                         cmp $b->county +} qsearch('cust_main_county',{}) ) { +  print "<OPTION"; +  print " SELECTED" if ( $cust_main->state eq $_->state +                         && $cust_main->county eq $_->county  +                         && $cust_main->country eq $_->country +                       ); +  print ">",$_->state; +  print " (",$_->county,")" if $_->county; +  print " / ", $_->country; +} +print qq!</SELECT></TD><TH>${r}Zip</TH><TD><INPUT TYPE="text" NAME="zip" VALUE="$zip" SIZE=10></TD></TR>!; + +my($daytime,$night,$fax)=( +  $cust_main->daytime, +  $cust_main->night, +  $cust_main->fax, +); + +print <<END; +<TR><TD ALIGN="right">Day Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="daytime" VALUE="$daytime" SIZE=18></TD></TR> +<TR><TD ALIGN="right">Night Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="night" VALUE="$night" SIZE=18></TD></TR> +<TR><TD ALIGN="right">Fax</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="fax" VALUE="$fax" SIZE=12></TD></TR> +END + +print "</TABLE>$r required fields<BR>"; + +# service address + +if ( defined $cust_main->dbdef_table->column('ship_last') ) { + +  print "\n", <<END; +  <SCRIPT> +  function changed(what) { +    what.form.same.checked = false; +  } +  function samechanged(what) { +    if ( what.checked ) { +END +print "      what.form.ship_$_.value = what.form.$_.value;\n" +  for (qw( last first company address1 address2 city zip daytime night fax )); +print <<END; +      what.form.ship_state.selectedIndex = what.form.state.selectedIndex; +    } +  } +  </SCRIPT> +END + +  print '<BR>Service address ', +        '(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)"'; +  unless ( $cust_main->ship_last ) { +    print ' CHECKED'; +    foreach ( +      qw( last first company address1 address2 city state zip daytime night fax) +    ) { +      $cust_main->set("ship_$_", $cust_main->get($_) ); +    } +  } +  print '>same as billing address)<BR>'; + +  my($ship_last,$ship_first,$ship_company,$ship_address1,$ship_address2,$ship_city,$ship_zip)=( +    $cust_main->ship_last, +    $cust_main->ship_first, +    $cust_main->ship_company, +    $cust_main->ship_address1, +    $cust_main->ship_address2, +    $cust_main->ship_city, +    $cust_main->ship_zip, +  ); + +  print &itable("#cccccc"), <<END; +  <TR><TH ALIGN="right">${r}Contact name<BR>(last, first)</TH><TD COLSPAN=5> +END + +  print <<END; +  <INPUT TYPE="text" NAME="ship_last" VALUE="$ship_last" onChange="changed(this)"> ,  +  <INPUT TYPE="text" NAME="ship_first" VALUE="$ship_first" onChange="changed(this)"> +END + +  print <<END; +  </TD></TR> +  <TR><TD ALIGN="right">Company</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_company" VALUE="$ship_company" SIZE=70 onChange="changed(this)"></TD></TR> +  <TR><TH ALIGN="right">${r}Address</TH><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_address1" VALUE="$ship_address1" SIZE=70 onChange="changed(this)"></TD></TR> +  <TR><TD ALIGN="right"> </TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_address2" VALUE="$ship_address2" SIZE=70 onChange="changed(this)"></TD></TR> +  <TR><TH ALIGN="right">${r}City</TH><TD><INPUT TYPE="text" NAME="ship_city" VALUE="$ship_city" onChange="changed(this)"></TD><TH ALIGN="right">${r}State/Country</TH><TD><SELECT NAME="ship_state" SIZE="1" onChange="changed(this)"> +END + +  $cust_main->ship_country( $conf->config('countrydefault') || 'US' ) +    unless $cust_main->ship_country; +  $cust_main->ship_state( $conf->config('statedefault') || 'CA' ) +    unless $cust_main->ship_state || $cust_main->ship_country ne 'US'; +  foreach ( qsearch('cust_main_county',{}) ) { +    print "<OPTION"; +    print " SELECTED" if ( $cust_main->ship_state eq $_->state +                           && $cust_main->ship_county eq $_->county  +                           && $cust_main->ship_country eq $_->country +                         ); +    print ">",$_->state; +    print " (",$_->county,")" if $_->county; +    print " / ", $_->country; +  } +  print qq!</SELECT></TD><TH>${r}Zip</TH><TD><INPUT TYPE="text" NAME="ship_zip" VALUE="$ship_zip" SIZE=10 onChange="changed(this)"></TD></TR>!; + +  my($ship_daytime,$ship_night,$ship_fax)=( +    $cust_main->ship_daytime, +    $cust_main->ship_night, +    $cust_main->ship_fax, +  ); + +  print <<END; +  <TR><TD ALIGN="right">Day Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_daytime" VALUE="$ship_daytime" SIZE=18 onChange="changed(this)"></TD></TR> +  <TR><TD ALIGN="right">Night Phone</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_night" VALUE="$ship_night" SIZE=18 onChange="changed(this)"></TD></TR> +  <TR><TD ALIGN="right">Fax</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="ship_fax" VALUE="$ship_fax" SIZE=12 onChange="changed(this)"></TD></TR> +END + +  print "</TABLE>$r required fields<BR>"; + +} + +# billing info + +sub expselect { +  my $prefix = shift; +  my( $m, $y ) = (0, 0); +  if ( scalar(@_) ) { +    my $date = shift || '01-2000'; +    if ( $date  =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format +      ( $m, $y ) = ( $2, $1 ); +    } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) { +      ( $m, $y ) = ( $1, $3 ); +    } else { +      die "unrecognized expiration date format: $date"; +    } +  } + +  my $return = qq!<SELECT NAME="$prefix!. qq!_month" SIZE="1">!; +  for ( 1 .. 12 ) { +    $return .= "<OPTION"; +    $return .= " SELECTED" if $_ == $m; +    $return .= ">$_"; +  } +  $return .= qq!</SELECT>/<SELECT NAME="$prefix!. qq!_year" SIZE="1">!; +  for ( 2001 .. 2037 ) { +    $return .= "<OPTION"; +    $return .= " SELECTED" if $_ == $y; +    $return .= ">$_"; +  } +  $return .= "</SELECT>"; + +  $return; +} + +print "<BR>Billing information", &itable("#cccccc"), +      qq!<TR><TD><INPUT TYPE="checkbox" NAME="tax" VALUE="Y"!; +print qq! CHECKED! if $cust_main->tax eq "Y"; +print qq!>Tax Exempt</TD></TR>!; +print qq!<TR><TD><INPUT TYPE="checkbox" NAME="invoicing_list_POST" VALUE="POST"!; +my @invoicing_list = $cust_main->invoicing_list; +print qq! CHECKED! +  if ( ! @invoicing_list && ! $conf->exists('disablepostalinvoicedefault') ) +     || grep { $_ eq 'POST' } @invoicing_list; +print qq!>Postal mail invoice</TD></TR>!; +my $invoicing_list = join(', ', grep { $_ ne 'POST' } @invoicing_list ); +print qq!<TR><TD>Email invoice <INPUT TYPE="text" NAME="invoicing_list" VALUE="$invoicing_list"></TD></TR>!; + +print "<TR><TD>Billing type</TD></TR>", +      "</TABLE>", +      &table("#cccccc"), "<TR>"; + +my($payinfo, $payname)=( +  $cust_main->payinfo, +  $cust_main->payname, +); + +my %payby = ( +  'CARD' => qq!Credit card<BR>${r}<INPUT TYPE="text" NAME="CARD_payinfo" VALUE="" MAXLENGTH=19><BR>${r}Exp !. expselect("CARD"). qq!<BR>${r}Name on card<BR><INPUT TYPE="text" NAME="CARD_payname" VALUE="">!, +  'BILL' => qq!Billing<BR>P.O. <INPUT TYPE="text" NAME="BILL_payinfo" VALUE=""><BR>${r}Exp !. expselect("BILL", "12-2037"). qq!<BR>Attention<BR><INPUT TYPE="text" NAME="BILL_payname" VALUE="">!, +  'COMP' => qq!Complimentary<BR>${r}Approved by<INPUT TYPE="text" NAME="COMP_payinfo" VALUE=""><BR>${r}Exp !. expselect("COMP"), +); +my %paybychecked = ( +  'CARD' => qq!Credit card<BR>${r}<INPUT TYPE="text" NAME="CARD_payinfo" VALUE="$payinfo" MAXLENGTH=19><BR>${r}Exp !. expselect("CARD", $cust_main->paydate). qq!<BR>${r}Name on card<BR><INPUT TYPE="text" NAME="CARD_payname" VALUE="$payname">!, +  'BILL' => qq!Billing<BR>P.O. <INPUT TYPE="text" NAME="BILL_payinfo" VALUE="$payinfo"><BR>${r}Exp !. expselect("BILL", $cust_main->paydate). qq!<BR>Attention<BR><INPUT TYPE="text" NAME="BILL_payname" VALUE="$payname">!, +  'COMP' => qq!Complimentary<BR>${r}Approved by<INPUT TYPE="text" NAME="COMP_payinfo" VALUE="$payinfo"><BR>${r}Exp !. expselect("COMP", $cust_main->paydate), +); +for (qw(CARD BILL COMP)) { +  print qq!<TD VALIGN=TOP><INPUT TYPE="radio" NAME="payby" VALUE="$_"!; +  if ($cust_main->payby eq "$_") { +    print qq! CHECKED> $paybychecked{$_}</TD>!; +  } else { +    print qq!> $payby{$_}</TD>!; +  } +} + +print "</TR></TABLE>$r required fields for each billing type"; + +if ( defined $cust_main->dbdef_table->column('comments') ) { +    print "<BR><BR>Comments", &itable("#cccccc"), +          qq!<TR><TD><TEXTAREA COLS=80 ROWS=5 WRAP="HARD" NAME="comments">!, +          $cust_main->comments, "</TEXTAREA>", +          "</TD></TR></TABLE>"; +} + +unless ( $custnum ) { +  # pry the wrong place for this logic.  also pretty expensive +  #use FS::part_pkg; + +  #false laziness, copied from FS::cust_pkg::order +  my $pkgpart; +  if ( scalar(@agents) == 1 ) { +    # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART +    my($agent)=qsearchs('agent',{'agentnum'=> $agentnum }); +    $pkgpart = $agent->pkgpart_hashref; +  } else { +    #can't know (agent not chosen), so, allow all +    my %typenum; +    foreach my $agent ( @agents ) { +      next if $typenum{$agent->typenum}++; +      #fixed in 5.004_05 #$pkgpart->{$_}++ foreach keys %{ $agent->pkgpart_hashref } +      foreach ( keys %{ $agent->pkgpart_hashref } ) { $pkgpart->{$_}++; } #5.004_04 workaround +    } +  } +  #eslaf + +  my @part_pkg = grep { $_->svcpart('svc_acct') && $pkgpart->{ $_->pkgpart } } +    qsearch( 'part_pkg', { 'disabled' => '' } ); + +  if ( @part_pkg ) { + +#    print "<BR><BR>First package", &itable("#cccccc", "0 ALIGN=LEFT"), +#apiabuse & undesirable wrapping +    print "<BR><BR>First package", &itable("#cccccc"), +          qq!<TR><TD COLSPAN=2><SELECT NAME="pkgpart_svcpart">!; + +    print qq!<OPTION VALUE="">(none)!; + +    foreach my $part_pkg ( @part_pkg ) { +      print qq!<OPTION VALUE="!, +#              $part_pkg->pkgpart. "_". $pkgpart{ $part_pkg->pkgpart }, '"'; +              $part_pkg->pkgpart. "_". $part_pkg->svcpart, '"'; +      print " SELECTED" if $saved_pkgpart && ( $part_pkg->pkgpart == $saved_pkgpart ); +      print ">", $part_pkg->pkg, " - ", $part_pkg->comment; +    } +    print "</SELECT></TD></TR>"; + +    #false laziness: (mostly) copied from edit/svc_acct.cgi +    #$ulen = $svc_acct->dbdef_table->column('username')->length; +    my $ulen = dbdef->table('svc_acct')->column('username')->length; +    my $ulen2 = $ulen+2; +    my $passwordmax = $conf->config('passwordmax') || 8; +    my $pmax2 = $passwordmax + 2; +    print <<END; +<TR><TD ALIGN="right">Username</TD> +<TD><INPUT TYPE="text" NAME="username" VALUE="$username" SIZE=$ulen2 MAXLENGTH=$ulen></TD></TR> +<TR><TD ALIGN="right">Password</TD> +<TD><INPUT TYPE="text" NAME="_password" VALUE="$password" SIZE=$pmax2 MAXLENGTH=$passwordmax> +(blank to generate)</TD></TR> +END + +    print '<TR><TD ALIGN="right">Access number</TD><TD WIDTH="100%">' +          . +          &FS::svc_acct_pop::popselector($popnum). +          '</TD></TR></TABLE>' +          ; +  } +} + +my $otaker = $cust_main->otaker; +print qq!<INPUT TYPE="hidden" NAME="otaker" VALUE="$otaker">!, +      qq!<BR><INPUT TYPE="submit" VALUE="!, +      $custnum ?  "Apply Changes" : "Add Customer", qq!">!, +      "</FORM></BODY></HTML>", +; + +%> diff --git a/httemplate/edit/cust_main_county-expand.cgi b/httemplate/edit/cust_main_county-expand.cgi new file mode 100755 index 000000000..66e8aaf9e --- /dev/null +++ b/httemplate/edit/cust_main_county-expand.cgi @@ -0,0 +1,51 @@ +<!-- mason kludge --> +<% + +my($taxnum, $delim, $expansion ); +if ( $cgi->param('error') ) { +  $taxnum = $cgi->param('taxnum'); +  $delim = $cgi->param('delim'); +  $expansion = $cgi->param('expansion'); +} else { +  my ($query) = $cgi->keywords; +  $query =~ /^(\d+)$/ +    or die "Illegal taxnum!"; +  $taxnum = $1; +  $delim = 'n'; +  $expansion = ''; +} + +my $cust_main_county = qsearchs('cust_main_county',{'taxnum'=>$taxnum}) +  or die "cust_main_county.taxnum $taxnum not found"; +die "Can't expand entry!" if $cust_main_county->getfield('county'); + +my $p1 = popurl(1); +print header("Tax Rate (expand)", menubar( +  'Main Menu' => popurl(2), +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print <<END; +    <FORM ACTION="${p1}process/cust_main_county-expand.cgi" METHOD=POST> +      <INPUT TYPE="hidden" NAME="taxnum" VALUE="$taxnum"> +      Separate by +END +print '<INPUT TYPE="radio" NAME="delim" VALUE="n"'; +print ' CHECKED' if $delim eq 'n'; +print '>line (rumor has it broken on some browsers) or', +      '<INPUT TYPE="radio" NAME="delim" VALUE="s"'; +print ' CHECKED' if $delim eq 's'; +print '>whitespace.'; +print <<END; +      <BR><INPUT TYPE="submit" VALUE="Submit"> +      <BR><TEXTAREA NAME="expansion" ROWS=100>$expansion</TEXTAREA> +    </FORM> +    </CENTER> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_main_county.cgi b/httemplate/edit/cust_main_county.cgi new file mode 100755 index 000000000..a11711770 --- /dev/null +++ b/httemplate/edit/cust_main_county.cgi @@ -0,0 +1,57 @@ +<!-- mason kludge --> +<% + +print header("Edit tax rates", menubar( +  'Main Menu' => popurl(2), +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print qq!<FORM ACTION="!, popurl(1), +    qq!process/cust_main_county.cgi" METHOD=POST>!, &table(), <<END; +      <TR> +        <TH><FONT SIZE=-1>Country</FONT></TH> +        <TH><FONT SIZE=-1>State</FONT></TH> +        <TH>County</TH> +        <TH><FONT SIZE=-1>Tax</FONT></TH> +      </TR> +END + +foreach my $cust_main_county ( sort {    $a->country cmp $b->country +                                      or $a->state   cmp $b->state +                                      or $a->county  cmp $b->county +                                    } qsearch('cust_main_county',{}) ) { +  my($hashref)=$cust_main_county->hashref; +  print <<END; +      <TR> +        <TD>$hashref->{country}</TD> +END + +  print "<TD>", $hashref->{state} +      ? $hashref->{state} +      : '(ALL)' +    , "</TD>"; + +  print "<TD>", $hashref->{county} +      ? $hashref->{county} +      : '(ALL)' +    , "</TD>"; + +  print qq!<TD><INPUT TYPE="text" NAME="tax!, $hashref->{taxnum}, +        qq!" VALUE="!, $hashref->{tax}, qq!" SIZE=6 MAXLENGTH=6>%</TD></TR>!; +END + +} + +print <<END; +    </TABLE> +    <INPUT TYPE="submit" VALUE="Apply changes"> +    </FORM> +    </CENTER> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_pay.cgi b/httemplate/edit/cust_pay.cgi new file mode 100755 index 000000000..f6ae7b299 --- /dev/null +++ b/httemplate/edit/cust_pay.cgi @@ -0,0 +1,129 @@ +<!-- mason kludge --> +<% + +my $conf = new FS::Conf; + +my($link, $linknum, $paid, $payby, $payinfo, $quickpay);  +if ( $cgi->param('error') ) { +  $link = $cgi->param('link'); +  $linknum = $cgi->param('linknum'); +  $paid = $cgi->param('paid'); +  $payby = $cgi->param('payby'); +  $payinfo = $cgi->param('payinfo'); +  $quickpay = $cgi->param('quickpay'); +} elsif ($cgi->keywords) { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $link = 'invnum'; +  $linknum = $1; +  $paid = ''; +  $payby = 'BILL'; +  $payinfo = ""; +  $quickpay = ''; +} elsif ( $cgi->param('custnum')  =~ /^(\d+)$/ ) { +  $link = 'custnum'; +  $linknum = $1; +  $paid = ''; +  $payby = 'BILL'; +  $payinfo = ''; +  $quickpay = $cgi->param('quickpay'); +} else { +  die "illegal query ". $cgi->keywords; +} +my $_date = time; + +my $paybatch = "webui-$_date-$$-". rand() * 2**32; + +my $p1 = popurl(1); +print header("Post payment", ''); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT><BR><BR>" +  if $cgi->param('error'); + +print <<END, ntable("#cccccc",2); +    <FORM ACTION="${p1}process/cust_pay.cgi" METHOD=POST> +    <INPUT TYPE="hidden" NAME="link" VALUE="$link"> +    <INPUT TYPE="hidden" NAME="linknum" VALUE="$linknum"> +    <INPUT TYPE="hidden" NAME="quickpay" VALUE="$quickpay"> +END + +my $custnum; +if ( $link eq 'invnum' ) { + +  my $cust_bill = qsearchs('cust_bill', { 'invnum' => $linknum } ) +    or die "unknown invnum $linknum"; +  print "Invoice #<B>$linknum</B>". ntable("#cccccc",2). +        '<TR><TD ALIGN="right">Date</TD><TD BGCOLOR="#ffffff">'. +        time2str("%D", $cust_bill->_date). '</TD></TR>'. +        '<TR><TD ALIGN="right" VALIGN="top">Items</TD><TD BGCOLOR="#ffffff">'; +  foreach ( $cust_bill->cust_bill_pkg ) { #false laziness with FS::cust_bill +    if ( $_->pkgnum ) { + +      my($cust_pkg)=qsearchs('cust_pkg', { 'pkgnum', $_->pkgnum } ); +      my($part_pkg)=qsearchs('part_pkg',{'pkgpart'=>$cust_pkg->pkgpart}); +      my($pkg)=$part_pkg->pkg; + +      if ( $_->setup != 0 ) { +        print "$pkg Setup<BR>"; # $money_char. sprintf("%10.2f",$_->setup); +        print join('<BR>', +          map { "  ". $_->[0]. ": ". $_->[1] } $cust_pkg->labels +        ). '<BR>'; +      } + +      if ( $_->recur != 0 ) { +        print +          "$pkg (" . time2str("%x",$_->sdate) . " - " . +                                time2str("%x",$_->edate) . ")<BR>"; +          #$money_char. sprintf("%10.2f",$_->recur) +        print join('<BR>', +          map { '--->'. $_->[0]. ": ". $_->[1] } $cust_pkg->labels +        ). '<BR>'; +      } + +    } else { #pkgnum Tax +      print "Tax<BR>" # $money_char. sprintf("%10.2f",$_->setup) +        if $_->setup != 0; +    } + +  } +  print '</TD></TR></TABLE><BR><BR>'; + +  $custnum = $cust_bill->custnum; + +} elsif ( $link eq 'custnum' ) { +  $custnum = $linknum; +} + +print small_custview($custnum, $conf->config('countrydefault')); + +print qq!<INPUT TYPE="hidden" NAME="_date" VALUE="$_date">!; +print qq!<INPUT TYPE="hidden" NAME="payby" VALUE="$payby">!; + +print '<BR><BR>Payment'. ntable("#cccccc", 2). +      '<TR><TD ALIGN="right">Date</TD><TD BGCOLOR="#ffffff">'. +      time2str("%D",$_date).  '</TD></TR>'; + +print qq!<TR><TD ALIGN="right">Amount</TD><TD BGCOLOR="#ffffff">\$<INPUT TYPE="text" NAME="paid" VALUE="$paid" SIZE=8 MAXLENGTH=8></TD></TR>!; + +print qq!<TR><TD ALIGN="right">Payby</TD><TD BGCOLOR="#ffffff">$payby</TD></TR>!; + +#payinfo (check # now as payby="BILL" hardcoded.. what to do later?) +print qq!<TR><TD ALIGN="right">Check #</TD><TD BGCOLOR="#ffffff"><INPUT TYPE="text" NAME="payinfo" VALUE="$payinfo"></TD></TR>!; + +print qq!<TR><TD ALIGN="right">Auto-apply<BR>to invoices</TD><TD><SELECT NAME="apply"><OPTION VALUE="yes" SELECTED>yes<OPTION>no</SELECT></TD>!; + +print "</TABLE>"; + +#paybatch +print qq!<INPUT TYPE="hidden" NAME="paybatch" VALUE="$paybatch">!; + +print <<END; +<BR> +<INPUT TYPE="submit" VALUE="Post payment"> +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/cust_pkg.cgi b/httemplate/edit/cust_pkg.cgi new file mode 100755 index 000000000..d546f7409 --- /dev/null +++ b/httemplate/edit/cust_pkg.cgi @@ -0,0 +1,108 @@ +<!-- mason kludge --> +<% + +my %pkg = (); +my %comment = (); +foreach (qsearch('part_pkg', { 'disabled' => '' })) { +  $pkg{ $_ -> getfield('pkgpart') } = $_->getfield('pkg'); +  $comment{ $_ -> getfield('pkgpart') } = $_->getfield('comment'); +} + +my($custnum, %remove_pkg); +if ( $cgi->param('error') ) { +  $custnum = $cgi->param('custnum'); +  %remove_pkg = map { $_ => 1 } $cgi->param('remove_pkg'); +} else { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $custnum = $1; +  %remove_pkg = (); +} + +my $p1 = popurl(1); +print header("Add/Edit Packages", ''); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print qq!<FORM ACTION="${p1}process/cust_pkg.cgi" METHOD=POST>!; + +print qq!<INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum">!; + +#current packages +my @cust_pkg = qsearch('cust_pkg',{ 'custnum' => $custnum, 'cancel' => '' } ); + +if (@cust_pkg) { +  print <<END; +Current packages - select to remove (services are moved to a new package below) +<BR><BR> +END + +  my $count = 0 ; +  print qq!<TABLE>! ; +  foreach (@cust_pkg) { +    print '<TR>' if $count == 0; +    my($pkgnum,$pkgpart)=( $_->getfield('pkgnum'), $_->getfield('pkgpart') ); +    print qq!<TD><INPUT TYPE="checkbox" NAME="remove_pkg" VALUE="$pkgnum"!; +    print " CHECKED" if $remove_pkg{$pkgnum}; +    print qq!>$pkgnum: $pkg{$pkgpart} - $comment{$pkgpart}</TD>\n!; +    $count ++ ; +    if ($count == 2) +    { +      $count = 0 ; +      print qq!</TR>\n! ; +    } +  } +  print qq!</TABLE><BR><BR>!; +} + +print <<END; +Order new packages<BR><BR> +END + +my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum}); +my $agent = qsearchs('agent',{'agentnum'=> $cust_main->agentnum }); + +my $count = 0; +my $pkgparts = 0; +print qq!<TABLE>!; +foreach my $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) { +  $pkgparts++; +  my($pkgpart)=$type_pkgs->pkgpart; +  next unless exists $pkg{$pkgpart}; #skip disabled ones +  print qq!<TR>! if ( $count == 0 ); +  my $value = $cgi->param("pkg$pkgpart") || 0; +  print <<END; +  <TD> +  <INPUT TYPE="text" NAME="pkg$pkgpart" VALUE="$value" SIZE="2" MAXLENGTH="2"> +  $pkgpart: $pkg{$pkgpart} - $comment{$pkgpart}</TD>\n +END +  $count ++ ; +  if ( $count == 2 ) { +    print qq!</TR>\n! ; +    $count = 0; +  } +} +print qq!</TABLE>!; + +unless ( $pkgparts ) { +  my $p2 = popurl(2); +  my $typenum = $agent->typenum; +  my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } ); +  my $atype = $agent_type->atype; +  print <<END; +(No <a href="${p2}browse/part_pkg.cgi">package definitions</a>, or agent type +<a href="${p2}edit/agent_type.cgi?$typenum">$atype</a> not allowed to purchase +any packages.) +END +} + +#submit +print <<END; +<P><INPUT TYPE="submit" VALUE="Order"> +    </FORM> +  </BODY> +</HTML> +END +%> diff --git a/httemplate/edit/part_bill_event.cgi b/httemplate/edit/part_bill_event.cgi new file mode 100755 index 000000000..018fc94a4 --- /dev/null +++ b/httemplate/edit/part_bill_event.cgi @@ -0,0 +1,184 @@ +<!-- mason kludge --> +<% + +if ( $cgi->param('eventpart') && $cgi->param('eventpart') =~ /^(\d+)$/ ) { +  $cgi->param('eventpart', $1); +} else { +  $cgi->param('eventpart', ''); +} + +my ($query) = $cgi->keywords; +my $action = ''; +my $part_bill_event = ''; +if ( $cgi->param('error') ) { +  $part_bill_event = new FS::part_bill_event ( { +    map { $_, scalar($cgi->param($_)) } fields('part_bill_event') +  } ); +} +if ( $query && $query =~ /^(\d+)$/ ) { +  $part_bill_event ||= qsearchs('part_bill_event',{'eventpart'=>$1}); +} else { +  $part_bill_event ||= new FS::part_bill_event {}; +} +$action ||= $part_bill_event->pkgpart ? 'Edit' : 'Add'; +my $hashref = $part_bill_event->hashref; + +print header("$action Invoice Event Definition", menubar( +  'Main Menu' => popurl(2), +  'View all invoice events' => popurl(2). 'browse/part_bill_event.cgi', +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print '<FORM ACTION="', popurl(1), 'process/part_bill_event.cgi" METHOD=POST>'. +      '<INPUT TYPE="hidden" NAME="eventpart" VALUE="'. +      $part_bill_event->eventpart  .'">'; +print "Invoice Event #", $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)"; + +print ntable("#cccccc",2), <<END; +<TR><TD ALIGN="right">Payby</TD><TD><SELECT NAME="payby"> +END + +for (qw(CARD BILL COMP)) { +  print qq!<OPTION VALUE="$_"!; +  if ($part_bill_event->payby eq $_) { +    print " SELECTED>$_</OPTION>"; +  } else { +    print ">$_</OPTION>"; +  } +} + +my $days = $hashref->{seconds}/86400; + +print <<END; +</SELECT></TD></TR> +<TR><TD ALIGN="right">Event</TD><TD><INPUT TYPE="text" NAME="event" VALUE="$hashref->{event}"></TD></TR> +<TR><TD ALIGN="right">After</TD><TD><INPUT TYPE="text" NAME="days" VALUE="$days"> days</TD></TR> +END + +print '<TR><TD ALIGN="right">Disabled</TD><TD>'; +print '<INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"'; +print ' CHECKED' if $hashref->{disabled} eq "Y"; +print '>'; +print '</TD></TR>'; + +print '<TR><TD ALIGN="right">Action</TD><TD>'; + +#print ntable(); + +#this is pretty kludgy right here. +tie my %events, 'Tie::IxHash', + +  'fee' => { +    'name'   => 'Late fee', +    'code'   => '$cust_main->charge( %%%charge%%%, \'%%%reason%%%\' );', +    'html'   =>  +      'Amount <INPUT TYPE="text" SIZE="7" NAME="charge" VALUE="%%%charge%%%">'. +      '<BR>Reason <INPUT TYPE="text" NAME="reason" VALUE="%%%reason%%%">', +    'weight' => 10, +  }, +  'suspend' => { +    'name'   => 'Suspend', +    'code'   => '$cust_main->suspend();', +    'weight' => 10, +  }, +  'cancel' => { +    'name'   => 'Cancel', +    'code'   => '$cust_main->cancel();', +    'weight' => 10, +  }, + +  'addpost' => { +    'name' => 'Add postal invoicing', +    'code' => '$cust_main->invoicing_list_addpost(); "";', +    'weight'  => 20, +  }, + +  'comp' => { +    'name' => 'Pay invoice with a complimentary "payment"', +    'code' => '$cust_bill->comp();', +    'weight' => 30, +  }, + +  'realtime-card' => { +    'name' => 'Run card with a <a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a> realtime gateway', +    'code' => '$cust_bill->realtime_card();', +    'weight' => 30, +  }, + +  'realtime-card-cybercash' => { +    'name' => '(<b>deprecated</b>) Run card with <a href="http://www.cybercash.com/cashregister">CyberCash CashRegister</a> realtime gateway', +    'code' => '$cust_bill->realtime_card_cybercash();', +    'weight' => 30, +  }, + +  'batch-card' => { +    'name' => 'Add card to the pending credit card batch', +    'code' => '$cust_bill->batch_card();', +    'weight' => 40, +  }, + +  'send' => { +    'name' => 'Send invoice (email/print)', +    'code' => '$cust_bill->send();', +    'weight' => 50, +  }, + +  'bill' => { +    'name' => 'Generate invoices (normally only used with a <i>Late Fee</i> event)', +    'code' => '$cust_main->bill();', +    'weight'  => 60, +  }, + +  'apply' => { +    'name' => 'Apply unapplied payments and credits', +    'code' => '$cust_main->apply_payments; $cust_main->apply_credits; "";', +    'weight'  => 70, +  }, + +  'collect' => { +    'name' => 'Collect on invoices (normally only used with a <i>Late Fee</i> and <i>Generate Invoice</i> events)', +    'code' => '$cust_main->collect();', +    'weight'  => 80, +  }, + +; + +foreach my $event ( keys %events ) { +  my %plandata = map { /^(\w+) (.*)$/; ($1, $2); } +                   split(/\n/, $part_bill_event->plandata); +  my $html = $events{$event}{html}; +  while ( $html =~ /%%%(\w+)%%%/ ) { +    my $field = $1; +    $html =~ s/%%%$field%%%/$plandata{$field}/; +  } + +  print ntable( "#cccccc", 2). +        qq!<TR><TD><INPUT TYPE="radio" NAME="plan_weight_eventcode" !; +  print "CHECKED " if $event eq $part_bill_event->plan; +  print qq!VALUE="!.  $event. ":". $events{$event}{weight}. ":". +        encode_entities($events{$event}{code}). +        qq!">$events{$event}{name}</TD>!; +  print '<TD>'. $html. '</TD>' if $html; +  print qq!</TR>!; +  print '</TABLE>'; +} + +#print '</TABLE>'; + +print <<END; +</TD></TR> +</TABLE> +END + +print qq!<INPUT TYPE="submit" VALUE="!, +      $hashref->{eventpart} ? "Apply changes" : "Add invoice event", +      qq!">!; +%> + +    </FORM> +  </BODY> +</HTML> + diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi new file mode 100755 index 000000000..f4ebd6770 --- /dev/null +++ b/httemplate/edit/part_pkg.cgi @@ -0,0 +1,464 @@ +<!-- mason kludge --> +<% + +if ( $cgi->param('clone') && $cgi->param('clone') =~ /^(\d+)$/ ) { +  $cgi->param('clone', $1); +} else { +  $cgi->param('clone', ''); +} +if ( $cgi->param('pkgnum') && $cgi->param('pkgnum') =~ /^(\d+)$/ ) { +  $cgi->param('pkgnum', $1); +} else { +  $cgi->param('pkgnum', ''); +} + +my ($query) = $cgi->keywords; +my $action = ''; +my $part_pkg = ''; +if ( $cgi->param('error') ) { +  $part_pkg = new FS::part_pkg ( { +    map { $_, scalar($cgi->param($_)) } fields('part_pkg') +  } ); +} +if ( $cgi->param('clone') ) { +  $action='Custom Pricing'; +  my $old_part_pkg = +    qsearchs('part_pkg', { 'pkgpart' => $cgi->param('clone') } ); +  $part_pkg ||= $old_part_pkg->clone; +  $part_pkg->disabled('Y'); +} elsif ( $query && $query =~ /^(\d+)$/ ) { +  $part_pkg ||= qsearchs('part_pkg',{'pkgpart'=>$1}); +} else { +  $part_pkg ||= new FS::part_pkg {}; +  $part_pkg->plan('flat'); +} +unless ( $part_pkg->plan ) { #backwards-compat +  $part_pkg->plan('flat'); +  $part_pkg->plandata("setup_fee=". $part_pkg->setup. "\n". +                      "recur_fee=". $part_pkg->recur. "\n"); +} +$action ||= $part_pkg->pkgpart ? 'Edit' : 'Add'; +my $hashref = $part_pkg->hashref; + +%> + +<SCRIPT> +function visualize(what) { +  if (document.getElementById) { +    document.getElementById('d<%= $part_pkg->plan %>').style.visibility = "visible"; +  } else { +    document.l<%= $part_pkg->plan %>.visibility = "visible"; +  } +} +</SCRIPT> + +<%  + +print header("$action Package Definition", menubar( +  'Main Menu' => popurl(2), +  'View all packages' => popurl(2). 'browse/part_pkg.cgi', +), ' onLoad="visualize()"'); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +#print '<FORM ACTION="', popurl(1), 'process/part_pkg.cgi" METHOD=POST>'; +print '<FORM NAME="dummy">'; + +#if ( $cgi->param('clone') ) { +#  print qq!<INPUT TYPE="hidden" NAME="clone" VALUE="!, $cgi->param('clone'), qq!">!; +#} +#if ( $cgi->param('pkgnum') ) { +#  print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="!, $cgi->param('pkgnum'), qq!">!; +#} +# +#print qq!<INPUT TYPE="hidden" NAME="pkgpart" VALUE="$hashref->{pkgpart}">!, +print "Package Part #", $hashref->{pkgpart} ? $hashref->{pkgpart} : "(NEW)"; + +print ntable("#cccccc",2), <<END; +<TR><TD ALIGN="right">Package (customer-visable)</TD><TD><INPUT TYPE="text" NAME="pkg" SIZE=32 VALUE="$hashref->{pkg}"></TD></TR> +<TR><TD ALIGN="right">Comment (customer-hidden)</TD><TD><INPUT TYPE="text" NAME="comment" SIZE=32 VALUE="$hashref->{comment}"></TD></TR> +<TR><TD ALIGN="right">Frequency (months) of recurring fee</TD><TD><INPUT TYPE="text" NAME="freq" VALUE="$hashref->{freq}" SIZE=3></TD></TR> +<TR><TD ALIGN="right">Setup fee tax exempt</TD><TD> +END + +print '<INPUT TYPE="checkbox" NAME="setuptax" VALUE="Y"'; +print ' CHECKED' if $hashref->{setuptax} eq "Y"; +print '>'; + +print <<END; +</TD></TR> +<TR><TD ALIGN="right">Recurring fee tax exempt</TD><TD> +END + +print '<INPUT TYPE="checkbox" NAME="recurtax" VALUE="Y"'; +print ' CHECKED' if $hashref->{recurtax} eq "Y"; +print '>'; + +print '</TD></TR>'; + +print '<TR><TD ALIGN="right">Disable new orders</TD><TD>'; +print '<INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"'; +print ' CHECKED' if $hashref->{disabled} eq "Y"; +print '>'; +print '</TD></TR></TABLE>'; + +my $thead =  "\n\n". ntable('#cccccc', 2). <<END; +<TR><TH BGCOLOR="#dcdcdc"><FONT SIZE=-1>Quan.</FONT></TH><TH BGCOLOR="#dcdcdc">Service</TH></TR> +END + +unless ( $cgi->param('clone') ) { +  #print <<END, $thead; +  print <<END, itable(), '<TR><TD VALIGN="top">', $thead; +<BR><BR>Enter the quantity of each service this package includes.<BR><BR> +END +} + +my @fixups = (); +my $count = 0; +my $columns = 3; +my @part_svc = qsearch( 'part_svc', { 'disabled' => '' } ); +foreach my $part_svc ( @part_svc ) { +  my $svcpart = $part_svc->svcpart; +  my $pkg_svc = qsearchs( 'pkg_svc', { +    'pkgpart'  => $cgi->param('clone') || $part_pkg->pkgpart, +    'svcpart'  => $svcpart, +  } ) || new FS::pkg_svc ( { +    'pkgpart'  => $cgi->param('clone') || $part_pkg->pkgpart, +    'svcpart'  => $svcpart, +    'quantity' => 0, +  }); +  #? #next unless $pkg_svc; + +  push @fixups, "pkg_svc$svcpart"; + +  unless ( defined ($cgi->param('clone')) && $cgi->param('clone') ) { +    print '<TR>'; # if $count == 0 ; +    print qq!<TD><INPUT TYPE="text" NAME="pkg_svc$svcpart" SIZE=4 MAXLENGTH=3 VALUE="!, +          $cgi->param("pkg_svc$svcpart") || $pkg_svc->quantity || 0, +          qq!"></TD><TD><A HREF="part_svc.cgi?!,$part_svc->svcpart, +          qq!">!, $part_svc->getfield('svc'), "</A></TD></TR>"; +#    print "</TABLE></TD><TD>$thead" if ++$count == int(scalar(@part_svc) / 2); +    $count+=1; +    foreach ( 1 .. $columns-1 ) { +      print "</TABLE></TD><TD VALIGN=\"top\">$thead" +        if $count == int( $_ * scalar(@part_svc) / $columns ); +    } +  } else { +    print qq!<INPUT TYPE="hidden" NAME="pkg_svc$svcpart" VALUE="!, +          $cgi->param("pkg_svc$svcpart") || $pkg_svc->quantity || 0, qq!">\n!; +  } +} + +unless ( $cgi->param('clone') ) { +  print "</TR></TABLE></TD></TR></TABLE>"; +  #print "</TR></TABLE>"; +} + +# prolly should be in database +use Tie::IxHash; +tie my %plans, 'Tie::IxHash', +  'flat' => { +    'name' => 'Flat rate', +    'fields' => { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_fee' => { 'name' => 'Recurring fee for this package', +                       'default' => 0, +                      }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_fee' ], +    'setup' => 'what.setup_fee.value', +    'recur' => 'what.recur_fee.value', +  }, + +  'prorate' => { +    'name' => 'First month pro-rated, then flat-rate', +    'fields' =>  { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_fee' => { 'name' => 'Recurring fee for this package', +                       'default' => 0, +                      }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_fee' ], +    'setup' => 'what.setup_fee.value', +    'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; my $mstart = timelocal(0,0,0,1,$mon,$year); my $mend = timelocal(0,0,0,1, $mon == 11 ? 0 : $mon+1, $year+($mon==11)); $sdate = $mstart; ( $part_pkg->freq - 1 ) * \' + what.recur_fee.value + \' / $part_pkg->freq + \' + what.recur_fee.value + \' / $part_pkg->freq * ($mend-$mnow) / ($mend-$mstart) ; \'', +  }, + +  'flat_comission_cust' => { +    'name' => 'Flat rate with recurring comission per active customer', +    'fields' => { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_fee' => { 'name' => 'Recurring fee for this package', +                       'default' => 0, +                     }, +      'comission_amount' => { 'name' => 'Comission amount per month (per active customer)', +                              'default' => 0, +                            }, +      'comission_depth'  => { 'name' => 'Number of layers', +                              'default' => 1, +                            }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ], +    'setup' => 'what.setup_fee.value', +    'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_main_ncancelled(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'', +  }, + +  'flat_comission' => { +    'name' => 'Flat rate with recurring comission per (any) active package', +    'fields' => { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_fee' => { 'name' => 'Recurring fee for this package', +                       'default' => 0, +                     }, +      'comission_amount' => { 'name' => 'Comission amount per month (per active package)', +                              'default' => 0, +                            }, +      'comission_depth'  => { 'name' => 'Number of layers', +                              'default' => 1, +                            }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ], +    'setup' => 'what.setup_fee.value', +    'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'', +  }, + +  'flat_comission_pkg' => { +    'name' => 'Flat rate with recurring comission per (selected) active package', +    'fields' => { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_fee' => { 'name' => 'Recurring fee for this package', +                       'default' => 0, +                     }, +      'comission_amount' => { 'name' => 'Comission amount per month (per uncancelled package)', +                              'default' => 0, +                            }, +      'comission_depth'  => { 'name' => 'Number of layers', +                              'default' => 1, +                            }, +      'comission_pkgpart' => { 'name' => 'Applicable packages<BR><FONT SIZE="-1">(hold <b>ctrl</b> to select multiple packages)</FONT>', +                               'type' => 'select_multiple', +                               'select_table' => 'part_pkg', +                               'select_hash'  => { 'disabled' => '' } , +                               'select_key'   => 'pkgpart', +                               'select_label' => 'pkg', +                             }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount', 'comission_pkgpart' ], +    'setup' => 'what.setup_fee.value', +    'recur' => '""; var pkgparts = ""; for ( var c=0; c < document.flat_comission_pkg.comission_pkgpart.options.length; c++ ) { if (document.flat_comission_pkg.comission_pkgpart.options[c].selected) { pkgparts = pkgparts + document.flat_comission_pkg.comission_pkgpart.options[c].value + \', \'; } } what.recur.value = \'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar( grep { my $pkgpart = $_->pkgpart; grep { $_ == $pkgpart } ( \' + pkgparts + \'  ) } $cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'', +  }, + + + +  'sesmon_hour' => { +    'name' => 'Base charge plus charge per-hour from the session monitor', +    'fields' => { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_flat' => { 'name' => 'Base monthly charge for this package', +                        'default' => 0, +                      }, +      'recur_included_hours' => { 'name' => 'Hours included', +                                  'default' => 0, +                                }, +      'recur_hourly_charge' => { 'name' => 'Additional charge per hour', +                                 'default' => 0, +                               }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_flat', 'recur_included_hours', 'recur_hourly_charge' ], +    'setup' => 'what.setup_fee.value', +    'recur' => '\'my $hours = $cust_pkg->seconds_since($cust_bkg->bill || 0) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'', +  }, + +  'sesmon_minute' => { +    'name' => 'Base charge plus charge per-minute from the session monitor', +    'fields' => { +      'setup_fee' => { 'name' => 'Setup fee for this package', +                       'default' => 0, +                     }, +      'recur_flat' => { 'name' => 'Base monthly charge for this package', +                        'default' => 0, +                      }, +      'recur_included_min' => { 'name' => 'Minutes included', +                                'default' => 0, +                                }, +      'recur_minly_charge' => { 'name' => 'Additional charge per minute', +                                'default' => 0, +                              }, +    }, +    'fieldorder' => [ 'setup_fee', 'recur_flat', 'recur_included_min', 'recur_minly_charge' ], +    'setup' => 'what.setup_fee.value', +    'recur' => '\'my $min = $cust_pkg->seconds_since($cust_bkg->bill || 0) / 60 - \' + what.recur_included_min.value + \'; $min = 0 if $min < 0; \' + what.recur_flat.value + \' + \' + what.recur_minly_charge.value + \' * $min;\'', + +  }, + +; + +%> + +<SCRIPT> +var layer = null; + +function changed(what) { +  layer = what.options[what.selectedIndex].value; +<% foreach my $layer ( keys %plans ) { %> +  if (layer == "<%= $layer %>" ) { +    <% foreach my $not ( grep { $_ ne $layer } keys %plans ) { %> +      if (document.getElementById) { +        document.getElementById('d<%= $not %>').style.visibility = "hidden"; +      } else { +        document.l<%= $not %>.visibility = "hidden"; +      } +    <% } %> +    if (document.getElementById) { +      document.getElementById('d<%= $layer %>').style.visibility = "visible"; +    } else { +      document.l<%= $layer %>.visibility = "visible"; +    } +  } +<% } %> +} + +</SCRIPT> +<BR> +Price plan <SELECT NAME="plan" SIZE=1 onChange="changed(this);"> +<OPTION> +<% foreach my $layer (keys %plans ) { %> +<OPTION VALUE="<%= $layer %>"<%= ' SELECTED'x($layer eq $part_pkg->plan) %>><%= $plans{$layer}->{'name'} %> +<% } %> +</SELECT></FORM> + +<SCRIPT> +function fchanged(what) { +  fixup(what.form); +} + +function fixup(what) { +<% foreach my $f ( qw( pkg comment freq ), @fixups ) { %> +  what.<%= $f %>.value = document.dummy.<%= $f %>.value; +<% } %> +<% foreach my $f ( qw( setuptax recurtax disabled ) ) { %> +  if (document.dummy.<%= $f %>.checked) +    what.<%= $f %>.value = 'Y'; +  else +    what.<%= $f %>.value = ''; +<% } %> +  what.plan.value = document.dummy.plan.options[document.dummy.plan.selectedIndex].value; +<% foreach my $p ( keys %plans ) { %> +  if ( what.plan.value == "<%= $p %>" ) { +    what.setup.value = <%= $plans{$p}->{setup} %>; +    what.recur.value = <%= $plans{$p}->{recur} %>; +  } +<% } %> +} +</SCRIPT> + +<% my %plandata = map { /^(\w+)=(.*)$/; ( $1 => $2 ); } +                    split("\n", $part_pkg->plandata ); +   #foreach my $layer ( 'konq_kludge', keys %plans ) {  +   foreach my $layer ( 'konq_kludge', keys %plans ) { +     my $visibility = "hidden"; +%> +<SCRIPT> +if (document.getElementById) { +    document.write("<DIV ID=\"d<%= $layer %>\" STYLE=\"visibility: <%= $visibility %>; position: absolute\">"); +} else { +<% $visibility="show" if $visibility eq "visible"; %> +    document.write("<LAYER ID=\"l<%= $layer %>\" VISIBILITY=\"<%= $visibility %>\">"); +} +</SCRIPT> + +<FORM NAME="<%= $layer %>" ACTION="process/part_pkg.cgi" METHOD=POST onSubmit="fixup(this)"> +<INPUT TYPE="hidden" NAME="plan" VALUE="<%= $part_pkg->plan %>"> +<INPUT TYPE="hidden" NAME="pkg" VALUE="<%= $hashref->{pkg} %>"> +<INPUT TYPE="hidden" NAME="comment" VALUE="$<%= $hashref->{comment} %>"> +<INPUT TYPE="hidden" NAME="freq" VALUE="<%= $hashref->{freq} %>"> +<INPUT TYPE="hidden" NAME="setuptax" VALUE="<%= $hashref->{setuptax} %>"> +<INPUT TYPE="hidden" NAME="recurtax" VALUE="<%= $hashref->{recurtax} %>"> +<INPUT TYPE="hidden" NAME="disabled" VALUE="<%= $hashref->{disabled} %>"> +<% foreach my $f ( @fixups ) { %> +<INPUT TYPE="hidden" NAME="<%= $f %>" VALUE=""> +<% } %> + +<% +if ( $cgi->param('clone') ) { +  print qq!<INPUT TYPE="hidden" NAME="clone" VALUE="!, $cgi->param('clone'), qq!">!; +} +if ( $cgi->param('pkgnum') ) { +  print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="!, $cgi->param('pkgnum'), qq!">!; +} +%> + +<INPUT TYPE="hidden" NAME="pkgpart" VALUE="<%= $hashref->{pkgpart} %>"> +<%= ntable("#cccccc",2) %> + +<% my $href = $plans{$layer}->{'fields'}; +   foreach my $field ( exists($plans{$layer}->{'fieldorder'}) +                         ? @{$plans{$layer}->{'fieldorder'}} +                         : keys %{ $href } +                     ) { +%> +  <TR><TD ALIGN="right"><%= $href->{$field}{'name'} %></TD> +  <TD> +  <% if ( ! exists($href->{$field}{'type'}) ) { %> +       <INPUT TYPE="text" NAME="<%= $field %>" VALUE="<%= exists($plandata{$field}) ? $plandata{$field} : $href->{$field}{'default'} %>" onChange="fchanged(this)"> +  <% } elsif ( $href->{$field}{'type'} eq 'select_multiple' ) { %> +       <SELECT MULTIPLE NAME="<%= $field %>" onChange="fchanged(this)"> +       <% foreach my $record ( qsearch( $href->{$field}{'select_table'}, $href->{$field}{'select_hash'} ) ) { +          my $value = $record->getfield($href->{$field}{'select_key'}); %> +         <OPTION VALUE="<%= $value %>"<%= $plandata{$field} =~ /(^|, *)$value *(,|$)/ ? ' SELECTED' : '' %>><%= $record->getfield($href->{$field}{'select_label'}) %> +       <% } %> +       </SELECT> +  <% } %> +  </TD></TR> +<% } %> + +</TABLE> +<INPUT TYPE="hidden" NAME="plandata" VALUE="<%= join(',', keys %{ $href } ) %>"> +<BR><BR> + +<% +print qq!<INPUT TYPE="submit" VALUE="!, +      $hashref->{pkgpart} ? "Apply changes" : "Add package", +      qq!" onClick="fchanged(this)">!; +%> + +<BR><BR>don't edit this unless you know what you're doing <INPUT TYPE="button" VALUE="refresh expressions" onClick="fchanged(this)"><%= ntable("#cccccc",2) %><TR><TD> +<FONT SIZE="1">Setup expression<BR><INPUT TYPE="text" NAME="setup" SIZE="160" VALUE="<%= $hashref->{setup} %>" onLoad="fchanged(this)"></FONT><BR> +<FONT SIZE="1">Recurring espression<BR><INPUT TYPE="text" NAME="recur" SIZE="160" VALUE="<%= $hashref->{recur} %>" onLoad="fchanged(this)"></FONT> +</TR></TD> +</TABLE> + +</FORM> + +<SCRIPT> +if (document.getElementById) { +  document.write("</DIV>"); +} else { +  document.write("</LAYER>"); +} +</SCRIPT> + +<% } %> + +<TAG onLoad=" +    if (document.getElementById) { +      document.getElementById('d<%= $part_pkg->plan %>').style.visibility = 'visible'; +    } else { +      document.l<%= $part_pkg->plan %>.visibility = 'visible'; +    } +"> +  </BODY> +</HTML> diff --git a/httemplate/edit/part_referral.cgi b/httemplate/edit/part_referral.cgi new file mode 100755 index 000000000..73be9e337 --- /dev/null +++ b/httemplate/edit/part_referral.cgi @@ -0,0 +1,50 @@ +<!-- mason kludge --> +<% + +my $part_referral; +if ( $cgi->param('error') ) { +  $part_referral = new FS::part_referral ( { +    map { $_, scalar($cgi->param($_)) } fields('part_referral') +  } ); +} elsif ( $cgi->keywords ) { +  my($query) = $cgi->keywords; +  $query =~ /^(\d+)$/; +  $part_referral = qsearchs( 'part_referral', { 'refnum' => $1 } ); +} else { #adding +  $part_referral = new FS::part_referral {}; +} +my $action = $part_referral->refnum ? 'Edit' : 'Add'; +my $hashref = $part_referral->hashref; + +my $p1 = popurl(1); +print header("$action Referral", menubar( +  'Main Menu' => popurl(2), +  'View all referrals' => popurl(2). "browse/part_referral.cgi", +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print qq!<FORM ACTION="${p1}process/part_referral.cgi" METHOD=POST>!; + +print qq!<INPUT TYPE="hidden" NAME="refnum" VALUE="$hashref->{refnum}">!, +      "Referral #", $hashref->{refnum} ? $hashref->{refnum} : "(NEW)"; + +print <<END; +<PRE> +Referral   <INPUT TYPE="text" NAME="referral" SIZE=32 VALUE="$hashref->{referral}"> +</PRE> +END + +print qq!<BR><INPUT TYPE="submit" VALUE="!, +      $hashref->{refnum} ? "Apply changes" : "Add referral", +      qq!">!; + +print <<END; +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi new file mode 100755 index 000000000..c3a4942ea --- /dev/null +++ b/httemplate/edit/part_svc.cgi @@ -0,0 +1,264 @@ +<!-- mason kludge --> +<%  +   my $part_svc; +   if ( $cgi->param('error') ) { #error +     $part_svc = new FS::part_svc ( { +       map { $_, scalar($cgi->param($_)) } fields('part_svc') +     } ); +   } elsif ( $cgi->keywords ) { #edit +     my($query) = $cgi->keywords; +     $query =~ /^(\d+)$/ or die "malformed query: $query"; +     $part_svc=qsearchs('part_svc', { 'svcpart'=>$1 } ) +       or die "unknown svcpart: $1"; +   } else { #adding +     $part_svc = new FS::part_svc {}; +   } +   my $action = $part_svc->svcpart ? 'Edit' : 'Add'; +   my $hashref = $part_svc->hashref; +   my $p_svcdb = $part_svc->svcdb || 'svc_acct'; + +%> + +<SCRIPT> +function visualize(what) { +  if (document.getElementById) { +    document.getElementById('d<%= $p_svcdb %>').style.visibility = "visible"; +  } else { +    document.l<%= $p_svcdb %>.visibility = "visible"; +  } +} +</SCRIPT> + +<%= header("$action Service Definition", +           menubar( 'Main Menu'         => $p, +                    'View all service definitions' => "${p}browse/part_svc.cgi" +                  ), +           " onLoad=\"visualize()\"" +           ) +%> + +<% if ( $cgi->param('error') ) { %> +<FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> +<% } %> + +<FORM NAME="dummy"> + +      Service Part #<%= $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %> +<BR><BR> +Service  <INPUT TYPE="text" NAME="svc" VALUE="<%= $hashref->{svc} %>"><BR> +Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<%= $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>><BR> +<BR> +Services are items you offer to your customers. +<UL><LI>svc_acct - Shell accounts, POP mailboxes, SLIP/PPP and ISDN accounts +    <LI>svc_domain - Domains +    <LI>svc_acct_sm - <B>deprecated</B> (use svc_forward for new installations) Virtual domain mail aliasing. +    <LI>svc_forward - mail forwarding +    <LI>svc_www - Virtual domain website +<!--   <LI>svc_charge - One-time charges (Partially unimplemented) +       <LI>svc_wo - Work orders (Partially unimplemented) +--> +</UL> +For the selected table, you can give fields default or fixed (unchangable) +values.  For example, a SLIP/PPP account may have a default (or perhaps fixed) +<B>slipip</B> of <B>0.0.0.0</B>, while a POP mailbox will probably have a fixed +blank <B>slipip</B> as well as a fixed shell something like <B>/bin/true</B> or +<B>/usr/bin/passwd</B>. +<BR><BR> +<SCRIPT> +var svcdb = null; +function changed(what) { +  svcdb = what.options[what.selectedIndex].value; +<% foreach my $svcdb ( qw( svc_acct svc_domain svc_acct_sm svc_forward svc_www ) ) { %> +  if (svcdb == "<%= $svcdb %>" ) { +    <% foreach my $not ( grep { $_ ne $svcdb } ( +                           qw(svc_acct svc_domain svc_acct_sm svc_forward svc_www) ) ) { %> +      if (document.getElementById) { +        document.getElementById('d<%= $not %>').style.visibility = "hidden"; +      } else { +        document.l<%= $not %>.visibility = "hidden"; +      } +    <% } %> +    if (document.getElementById) { +      document.getElementById('d<%= $svcdb %>').style.visibility = "visible"; +    } else { +      document.l<%= $svcdb %>.visibility = "visible"; +    } +  } +<% } %> +} +</SCRIPT> +<% my @dbs = $hashref->{svcdb} +             ? ( $hashref->{svcdb} ) +             : qw( svc_acct svc_domain svc_acct_sm svc_forward svc_www ); %> +Table<SELECT NAME="svcdb" SIZE=1 onChange="changed(this)"> +<% foreach my $svcdb (@dbs) { %> +<OPTION VALUE="<%= $svcdb %>" <%= ' SELECTED'x($svcdb eq $hashref->{svcdb}) %>><%= $svcdb %> +<% } %> +</SELECT></FORM> + +<% +#these might belong somewhere else for other user interfaces  +#pry need to eventually create stuff that's shared amount UIs +my %defs = ( +  'svc_acct' => { +    'dir'       => 'Home directory', +    'uid'       => 'UID (set to fixed and blank for dial-only)', +    'slipip'    => 'IP address (Set to fixed and blank to disable dialin, or, set a value to be exported to RADIUS Framed-IP-Address.  Use the special value <code>0e0</code> [zero e zero] to enable export to RADIUS without a Framed-IP-Address.)', +    'popnum'    => qq!<A HREF="$p/browse/svc_acct_pop.cgi/">POP number</A>!, +    'username'  => 'Username', +    'quota'     => '', +    '_password' => 'Password', +    'gid'       => 'GID (when blank, defaults to UID)', +    'shell'     => 'Shell (all service definitions should have a default or fixed shell that is present in the <b>shells</b> configuration file)', +    'finger'    => 'GECOS', +    'domsvc'    => { +                     desc =>'svcnum from svc_domain', +                     type =>'select', +                     select_table => 'svc_domain', +                     select_key   => 'svcnum', +                     select_label => 'domain', +                   }, +  }, +  'svc_domain' => { +    'domain'    => 'Domain', +  }, +  'svc_acct_sm' => { +    'domuser'   => 'domuser@virtualdomain.com', +    'domuid'    => 'UID where domuser@virtualdomain.com mail is forwarded', +    'domsvc'    => 'svcnum from svc_domain for virtualdomain.com', +  }, +  'svc_forward' => { +    'srcsvc'    => 'service from which mail is to be forwarded', +    'dstsvc'    => 'service to which mail is to be forwarded', +    'dst'       => 'someone@another.domain.com to use when dstsvc is 0', +  }, +  'svc_charge' => { +    'amount'    => 'amount', +  }, +  'svc_wo' => { +    'worker'    => 'Worker', +    '_date'      => 'Date', +  }, +  'svc_www' => { +    #'recnum' => '', +    #'usersvc' => '', +  }, +); + +#  svc_acct svc_domain svc_acct_sm svc_charge svc_wo +foreach my $svcdb ( qw( +  konq_kludge svc_acct svc_domain svc_acct_sm svc_forward svc_www +) ) { + +#  my(@fields) = $svcdb eq 'konq_kludge' +#                  ? () +#                  : grep { $_ ne 'svcnum' } fields($svcdb); +  #yucky kludge +  my(@fields) = defined( $FS::Record::dbdef->table($svcdb) ) +                  ? grep { $_ ne 'svcnum' } fields($svcdb) +                  : (); +  #my($rowspan)=scalar(@rows); + +  #my($ptmp)="<TD ROWSPAN=$rowspan>$svcdb</TD>"; +#  $visibility = $svcdb eq $part_svc->svcdb ? "SHOW" : "HIDDEN"; +#  $visibility = $svcdb eq $p_svcdb ? "visible" : "hidden"; +  my $visibility = "hidden"; +%> +<SCRIPT> +if (document.getElementById) { +    document.write("<DIV ID=\"d<%= $svcdb %>\" STYLE=\"visibility: <%= $visibility %>; position: absolute\">"); +} else { +<% $visibility="show" if $visibility eq "visible"; %> +    document.write("<LAYER ID=\"l<%= $svcdb %>\" VISIBILITY=\"<%= $visibility %>\">"); +} + +function fixup(what) { +  what.svc.value = document.dummy.svc.value; +  what.svcdb.value = document.dummy.svcdb.options[document.dummy.svcdb.selectedIndex].value; +  if (document.dummy.disabled.checked) +    what.disabled.value = 'Y'; +  else +    what.disabled.value = ''; +} +</SCRIPT> +<FORM NAME="<%= $svcdb %>" ACTION="process/part_svc.cgi" METHOD=POST onSubmit="fixup(this)"> +<INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $hashref->{svcpart} %>"> +<INPUT TYPE="hidden" NAME="svc" VALUE="<%= $hashref->{svc} %>"> +<INPUT TYPE="hidden" NAME="disabled" VALUE="<%= $hashref->{disabled} %>"> +<INPUT TYPE="hidden" NAME="svcdb" VALUE="<%= $svcdb %>"> +<% +  #print "$svcdb<BR>" unless $svcdb eq 'konq_kludge'; +  print table(). "<TH>Field</TH><TH COLSPAN=2>Modifier</TH>" unless $svcdb eq 'konq_kludge'; + +  foreach my $field (@fields) { +    my $part_svc_column = $part_svc->part_svc_column($field); +    my $value = $cgi->param('error') +                  ? $cgi->param("${svcdb}__${field}") +                  : $part_svc_column->columnvalue; +    my $flag = $cgi->param('error') +                 ? $cgi->param("${svcdb}__${field}_flag") +                 : $part_svc_column->columnflag; +    #print "<TR>$ptmp<TD>$field"; +    print "<TR><TD>$field"; +    my $def = $defs{$svcdb}{$field}; +    my $desc = ref($def) ? $def->{desc} : $def; +     +    print "- <FONT SIZE=-1>$desc</FONT>" if $desc; +    print "</TD>"; +    print qq!<TD><INPUT TYPE="radio" NAME="${svcdb}__${field}_flag" VALUE=""!. +      ' CHECKED'x($flag eq ''). ">Off</TD>"; +    print qq!<TD><INPUT TYPE="radio" NAME="${svcdb}__${field}_flag" VALUE="D"!. +      ' CHECKED'x($flag eq 'D'). ">Default "; +    print qq!<INPUT TYPE="radio" NAME="${svcdb}__${field}_flag" VALUE="F"!. +      ' CHECKED'x($flag eq 'F'). ">Fixed "; +    print '<BR>'; +    if ( ref($def) ) { +      if ( $def->{type} eq 'select' ) { +        print qq!<SELECT NAME="${svcdb}__${field}">!; +        print '<OPTION>' unless $value; +        foreach my $record ( qsearch( $def->{select_table}, {} ) ) { +          my $rvalue = $record->getfield($def->{select_key}); +          print qq!<OPTION VALUE="$rvalue"!. +                ( $rvalue==$value ? ' SELECTED>' : '>' ). +                $record->getfield($def->{select_label}); +        } +      } else { +        print '<font color="#ff0000">unknown type'. $def->{type}; +      } +    } else { +      print qq!<INPUT TYPE="text" NAME="${svcdb}__${field}" VALUE="$value">!; +    } +    print "</TD></TR>\n"; +    #$ptmp=''; +  } +  print "</TABLE>" unless $svcdb eq 'konq_kludge'; + +print qq!\n<BR><INPUT TYPE="submit" VALUE="!, +      $hashref->{svcpart} ? "Apply changes" : "Add service", +      qq!">! unless $svcdb eq 'konq_kludge'; + +  print "</FORM>"; +  print <<END; +    <SCRIPT> +    if (document.getElementById) { +      document.write("</DIV>"); +    } else { +      document.write("</LAYER>"); +    } +    </SCRIPT> +END +} +#print "</TABLE>"; +%> + +<TAG onLoad=" +    if (document.getElementById) { +      document.getElementById('d<%= $p_svcdb %>').style.visibility = 'visible'; +    } else { +      document.l<%= $p_svcdb %>.visibility = 'visible'; +    } +"> + +  </BODY> +</HTML> + diff --git a/httemplate/edit/process/REAL_cust_pkg.cgi b/httemplate/edit/process/REAL_cust_pkg.cgi new file mode 100755 index 000000000..6bed85c19 --- /dev/null +++ b/httemplate/edit/process/REAL_cust_pkg.cgi @@ -0,0 +1,19 @@ +<% + +my $pkgnum = $cgi->param('pkgnum') or die; +my $old = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); +my %hash = $old->hash; +$hash{'setup'} = $cgi->param('setup') ? str2time($cgi->param('setup')) : ''; +$hash{'bill'} = $cgi->param('bill') ? str2time($cgi->param('bill')) : ''; +my $new = new FS::cust_pkg \%hash; + +my $error = $new->replace($old); + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "REAL_cust_pkg.cgi?". $cgi->query_string ); +} else {  +  print $cgi->redirect(popurl(3). "view/cust_pkg.cgi?". $pkgnum); +} + +%> diff --git a/httemplate/edit/process/agent.cgi b/httemplate/edit/process/agent.cgi new file mode 100755 index 000000000..182eeab41 --- /dev/null +++ b/httemplate/edit/process/agent.cgi @@ -0,0 +1,28 @@ +<% + +my $agentnum = $cgi->param('agentnum'); + +my $old = qsearchs('agent',{'agentnum'=>$agentnum}) if $agentnum; + +my $new = new FS::agent ( { +  map { +    $_, scalar($cgi->param($_)); +  } fields('agent') +} ); + +my $error; +if ( $agentnum ) { +  $error=$new->replace($old); +} else { +  $error=$new->insert; +  $agentnum=$new->getfield('agentnum'); +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "agent.cgi?". $cgi->query_string ); +} else {  +  print $cgi->redirect(popurl(3). "browse/agent.cgi"); +} + +%> diff --git a/httemplate/edit/process/agent_type.cgi b/httemplate/edit/process/agent_type.cgi new file mode 100755 index 000000000..67aacfdd5 --- /dev/null +++ b/httemplate/edit/process/agent_type.cgi @@ -0,0 +1,54 @@ +<% + +my $typenum = $cgi->param('typenum'); +my $old = qsearchs('agent_type',{'typenum'=>$typenum}) if $typenum; + +my $new = new FS::agent_type ( { +  map { +    $_, scalar($cgi->param($_)); +  } fields('agent_type') +} ); + +my $error; +if ( $typenum ) { +  $error=$new->replace($old); +} else { +  $error=$new->insert; +  $typenum=$new->getfield('typenum'); +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "agent_type.cgi?". $cgi->query_string ); +} else { + +  foreach my $part_pkg (qsearch('part_pkg',{})) { +    my($pkgpart)=$part_pkg->getfield('pkgpart'); + +    my($type_pkgs)=qsearchs('type_pkgs',{ +        'typenum' => $typenum, +        'pkgpart' => $pkgpart, +    }); +    if ( $type_pkgs && ! $cgi->param("pkgpart$pkgpart") ) { +      my($d_type_pkgs)=$type_pkgs; #need to save $type_pkgs for below. +      $error=$d_type_pkgs->delete; +      die $error if $error; + +    } elsif ( $cgi->param("pkgpart$pkgpart") +              && ! $type_pkgs +    ) { +      #ok to clobber it now (but bad form nonetheless?) +      $type_pkgs=new FS::type_pkgs ({ +        'typenum' => $typenum, +        'pkgpart' => $pkgpart, +      }); +      $error= $type_pkgs->insert; +      die $error if $error; +    } + +  } + +  print $cgi->redirect(popurl(3). "browse/agent_type.cgi"); +} + +%> diff --git a/httemplate/edit/process/cust_bill_pay.cgi b/httemplate/edit/process/cust_bill_pay.cgi new file mode 100755 index 000000000..0c33506a8 --- /dev/null +++ b/httemplate/edit/process/cust_bill_pay.cgi @@ -0,0 +1,31 @@ +<% + +$cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!"; +my $paynum = $1; + +my $cust_pay = qsearchs('cust_pay', { 'paynum' => $paynum } ) +  or die "No such paynum"; + +my $cust_main = qsearchs('cust_main', { 'custnum' => $cust_pay->custnum } ) +  or die "Bogus credit:  not attached to customer"; + +my $custnum = $cust_main->custnum; + +my $new = new FS::cust_bill_pay ( { +  map { +    $_, scalar($cgi->param($_)); +  #} qw(custnum _date amount invnum) +  } fields('cust_bill_pay') +} ); + +my $error = $new->insert; + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "cust_bill_pay.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); +} + + +%> diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi new file mode 100755 index 000000000..ac92631f8 --- /dev/null +++ b/httemplate/edit/process/cust_credit.cgi @@ -0,0 +1,30 @@ +<% + +$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!"; +my $custnum = $1; + +$cgi->param('otaker',getotaker); + +my $new = new FS::cust_credit ( { +  map { +    $_, scalar($cgi->param($_)); +  #} qw(custnum _date amount otaker reason) +  } fields('cust_credit') +} ); + +my $error = $new->insert; + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ); +} else { +  if ( $cgi->param('apply') eq 'yes' ) { +    my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum }) +      or die "unknown custnum $custnum"; +    $cust_main->apply_credits; +  } +  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); +} + + +%> diff --git a/httemplate/edit/process/cust_credit_bill.cgi b/httemplate/edit/process/cust_credit_bill.cgi new file mode 100755 index 000000000..4879b0eab --- /dev/null +++ b/httemplate/edit/process/cust_credit_bill.cgi @@ -0,0 +1,43 @@ +<% + +$cgi->param('crednum') =~ /^(\d*)$/ or die "Illegal crednum!"; +my $crednum = $1; + +my $cust_credit = qsearchs('cust_credit', { 'crednum' => $crednum } ) +  or die "No such crednum"; + +my $cust_main = qsearchs('cust_main', { 'custnum' => $cust_credit->custnum } ) +  or die "Bogus credit:  not attached to customer"; + +my $custnum = $cust_main->custnum; + +my $new; +if ($cgi->param('invnum') =~ /^Refund$/) { +  $new = new FS::cust_refund ( { +    'reason'  => $cust_credit->reason, +    'refund'  => $cgi->param('amount'), +    'payby'   => 'BILL', +    '_date'   => $cgi->param('_date'), +    'payinfo' => 'Cash', +    'crednum' => $crednum, +  } ); +} else { +  $new = new FS::cust_credit_bill ( { +    map { +      $_, scalar($cgi->param($_)); +    #} qw(custnum _date amount invnum) +    } fields('cust_credit_bill') +  } ); +} + +my $error = $new->insert; + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "cust_credit_bill.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); +} + + +%> diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi new file mode 100755 index 000000000..c8038ecf6 --- /dev/null +++ b/httemplate/edit/process/cust_main.cgi @@ -0,0 +1,132 @@ +<% + +my $error = ''; + +#unmunge stuff + +$cgi->param('tax','') unless defined $cgi->param('tax'); + +$cgi->param('refnum', (split(/:/, ($cgi->param('refnum'))[0] ))[0] ); + +$cgi->param('state') =~ /^(\w*)( \(([\w ]+)\))? ?\/ ?(\w+)$/ +  or die "Oops, illegal \"state\" param: ". $cgi->param('state'); +$cgi->param('state', $1); +$cgi->param('county', $3 || ''); +$cgi->param('country', $4); + +$cgi->param('ship_state') =~ /^(\w*)( \(([\w ]+)\))? ?\/ ?(\w+)$/ +  or $cgi->param('ship_state') =~ /^(((())))$/ +  or die "Oops, illegal \"ship_state\" param: ". $cgi->param('ship_state'); +$cgi->param('ship_state', $1); +$cgi->param('ship_county', $3 || ''); +$cgi->param('ship_country', $4); + +my $payby = $cgi->param('payby'); +if ( $payby ) { +  $cgi->param('payinfo', $cgi->param( $payby. '_payinfo' ) ); +  $cgi->param('paydate', +  $cgi->param( $payby. '_month' ). '-'. $cgi->param( $payby. '_year' ) ); +  $cgi->param('payname', $cgi->param( $payby. '_payname' ) ); +} + +$cgi->param('otaker', &getotaker ); + +my @invoicing_list = split( /\s*\,\s*/, $cgi->param('invoicing_list') ); +push @invoicing_list, 'POST' if $cgi->param('invoicing_list_POST'); + +#create new record object + +my $new = new FS::cust_main ( { +  map { +    $_, scalar($cgi->param($_)) +#  } qw(custnum agentnum last first ss company address1 address2 city county +#       state zip daytime night fax payby payinfo paydate payname tax +#       otaker refnum) +  } fields('cust_main') +} ); + +if ( defined($cgi->param('same')) && $cgi->param('same') eq "Y" ) { +  $new->setfield("ship_$_", '') foreach qw( +    last first company address1 address2 city county state zip +    country daytime night fax +  ); +} + +#perhaps this stuff should go to cust_main.pm +my $cust_pkg = ''; +my $svc_acct = ''; +if ( $new->custnum eq '' ) { + +  if ( $cgi->param('pkgpart_svcpart') ) { +    my $x = $cgi->param('pkgpart_svcpart'); +    $x =~ /^(\d+)_(\d+)$/; +    my($pkgpart, $svcpart) = ($1, $2); +    #false laziness: copied from FS::cust_pkg::order (which should become a +    #FS::cust_main method) +    my(%part_pkg); +    # generate %part_pkg +    # $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart +    my $agent = qsearchs('agent',{'agentnum'=> $new->agentnum }); +    	#my($type_pkgs); +    	#foreach $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) { +    	#  my($pkgpart)=$type_pkgs->pkgpart; +    	#  $part_pkg{$pkgpart}++; +    	#} +    # $pkgpart_href->{PKGPART} is true iff $custnum may purchase $pkgpart +    my $pkgpart_href = $agent->pkgpart_hashref; +    #eslaf + +    # this should wind up in FS::cust_pkg! +    $error ||= "Agent ". $new->agentnum. " (type ". $agent->typenum. ") can't". +               "purchase pkgpart ". $pkgpart +      #unless $part_pkg{ $pkgpart }; +      unless $pkgpart_href->{ $pkgpart }; + +    $cust_pkg = new FS::cust_pkg ( { +      #later         'custnum' => $custnum, +      'pkgpart' => $pkgpart, +    } ); +    $error ||= $cust_pkg->check; + +    #$cust_svc = new FS::cust_svc ( { 'svcpart' => $svcpart } ); + +    #$error ||= $cust_svc->check; + +    $svc_acct = new FS::svc_acct ( { +                                     'svcpart'   => $svcpart, +                                     'username'  => $cgi->param('username'), +                                     '_password' => $cgi->param('_password'), +                                     'popnum'    => $cgi->param('popnum'), +                                   } ); + +    my $y = $svc_acct->setdefault; # arguably should be in new method +    $error ||= $y unless ref($y); +    #and just in case you were silly +    $svc_acct->svcpart($svcpart); +    $svc_acct->username($cgi->param('username')); +    $svc_acct->_password($cgi->param('_password')); +    $svc_acct->popnum($cgi->param('popnum')); + +    $error ||= $svc_acct->check; + +  } elsif ( $cgi->param('username') ) { #good thing to catch +    $error = "Can't assign username without a package!"; +  } + +  use Tie::RefHash; +  tie my %hash, 'Tie::RefHash'; +  %hash = ( $cust_pkg => [ $svc_acct ] ) if $cust_pkg; +  $error ||= $new->insert( \%hash, \@invoicing_list ); +} else { #create old record object +  my $old = qsearchs( 'cust_main', { 'custnum' => $new->custnum } );  +  $error ||= "Old record not found!" unless $old; +  $error ||= $new->replace($old, \@invoicing_list); +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "cust_main.cgi?". $cgi->query_string ); +} else {  +  print $cgi->redirect(popurl(3). "view/cust_main.cgi?". $new->custnum); +}  +%> diff --git a/httemplate/edit/process/cust_main_county-collapse.cgi b/httemplate/edit/process/cust_main_county-collapse.cgi new file mode 100755 index 000000000..8e67140a8 --- /dev/null +++ b/httemplate/edit/process/cust_main_county-collapse.cgi @@ -0,0 +1,35 @@ +<% + +my($query) = $cgi->keywords; +$query =~ /^(\d+)$/ or die "Illegal taxnum!"; +my $taxnum = $1; +my $cust_main_county = qsearchs('cust_main_county',{'taxnum'=>$taxnum}) +  or die ("Unknown taxnum!"); + +#really should do this in a .pm & start transaction + +foreach my $delete ( qsearch('cust_main_county', { +                    'country' => $cust_main_county->country, +                    'state' => $cust_main_county->state   +                 } ) ) { +#  unless ( qsearch('cust_main',{ +#    'state'  => $cust_main_county->getfield('state'), +#    'county' => $cust_main_county->getfield('county'), +#    'country' =>  $cust_main_county->getfield('country'), +#  } ) ) { +    my $error = $delete->delete; +    die $error if $error; +#  } else { +    #should really fix the $cust_main record +#  } + +} + +$cust_main_county->taxnum(''); +$cust_main_county->county(''); +my $error = $cust_main_county->insert; +die $error if $error; + +print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi"); + +%> diff --git a/httemplate/edit/process/cust_main_county-expand.cgi b/httemplate/edit/process/cust_main_county-expand.cgi new file mode 100755 index 000000000..64061deed --- /dev/null +++ b/httemplate/edit/process/cust_main_county-expand.cgi @@ -0,0 +1,56 @@ +<% + +$cgi->param('taxnum') =~ /^(\d+)$/ or die "Illegal taxnum!"; +my $taxnum = $1; +my $cust_main_county = qsearchs('cust_main_county',{'taxnum'=>$taxnum}) +  or die ("Unknown taxnum!"); + +my @expansion; +if ( $cgi->param('delim') eq 'n' ) { +  @expansion=split(/\n/,$cgi->param('expansion')); +} elsif ( $cgi->param('delim') eq 's' ) { +  @expansion=split(' ',$cgi->param('expansion')); +} else { +  die "Illegal delim!"; +} + +@expansion=map { +  unless ( /^\s*([\w\- ]+)\s*$/ ) { +    $cgi->param('error', "Illegal item in expansion"); +    print $cgi->redirect(popurl(2). "cust_main_county-expand.cgi?". $cgi->query_string ); +    myexit(); +  } +  $1; +} @expansion; + +foreach ( @expansion) { +  my(%hash)=$cust_main_county->hash; +  my($new)=new FS::cust_main_county \%hash; +  $new->setfield('taxnum',''); +  if ( ! $cust_main_county->state ) { +    $new->setfield('state',$_); +  } else { +    $new->setfield('county',$_); +  } +  #if (datasrc =~ m/Pg/) +  #{ +  #    $new->setfield('tax',0.0); +  #} +  my($error)=$new->insert; +  die $error if $error; +} + +unless ( qsearch( 'cust_main', { +                                 'state'  => $cust_main_county->state, +                                 'county' => $cust_main_county->county, +                                 'country' =>  $cust_main_county->country, +                               } ) +         || ! @expansion +) { +  my($error)=($cust_main_county->delete); +  die $error if $error; +} + +print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi"); + +%> diff --git a/httemplate/edit/process/cust_main_county.cgi b/httemplate/edit/process/cust_main_county.cgi new file mode 100755 index 000000000..0800789b5 --- /dev/null +++ b/httemplate/edit/process/cust_main_county.cgi @@ -0,0 +1,22 @@ +<% + +foreach ( $cgi->param ) { +  /^tax(\d+)$/ or die "Illegal form $_!"; +  my($taxnum)=$1; +  my($old)=qsearchs('cust_main_county',{'taxnum'=>$taxnum}) +    or die "Couldn't find taxnum $taxnum!"; +  next unless $old->getfield('tax') ne $cgi->param("tax$taxnum"); +  my(%hash)=$old->hash; +  $hash{tax}=$cgi->param("tax$taxnum"); +  my($new)=new FS::cust_main_county \%hash; +  my($error)=$new->replace($old); +  if ( $error ) { +    $cgi->param('error', $error); +    print $cgi->redirect(popurl(2). "cust_main_county.cgi?". $cgi->query_string ); +    myexit(); +  } +} + +print $cgi->redirect(popurl(3). "browse/cust_main_county.cgi"); + +%> diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi new file mode 100755 index 000000000..82442ae00 --- /dev/null +++ b/httemplate/edit/process/cust_pay.cgi @@ -0,0 +1,39 @@ +<% + +$cgi->param('linknum') =~ /^(\d+)$/ +  or die "Illegal linknum: ". $cgi->param('linknum'); +my $linknum = $1; + +$cgi->param('link') =~ /^(custnum|invnum)$/ +  or die "Illegal link: ". $cgi->param('link'); +my $link = $1; + +my $new = new FS::cust_pay ( { +  $link => $linknum, +  map { +    $_, scalar($cgi->param($_)); +  } qw(paid _date payby payinfo paybatch) +  #} fields('cust_pay') +} ); + +my $error = $new->insert; + +if ($error) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). 'cust_pay.cgi?'. $cgi->query_string ); +} elsif ( $link eq 'invnum' ) { +  print $cgi->redirect(popurl(3). "view/cust_bill.cgi?$linknum"); +} elsif ( $link eq 'custnum' ) { +  if ( $cgi->param('apply') eq 'yes' ) { +    my $cust_main = qsearchs('cust_main', { 'custnum' => $linknum }) +      or die "unknown custnum $linknum"; +    $cust_main->apply_payments; +  } +  if ( $cgi->param('quickpay') eq 'yes' ) { +    print $cgi->redirect(popurl(3). "search/cust_main-quickpay.html"); +  } else { +    print $cgi->redirect(popurl(3). "view/cust_main.cgi?$linknum"); +  } +} + +%> diff --git a/httemplate/edit/process/cust_pkg.cgi b/httemplate/edit/process/cust_pkg.cgi new file mode 100755 index 000000000..f8c9f5151 --- /dev/null +++ b/httemplate/edit/process/cust_pkg.cgi @@ -0,0 +1,36 @@ +<% + +my $error = ''; + +#untaint custnum +$cgi->param('custnum') =~ /^(\d+)$/; +my $custnum = $1; + +my @remove_pkgnums = map { +  /^(\d+)$/ or die "Illegal remove_pkg value!"; +  $1; +} $cgi->param('remove_pkg'); + +my @pkgparts; +foreach my $pkgpart ( map /^pkg(\d+)$/ ? $1 : (), $cgi->param ) { +  if ( $cgi->param("pkg$pkgpart") =~ /^(\d+)$/ ) { +    my $num_pkgs = $1; +    while ( $num_pkgs-- ) { +      push @pkgparts,$pkgpart; +    } +  } else { +    $error = "Illegal quantity"; +    last; +  } +} + +$error ||= FS::cust_pkg::order($custnum,\@pkgparts,\@remove_pkgnums); + +if ($error) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "cust_pkg.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); +} + +%> diff --git a/httemplate/edit/process/part_bill_event.cgi b/httemplate/edit/process/part_bill_event.cgi new file mode 100755 index 000000000..4049ade80 --- /dev/null +++ b/httemplate/edit/process/part_bill_event.cgi @@ -0,0 +1,53 @@ +<% + +my $eventpart = $cgi->param('eventpart'); + +my $old = qsearchs('part_bill_event',{'eventpart'=>$eventpart}) if $eventpart; + +#s/days/seconds/ +$cgi->param('seconds', $cgi->param('days') * 86400 ); + +my $error; +if ( ! $cgi->param('plan_weight_eventcode') ) { +  $error = "Must select an action"; +} else { + +  $cgi->param('plan_weight_eventcode') =~ /^([\w\-]+):(\d+):(.*)$/ +    or die "illegal plan_weight_eventcode:". +           $cgi->param('plan_weight_eventcode'); +  $cgi->param('plan', $1); +  $cgi->param('weight', $2); +  my $eventcode = $3; +  my $plandata = ''; +  while ( $eventcode =~ /%%%(\w+)%%%/ ) { +    my $field = $1; +    my $value = $cgi->param($field); +    $eventcode =~ s/%%%$field%%%/$value/; +    $plandata .= "$field $value\n"; +  } +  $cgi->param('eventcode', $eventcode); +  $cgi->param('plandata', $plandata); + +  my $new = new FS::part_bill_event ( { +    map { +      $_, scalar($cgi->param($_)); +    } fields('part_bill_event'), +  } ); + +  if ( $eventpart ) { +    $error = $new->replace($old); +  } else { +    $error = $new->insert; +    $eventpart = $new->getfield('eventpart'); +  } +}  + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "part_bill_event.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3)."browse/part_bill_event.cgi"); +} + +%> + diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi new file mode 100755 index 000000000..d489426f9 --- /dev/null +++ b/httemplate/edit/process/part_pkg.cgi @@ -0,0 +1,109 @@ +<% + +my $dbh = dbh; + +my $pkgpart = $cgi->param('pkgpart'); + +my $old = qsearchs('part_pkg',{'pkgpart'=>$pkgpart}) if $pkgpart; + +#fixup plandata +my $plandata = $cgi->param('plandata'); +my @plandata = split(',', $plandata); +$cgi->param('plandata',  +  join('', map { "$_=". join(', ', $cgi->param($_)). "\n" } @plandata ) +); + +foreach (qw( setuptax recurtax disabled )) { +  $cgi->param($_, '') unless defined $cgi->param($_); +} + +my $new = new FS::part_pkg ( { +  map { +    $_, scalar($cgi->param($_)); +  } fields('part_pkg') +} ); + +#warn "setuptax: ". $new->setuptax; +#warn "recurtax: ". $new->recurtax; + +#most of the stuff below should move to part_pkg.pm + +foreach my $part_svc ( qsearch('part_svc', {} ) ) { +  my $quantity = $cgi->param('pkg_svc'. $part_svc->svcpart) || 0; +  unless ( $quantity =~ /^(\d+)$/ ) { +    $cgi->param('error', "Illegal quantity" ); +    print $cgi->redirect(popurl(2). "part_pkg.cgi?". $cgi->query_string ); +    myexit(); +  } +} + +local $SIG{HUP} = 'IGNORE'; +local $SIG{INT} = 'IGNORE'; +local $SIG{QUIT} = 'IGNORE'; +local $SIG{TERM} = 'IGNORE'; +local $SIG{TSTP} = 'IGNORE'; +local $SIG{PIPE} = 'IGNORE'; + +local $FS::UID::AutoCommit = 0; + +my $error; +if ( $pkgpart ) { +  $error = $new->replace($old); +} else { +  $error = $new->insert; +  $pkgpart=$new->pkgpart; +} +if ( $error ) { +  $dbh->rollback; +  $cgi->param('error', $error ); +  print $cgi->redirect(popurl(2). "part_pkg.cgi?". $cgi->query_string ); +  myexit(); +} + +foreach my $part_svc (qsearch('part_svc',{})) { +  my $quantity = $cgi->param('pkg_svc'. $part_svc->svcpart) || 0; +  my $old_pkg_svc = qsearchs('pkg_svc', { +    'pkgpart' => $pkgpart, +    'svcpart' => $part_svc->svcpart, +  } ); +  my $old_quantity = $old_pkg_svc ? $old_pkg_svc->quantity : 0; +  next unless $old_quantity != $quantity; #!here +  my $new_pkg_svc = new FS::pkg_svc( { +    'pkgpart'  => $pkgpart, +    'svcpart'  => $part_svc->svcpart, +    'quantity' => $quantity,  +  } ); +  if ( $old_pkg_svc ) { +    my $myerror = $new_pkg_svc->replace($old_pkg_svc); +    if ( $myerror ) { +      $dbh->rollback; +      die $myerror; +    } +  } else { +    my $myerror = $new_pkg_svc->insert; +    if ( $myerror ) { +      $dbh->rollback; +      die $myerror; +    } +  } +} + +unless ( $cgi->param('pkgnum') && $cgi->param('pkgnum') =~ /^(\d+)$/ ) { +  $dbh->commit or die $dbh->errstr; +  print $cgi->redirect(popurl(3). "browse/part_pkg.cgi"); +} else { +  my($old_cust_pkg) = qsearchs( 'cust_pkg', { 'pkgnum' => $1 } ); +  my %hash = $old_cust_pkg->hash; +  $hash{'pkgpart'} = $pkgpart; +  my($new_cust_pkg) = new FS::cust_pkg \%hash; +  my $myerror = $new_cust_pkg->replace($old_cust_pkg); +  if ( $myerror ) { +    $dbh->rollback; +    die "Error modifying cust_pkg record: $myerror\n"; +  } + +  $dbh->commit or die $dbh->errstr; +  print $cgi->redirect(popurl(3). "view/cust_main.cgi?". $new_cust_pkg->custnum); +} + +%> diff --git a/httemplate/edit/process/part_referral.cgi b/httemplate/edit/process/part_referral.cgi new file mode 100755 index 000000000..fd2c01506 --- /dev/null +++ b/httemplate/edit/process/part_referral.cgi @@ -0,0 +1,28 @@ +<% + +my $refnum = $cgi->param('refnum'); + +my $new = new FS::part_referral ( { +  map { +    $_, scalar($cgi->param($_)); +  } fields('part_referral') +} ); + +my $error; +if ( $refnum ) { +  my $old = qsearchs( 'part_referral', { 'refnum' =>$ refnum } ); +  die "(Old) Record not found!" unless $old; +  $error = $new->replace($old); +} else { +  $error = $new->insert; +} +$refnum=$new->refnum; + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "part_referral.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "browse/part_referral.cgi"); +} + +%> diff --git a/httemplate/edit/process/part_svc.cgi b/httemplate/edit/process/part_svc.cgi new file mode 100755 index 000000000..423db93b5 --- /dev/null +++ b/httemplate/edit/process/part_svc.cgi @@ -0,0 +1,35 @@ +<% + +my $svcpart = $cgi->param('svcpart'); + +my $old = qsearchs('part_svc',{'svcpart'=>$svcpart}) if $svcpart; + +my $new = new FS::part_svc ( { +  map { +    $_, scalar($cgi->param($_)); +#  } qw(svcpart svc svcdb) +  } ( fields('part_svc'), +      map { my $svcdb = $_; +            map { ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' )  } +              fields($svcdb) +          } grep defined( $FS::Record::dbdef->table($_) ), +                 qw( svc_acct svc_domain svc_acct_sm svc_forward svc_www ) +    ) +} ); + +my $error; +if ( $svcpart ) { +  $error = $new->replace($old, '1.3-COMPAT'); +} else { +  $error = $new->insert; +  $svcpart=$new->getfield('svcpart'); +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "part_svc.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3)."browse/part_svc.cgi"); +} + +%> diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi new file mode 100644 index 000000000..c663dce32 --- /dev/null +++ b/httemplate/edit/process/quick-cust_pkg.cgi @@ -0,0 +1,24 @@ +<% + +#untaint custnum +$cgi->param('custnum') =~ /^(\d+)$/ +  or eidiot 'illegal custnum '. $cgi->param('custnum'); +my $custnum = $1; +$cgi->param('pkgpart') =~ /^(\d+)$/ +  or eidiot 'illegal pkgpart '. $cgi->param('pkgpart'); +my $pkgpart = $1; + +my @cust_pkg = (); +my $error = FS::cust_pkg::order($custnum, [ $pkgpart ], [], \@cust_pkg, ); + +if ($error) { +%> +<!-- mason kludge --> +<% +  eidiot($error); +} else { +  print $cgi->redirect(popurl(3). "view/cust_pkg.cgi?". $cust_pkg[0]->pkgnum ); +} + +%> + diff --git a/httemplate/edit/process/svc_acct.cgi b/httemplate/edit/process/svc_acct.cgi new file mode 100755 index 000000000..5e8a16f4a --- /dev/null +++ b/httemplate/edit/process/svc_acct.cgi @@ -0,0 +1,46 @@ +<% + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; + +my $old; +if ( $svcnum ) { +  $old = qsearchs('svc_acct', { 'svcnum' => $svcnum } ) +    or die "fatal: can't find account (svcnum $svcnum)!"; +} else { +  $old = ''; +} + +#unmunge popnum +$cgi->param('popnum', (split(/:/, $cgi->param('popnum') ))[0] ); + +#unmunge passwd +if ( $cgi->param('_password') eq '*HIDDEN*' ) { +  die "fatal: no previous account to recall hidden password from!" unless $old; +  $cgi->param('_password',$old->getfield('_password')); +} + +my $new = new FS::svc_acct ( { +  map { +    $_, scalar($cgi->param($_)); +  #} qw(svcnum pkgnum svcpart username _password popnum uid gid finger dir +  #  shell quota slipip) +  } ( fields('svc_acct'), qw( pkgnum svcpart ) ) +} ); + +my $error; +if ( $svcnum ) { +  $error = $new->replace($old); +} else { +  $error = $new->insert; +  $svcnum = $new->svcnum; +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "svc_acct.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/svc_acct.cgi?" . $svcnum ); +} + +%> diff --git a/httemplate/edit/process/svc_acct_pop.cgi b/httemplate/edit/process/svc_acct_pop.cgi new file mode 100755 index 000000000..46ad74d62 --- /dev/null +++ b/httemplate/edit/process/svc_acct_pop.cgi @@ -0,0 +1,28 @@ +<% + +my $popnum = $cgi->param('popnum'); + +my $old = qsearchs('svc_acct_pop',{'popnum'=>$popnum}) if $popnum; + +my $new = new FS::svc_acct_pop ( { +  map { +    $_, scalar($cgi->param($_)); +  } fields('svc_acct_pop') +} ); + +my $error = ''; +if ( $popnum ) { +  $error = $new->replace($old); +} else { +  $error = $new->insert; +  $popnum=$new->getfield('popnum'); +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "svc_acct_pop.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "browse/svc_acct_pop.cgi"); +} + +%> diff --git a/httemplate/edit/process/svc_acct_sm.cgi b/httemplate/edit/process/svc_acct_sm.cgi new file mode 100755 index 000000000..41d03fb92 --- /dev/null +++ b/httemplate/edit/process/svc_acct_sm.cgi @@ -0,0 +1,34 @@ +<% + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum =$1; + +my $old = qsearchs('svc_acct_sm',{'svcnum'=>$svcnum}) if $svcnum; + +#unmunge domsvc and domuid +#$cgi->param('domsvc',(split(/:/, $cgi->param('domsvc') ))[0] ); +#$cgi->param('domuid',(split(/:/, $cgi->param('domuid') ))[0] ); + +my $new = new FS::svc_acct_sm ( { +  map { +    ($_, scalar($cgi->param($_))); +  #} qw(svcnum pkgnum svcpart domuser domuid domsvc) +  } ( fields('svc_acct_sm'), qw( pkgnum svcpart ) ) +} ); + +my $error = ''; +if ( $svcnum ) { +  $error = $new->replace($old); +} else { +  $error = $new->insert; +  $svcnum = $new->getfield('svcnum'); +}  + +if ($error) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "svc_acct_sm.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/svc_acct_sm.cgi?$svcnum"); +} + +%> diff --git a/httemplate/edit/process/svc_domain.cgi b/httemplate/edit/process/svc_domain.cgi new file mode 100755 index 000000000..19f8eb4f8 --- /dev/null +++ b/httemplate/edit/process/svc_domain.cgi @@ -0,0 +1,31 @@ +<% + +#remove this to actually test the domains! +$FS::svc_domain::whois_hack = 1; + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; + +my $new = new FS::svc_domain ( { +  map { +    $_, scalar($cgi->param($_)); +  #} qw(svcnum pkgnum svcpart domain action purpose) +  } ( fields('svc_domain'), qw( pkgnum svcpart action purpose ) ) +} ); + +my $error = ''; +if ($cgi->param('svcnum')) { +  $error="Can't modify a domain!"; +} else { +  $error=$new->insert; +  $svcnum=$new->svcnum; +} + +if ($error) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "svc_domain.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/svc_domain.cgi?$svcnum"); +} + +%> diff --git a/httemplate/edit/process/svc_forward.cgi b/httemplate/edit/process/svc_forward.cgi new file mode 100755 index 000000000..bb066d8a6 --- /dev/null +++ b/httemplate/edit/process/svc_forward.cgi @@ -0,0 +1,29 @@ +<% + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum =$1; + +my $old = qsearchs('svc_forward',{'svcnum'=>$svcnum}) if $svcnum; + +my $new = new FS::svc_forward ( { +  map { +    ($_, scalar($cgi->param($_))); +  } ( fields('svc_forward'), qw( pkgnum svcpart ) ) +} ); + +my $error = ''; +if ( $svcnum ) { +  $error = $new->replace($old); +} else { +  $error = $new->insert; +  $svcnum = $new->getfield('svcnum'); +}  + +if ($error) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "svc_forward.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/svc_forward.cgi?$svcnum"); +} + +%> diff --git a/httemplate/edit/process/svc_www.cgi b/httemplate/edit/process/svc_www.cgi new file mode 100644 index 000000000..38d5e1c79 --- /dev/null +++ b/httemplate/edit/process/svc_www.cgi @@ -0,0 +1,36 @@ +<% + +$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; +my $svcnum = $1; + +my $old; +if ( $svcnum ) { +  $old = qsearchs('svc_acct', { 'svcnum' => $svcnum } ) +    or die "fatal: can't find account (svcnum $svcnum)!"; +} else { +  $old = ''; +} + +my $new = new FS::svc_www ( { +  map { +    ($_, scalar($cgi->param($_))); +  #} qw(svcnum pkgnum svcpart recnum usersvc) +  } ( fields('svc_www'), qw( pkgnum svcpart ) ) +} ); + +my $error; +if ( $svcnum ) { +  $error = $new->replace($old); +} else { +  $error = $new->insert; +  $svcnum = $new->svcnum; +} + +if ( $error ) { +  $cgi->param('error', $error); +  print $cgi->redirect(popurl(2). "svc_www.cgi?". $cgi->query_string ); +} else { +  print $cgi->redirect(popurl(3). "view/svc_www.cgi?" . $svcnum ); +} + +%> diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi new file mode 100755 index 000000000..d147a1683 --- /dev/null +++ b/httemplate/edit/svc_acct.cgi @@ -0,0 +1,251 @@ +<!-- mason kludge --> +<% + +my $conf = new FS::Conf; +my @shells = $conf->config('shells'); + +my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_acct); +if ( $cgi->param('error') ) { +  $svc_acct = new FS::svc_acct ( { +    map { $_, scalar($cgi->param($_)) } fields('svc_acct') +  } ); +  $svcnum = $svc_acct->svcnum; +  $pkgnum = $cgi->param('pkgnum'); +  $svcpart = $cgi->param('svcpart'); +  $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +  die "No part_svc entry!" unless $part_svc; +} else { +  my($query) = $cgi->keywords; +  if ( $query =~ /^(\d+)$/ ) { #editing +    $svcnum=$1; +    $svc_acct=qsearchs('svc_acct',{'svcnum'=>$svcnum}) +      or die "Unknown (svc_acct) svcnum!"; + +    my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum}) +      or die "Unknown (cust_svc) svcnum!"; + +    $pkgnum=$cust_svc->pkgnum; +    $svcpart=$cust_svc->svcpart; + +    $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +  } else { #adding + +    $svc_acct = new FS::svc_acct({});  + +    foreach $_ (split(/-/,$query)) { +      $pkgnum=$1 if /^pkgnum(\d+)$/; +      $svcpart=$1 if /^svcpart(\d+)$/; +    } +    $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +    $svcnum=''; + +    #set gecos +    my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); +    if ($cust_pkg) { +      my($cust_main)=qsearchs('cust_main',{'custnum'=> $cust_pkg->custnum } ); +      unless ( $part_svc->part_svc_column('uid')->columnflag eq 'F' ) { +        $svc_acct->setfield('finger', +          $cust_main->getfield('first') . " " . $cust_main->getfield('last') +        ); +      } +    } + +    #set fixed and default fields from part_svc +    foreach my $part_svc_column ( +      grep { $_->columnflag } $part_svc->all_part_svc_column +    ) { +      $svc_acct->setfield( $part_svc_column->columnname, +                           $part_svc_column->columnvalue, +                         ); +    } + +  } +} +my $action = $svcnum ? 'Edit' : 'Add'; + +my $svc = $part_svc->getfield('svc'); + +my $otaker = getotaker; + +my $username = $svc_acct->username; +my $password; +if ( $svc_acct->_password ) { +  if ( $conf->exists('showpasswords') || ! $svcnum ) { +    $password = $svc_acct->_password; +  } else { +    $password = "*HIDDEN*"; +  } +} else { +  $password = ''; +} + +my $ulen = $conf->config('usernamemax') +           || $svc_acct->dbdef_table->column('username')->length; +my $ulen2 = $ulen+2; + +my $pmax = $conf->config('passwordmax') || 8; +my $pmax2 = $pmax+2; + +my $p1 = popurl(1); +print header("$action $svc account"); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT><BR><BR>" +  if $cgi->param('error'); + +print 'Service # '. ( $svcnum ? "<B>$svcnum</B>" : " (NEW)" ). '<BR>'. +      'Service: <B>'. $part_svc->svc. '</B><BR><BR>'. +      <<END; +    <FORM ACTION="${p1}process/svc_acct.cgi" METHOD=POST> +      <INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum"> +      <INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum"> +      <INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart"> +END + +print &ntable("#cccccc",2), <<END; +<TR><TD ALIGN="right">Username</TD> +<TD><INPUT TYPE="text" NAME="username" VALUE="$username" SIZE=$ulen2 MAXLENGTH=$ulen></TD></TR> +<TR><TD ALIGN="right">Password</TD> +<TD><INPUT TYPE="text" NAME="_password" VALUE="$password" SIZE=$pmax2 MAXLENGTH=$pmax> +(blank to generate)</TD> +</TR> +END + +#domain +my $domsvc = $svc_acct->domsvc || 0; +if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'F' ) { +  print qq!<INPUT TYPE="hidden" NAME="domsvc" VALUE="$domsvc">!; +} else {  +  my %svc_domain = (); + +  if ( $domsvc ) { +    my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $domsvc, } ); +    if ( $svc_domain ) { +      $svc_domain{$svc_domain->svcnum} = $svc_domain; +    } else { +      warn "unknown svc_domain.svcnum for svc_acct.domsvc: $domsvc"; +    } +  } + +  if ( $part_svc->part_svc_column('domsvc')->columnflag eq 'D' ) { +    my $svc_domain = qsearchs('svc_domain', { +      'svcnum' => $part_svc->part_svc_column('domsvc')->columnvalue, +    } ); +    if ( $svc_domain ) { +      $svc_domain{$svc_domain->svcnum} = $svc_domain; +    } else { +      warn "unknown svc_domain.svcnum for part_svc_column domsvc: ". +           $part_svc->part_svc_column('domsvc')->columnvalue; +    } +  } + +  my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } ); +  if ($cust_pkg) { +    my @cust_svc = +      map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) } +          qsearch('cust_pkg', { 'custnum' => $cust_pkg->custnum } ); +    foreach my $cust_svc ( @cust_svc ) { +      my $svc_domain = +        qsearchs('svc_domain', { 'svcnum' => $cust_svc->svcnum } ); +     $svc_domain{$svc_domain->svcnum} = $svc_domain if $svc_domain; +    } +  } else { +    %svc_domain = map { $_->svcnum => $_ } qsearch('svc_domain', {} ); +  } +  print qq!<TR><TD ALIGN="right">Domain</TD>!. +        qq!<TD><SELECT NAME="domsvc" SIZE=1>\n!; +  foreach my $svcnum ( +    sort { $svc_domain{$a}->domain cmp $svc_domain{$b}->domain } +      keys %svc_domain +  ) { +    my $svc_domain = $svc_domain{$svcnum}; +    print qq!<OPTION VALUE="!. $svc_domain->svcnum. qq!"!. +          ( $svc_domain->svcnum == $domsvc ? ' SELECTED' : '' ). +          '>'. $svc_domain->domain. "\n" ; +  } +  print "</SELECT></TD></TR>"; +} + +#pop +my $popnum = $svc_acct->popnum || 0; +if ( $part_svc->part_svc_column('popnum')->columnflag eq "F" ) { +  print qq!<INPUT TYPE="hidden" NAME="popnum" VALUE="$popnum">!; +} else {  +  print qq!<TR><TD ALIGN="right">Access number</TD>!. +        qq!<TD>!. FS::svc_acct_pop::popselector($popnum). '</TD></TR>'; +} + +my($uid,$gid,$finger,$dir)=( +  $svc_acct->uid, +  $svc_acct->gid, +  $svc_acct->finger, +  $svc_acct->dir, +); + +print <<END; +<INPUT TYPE="hidden" NAME="uid" VALUE="$uid"> +<INPUT TYPE="hidden" NAME="gid" VALUE="$gid"> +END + +if ( !$finger && $part_svc->part_svc_column('uid')->columnflag eq 'F' ) { +  print '<INPUT TYPE="hidden" NAME="finger" VALUE="">'; +} else { +  print '<TR><TD ALIGN="right">GECOS</TD>'. +        qq!<TD><INPUT TYPE="text" NAME="finger" VALUE="$finger"></TD></TR>!; +} +print qq!<INPUT TYPE="hidden" NAME="dir" VALUE="$dir">!; + +my $shell = $svc_acct->shell; +if ( $part_svc->part_svc_column('shell')->columnflag eq "F" +     || ( !$shell && $part_svc->part_svc_column('uid')->columnflag eq 'F' ) +   ) { +  print qq!<INPUT TYPE="hidden" NAME="shell" VALUE="$shell">!; +} else { +  print qq!<TR><TD ALIGN="right">Shell</TD><TD><SELECT NAME="shell" SIZE=1>!; +  my($etc_shell); +  foreach $etc_shell (@shells) { +    print "<OPTION", $etc_shell eq $shell ? ' SELECTED' : '', ">", +          $etc_shell, "\n"; +  } +  print "</SELECT></TD></TR>"; +} + +my($quota,$slipip)=( +  $svc_acct->quota, +  $svc_acct->slipip, +); + +print qq!<INPUT TYPE="hidden" NAME="quota" VALUE="$quota">!; + +if ( $part_svc->part_svc_column('slipip')->columnflag eq "F" ) { +  print qq!<INPUT TYPE="hidden" NAME="slipip" VALUE="$slipip">!; +} else { +  print qq!<TR><TD ALIGN="right">IP</TD><TD><INPUT TYPE="text" NAME="slipip" VALUE="$slipip"></TD></TR>!; +} + +foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) { +  $r =~ /^^r(adius|[cr])_(.+)$/ or next; #? +  my $a = $2; +  if ( $part_svc->part_svc_column($r)->columnflag eq 'F' ) { +    print qq!<INPUT TYPE="hidden" NAME="$r" VALUE="!. +          $svc_acct->getfield($r). '">'; +  } else { +    print qq!<TR><TD ALIGN="right">$FS::raddb::attrib{$a}</TD><TD><INPUT TYPE="text" NAME="$r" VALUE="!. +          $svc_acct->getfield($r). '"></TD></TR>'; +  } +} + +#submit +print qq!</TABLE><BR><INPUT TYPE="submit" VALUE="Submit">!;  + +print <<END; +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/svc_acct_pop.cgi b/httemplate/edit/svc_acct_pop.cgi new file mode 100755 index 000000000..399502a70 --- /dev/null +++ b/httemplate/edit/svc_acct_pop.cgi @@ -0,0 +1,56 @@ +<!-- mason kludge --> +<% + +my $svc_acct_pop; +if ( $cgi->param('error') ) { +  $svc_acct_pop = new FS::svc_acct_pop ( { +    map { $_, scalar($cgi->param($_)) } fields('svc_acct_pop') +  } ); +} elsif ( $cgi->keywords ) { #editing +  my($query)=$cgi->keywords; +  $query =~ /^(\d+)$/; +  $svc_acct_pop=qsearchs('svc_acct_pop',{'popnum'=>$1}); +} else { #adding +  $svc_acct_pop = new FS::svc_acct_pop {}; +} +my $action = $svc_acct_pop->popnum ? 'Edit' : 'Add'; +my $hashref = $svc_acct_pop->hashref; + +my $p1 = popurl(1); +print header("$action Access Number", menubar( +  'Main Menu' => popurl(2), +  'View all Access Numbers' => popurl(2). "browse/svc_acct_pop.cgi", +)); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print qq!<FORM ACTION="${p1}process/svc_acct_pop.cgi" METHOD=POST>!; + +#display + +print qq!<INPUT TYPE="hidden" NAME="popnum" VALUE="$hashref->{popnum}">!, +      "POP #", $hashref->{popnum} ? $hashref->{popnum} : "(NEW)"; + +print <<END; +<PRE> +City      <INPUT TYPE="text" NAME="city" SIZE=32 VALUE="$hashref->{city}"> +State     <INPUT TYPE="text" NAME="state" SIZE=16 MAXLENGTH=16 VALUE="$hashref->{state}"> +Area Code <INPUT TYPE="text" NAME="ac" SIZE=4 MAXLENGTH=3 VALUE="$hashref->{ac}"> +Exchange  <INPUT TYPE="text" NAME="exch" SIZE=4 MAXLENGTH=3 VALUE="$hashref->{exch}"> +Local     <INPUT TYPE="text" NAME="loc" SIZE=5 MAXLENGTH=4 VALUE="$hashref->{loc}"> +</PRE> +END + +print qq!<BR><INPUT TYPE="submit" VALUE="!, +      $hashref->{popnum} ? "Apply changes" : "Add Access Number", +      qq!">!; + +print <<END; +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/svc_acct_sm.cgi b/httemplate/edit/svc_acct_sm.cgi new file mode 100755 index 000000000..0fd5f7622 --- /dev/null +++ b/httemplate/edit/svc_acct_sm.cgi @@ -0,0 +1,178 @@ +<!-- mason kludge --> +<% + +my $conf = new FS::Conf; +my $mydomain = $conf->config('domain'); + +my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_acct_sm ); +if ( $cgi->param('error') ) { +  $svc_acct_sm = new FS::svc_acct_sm ( { +    map { $_, scalar($cgi->param($_)) } fields('svc_acct_sm') +  } ); +  $svcnum = $svc_acct_sm->svcnum; +  $pkgnum = $cgi->param('pkgnum'); +  $svcpart = $cgi->param('svcpart'); +  #$part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +  #die "No part_svc entry!" unless $part_svc; +} else { +  my($query) = $cgi->keywords; +  if ( $query =~ /^(\d+)$/ ) { #editing +    $svcnum=$1; +    $svc_acct_sm=qsearchs('svc_acct_sm',{'svcnum'=>$svcnum}) +      or die "Unknown (svc_acct_sm) svcnum!"; + +    my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum}) +      or die "Unknown (cust_svc) svcnum!"; + +    $pkgnum=$cust_svc->pkgnum; +    $svcpart=$cust_svc->svcpart; +   +    #$part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    #die "No part_svc entry!" unless $part_svc; + +  } else { #adding + +    $svc_acct_sm = new FS::svc_acct_sm({}); + +    foreach $_ (split(/-/,$query)) { #get & untaint pkgnum & svcpart +      $pkgnum=$1 if /^pkgnum(\d+)$/; +      $svcpart=$1 if /^svcpart(\d+)$/; +    } +    my $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +    $svcnum=''; + +    #set fixed and default fields from part_svc +    foreach my $part_svc_column ( +      grep { $_->columnflag } $part_svc->all_part_svc_column +    ) { +      $svc_acct_sm->setfield( $part_svc_column->columnname, +                              $part_svc_column->columnvalue, +                            ); +    } + +  } +} +my $action = $svc_acct_sm->svcnum ? 'Edit' : 'Add'; + +my %username = (); +my %domain = (); +if ($pkgnum) { + +  #find all possible uids (and usernames) + +  my @u_acct_svcparts = (); +  foreach my $u_part_svc ( qsearch('part_svc',{'svcdb'=>'svc_acct'}) ) { +    push @u_acct_svcparts,$u_part_svc->getfield('svcpart'); +  } + +  my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); +  my($custnum)=$cust_pkg->getfield('custnum'); +  foreach my $i_cust_pkg ( qsearch('cust_pkg',{'custnum'=>$custnum}) ) { +    my($cust_pkgnum)=$i_cust_pkg->getfield('pkgnum'); +    my($acct_svcpart); +    foreach $acct_svcpart (@u_acct_svcparts) {   #now find the corresponding  +                                              #record(s) in cust_svc ( for this +                                              #pkgnum ! ) +      my($i_cust_svc); +      foreach $i_cust_svc ( qsearch('cust_svc',{'pkgnum'=>$cust_pkgnum,'svcpart'=>$acct_svcpart}) ) { +        my($svc_acct)=qsearchs('svc_acct',{'svcnum'=>$i_cust_svc->getfield('svcnum')}); +        $username{$svc_acct->getfield('uid')}=$svc_acct->getfield('username'); +      }   +    } +  } + +  #find all possible domains (and domsvc's) + +  my @d_acct_svcparts = (); +  foreach my $d_part_svc ( qsearch('part_svc',{'svcdb'=>'svc_domain'}) ) { +    push @d_acct_svcparts,$d_part_svc->getfield('svcpart'); +  } + +  foreach $i_cust_pkg ( qsearch('cust_pkg',{'custnum'=>$custnum}) ) { +    my($cust_pkgnum)=$i_cust_pkg->getfield('pkgnum'); +    my($acct_svcpart); +    foreach $acct_svcpart (@d_acct_svcparts) { +      my($i_cust_svc); +      foreach $i_cust_svc ( qsearch('cust_svc',{'pkgnum'=>$cust_pkgnum,'svcpart'=>$acct_svcpart}) ) { +        my($svc_domain)=qsearch('svc_domain',{'svcnum'=>$i_cust_svc->getfield('svcnum')}); +        $domain{$svc_domain->getfield('svcnum')}=$svc_domain->getfield('domain'); +      } +    } +  } + +} elsif ( $action eq 'Edit' ) { + +  my($svc_acct)=qsearchs('svc_acct',{'uid'=>$svc_acct_sm->domuid}); +  $username{$svc_acct_sm->uid} = $svc_acct->username; + +  my($svc_domain)=qsearchs('svc_domain',{'svcnum'=>$svc_acct_sm->domsvc}); +  $domain{$svc_acct_sm->domsvc} = $svc_domain->domain; + +} else { +  die "\$action eq Add, but \$pkgnum is null!\n"; +} + +my $p1 = popurl(1); +print header("Mail Alias $action", ''); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print qq!<FORM ACTION="${p1}process/svc_acct_sm.cgi" METHOD=POST>!; + +#display + +	#formatting +	print "<PRE>"; + +#svcnum +print qq!<INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum">!; +print qq!Service #<FONT SIZE=+1><B>!, $svcnum ? $svcnum : " (NEW)", "</B></FONT>"; + +#pkgnum +print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!; +  +#svcpart +print qq!<INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart">!; + +my($domuser,$domsvc,$domuid)=( +  $svc_acct_sm->domuser, +  $svc_acct_sm->domsvc, +  $svc_acct_sm->domuid, +); + +#domuser +print qq!\n\nMail to <INPUT TYPE="text" NAME="domuser" VALUE="$domuser"> <I>( * for anything )</I>!; + +#domsvc +print qq! \@ <SELECT NAME="domsvc" SIZE=1>!; +foreach $_ (keys %domain) { +  print "<OPTION", $_ eq $domsvc ? " SELECTED" : "", +        qq! VALUE="$_">$domain{$_}!; +} +print "</SELECT>"; + +#uid +print qq!\nforwards to <SELECT NAME="domuid" SIZE=1>!; +foreach $_ (keys %username) { +  print "<OPTION", ($_ eq $domuid) ? " SELECTED" : "", +        qq! VALUE="$_">$username{$_}!; +} +print "</SELECT>\@$mydomain mailbox."; + +	#formatting +	print "</PRE>\n"; + +print qq!<CENTER><INPUT TYPE="submit" VALUE="Submit"></CENTER>!; + +print <<END; + +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi new file mode 100755 index 000000000..d20e1f336 --- /dev/null +++ b/httemplate/edit/svc_domain.cgi @@ -0,0 +1,98 @@ +<!-- mason kludge --> +<% + +my($svcnum, $pkgnum, $svcpart, $kludge_action, $purpose, $part_svc, +   $svc_domain); +if ( $cgi->param('error') ) { +  $svc_domain = new FS::svc_domain ( { +    map { $_, scalar($cgi->param($_)) } fields('svc_domain') +  } ); +  $svcnum = $svc_domain->svcnum; +  $pkgnum = $cgi->param('pkgnum'); +  $svcpart = $cgi->param('svcpart'); +  $kludge_action = $cgi->param('action'); +  $purpose = $cgi->param('purpose'); +  $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } ); +  die "No part_svc entry!" unless $part_svc; +} else { +  $kludge_action = ''; +  $purpose = ''; +  my($query) = $cgi->keywords; +  if ( $query =~ /^(\d+)$/ ) { #editing +    $svcnum=$1; +    $svc_domain=qsearchs('svc_domain',{'svcnum'=>$svcnum}) +      or die "Unknown (svc_domain) svcnum!"; + +    my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum}) +      or die "Unknown (cust_svc) svcnum!"; + +    $pkgnum=$cust_svc->pkgnum; +    $svcpart=$cust_svc->svcpart; + +    $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +  } else { #adding + +    $svc_domain = new FS::svc_domain({}); +   +    foreach $_ (split(/-/,$query)) { +      $pkgnum=$1 if /^pkgnum(\d+)$/; +      $svcpart=$1 if /^svcpart(\d+)$/; +    } +    $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +    $svcnum=''; + +    #set fixed and default fields from part_svc +    foreach my $part_svc_column ( +      grep { $_->columnflag } $part_svc->all_part_svc_column +    ) { +      $svc_domain->setfield( $part_svc_column->columnname, +                             $part_svc_column->columnvalue, +                           ); +    } + +  } + +} +my $action = $svcnum ? 'Edit' : 'Add'; + +my $svc = $part_svc->getfield('svc'); + +my $otaker = getotaker; + +my $domain = $svc_domain->domain; + +my $p1 = popurl(1); +print header("$action $svc", ''); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print <<END; +    <FORM ACTION="${p1}process/svc_domain.cgi" METHOD=POST> +      <INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum"> +      <INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum"> +      <INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart"> +END + +print qq!<INPUT TYPE="radio" NAME="action" VALUE="N"!; +print ' CHECKED' if $kludge_action eq 'N'; +print qq!>New!; +print qq!<BR><INPUT TYPE="radio" NAME="action" VALUE="M"!; +print ' CHECKED' if $kludge_action eq 'M'; +print qq!>Transfer!; + +print <<END; +<P>Domain <INPUT TYPE="text" NAME="domain" VALUE="$domain" SIZE=28 MAXLENGTH=26> +<BR>Purpose/Description: <INPUT TYPE="text" NAME="purpose" VALUE="$purpose" SIZE=64> +<P><INPUT TYPE="submit" VALUE="Submit"> +    </FORM> +  </BODY> +</HTML> +END + +%> diff --git a/httemplate/edit/svc_forward.cgi b/httemplate/edit/svc_forward.cgi new file mode 100755 index 000000000..5f1466bbb --- /dev/null +++ b/httemplate/edit/svc_forward.cgi @@ -0,0 +1,223 @@ +<!-- mason kludge --> +<% + +my $conf = new FS::Conf; +my $mydomain = $conf->config('domain'); + +my($svcnum, $pkgnum, $svcpart, $part_svc, $svc_forward); +if ( $cgi->param('error') ) { +  $svc_forward = new FS::svc_forward ( { +    map { $_, scalar($cgi->param($_)) } fields('svc_forward') +  } ); +  $svcnum = $svc_forward->svcnum; +  $pkgnum = $cgi->param('pkgnum'); +  $svcpart = $cgi->param('svcpart'); +  $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +  die "No part_svc entry!" unless $part_svc; +} else { + +  my($query) = $cgi->keywords; + +  if ( $query =~ /^(\d+)$/ ) { #editing +    $svcnum=$1; +    $svc_forward=qsearchs('svc_forward',{'svcnum'=>$svcnum}) +      or die "Unknown (svc_forward) svcnum!"; + +    my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum}) +      or die "Unknown (cust_svc) svcnum!"; + +    $pkgnum=$cust_svc->pkgnum; +    $svcpart=$cust_svc->svcpart; +   +    $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +  } else { #adding + +    $svc_forward = new FS::svc_forward({}); + +    foreach $_ (split(/-/,$query)) { #get & untaint pkgnum & svcpart +      $pkgnum=$1 if /^pkgnum(\d+)$/; +      $svcpart=$1 if /^svcpart(\d+)$/; +    } +    $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); +    die "No part_svc entry!" unless $part_svc; + +    $svcnum=''; + +    #set fixed and default fields from part_svc +    foreach my $part_svc_column ( +      grep { $_->columnflag } $part_svc->all_part_svc_column +    ) { +      $svc_forward->setfield( $part_svc_column->columnname, +                              $part_svc_column->columnvalue, +                            ); +    } +  } + +} +my $action = $svc_forward->svcnum ? 'Edit' : 'Add'; + +my %email; +if ($pkgnum) { + +  #find all possible user svcnums (and emails) + +  #starting with those currently attached +  if ( $svc_forward->srcsvc ) { +    my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $svc_forward->srcsvc } ); +    $email{$svc_forward->srcsvc} = $svc_acct->email; +  } +  if ( $svc_forward->dstsvc ) { +    my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $svc_forward->dstsvc } ); +    $email{$svc_forward->dstsvc} = $svc_acct->email; +  } + +  #and including the rest for this customer +  my($u_part_svc,@u_acct_svcparts); +  foreach $u_part_svc ( qsearch('part_svc',{'svcdb'=>'svc_acct'}) ) { +    push @u_acct_svcparts,$u_part_svc->getfield('svcpart'); +  } + +  my($cust_pkg)=qsearchs('cust_pkg',{'pkgnum'=>$pkgnum}); +  my($custnum)=$cust_pkg->getfield('custnum'); +  my($i_cust_pkg); +  foreach $i_cust_pkg ( qsearch('cust_pkg',{'custnum'=>$custnum}) ) { +    my($cust_pkgnum)=$i_cust_pkg->getfield('pkgnum'); +    my($acct_svcpart); +    foreach $acct_svcpart (@u_acct_svcparts) {   #now find the corresponding  +                                              #record(s) in cust_svc ( for this +                                              #pkgnum ! ) +      foreach my $i_cust_svc ( +        qsearch( 'cust_svc', { 'pkgnum'  => $cust_pkgnum, +                               'svcpart' => $acct_svcpart } ) +      ) { +        my $svc_acct = +          qsearchs( 'svc_acct', { 'svcnum' => $i_cust_svc->svcnum } ); +        $email{$svc_acct->svcnum} = $svc_acct->email; +      }   +    } +  } + +} elsif ( $action eq 'Edit' ) { + +  my($svc_acct)=qsearchs('svc_acct',{'svcnum'=>$svc_forward->srcsvc}); +  $email{$svc_forward->srcsvc} = $svc_acct->email; + +  $svc_acct=qsearchs('svc_acct',{'svcnum'=>$svc_forward->dstsvc}); +  $email{$svc_forward->dstsvc} = $svc_acct->email; + +} else { +  die "\$action eq Add, but \$pkgnum is null!\n"; +} + +my($srcsvc,$dstsvc,$dst)=( +  $svc_forward->srcsvc, +  $svc_forward->dstsvc, +  $svc_forward->dst, +); + +#display + +my $p1 = popurl(1); +print header("Mail Forward $action", '', +      " onLoad=\"visualize()\""); + +%> + +<SCRIPT> +function visualize(what){ +    if (document.getElementById) { +      document.getElementById('dother').style.visibility = '<%= $dstsvc ? 'hidden' : 'visible' %>'; +    } +} +function fixup(what){ +    if (document.getElementById) { +      if (document.getElementById('dother').style.visibility == 'hidden') { +        what.dst.value=''; +      } +    } +} +</SCRIPT> + +<% + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), +      "</FONT>" +  if $cgi->param('error'); + +print qq!<FORM ACTION="${p1}process/svc_forward.cgi" onSubmit="fixup(this)" METHOD=POST>!; + +#svcnum +print qq!<INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum">!; +print qq!Service #<FONT SIZE=+1><B>!, $svcnum ? $svcnum : " (NEW)", "</B></FONT>"; +print qq!<BR>!; + +#pkgnum +print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!; +  +#svcpart +print qq!<INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart">!; + +#srcsvc +print qq!\n\nMail to <SELECT NAME="srcsvc" SIZE=1>!; +foreach $_ (keys %email) { +  print "<OPTION", $_ eq $srcsvc ? " SELECTED" : "", +        qq! VALUE="$_">$email{$_}!; +} +print "</SELECT>"; + +#dstsvc +print qq! forwards to <SELECT NAME="dstsvc" SIZE=1 onChange="changed(this)">!; +foreach $_ (keys %email) { +  print "<OPTION", $_ eq $dstsvc ? " SELECTED" : "", +        qq! VALUE="$_">$email{$_}!; +} +print "<OPTION", 0 eq $dstsvc ? " SELECTED" : "", +      qq! VALUE="0">(other)!; +print "</SELECT> mailbox."; + +%> + +<SCRIPT> +var selectchoice = null; +function changed(what) { +  selectchoice = what.options[what.selectedIndex].value; +  if (selectchoice == "0") { +    if (document.getElementById) { +      document.getElementById('dother').style.visibility = "visible"; +    } +  }else{ +    if (document.getElementById) { +      document.getElementById('dother').style.visibility = "hidden"; +    } +  } +} +if (document.getElementById) { +    document.write("<DIV ID=\"dother\" STYLE=\"visibility: hidden\">"); +} +</SCRIPT> + +<% +print qq! Other destination: <INPUT TYPE="text" NAME="dst" VALUE="$dst">!; +%> + +<SCRIPT> +if (document.getElementById) { +    document.write("</DIV>"); +} +</SCRIPT> + +<CENTER><INPUT TYPE="submit" VALUE="Submit"></CENTER> +</FORM> + +<TAG onLoad=" +    if (document.getElementById) { +      document.getElementById('dother').style.visibility = '<%= $dstsvc ? 'hidden' : 'visible' %>'; +      document.getElementById('dlabel').style.visibility = '<%= $dstsvc ? 'hidden' : 'visible' %>'; +    } +"> + + +  </BODY> +</HTML>  | 
