X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fquotation_pkg.pm;h=f4d5d5d0a0eef707e6bf23ed35d17e241e2aa66a;hb=a85fa2e48276fe14334d7d414fd3c0cbca8ed3c6;hp=914e1ce4ef2c2b13b0ce6f4511c49ec93054dba5;hpb=973d5dd654ea23dea3ff185e157a404556815ccb;p=freeside.git diff --git a/FS/FS/quotation_pkg.pm b/FS/FS/quotation_pkg.pm index 914e1ce4e..f4d5d5d0a 100644 --- a/FS/FS/quotation_pkg.pm +++ b/FS/FS/quotation_pkg.pm @@ -7,6 +7,7 @@ use FS::part_pkg; use FS::cust_location; use FS::quotation; use FS::quotation_pkg_discount; #so its loaded when TemplateItem_Mixin needs it +use FS::quotation_pkg_detail; use List::Util qw(sum); =head1 NAME @@ -97,6 +98,7 @@ sub display_table { 'quotation_pkg'; } # # (for invoice display order) sub discount_table { 'quotation_pkg_discount'; } +sub detail_table { 'quotation_pkg_detail'; } =item insert @@ -112,6 +114,22 @@ sub insert { my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; + #false laziness w/cust_main::Packages::order_pkg + if ( $options{'locationnum'} and $options{'locationnum'} != -1 ) { + + $self->locationnum($options{'locationnum'}); + + } elsif ( $options{'cust_location'} ) { + + my $error = $options{'cust_location'}->find_or_insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "inserting cust_location (transaction rolled back): $error"; + } + $self->locationnum($options{'cust_location'}->locationnum); + + } + my $error = $self->SUPER::insert; if ( !$error and $self->discountnum ) { @@ -147,15 +165,21 @@ sub delete { my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; - foreach ($self->quotation_pkg_discount) { - my $error = $_->delete; + my $error = $self->delete_details; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + foreach ($self->quotation_pkg_discount, $self->quotation_pkg_tax) { + $error = $_->delete; if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error . ' (deleting discount)'; } } - my $error = $self->SUPER::delete; + $error = $self->SUPER::delete; if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; @@ -195,6 +219,20 @@ sub check { || $self->ut_enum('waive_setup', [ '', 'Y'] ) ; + if ($self->locationnum eq '') { + # use the customer default + my $quotation = $self->quotation; + if ($quotation->custnum) { + $self->set('locationnum', $quotation->cust_main->ship_locationnum); + } elsif ($quotation->prospectnum) { + # use the first non-disabled location for that prospect + my $cust_location = qsearchs('cust_location', + { prospectnum => $quotation->prospectnum, + disabled => '' }); + $self->set('locationnum', $cust_location->locationnum) if $cust_location; + } # else the quotation is invalid + } + return $error if $error; $self->SUPER::check; @@ -251,6 +289,9 @@ sub estimate { # XXX the order of applying discounts is ill-defined, which matters # if there are percentage and amount discounts on the same package. + # + # but right now there can only be one discount on any package, so + # it doesn't matter foreach my $pkg_discount ($self->quotation_pkg_discount) { my $discount = $pkg_discount->discount; @@ -312,7 +353,7 @@ sub insert_discount { #my ($self, %options) = @_; my $self = shift; - my $cust_pkg_discount = FS::quotation_pkg_discount->new( { + my $quotation_pkg_discount = FS::quotation_pkg_discount->new( { 'quotationpkgnum' => $self->quotationpkgnum, 'discountnum' => $self->discountnum, #for the create a new discount case @@ -323,7 +364,7 @@ sub insert_discount { 'setup' => $self->discountnum_setup, } ); - $cust_pkg_discount->insert; + $quotation_pkg_discount->insert; } sub _item_discount { @@ -345,7 +386,7 @@ sub _item_discount { push @ext, $pkg_discount->description; $d->{setup_amount} -= $pkg_discount->setup_amount; $d->{recur_amount} -= $pkg_discount->recur_amount; - } + } $d->{setup_amount} *= $self->quantity || 1; $d->{recur_amount} *= $self->quantity || 1; $d->{amount} = $d->{setup_amount} + $d->{recur_amount}; @@ -355,16 +396,106 @@ sub _item_discount { sub setup { my $self = shift; - ($self->unitsetup - sum(map { $_->setup_amount } $self->pkg_discount)) + ($self->unitsetup - sum(0, map { $_->setup_amount } $self->pkg_discount)) * ($self->quantity || 1); } +sub setup_show_zero { + my $self = shift; + return $self->part_pkg->setup_show_zero; +} + sub recur { my $self = shift; - ($self->unitrecur - sum(map { $_->recur_amount } $self->pkg_discount)) + ($self->unitrecur - sum(0, map { $_->recur_amount } $self->pkg_discount)) * ($self->quantity || 1); } +sub recur_show_zero { + my $self = shift; + return $self->part_pkg->recur_show_zero; +} + +=item delete_details + +Deletes all quotation_pkgs_details associated with this pkg (see L). + +=cut + +sub delete_details { + my $self = shift; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + foreach my $detail ( qsearch('quotation_pkg_detail',{ 'quotationpkgnum' => $self->quotationpkgnum }) ) { + my $error = $detail->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error removing old detail: $error"; + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + +=item set_details PARAM + +Sets new quotation details for this package (see L), +removing existing details. + +Recognizes the following parameters: + +details - arrayref of strings, one for each new detail + +copy_on_order - if true, sets copy_on_order flag on new details + +If there is an error, returns the error, otherwise returns false. + +=cut + +sub set_details { + my $self = shift; + my %opt = @_; + + $opt{'details'} ||= []; + my @details = @{$opt{'details'}}; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + my $error = $self->delete_details; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + foreach my $detail ( @details ) { + my $quotation_pkg_detail = new FS::quotation_pkg_detail { + 'quotationpkgnum' => $self->quotationpkgnum, + 'detail' => $detail, + 'copy_on_order' => $opt{'copy_on_order'} ? 'Y' : '', + }; + $error = $quotation_pkg_detail->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error adding new detail: $error"; + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + +sub details_header { + return (); +} + =item cust_bill_pkg_display [ type => TYPE ] =cut @@ -414,6 +545,11 @@ sub cust_main { $quotation->cust_main; } +sub tax_locationnum { + my $self = shift; + $self->locationnum; +} + #stub for 3.x sub quotation { @@ -421,16 +557,50 @@ sub quotation { FS::quotation->by_key($self->quotationnum); } +sub quotation_pkg_detail { + my $self = shift; + sort { $a->detailnum <=> $b->detailnum } + qsearch('quotation_pkg_detail', { quotationpkgnum => $self->quotationpkgnum }); +} + sub quotation_pkg_discount { my $self = shift; qsearch('quotation_pkg_discount', { quotationpkgnum => $self->quotationpkgnum }); } +sub quotation_pkg_tax { + my $self = shift; + qsearch('quotation_pkg_tax', { quotationpkgnum => $self->quotationpkgnum }); +} + +sub cust_location { + my $self = shift; + $self->locationnum ? qsearchs('cust_location', { locationnum => $self->locationnum }) : ''; +} + + +sub _upgrade_data { + my $class = shift; + my @quotation_pkg_without_location = + qsearch( 'quotation_pkg', { locationnum => '' } ); + if (@quotation_pkg_without_location) { + warn "setting default location on quotation_pkg records\n"; + foreach my $quotation_pkg (@quotation_pkg_without_location) { + # check() will fix this + my $error = $quotation_pkg->replace; + if ($error) { + die "quotation #".$quotation_pkg->quotationnum.": $error\n"; + } + } + } + ''; +} + =back =head1 BUGS -Doesn't support taxes, fees, or add-on packages. +Doesn't support fees, or add-on packages. =head1 SEE ALSO