From dd204a0e9ccfd6374b843fa8e5ad4585768d11e0 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Thu, 20 Sep 2012 01:24:52 -0700 Subject: [PATCH] fix part_pkg upgrade, fallout from 18503 --- FS/FS/part_pkg.pm | 83 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index 91bcdc5b5..70b2d4dd6 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -1598,18 +1598,79 @@ sub _upgrade_data { # class method # set any package with FCC voice lines to the "VoIP with broadband" category # for backward compatibility - my $journal = 'part_pkg_fcc_voip_class'; - if (!FS::upgrade_journal->is_done($journal)) { - @part_pkg = qsearch('part_pkg', { - fcc_ds0s => { op => '>', value => 0 }, - fcc_voip_class => '' - }); - foreach my $part_pkg (@part_pkg) { - $part_pkg->set(fcc_voip_class => 2); - my $error = $part_pkg->replace; - die $error if $error; + # + # recover from a bad upgrade bug + my $upgrade = 'part_pkg_fcc_voip_class_FIX'; + if (!FS::upgrade_journal->is_done($upgrade)) { + my $bad_upgrade = qsearchs('upgrade_journal', + { upgrade => 'part_pkg_fcc_voip_class' } + ); + if ( $bad_upgrade ) { + my $where = 'WHERE history_date <= '.$bad_upgrade->_date. + ' AND history_date > '.($bad_upgrade->_date - 600); + my @h_part_pkg_option = map { FS::part_pkg_option->new($_->hashref) } + qsearch({ + 'select' => '*', + 'table' => 'h_part_pkg_option', + 'hashref' => {}, + 'extra_sql' => "$where AND history_action = 'delete'", + 'order_by' => 'ORDER BY history_date ASC', + }); + my @h_pkg_svc = map { FS::pkg_svc->new($_->hashref) } + qsearch({ + 'select' => '*', + 'table' => 'h_pkg_svc', + 'hashref' => {}, + 'extra_sql' => "$where AND history_action = 'replace_old'", + 'order_by' => 'ORDER BY history_date ASC', + }); + my %opt; + foreach my $deleted (@h_part_pkg_option, @h_pkg_svc) { + my $pkgpart ||= $deleted->pkgpart; + $opt{$pkgpart} ||= { + options => {}, + pkg_svc => {}, + primary_svc => '', + hidden_svc => {}, + }; + if ( $deleted->isa('FS::part_pkg_option') ) { + $opt{$pkgpart}{options}{ $deleted->optionname } = $deleted->optionvalue; + } else { # pkg_svc + my $svcpart = $deleted->svcpart; + $opt{$pkgpart}{pkg_svc}{$svcpart} = $deleted->quantity; + $opt{$pkgpart}{hidden_svc}{$svcpart} ||= $deleted->hidden; + $opt{$pkgpart}{primary_svc} = $svcpart if $deleted->primary_svc; + } + } + foreach my $pkgpart (keys %opt) { + my $part_pkg = FS::part_pkg->by_key($pkgpart); + my $error = $part_pkg->replace( $part_pkg->replace_old, $opt{$pkgpart} ); + if ( $error ) { + die "error recovering damaged pkgpart $pkgpart:\n$error\n"; + } + } + } # $bad_upgrade exists + else { # do the original upgrade, but correctly this time + @part_pkg = qsearch('part_pkg', { + fcc_ds0s => { op => '>', value => 0 }, + fcc_voip_class => '' + }); + foreach my $part_pkg (@part_pkg) { + $part_pkg->set(fcc_voip_class => 2); + my @pkg_svc = $part_pkg->pkg_svc; + my %quantity = map {$_->svcpart, $_->quantity} @pkg_svc; + my %hidden = map {$_->svcpart, $_->hidden } @pkg_svc; + my $error = $part_pkg->replace( + $part_pkg->replace_old, + options => { $part_pkg->options }, + pkg_svc => \%quantity, + hidden_svc => \%hidden, + primary_svc => ($part_pkg->svcpart || ''), + ); + die $error if $error; + } } - FS::upgrade_journal->set_done($journal); + FS::upgrade_journal->set_done($upgrade); } } -- 2.11.0