X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_pay.pm;h=63d7c48351ab4ab3381be1260fdd2460547b360c;hb=c7bc6770f2f0b4413b788f8fc9abde6ad5548da3;hp=4535aadb2dd85b044bc86826c8d743d809a0422e;hpb=e5d6af11f52aabe8c9e6e12ce43c3401ccf025a8;p=freeside.git diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 4535aadb2..63d7c4835 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -9,8 +9,7 @@ use vars qw( $DEBUG $me $conf @encrypted_fields use Date::Format; use Business::CreditCard; use Text::Template; -use FS::UID qw( getotaker ); -use FS::Misc qw( send_email ); +use FS::Misc::DateTime qw( parse_datetime ); #for batch_import use FS::Record qw( dbh qsearch qsearchs ); use FS::CurrentUser; use FS::payby; @@ -23,6 +22,7 @@ use FS::cust_main; use FS::cust_pkg; use FS::cust_pay_void; use FS::upgrade_journal; +use FS::Cursor; $DEBUG = 0; @@ -37,6 +37,7 @@ FS::UID->install_callback( sub { } ); @encrypted_fields = ('payinfo'); +sub nohistory_fields { ('payinfo'); } =head1 NAME @@ -169,7 +170,7 @@ Creates a new payment. To add the payment to the databse, see L<"insert">. =cut sub table { 'cust_pay'; } -sub cust_linked { $_[0]->cust_main_custnum; } +sub cust_linked { $_[0]->cust_main_custnum || $_[0]->custnum; } sub cust_unlinked_msg { my $self = shift; "WARNING: can't find cust_main.custnum ". $self->custnum. @@ -192,6 +193,15 @@ A hash of optional arguments may be passed. Currently "manual" is supported. If true, a payment receipt is sent instead of a statement when 'payment_receipt_email' configuration option is set. +About the "manual" flag: Normally, if the 'payment_receipt' config option +is set, and the customer has an invoice email address, inserting a payment +causes a I to be emailed to the customer. If the payment is +considered "manual" (or if the customer has no invoices), then it will +instead send a I. "manual" should be true whenever a +payment is created directly from the web interface, from a user-initiated +realtime payment, or from a third-party payment via self-service. It should +be I when creating a payment from a billing event or from a batch. + =cut sub insert { @@ -460,38 +470,6 @@ sub delete { return $error; } - if ( $conf->exists('deletepayments') - && $conf->config('deletepayments') ne '' ) { - - my $cust_main = $self->cust_main; - - my $error = send_email( - 'from' => $conf->config('invoice_from', $self->cust_main->agentnum), - #invoice_from??? well as good as any - 'to' => $conf->config('deletepayments'), - 'subject' => 'FREESIDE NOTIFICATION: Payment deleted', - 'body' => [ - "This is an automatic message from your Freeside installation\n", - "informing you that the following payment has been deleted:\n", - "\n", - 'paynum: '. $self->paynum. "\n", - 'custnum: '. $self->custnum. - " (". $cust_main->last. ", ". $cust_main->first. ")\n", - 'paid: $'. sprintf("%.2f", $self->paid). "\n", - 'date: '. time2str("%a %b %e %T %Y", $self->_date). "\n", - 'payby: '. $self->payby. "\n", - 'payinfo: '. $self->paymask. "\n", - 'paybatch: '. $self->paybatch. "\n", - ], - ); - - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "can't send payment deletion notification: $error"; - } - - } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; @@ -626,11 +604,18 @@ sub send_receipt { { my $msgnum = $conf->config('payment_receipt_msgnum', $cust_main->agentnum); if ( $msgnum ) { - my $msg_template = FS::msg_template->by_key($msgnum); - $error = $msg_template->send( - 'cust_main' => $cust_main, - 'object' => $self, - 'from_config' => 'payment_receipt_from', + + my $queue = new FS::queue { + 'job' => 'FS::Misc::process_send_email', + 'paynum' => $self->paynum, + 'custnum' => $cust_main->custnum, + }; + $error = $queue->insert( + FS::msg_template->by_key($msgnum)->prepare( + 'cust_main' => $cust_main, + 'object' => $self, + 'from_config' => 'payment_receipt_from', + ) ); } elsif ( $conf->exists('payment_receipt_email') ) { @@ -669,7 +654,12 @@ sub send_receipt { #setup date, other things? } - $error = send_email( + my $queue = new FS::queue { + 'job' => 'FS::Misc::process_send_generated_email', + 'paynum' => $self->paynum, + 'custnum' => $cust_main->custnum, + }; + $error = $queue->insert( 'from' => $conf->config('invoice_from', $cust_main->agentnum), #invoice_from??? well as good as any 'to' => \@invoicing_list, @@ -686,8 +676,9 @@ sub send_receipt { } elsif ( ! $cust_main->invoice_noemail ) { #not manual my $queue = new FS::queue { - 'paynum' => $self->paynum, - 'job' => 'FS::cust_bill::queueable_email', + 'job' => 'FS::cust_bill::queueable_email', + 'paynum' => $self->paynum, + 'custnum' => $cust_main->custnum, }; $error = $queue->insert( @@ -699,7 +690,7 @@ sub send_receipt { } - warn "send_receipt: $error\n" if $error; + warn "send_receipt: $error\n" if $error; } =item cust_bill_pay @@ -1015,11 +1006,11 @@ sub _upgrade_data { #class method ### # migrate batchnums from the misused 'paybatch' field to 'batchnum' ### - my @cust_pay = qsearch( { - 'table' => 'cust_pay', - 'addl_from' => ' JOIN pay_batch ON cust_pay.paybatch = CAST(pay_batch.batchnum AS text) ', + my $search = FS::Cursor->new( { + 'table' => 'cust_pay', + 'addl_from' => ' JOIN pay_batch ON cust_pay.paybatch = CAST(pay_batch.batchnum AS text) ', } ); - foreach my $cust_pay (@cust_pay) { + while (my $cust_pay = $search->fetch) { $cust_pay->set('batchnum' => $cust_pay->paybatch); $cust_pay->set('paybatch' => ''); my $error = $cust_pay->replace; @@ -1032,18 +1023,48 @@ sub _upgrade_data { #class method ### # not only cust_pay, but also voided and refunded payments - if (!FS::upgrade_journal->is_done('cust_pay__parse_paybatch')) { + if (!FS::upgrade_journal->is_done('cust_pay__parse_paybatch_1')) { + local $FS::Record::nowarn_classload=1; # really inefficient, but again, only has to run once foreach my $table (qw(cust_pay cust_pay_void cust_refund)) { - foreach my $object ( qsearch({ - table => $table, - extra_sql => "WHERE payby IN('CARD','CHEK') ". - "AND paybatch IS NOT NULL", - }) ) - { + my $and_batchnum_is_null = + ( $table =~ /^cust_pay/ ? ' AND batchnum IS NULL' : '' ); + my $search = FS::Cursor->new({ + table => $table, + extra_sql => "WHERE payby IN('CARD','CHEK') ". + "AND (paybatch IS NOT NULL ". + "OR (paybatch IS NULL AND auth IS NULL + $and_batchnum_is_null ) )", + }); + while ( my $object = $search->fetch ) { + if ( $object->paybatch eq '' ) { + # repair for a previous upgrade that didn't save 'auth' + my $pkey = $object->primary_key; + # find the last history record that had a paybatch value + my $h = qsearchs({ + table => "h_$table", + hashref => { + $pkey => $object->$pkey, + paybatch => { op=>'!=', value=>''}, + history_action => 'replace_old', + }, + order_by => 'ORDER BY history_date DESC LIMIT 1', + }); + if (!$h) { + warn "couldn't find paybatch history record for $table ".$object->$pkey."\n"; + next; + } + # if the paybatch didn't have an auth string, then it's fine + $h->paybatch =~ /:(\w+):/ or next; + # set paybatch to what it was in that record + $object->set('paybatch', $h->paybatch) + # and then upgrade it like the old records + } + my $parsed = $object->_parse_paybatch; if (keys %$parsed) { $object->set($_ => $parsed->{$_}) foreach keys %$parsed; + $object->set('auth' => $parsed->{authorization}); $object->set('paybatch', ''); my $error = $object->replace; warn "error parsing CARD/CHEK paybatch fields on $object #". @@ -1052,7 +1073,7 @@ sub _upgrade_data { #class method } } #$object } #$table - FS::upgrade_journal->set_done('cust_pay__parse_paybatch'); + FS::upgrade_journal->set_done('cust_pay__parse_paybatch_1'); } } @@ -1071,11 +1092,17 @@ Inserts new payments. sub batch_import { my $param = shift; - my $fh = $param->{filehandle}; + my $fh = $param->{filehandle}; + my $format = $param->{'format'}; + my $agentnum = $param->{agentnum}; - my $format = $param->{'format'}; + my $_date = $param->{_date}; + $_date = parse_datetime($_date) if $_date && $_date =~ /\D/; my $paybatch = $param->{'paybatch'}; + my $custnum_prefix = $conf->config('cust_main-custnum-display_prefix'); + my $custnum_length = $conf->config('cust_main-custnum-display_length') || 8; + # here is the agent virtualization my $extra_sql = ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql; @@ -1124,6 +1151,7 @@ sub batch_import { payby => $payby, paybatch => $paybatch, ); + $cust_pay{_date} = $_date if $_date; my $cust_main; foreach my $field ( @fields ) { @@ -1161,6 +1189,11 @@ sub batch_import { $cust_pay{$field} = shift @columns; } + if ( $custnum_prefix && $cust_pay{custnum} =~ /^$custnum_prefix(0*([1-9]\d*))$/ + && length($1) == $custnum_length ) { + $cust_pay{custnum} = $2; + } + my $cust_pay = new FS::cust_pay( \%cust_pay ); my $error = $cust_pay->insert;