use FS::prepay_credit;
use FS::queue;
use FS::part_pkg;
-use FS::part_bill_event;
+use FS::part_bill_event qw(due_events);
use FS::cust_bill_event;
use FS::cust_tax_exempt;
use FS::cust_tax_exempt_pkg;
my $self = shift;
#'mg_user_preference' => {},
- #'mg_user_indicator_profile' => { 'mg_profile_indicator' => { 'mg_profile_details' }, },
- #'mg_watchlist_header' => { 'mg_watchlist_details' },
- #'mg_user_grid_header' => { 'mg_user_grid_details' },
- #'mg_portfolio_header' => { 'mg_portfolio_trades' => { 'mg_portfolio_trades_positions' } },
+ #'mg_user_indicator_profile.user_indicator_profile_id' => { 'mg_profile_indicator.profile_indicator_id' => { 'mg_profile_details.profile_detail_id' }, },
+ #'mg_watchlist_header.watchlist_header_id' => { 'mg_watchlist_details.watchlist_details_id' },
+ #'mg_user_grid_header.grid_header_id' => { 'mg_user_grid_details.user_grid_details_id' },
+ #'mg_portfolio_header.portfolio_header_id' => { 'mg_portfolio_trades.portfolio_trades_id' => { 'mg_portfolio_trades_positions.portfolio_trades_positions_id' } },
my @tables = eval($conf->config_binary('cust_main-skeleton_tables'));
die $@ if $@;
sub _copy_skel {
my( $table, $sourceid, $destid, %child_tables ) = @_;
- my $dbdef_table = dbdef->table($table);
- my $primary_key = $dbdef_table->primary_key
- or return "$table has no primary key".
- " (or do you need to run dbdef-create?)";
+ my $primary_key;
+ if ( $table =~ /^(\w+)\.(\w+)$/ ) {
+ ( $table, $primary_key ) = ( $1, $2 );
+ } else {
+ my $dbdef_table = dbdef->table($table);
+ $primary_key = $dbdef_table->primary_key
+ or return "$table has no primary key".
+ " (or do you need to run dbdef-create?)";
+ }
warn " _copy_skel: $table.$primary_key $sourceid to $destid for ".
join (', ', keys %child_tables). "\n"
if $DEBUG > 2;
- foreach my $child_table ( keys %child_tables ) {
+ foreach my $child_table_def ( keys %child_tables ) {
+
+ my $child_table;
+ my $child_pkey = '';
+ if ( $child_table_def =~ /^(\w+)\.(\w+)$/ ) {
+ ( $child_table, $child_pkey ) = ( $1, $2 );
+ } else {
+ $child_table = $child_table_def;
+
+ $child_pkey = dbdef->table($child_table)->primary_key;
+ # or return "$table has no primary key".
+ # " (or do you need to run dbdef-create?)\n";
+ }
- my $child_pkey = dbdef->table($child_table)->primary_key;
- # or return "$table has no primary key".
- # " (or do you need to run dbdef-create?)\n";
my $sequence = '';
- if ( keys %{ $child_tables{$child_table} } ) {
+ if ( keys %{ $child_tables{$child_table_def} } ) {
- return "$child_table has no primary key\n" unless $child_pkey;
+ return "$child_table has no primary key".
+ " (run dbdef-create or try specifying it?)\n"
+ unless $child_pkey;
#false laziness w/Record::insert and only works on Pg
#refactor the proper last-inserted-id stuff out of Record::insert if this
# don't drink soap! recurse! recurse! okay!
my $error =
- _copy_skel( $child_table,
+ _copy_skel( $child_table_def,
$row->{$child_pkey}, #sourceid
$insertid, #destid
- %{ $child_tables{$child_table} },
+ %{ $child_tables{$child_table_def} },
);
return $error if $error;
warn " invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ")\n"
if $DEBUG > 1;
- foreach my $part_bill_event (
- sort { $a->seconds <=> $b->seconds
- || $a->weight <=> $b->weight
- || $a->eventpart <=> $b->eventpart }
- grep { $_->seconds <= ( $invoice_time - $cust_bill->_date )
- && ! qsearch( 'cust_bill_event', {
- 'invnum' => $cust_bill->invnum,
- 'eventpart' => $_->eventpart,
- 'status' => 'done',
- } )
- }
- qsearch( {
- 'table' => 'part_bill_event',
- 'hashref' => { 'payby' => (exists($options{'payby'})
- ? $options{'payby'}
- : $self->payby
- ),
- 'disabled' => '', },
- 'extra_sql' => $extra_sql,
- } )
- ) {
+ foreach my $part_bill_event ( due_events ( $cust_bill,
+ exists($options{'payby'})
+ ? $options{'payby'}
+ : $self->payby,
+ $invoice_time,
+ $extra_sql ) ) {
last if $cust_bill->owed <= 0 # don't run subsequent events if owed<=0
|| $self->balance <= 0; # or if balance<=0
- warn " calling invoice event (". $part_bill_event->eventcode. ")\n"
- if $DEBUG > 1;
- my $cust_main = $self; #for callback
-
- my $error;
{
local $realtime_bop_decline_quiet = 1 if $options{'quiet'};
- local $SIG{__DIE__}; # don't want Mason __DIE__ handler active
- $error = eval $part_bill_event->eventcode;
- }
-
- my $status = '';
- my $statustext = '';
- if ( $@ ) {
- $status = 'failed';
- $statustext = $@;
- } elsif ( $error ) {
- $status = 'done';
- $statustext = $error;
- } else {
- $status = 'done'
- }
-
- #add cust_bill_event
- my $cust_bill_event = new FS::cust_bill_event {
- 'invnum' => $cust_bill->invnum,
- 'eventpart' => $part_bill_event->eventpart,
- #'_date' => $invoice_time,
- '_date' => time,
- 'status' => $status,
- 'statustext' => $statustext,
- };
- $error = $cust_bill_event->insert;
- if ( $error ) {
- #$dbh->rollback if $oldAutoCommit;
- #return "error: $error";
+ warn " do_event " . $cust_bill . " ". (%options) . "\n"
+ if $DEBUG > 1;
- # gah, even with transactions.
- $dbh->commit if $oldAutoCommit; #well.
- my $e = 'WARNING: Event run but database not updated - '.
- 'error inserting cust_bill_event, invnum #'. $cust_bill->invnum.
- ', eventpart '. $part_bill_event->eventpart.
- ": $error";
- warn $e;
- return $e;
+ if (my $error = $part_bill_event->do_event($cust_bill, %options)) {
+ # gah, even with transactions.
+ $dbh->commit if $oldAutoCommit; #well.
+ return $error;
+ }
}
-
}
}
=item retry_realtime
-Schedules realtime credit card / electronic check / LEC billing events for
-for retry. Useful if card information has changed or manual retry is desired.
-The 'collect' method must be called to actually retry the transaction.
+Schedules realtime / batch credit card / electronic check / LEC billing
+events for for retry. Useful if card information has changed or manual
+retry is desired. The 'collect' method must be called to actually retry
+the transaction.
Implementation details: For each of this customer's open invoices, changes
the status of the first "done" (with statustext error) realtime processing
grep {
#$_->part_bill_event->plan eq 'realtime-card'
$_->part_bill_event->eventcode =~
- /\$cust_bill\->realtime_(card|ach|lec)/
+ /\$cust_bill\->(batch|realtime)_(card|ach|lec)/
&& $_->status eq 'done'
&& $_->statustext
}
cust_pkg.pkgpart
svc_acct.username svc_acct._password
);
- $payby = 'CARD';
+ $payby = 'BILL';
} else {
die "unknown format $format";
}
if ( $field eq 'refnum' && $columns[0] !~ /^\s*(\d+)\s*$/ ) {
my $referral = $columns[0];
- my $part_referral = new FS::part_referral {
- 'referral' => $referral,
- 'agentnum' => $agentnum,
- };
-
- my $error = $part_referral->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "can't auto-insert advertising source: $referral: $error";
+ my %hash = ( 'referral' => $referral,
+ 'agentnum' => $agentnum,
+ 'disabled' => '',
+ );
+
+ my $part_referral = qsearchs('part_referral', \%hash )
+ || new FS::part_referral \%hash;
+
+ unless ( $part_referral->refnum ) {
+ my $error = $part_referral->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't auto-insert advertising source: $referral: $error";
+ }
}
+
$columns[0] = $part_referral->refnum;
}
}
}
+ $cust_main{'payby'} = 'CARD' if length($cust_main{'payinfo'});
+
my $invoicing_list = $cust_main{'invoicing_list'}
? [ delete $cust_main{'invoicing_list'} ]
: [];