+#false laziness w/agent::generate_reg_codes
+sub generate {
+ my( $num, $type, $length, $hashref ) = @_;
+
+ my @codeset = ();
+ push @codeset, ( 'A'..'Z' ) if $type =~ /alpha/;
+ push @codeset, ( '1'..'9' ) if $type =~ /numeric/;
+ $length ||= 8;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $condup = 0; #don't retry forever
+
+ my @cards = ();
+ for ( 1 ... $num ) {
+
+ my $identifier = join('', map($codeset[int(rand $#codeset)], (1..$length) ) );
+
+ if ( qsearchs('prepay_credit',{identifier=>$identifier}) ) {
+ if ( $condup++ < 54 ) {
+ warn "$me generate: duplicate identifier $identifier; retrying\n"
+ if $DEBUG;
+ redo;
+ } else {
+ warn "$me generate: giving up after 54 tries"
+ if $DEBUG;
+ }
+ }
+ $condup = 0;
+
+ my $prepay_credit = new FS::prepay_credit {
+ 'identifier' => $identifier,
+ %$hashref,
+ };
+ my $error = $prepay_credit->check || $prepay_credit->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "(inserting prepay_credit) $error";
+ }
+ push @cards, $prepay_credit->identifier;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ \@cards;