fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2010-10-14 05:13 am

[dw-free] allow promo codes to have attached paid time

[commit: http://hg.dwscoalition.org/dw-free/rev/53fc4397240f]

http://bugs.dwscoalition.org/show_bug.cgi?id=3128

Allow promo invite codes to come preloaded with paid time.

Patch by [personal profile] exor674.

Files modified:
  • bin/upgrading/update-db-general.pl
  • cgi-bin/DW/InviteCodes.pm
  • cgi-bin/DW/InviteCodes/Promo.pm
  • cgi-bin/LJ/User.pm
  • cgi-bin/LJ/Widget/CreateAccount.pm
  • cgi-bin/LJ/Widget/CreateAccountProgressMeter.pm
  • htdocs/admin/invites/promo.bml
  • htdocs/admin/invites/promo.bml.text
--------------------------------------------------------------------------------
diff -r 88ea0f26d63f -r 53fc4397240f bin/upgrading/update-db-general.pl
--- a/bin/upgrading/update-db-general.pl	Thu Oct 14 11:47:13 2010 +0800
+++ b/bin/upgrading/update-db-general.pl	Thu Oct 14 13:12:05 2010 +0800
@@ -2908,6 +2908,8 @@ CREATE TABLE acctcode_promo (
     current_count int(10) unsigned not null default 0,
     active enum('1','0') not null default 1,
     suggest_journalid int unsigned,
+    paid_class varchar(100),
+    paid_months tinyint unsigned,
 
     PRIMARY KEY ( code )
 )
@@ -3854,6 +3856,14 @@ EOF
         do_alter( 'externalaccount',
                   "ALTER TABLE externalaccount ADD COLUMN options blob");
     }
+
+    unless ( column_type( 'acctcode_promo', 'paid_class' ) ) {
+        do_alter( 'acctcode_promo', "ALTER TABLE acctcode_promo ADD COLUMN paid_class varchar(10000)" );
+    }
+
+    unless ( column_type( 'acctcode_promo', 'paid_months' ) ) {
+        do_alter( 'acctcode_promo', "ALTER TABLE acctcode_promo ADD COLUMN paid_months tinyint unsigned" );
+    }
 });
 
 
