X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fcust_bill.pm;h=ef6dc7bee233051f8ee29187f024f506de273a5a;hp=79c78d859d680457dab224a78225333be69bd0db;hb=c5e31619e5a3071506cff19578e9e377753a96f4;hpb=5fef26f41acb87904f2ce95a4dda0e50d34f995b diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 79c78d859..ef6dc7bee 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -43,6 +43,7 @@ use FS::bill_batch; use FS::cust_bill_batch; use FS::cust_bill_pay_pkg; use FS::cust_credit_bill_pkg; +use FS::discount_plan; use FS::L10N; @ISA = qw( FS::cust_main_Mixin FS::Record ); @@ -748,6 +749,18 @@ sub cust_bill_batch { qsearch('cust_bill_batch', { 'invnum' => $self->invnum }); } +=item discount_plans + +Returns all discount plans (L) for this invoice, as a +hash keyed by term length. + +=cut + +sub discount_plans { + my $self = shift; + FS::discount_plan->all($self); +} + =item tax Returns the tax amount (see L) for this invoice. @@ -1045,41 +1058,54 @@ sub generate_email { 'Disposition' => 'inline', ); - $args{'from'} =~ /\@([\w\.\-]+)/; - my $from = $1 || 'example.com'; - my $content_id = join('.', rand()*(2**32), $$, time). "\@$from"; - my $logo; - my $agentnum = $cust_main->agentnum; - if ( defined($args{'template'}) && length($args{'template'}) - && $conf->exists( 'logo_'. $args{'template'}. '.png', $agentnum ) - ) - { - $logo = 'logo_'. $args{'template'}. '.png'; + my $htmldata; + my $image = ''; + my $barcode = ''; + if ( $conf->exists('invoice_email_pdf') + and scalar($conf->config('invoice_email_pdf_note')) ) { + + $htmldata = join('
', $conf->config('invoice_email_pdf_note') ); + } else { - $logo = "logo.png"; - } - my $image_data = $conf->config_binary( $logo, $agentnum); - - my $image = build MIME::Entity - 'Type' => 'image/png', - 'Encoding' => 'base64', - 'Data' => $image_data, - 'Filename' => 'logo.png', - 'Content-ID' => "<$content_id>", - ; + + $args{'from'} =~ /\@([\w\.\-]+)/; + my $from = $1 || 'example.com'; + my $content_id = join('.', rand()*(2**32), $$, time). "\@$from"; + + my $logo; + my $agentnum = $cust_main->agentnum; + if ( defined($args{'template'}) && length($args{'template'}) + && $conf->exists( 'logo_'. $args{'template'}. '.png', $agentnum ) + ) + { + $logo = 'logo_'. $args{'template'}. '.png'; + } else { + $logo = "logo.png"; + } + my $image_data = $conf->config_binary( $logo, $agentnum); + + $image = build MIME::Entity + 'Type' => 'image/png', + 'Encoding' => 'base64', + 'Data' => $image_data, + 'Filename' => 'logo.png', + 'Content-ID' => "<$content_id>", + ; - my $barcode; - if($conf->exists('invoice-barcode')){ - my $barcode_content_id = join('.', rand()*(2**32), $$, time). "\@$from"; - $barcode = build MIME::Entity - 'Type' => 'image/png', - 'Encoding' => 'base64', - 'Data' => $self->invoice_barcode(0), - 'Filename' => 'barcode.png', - 'Content-ID' => "<$barcode_content_id>", - ; - $opt{'barcode_cid'} = $barcode_content_id; + if ($conf->exists('invoice-barcode')) { + my $barcode_content_id = join('.', rand()*(2**32), $$, time). "\@$from"; + $barcode = build MIME::Entity + 'Type' => 'image/png', + 'Encoding' => 'base64', + 'Data' => $self->invoice_barcode(0), + 'Filename' => 'barcode.png', + 'Content-ID' => "<$barcode_content_id>", + ; + $opt{'barcode_cid'} = $barcode_content_id; + } + + $htmldata = $self->print_html({ 'cid'=>$content_id, %opt }); } $alternative->attach( @@ -1092,7 +1118,7 @@ sub generate_email { ' ', ' ', ' ', - $self->print_html({ 'cid'=>$content_id, %opt }), + $htmldata, ' ', '', ], @@ -1100,6 +1126,7 @@ sub generate_email { #'Filename' => 'invoice.pdf', ); + my @otherparts = (); if ( $cust_main->email_csv_cdr ) { @@ -1138,7 +1165,7 @@ sub generate_email { $related->add_part($alternative); - $related->add_part($image); + $related->add_part($image) if $image; my $pdf = build MIME::Entity $self->mimebuild_pdf(\%opt); @@ -1154,11 +1181,10 @@ sub generate_email { # image/png $return{'content-type'} = 'multipart/related'; - if($conf->exists('invoice-barcode')){ - $return{'mimeparts'} = [ $alternative, $image, $barcode, @otherparts ]; - } - else { - $return{'mimeparts'} = [ $alternative, $image, @otherparts ]; + if ($conf->exists('invoice-barcode') && $barcode) { + $return{'mimeparts'} = [ $alternative, $image, $barcode, @otherparts ]; + } else { + $return{'mimeparts'} = [ $alternative, $image, @otherparts ]; } $return{'type'} = 'multipart/alternative'; #Content-Type of first part... #$return{'disposition'} = 'inline'; @@ -5205,108 +5231,34 @@ a setup fee if the discount is allowed to apply to setup fees. sub _items_discounts_avail { my $self = shift; - my %terms; my $list_pkgnums = 0; # if any packages are not eligible for all discounts - - my ($previous_balance) = $self->previous; - - foreach (qsearch('discount',{ 'months' => { op => '>', value => 1} })) { - $terms{$_->months} = { - pkgnums => [], - base => $previous_balance || 0, # pre-discount sum of charges - discounted => $previous_balance || 0, # post-discount sum - list_pkgnums => 0, # whether any packages are not discounted - } - } - foreach my $months (keys %terms) { - my $hash = $terms{$months}; - - # tricky, because packages may not all be eligible for the same discounts - foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) { - my $cust_pkg = $cust_bill_pkg->cust_pkg or next; - my $part_pkg = $cust_pkg->part_pkg or next; - my $freq = $part_pkg->freq; - my $setup = $cust_bill_pkg->setup || 0; - my $recur = $cust_bill_pkg->recur || 0; - - if ( $freq eq '1' ) { #monthly - my $permonth = $part_pkg->base_recur_permonth || 0; - - my ($discount) = grep { $_->months == $months } - map { $_->discount } $part_pkg->part_pkg_discount; - - $hash->{base} += $setup + $recur + ($months - 1) * $permonth; - - if ( $discount ) { - - my $discountable; - if ( $discount->setup ) { - $discountable += $setup; - } - else { - $hash->{discounted} += $setup; - } - - if ( $discount->percent ) { - $discountable += $months * $permonth; - $discountable -= ($discountable * $discount->percent / 100); - $discountable -= ($permonth - $recur); # correct for prorate - $hash->{discounted} += $discountable; - } - else { - $discountable += $recur; - $discountable -= $discount->amount * $recur/$permonth; - $discountable += ($months - 1) * max($permonth - $discount->amount,0); - } + my %plans = $self->discount_plans; - $hash->{discounted} += $discountable; - push @{ $hash->{pkgnums} }, $cust_pkg->pkgnum; - } - else { #no discount - $hash->{discounted} += $setup + $recur + ($months - 1) * $permonth; - $hash->{list_pkgnums} = 1; - } - } #if $freq eq '1' - else { # all non-monthly packages: include current charges only - $hash->{discounted} += $setup + $recur; - $hash->{base} += $setup + $recur; - $hash->{list_pkgnums} = 1; - } - } #foreach $cust_bill_pkg - - # don't show this line if no packages have discounts at this term - # or if there are no new charges to apply the discount to - delete $terms{$months} if $hash->{base} == $hash->{discounted} - or $hash->{base} == 0; + $list_pkgnums = grep { $_->list_pkgnums } values %plans; - } + map { + my $months = $_; + my $plan = $plans{$months}; - $list_pkgnums = grep { $_->{list_pkgnums} > 0 } values %terms; - - foreach my $months (keys %terms) { - my $hash = $terms{$months}; - my $term_total = sprintf('%.2f', $hash->{discounted}); - # possibly shouldn't include previous balance in these? - my $percent = sprintf('%.0f', 100 * (1 - $term_total / $hash->{base}) ); + my $term_total = sprintf('%.2f', $plan->discounted_total); + my $percent = sprintf('%.0f', + 100 * (1 - $term_total / $plan->base_total) ); my $permonth = sprintf('%.2f', $term_total / $months); - - $hash->{description} = $self->mt('Save [_1]% by paying for [_2] months', - $percent, $months - ); - $hash->{amount} = $self->mt('[_1] ([_2] per month)', - $term_total, $money_char.$permonth - ); - - my @detail; - if ( $list_pkgnums ) { - push @detail, $self->mt('discount on item'). ' '. - join(', ', map { "#$_" } @{ $hash->{pkgnums} }); + my $detail = $self->mt('discount on item'). ' '. + join(', ', map { "#$_" } $plan->pkgnums) + if $list_pkgnums; + + +{ + description => $self->mt('Save [_1]% by paying for [_2] months', + $percent, $months), + amount => $self->mt('[_1] ([_2] per month)', + $term_total, $money_char.$permonth), + ext_description => ($detail || ''), } - $hash->{ext_description} = join ', ', @detail; - } + } #map + sort { $b <=> $a } keys %plans; - map { $terms{$_} } sort {$b <=> $a} keys %terms; } =item call_details [ OPTION => VALUE ... ]