Add a creation date to the Cart.

Use that date to expire carts older than an interval, via a new workflow.
Config file changes, tests, i18n.
This commit is contained in:
Colin Kuskie 2009-04-02 21:58:45 +00:00
parent 6bd159bcfd
commit 60a3906b05
9 changed files with 299 additions and 5 deletions

View file

@ -21,6 +21,7 @@
- Survey now shows warnings if bad goto, bad gotoExpressions, no question text, survey looping,
or no question answers are found.
- fixed: Gateway problem with VendorPayout.
- fixed #9976: carts not cleaned up
7.7.1
- the AdSku project: create a Sku that allows buyers to purchase advertising in select AdSpaces at selected priorities

View file

@ -10,6 +10,8 @@ save you many hours of grief.
7.7.2
--------------------------------------------------------------------
* WebGUI now requires Clone version 0.31 or greater.
* You must upgrade to WebGUI 7.7.2 before going on to higher versions of WebGUI due
to changes in the database table for the Cart.
7.7.1
--------------------------------------------------------------------

View file

@ -22,7 +22,8 @@ use Getopt::Long;
use WebGUI::Session;
use WebGUI::Storage;
use WebGUI::Asset;
use WebGUI::Workflow;
use WebGUI::Utility;
my $toVersion = '7.7.2';
my $quiet; # this line required
@ -37,6 +38,9 @@ addRssFeedAspect($session);
addRssFeedAspectToAssets($session);
addRssFeedAspectToCollaboration($session);
removeRssCapableAsset($session);
addCreationTimeToCart($session);
addCartKillerActivityToConfig($session);
addCartKillerActivityToWorkflow($session);
finish($session); # this line required
@ -128,6 +132,38 @@ sub removeRssCapableAsset {
print "Done.\n" unless $quiet;
}
#----------------------------------------------------------------------------
sub addCreationTimeToCart {
my $session = shift;
print "\tAdding creation time to cart..." unless $quiet;
$session->db->write("alter table cart add column creationDate int(20)");
$session->db->write('update cart set creationDate=NOW()');
print "Done.\n" unless $quiet;
}
#----------------------------------------------------------------------------
sub addCartKillerActivityToConfig {
my $session = shift;
print "\tAdding Remove Old Carts workflow activity to config files..." unless $quiet;
my $activities = $session->config->get('workflowActivities');
my $none = $activities->{'None'};
if (!isIn('WebGUI::Workflow::Activity::RemoveOldCarts', @{ $none })) {
push @{ $none }, 'WebGUI::Workflow::Activity::RemoveOldCarts';
}
$session->config->set('workflowActivities', $activities);
print "Done.\n" unless $quiet;
}
#----------------------------------------------------------------------------
sub addCartKillerActivityToWorkflow {
my $session = shift;
print "\tAdding Remove Old Carts workflow activity to Daily Workflow..." unless $quiet;
my $workflow = WebGUI::Workflow->new($session, 'pbworkflow000000000001');
my $removeCarts = $workflow->addActivity('WebGUI::Workflow::Activity::RemoveOldCarts');
$removeCarts->set('title', 'Remove old carts');
print "Done.\n" unless $quiet;
}
#----------------------------------------------------------------------------
# Describe what our function does

View file

@ -814,6 +814,7 @@
"WebGUI::Workflow::Activity::NotifyAdminsWithOpenVersionTags",
"WebGUI::Workflow::Activity::PurgeOldAssetRevisions",
"WebGUI::Workflow::Activity::PurgeOldTrash",
"WebGUI::Workflow::Activity::RemoveOldCarts",
"WebGUI::Workflow::Activity::SendQueuedMailMessages",
"WebGUI::Workflow::Activity::SummarizePassiveProfileLog",
"WebGUI::Workflow::Activity::SyncProfilesToLdap",

View file