diff -r 88ea0f26d63f -r 53fc4397240f cgi-bin/DW/InviteCodes.pm
--- a/cgi-bin/DW/InviteCodes.pm	Thu Oct 14 11:47:13 2010 +0800
+++ b/cgi-bin/DW/InviteCodes.pm	Thu Oct 14 13:12:05 2010 +0800
@@ -67,6 +67,8 @@ use constant DIGITS => qw(A B C D E F G 
 use constant DIGITS => qw(A B C D E F G H J K L M N P Q R S T U V W X Y Z 2 3 4 5 6 7 8 9);
 use constant { CODE_LEN => AUTH_LEN + ACID_LEN, DIGITS_LEN => scalar(DIGITS) };
 
+use DW::InviteCodes::Promo;
+
 =head1 API
 
 =head2 C<< $class->generate( [ count => $howmany, ] owner => $forwho, reason => $why >>
@@ -129,75 +131,6 @@ sub could_be_code {
     return 1;
 }
 
-=head2 C<< $class->is_promo_code( code => $code ) >>
-
-Returns if the given code is a promo code or not.
-
-=cut
-
-sub is_promo_code {
-    my ( $class, %opts ) = @_;
-
-    my $promo_code_info = $class->get_promo_code_info( code => $opts{code} );
-
-    return ref $promo_code_info ? 1 : 0;
-}
-
-=head2 C<< $class->get_promo_code_info( code => $code ) >>
-
-Return the info for this promo code in a hashref.
-
-=cut
-
-sub get_promo_code_info {
-    my ( $class, %opts ) = @_;
-    my $dbh = LJ::get_db_writer();
-    my $code = $opts{code};
-
-    return undef unless $code && $code =~ /^[a-z0-9]+$/i; # make sure the code is valid first
-    return $dbh->selectrow_hashref( "SELECT * FROM acctcode_promo WHERE code = ?", undef, $code );
-}
-
-=head2 C<< $class->get_promo_codes( state => $state ) >>
-
-Return the list of promo codes, optionally filtering by state.
-State can be:
-  * active ( active promo codes )
-  * inactive ( inactive promo codes )
-  * unused ( unused promo codes )
-  * noneleft ( no uses left )
-  * all ( all promo codes )
-
-=cut
-
-sub get_promo_codes {
-    my ( $class, %opts ) = @_;
-    my $dbh = LJ::get_db_writer();
-    my $state = $opts{state} || 'active';
-
-    my $sql = "SELECT * FROM acctcode_promo";
-    if ( $state eq 'all' ) {
-        # do nothing
-    } elsif ( $state eq 'active' ) {
-        $sql .= " WHERE active = '1' AND current_count < max_count";
-    } elsif ( $state eq 'inactive' ) {
-        $sql .= " WHERE active = '0' OR current_count >= max_count";
-    } elsif ( $state eq 'unused' ) {
-        $sql .= " WHERE current_count = 0"
-    } elsif ( $state eq 'noneleft' ) {
-        $sql .= " WHERE current_count >= max_count";
-    }
-
-    my $sth = $dbh->prepare( $sql ) or die $dbh->errstr;
-    $sth->execute() or die $dbh->errstr;
-
-    my @out;
-    while ( my $row = $sth->fetchrow_hashref ) {
-        push @out, $row;
-    }
-    return \@out;
-}
-
 =head2 C<< $class->check_code( code => $invite [, userid => $recipient] ) >>
 
 Checks whether code $invite is valid before trying to create an account. Takes
@@ -213,7 +146,7 @@ sub check_code {
 
     # check if this code is a promo code first
     # if it is, make sure it's active and we're not over the creation limit for the code
-    my $promo_code_info = $class->get_promo_code_info( code => $code );
+    my $promo_code_info = DW::InviteCodes::Promo->load( code => $code );
     if ( ref $promo_code_info ) {
         return 0 unless $promo_code_info->{active} && ( $promo_code_info->{current_count} < $promo_code_info->{max_count} );
         return 1;
@@ -277,24 +210,6 @@ sub use_code {
         undef, $opts{user}->{userid}, $self->{acid} );
 
     return 1; # 1 means success? Needs error return in that case.
-}
-
-=head2 C<< $class->use_promo_code >>
-
-Increments the current_count on the given promo code.
-
-=cut
-
-sub use_promo_code {
-    my ( $class, %opts ) = @_;
-    my $dbh = LJ::get_db_writer();
-    my $code = $opts{code};
-
-    return 0 unless $class->is_promo_code( code => $code );
-
-    $dbh->do( "UPDATE acctcode_promo SET current_count = current_count + 1 WHERE code = ?", undef, $code );
-
-    return 1;
 }
 
 =head2 C<< $object->send_code ( [ email => $email ] ) >>
diff -r 88ea0f26d63f -r 53fc4397240f cgi-bin/DW/InviteCodes/Promo.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/InviteCodes/Promo.pm	Thu Oct 14 13:12:05 2010 +0800
@@ -0,0 +1,187 @@
+#!/usr/bin/perl
+#
+# DW::InviteCodes::Promo - Represents a promotional invite code
+#
+# Authors:
+#      Andrea Nall <anall@andreanall.com>
+#
+# Copyright (c) 2010 by Dreamwidth Studios, LLC.
+#
+# This program is free software; you may redistribute it and/or modify it under
+# the same terms as Perl itself. For a copy of the license, please reference
+# 'perldoc perlartistic' or 'perldoc perlgpl'.
+
+package DW::InviteCodes::Promo;
+
+=head1 NAME
+
+DW::InviteCodes::Promo - Represents a promotional invite code
+
+=cut
+
+use strict;
+
+sub _from_row {
+    my ( $class, $row ) = @_;
+    return bless $row, $class;
+}
+
+=head1 CLASS METHODS
+
+=head2 C<< DW::InviteCodes::Promo->load( code => $code ); >>
+
+Gets a DW::InviteCode::Promo objct
+
+=cut
+# FIXME: Consider process caching and/or memcache, if this is a busy enough path
+sub load {
+    my ( $class, %opts ) = @_;
+    my $dbh = LJ::get_db_writer();
+    my $code = $opts{code};
+
+    return undef unless $code && $code =~ /^[a-z0-9]+$/i; # make sure the code is valid first
+    my $data = $dbh->selectrow_hashref( "SELECT * FROM acctcode_promo WHERE code = ?", undef, $code );
+    return undef unless $data;
+
+    return $class->_from_row( $data );
+}
+
+=head2 C<< DW::InviteCodes::Promo->load_bulk( state => $state ); >>
+
+Return the list of promo codes, optionally filtering by state.
+State can be:
+  * active ( active promo codes )
+  * inactive ( inactive promo codes )
+  * unused ( unused promo codes )
+  * noneleft ( no uses left )
+  * all ( all promo codes )
+
+=cut
+sub load_bulk {
+    my ( $class, %opts ) = @_;
+    my $dbh = LJ::get_db_writer();
+    my $state = $opts{state} || 'active';
+
+    my $sql = "SELECT * FROM acctcode_promo";
+    if ( $state eq 'all' ) {
+        # do nothing
+    } elsif ( $state eq 'active' ) {
+        $sql .= " WHERE active = '1' AND current_count < max_count";
+    } elsif ( $state eq 'inactive' ) {
+        $sql .= " WHERE active = '0' OR current_count >= max_count";
+    } elsif ( $state eq 'unused' ) {
+        $sql .= " WHERE current_count = 0"
+    } elsif ( $state eq 'noneleft' ) {
+        $sql .= " WHERE current_count >= max_count";
+    }
+
+    my $sth = $dbh->prepare( $sql ) or die $dbh->errstr;
+    $sth->execute() or die $dbh->errstr;
+
+    my @out;
+    while ( my $row = $sth->fetchrow_hashref ) {
+        push @out, $class->_from_row( $row );
+    }
+    return \@out;
+}
+
+=head2 C<< $class->is_promo_code( code => $code ) >>
+
+Returns if the given code is a promo code or not.
+
+=cut
+sub is_promo_code {
+    my ( $class, %opts ) = @_;
+
+    my $promo_code_info = $class->load( %opts );
+
+    return ref $promo_code_info ? 1 : 0;
+}
+
+=head1 INSTANCE METHODS
+
+=head2 C<< $self->apply_for_user( $u ) >>
+
+Handle any post-create operations for this user.
+
+=cut
+sub apply_for_user {
+    my ( $self, $u ) = @_;
+
+    my $code = $self->code;
+    my $paid_type = $self->paid_class;
+    my $paid_months = $self->paid_months;
+
+    LJ::statushistory_add( $u, undef, 'create_from_promo', "Created new account from promo code '$code'." );
+
+    if ( defined $paid_type ) {
+        if ( DW::Pay::add_paid_time( $u, $paid_type, $paid_months ) ) {
+            LJ::statushistory_add( $u, undef, 'paid_from_promo', "Created new '$paid_type' account from promo code '$code'." );
+        }
+    }
+}
+
+=head2 C<< $self->code >>
+
+=cut
+sub code {
+    return $_[0]->{code};
+}
+
+=head2 C<< $self->paid_class_name >>
+
+Return the display name of this account class.
+
+=cut
+sub paid_class_name {
+    my $self = $_[0];
+
+    foreach my $cap ( keys %LJ::CAP ) {
+        return $LJ::CAP{$cap}->{_visible_name}
+            if $LJ::CAP{$cap} && $LJ::CAP{$cap}->{_account_type} eq $self->paid_class;
+    }
+
+    return 'Invalid Account Class';
+}
+
+=head2 C<< $self->paid_months >>
+
+=cut
+sub paid_months {
+    return $_[0]->{paid_class} ? $_[0]->{paid_months} : 0;
+}
+
+=head2 C<< $self->paid_type >>
+
+=cut
+sub paid_class {
+    return $_[0]->{paid_class};
+}
+
+=head2 C<< $self->suggest_journal
+
+Return the LJ::User to suggest
+
+=cut
+sub suggest_journal {
+    my $id = $_[0]->{suggest_journalid};
+    return $id ? LJ::load_userid( $id ) : undef;
+}
+
+=head2 C<< $self->use_code >>
+
+Increments the current_count on the given promo code.
+
+=cut
+sub use_code {
+    my ( $self ) = @_;
+    my $dbh = LJ::get_db_writer();
+
+    my $code = $self->code;
+
+    $dbh->do( "UPDATE acctcode_promo SET current_count = current_count + 1 WHERE code = ?", undef, $code );
+
+    return 1;
+}
+
+1;
diff -r 88ea0f26d63f -r 53fc4397240f cgi-bin/LJ/User.pm
--- a/cgi-bin/LJ/User.pm	Thu Oct 14 11:47:13 2010 +0800
+++ b/cgi-bin/LJ/User.pm	Thu Oct 14 13:12:05 2010 +0800
@@ -42,6 +42,7 @@ use DW::Pay;
 use DW::Pay;
 use DW::User::ContentFilters;
 use DW::User::Edges;
+use DW::InviteCodes::Promo;
 
 use LJ::Community;
 use LJ::Subscription;
@@ -250,8 +251,9 @@ sub create_personal {
     if ( $LJ::USE_ACCT_CODES && $opts{code} ) {
         my $code = $opts{code};
         my $itemidref;
-        if ( DW::InviteCodes->is_promo_code( code => $code ) ) {
-            LJ::statushistory_add( $u, undef, 'create_from_promo', "Created new account from promo code '$code'." );
+        my $promo_code = DW::InviteCodes::Promo->load( code => $code );
+        if ( $promo_code ) {
+            $promo_code->apply_for_user( $u );
         } elsif ( my $cart = DW::Shop::Cart->get_from_invite( $code, itemidref => \$itemidref ) ) {
             my $item = $cart->get_item( $itemidref );
             if ( $item && $item->isa( 'DW::Shop::Item::Account' ) ) {
diff -r 88ea0f26d63f -r 53fc4397240f cgi-bin/LJ/Widget/CreateAccount.pm
--- a/cgi-bin/LJ/Widget/CreateAccount.pm	Thu Oct 14 11:47:13 2010 +0800
+++ b/cgi-bin/LJ/Widget/CreateAccount.pm	Thu Oct 14 13:12:05 2010 +0800
@@ -251,16 +251,24 @@ sub render_body {
     $ret .= "</label>";
     $ret .= "</td></tr>\n";
 
-    if ( $LJ::USE_ACCT_CODES && !DW::InviteCodes->is_promo_code( code => $code ) ) {
-        my $item = DW::InviteCodes->paid_status( code => $code );
-        if ( $item ) {
-            $ret .= "<tr valign='top'><td class='field-name'>&nbsp;</td>\n<td>";
-            if ( $item->permanent ) {
-                $ret .= $class->ml( 'widget.createaccount.field.paidaccount.permanent', { type => "<strong>" . $item->class_name . "</strong>" } );
-            } else {
-                $ret .= $class->ml( 'widget.createaccount.field.paidaccount', { type => "<strong>" . $item->class_name . "</strong>", nummonths => $item->months } );
+    if ( $LJ::USE_ACCT_CODES ) {
+        if ( my $pc = DW::InviteCodes::Promo->load( code => $code ) ) {
+            if ( $pc->paid_class ) {
+                $ret .= "<tr valign='top'><td class='field-name'>&nbsp;</td>\n<td>";
+                $ret .= $class->ml( 'widget.createaccount.field.paidaccount', { type => "<strong>" . $pc->paid_class_name . "</strong>", nummonths => $pc->paid_months } );
+                $ret .= "</td></tr>";
+            } 
+        } else {
+            my $item = DW::InviteCodes->paid_status( code => $code );
+            if ( $item ) {
+                $ret .= "<tr valign='top'><td class='field-name'>&nbsp;</td>\n<td>";
+                if ( $item->permanent ) {
+                    $ret .= $class->ml( 'widget.createaccount.field.paidaccount.permanent', { type => "<strong>" . $item->class_name . "</strong>" } );
+                } else {
+                    $ret .= $class->ml( 'widget.createaccount.field.paidaccount', { type => "<strong>" . $item->class_name . "</strong>", nummonths => $item->months } );
+                }
+                $ret .= "</td></tr>";
             }
-            $ret .= "</td></tr>";
         }
     }
 
@@ -319,11 +327,9 @@ sub handle_post {
             $from_post{code_valid} = 1;
 
             # and if this is a community promo code, set the inviter
-            if ( my $pc = DW::InviteCodes->get_promo_code_info( code => $code ) ) {
-                if ( $pc->{suggest_journalid} ) {
-                    my $invu = LJ::load_userid( $pc->{suggest_journalid} );
-                    $post->{from} = $invu->user if $invu;
-                }
+            if ( my $pc = DW::InviteCodes::Promo->load( code => $code ) ) {
+                my $invu = $pc->suggest_journal;
+                $post->{from} = $invu->user if $invu;
             }
 
         } else {
@@ -453,8 +459,8 @@ sub handle_post {
 
         # we're all done; mark the invite code as used
         if ( $LJ::USE_ACCT_CODES && $code ) {
-            if ( DW::InviteCodes->is_promo_code( code => $code ) ) {
-                DW::InviteCodes->use_promo_code( code => $code );
+            if ( my $pc = DW::InviteCodes::Promo->load( code => $code ) ) {
+                $pc->use_code;
             } else {
                 my $invitecode = DW::InviteCodes->new( code => $code );
                 $invitecode->use_code( user => $nu );
diff -r 88ea0f26d63f -r 53fc4397240f cgi-bin/LJ/Widget/CreateAccountProgressMeter.pm
--- a/cgi-bin/LJ/Widget/CreateAccountProgressMeter.pm	Thu Oct 14 11:47:13 2010 +0800
+++ b/cgi-bin/LJ/Widget/CreateAccountProgressMeter.pm	Thu Oct 14 13:12:05 2010 +0800
@@ -27,7 +27,7 @@ sub render_body {
 
     my $given_step = $opts{step} || 1;
     my @steps_to_show = !LJ::is_enabled( 'payments' )
-                    || ( $LJ::USE_ACCT_CODES && $given_step == 1 && !DW::InviteCodes->is_promo_code( code => $opts{code} ) && DW::InviteCodes->paid_status( code => $opts{code} ) )
+                    || ( $LJ::USE_ACCT_CODES && $given_step == 1 && !DW::InviteCodes::Promo->is_promo_code( code => $opts{code} ) && DW::InviteCodes->paid_status( code => $opts{code} ) )
                     || ( $given_step > 1 && $u && $u->is_paid )
                     ? ( 1, 2, 4 ) : ( 1..4 );
 
diff -r 88ea0f26d63f -r 53fc4397240f htdocs/admin/invites/promo.bml
--- a/htdocs/admin/invites/promo.bml	Thu Oct 14 11:47:13 2010 +0800
+++ b/htdocs/admin/invites/promo.bml	Thu Oct 14 13:12:05 2010 +0800
@@ -15,7 +15,7 @@ body<=
 {
     use strict;
     use vars qw( %GET %POST $title );
-    use DW::InviteCodes;
+    use DW::InviteCodes::Promo;
 
     $title = $ML{'.title'};
 
@@ -68,6 +68,24 @@ body<=
         $ret .= LJ::html_text( { id => 'suggest_journal', name => 'suggest_journal', value => ( $suggest_u ? $suggest_u->username : ( $data->{suggest_journal} || "" ) ), size => 28, maxlength => 25  } );
         $ret .= "  <strong>[$ML{'.error.label'} " . join(', ', @{$errors->{suggest_journal}}) . "]</strong>" if $errors->{suggest_journal};
         $ret .= '<br />';
+        
+        $ret .= LJ::labelfy( 'paid_class', "$ML{'.field.paid_class.label'} "  );
+        $ret .= LJ::html_select( {
+                id => 'paid_class',
+                name => 'paid_class',
+                selected => ( $data->{paid_class} || '' ),
+            },
+            { value => '', text => $ML{'.field.paid_class.none'} },
+            { value => 'paid', text => $ML{'.field.paid_class.paid'} },
+            { value => 'premium', text => $ML{'.field.paid_class.premium'} },
+        );
+        $ret .= '<br />';
+        
+        $ret .= LJ::labelfy( 'paid_months', "$ML{'.field.paid_months.label'} "  );
+        $ret .= LJ::html_text( { id => 'paid_months', name => 'paid_months', value => ( $data->{paid_months} || "" ), size => 10, maxlength => 2 } );
+        $ret .= '<br />';
+
+        
         $ret .= LJ::html_submit( value => $ML{ ( $data ? '.btn.save' : '.btn.create' ) } );
         $ret .= "</form>";
     };
@@ -84,6 +102,8 @@ body<=
                 current_count => 0,
                 max_count => $POST{max_count} || 0,
                 suggest_journal => $POST{suggest_journal},
+                paid_class => $POST{paid_class} || '',
+                paid_months => $POST{paid_months} || undef,
             };
             my $valid = 1;
             my $errors = {};
@@ -93,7 +113,7 @@ body<=
             } elsif ( ! ( $code =~ /^[a-z0-9]+$/i ) ) {
                 push @{$errors->{code}}, $ML{'.error.code.invalid_character'};
                 $valid = 0;
-            } elsif ( DW::InviteCodes->is_promo_code( code => $code ) ) {
+            } elsif ( DW::InviteCodes::Promo->is_promo_code( code => $code ) ) {
                 push @{$errors->{code}}, $ML{'.error.code.exists'};
                 $valid = 0;
             }
@@ -111,10 +131,14 @@ body<=
             } else {
                 $data->{suggest_journal} = undef;
             }
+            if ( $data->{paid_class} !~ /^(paid|premium)$/ ) {
+                $data->{paid_class} = undef;
+                $data->{paid_months} = undef;
+            }
             if ( $valid ) {
                 my $dbh = LJ::get_db_writer();
-                $dbh->do( "INSERT INTO acctcode_promo (code, max_count, active, suggest_journalid) VALUES (?, ?, ?, ?)", undef,
-                            $data->{code}, $data->{max_count}, $data->{active}, $data->{suggest_journalid} ) or die $dbh->errstr;
+                $dbh->do( "INSERT INTO acctcode_promo (code, max_count, active, suggest_journalid, paid_class, paid_months) VALUES (?, ?, ?, ?, ?, ?)", undef,
+                            $data->{code}, $data->{max_count}, $data->{active}, $data->{suggest_journalid}, $data->{paid_class}, $data->{paid_months} ) or die $dbh->errstr;
             } else {
                 $create_form->( $data, $errors );
                 return $ret;
@@ -128,6 +152,8 @@ body<=
                 current_count => 0,
                 max_count => $POST{max_count} || 0,
                 suggest_journal => $POST{suggest_journal},
+                paid_class => $POST{paid_class} || '',
+                paid_months => $POST{paid_months} || undef,
             };
             my $valid = 1;
             my $errors = {};
@@ -135,7 +161,7 @@ body<=
             if ( ! $code ) {
                 push @{$errors->{code}}, $ML{'.error.code.missing'};
                 $valid = 0;
-            } elsif ( ! ref ( $info = DW::InviteCodes->get_promo_code_info( code => $code ) ) ) {
+            } elsif ( ! ref ( $info = DW::InviteCodes::Promo->load( code => $code ) ) ) {
                 push @{$errors->{code}}, $ML{'.error.code.invalid'};
                 $valid = 0;
             } else {
@@ -155,10 +181,14 @@ body<=
             } else {
                 $data->{suggest_journal} = undef;
             }
+            if ( $data->{paid_class} !~ /^(paid|premium)$/ ) {
+                $data->{paid_class} = undef;
+                $data->{paid_months} = undef;
+            }
             if ( $valid ) {
                 my $dbh = LJ::get_db_writer();
-                $dbh->do( "UPDATE acctcode_promo SET max_count = ?, active = ?, suggest_journalid = ? WHERE code = ?", undef,
-                            $data->{max_count}, $data->{active}, $data->{suggest_journalid}, $data->{code} ) or die $dbh->errstr;
+                $dbh->do( "UPDATE acctcode_promo SET max_count = ?, active = ?, suggest_journalid = ?, paid_class = ?, paid_months = ? WHERE code = ?", undef,
+                            $data->{max_count}, $data->{active}, $data->{suggest_journalid}, $data->{paid_class}, $data->{paid_months}, $data->{code} ) or die $dbh->errstr;
             } else {
                 $create_form->( $data, $errors );
                 return $ret;
@@ -169,10 +199,11 @@ body<=
 
     if ( $state eq 'create' ) {
         $create_form->( );
-    } elsif ( DW::InviteCodes->is_promo_code( code => $code ) ) {
-        $create_form->( DW::InviteCodes->get_promo_code_info( code => $code ) );
+    } elsif ( DW::InviteCodes::Promo->is_promo_code( code => $code ) ) {
+        $create_form->( DW::InviteCodes::Promo->load( code => $code ) );
     } else {
-        my $codes = DW::InviteCodes->get_promo_codes( state => $state );
+        # FIXME: Do not do hash accesses on this.
+        my $codes = DW::InviteCodes::Promo->load_bulk( state => $state );
 
         $ret .= '<a href="/admin/invites/promo?state=create">' . $ML{'.state.new'} . '</a> | ';
         $ret .= '<a href="/admin/invites/promo?state=all">' . $ML{'.state.unfiltered'} . '</a> | ';
@@ -182,7 +213,7 @@ body<=
         $ret .= '<a href="/admin/invites/promo?state=noneleft">' . $ML{'.state.noneleft'} . '</a>';
 
         $ret .= "<table>";
-        $ret .= "<tr><th>$ML{'.heading.code'}</th><th>$ML{'.heading.active'}</th><th>$ML{'.heading.count'}</th><th>$ML{'.heading.suggest'}</th></tr>";
+        $ret .= "<tr><th>$ML{'.heading.code'}</th><th>$ML{'.heading.active'}</th><th>$ML{'.heading.count'}</th><th>$ML{'.heading.suggest'}</th><th>$ML{'.heading.paid'}</tr>";
         
         if ( scalar( @$codes ) ) {
             foreach my $code (@$codes) {
@@ -192,6 +223,15 @@ body<=
                 $ret .= "<td>" . ( $code->{active} ? $ML{'.active.active'} : $ML{'.active.inactive'} ) . "</td>";
                 $ret .= "<td>" . $code->{current_count} . $ML{'.count.outof'} . $code->{max_count} . "</td>";
                 $ret .= "<td>" . ( $suggest_u ? $suggest_u->ljuser_display : $ML{'.suggest.none'} ) . "</td>";
+                if ( defined $code->{paid_class} ) {
+                    $ret .= "<td>" .
+                            BML::ml('.paid', {
+                                type => $code->{paid_class},
+                                months => $code->{paid_months}
+                            } ) . "</td>";
+                } else {
+                    $ret .= "<td>$ML{'.paid.no'}</td>";
+                }
                 $ret .= "</tr>";
             }
         } else {
diff -r 88ea0f26d63f -r 53fc4397240f htdocs/admin/invites/promo.bml.text
--- a/htdocs/admin/invites/promo.bml.text	Thu Oct 14 11:47:13 2010 +0800
+++ b/htdocs/admin/invites/promo.bml.text	Thu Oct 14 13:12:05 2010 +0800
@@ -28,6 +28,16 @@
 
 .field.count.label=Count:
 
+.field.paid_class.label=Paid Account:
+
+.field.paid_class.none=(No Paid Time)
+
+.field.paid_class.paid=Paid
+
+.field.paid_class.premium=Premium Paid
+
+.field.paid_months.label=Months:
+
 .field.suggest_journal.label=Suggest Journal:
 
 .heading.active=Active
@@ -36,9 +46,15 @@
 
 .heading.count=Count
 
+.heading.paid=Paid Time
+
 .heading.suggest=Suggest Journal
 
 .nomatch=No promo codes match your criteria
+
+.paid=[[type]] for [[months]] [[?months|month|months]]
+
+.paid.no=(none)
 
 .return=Return to list
 
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
No Subject Icon Selected
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org