added in-store credit

added refund mechanism
modified ems to use refund mechanism
This commit is contained in:
JT Smith 2008-04-20 01:12:25 +00:00
parent 9d99c7e71d
commit 8d03655bdb
14 changed files with 441 additions and 43 deletions

View file

@ -23,7 +23,7 @@ my $quiet; # this line required
my $session = start(); # this line required my $session = start(); # this line required
# upgrade functions go here # upgrade functions go here
adddingInStoreCredit($session);
insertCommerceTaxTable($session); insertCommerceTaxTable($session);
migrateOldTaxTable($session); migrateOldTaxTable($session);
insertCommerceShipDriverTable($session); insertCommerceShipDriverTable($session);
@ -42,6 +42,21 @@ mergeProductsWithCommerce($session);
finish($session); # this line required finish($session); # this line required
#-------------------------------------------------
sub addingInStoreCredit {
my $session = shift;
print "\tAdding refunds and in-store credit.\n" unless ($quiet);
$session->db->write("create table shopCredit (
creditId varchar(22) binary not null primary key,
userId varchar(22) binary not null,
amount float not null default 0.00,
comment text,
dateOfAdjustment datetime,
index userId (userId)
)");
}
#------------------------------------------------- #-------------------------------------------------
sub upgradeEMS { sub upgradeEMS {
my $session = shift; my $session = shift;
@ -105,12 +120,14 @@ sub upgradeEMS {
notes mediumtext, notes mediumtext,
purchaseComplete boolean, purchaseComplete boolean,
hasCheckedIn boolean, hasCheckedIn boolean,
transactionItemId varchar(22) binary,
index badgeAssetId_purchaseComplete (badgeAssetId,purchaseComplete) index badgeAssetId_purchaseComplete (badgeAssetId,purchaseComplete)
)"); )");
$db->write("create table EMSRegistrantTicket ( $db->write("create table EMSRegistrantTicket (
badgeId varchar(22) binary not null, badgeId varchar(22) binary not null,
ticketAssetId varchar(22) binary not null, ticketAssetId varchar(22) binary not null,
purchaseComplete boolean, purchaseComplete boolean,
transactionItemId varchar(22) binary,
primary key (badgeId, ticketAssetId), primary key (badgeId, ticketAssetId),
index ticketAssetId_purchaseComplete (ticketAssetId,purchaseComplete) index ticketAssetId_purchaseComplete (ticketAssetId,purchaseComplete)
)"); )");
@ -118,11 +135,13 @@ sub upgradeEMS {
badgeId varchar(22) binary not null, badgeId varchar(22) binary not null,
tokenAssetId varchar(22) binary not null, tokenAssetId varchar(22) binary not null,
quantity int, quantity int,
transactionItemIds text binary,
primary key (badgeId,tokenAssetId) primary key (badgeId,tokenAssetId)
)"); )");
$db->write("create table EMSRegistrantRibbon ( $db->write("create table EMSRegistrantRibbon (
badgeId varchar(22) binary not null, badgeId varchar(22) binary not null,
ribbonAssetId varchar(22) binary not null, ribbonAssetId varchar(22) binary not null,
transactionItemId varchar(22) binary,
primary key (badgeId,ribbonAssetId) primary key (badgeId,ribbonAssetId)
)"); )");
$db->write("create table EMSBadgeGroup ( $db->write("create table EMSBadgeGroup (

View file

@ -384,7 +384,7 @@ tasks to be performed. It should be overriden by subclasses that need to do spec
=head3 item =head3 item
Receives a reference to the WebGUI::Shop::CartItem so it can determine things like itemId and quantity if it needs them for book keeping purposes. Receives a reference to the WebGUI::Shop::TransactionItem so it can determine things like itemId and quantity if it needs them for book keeping purposes.
=cut =cut
@ -395,6 +395,23 @@ sub onCompletePurchase {
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 onRefund ( item )
Called by a transaction upon issuing a refund for this item. Extend to do extra book keeping or restocking.
=head3 item
The WebGUI::Shop::TransactionItem being refunded.
=cut
sub onRefund {
my ($self, $item) = @_;
return undef;
}
#-------------------------------------------------------------------
=head2 onRemoveFromCart ( item ) =head2 onRemoveFromCart ( item )
Called by the cart just B<before> the item is removed from the cart. This allows for cleanup. Should be overridden by subclasses for inventory control or other housekeeping. Called by the cart just B<before> the item is removed from the cart. This allows for cleanup. Should be overridden by subclasses for inventory control or other housekeeping.

View file

@ -193,12 +193,67 @@ sub onCompletePurchase {
my $badgeInfo = $self->getOptions; my $badgeInfo = $self->getOptions;
$badgeInfo->{purchaseComplete} = 1; $badgeInfo->{purchaseComplete} = 1;
$badgeInfo->{userId} = $self->session->user->userId; # they have to be logged in at this point $badgeInfo->{userId} = $self->session->user->userId; # they have to be logged in at this point
$badgeInfo->{transactionItemId} = $item->getId;
$self->session->db->setRow("EMSRegistrant","badgeId", $badgeInfo); $self->session->db->setRow("EMSRegistrant","badgeId", $badgeInfo);
return undef; return undef;
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 onRefund ( item)
Destroys the badge so that it can be resold.
=cut
sub onRefund {
my ($self, $item) = @_;
my $db = $self->session->db;
my $badgeId = $self->getOptions->{badgeId};
# refund any purchased tickets related to the badge
foreach my $id ($db->buildArray("select transactionItemId from EMSRegistrantTicket where badgeId=?",[$badgeId])) {
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction($self->session, $id);
if (defined $item) {
$item->issueCredit;
}
}
# refund any purchased ribbons related to the badge
foreach my $id ($db->buildArray("select transactionItemId from EMSRegistrantRibbon where badgeId=?",[$badgeId])) {
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction($self->session, $id);
if (defined $item) {
$item->issueCredit;
}
}
# refund any purchased tokens related to this badge
foreach my $ids ($db->buildArray("select transactionItemIds from EMSRegistrantToken where badgeId=?",[$badgeId])) {
foreach my $id (split(',', $ids)) {
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction($self->session, $id);
if (defined $item) {
$item->issueCredit;
}
}
}
# get rid of any items in the cart related to this badge
foreach my $cartitem (@{$self->getCart->getItems()}) {
my $sku = $cartitem->getSku;
if (isIn((ref $sku), qw(WebGUI::Asset::Sku::EMSTicket WebGUI::Asset::Sku::EMSRibbon WebGUI::Asset::Sku::EMSToken))) {
if ($sku->getOptions->{badgeId} eq $badgeId) {
$cartitem->remove;
}
}
}
# get rid ofthe badge itself
$db->write("delete from EMSRegistrant where transactionItemId=?",[$item->getId]);
return undef;
}
#-------------------------------------------------------------------
=head2 onRemoveFromCart ( item ) =head2 onRemoveFromCart ( item )
Destroys badge. Destroys badge.
@ -209,8 +264,9 @@ sub onRemoveFromCart {
my ($self, $item) = @_; my ($self, $item) = @_;
my $badgeId = $self->getOptions->{badgeId}; my $badgeId = $self->getOptions->{badgeId};
foreach my $cartitem (@{$item->cart->getItems()}) { foreach my $cartitem (@{$item->cart->getItems()}) {
if (isIn((ref $cartitem), qw(WebGUI::Asset::Sku::EMSTicket WebGUI::Asset::Sku::EMSRibbon WebGUI::Asset::Sku::EMSToken))) { my $sku = $cartitem->getSku;
if ($cartitem->getSku->getOptions->{badgeId} eq $badgeId) { if (isIn((ref $sku), qw(WebGUI::Asset::Sku::EMSTicket WebGUI::Asset::Sku::EMSRibbon WebGUI::Asset::Sku::EMSToken))) {
if ($sku->getOptions->{badgeId} eq $badgeId) {
$cartitem->remove; $cartitem->remove;
} }
} }
@ -255,7 +311,7 @@ sub view {
my $book = WebGUI::HTMLForm->new($self->session, action=>$self->getUrl); my $book = WebGUI::HTMLForm->new($self->session, action=>$self->getUrl);
$book->hidden(name=>"shop", value=>"address"); $book->hidden(name=>"shop", value=>"address");
$book->hidden(name=>"method", value=>"view"); $book->hidden(name=>"method", value=>"view");
$book->hidden(name=>"callback", value=>JSON::to_json({ $book->hidden(name=>"callback", value=>JSON->new->utf8->encode({
url => $self->getUrl, url => $self->getUrl,
})); }));
$book->submit(value=>$i18n->get("populate from address book")); $book->submit(value=>$i18n->get("populate from address book"));

View file

@ -132,8 +132,22 @@ Does bookkeeping on EMSRegistrationRibbon table.
sub onCompletePurchase { sub onCompletePurchase {
my ($self, $item) = @_; my ($self, $item) = @_;
$self->session->db->write("insert into EMSRegistrantRibbon (ribbonAssetId, badgeId) values (?,?)", $self->session->db->write("insert into EMSRegistrantRibbon (transactionItemId, ribbonAssetId, badgeId) values (?,?,?)",
[$self->getId, $self->getOptions->{badgeId}]); [$item->getId, $self->getId, $self->getOptions->{badgeId}]);
return undef;
}
#-------------------------------------------------------------------
=head2 onRefund ( item)
Destroys the ribbon so that it can be resold.
=cut
sub onRefund {
my ($self, $item) = @_;
$self->session->db->write("delete from EMSRegistrantRibbon where transactionItemId=?",[$item->getId]);
return undef; return undef;
} }

View file

@ -251,7 +251,7 @@ Extended to support event metadata.
sub getEditForm { sub getEditForm {
my $self = shift; my $self = shift;
my $form = $self->SUPER::getEditForm(@_); my $form = $self->SUPER::getEditForm(@_);
my $metadata = JSON->new->decode($self->get("eventMetaData") || '{}'); my $metadata = JSON->new->utf8->decode($self->get("eventMetaData") || '{}');
foreach my $field (@{$self->getParent->getEventMetaFields}) { foreach my $field (@{$self->getParent->getEventMetaFields}) {
$form->getTab("meta")->DynamicField( $form->getTab("meta")->DynamicField(
name => "eventmeta ".$field->{label}, name => "eventmeta ".$field->{label},
@ -293,7 +293,7 @@ sub getPrice {
my $badgeId = $self->getOptions->{badgeId}; my $badgeId = $self->getOptions->{badgeId};
my $ribbonId = $self->session->db->quickScalar("select ribbonAssetId from EMSRegistrantRibbon where badgeId=? limit 1",[$badgeId]); my $ribbonId = $self->session->db->quickScalar("select ribbonAssetId from EMSRegistrantRibbon where badgeId=? limit 1",[$badgeId]);
if (defined $ribbonId) { if (defined $ribbonId) {
my $ribbon = WebGUI::Asset->new($self->session,$ribbonId,'WebGUI::Asset::Sku::Ribbon'); my $ribbon = WebGUI::Asset->new($self->session,$ribbonId,'WebGUI::Asset::Sku::EMSRibbon');
$discount = $ribbon->get('percentageDiscount'); $discount = $ribbon->get('percentageDiscount');
} }
else { else {
@ -350,8 +350,22 @@ Marks the ticket as purchased.
sub onCompletePurchase { sub onCompletePurchase {
my ($self, $item) = @_; my ($self, $item) = @_;
$self->session->db->write("update EMSRegistrantTicket set purchaseComplete=1 where ticketAssetId=? and badgeId=?", $self->session->db->write("update EMSRegistrantTicket set purchaseComplete=1, transactionItemId=? where ticketAssetId=? and badgeId=?",
[$self->getId, $self->getOptions->{badgeId}]); [$item->getId, $self->getId, $self->getOptions->{badgeId}]);
return undef;
}
#-------------------------------------------------------------------
=head2 onRefund ( item)
Destroys the ticket so that it can be resold.
=cut
sub onRefund {
my ($self, $item) = @_;
$self->session->db->write("delete from EMSRegistrantTicket where transactionItemId=?",[$item->getId]);
return undef; return undef;
} }
@ -386,7 +400,7 @@ sub processPropertiesFromFormPost {
$metadata{$field->{label}} = $form->process('eventmeta '.$field->{label}, $field->{dataType}, $metadata{$field->{label}} = $form->process('eventmeta '.$field->{label}, $field->{dataType},
{ defaultValue => $field->{defaultValues}, options => $field->{possibleValues}}); { defaultValue => $field->{defaultValues}, options => $field->{possibleValues}});
} }
$self->update({eventMetaData => JSON->new->encode(\%metadata)}); $self->update({eventMetaData => JSON->new->utf8->encode(\%metadata)});
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -115,13 +115,43 @@ sub onCompletePurchase {
my ($self, $item) = @_; my ($self, $item) = @_;
my $db = $self->session->db; my $db = $self->session->db;
my @params = ($self->getId, $self->getOptions->{badgeId}); my @params = ($self->getId, $self->getOptions->{badgeId});
my $currentQuantity = $db->quickScalar("select quantity from EMSRegistrantToken where tokenAssetId=? and badgeId=?",\@params); my ($currentQuantity, $currentItemIds) = $db->quickArray("select quantity, transactionItemids from EMSRegistrantToken where tokenAssetId=? and badgeId=?",\@params);
unshift @params, $item->get("quantity"); unshift @params, $item->get("quantity");
if (defined $currentQuantity) { if (defined $currentQuantity) {
$db->write("update EMSRegistrantToken set quantity=quantity+? where tokenAssetId=? and badgeId=?",\@params); unshift @params, join(",", $currentItemIds, $item->getId);
$db->write("update EMSRegistrantToken set transactionItemIds=?, quantity=quantity+? where tokenAssetId=? and badgeId=?",\@params);
} }
else { else {
$db->write("insert into EMSRegistrantToken (quantity, tokenAssetId, badgeId) values (?,?,?)",\@params); unshift @params, $item->getId;
$db->write("insert into EMSRegistrantToken (transactionItemIds, quantity, tokenAssetId, badgeId) values (?,?,?,?)",\@params);
}
return undef;
}
#-------------------------------------------------------------------
=head2 onRefund ( item)
Destroys the token so that it can be resold.
=cut
sub onRefund {
my ($self, $item) = @_;
my $db = $self->session->db;
my $token = $db->quickHashRef("select * from EMSRegistrantToken where transactionItemIds like ?",['%'.$item->getId.'%']);
my @itemIds = split ',', $token->{transactionItemIds};
for (my $i=0; $i<scalar @itemIds; $i++) {
if ($itemIds[$i] eq $item->getId) {
delete $itemIds[$i];
}
}
if (scalar @itemIds < 2) {
$db->write("delete from EMSRegistrantToken where badgeId=? and tokenAssetId=?",[$token->{badgeId}, $self->getId]);
}
else {
$db->write("update EMSRegistrantToken set quantity=?, transactionItemIds=? where badgeId=? and tokenAssetId=?",
[($token->{quantity} - $item->get('quantity')), join(',', @itemIds), $token->{badgeId}, $self->getId]);
} }
return undef; return undef;
} }

View file

@ -642,6 +642,7 @@ sub www_editRegistrantSave {
foreach my $field (qw(name address1 address2 address3 city state organization notes)) { foreach my $field (qw(name address1 address2 address3 city state organization notes)) {
$badgeInfo{$field} = $form->get($field, "text"); $badgeInfo{$field} = $form->get($field, "text");
} }
$badgeInfo{'userId'} = $form->get('userId', 'user');
$badgeInfo{'phoneNumber'} = $form->get('phoneNumber', 'phone'); $badgeInfo{'phoneNumber'} = $form->get('phoneNumber', 'phone');
$badgeInfo{'email'} = $form->get('email', 'email'); $badgeInfo{'email'} = $form->get('email', 'email');
$badgeInfo{'country'} = $form->get('country', 'country'); $badgeInfo{'country'} = $form->get('country', 'country');
@ -681,7 +682,7 @@ sub www_getBadgesAsJson {
$results{'sort'} = undef; $results{'sort'} = undef;
$results{'dir'} = "asc"; $results{'dir'} = "asc";
$session->http->setMimeType('text/json'); $session->http->setMimeType('text/json');
return JSON->new->encode(\%results); return JSON->new->utf8->encode(\%results);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -811,7 +812,7 @@ sub www_getRegistrantAsJson {
$badgeInfo->{ribbons} = \@ribbons; $badgeInfo->{ribbons} = \@ribbons;
# build json datasource # build json datasource
return JSON->new->encode($badgeInfo); return JSON->new->utf8->encode($badgeInfo);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -871,7 +872,7 @@ sub www_getRegistrantsAsJson {
# build json datasource # build json datasource
$session->http->setMimeType('text/json'); $session->http->setMimeType('text/json');
return JSON->new->encode(\%results); return JSON->new->utf8->encode(\%results);
} }
@ -905,7 +906,7 @@ sub www_getRibbonsAsJson {
$results{'sort'} = undef; $results{'sort'} = undef;
$results{'dir'} = "asc"; $results{'dir'} = "asc";
$session->http->setMimeType('text/json'); $session->http->setMimeType('text/json');
return JSON->new->encode(\%results); return JSON->new->utf8->encode(\%results);
} }
@ -1046,7 +1047,7 @@ sub www_getTicketsAsJson {
$results{'sort'} = undef; $results{'sort'} = undef;
$results{'dir'} = "asc"; $results{'dir'} = "asc";
$session->http->setMimeType('text/json'); $session->http->setMimeType('text/json');
return JSON->new->encode(\%results); return JSON->new->utf8->encode(\%results);
} }
@ -1080,7 +1081,7 @@ sub www_getTokensAsJson {
$results{'sort'} = undef; $results{'sort'} = undef;
$results{'dir'} = "asc"; $results{'dir'} = "asc";
$session->http->setMimeType('text/json'); $session->http->setMimeType('text/json');
return JSON->new->encode(\%results); return JSON->new->utf8->encode(\%results);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -1194,13 +1195,27 @@ sub www_manageRegistrant {
my $badgeId = $self->session->form->get('badgeId'); my $badgeId = $self->session->form->get('badgeId');
my $db = $session->db; my $db = $session->db;
my $i18n = WebGUI::International->new($session, "Asset_EventManagementSystem"); my $i18n = WebGUI::International->new($session, "Asset_EventManagementSystem");
my $registrant = $self->getRegistrant($badgeId);
# show lookup registrant if registrant requested doesn't exist
unless ($registrant->{badgeId} ne "") {
return $self->www_lookupRegistrant;
}
# build form # build form
my $registrant = $self->getRegistrant($badgeId); my $f = WebGUI::HTMLForm->new($session, action=>$self->getUrl, tableExtras=>'class="manageRegistrant"');
my $f = WebGUI::HTMLForm->new($session, action=>$self->getUrl);
$f->submit; $f->submit;
$f->hidden(name=>"func", value=>"editRegistrantSave"); $f->hidden(name=>"func", value=>"editRegistrantSave");
$f->hidden(name=>'badgeId', value=>$badgeId); $f->hidden(name=>'badgeId', value=>$badgeId);
$f->readOnly(
label => $i18n->get('badge number'),
value => $registrant->{badgeNumber},
);
$f->user(
name => 'userId',
label => $i18n->get('user'),
defaultValue => $registrant->{userId},
);
$f->text( $f->text(
name => 'name', name => 'name',
label => $i18n->get('name','Shop'), label => $i18n->get('name','Shop'),
@ -1270,7 +1285,7 @@ sub www_manageRegistrant {
&bull; <a href="|.$self->getUrl.q|">|.$i18n->get('buy badge').q|</a> &bull; <a href="|.$self->getUrl.q|">|.$i18n->get('buy badge').q|</a>
</div> </div>
<div id="bd"> <div id="bd">
<div class="yui-g"> <div class="yui-gc">
<div class="yui-u first"> <div class="yui-u first">
|.$f->print.q| |.$f->print.q|
</div> </div>
@ -1288,7 +1303,7 @@ sub www_manageRegistrant {
my $badge = WebGUI::Asset::Sku::EMSBadge->new($session, $registrant->{badgeAssetId}); my $badge = WebGUI::Asset::Sku::EMSBadge->new($session, $registrant->{badgeAssetId});
$output .= q|<p><b style="font-size: 150%; line-height: 150%;">|.$badge->getTitle.q|</b><br /> $output .= q|<p><b style="font-size: 150%; line-height: 150%;">|.$badge->getTitle.q|</b><br />
<a href="|.$self->getUrl('func=printBadge;badgeId='.$badgeId).q|" target="_blank">|.$i18n->get('print').q|</a> <a href="|.$self->getUrl('func=printBadge;badgeId='.$badgeId).q|" target="_blank">|.$i18n->get('print').q|</a>
&bull; <a href="">|.$i18n->get('refund').q|</a> &bull; <a href="|.$self->getUrl('func=refundItem;badgeId='.$badgeId.';transactionItemId='.$registrant->{transactionItemId}).q|">|.$i18n->get('refund').q|</a>
&bull; |; &bull; |;
if ($registrant->{hasCheckedIn}) { if ($registrant->{hasCheckedIn}) {
$output .= q|<a href="|.$self->getUrl('func=toggleRegistrantCheckedIn;badgeId='.$badgeId).q|">|.$i18n->get('mark as not checked in').q|</a>|; $output .= q|<a href="|.$self->getUrl('func=toggleRegistrantCheckedIn;badgeId='.$badgeId).q|">|.$i18n->get('mark as not checked in').q|</a>|;
@ -1301,30 +1316,31 @@ sub www_manageRegistrant {
</p><br />|; </p><br />|;
# ticket management # ticket management
my $existingTickets = $db->read("select ticketAssetId from EMSRegistrantTicket where badgeId=? and purchaseComplete=1",[$badgeId]); my $existingTickets = $db->read("select ticketAssetId, transactionItemId from EMSRegistrantTicket where badgeId=? and purchaseComplete=1",[$badgeId]);
while (my ($id) = $existingTickets->array) { while (my ($id, $itemId) = $existingTickets->array) {
my $ticket = WebGUI::Asset::Sku::EMSTicket->new($session, $id); my $ticket = WebGUI::Asset::Sku::EMSTicket->new($session, $id);
$output .= q|<p><b>|.$ticket->getTitle.q|</b><br /> $output .= q|<p><b>|.$ticket->getTitle.q|</b><br />
<a href="|.$self->getUrl('func=printTicket;badgeId='.$badgeId.';ticketAssetId='.$id).q|" target="_blank">|.$i18n->get('print').q|</a> <a href="|.$self->getUrl('func=printTicket;badgeId='.$badgeId.';ticketAssetId='.$id).q|" target="_blank">|.$i18n->get('print').q|</a>
&bull; <a href="">|.$i18n->get('refund').q|</a> &bull; <a href="|.$self->getUrl('func=refundItem;badgeId='.$badgeId.';transactionItemId='.$itemId).q|">|.$i18n->get('refund').q|</a>
</p><br />|; </p><br />|;
} }
# ribbon management # ribbon management
my $existingRibbons = $db->read("select ribbonAssetId from EMSRegistrantRibbon where badgeId=?",[$badgeId]); my $existingRibbons = $db->read("select ribbonAssetId, transactionItemId from EMSRegistrantRibbon where badgeId=?",[$badgeId]);
while (my ($id) = $existingRibbons->array) { while (my ($id, $itemId) = $existingRibbons->array) {
my $ribbon = WebGUI::Asset::Sku::EMSRibbon->new($session, $id); my $ribbon = WebGUI::Asset::Sku::EMSRibbon->new($session, $id);
$output .= q|<p><b>|.$ribbon->getTitle.q|</b><br /> $output .= q|<p><b>|.$ribbon->getTitle.q|</b><br />
<a href="">|.$i18n->get('refund').q|</a> <a href="|.$self->getUrl('func=refundItem;badgeId='.$badgeId.';transactionItemId='.$itemId).q|">|.$i18n->get('refund').q|</a>
</p><br />|; </p><br />|;
} }
# token management # token management
my $existingTokens = $db->read("select tokenAssetId,quantity from EMSRegistrantToken where badgeId=?",[$badgeId]); my $existingTokens = $db->read("select tokenAssetId,quantity,transactionItemIds from EMSRegistrantToken where badgeId=?",[$badgeId]);
while (my ($id, $quantity) = $existingTokens->array) { while (my ($id, $quantity, $itemIds) = $existingTokens->array) {
my $token = WebGUI::Asset::Sku::EMSToken->new($session, $id); my $token = WebGUI::Asset::Sku::EMSToken->new($session, $id);
my @itemIds = split(',', $itemIds);
$output .= q|<p><b>|.$token->getTitle.q|</b> (|.$quantity.q|)<br /> $output .= q|<p><b>|.$token->getTitle.q|</b> (|.$quantity.q|)<br />
<a href="">|.$i18n->get('refund').q|</a> <a href="|.$self->getUrl('func=refundItem;badgeId='.$badgeId.';transactionItemId='.join(';transactionItemId=', @itemIds)).q|">|.$i18n->get('refund').q|</a>
</p><br />|; </p><br />|;
} }
@ -1338,6 +1354,11 @@ sub www_manageRegistrant {
# render # render
$session->style->setLink($session->url->extras('/yui/build/reset-fonts-grids/reset-fonts-grids.css'), {rel=>"stylesheet", type=>"text/css"}); $session->style->setLink($session->url->extras('/yui/build/reset-fonts-grids/reset-fonts-grids.css'), {rel=>"stylesheet", type=>"text/css"});
$session->style->setRawHeadTags(q|
<style type="text/css">
.manageRegistrant tbody tr td { padding: 2px;}
</style>
|);
return $self->processStyle($output); return $self->processStyle($output);
} }
@ -1414,6 +1435,29 @@ sub www_printTicket {
} }
#-------------------------------------------------------------------
=head2 www_refundItem ()
Removes a ribbon, token, or ticket or badge that is attached to a registrant.
=cut
sub www_refundItem {
my $self = shift;
my $session = $self->session;
return $session->privilege->insufficient() unless $self->canView;
my @itemIds = $session->form->param("transactionItemId");
foreach my $id (@itemIds) {
my $item = WebGUI::Shop::TransactionItem->newByDynamicTransaction($session, $id);
if (defined $item) {
$item->issueCredit;
}
}
return $self->www_manageRegistrant();
}
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 www_removeItemFromBadge () =head2 www_removeItemFromBadge ()

View file

@ -434,7 +434,7 @@ sub www_view {
my $form = $session->form; my $form = $session->form;
my $callback = $form->get('callback'); my $callback = $form->get('callback');
$callback =~ s/'/"/g; $callback =~ s/'/"/g;
$callback = JSON::from_json($callback); $callback = JSON->new->utf8->decode($callback);
my $callbackForm = ''; my $callbackForm = '';
foreach my $param (@{$callback->{params}}) { foreach my $param (@{$callback->{params}}) {
$callbackForm .= WebGUI::Form::hidden($session, {name=>$param->{name}, value=>$param->{value}}); $callbackForm .= WebGUI::Form::hidden($session, {name=>$param->{name}, value=>$param->{value}});

View file

@ -374,14 +374,13 @@ sub new {
=head2 onCompletePurchase () =head2 onCompletePurchase ()
Calls onCompletePurchase() on all the items in the cart. Then deletes all the items in the cart without calling $item->remove() on them which would affect inventory levels. See also delete() and empty(). Deletes all the items in the cart without calling $item->remove() on them which would affect inventory levels. See also delete() and empty().
=cut =cut
sub onCompletePurchase { sub onCompletePurchase {
my $self = shift; my $self = shift;
foreach my $item (@{$self->getItems}) { foreach my $item (@{$self->getItems}) {
$item->getSku->onCompletePurchase($item);
$item->delete; $item->delete;
} }
$self->delete; $self->delete;

View file

@ -126,7 +126,7 @@ sub get {
return {}; return {};
} }
else { else {
return JSON::from_json($properties{id $self}{$name}); return JSON->new->utf8->decode($properties{id $self}{$name});
} }
} }
return $properties{id $self}{$name}; return $properties{id $self}{$name};
@ -313,7 +313,7 @@ sub update {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field}; $properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
} }
if (exists $newProperties->{options} && ref($newProperties->{options}) eq "HASH") { if (exists $newProperties->{options} && ref($newProperties->{options}) eq "HASH") {
$properties{$id}{options} = JSON::to_json($newProperties->{options}); $properties{$id}{options} = JSON->new->utf8->encode($newProperties->{options});
} }
$self->cart->session->db->setRow("cartItem","itemId",$properties{$id}); $self->cart->session->db->setRow("cartItem","itemId",$properties{$id});
} }

149
lib/WebGUI/Shop/Credit.pm Normal file
View file

@ -0,0 +1,149 @@
package WebGUI::Shop::Credit;
use strict;
use Class::InsideOut qw{ :std };
use WebGUI::Shop::Admin;
use WebGUI::Exception::Shop;
use WebGUI::International;
=head1 NAME
Package WebGUI::Shop::Credit
=head1 DESCRIPTION
Keeps track of what in-store credit is owed a customer. All refunds are issued as in-store credit.
=head1 SYNOPSIS
use WebGUI::Shop::Credit;
my $credit = WebGUI::Shop::Credit->new($session, $userId);
=head1 METHODS
These subroutines are available from this package:
=cut
readonly session => my %session;
readonly userId => my %userId;
#-------------------------------------------------------------------
=head2 adjust ( amount, [ comment ] )
Adjusts the amount of credit this user has by a specified amount.
=head3 amount
The amount to adjust the credit by. A positive number adds credit, and a negative number removes credit.
=head3 comment
The reason for this adjustment.
=cut
sub adjust {
my ($self, $amount, $comment) = @_;
$self->session->db->write("insert into shopCredit (creditId, userId, amount, comment, dateOfAdjustment) values (?,?,?,?,now())",
[$self->session->id->generate, $self->userId, $amount, $comment]);
}
#-------------------------------------------------------------------
=head2 getGeneralLedger ( session )
A class method. Returns a WebGUI::SQL::ResultSet containing the data from the shopCredit table for all users.
=head3 session
A reference to the current session.
=cut
sub getGeneralLedger {
my ($class, $session) = @_;
return $session->db->read("select * from shopCredit order by dateOfAdjustment");
}
#-------------------------------------------------------------------
=head2 getLedger ()
Returns a WebGUI::SQL::ResultSet containing the data from the shopCredit table for this user.
=cut
sub getLedger {
my $self = shift;
return $self->session->db->read("select * from shopCredit where userId=?",[$self->userId]);
}
#-------------------------------------------------------------------
=head2 getSum ()
Returns the amount of credit that is owed to this user.
=cut
sub getSum {
my $self = shift;
my $credit = $self->session->db->getScalar("select sum(amount) from shopCredit where userId=? order by dateOfAdjustment",[$self->userId]);
return sprintf("%.2f", $credit);
}
#-------------------------------------------------------------------
=head2 new ( session, userId )
Constructor.
=head3 session
A reference to the current session.
=head3 userId
A unique id for a user that you want to adjust the credit of.
=cut
sub new {
my ($class, $session, $userId) = @_;
unless (defined $session && $session->isa("WebGUI::Session")) {
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
}
unless (defined $userId) {
WebGUI::Error::InvalidParam->throw( param=>$userId, error=>"Need a userId.");
}
my $self = register $class;
my $id = id $self;
$session{ $id } = $session;
$userId{ $id } = $userId;
return $self;
}
#-------------------------------------------------------------------
=head2 session ()
Returns a reference to the current session.
=cut
#-------------------------------------------------------------------
=head2 userId ()
Returns a reference to the userId.
=cut
1;

View file

@ -11,6 +11,7 @@ use WebGUI::International;
use WebGUI::Paginator; use WebGUI::Paginator;
use WebGUI::Shop::Admin; use WebGUI::Shop::Admin;
use WebGUI::Shop::AddressBook; use WebGUI::Shop::AddressBook;
use WebGUI::Shop::Credit;
use WebGUI::Shop::TransactionItem; use WebGUI::Shop::TransactionItem;
=head1 NAME =head1 NAME
@ -69,7 +70,7 @@ sub addItem {
=head2 completePurchase ( transactionCode, statusCode, statusMessage ) =head2 completePurchase ( transactionCode, statusCode, statusMessage )
See also denyPurchase(). Completes a purchase by updating the transaction as a success, and clearing the cart of it's items. See also denyPurchase(). Completes a purchase by updating the transaction as a success, and calling onCompletePurchase on all the skus in the transaction.
=head3 transactionCode =head3 transactionCode
@ -87,6 +88,9 @@ The extended status message that came back from the payment gateway when trying
sub completePurchase { sub completePurchase {
my ($self, $transactionCode, $statusCode, $statusMessage) = @_; my ($self, $transactionCode, $statusCode, $statusMessage) = @_;
foreach my $item (@{$self->getItems}) {
$item->getSku->onCompletePurchase($item);
}
$self->update({ $self->update({
transactionCode => $transactionCode, transactionCode => $transactionCode,
isSuccessful => 1, isSuccessful => 1,
@ -437,7 +441,7 @@ sub www_getTransactionsAsJson {
$results{'sort'} = undef; $results{'sort'} = undef;
$results{'dir'} = "desc"; $results{'dir'} = "desc";
$session->http->setMimeType('text/json'); $session->http->setMimeType('text/json');
return JSON::to_json(\%results); return JSON->new->utf8->encode(\%results);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -5,6 +5,7 @@ use Class::InsideOut qw{ :std };
use JSON; use JSON;
use WebGUI::DateTime; use WebGUI::DateTime;
use WebGUI::Exception::Shop; use WebGUI::Exception::Shop;
use WebGUI::Shop::Transaction;
=head1 NAME =head1 NAME
@ -97,7 +98,7 @@ sub get {
return {}; return {};
} }
else { else {
return JSON::from_json($properties{id $self}{$name}); return JSON->new->utf8->decode($properties{id $self}{$name});
} }
} }
return $properties{id $self}{$name}; return $properties{id $self}{$name};
@ -135,6 +136,21 @@ sub getSku {
return $asset; return $asset;
} }
#-------------------------------------------------------------------
=head2 issueCredit ( )
Returns the money from this item to the user in the form of in-store credit.
=cut
sub issueCredit {
my $self = shift;
my $credit = WebGUI::Shop::Credit->new($self->transaction->session, $self->transaction->get('userId'));
$credit->adjust($self->get('price'), "Issued credit on sku ".$self->get('assetId')." for transaction item ".$self->getId." on transaction ".$self->transaction->getId);
$self->getSku->onRefund($self);
$self->update({shippingStatus=>'Cancelled'});
}
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -174,6 +190,36 @@ sub new {
return $self; return $self;
} }
#-------------------------------------------------------------------
=head2 newByDynamicTransaction ( session, itemId )
Constructor, but will dynamically find the approriate transaction and attach it to the item object.
=head3 session
A reference to the current session.
=head3 itemId
The unique id for this transaction item.
=cut
sub newByDynamicTransaction {
my ($class, $session, $itemId) = @_;
unless (defined $session && $session->isa("WebGUI::Session")) {
WebGUI::Error::InvalidObject->throw(expected=>"WebGUI::Session", got=>(ref $session), error=>"Need a session.");
}
unless (defined $itemId) {
WebGUI::Error::InvalidParam->throw(error=>"Need an itemId.");
}
my $transactionId = $session->db->quickScalar("select transactionId from transactionItem where itemId=?",[$itemId]);
my $transaction = WebGUI::Shop::Transaction->new($session, $transactionId);
return $class->new($transaction, $itemId);
}
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -243,7 +289,7 @@ sub update {
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field}; $properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
} }
if (exists $newProperties->{options} && ref($newProperties->{options}) eq "HASH") { if (exists $newProperties->{options} && ref($newProperties->{options}) eq "HASH") {
$properties{$id}{options} = JSON::to_json($newProperties->{options}); $properties{$id}{options} = JSON->new->utf8->encode($newProperties->{options});
} }
if (exists $newProperties->{shippingStatus}) { if (exists $newProperties->{shippingStatus}) {
$properties{$id}{shippingDate} = WebGUI::DateTime->new($self->transaction->session,time())->toDatabase; $properties{$id}{shippingDate} = WebGUI::DateTime->new($self->transaction->session,time())->toDatabase;

View file

@ -20,6 +20,12 @@ our $I18N = {
context => q|help for a workflow activity field label|, context => q|help for a workflow activity field label|,
}, },
'user' => {
message => q|User|,
lastUpdated => 0,
context => q|a property label|,
},
'badge number' => { 'badge number' => {
message => q|Badge #|, message => q|Badge #|,
lastUpdated => 0, lastUpdated => 0,