From b3858ef250d2d85dadd212d78d2443d6cc4c3456 Mon Sep 17 00:00:00 2001 From: Colin Kuskie Date: Tue, 13 Oct 2009 16:37:20 -0700 Subject: [PATCH] Fix bug #10914. Move email notifications about of PayDriver and into Transaction. Send a notification when the cart value is 0 due to shop credit. --- docs/changelog/7.x.x.txt | 1 + docs/upgrades/upgrade_7.8.1-7.8.2.pl | 29 ++++++++++- lib/WebGUI/Shop/Admin.pm | 17 +++++- lib/WebGUI/Shop/Pay.pm | 1 + lib/WebGUI/Shop/PayDriver.pm | 58 +-------------------- lib/WebGUI/Shop/Transaction.pm | 42 +++++++++++++++ lib/WebGUI/i18n/English/PayDriver.pm | 24 --------- lib/WebGUI/i18n/English/Shop.pm | 25 +++++++++ t/Shop/PayDriver.t | 27 +--------- t/Shop/PayDriver/Ogone.t | 14 +---- t/Shop/Transaction.t | 78 ++++++++++++++++++++++++---- t/lib/WebGUI/Test.pm | 40 +++++++------- 12 files changed, 206 insertions(+), 150 deletions(-) diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 2f105e800..fe462decb 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -15,6 +15,7 @@ - fixed #11057: Deleting wiki attachments - fixed #11122: Survey icon is missing from admin console - fixed #11107: linked image with caption + - fixed #10914: Shop: No email notifications sent when the cart has net value 0 7.8.1 - mark $session->datetime->time as deprecated and remove its use from core code diff --git a/docs/upgrades/upgrade_7.8.1-7.8.2.pl b/docs/upgrades/upgrade_7.8.1-7.8.2.pl index bb3685783..8fe9f57c9 100644 --- a/docs/upgrades/upgrade_7.8.1-7.8.2.pl +++ b/docs/upgrades/upgrade_7.8.1-7.8.2.pl @@ -22,7 +22,8 @@ use Getopt::Long; use WebGUI::Session; use WebGUI::Storage; use WebGUI::Asset; - +use WebGUI::Shop::Pay; +use WebGUI::Shop::PayDriver; my $toVersion = '7.8.2'; my $quiet; # this line required @@ -32,6 +33,7 @@ my $session = start(); # this line required fixTableDefaultCharsets($session); correctWikiAttachmentPermissions( $session ); +transactionsNotifications( $session ); finish($session); # this line required @@ -99,6 +101,31 @@ sub correctWikiAttachmentPermissions { print "Done.\n" unless $quiet; } +#---------------------------------------------------------------------------- +# Describe what our function does +sub transactionsNotifications { + my $session = shift; + print "\tMove Shop notifications from PayDriver to Transactions... " unless $quiet; + my $pay = WebGUI::Shop::Pay->new($session); + my $gateways = $pay->getPaymentGateways; + my $defaultNotificationGroup = '3'; + my $defaultTemplate = 'bPz1yk6Y9uwMDMBcmMsSCg'; + if (@{ $gateways }) { + my $firstGateway = $gateways->[0]; + $defaultNotificationGroup = $firstGateway->get('saleNotificationGroupId'); + $defaultTemplate = $firstGateway->get('receiptEmailTemplateId' ); + foreach my $gateway (@{ $gateways }) { + my $properties = $gateway->get(); + delete $properties->{ saleNotificationGroupId }; + delete $properties->{ receiptEmailTemplateId }; + $gateway->update($properties); + } + } + $session->setting->add('shopSaleNotificationGroupId', $defaultNotificationGroup); + $session->setting->add('shopReceiptEmailTemplateId', $defaultTemplate); + print "Done.\n" unless $quiet; +} + # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- #---------------------------------------------------------------------------- diff --git a/lib/WebGUI/Shop/Admin.pm b/lib/WebGUI/Shop/Admin.pm index 3d83c8678..ce4cedd2d 100644 --- a/lib/WebGUI/Shop/Admin.pm +++ b/lib/WebGUI/Shop/Admin.pm @@ -194,6 +194,19 @@ sub www_editSettings { label => $i18n->get("my purchases detail template"), hoverHelp => $i18n->get("my purchases detail template help"), ); + $form->template( + name => 'receiptEmailTemplateId', + namespace => "Shop/EmailReceipt", + label => $i18n->get("receipt email template"), + hoverHelp => $i18n->get("receipt email template help"), + defaultValue => 'bPz1yk6Y9uwMDMBcmMsSCg', + ); + $form->group( + name => 'saleNotificationGroupId', + label => $i18n->get("sale notification group"), + hoverHelp => $i18n->get("sale notification group help"), + defaultValue => '3', + ); $form->submit; return $ac->render($form->print, $i18n->get("shop settings")); } @@ -213,12 +226,12 @@ sub www_editSettingsSave { # Save shop templates foreach my $template (qw(shopMyPurchasesDetailTemplateId shopMyPurchasesTemplateId - shopCartTemplateId shopAddressBookTemplateId shopAddressTemplateId)) { + shopCartTemplateId shopAddressBookTemplateId shopAddressTemplateId shopReceiptEmailTemplateId)) { $setting->set($template, $form->get($template, "template")); } # Save group settings - foreach my $group (qw(groupIdCashier groupIdAdminCommerce)) { + foreach my $group (qw(groupIdCashier groupIdAdminCommerce shopSaleNotificationGroupId)) { $setting->set($group, $form->get($group, "group")); } diff --git a/lib/WebGUI/Shop/Pay.pm b/lib/WebGUI/Shop/Pay.pm index 50dedb5d4..b33d6ca17 100644 --- a/lib/WebGUI/Shop/Pay.pm +++ b/lib/WebGUI/Shop/Pay.pm @@ -413,6 +413,7 @@ sub www_selectPaymentGateway { my $transaction = WebGUI::Shop::Transaction->create($session, {cart => $cart}); $transaction->completePurchase('zero', 'success', 'success'); $cart->onCompletePurchase; + $transaction->sendNotifications(); return $transaction->thankYou(); } diff --git a/lib/WebGUI/Shop/PayDriver.pm b/lib/WebGUI/Shop/PayDriver.pm index 21c2942c4..f5bb67fad 100644 --- a/lib/WebGUI/Shop/PayDriver.pm +++ b/lib/WebGUI/Shop/PayDriver.pm @@ -237,19 +237,6 @@ sub definition { hoverHelp => $i18n->get('who can use help'), defaultValue => 7, }, - receiptEmailTemplateId => { - fieldType => 'template', - namespace => "Shop/EmailReceipt", - label => $i18n->get("receipt email template"), - hoverHelp => $i18n->get("receipt email template help"), - defaultValue => 'bPz1yk6Y9uwMDMBcmMsSCg', - }, - saleNotificationGroupId => { - fieldType => 'group', - label => $i18n->get("sale notification group"), - hoverHelp => $i18n->get("sale notification group help"), - defaultValue => '3', - }, ); my %properties = ( @@ -662,7 +649,7 @@ sub processTransaction { if ($success) { $transaction->completePurchase($transactionCode, $statusCode, $statusMessage); $cart->onCompletePurchase; - $self->sendNotifications($transaction); + $transaction->sendNotifications(); } else { $transaction->denyPurchase($transactionCode, $statusCode, $statusMessage); @@ -680,49 +667,6 @@ Accessor for the session object. Returns the session object. =cut - -#------------------------------------------------------------------- - -=head2 sendNotifications ( transaction ) - -Sends out a receipt and a sale notification to the buyer and the store owner respectively. - -=cut - -sub sendNotifications { - my ($self, $transaction) = @_; - my $session = $self->session; - my $i18n = WebGUI::International->new($session, 'PayDriver'); - my $url = $session->url; - my $var = $transaction->getTransactionVars; - - # render - my $template = WebGUI::Asset::Template->new( $session, $self->get("receiptEmailTemplateId") ); - my $inbox = WebGUI::Inbox->new($session); - my $receipt = $template->process( $var ); - WebGUI::Macro::process($session, \$receipt); - - # purchase receipt - $inbox->addMessage( { - message => $receipt, - subject => $i18n->get('receipt subject') . ' ' . $transaction->get('orderNumber'), - userId => $transaction->get('userId'), - status => 'completed', - } ); - - # shop owner notification - # Shop owner uses method=view rather than method=viewMy - $var->{viewDetailUrl} = $url->page( 'shop=transaction;method=view;transactionId='.$transaction->getId, 1 ); - my $notification = $template->process( $var ); - WebGUI::Macro::process($session, \$notification); - $inbox->addMessage( { - message => $notification, - subject => $i18n->get('a sale has been made') . ' ' . $transaction->get('orderNumber'), - groupId => $self->get('saleNotificationGroupId'), - status => 'unread', - } ); -} - #------------------------------------------------------------------- =head2 update ( $options ) diff --git a/lib/WebGUI/Shop/Transaction.pm b/lib/WebGUI/Shop/Transaction.pm index 6bb226ffd..7619dbc51 100644 --- a/lib/WebGUI/Shop/Transaction.pm +++ b/lib/WebGUI/Shop/Transaction.pm @@ -619,6 +619,48 @@ sub newByGatewayId { #------------------------------------------------------------------- +=head2 sendNotifications ( transaction ) + +Sends out a receipt and a sale notification to the buyer and the store owner respectively. + +=cut + +sub sendNotifications { + my ($self) = @_; + my $session = $self->session; + my $i18n = WebGUI::International->new($session, 'PayDriver'); + my $url = $session->url; + my $var = $self->getTransactionVars; + + # render + my $template = WebGUI::Asset::Template->new( $session, $session->setting->get("shopReceiptEmailTemplateId") ); + my $inbox = WebGUI::Inbox->new($session); + my $receipt = $template->process( $var ); + WebGUI::Macro::process($session, \$receipt); + + # purchase receipt + $inbox->addMessage( { + message => $receipt, + subject => $i18n->get('receipt subject') . ' ' . $self->get('orderNumber'), + userId => $self->get('userId'), + status => 'completed', + } ); + + # shop owner notification + # Shop owner uses method=view rather than method=viewMy + $var->{viewDetailUrl} = $url->page( 'shop=transaction;method=view;transactionId='.$self->getId, 1 ); + my $notification = $template->process( $var ); + WebGUI::Macro::process($session, \$notification); + $inbox->addMessage( { + message => $notification, + subject => $i18n->get('a sale has been made') . ' ' . $self->get('orderNumber'), + groupId => $session->setting->get('shopSaleNotificationGroupId'), + status => 'unread', + } ); +} + +#------------------------------------------------------------------- + =head2 thankYou () Displays the default thank you page. diff --git a/lib/WebGUI/i18n/English/PayDriver.pm b/lib/WebGUI/i18n/English/PayDriver.pm index bda767ae0..3da096822 100644 --- a/lib/WebGUI/i18n/English/PayDriver.pm +++ b/lib/WebGUI/i18n/English/PayDriver.pm @@ -15,12 +15,6 @@ our $I18N = { context => q|commerce setting| }, - 'sale notification group' => { - message => q|Sale Notification Group|, - lastUpdated => 0, - context => q|commerce setting| - }, - 'error processing payment' => { message => q|Error Processing Payment|, lastUpdated => 0, @@ -33,24 +27,6 @@ our $I18N = { context => q|the description on the error screen| }, - 'sale notification group help' => { - message => q|Who should be notified of new transactions?|, - lastUpdated => 0, - context => q|commerce setting help| - }, - - 'receipt email template' => { - message => q|Receipt Email Template|, - lastUpdated => 0, - context => q|commerce setting| - }, - - 'receipt email template help' => { - message => q|Which template should be used to generate an email that will be sent to the user to acknowledge their purchase?|, - lastUpdated => 0, - context => q|commerce setting help| - }, - 'label' => { message => q|Label|, lastUpdated => 0, diff --git a/lib/WebGUI/i18n/English/Shop.pm b/lib/WebGUI/i18n/English/Shop.pm index a03244c55..7b0f30d32 100644 --- a/lib/WebGUI/i18n/English/Shop.pm +++ b/lib/WebGUI/i18n/English/Shop.pm @@ -1671,6 +1671,31 @@ our $I18N = { context => q|Label to make the user choose a shipping method|, }, + 'receipt email template' => { + message => q|Receipt Email Template|, + lastUpdated => 0, + context => q|commerce setting| + }, + + 'receipt email template help' => { + message => q|Which template should be used to generate an email that will be sent to the user to acknowledge their purchase?|, + lastUpdated => 0, + context => q|commerce setting help| + }, + + 'sale notification group' => { + message => q|Sale Notification Group|, + lastUpdated => 0, + context => q|commerce setting| + }, + + 'sale notification group help' => { + message => q|Who should be notified of new transactions?|, + lastUpdated => 0, + context => q|commerce setting help| + }, + + }; 1; diff --git a/t/Shop/PayDriver.t b/t/Shop/PayDriver.t index 8bb46ea3b..d4a87acfd 100644 --- a/t/Shop/PayDriver.t +++ b/t/Shop/PayDriver.t @@ -93,19 +93,6 @@ cmp_deeply ( hoverHelp => ignore(), defaultValue => 7, }, - receiptEmailTemplateId => { - fieldType => 'template', - label => ignore(), - hoverHelp => ignore(), - defaultValue => 'bPz1yk6Y9uwMDMBcmMsSCg', - namespace => 'Shop/EmailReceipt', - }, - saleNotificationGroupId => { - fieldType => 'group', - label => ignore(), - hoverHelp => ignore(), - defaultValue => 3, - }, } } ], , @@ -286,7 +273,7 @@ my @forms = HTML::Form->parse($html, 'http://www.webgui.org'); is (scalar @forms, 1, 'getEditForm generates just 1 form'); my @inputs = $forms[0]->inputs; -is (scalar @inputs, 14, 'getEditForm: the form has 14 controls'); +is (scalar @inputs, 11, 'getEditForm: the form has 11 controls'); my @interestingFeatures; foreach my $input (@inputs) { @@ -342,18 +329,6 @@ cmp_deeply( name => '__groupToUse_isIn', type => 'hidden', }, - { - name => 'receiptEmailTemplateId', - type => 'option', - }, - { - name => 'saleNotificationGroupId', - type => 'option', - }, - { - name => '__saleNotificationGroupId_isIn', - type => 'hidden', - }, ], 'getEditForm made the correct form with all the elements' diff --git a/t/Shop/PayDriver/Ogone.t b/t/Shop/PayDriver/Ogone.t index b5f293415..8b0749155 100644 --- a/t/Shop/PayDriver/Ogone.t +++ b/t/Shop/PayDriver/Ogone.t @@ -372,7 +372,7 @@ my @forms = HTML::Form->parse($html, 'http://www.webgui.org'); is (scalar @forms, 1, 'getEditForm generates just 1 form'); my @inputs = $forms[0]->inputs; -is (scalar @inputs, 20, 'getEditForm: the form has 20 controls'); +is (scalar @inputs, 17, 'getEditForm: the form has 17 controls'); my @interestingFeatures; foreach my $input (@inputs) { @@ -428,18 +428,6 @@ cmp_deeply( name => '__groupToUse_isIn', type => 'hidden', }, - { - name => 'receiptEmailTemplateId', - type => 'option', - }, - { - name => 'saleNotificationGroupId', - type => 'option', - }, - { - name => '__saleNotificationGroupId_isIn', - type => 'hidden', - }, { name => 'pspid', type => 'text', diff --git a/t/Shop/Transaction.t b/t/Shop/Transaction.t index b2153a4d6..925e9c3ea 100644 --- a/t/Shop/Transaction.t +++ b/t/Shop/Transaction.t @@ -21,6 +21,8 @@ use Test::Deep; use WebGUI::Test; # Must use this before any other WebGUI modules use WebGUI::Session; use WebGUI::Shop::Transaction; +use WebGUI::Inbox; +use Clone qw/clone/; #---------------------------------------------------------------------------- # Init @@ -30,7 +32,7 @@ my $session = WebGUI::Test->session; #---------------------------------------------------------------------------- # Tests -plan tests => 68; # Increment this number for each test you create +plan tests => 77; # Increment this number for each test you create #---------------------------------------------------------------------------- # put your tests here @@ -64,6 +66,7 @@ my $transaction = WebGUI::Shop::Transaction->create($session,{ paymentDriverLabel => 'kkk', taxes => 7, }); +addToCleanup($transaction); # objects work isa_ok($transaction, "WebGUI::Shop::Transaction"); @@ -223,15 +226,72 @@ TODO: { ok(0, 'test keywords'); } +####################################################################### +# +# sendNotification +# +####################################################################### + +my $shopUser = WebGUI::User->create($session); +$shopUser->username('shopUser'); +my $shopGroup = WebGUI::Group->new($session, 'new'); +my $shopAdmin = WebGUI::User->create($session); +$shopUser->username('shopAdmin'); +$shopGroup->addUsers([$shopAdmin->getId]); +addToCleanup($shopUser, $shopAdmin, $shopGroup); +$session->setting->set('shopSaleNotificationGroupId', $shopGroup->getId); +$session->user({userId => $shopUser->getId}); + +my $trans = WebGUI::Shop::Transaction->create($session, {}); +ok($trans->can('sendNotifications'), 'sendNotifications: valid method for transactions'); +addToCleanup($trans); + +##Disable sending email +my $sendmock = Test::MockObject->new( {} ); +$sendmock->set_isa('WebGUI::Mail::Send'); +$sendmock->set_true('addText', 'send', 'addHeaderField', 'addHtml', 'queue', 'addFooter'); +local *WebGUI::Mail::Send::create; +$sendmock->fake_module('WebGUI::Mail::Send', + create => sub { return $sendmock }, +); + + #1234567890123456789012# +my $templateId = 'SHOP_NOTIFICATION_____'; + +my $templateMock = Test::MockObject->new({}); +$templateMock->set_isa('WebGUI::Asset::Template'); +$templateMock->set_always('getId', $templateId); +my @templateVars; +$templateMock->mock('process', sub { push @templateVars, clone $_[1]; } ); + +$session->setting->set('shopReceiptEmailTemplateId', $templateId); + +{ + WebGUI::Test->mockAssetId($templateId, $templateMock); + $trans->sendNotifications; + is(@templateVars, 2, '... called template->process twice'); + my $inbox = WebGUI::Inbox->new($session); + my $userMessages = $inbox->getMessagesForUser($shopUser); + my $adminMessages = $inbox->getMessagesForUser($shopAdmin); + is(@{ $userMessages }, 1, '... sent one message to shop user'); + is(@{ $adminMessages }, 1, '... sent one message to shop admin, via shopSaleNotificationGroupId'); + like($userMessages->[0]->get('subject'), qr/^Receipt for Order #/, '... subject for user email okay'); + like($adminMessages->[0]->get('subject'), qr/^A sale has been made/, '... subject for admin email okay'); + like($templateVars[0]->{viewDetailUrl}, qr/shop=transaction;method=viewMy;/, '... viewDetailUrl okay for user'); + like($templateVars[1]->{viewDetailUrl}, qr/shop=transaction;method=view;/ , '... viewDetailUrl okay for admin'); + WebGUI::Test->unmockAssetId($templateId); +} + +####################################################################### +# +# delete +# +####################################################################### $transaction->delete; -is($session->db->quickScalar("select transactionId from transaction where transactionId=?",[$transaction->getId]), undef, "can delete transactions"); +is($session->db->quickScalar("select count(*) from transaction where transactionId=?",[$transaction->getId]), + 0, "delete: deleted transaction"); +is($session->db->quickScalar("select count(*) from transactionItem where transactionId=?",[$transaction->getId]), + 0, "... deleted transactionItems associated with this transaction"); - -#---------------------------------------------------------------------------- -# Cleanup -END { - $session->db->write('delete from transaction'); - $session->db->write('delete from transactionItem'); -} diff --git a/t/lib/WebGUI/Test.pm b/t/lib/WebGUI/Test.pm index 2a0472bb1..86ecececa 100644 --- a/t/lib/WebGUI/Test.pm +++ b/t/lib/WebGUI/Test.pm @@ -100,16 +100,18 @@ sub import { if ($ENV{WEBGUI_TEST_DEBUG}) { ##Offset Sessions, and Scratch by 1 because 1 will exist at the start my @checkCount = ( - Sessions => 'userSession', - Scratch => 'userSessionScratch', - Users => 'users', - Groups => 'groups', - mailQ => 'mailQueue', - Tags => 'assetVersionTag', - Assets => 'assetData', - Workflows => 'Workflow', - Carts => 'cart', - 'Ship Drivers' => 'shipper', + Sessions => 'userSession', + Scratch => 'userSessionScratch', + Users => 'users', + Groups => 'groups', + mailQ => 'mailQueue', + Tags => 'assetVersionTag', + Assets => 'assetData', + Workflows => 'Workflow', + Carts => 'cart', + Transactions => 'transaction', + 'Transaction Items' => 'transactionItem', + 'Ship Drivers' => 'shipper', ); my %initCounts; for ( my $i = 0; $i < @checkCount; $i += 2) { @@ -767,6 +769,7 @@ were passed in. Currently able to destroy: WebGUI::Workflow WebGUI::Shop::Cart WebGUI::Shop::ShipDriver + WebGUI::Shop::Transaction Example call: @@ -835,14 +838,15 @@ Example call: ); my %cleanup = ( - 'WebGUI::User' => 'delete', - 'WebGUI::Group' => 'delete', - 'WebGUI::Storage' => 'delete', - 'WebGUI::Asset' => 'purge', - 'WebGUI::VersionTag' => 'rollback', - 'WebGUI::Workflow' => 'delete', - 'WebGUI::Shop::ShipDriver' => 'delete', - 'WebGUI::Shop::Cart' => sub { + 'WebGUI::User' => 'delete', + 'WebGUI::Group' => 'delete', + 'WebGUI::Storage' => 'delete', + 'WebGUI::Asset' => 'purge', + 'WebGUI::VersionTag' => 'rollback', + 'WebGUI::Workflow' => 'delete', + 'WebGUI::Shop::Transaction' => 'delete', + 'WebGUI::Shop::ShipDriver' => 'delete', + 'WebGUI::Shop::Cart' => sub { my $cart = shift; my $addressBook = $cart->getAddressBook(); $addressBook->delete if $addressBook; ##Should we call cleanupGuard instead???