mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2010-04-30 06:36 am

[dw-free] anniversary promotion

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

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

Anniversary Promotion code.

Patch by [staff profile] mark.

Files modified:
  • cgi-bin/DW/Controller/Shop.pm
  • cgi-bin/DW/Hooks/AnniversaryPromotion.pm
  • cgi-bin/DW/Hooks/HolidayPromotion.pm
  • cgi-bin/DW/Shop/Cart.pm
  • cgi-bin/DW/Shop/Item/Points.pm
  • cgi-bin/LJ/Widget/ShopCart.pm
--------------------------------------------------------------------------------
diff -r 075727259777 -r cf64a41b1154 cgi-bin/DW/Controller/Shop.pm
--- a/cgi-bin/DW/Controller/Shop.pm	Thu Apr 29 05:07:18 2010 -0500
+++ b/cgi-bin/DW/Controller/Shop.pm	Fri Apr 30 06:36:45 2010 +0000
@@ -59,6 +59,10 @@ sub _shop_controller {
 
     # populate vars with cart display template
     $rv->{cart_display} = DW::Template->template_string( 'shop/cartdisplay.tt', $rv );
+
+    # call any hooks to do things before we return success
+    LJ::Hooks::run_hooks( 'shop_controller', $rv );
+
     return ( 1, $rv );
 }
 
