- my($custnum, $pkgparts, $remove_pkgnums, $return_cust_pkg) = @_;
- $remove_pkgnums = [] unless defined($remove_pkgnums);
-
- my $oldAutoCommit = $FS::UID::AutoCommit;
- local $FS::UID::AutoCommit = 0;
- my $dbh = dbh;
-
- # generate %part_pkg
- # $part_pkg{$pkgpart} is true iff $custnum may purchase $pkgpart
- #
- my($cust_main)=qsearchs('cust_main',{'custnum'=>$custnum});
- my($agent)=qsearchs('agent',{'agentnum'=> $cust_main->agentnum });
- my %part_pkg = %{ $agent->pkgpart_hashref };
-
- my(%svcnum);
- # generate %svcnum
- # for those packages being removed:
- #@{ $svcnum{$svcpart} } goes from a svcpart to a list of FS::cust_svc objects
- my($pkgnum);
- foreach $pkgnum ( @{$remove_pkgnums} ) {
- foreach my $cust_svc (qsearch('cust_svc',{'pkgnum'=>$pkgnum})) {
- push @{ $svcnum{$cust_svc->getfield('svcpart')} }, $cust_svc;
- }
- }
-
- my @cust_svc;
- #generate @cust_svc
- # for those packages the customer is purchasing:
- # @{$pkgparts} is a list of said packages, by pkgpart
- # @cust_svc is a corresponding list of lists of FS::Record objects
- foreach my $pkgpart ( @{$pkgparts} ) {
- unless ( $part_pkg{$pkgpart} ) {
- $dbh->rollback if $oldAutoCommit;
- return "Customer not permitted to purchase pkgpart $pkgpart!";
- }
- push @cust_svc, [
- map {
- ( $svcnum{$_} && @{ $svcnum{$_} } ) ? shift @{ $svcnum{$_} } : ();
- } map { $_->svcpart }
- qsearch('pkg_svc', { pkgpart => $pkgpart,
- quantity => { op=>'>', value=>'0', } } )
- ];
- }
-
- #special-case until this can be handled better
- # move services to new svcparts - even if the svcparts don't match (svcdb
- # needs to...)
- # looks like they're moved in no particular order, ewwwwwwww
- # and looks like just one of each svcpart can be moved... o well
-
- #start with still-leftover services
- #foreach my $svcpart ( grep { scalar(@{ $svcnum{$_} }) } keys %svcnum ) {
- foreach my $svcpart ( keys %svcnum ) {
- next unless @{ $svcnum{$svcpart} };
-
- my $svcdb = $svcnum{$svcpart}->[0]->part_svc->svcdb;
-
- #find an empty place to put one
- my $i = 0;
- foreach my $pkgpart ( @{$pkgparts} ) {
- my @pkg_svc =
- qsearch('pkg_svc', { pkgpart => $pkgpart,
- quantity => { op=>'>', value=>'0', } } );
- #my @pkg_svc =
- # grep { $_->quantity > 0 } qsearch('pkg_svc', { pkgpart=>$pkgpart } );
- if ( ! @{$cust_svc[$i]} #find an empty place to put them with
- && grep { $svcdb eq $_->part_svc->svcdb } #with appropriate svcdb
- @pkg_svc
- ) {
- my $new_svcpart =
- ( grep { $svcdb eq $_->part_svc->svcdb } @pkg_svc )[0]->svcpart;
- my $cust_svc = shift @{$svcnum{$svcpart}};
- $cust_svc->svcpart($new_svcpart);
- #warn "changing from $svcpart to $new_svcpart!!!\n";
- $cust_svc[$i] = [ $cust_svc ];
- }
- $i++;
- }
-
- }
-
- #check for leftover services
- foreach (keys %svcnum) {
- next unless @{ $svcnum{$_} };
- $dbh->rollback if $oldAutoCommit;
- return "Leftover services, svcpart $_: svcnum ".
- join(', ', map { $_->svcnum } @{ $svcnum{$_} } );
- }