-# _upgrade_data
-#
-# Used by FS::Upgrade to migrate to a new database.
-#
-#
-
-sub _upgrade_data { # class method
- my ($self, %opts) = @_;
- my $dbh = dbh;
-
- warn "$me upgrading $self\n" if $DEBUG;
-
- my $column = dbdef->table($self->table)->column('reason');
- unless ($column->type eq 'text') { # assume history matches main table
-
- # ideally this would be supported in DBIx-DBSchema and friends
- warn "$me Shifting reason column to type 'text'\n" if $DEBUG;
- foreach my $table ( $self->table, 'h_'. $self->table ) {
- my @sql = ();
-
- $column = dbdef->table($self->table)->column('reason');
- my $columndef = $column->line($dbh);
- $columndef =~ s/varchar\(\d+\)/text/i;
- if ( $dbh->{Driver}->{Name} eq 'Pg' ) {
- my $notnull = $columndef =~ s/not null//i;
- push @sql,"ALTER TABLE $table RENAME reason TO freeside_upgrade_reason";
- push @sql,"ALTER TABLE $table ADD $columndef";
- push @sql,"UPDATE $table SET reason = freeside_upgrade_reason";
- push @sql,"ALTER TABLE $table ALTER reason SET NOT NULL"
- if $notnull;
- push @sql,"ALTER TABLE $table DROP freeside_upgrade_reason";
- }elsif( $dbh->{Driver}->{Name} =~ /^mysql/i ){
- push @sql,"ALTER TABLE $table MODIFY reason ". $column->line($dbh);
- }else{
- die "watchu talkin' 'bout, Willis? (unsupported database type)";
- }
-
- foreach (@sql) {
- my $sth = $dbh->prepare($_) or die $dbh->errstr;
- $sth->execute or die $sth->errstr;
- }
+=back
+
+=head1 CLASS METHODS
+
+=over 4
+
+=item new_or_existing reason => REASON, type => TYPE, class => CLASS
+
+Fetches the reason matching these parameters if there is one. If not,
+inserts one. Will also insert the reason type if necessary. CLASS must
+be one of 'C' (cancel reasons), 'R' (credit reasons), 'S' (suspend reasons),
+or 'F' (refund reasons).
+
+This will die if anything fails.
+
+=cut
+
+sub new_or_existing {
+ my $class = shift;
+ my %opt = @_;
+
+ my $error = '';
+ my $reason_type;
+ if ( ref $opt{type} eq 'FS::reason_type' ) {
+ $reason_type = $opt{type};
+ } elsif ( $opt{type} =~ /^\d+$/ ) {
+ $reason_type = FS::reason_type->by_key($opt{type});
+ if (!$reason_type) {
+ die "reason_type #$opt{type} not found\n";