From: Mark Wells Date: Fri, 6 May 2016 22:45:57 +0000 (-0700) Subject: create invoice details with sql_external package plans, #40558 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=3f15da8a0dd800432253294e623c6caaabc59fe3 create invoice details with sql_external package plans, #40558 --- diff --git a/FS/FS/cust_main/Billing.pm b/FS/FS/cust_main/Billing.pm index a18873f11..47a3dc2d4 100644 --- a/FS/FS/cust_main/Billing.pm +++ b/FS/FS/cust_main/Billing.pm @@ -1067,6 +1067,9 @@ sub _make_lines { my $recur_billed_currency = ''; my $recur_billed_amount = 0; my $sdate; + + my $override_quantity; + # Conditions for billing the recurring fee: # - the package doesn't have a future start date # - and it's not suspended @@ -1167,6 +1170,10 @@ sub _make_lines { $recur_billed_amount = delete $param{'billed_amount'}; } + if ( $param{'override_quantity'} ) { + $override_quantity = $param{'override_quantity'}; + } + if ( $increment_next_bill ) { my $next_bill; @@ -1241,7 +1248,7 @@ sub _make_lines { } } - } + } # end of recurring fee warn "\$setup is undefined" unless defined($setup); warn "\$recur is undefined" unless defined($recur); @@ -1312,7 +1319,7 @@ sub _make_lines { 'unitrecur' => sprintf('%.2f', $unitrecur), 'recur_billed_currency' => $recur_billed_currency, 'recur_billed_amount' => $recur_billed_amount, - 'quantity' => $cust_pkg->quantity, + 'quantity' => $override_quantity || $cust_pkg->quantity, 'details' => \@details, 'discounts' => [ @setup_discounts, @recur_discounts ], 'hidden' => $part_pkg->hidden, diff --git a/FS/FS/part_pkg/sql_external.pm b/FS/FS/part_pkg/sql_external.pm index be36c11ee..676063460 100644 --- a/FS/FS/part_pkg/sql_external.pm +++ b/FS/FS/part_pkg/sql_external.pm @@ -6,6 +6,14 @@ use vars qw( %info ); use DBI; #use FS::Record qw(qsearch qsearchs); +tie our %query_style, 'Tie::IxHash', ( + 'simple' => 'Simple (a single value for the recurring charge)', + 'detailed' => 'Detailed (multiple rows for invoice details)', +); + +our @detail_cols = ( qw(amount format duration phonenum accountcode + startdate regionname detail) + ); %info = ( 'name' => 'Base charge plus additional fees for external services from a configurable SQL query', 'shortname' => 'External SQL query', @@ -34,10 +42,17 @@ use DBI; 'query' => { 'name' => 'SQL query', 'default' => '', }, + + 'query_style' => { + 'name' => 'Query output style', + 'type' => 'select', + 'select_options' => \%query_style, + }, + }, 'fieldorder' => [qw( recur_method cutoff_day ), FS::part_pkg::prorate_Mixin::fieldorder, - qw( datasrc db_username db_password query + qw( datasrc db_username db_password query query_style )], 'weight' => '58', ); @@ -53,6 +68,7 @@ sub calc_recur { my $self = shift; my($cust_pkg, $sdate, $details, $param ) = @_; my $price = 0; + my $quantity; # can be overridden; if not we use the default my $dbh = DBI->connect( map { $self->option($_) } qw( datasrc db_username db_password ) @@ -67,9 +83,60 @@ sub calc_recur { ) { my $id = $cust_svc->svc_x->id; $sth->execute($id) or die $sth->errstr; - $price += $sth->fetchrow_arrayref->[0]; + + if ( $self->option('query_style') eq 'detailed' ) { + + while (my $row = $sth->fetchrow_hashref) { + if (exists $row->{amount}) { + if ( $row->{amount} eq '' ) { + # treat as zero + } elsif ( $row->{amount} =~ /^\d+(?:\.\d+)?$/ ) { + $price += $row->{amount}; + } else { + die "sql_external query returned non-numeric amount: $row->{amount}"; + } + } + if (exists $row->{quantity}) { + $quantity ||= 0; + if ( $row->{quantity} eq '' ) { + # treat as zero + } elsif ( $row->{quantity} =~ /^\d+$/ ) { + $quantity += $row->{quantity}; + } else { + die "sql_external query returned non-integer quantity: $row->{quantity}"; + } + } + + my $detail = FS::cust_bill_pkg_detail->new; + foreach my $field (@detail_cols) { + if (exists $row->{$field}) { + $detail->set($field, $row->{$field}); + } + } + if (!$detail->get('detail')) { + die "sql_external query did not return detail description"; + # or make something up? + # or just don't insert the detail? + } + + push @$details, $detail; + } # while $row + + } else { + + # simple style: returns only a single value, which is the price + $price += $sth->fetchrow_arrayref->[0]; + + } + } + $price = sprintf('%.2f', $price); + + # XXX probably shouldn't allow package quantity > 1 on these packages. + if ($cust_pkg->quantity > 1) { + warn "sql_external package #".$cust_pkg->pkgnum." has quantity > 1\n"; } + $param->{'override_quantity'} = $quantity; $param->{'override_charges'} = $price; ($cust_pkg->quantity || 1) * $self->calc_recur_Common($cust_pkg,$sdate,$details,$param); }