diff --git a/docs/upgrades/upgrade_7.5.2-7.5.3.pl b/docs/upgrades/upgrade_7.5.2-7.5.3.pl index 1519c3fc0..5444c7060 100644 --- a/docs/upgrades/upgrade_7.5.2-7.5.3.pl +++ b/docs/upgrades/upgrade_7.5.2-7.5.3.pl @@ -23,7 +23,7 @@ my $quiet; # this line required my $session = start(); # this line required # upgrade functions go here - +adddingInStoreCredit($session); insertCommerceTaxTable($session); migrateOldTaxTable($session); insertCommerceShipDriverTable($session); @@ -42,6 +42,21 @@ mergeProductsWithCommerce($session); 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 { my $session = shift; @@ -105,12 +120,14 @@ sub upgradeEMS { notes mediumtext, purchaseComplete boolean, hasCheckedIn boolean, + transactionItemId varchar(22) binary, index badgeAssetId_purchaseComplete (badgeAssetId,purchaseComplete) )"); $db->write("create table EMSRegistrantTicket ( badgeId varchar(22) binary not null, ticketAssetId varchar(22) binary not null, purchaseComplete boolean, + transactionItemId varchar(22) binary, primary key (badgeId, ticketAssetId), index ticketAssetId_purchaseComplete (ticketAssetId,purchaseComplete) )"); @@ -118,11 +135,13 @@ sub upgradeEMS { badgeId varchar(22) binary not null, tokenAssetId varchar(22) binary not null, quantity int, + transactionItemIds text binary, primary key (badgeId,tokenAssetId) )"); $db->write("create table EMSRegistrantRibbon ( badgeId varchar(22) binary not null, ribbonAssetId varchar(22) binary not null, + transactionItemId varchar(22) binary, primary key (badgeId,ribbonAssetId) )"); $db->write("create table EMSBadgeGroup ( diff --git a/lib/WebGUI/Asset/Sku.pm b/lib/WebGUI/Asset/Sku.pm index 80a6fa3ac..72af528ea 100644 --- a/lib/WebGUI/Asset/Sku.pm +++ b/lib/WebGUI/Asset/Sku.pm @@ -384,7 +384,7 @@ tasks to be performed. It should be overriden by subclasses that need to do spec =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 @@ -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 ) Called by the cart just B the item is removed from the cart. This allows for cleanup. Should be overridden by subclasses for inventory control or other housekeeping. diff --git a/lib/WebGUI/Asset/Sku/EMSBadge.pm b/lib/WebGUI/Asset/Sku/EMSBadge.pm index 1be4f3ebf..3e37e57ad 100644 --- a/lib/WebGUI/Asset/Sku/EMSBadge.pm +++ b/lib/WebGUI/Asset/Sku/EMSBadge.pm @@ -193,12 +193,67 @@ sub onCompletePurchase { my $badgeInfo = $self->getOptions; $badgeInfo->{purchaseComplete} = 1; $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); 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 ) Destroys badge. @@ -209,8 +264,9 @@ sub onRemoveFromCart { my ($self, $item) = @_; my $badgeId = $self->getOptions->{badgeId}; foreach my $cartitem (@{$item->cart->getItems()}) { - if (isIn((ref $cartitem), qw(WebGUI::Asset::Sku::EMSTicket WebGUI::Asset::Sku::EMSRibbon WebGUI::Asset::Sku::EMSToken))) { - if ($cartitem->getSku->getOptions->{badgeId} eq $badgeId) { + 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; } } @@ -255,7 +311,7 @@ sub view { my $book = WebGUI::HTMLForm->new($self->session, action=>$self->getUrl); $book->hidden(name=>"shop", value=>"address"); $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, })); $book->submit(value=>$i18n->get("populate from address book")); diff --git a/lib/WebGUI/Asset/Sku/EMSRibbon.pm b/lib/WebGUI/Asset/Sku/EMSRibbon.pm index a194a978f..f7d180db5 100644 --- a/lib/WebGUI/Asset/Sku/EMSRibbon.pm +++ b/lib/WebGUI/Asset/Sku/EMSRibbon.pm @@ -132,8 +132,22 @@ Does bookkeeping on EMSRegistrationRibbon table. sub onCompletePurchase { my ($self, $item) = @_; - $self->session->db->write("insert into EMSRegistrantRibbon (ribbonAssetId, badgeId) values (?,?)", - [$self->getId, $self->getOptions->{badgeId}]); + $self->session->db->write("insert into EMSRegistrantRibbon (transactionItemId, ribbonAssetId, badgeId) values (?,?,?)", + [$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; } diff --git a/lib/WebGUI/Asset/Sku/EMSTicket.pm b/lib/WebGUI/Asset/Sku/EMSTicket.pm index 871a06352..7ce4094a7 100644 --- a/lib/WebGUI/Asset/Sku/EMSTicket.pm +++ b/lib/WebGUI/Asset/Sku/EMSTicket.pm @@ -251,7 +251,7 @@ Extended to support event metadata. sub getEditForm { my $self = shift; 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}) { $form->getTab("meta")->DynamicField( name => "eventmeta ".$field->{label}, @@ -293,7 +293,7 @@ sub getPrice { my $badgeId = $self->getOptions->{badgeId}; my $ribbonId = $self->session->db->quickScalar("select ribbonAssetId from EMSRegistrantRibbon where badgeId=? limit 1",[$badgeId]); 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'); } else { @@ -350,8 +350,22 @@ Marks the ticket as purchased. sub onCompletePurchase { my ($self, $item) = @_; - $self->session->db->write("update EMSRegistrantTicket set purchaseComplete=1 where ticketAssetId=? and badgeId=?", - [$self->getId, $self->getOptions->{badgeId}]); + $self->session->db->write("update EMSRegistrantTicket set purchaseComplete=1, transactionItemId=? where ticketAssetId=? and 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; } @@ -386,7 +400,7 @@ sub processPropertiesFromFormPost { $metadata{$field->{label}} = $form->process('eventmeta '.$field->{label}, $field->{dataType}, { defaultValue => $field->{defaultValues}, options => $field->{possibleValues}}); } - $self->update({eventMetaData => JSON->new->encode(\%metadata)}); + $self->update({eventMetaData => JSON->new->utf8->encode(\%metadata)}); } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Asset/Sku/EMSToken.pm b/lib/WebGUI/Asset/Sku/EMSToken.pm index e8add53e6..37d084335 100644 --- a/lib/WebGUI/Asset/Sku/EMSToken.pm +++ b/lib/WebGUI/Asset/Sku/EMSToken.pm @@ -115,13 +115,43 @@ sub onCompletePurchase { my ($self, $item) = @_; my $db = $self->session->db; 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"); 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 { - $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; $igetId) { + 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; } diff --git a/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm b/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm index 764cc0b68..a56947221 100644 --- a/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm +++ b/lib/WebGUI/Asset/Wobject/EventManagementSystem.pm @@ -642,6 +642,7 @@ sub www_editRegistrantSave { foreach my $field (qw(name address1 address2 address3 city state organization notes)) { $badgeInfo{$field} = $form->get($field, "text"); } + $badgeInfo{'userId'} = $form->get('userId', 'user'); $badgeInfo{'phoneNumber'} = $form->get('phoneNumber', 'phone'); $badgeInfo{'email'} = $form->get('email', 'email'); $badgeInfo{'country'} = $form->get('country', 'country'); @@ -681,7 +682,7 @@ sub www_getBadgesAsJson { $results{'sort'} = undef; $results{'dir'} = "asc"; $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; # build json datasource - return JSON->new->encode($badgeInfo); + return JSON->new->utf8->encode($badgeInfo); } #------------------------------------------------------------------- @@ -871,7 +872,7 @@ sub www_getRegistrantsAsJson { # build json datasource $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{'dir'} = "asc"; $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{'dir'} = "asc"; $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{'dir'} = "asc"; $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 $db = $session->db; 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 - my $registrant = $self->getRegistrant($badgeId); - my $f = WebGUI::HTMLForm->new($session, action=>$self->getUrl); + my $f = WebGUI::HTMLForm->new($session, action=>$self->getUrl, tableExtras=>'class="manageRegistrant"'); $f->submit; $f->hidden(name=>"func", value=>"editRegistrantSave"); $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( name => 'name', label => $i18n->get('name','Shop'), @@ -1270,7 +1285,7 @@ sub www_manageRegistrant { • |.$i18n->get('buy badge').q|
-
+
|.$f->print.q|
@@ -1288,7 +1303,7 @@ sub www_manageRegistrant { my $badge = WebGUI::Asset::Sku::EMSBadge->new($session, $registrant->{badgeAssetId}); $output .= q|

|.$badge->getTitle.q|
|.$i18n->get('print').q| - • |.$i18n->get('refund').q| + • |.$i18n->get('refund').q| • |; if ($registrant->{hasCheckedIn}) { $output .= q||.$i18n->get('mark as not checked in').q||; @@ -1301,30 +1316,31 @@ sub www_manageRegistrant {


|; # ticket management - my $existingTickets = $db->read("select ticketAssetId from EMSRegistrantTicket where badgeId=? and purchaseComplete=1",[$badgeId]); - while (my ($id) = $existingTickets->array) { + my $existingTickets = $db->read("select ticketAssetId, transactionItemId from EMSRegistrantTicket where badgeId=? and purchaseComplete=1",[$badgeId]); + while (my ($id, $itemId) = $existingTickets->array) { my $ticket = WebGUI::Asset::Sku::EMSTicket->new($session, $id); $output .= q|

|.$ticket->getTitle.q|
|.$i18n->get('print').q| - • |.$i18n->get('refund').q| + • |.$i18n->get('refund').q|


|; } # ribbon management - my $existingRibbons = $db->read("select ribbonAssetId from EMSRegistrantRibbon where badgeId=?",[$badgeId]); - while (my ($id) = $existingRibbons->array) { + my $existingRibbons = $db->read("select ribbonAssetId, transactionItemId from EMSRegistrantRibbon where badgeId=?",[$badgeId]); + while (my ($id, $itemId) = $existingRibbons->array) { my $ribbon = WebGUI::Asset::Sku::EMSRibbon->new($session, $id); $output .= q|

|.$ribbon->getTitle.q|
- |.$i18n->get('refund').q| + |.$i18n->get('refund').q|


|; } # token management - my $existingTokens = $db->read("select tokenAssetId,quantity from EMSRegistrantToken where badgeId=?",[$badgeId]); - while (my ($id, $quantity) = $existingTokens->array) { + my $existingTokens = $db->read("select tokenAssetId,quantity,transactionItemIds from EMSRegistrantToken where badgeId=?",[$badgeId]); + while (my ($id, $quantity, $itemIds) = $existingTokens->array) { my $token = WebGUI::Asset::Sku::EMSToken->new($session, $id); + my @itemIds = split(',', $itemIds); $output .= q|

|.$token->getTitle.q| (|.$quantity.q|)
- |.$i18n->get('refund').q| + |.$i18n->get('refund').q|


|; } @@ -1338,6 +1354,11 @@ sub www_manageRegistrant { # render $session->style->setLink($session->url->extras('/yui/build/reset-fonts-grids/reset-fonts-grids.css'), {rel=>"stylesheet", type=>"text/css"}); + $session->style->setRawHeadTags(q| + + |); 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 () diff --git a/lib/WebGUI/Shop/AddressBook.pm b/lib/WebGUI/Shop/AddressBook.pm index cdfada36e..26ecd7470 100644 --- a/lib/WebGUI/Shop/AddressBook.pm +++ b/lib/WebGUI/Shop/AddressBook.pm @@ -434,7 +434,7 @@ sub www_view { my $form = $session->form; my $callback = $form->get('callback'); $callback =~ s/'/"/g; - $callback = JSON::from_json($callback); + $callback = JSON->new->utf8->decode($callback); my $callbackForm = ''; foreach my $param (@{$callback->{params}}) { $callbackForm .= WebGUI::Form::hidden($session, {name=>$param->{name}, value=>$param->{value}}); diff --git a/lib/WebGUI/Shop/Cart.pm b/lib/WebGUI/Shop/Cart.pm index ad9149a4f..2e34723cd 100644 --- a/lib/WebGUI/Shop/Cart.pm +++ b/lib/WebGUI/Shop/Cart.pm @@ -374,14 +374,13 @@ sub new { =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 sub onCompletePurchase { my $self = shift; foreach my $item (@{$self->getItems}) { - $item->getSku->onCompletePurchase($item); $item->delete; } $self->delete; diff --git a/lib/WebGUI/Shop/CartItem.pm b/lib/WebGUI/Shop/CartItem.pm index f3728416a..e3e5b0375 100644 --- a/lib/WebGUI/Shop/CartItem.pm +++ b/lib/WebGUI/Shop/CartItem.pm @@ -126,7 +126,7 @@ sub get { return {}; } else { - return JSON::from_json($properties{id $self}{$name}); + return JSON->new->utf8->decode($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}; } 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}); } diff --git a/lib/WebGUI/Shop/Credit.pm b/lib/WebGUI/Shop/Credit.pm new file mode 100644 index 000000000..90beb0059 --- /dev/null +++ b/lib/WebGUI/Shop/Credit.pm @@ -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; diff --git a/lib/WebGUI/Shop/Transaction.pm b/lib/WebGUI/Shop/Transaction.pm index a46d6f089..6927f367d 100644 --- a/lib/WebGUI/Shop/Transaction.pm +++ b/lib/WebGUI/Shop/Transaction.pm @@ -11,6 +11,7 @@ use WebGUI::International; use WebGUI::Paginator; use WebGUI::Shop::Admin; use WebGUI::Shop::AddressBook; +use WebGUI::Shop::Credit; use WebGUI::Shop::TransactionItem; =head1 NAME @@ -69,7 +70,7 @@ sub addItem { =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 @@ -87,6 +88,9 @@ The extended status message that came back from the payment gateway when trying sub completePurchase { my ($self, $transactionCode, $statusCode, $statusMessage) = @_; + foreach my $item (@{$self->getItems}) { + $item->getSku->onCompletePurchase($item); + } $self->update({ transactionCode => $transactionCode, isSuccessful => 1, @@ -437,7 +441,7 @@ sub www_getTransactionsAsJson { $results{'sort'} = undef; $results{'dir'} = "desc"; $session->http->setMimeType('text/json'); - return JSON::to_json(\%results); + return JSON->new->utf8->encode(\%results); } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Shop/TransactionItem.pm b/lib/WebGUI/Shop/TransactionItem.pm index 81b6e8c44..a5df537f9 100644 --- a/lib/WebGUI/Shop/TransactionItem.pm +++ b/lib/WebGUI/Shop/TransactionItem.pm @@ -5,6 +5,7 @@ use Class::InsideOut qw{ :std }; use JSON; use WebGUI::DateTime; use WebGUI::Exception::Shop; +use WebGUI::Shop::Transaction; =head1 NAME @@ -97,7 +98,7 @@ sub get { return {}; } else { - return JSON::from_json($properties{id $self}{$name}); + return JSON->new->utf8->decode($properties{id $self}{$name}); } } return $properties{id $self}{$name}; @@ -135,6 +136,21 @@ sub getSku { 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; } +#------------------------------------------------------------------- + +=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}; } 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}) { $properties{$id}{shippingDate} = WebGUI::DateTime->new($self->transaction->session,time())->toDatabase; diff --git a/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm b/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm index 258412000..af5a01485 100644 --- a/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm +++ b/lib/WebGUI/i18n/English/Asset_EventManagementSystem.pm @@ -20,6 +20,12 @@ our $I18N = { context => q|help for a workflow activity field label|, }, + 'user' => { + message => q|User|, + lastUpdated => 0, + context => q|a property label|, + }, + 'badge number' => { message => q|Badge #|, lastUpdated => 0,