X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=httemplate%2Fedit%2Fprocess%2Fcust_refund.cgi;h=d582b128fc40e5fe17ce73b12183101b361d2e51;hp=8f63c1f782a0d6826a4ad649beb065f3baebd2f9;hb=3e3283b104c41a663e7599097dfcc2f33ccbbbbf;hpb=31ce194a3315d3a5a69869b11947d63fc135d9a0 diff --git a/httemplate/edit/process/cust_refund.cgi b/httemplate/edit/process/cust_refund.cgi index 8f63c1f78..d582b128f 100755 --- a/httemplate/edit/process/cust_refund.cgi +++ b/httemplate/edit/process/cust_refund.cgi @@ -1,34 +1,285 @@ -%$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!"; -%my $custnum = $1; -%my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) -% or die "unknown custnum $custnum"; -% -%my $error = ''; -%if ( $cgi->param('payby') =~ /^(CARD|CHEK)$/ ) { -% my $bop = FS::payby::payby2bop->{$1}; -% $cgi->param('refund') =~ /^(\d*)(\.\d{2})?$/ -% or die "illegal refund amount ". $cgi->param('refund'); -% my $refund = "$1$2"; -% $cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!"; -% my $paynum = $1; -% my $reason = $cgi->param('reason'); -% $error = $cust_main->realtime_refund_bop( $bop, 'amount' => $refund, -% 'paynum' => $paynum, -% 'reason' => $reason, ); -%} else { -% die 'unimplemented'; -% #my $new = new FS::cust_refund ( { -% # map { -% # $_, scalar($cgi->param($_)); -% # } ( fields('cust_refund'), 'paynum' ) -% #} ); -% #$error = $new->insert; -%} -% -% %if ( $error ) { % $cgi->param('error', $error); -% print $cgi->redirect(popurl(2). "cust_refund.cgi?". $cgi->query_string ); +<% $cgi->redirect(popurl(2). "cust_refund.cgi?". $cgi->query_string ) %> %} else { -% print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); +% +% if ( $link eq 'popup' ) { +% +<& /elements/header-popup.html, 'Refund entered' &> + + + +% } else { +<% $cgi->redirect(popurl(3). "view/cust_main.cgi?custnum=$custnum;show=payment_history") %> +% } %} +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Refund payment') + || $FS::CurrentUser::CurrentUser->access_right('Post refund'); + +my $conf = new FS::Conf; + +$cgi->param('custnum') =~ /^(\d*)$/ or die "Illegal custnum!"; +my $custnum = $1; +my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or die "unknown custnum $custnum"; + +my $link = $cgi->param('popup') ? 'popup' : ''; + +my $payby = $cgi->param('payby'); + +die "access denied" + unless $FS::CurrentUser::CurrentUser->refund_access_right($payby); + +$cgi->param('reasonnum') =~ /^(-?\d+)$/ or die "Illegal reasonnum"; +my ($reasonnum, $error) = $m->comp('/misc/process/elements/reason'); +$cgi->param('reasonnum', $reasonnum) unless $error; + +if ( $cgi->param('batch') ) { + $error = "No batch download format configured that allows electronic refunds via batch processing." + unless (FS::pay_batch->can_handle_electronic_refunds && !$error); +} + +#die "my error\n".$error; + +if ( $error ) { + # do nothing +} elsif ( $payby =~ /^(CARD|CHEK)$/ ) { + my %options = (); + my $bop = $FS::payby::payby2bop{$1}; + + my %payby2fields = ( + 'CARD' => [ qw( address1 address2 city county state zip country ) ], + 'CHEK' => [ qw( ss paytype paystate stateid stateid_state ) ], + ); + my %type = ( 'CARD' => 'credit card', + 'CHEK' => 'electronic check (ACH)', + ); + +my( $cust_pay, $cust_payby, $payinfo, $paycvv, $month, $year, $payname, $paycardtype ); +my $paymask = ''; + +## get cust pay info if paynum exists +if ( $cgi->param('paynum') > 0) { + $cust_pay = qsearchs({ + 'table' => 'cust_pay', + 'hashref' => { 'paynum' => $cgi->param('paynum') }, + 'select' => 'cust_pay.*, cust_pay_batch.payname ', + 'addl_from' => "left join cust_pay_batch on cust_pay_batch.batchnum = cust_pay.batchnum and cust_pay_batch.custnum = $custnum ", + }); +} + +if ( (my $custpaybynum = scalar($cgi->param('custpaybynum'))) > 0 ) { + + ## + # use stored cust_payby info + ## + + $cust_payby = qsearchs('cust_payby', { custnum => $custnum, + custpaybynum => $custpaybynum, } ) + or die "unknown custpaybynum $custpaybynum"; + + # not needed for realtime_bop, but still needed for batch_card + $payinfo = $cust_payby->payinfo; + $paymask = $cust_payby->paymask; + $paycvv = $cust_payby->paycvv; # pass it if we got it, running a transaction will clear it + ( $month, $year ) = $cust_payby->paydate_mon_year; + $payname = $cust_payby->payname; + $cgi->param(-name=>"paytype", -value=>$cust_payby->paytype) unless $cgi->param("paytype"); + +} elsif ( $cgi->param('paynum') > 0) { + + $payinfo = $cust_pay->payinfo; + $paycardtype = $cust_pay->paycardtype; + $payname = $cust_pay->payname; + +} else { + + ## + # use new info + ## + + $cgi->param('year') =~ /^(\d+)$/ + or errorpage("illegal year ". $cgi->param('year')); + $year = $1; + + $cgi->param('month') =~ /^(\d+)$/ + or errorpage("illegal month ". $cgi->param('month')); + $month = $1; + + $cgi->param('payname') =~ /^([\w \,\.\-\']+)$/ + or errorpage(gettext('illegal_name'). " payname: ". $cgi->param('payname')); + $payname = $1; + + if ( $payby eq 'CHEK' ) { + + $cgi->param('payinfo1') =~ /^(\d+)$/ + or errorpage("Illegal account number ". $cgi->param('payinfo1')); + my $payinfo1 = $1; + $cgi->param('payinfo2') =~ /^(\d+)$/ + or errorpage("Illegal ABA/routing number ". $cgi->param('payinfo2')); + my $payinfo2 = $1; + if ( $conf->config('echeck-country') eq 'CA' ) { + $cgi->param('payinfo3') =~ /^(\d{5})$/ + or errorpage("Illegal branch number ". $cgi->param('payinfo2')); + $payinfo2 = "$1.$payinfo2"; + } + $payinfo = $payinfo1 . '@'. $payinfo2; + + } elsif ( $payby eq 'CARD' ) { + + $payinfo = $cgi->param('payinfo'); + + $payinfo =~ s/\D//g; + $payinfo =~ /^(\d{13,19}|\d{8,9})$/ + or errorpage(gettext('invalid_card')); + $payinfo = $1; + validate($payinfo) + or errorpage(gettext('invalid_card')); + + unless ( $cust_main->tokenized($payinfo) ) { #token + + my $cardtype = cardtype($payinfo); + + errorpage(gettext('unknown_card_type')) + if $cardtype eq "Unknown"; + + my %bop_card_types = map { $_=>1 } values %{ card_types() }; + errorpage("$cardtype not accepted") unless $bop_card_types{$cardtype}; + + } + + if ( length($cgi->param('paycvv') ) ) { + if ( cardtype($payinfo) eq 'American Express card' ) { + $cgi->param('paycvv') =~ /^(\d{4})$/ + or errorpage("CVV2 (CID) for American Express cards is four digits."); + $paycvv = $1; + } else { + $cgi->param('paycvv') =~ /^(\d{3})$/ + or errorpage("CVV2 (CVC2/CID) is three digits."); + $paycvv = $1; + } + } elsif ( $conf->exists('backoffice-require_cvv') ){ + errorpage("CVV2 is required"); + } + + } else { + die "unknown payby $payby"; + } + + # save first, for proper tokenization + if ( $cgi->param('save') ) { + + my %saveopt; + if ( $payby eq 'CARD' ) { + my $bill_location = FS::cust_location->new; + $bill_location->set( $_ => scalar($cgi->param($_)) ) + foreach @{$payby2fields{$payby}}; + $saveopt{'bill_location'} = $bill_location; + $saveopt{'paycvv'} = $paycvv; # save_cust_payby contains conf logic for when to use this + $saveopt{'paydate'} = "$year-$month-01"; + } else { + # ss/stateid/stateid_state won't be saved, but should be harmless to pass + %saveopt = map { $_ => scalar($cgi->param($_)) } @{$payby2fields{$payby}}; + } + + my $error = $cust_main->save_cust_payby( + 'saved_cust_payby' => \$cust_payby, + 'payment_payby' => $payby, + 'auto' => scalar($cgi->param('auto')), + 'weight' => scalar($cgi->param('weight')), + 'payinfo' => $payinfo, + 'payname' => $payname, + %saveopt + ); + + errorpage("error saving info, payment not processed: $error") + if $error; + + } elsif ( $payby eq 'CARD' ) { # not saving + + $paymask = FS::payinfo_Mixin->mask_payinfo('CARD',$payinfo); # for untokenized but tokenizable payinfo + + } + +} + +## +# now run the refund +## + + $cgi->param('refund') =~ /^(\d*)(\.\d{2})?$/ + or die "illegal refund amount ". $cgi->param('refund'); + my $refund = "$1$2"; + $cgi->param('paynum') =~ /^(\d*)$/ or die "Illegal paynum!"; + my $paynum = $1; + my $paydate; + unless ($paynum) { + if ($cust_payby->paydate) { $paydate = "$year-$month-01"; } + else { $paydate = "2037-12-01"; } + } + + if ( $cgi->param('batch') ) { + $paydate = "2037-12-01" unless $paydate; + $error ||= $cust_main->batch_card( + 'payby' => $payby, + 'amount' => $refund, + 'payinfo' => $payinfo, + 'paydate' => $paydate, + 'payname' => $payname, + 'paycode' => 'C', + map { $_ => scalar($cgi->param($_)) } + @{$payby2fields{$payby}} + ); + errorpage($error) if $error; + + my %hash = map { + $_, scalar($cgi->param($_)) + } fields('cust_refund'); + + $hash{'payinfo'} = $payinfo; + $hash{'paymask'} = $paymask; + $hash{'paycardtype'} = $paycardtype; + + ## unapply payment before creating refund. + while ( $cust_pay && $cust_pay->unapplied < $refund ) { + my @cust_bill_pay = $cust_pay->cust_bill_pay; + last unless @cust_bill_pay; + my $cust_bill_pay = pop @cust_bill_pay; + my $error = $cust_bill_pay->delete; + last if $error; + } + + my $new = new FS::cust_refund ( { 'paynum' => $paynum, + %hash, + } ); + $error = $new->insert; + + # if not a batch refund run realtime. + } else { + $error = $cust_main->realtime_refund_bop( $bop, 'amount' => $refund, + 'paynum' => $paynum, + 'reasonnum' => scalar($cgi->param('reasonnum')), + %options ); + } +} else { # run cash refund. + my %hash = map { + $_, scalar($cgi->param($_)) + } fields('cust_refund'); + my $paynum = $cgi->param('paynum'); + $paynum =~ /^(\d*)$/ or die "Illegal paynum!"; + if ($paynum) { + my $cust_pay = qsearchs('cust_pay',{ 'paynum' => $paynum }); + die "Could not find paynum $paynum" unless $cust_pay; + $error = $cust_pay->refund(\%hash); + } else { + my $new = new FS::cust_refund ( \%hash ); + $error = $new->insert; + } +} + +