@ -175,7 +175,7 @@ sub create {
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
}
my $cartId = $session->id->generate;
$session->db->write('insert into cart (cartId, sessionId) values (?,?)', [$cartId, $session->getId]);
$session->db->write('insert into cart (cartId, sessionId, creationDate) values (?,?,UNIX_TIMESTAMP())', [$cartId, $session->getId]);
return $class->new($session, $cartId);
}
@ -561,6 +561,10 @@ The unique id of the configured shipping driver that will be used to ship these
The ID of a user being checked out, if they're being checked out by a cashier.
=head4 creationDate
The date the cart was created.
=cut
sub update {
@ -569,7 +573,7 @@ sub update {
WebGUI::Error::InvalidParam->throw(error=>"Need a properties hash ref.");
}
my $id = id $self;
foreach my $field (qw(shippingAddressId posUserId shipperId)) {
foreach my $field (qw(shippingAddressId posUserId shipperId creationDate)) {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
}
$self->session->db->setRow("cart","cartId",$properties{$id});

View file

@ -0,0 +1,110 @@
package WebGUI::Workflow::Activity::RemoveOldCarts;
=head1 LEGAL
-------------------------------------------------------------------
WebGUI is Copyright 2001-2009 Plain Black Corporation.
-------------------------------------------------------------------
Please read the legal notices (docs/legal.txt) and the license
(docs/license.txt) that came with this distribution before using
this software.
-------------------------------------------------------------------
http://www.plainblack.com info@plainblack.com
-------------------------------------------------------------------
=cut
use strict;
use base 'WebGUI::Workflow::Activity';
use WebGUI::International;
use WebGUI::Asset::Sku::Product;
use WebGUI::Inbox;
=head1 NAME
Package WebGUI::Workflow::Activity::RemoveOldCarts
=head1 DESCRIPTION
Remove carts that are older than a configurable threshold.
=head1 SYNOPSIS
See WebGUI::Workflow::Activity for details on how to use any activity.
=head1 METHODS
These methods are available from this class:
=cut
#-------------------------------------------------------------------
=head2 definition ( session, definition )
See WebGUI::Workflow::Activity::defintion() for details.
=cut
sub definition {
my $class = shift;
my $session = shift;
my $definition = shift;
my $i18n = WebGUI::International->new($session, 'Workflow_Activity_RemoveOldCarts');
push(@{$definition}, {
name=>$i18n->get('activityName'),
properties=> {
cartTimeout => {
fieldType=>'interval',
label=>$i18n->get('cart timeout'),
defaultValue=>48*3600,
hoverHelp=>$i18n->get('cart timeout help'),
},
}
});
return $class->SUPER::definition($session,$definition);
}
#-------------------------------------------------------------------
=head2 execute ( [ object ] )
See WebGUI::Workflow::Activity::execute() for details.
=cut
sub execute {
my ($self) = @_;
my $session = $self->session;
my $now = time();
my $finishTime = $now + $self->getTTL;
my $expired = 0;
my $cartIds = [];
my $limit = $now - $self->get('cartTimeout');
$session->log->warn("limit: $limit");
my $expiredCarts = $session->db->read('select cartId from cart where creationDate < '.$limit);
$expiredCarts->execute();
CART: while( my ($cartId) = $expiredCarts->array() ) {
my $cart = eval {
WebGUI::Shop::Cart->new($session, $cartId);
};
next CART if WebGUI::Error->caught;
$session->log->warn("cartId: $cartId");
$cart->delete; ##Delete will empty, then delete.
##Time check and set flag
if (time() > $finishTime) {
$expired = 1;
last CART;
}
}
##If timer expired, then store message and limit and release
if ($expired) {
return $self->WAITING(1);
}
return $self->COMPLETE;
}
1;

View file

@ -0,0 +1,25 @@
package WebGUI::i18n::English::Workflow_Activity_RemoveOldCarts;
use strict;
our $I18N = {
'cart timeout help' => {
message => q|How old should carts be before we delete them?|,
context => q|the hover help for the storage timeout field|,
lastUpdated => 0,
},
'cart timeout' => {
message => q|Cart Timeout|,
context => q|a label indicating how old carts should be before we delete them|,
lastUpdated => 0,
},
'activityName' => {
message => q|Remove Old Carts|,
context => q|The name of this workflow activity.|,
lastUpdated => 0,
},
};
1;

View file

@ -33,7 +33,7 @@ my $i18n = WebGUI::International->new($session, "Shop");
#----------------------------------------------------------------------------
# Tests
plan tests => 27; # Increment this number for each test you create
plan tests => 29; # Increment this number for each test you create
#----------------------------------------------------------------------------
# put your tests here
@ -52,6 +52,7 @@ my $cart = WebGUI::Shop::Cart->newBySession($session);
isa_ok($cart, "WebGUI::Shop::Cart");
isa_ok($cart->session, "WebGUI::Session");
ok($cart->get('creationDate'), 'creationDate set on cart creation');
my $message = $i18n->get('empty cart') . "\n";
like($cart->www_view, qr/There are no items currently in your cart./, 'Display empty cart message');
@ -73,9 +74,13 @@ is($item->get("quantity"), 3, "Should have 3 of these in the cart.");
is(scalar(@{$cart->getItems}), 1, "Should have 1 item type in cart regardless of quanity.");
$item->update({shippingAddressId => "XXXX"});
is($item->get("shippingAddressId"), "XXXX", "Can set values to the cart item properties.");
is($item->get("shippingAddressId"), "XXXX", "Can set shippingAddressId in the cart item properties.");
$item->update({shippingAddressId => undef});
my $now = time();
$cart->update({creationDate => $now});
is($cart->get('creationDate'), $now, 'update: set creationDate');
like($cart->getId, qr/[A-Za-z0-9\_\-]{22}/, "Id looks like a guid.");
is(ref($cart->get), "HASH", "Cart properties are a hash reference.");

View file

@ -0,0 +1,110 @@
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use FindBin;
use strict;
use lib "$FindBin::Bin/../../lib";
use WebGUI::Test;
use WebGUI::Session;
use WebGUI::Utility;
use WebGUI::Workflow::Activity::RemoveOldCarts;
use WebGUI::Shop::Cart;
use Test::More;
use Test::Deep;
plan tests => 6; # increment this value for each test you create
my $session = WebGUI::Test->session;
my $root = WebGUI::Asset->getRoot($session);
my $donation = $root->addChild({
className => 'WebGUI::Asset::Sku::Donation',
title => 'test donation',
});
my $tag = WebGUI::VersionTag->getWorking($session);
$tag->commit;
my $cart1 = WebGUI::Shop::Cart->create($session);
my $session2 = WebGUI::Session->open(WebGUI::Test->root, WebGUI::Test->file);
my $cart2 = WebGUI::Shop::Cart->create($session2);
$cart2->update({creationDate => time()-10000});
my @cartIds = $session->db->buildArray('select cartId from cart');
cmp_bag(
\@cartIds,
[ $cart1->getId, $cart2->getId ],
'Made two carts for testing'
);
$donation->applyOptions({ price => 1111});
my $item1 = $cart1->addItem($donation);
$donation->applyOptions({ price => 2222});
my $item2 = $cart2->addItem($donation);
my @itemIds = $session->db->buildArray('select itemId from cartItem');
cmp_bag(
\@itemIds,
[ $item1->getId, $item2->getId ],
'Made two items for testing'
);
my $workflow = WebGUI::Workflow->create($session,
{
enabled => 1,
objectType => 'None',
mode => 'realtime',
},
);
my $cartNuker = $workflow->addActivity('WebGUI::Workflow::Activity::RemoveOldCarts');
$cartNuker->set('cartTimeout', 3600);
my $instance1 = WebGUI::Workflow::Instance->create($session,
{
workflowId => $workflow->getId,
skipSpectreNotification => 1,
}
);
my $retVal;
$retVal = $instance1->run();
is($retVal, 'complete', 'cleanup: activity complete');
$retVal = $instance1->run();
is($retVal, 'done', 'cleanup: activity is done');
$instance1->delete;
@cartIds = $session->db->buildArray('select cartId from cart');
cmp_bag(
\@cartIds,
[ $cart1->getId, ],
'Deleted 1 cart, the correct one'
);
@itemIds = $session->db->buildArray('select itemId from cartItem');
cmp_bag(
\@itemIds,
[ $item1->getId, ],
'Deleted 1 item, the correct one'
);
END {
$instance1->delete('skipNotify');
$workflow->delete;
$cart1->delete;
$cart2->delete;
$session2->close;
$donation->purge;
$tag->rollback;
}