added item and sku caching to cart

ribbon discounts now work
checklist form control works more like you'd expect
added badge groups
This commit is contained in:
JT Smith 2008-04-02 22:46:40 +00:00
parent 6edce95ba4
commit 50a4b564e5
10 changed files with 401 additions and 40 deletions

View file

@ -116,6 +116,12 @@ sub upgradeEMS {
ribbonAssetId varchar(22) binary not null,
primary key (badgeId,ribbonAssetId)
)");
$db->write("create table EMSBadgeGroup (
badgeGroupId varchar(22) binary not null primary key,
emsAssetId varchar(22) binary not null,
name varchar(100),
badgeList text
)");
$db->write("create table EMSBadge (
assetId varchar(22) binary not null,
revisionDate bigint not null,
@ -132,7 +138,8 @@ sub upgradeEMS {
duration float not null default 1.0,
eventNumber int,
location varchar(100),
relatedBadges mediumtext,
relatedBadgeGroups mediumtext,
relatedRibbons mediumtext,
primary key (assetId, revisionDate)
)");
$db->write("create table EMSToken (
@ -144,6 +151,7 @@ sub upgradeEMS {
$db->write("create table EMSRibbon (
assetId varchar(22) binary not null,
revisionDate bigint not null,
percentageDiscount float not null default 10.0,
price float not null default 0.00,
primary key (assetId, revisionDate)
)");

View file

@ -2325,6 +2325,7 @@ sub www_add {
}
my %properties = (
%prototypeProperties,
parentId => $self->getId,
groupIdView => $self->get("groupIdView"),
groupIdEdit => $self->get("groupIdEdit"),
ownerUserId => $self->get("ownerUserId"),

View file

@ -63,6 +63,13 @@ sub definition {
label => $i18n->get("price"),
hoverHelp => $i18n->get("price help"),
},
percentageDiscount => {
tab => "shop",
fieldType => "float",
defaultValue => 10.0,
label => $i18n->get("percentage discount"),
hoverHelp => $i18n->get("percentage discount help"),
},
);
push(@{$definition}, {
assetName => $i18n->get('ems ribbon'),
@ -192,6 +199,21 @@ sub www_addToCart {
return $self->getParent->www_buildBadge($badgeId);
}
#-------------------------------------------------------------------
=head2 www_delete
Override to return to appropriate page.
=cut
sub www_delete {
my ($self) = @_;
$self->SUPER::www_delete;
return $self->getParent->www_buildBadge(undef,'ribbons');
}
#-------------------------------------------------------------------
=head2 www_edit ()

View file

@ -19,7 +19,6 @@ use Tie::IxHash;
use base 'WebGUI::Asset::Sku';
=head1 NAME
Package WebGUI::Asset::Sku::EMSTicket
@ -86,8 +85,8 @@ sub definition {
},
eventNumber => {
tab => "properties",
fieldType => "integer",
defaultValue => $session->db->quickScalar("select max(eventNumber)+1 from EMSTicket"),
fieldType => "integer",
customDrawMethod=> 'drawEventNumberField',
label => $i18n->get("event number"),
hoverHelp => $i18n->get("event number help"),
},
@ -107,19 +106,25 @@ sub definition {
hoverHelp => $i18n->get("duration help"),
},
location => {
fieldType => "combo",
tab => "properties",
fieldType => "combo",
options => $session->db->buildHashRef("select distinct(location) from EMSTicket order by location"),
customDrawMethod=> 'drawLocationField',
label => $i18n->get("location"),
hoverHelp => $i18n->get("location help"),
},
relatedBadges => {
relatedBadgeGroups => {
tab => "properties",
fieldType => "checkList",
options => {},
defaultValue => undef,
label => $i18n->get("related badges"),
hoverHelp => $i18n->get("related badges help"),
fieldType => "checkList",
customDrawMethod=> 'drawRelatedBadgeGroupsField',
label => $i18n->get("related badge groups"),
hoverHelp => $i18n->get("related badge groups help"),
},
relatedRibbons => {
tab => "properties",
fieldType => "checkList",
customDrawMethod=> 'drawRelatedRibbonsField',
label => $i18n->get("related ribbons"),
hoverHelp => $i18n->get("related ribbons help"),
},
);
push(@{$definition}, {
@ -133,6 +138,83 @@ sub definition {
return $class->SUPER::definition($session, $definition);
}
#-------------------------------------------------------------------
=head2 drawEventNumberField ()
Draws the field for the eventNumber property.
=cut
sub drawEventNumberField {
my ($self, $params) = @_;
my $default = $self->session->db->quickScalar("select max(eventNumber)+1 from EMSTicket left join asset using (assetId)
where parentId=?",[$self->get('parentId')]);
return WebGUI::Form::integer($self->session, {
name => $params->{name},
value => $self->get($params->{name}),
defaultValue => $default,
});
}
#-------------------------------------------------------------------
=head2 drawLocationField ()
Draws the field for the location property.
=cut
sub drawLocationField {
my ($self, $params) = @_;
my $options = $self->session->db->buildHashRef("select distinct(location) from EMSTicket left join asset using (assetId)
where parentId=? order by location",[$self->get('parentId')]);
return WebGUI::Form::combo($self->session, {
name => $params->{name},
value => $self->get($params->{name}),
options => $options,
});
}
#-------------------------------------------------------------------
=head2 drawRelatedBadgeGroupsField ()
Draws the field for the relatedBadgeGroups property.
=cut
sub drawRelatedBadgeGroupsField {
my ($self, $params) = @_;
return WebGUI::Form::checkList($self->session, {
name => $params->{name},
value => $self->get($params->{name}),
vertical => 1,
options => $self->getParent->getBadgeGroups,
});
}
#-------------------------------------------------------------------
=head2 drawRelatedRibbonsField ()
Draws the field for the relatedRibbons property.
=cut
sub drawRelatedRibbonsField {
my ($self, $params) = @_;
my %ribbons = ();
foreach my $ribbon (@{$self->getParent->getRibbons}) {
$ribbons{$ribbon->getId} = $ribbon->getTitle;
}
return WebGUI::Form::checkList($self->session, {
name => $params->{name},
value => $self->get($params->{name}),
vertical => 1,
options => \%ribbons,
});
}
#-------------------------------------------------------------------
@ -164,13 +246,20 @@ sub getMaxAllowedInCart {
=head2 getPrice
Returns the value of the price field
Returns the value of the price field, after applying ribbon discounts.
=cut
sub getPrice {
my $self = shift;
return $self->get("price");
my @ribbonIds = split("\n", $self->get('relatedRibbons'));
my $price = $self->get("price");
foreach my $item (@{$self->getCart->getItemsByAssetId(\@ribbonIds)}) {
my $ribbon = $item->getSku;
$price -= ($price * $ribbon->get('percentageDiscount') / 100);
last;
}
return $price;
}
#-------------------------------------------------------------------
@ -296,6 +385,21 @@ sub www_addToCart {
return $self->getParent->www_buildBadge($badgeId);
}
#-------------------------------------------------------------------
=head2 www_delete
Override to return to appropriate page.
=cut
sub www_delete {
my ($self) = @_;
$self->SUPER::www_delete;
return $self->getParent->www_buildBadge(undef,'tickets');
}
#-------------------------------------------------------------------
=head2 www_edit ()

View file

@ -189,6 +189,21 @@ sub www_addToCart {
return $self->getParent->www_buildBadge($badgeId);
}
#-------------------------------------------------------------------
=head2 www_delete
Override to return to appropriate page.
=cut
sub www_delete {
my ($self) = @_;
$self->SUPER::www_delete;
return $self->getParent->www_buildBadge(undef,'tokens');
}
#-------------------------------------------------------------------
=head2 www_edit ()

View file

@ -109,6 +109,71 @@ sub definition {
#-------------------------------------------------------------------
=head2 getBadges ()
Returns an array reference of badge objects.
=cut
sub getBadges {
my $self = shift;
return $self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSBadge']});
}
#-------------------------------------------------------------------
=head2 getBadgeGroups ()
Returns a hash reference of id,name pairs of badge groups.
=cut
sub getBadgeGroups {
my $self = shift;
return $self->session->db->buildHashRef("select badgeGroupId,name from EMSBadgeGroup where emsAssetId=?",[$self->getId]);
}
#-------------------------------------------------------------------
=head2 getRibbons ()
Returns an array reference of ribbon objects.
=cut
sub getRibbons {
my $self = shift;
return $self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSRibbon']});
}
#-------------------------------------------------------------------
=head2 getTickets ()
Returns an array reference of ticket objects.
=cut
sub getTickets {
my $self = shift;
return $self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSTicket']});
}
#-------------------------------------------------------------------
=head2 getTokens ()
Returns an array reference of badge objects.
=cut
sub getTokens {
my $self = shift;
return $self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSToken']});
}
#-------------------------------------------------------------------
=head2 prepareView ( )
See WebGUI::Asset::prepareView() for details.
@ -181,9 +246,12 @@ sub view {
my $output = q|
<div class=" yui-skin-sam">
<p><a href="|.$self->getUrl('func=add;class=WebGUI::Asset::Sku::EMSBadge').q|">Add a badge</a>
<p>
<a href="|.$self->getUrl('func=add;class=WebGUI::Asset::Sku::EMSBadge').q|">Add a badge</a>
&bull; <a href="|.$self->getUrl('func=buildBadge').q|">View Events</a>
&bull; <a href="|.$self->getUrl('shop=cart').q|">View Cart</a></p>
&bull; <a href="|.$self->getUrl('shop=cart').q|">View Cart</a>
&bull; <a href="|.$self->getUrl('func=manageBadgeGroups').q|">Badge Groups</a>
</p>
<p>|.$self->get('badgeInstructions').q|</p>
<div id="emsBadgePaging"></div>
<div id="emsBadgeList"></div>
@ -394,7 +462,6 @@ sub www_buildBadge {
});
}
$var{otherBadgesInCart} = \@otherBadges;
#return JSON->new->pretty->encode(\@otherBadges);
# render
return $self->processStyle($self->processTemplate(\%var,$self->get('badgeBuilderTemplateId')));
@ -410,6 +477,8 @@ Deletes a badge group.
sub www_deleteBadgeGroup {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->canEdit;
$self->session->db->deleteRow("EMSBadgeGroup","badgeGroupId",$self->session->form->get("badgeGroupId"));
return $self->www_manageBadgeGroups;
}
@ -424,29 +493,33 @@ Displays an edit screen for a badge group.
sub www_editBadgeGroup {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->canEdit;
my ($form, $db) = $self->session->quick(qw(form db));
my $f = WebGUI::HTMLForm->new($self->session, action=>$self->getUrl);
my $badgeGroup = $db->getRow("EMSBadgeGroup","badgeGroupId",$form->get('badgeGroupId'));
$badgeGroup->{badgeList} = ($badgeGroup->{badgeList} ne "") ? JSON::decode_json($badgeGroup->{badgeList}) : [];
my $i18n = WebGUI::International->new($self->session, "Asset_EventManagementSystem");
$f->hidden(name=>'func', value=>'editBadgeGroupSave');
$f->hidden(name=>'badgeGroupId', value=>$form->get('badgeGroupId'));
$f->text(
name => 'name',
value => $badgeGroup->{name},
label =>,
hoverHelp =>,
label => $i18n->get('badge group name'),
hoverHelp => $i18n->get('badge group name help'),
);
$f->checkList(
name => 'badgeList',
value => JSON::decode_json($badgeGroup->{badgeList}),
value => $badgeGroup->{badgeList},
options => $db->buildHashRef("select asset.assetId,assetData.title from asset left join assetData
using (assetId) where asset.parentId=? and assetData.revisionDate=
(SELECT max(revisionDate) from assetData where assetData.assetId=asset.assetId)",
[$self->getId]),
label => ,
hoverHelp =>,
);
return $self->processStyle($f->print);
(SELECT max(revisionDate) from assetData where assetData.assetId=asset.assetId)
and asset.className='WebGUI::Asset::Sku::EMSBadge'", [$self->getId]),
vertical => 1,
label => $i18n->get('badge list'),
hoverHelp => $i18n->get('badge list help'),
);
$f->submit;
return $self->processStyle('<h1>'.$i18n->get('badge groups').'</h1>'.$f->print);
}
@ -460,6 +533,16 @@ Saves a badge group.
sub www_editBadgeGroupSave {
my $self = shift;
return $self->session->privilege->insufficient() unless $self->canEdit;
my $form = $self->session->form;
my $id = $form->get("badgeGroupId") || "new";
my @badgeList = $form->get("badgeList",'checkList');
$self->session->db->setRow("EMSBadgeGroup","badgeGroupId",{
badgeGroupId => $id,
emsAssetId => $self->getId,
name => $form->get('name'),
badgeList => JSON::encode_json(\@badgeList),
});
return $self->www_manageBadgeGroups;
}
@ -478,7 +561,7 @@ sub www_getBadgesAsJson {
return $session->privilege->insufficient() unless $self->canView;
my ($db, $form) = $session->quick(qw(db form));
my %results = ();
foreach my $badge (@{$self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSBadge']})}) {
foreach my $badge (@{$self->getBadges}) {
push(@{$results{records}}, {
title => $badge->getTitle,
description => $badge->get('description'),
@ -643,7 +726,7 @@ sub www_getRibbonsAsJson {
return $session->privilege->insufficient() unless $self->canView;
my ($db, $form) = $session->quick(qw(db form));
my %results = ();
foreach my $ribbon (@{$self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSRibbon']})}) {
foreach my $ribbon (@{$self->getRibbons}) {
push(@{$results{records}}, {
title => $ribbon->getTitle,
description => $ribbon->get('description'),
@ -754,7 +837,7 @@ sub www_getTokensAsJson {
return $session->privilege->insufficient() unless $self->canView;
my ($db, $form) = $session->quick(qw(db form));
my %results = ();
foreach my $token (@{$self->getLineage(['children'],{returnObjects=>1, includeOnlyClasses=>['WebGUI::Asset::Sku::EMSToken']})}) {
foreach my $token (@{$self->getTokens}) {
push(@{$results{records}}, {
title => $token->getTitle,
description => $token->get('description'),
@ -796,6 +879,22 @@ Displays a list of badge groups.
sub www_manageBadgeGroups {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless $self->canView;
my $i18n = WebGUI::International->new($session, 'Asset_EventManagementSystem');
my $output = '<h1>'.$i18n->get('badge groups')
.q|</h1><p><a href="|.$self->getUrl("func=editBadgeGroup").q|">|.$i18n->get('add a badge group').q|</a>
&bull; <a href="|.$self->getUrl.q|">|.$i18n->get('view badges').q|</a>
&bull; <a href="|.$self->getUrl("func=buildBadge").q|">|.$i18n->get('view tickets').q|</a>
</p>|;
my $groups = $session->db->read("select badgeGroupId,name from EMSBadgeGroup where emsAssetId=?",[$self->getId]);
my $badgeGroups = $self->getBadgeGroups;
foreach my $id (keys %{$badgeGroups}) {
$output .= q|<div>[<a href="|.$self->getUrl("func=deleteBadgeGroup;badgeGroupId=".$id).q|">|.$i18n->get('delete').q|</a>
/ <a href="|.$self->getUrl("func=editBadgeGroup;badgeGroupId=".$id).q|">|.$i18n->get('edit').q|</a>]
|.$badgeGroups->{$id}.q|</div>|;
}
return $self->processStyle($output);
}
#-------------------------------------------------------------------

View file

@ -134,7 +134,7 @@ sub toHtml {
tie my %options, 'Tie::IxHash', $self->orderedHash();
foreach my $key (keys %options) {
$i++;
my $checked = (grep { $_ eq $key } @{ $self->get('value') })
my $checked = (grep { $_ eq $key } @{ $self->correctValues($self->get('value')) })
? 1
: 0
;

View file

@ -37,6 +37,7 @@ These subroutines are available from this package:
readonly session => my %session;
private properties => my %properties;
private error => my %error;
private itemCache => my %itemCache;
#-------------------------------------------------------------------
@ -114,6 +115,7 @@ sub delete {
$self->empty;
$self->session->db->write("delete from cart where cartId=?",[$self->getId]);
undef $self;
%itemCache{ref $self} = {};
return undef;
}
@ -129,7 +131,8 @@ sub empty {
my ($self) = @_;
foreach my $item (@{$self->getItems}) {
$item->remove;
}
}
%itemCache{ref $self} = {};
}
#-------------------------------------------------------------------
@ -238,7 +241,13 @@ sub getItem {
unless (defined $itemId && $itemId =~ m/^[A-Za-z0-9_-]{22}$/) {
WebGUI::Error::InvalidParam->throw(error=>"Need an itemId.");
}
return WebGUI::Shop::CartItem->new($self, $itemId);
my $id = ref $self;
if (exists $itemCache{$id}{$itemId}) {
return $itemCache{$id}{$itemId};
}
my $item = WebGUI::Shop::CartItem->new($self, $itemId);
$itemCache{$id}{$itemId} = $item;
return $item;
}
#-------------------------------------------------------------------
@ -261,6 +270,28 @@ sub getItems {
#-------------------------------------------------------------------
=head2 getItemsByAssetId ( assetIds )
Returns an array reference of WebGUI::Asset::Sku objects that have a specific asset id that are in the cart.
=head3 assetIds
An array reference of assetIds to look for.
=cut
sub getItemsByAssetId {
my ($self, $assetIds) = @_;
my @itemsObjects = ();
my $items = $self->session->db->read("select itemId from cartItem where cartId=? and assetId in (".$self->session->db->quoteAndJoin($assetIds).")",[$self->getId]);
while (my ($itemId) = $items->array) {
push(@itemsObjects, $self->getItem($itemId));
}
return \@itemsObjects;
}
#-------------------------------------------------------------------
=head2 getShipper ()
Returns the WebGUI::Shop::ShipDriver object that is attached to this cart for shipping.
@ -461,6 +492,7 @@ Remove an item from the cart and then display the cart again.
sub www_removeItem {
my $self = shift;
my $item = $self->getItem($self->session->form->get("itemId"))->remove;
delete $itemCache{ref $self}{$item->getId};
return $self->www_view;
}

View file

@ -28,7 +28,7 @@ These subroutines are available from this package:
readonly cart => my %cart;
private properties => my %properties;
private skuCache => my %skuCache;
#-------------------------------------------------------------------
@ -174,7 +174,15 @@ Returns an instanciated WebGUI::Asset::Sku object for this cart item.
sub getSku {
my ($self) = @_;
my $asset = WebGUI::Asset->newByDynamicClass($self->cart->session, $self->get("assetId"));
my $id = ref $self;
my $asset = '';
if (exists $skuCache{$id}{$self->get("assetId")}) {
$asset = $skuCache{$id}{$self->get("assetId")};
}
else {
$asset = WebGUI::Asset->newByDynamicClass($self->cart->session, $self->get("assetId"));
$skuCache{$id}{$self->get("assetId")} = $asset;
}
$asset->applyOptions($self->get("options"));
return $asset;
}

View file

@ -2,9 +2,57 @@ package WebGUI::i18n::English::Asset_EventManagementSystem;
use strict;
our $I18N = {
'percentage discount' => {
message => q|Percentage Discount|,
lastUpdated => 0,
context => q|a ribbon property label|,
},
'percentage discount help' => {
message => q|What percentage discount will be applied to the tickets if the user purchases this ribbon?|,
lastUpdated => 0,
context => q|help for a ribbon property label|,
},
'badge group name' => {
message => q|Badge Group Name|,
lastUpdated => 0,
context => q|a badge group property label|,
},
'badge group name help' => {
message => q|Enter a name to group these badges under.|,
lastUpdated => 0,
context => q|help for a badge group property label|,
},
'badge list' => {
message => q|Badge List|,
lastUpdated => 0,
context => q|a badge group property label|,
},
'badge list help' => {
message => q|Select the badges that belong to this group.|,
lastUpdated => 0,
context => q|help for a badge group property label|,
},
'badge groups' => {
message => q|Badge Groups|,
lastUpdated => 0,
context => q|a header label|,
},
'hours' => {
message => q|Hours|,
lastUpdated => 0,
context => q|subtext for the duration form field|,
},
'add a badge group' => {
message => q|Add A Badge Group|,
lastUpdated => 0,
context => q|a link label|,
},
@ -14,6 +62,18 @@ our $I18N = {
context => q|a link label|,
},
'view tickets' => {
message => q|View Tickets|,
lastUpdated => 0,
context => q|a link label|,
},
'view badges' => {
message => q|View Badges|,
lastUpdated => 0,
context => q|a link label|,
},
'buy badge' => {
message => q|Buy A Badge|,
lastUpdated => 0,
@ -296,16 +356,28 @@ our $I18N = {
context => q|a button on the add badge to cart screen|,
},
'related badges' => {
message => q|Related Badges|,
'related badge groups' => {
message => q|Related Badge Groups|,
lastUpdated => 0,
context => q|a property label|,
context => q|a ticket property label|,
},
'related badges help' => {
message => q|Check the badges that can act as a prerequisite to being able to attend this event.|,
'related badge groups help' => {
message => q|Check the badge groups that can act as a prerequisite to being able to attend this event. If none are checked, then any badge will do.|,
lastUpdated => 0,
context => q|help for a property label|,
context => q|help for a ticket property label|,
},
'related ribbons' => {
message => q|Related Ribbons|,
lastUpdated => 0,
context => q|a ribbon ticket label|,
},
'related ribbons help' => {
message => q|Check the ribbons that can provide a discount for this ticket.|,
lastUpdated => 0,
context => q|help for a ticket property label|,
},
'time zone' => {