diff -r 075727259777 -r cf64a41b1154 cgi-bin/DW/Hooks/AnniversaryPromotion.pm
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cgi-bin/DW/Hooks/AnniversaryPromotion.pm	Fri Apr 30 06:36:45 2010 +0000
@@ -0,0 +1,121 @@
+#!/usr/bin/perl
+#
+# DW::Hooks::AnniversaryPromotion
+#
+# This file explains Dreamwidth's plans for world domination. Be sure to keep it updated!
+#
+# Authors:
+#      Mark Smith <mark@dreamwidth.org>
+#
+# This program is NOT free software or open-source; you can use it as an
+# example of how to implement your own site-specific extensions to the
+# Dreamwidth Studios open-source code, but you cannot use it on your site
+# or redistribute it, with or without modifications.
+#
+
+package DW::Hooks::AnniversasryPromotion;
+
+use strict;
+use LJ::Hooks;
+
+
+# returns if the promotion is valid right now
+sub promo_valid {
+    # valid from 2010-05-01 01:00:00 UTC to 2010-05-08 01:00:00 UTC
+    # this corresponds to 2010-04-30 21:00:00 EDT and a week later...
+    return 0 if time < 1272675600 || time > 1273280400;
+    return 1;
+}
+
+
+# returns how many points this cart is eligible for
+sub cart_bonus_points {
+    return int( $_[0]->total_cash );
+}
+
+
+# promotion HTML
+LJ::Hooks::register_hook( 'shop_controller', sub {
+    my ( $rv ) = @_;
+
+    # ensure we're a valid promotional period and not anon
+    return unless promo_valid();
+    return if $rv->{shop}->anonymous;
+
+    # put the note up top so people know
+    $rv->{cart_display} .=
+        "<div class='shop-error'><strong>" .
+        LJ::Lang::ml( 'shop.anniversarypromoblurb' ) .
+        "</strong></div>\n";
+} );
+
+
+# put information after the cart is rendered
+LJ::Hooks::register_hook( 'shop_cart_render', sub {
+    my ( $retref, %opts ) = @_;
+    return if $opts{admin};
+
+    # promo period and not anonymous
+    return unless promo_valid();
+    return unless $opts{cart}->userid;
+
+    # determine how many points they get ... basically, 1 point per $1 USD
+    # spent..  does not get points for spending points!
+    my $points = cart_bonus_points( $opts{cart} );
+
+    # text depends on how many points they get
+    $$retref .= '<p class="shop-account-status">';
+    if ( $points > 0 ) {
+        $$retref .= LJ::Lang::ml( 'shop.annivpromo.points', { points => $points } );
+    } else {
+        $$retref .= LJ::Lang::ml( 'shop.annivpromo.nopoints' );
+    }
+    $$retref .= '</p>';
+} );
+
+
+# this is where the magic happens.  when a cart enters or leaves the
+# paid state, then we have to apply or unapply their bonus points.
+LJ::Hooks::register_hook( 'shop_cart_state_change', sub {
+    my ( $cart, $newstate ) = @_;
+
+    # if the cart is going INTO the paid state, then we apply the bonus points
+    # to the user who bought the items
+    if ( $newstate == $DW::Shop::STATE_PAID ) {
+        my $points = cart_bonus_points( $cart );
+        my $u = LJ::load_userid( $cart->userid );
+        return unless $points && $u;
+
+        # now give them the points for their bonus
+        $u->give_shop_points( amount => $points, reason => sprintf( 'order %d bonus points', $cart->id ) );
+        return;
+    }
+
+    # however, if the OLD state was PROCESSED (means we're being refunded or
+    # something is happening) then we need to email admins.  the logic to
+    # determine if we ever gave the user bonus points is too fickle, for now
+    # we can just handle point reversals manually.
+    if ( $cart->state == $DW::Shop::STATE_PROCESSED ) {
+        LJ::send_mail( {
+            to => $LJ::ADMIN_EMAIL,
+            from => $LJ::BOGUS_EMAIL,
+            fromname => $LJ::SITENAME,
+            subject => 'Attention: Order Investigation Needed',
+            body => <<EOF,
+Dear admins,
+
+Order #@{[$cart->id]} has left the PROCESSED state during an active promotion
+period and needs to be investigated.  The user may need to have bonus points
+unapplied from their account.
+
+
+Best regards,
+The $LJ::SITENAMESHORT Payment System
+EOF
+        } );
+    }
+
+} );
+
+
+1;
diff -r 075727259777 -r cf64a41b1154 cgi-bin/DW/Hooks/HolidayPromotion.pm
--- a/cgi-bin/DW/Hooks/HolidayPromotion.pm	Thu Apr 29 05:07:18 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-#!/usr/bin/perl
-#
-# DW::Hooks::HolidayPromotion
-#
-# This file explains Dreamwidth's plans for world domination. Be sure to keep it updated!
-#
-# Authors:
-#      Mark Smith <mark@dreamwidth.org>
-#
-# This program is NOT free software or open-source; you can use it as an
-# example of how to implement your own site-specific extensions to the
-# Dreamwidth Studios open-source code, but you cannot use it on your site
-# or redistribute it, with or without modifications.
-#
-
-package DW::Hooks::HolidayPromotion;
-
-use strict;
-use LJ::Hooks;
-
-# promotion HTML
-LJ::Hooks::register_hook( 'shop_cart_status_bar', sub {
-    my ( $shop, $cart, $retref ) = @_;
-
-    # anonymous sessions can't benefit from the promotion
-    return if $shop->anonymous;
-
-    # bail out if it's expired (2010-01-01 00:00:00)
-    return if time > 1262304000;
-
-    # put the note up top so people know
-    $$retref = "<div class='shop-error'><strong>" . BML::ml( 'shop.holidaypromoblurb' ) .
-               "</strong></div>\n" . $$retref;
-} );
-
-# hook to add a new item when they purchase somethign eligibile
-LJ::Hooks::register_hook( 'shop_cart_added_item', sub {
-    my ( $cart, $item ) = @_;
-
-    # bail out if it's expired (2010-01-01 00:00:00)
-    return if time > 1262304000;
-
-    # ignore promo linked items so we don't loop forever
-    return if $item->{_holiday_promo_2009};
-
-    # validation checks
-    return unless $cart->userid;
-    return if $item->t_userid && $item->t_userid == $cart->userid;
-    return if $item->permanent || $item->months < 6;
-
-    # determine what kind of time to give the user.  rules are simple, if
-    # the user has premium, give them premium.  else, they get paid.
-    my $type = DW::Pay::get_account_type( $cart->userid );
-    $type = 'paid' if $type ne 'premium';
-
-    # looks good, build a new object and stick it on the cart
-    my $new = bless {
-        cost_cash => 0.00,
-        cost_points => 0,
-        months => int( $item->months / 6 ) * 2,
-        class  => $type,
-        target_userid => $cart->userid,
-        cannot_conflict => 1,
-        noremove => 1,
-        from_name => $LJ::SITENAME,
-
-        _holiday_promo_2009  => $item->id,
-    }, 'DW::Shop::Item::Account';
-
-    my ( $rv, $msg ) = $cart->add_item( $new );
-    warn "Failed to add holiday promotion time: $msg\n"
-        unless $rv;
-} );
-
-# when they remove an item ...
-LJ::Hooks::register_hook( 'shop_cart_removed_item', sub {
-    my ( $cart, $item ) = @_;
-
-    # don't do anything if we're removing a promo item
-    return if $item->{_holiday_promo_2009};
-
-    # iterate over the cart to see if any items link to this one
-    foreach my $it ( @{$cart->items} ) {
-        if ( $it->{_holiday_promo_2009} == $item->id ) {
-            # they're linked, remove it forcefully (mental image: large hammer)
-            $cart->remove_item( $it->id, force => 1 );
-        }
-    }
-
-} );
-
-
-1;
diff -r 075727259777 -r cf64a41b1154 cgi-bin/DW/Shop/Cart.pm
--- a/cgi-bin/DW/Shop/Cart.pm	Thu Apr 29 05:07:18 2010 -0500
+++ b/cgi-bin/DW/Shop/Cart.pm	Fri Apr 30 06:36:45 2010 +0000
@@ -436,6 +436,8 @@ sub state {
     return $self->{state}
         unless defined $newstate;
 
+    LJ::Hooks::run_hooks( 'shop_cart_state_change', $self, $newstate );
+
     $self->{state} = $newstate;
     $self->save;
 
diff -r 075727259777 -r cf64a41b1154 cgi-bin/DW/Shop/Item/Points.pm
--- a/cgi-bin/DW/Shop/Item/Points.pm	Thu Apr 29 05:07:18 2010 -0500
+++ b/cgi-bin/DW/Shop/Item/Points.pm	Fri Apr 30 06:36:45 2010 +0000
@@ -154,8 +154,9 @@ sub can_be_added {
         return 0;
     }
 
-    # sanity check that the points are in-range and less than 5000?
-    if ( $self->points < 30 || $self->points > 5000 ) {
+    # sanity check that the points are in-range and less than 5000, but only if they're being
+    # purchased.  otherwise, we allow anything if it's a 0.00 cost item.
+    if ( $self->cost_cash > 0.00 && ( $self->points < 30 || $self->points > 5000 ) ) {
         $$errref = LJ::Lang::ml( 'shop.item.points.canbeadded.outofrange' );
         return 0;
     }
diff -r 075727259777 -r cf64a41b1154 cgi-bin/LJ/Widget/ShopCart.pm
--- a/cgi-bin/LJ/Widget/ShopCart.pm	Thu Apr 29 05:07:18 2010 -0500
+++ b/cgi-bin/LJ/Widget/ShopCart.pm	Fri Apr 30 06:36:45 2010 +0000
@@ -29,7 +29,7 @@ sub render_body {
 
     my $ret;
 
-    my $cart = $opts{cart} || DW::Shop->get->cart
+    my $cart = $opts{cart} ||= DW::Shop->get->cart
         or return $class->ml( 'widget.shopcart.error.nocart' );
 
     return $class->ml( 'widget.shopcart.error.noitems' )
@@ -146,6 +146,9 @@ sub render_body {
         $ret .= $class->end_form;
     }
 
+    # allow hooks to alter the cart or append to it
+    LJ::Hooks::run_hooks( 'shop_cart_render', \$ret, %opts );
+
     return $ret;
 }
 
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

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