X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main.pm;h=c1a8aafdee9dbde3456de3d202d0f47c20865baf;hb=7b125e587a4d1ee0aca692e23ea7897f671855ae;hp=9c16294905824723eb50c3b1e62b514c349df97e;hpb=fd93bd0bf90836be82c5271bb36e46cca83735f4;p=freeside.git diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 9c1629490..c1a8aafde 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -62,7 +62,6 @@ use FS::queue; use FS::part_pkg; use FS::part_event; use FS::part_event_condition; -use FS::part_export; #use FS::cust_event; use FS::type_pkgs; use FS::payment_gateway; @@ -87,7 +86,7 @@ $skip_fuzzyfiles = 0; @fuzzyfields = ( 'first', 'last', 'company', 'address1' ); @encrypted_fields = ('payinfo', 'paycvv'); -sub nohistory_fields { ('payinfo', 'paycvv'); } +sub nohistory_fields { ('paycvv'); } @paytypes = ('', 'Personal checking', 'Personal savings', 'Business checking', 'Business savings'); @@ -547,45 +546,6 @@ sub insert { } } - # cust_main exports! - warn " exporting\n" if $DEBUG > 1; - - my $export_args = $options{'export_args'} || []; - - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_main-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_insert($self, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; - } - } - - #foreach my $depend_jobnum ( @$depend_jobnums ) { - # warn "[$me] inserting dependancies on supplied job $depend_jobnum\n" - # if $DEBUG; - # foreach my $jobnum ( @jobnums ) { - # my $queue = qsearchs('queue', { 'jobnum' => $jobnum } ); - # warn "[$me] inserting dependancy for job $jobnum on $depend_jobnum\n" - # if $DEBUG; - # my $error = $queue->depend_insert($depend_jobnum); - # if ( $error ) { - # $dbh->rollback if $oldAutoCommit; - # return "error queuing job dependancy: $error"; - # } - # } - # } - # - #} - # - #if ( exists $options{'jobnums'} ) { - # push @{ $options{'jobnums'} }, @jobnums; - #} - warn " insert complete; committing transaction\n" if $DEBUG > 1; @@ -1380,23 +1340,6 @@ sub delete { return $error; } - # cust_main exports! - - #my $export_args = $options{'export_args'} || []; - - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_main-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_delete( $self ); #, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; - } - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -1510,15 +1453,8 @@ sub replace { } - if ( $self->payby =~ /^(CARD|CHEK|LECB)$/ - && ( ( $self->get('payinfo') ne $old->get('payinfo') - && $self->get('payinfo') !~ /^99\d{14}$/ - ) - || grep { $self->get($_) ne $old->get($_) } qw(paydate payname) - ) - ) - { - + if ( $self->payby =~ /^(CARD|CHEK|LECB)$/ && + grep { $self->get($_) ne $old->get($_) } qw(payinfo paydate payname) ) { # card/check/lec info has changed, want to retry realtime_ invoice events my $error = $self->retry_realtime; if ( $error ) { @@ -1535,23 +1471,6 @@ sub replace { } } - # cust_main exports! - - my $export_args = $options{'export_args'} || []; - - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_main-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_replace( $self, $old, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; - } - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -1789,7 +1708,12 @@ sub check { # If it is encrypted and the private key is not availaible then we can't # check the credit card. - my $check_payinfo = ! $self->is_encrypted($self->payinfo); + + my $check_payinfo = 1; + + if ($self->is_encrypted($self->payinfo)) { + $check_payinfo = 0; + } if ( $check_payinfo && $self->payby =~ /^(CARD|DCRD)$/ ) { @@ -1803,8 +1727,7 @@ sub check { or return gettext('invalid_card'); # . ": ". $self->payinfo; return gettext('unknown_card_type') - if $self->payinfo !~ /^99\d{14}$/ #token - && cardtype($self->payinfo) eq "Unknown"; + if cardtype($self->payinfo) eq "Unknown"; my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref); if ( $ban ) { @@ -4316,7 +4239,6 @@ sub _bop_options { $options->{payment_gateway}->gatewaynum ? $options->{payment_gateway}->options : @{ $options->{payment_gateway}->get('options') }; - } sub _bop_defaults { @@ -4343,6 +4265,14 @@ sub _bop_content { my ($self, $options) = @_; my %content = (); + $content{address} = exists($options->{'address1'}) + ? $options->{'address1'} + : $self->address1; + my $address2 = exists($options->{'address2'}) + ? $options->{'address2'} + : $self->address2; + $content{address} .= ", ". $address2 if length($address2); + my $payip = exists($options->{'payip'}) ? $options->{'payip'} : $self->payip; $content{customer_ip} = $payip if length($payip); @@ -4353,30 +4283,14 @@ sub _bop_content { ( $conf->exists('business-onlinepayment-email_customer') || $conf->exists('business-onlinepayment-email-override') ); - my ($payname, $payfirst, $paylast); - if ( $options->{payname} && $options->{method} ne 'ECHECK' ) { - ($payname = $options->{payname}) =~ - /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ - or return "Illegal payname $payname"; - ($payfirst, $paylast) = ($1, $2); - } else { - $payfirst = $self->getfield('first'); - $paylast = $self->getfield('last'); - $payname = "$payfirst $paylast"; - } + $content{payfirst} = $self->getfield('first'); + $content{paylast} = $self->getfield('last'); - $content{last_name} = $paylast; - $content{first_name} = $payfirst; + $content{account_name} = "$content{payfirst} $content{paylast}" + if $options->{method} eq 'ECHECK'; - $content{name} = $payname; - - $content{address} = exists($options->{'address1'}) - ? $options->{'address1'} - : $self->address1; - my $address2 = exists($options->{'address2'}) - ? $options->{'address2'} - : $self->address2; - $content{address} .= ", ". $address2 if length($address2); + $content{name} = $options->{payname}; + $content{name} = $content{account_name} if exists($content{account_name}); $content{city} = exists($options->{city}) ? $options->{city} @@ -4390,11 +4304,10 @@ sub _bop_content { $content{country} = exists($options->{country}) ? $options->{country} : $self->country; - $content{referer} = 'http://cleanwhisker.420.am/'; #XXX fix referer :/ $content{phone} = $self->daytime || $self->night; - \%content; + (%content); } my %bop_method2payby = ( @@ -4470,8 +4383,13 @@ sub realtime_bop { # massage data ### - my $bop_content = $self->_bop_content(\%options); - return $bop_content unless ref($bop_content); + my (%bop_content) = $self->_bop_content(\%options); + + if ( $options{method} ne 'ECHECK' ) { + $options{payname} =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ + or return "Illegal payname $options{payname}"; + ($bop_content{payfirst}, $bop_content{paylast}) = ($1, $2); + } my @invoicing_list = $self->invoicing_list_emailonly; if ( $conf->exists('emailinvoiceautoalways') @@ -4537,9 +4455,6 @@ sub realtime_bop { $content{account_type} = exists($options{'paytype'}) ? uc($options{'paytype'}) || 'CHECKING' : uc($self->getfield('paytype')) || 'CHECKING'; - $content{account_name} = $self->getfield('first'). ' '. - $self->getfield('last'); - $content{customer_org} = $self->company ? 'B' : 'I'; $content{state_id} = exists($options{'stateid'}) ? $options{'stateid'} @@ -4624,7 +4539,7 @@ sub realtime_bop { 'amount' => $options{amount}, #'invoice_number' => $options{'invnum'}, 'customer_id' => $self->custnum, - %$bop_content, + %bop_content, 'reference' => $cust_pay_pending->paypendingnum, #for now 'email' => $email, %content, #after @@ -4639,8 +4554,6 @@ sub realtime_bop { my $BOP_TESTING_SUCCESS = 1; unless ( $BOP_TESTING ) { - $transaction->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $transaction->submit(); } else { if ( $BOP_TESTING_SUCCESS ) { @@ -4693,8 +4606,6 @@ sub realtime_bop { $capture->content( %capture ); - $capture->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $capture->submit(); unless ( $capture->is_success ) { @@ -4724,25 +4635,6 @@ sub realtime_bop { } ### - # Tokenize - ### - - - if ( $transaction->can('card_token') && $transaction->card_token ) { - - $self->card_token($transaction->card_token); - - if ( $options{'payinfo'} eq $self->payinfo ) { - $self->payinfo($transaction->card_token); - my $error = $self->replace; - if ( $error ) { - warn "WARNING: error storing token: $error, but proceeding anyway\n"; - } - } - - } - - ### # result handling ### @@ -4865,7 +4757,7 @@ sub _realtime_bop_result { 'paid' => $cust_pay_pending->paid, '_date' => '', 'payby' => $cust_pay_pending->payby, - 'payinfo' => $options{'payinfo'}, + #'payinfo' => $payinfo, 'paybatch' => $paybatch, 'paydate' => $cust_pay_pending->paydate, 'pkgnum' => $cust_pay_pending->pkgnum, @@ -5269,7 +5161,7 @@ sub realtime_refund_bop { my $self = shift; my %options = (); - if (ref($_[0]) eq 'HASH') { + if (ref($_[0]) ne 'HASH') { %options = %{$_[0]}; } else { my $method = shift; @@ -5401,8 +5293,6 @@ sub realtime_refund_bop { } } $void->content( 'action' => 'void', %content ); - $void->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $void->submit(); if ( $void->is_success ) { my $error = $cust_pay->void($options{'reason'}); @@ -5505,8 +5395,6 @@ sub realtime_refund_bop { ); warn join('', map { " $_ => $sub_content{$_}\n" } keys %sub_content ) if $DEBUG > 1; - $refund->test_transaction(1) - if $conf->exists('business-onlinepayment-test_transaction'); $refund->submit(); return "$processor error: ". $refund->error_message @@ -5945,17 +5833,29 @@ sub total_owed_date { my $self = shift; my $time = shift; - my $custnum = $self->custnum; - - my $owed_sql = FS::cust_bill->owed_sql; - - my $sql = " - SELECT SUM($owed_sql) FROM cust_bill - WHERE custnum = $custnum - AND _date <= $time - "; +# my $custnum = $self->custnum; +# +# my $owed_sql = FS::cust_bill->owed_sql; +# +# my $sql = " +# SELECT SUM($owed_sql) FROM cust_bill +# WHERE custnum = $custnum +# AND _date <= $time +# "; +# +# my $sth = dbh->prepare($sql) or die dbh->errstr; +# $sth->execute() or die $sth->errstr; +# +# return sprintf( '%.2f', $sth->fetchrow_arrayref->[0] ); - sprintf( "%.2f", $self->scalar_sql($sql) ); + my $total_bill = 0; + foreach my $cust_bill ( + grep { $_->_date <= $time } + qsearch('cust_bill', { 'custnum' => $self->custnum, } ) + ) { + $total_bill += $cust_bill->owed; + } + sprintf( "%.2f", $total_bill ); } @@ -6025,18 +5925,9 @@ sub total_credited { sub total_unapplied_credits { my $self = shift; - - my $custnum = $self->custnum; - - my $unapplied_sql = FS::cust_credit->unapplied_sql; - - my $sql = " - SELECT SUM($unapplied_sql) FROM cust_credit - WHERE custnum = $custnum - "; - - sprintf( "%.2f", $self->scalar_sql($sql) ); - + my $total_credit = 0; + $total_credit += $_->credited foreach $self->cust_credit; + sprintf( "%.2f", $total_credit ); } =item total_unapplied_credits_pkgnum PKGNUM @@ -6063,18 +5954,9 @@ See L. sub total_unapplied_payments { my $self = shift; - - my $custnum = $self->custnum; - - my $unapplied_sql = FS::cust_pay->unapplied_sql; - - my $sql = " - SELECT SUM($unapplied_sql) FROM cust_pay - WHERE custnum = $custnum - "; - - sprintf( "%.2f", $self->scalar_sql($sql) ); - + my $total_unapplied = 0; + $total_unapplied += $_->unapplied foreach $self->cust_pay; + sprintf( "%.2f", $total_unapplied ); } =item total_unapplied_payments_pkgnum PKGNUM @@ -6102,17 +5984,9 @@ customer. See L. sub total_unapplied_refunds { my $self = shift; - my $custnum = $self->custnum; - - my $unapplied_sql = FS::cust_refund->unapplied_sql; - - my $sql = " - SELECT SUM($unapplied_sql) FROM cust_refund - WHERE custnum = $custnum - "; - - sprintf( "%.2f", $self->scalar_sql($sql) ); - + my $total_unapplied = 0; + $total_unapplied += $_->unapplied foreach $self->cust_refund; + sprintf( "%.2f", $total_unapplied ); } =item balance @@ -6124,7 +5998,12 @@ total_unapplied_credits minus total_unapplied_payments). sub balance { my $self = shift; - $self->balance_date_range; + sprintf( "%.2f", + $self->total_owed + + $self->total_unapplied_refunds + - $self->total_unapplied_credits + - $self->total_unapplied_payments + ); } =item balance_date TIME @@ -6139,13 +6018,19 @@ functions. sub balance_date { my $self = shift; - $self->balance_date_range(shift); + my $time = shift; + sprintf( "%.2f", + $self->total_owed_date($time) + + $self->total_unapplied_refunds + - $self->total_unapplied_credits + - $self->total_unapplied_payments + ); } -=item balance_date_range [ START_TIME [ END_TIME [ OPTION => VALUE ... ] ] ] +=item balance_date_range START_TIME [ END_TIME [ OPTION => VALUE ... ] ] -Returns the balance for this customer, optionally considering invoices with -date earlier than START_TIME, and not later than END_TIME +Returns the balance for this customer, only considering invoices with date +earlier than START_TIME, and optionally not later than END_TIME (total_owed_date minus total_unapplied_credits minus total_unapplied_payments). Times are specified as SQL fragments or numeric @@ -7209,8 +7094,6 @@ Returns a status string for this customer, currently: =item prospect - No packages have ever been ordered -=item ordered - Recurring packages all are new (not yet billed). - =item active - One or more recurring packages is active =item inactive - No active recurring packages, but otherwise unsuspended/uncancelled (the inactive status is new - previously inactive customers were mis-identified as cancelled) @@ -7227,8 +7110,7 @@ sub status { shift->cust_status(@_); } sub cust_status { my $self = shift; - # prospect ordered active inactive suspended cancelled - for my $status ( FS::cust_main->statuses() ) { + for my $status (qw( prospect active inactive suspended cancelled )) { my $method = $status.'_sql'; my $numnum = ( my $sql = $self->$method() ) =~ s/cust_main\.custnum/?/g; my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr; @@ -7263,7 +7145,6 @@ use vars qw(%statuscolor); tie %statuscolor, 'Tie::IxHash', 'prospect' => '7e0079', #'000000', #black? naw, purple 'active' => '00CC00', #green - 'ordered' => '009999', #teal? cyan? 'inactive' => '0000CC', #blue 'suspended' => 'FF9900', #yellow 'cancelled' => 'FF0000', #red @@ -7373,20 +7254,9 @@ sub select_count_pkgs_sql { $select_count_pkgs; } -sub prospect_sql { - " 0 = ( $select_count_pkgs ) "; -} - -=item ordered_sql - -Returns an SQL expression identifying ordered cust_main records (customers with -recurring packages not yet setup). - -=cut - -sub ordered_sql { - " 0 < ( $select_count_pkgs AND ". FS::cust_pkg->ordered_sql. " ) "; -} +sub prospect_sql { " + 0 = ( $select_count_pkgs ) +"; } =item active_sql @@ -7395,9 +7265,10 @@ active recurring packages). =cut -sub active_sql { - " 0 < ( $select_count_pkgs AND ". FS::cust_pkg->active_sql. " ) "; -} +sub active_sql { " + 0 < ( $select_count_pkgs AND ". FS::cust_pkg->active_sql. " + ) +"; } =item inactive_sql @@ -7486,10 +7357,10 @@ sub balance_sql { " WHERE cust_refund.custnum = cust_main.custnum ) "; } -=item balance_date_sql [ START_TIME [ END_TIME [ OPTION => VALUE ... ] ] ] +=item balance_date_sql START_TIME [ END_TIME [ OPTION => VALUE ... ] ] -Returns an SQL fragment to retreive the balance for this customer, optionally -considering invoices with date earlier than START_TIME, and not +Returns an SQL fragment to retreive the balance for this customer, only +considering invoices with date earlier than START_TIME, and optionally not later than END_TIME (total_owed_date minus total_unapplied_credits minus total_unapplied_payments). @@ -7572,11 +7443,9 @@ Available options are: =cut sub unapplied_payments_date_sql { - my( $class, $start, $end, %opt ) = @_; - - my $cutoff = $opt{'cutoff'}; + my( $class, $start, $end, ) = @_; - my $unapp_pay = FS::cust_pay->unapplied_sql($cutoff); + my $unapp_pay = FS::cust_pay->unapplied_sql; my $pay_where = $class->_money_table_where( 'cust_pay', $start, $end, 'unapplied_date'=>1 ); @@ -7687,7 +7556,7 @@ sub search { # parse status ## - #prospect ordered active inactive suspended cancelled + #prospect active inactive suspended cancelled if ( grep { $params->{'status'} eq $_ } FS::cust_main->statuses() ) { my $method = $params->{'status'}. '_sql'; #push @where, $class->$method(); @@ -8929,23 +8798,14 @@ sub _agent_plandata { } -=item queued_bill 'custnum' => CUSTNUM [ , OPTION => VALUE ... ] - -Subroutine (not a method), designed to be called from the queue. - -Takes a list of options and values. - -Pulls up the customer record via the custnum option and calls bill_and_collect. - -=cut - sub queued_bill { + ## actual sub, not a method, designed to be called from the queue. + ## sets up the customer, and calls the bill_and_collect my (%args) = @_; #, ($time, $invoice_time, $check_freq, $resetup) = @_; - my $cust_main = qsearchs( 'cust_main', { custnum => $args{'custnum'} } ); - warn 'bill_and_collect custnum#'. $cust_main->custnum. "\n";#log custnum w/pid - - $cust_main->bill_and_collect( %args ); + $cust_main->bill_and_collect( + %args, + ); } sub _upgrade_data { #class method