Merge commit 'v7.10.22' into WebGUI8
This commit is contained in:
commit
431cd280a4
92 changed files with 3543 additions and 313 deletions
|
|
@ -431,16 +431,67 @@ sub www_editSave {
|
|||
|
||||
unless(scalar(@{$retHash->{errors}})) {
|
||||
my $profile = $retHash->{profile};
|
||||
|
||||
my $privacy = {};
|
||||
$session->user->update($profile);
|
||||
|
||||
my $address = {};
|
||||
my $address_mappings = WebGUI::Shop::AddressBook->getProfileAddressMappings;
|
||||
foreach my $fieldName (keys %{$profile}) {
|
||||
#set the shop address fields
|
||||
my $address_key = $address_mappings->{$fieldName};
|
||||
$address->{$address_key} = $profile->{ $fieldName } if ($address_key);
|
||||
|
||||
#set the privacy settings
|
||||
my $privacySetting = $session->form->get("privacy_".$fieldName);
|
||||
next unless $privacySetting;
|
||||
$privacy->{$fieldName} = $privacySetting;
|
||||
}
|
||||
|
||||
$session->user->setProfileFieldPrivacySetting($privacy);
|
||||
|
||||
#Update or create and update the shop address
|
||||
if ( keys %$address ) {
|
||||
$address->{'isProfile' } = 1;
|
||||
|
||||
#Get the address book for the user (one is created if it does not exist)
|
||||
my $addressBook = WebGUI::Shop::AddressBook->newByUserId($session,$self->uid);
|
||||
my $profileAddress = eval { $addressBook->getProfileAddress() };
|
||||
|
||||
my $e;
|
||||
if($e = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
|
||||
#Get home address only mappings to avoid creating addresses with just firstName, lastName, email
|
||||
my %home_address_map = %{$address_mappings};
|
||||
foreach my $exclude ( qw{ firstName lastName email } ) {
|
||||
delete $home_address_map{$exclude};
|
||||
}
|
||||
#Add the profile address for the user if there are homeAddress fields
|
||||
if( grep { $address->{$_} } values %home_address_map ) {
|
||||
$address->{label} = "Profile Address";
|
||||
my $new_address = $addressBook->addAddress($address);
|
||||
#Set this as the default address if one doesn't already exist
|
||||
my $defaultAddress = eval{ $addressBook->getDefaultAddress };
|
||||
if(WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
|
||||
$addressBook->update( {
|
||||
defaultAddressId => $new_address->getId
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($e = WebGUI::Error->caught) {
|
||||
#Bad stuff happened - log an error but don't fail since this isn't a vital function
|
||||
$session->log->error(
|
||||
q{Could not update Shop Profile Address for user }
|
||||
.$self->username.q{ : }.$e->error
|
||||
);
|
||||
}
|
||||
else {
|
||||
#Update the profile address for the user
|
||||
$profileAddress->update($address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#Store the category the error occurred in the object for reference
|
||||
$self->store->{selected} = $retHash->{errorCategory};
|
||||
|
||||
|
|
|
|||
|
|
@ -257,15 +257,17 @@ sub duplicate {
|
|||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $copy = $self->SUPER::duplicate(@_);
|
||||
my $oldGroupId = $self->get('subscriptionGroupId');
|
||||
my $key = 'subscriptionGroupId';
|
||||
my $oldGroupId = $self->get($key);
|
||||
|
||||
if ($oldGroupId) {
|
||||
my $newGroup = WebGUI::Group->new($session, 'new');
|
||||
my $oldGroup = WebGUI::Group->new($session, $oldGroupId);
|
||||
if ($oldGroup) {
|
||||
$copy->update({ $key => '' });
|
||||
$copy->createSubscriptionGroup();
|
||||
if (my $oldGroup = WebGUI::Group->new($session, $oldGroupId)) {
|
||||
my $newGroup = WebGUI::Group->new($session, $copy->get($key));
|
||||
$newGroup->addUsers($oldGroup->getUsers('withoutExpired'));
|
||||
$newGroup->addGroups($oldGroup->getGroupsIn);
|
||||
}
|
||||
$copy->update({subscriptionGroupId => $newGroup->getId});
|
||||
}
|
||||
return $copy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -592,6 +592,22 @@ sub processStyle {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 purge ( )
|
||||
|
||||
Extent the base class to clean out any items using this Sku in all Carts.
|
||||
|
||||
=cut
|
||||
|
||||
sub purge {
|
||||
my $self = shift;
|
||||
my $assetId = $self->getId;
|
||||
my $success = $self->SUPER::purge;
|
||||
return $success unless $success;
|
||||
$self->session->db->write('delete from cartItem where assetId=?',[$assetId]);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 setTaxConfiguration ($namespace, $configuration)
|
||||
|
||||
=head3 $namespace
|
||||
|
|
|
|||
|
|
@ -83,6 +83,7 @@ property templateId => (
|
|||
|
||||
use JSON;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Shop::Admin;
|
||||
use WebGUI::Shop::AddressBook;
|
||||
|
||||
=head1 NAME
|
||||
|
|
@ -204,6 +205,28 @@ sub getMaxAllowedInCart {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
=head2 getPostPurchaseActions ( item )
|
||||
|
||||
Return a hash reference of "label" => "url" to do things with this item after
|
||||
it is purchased. C<item> is the WebGUI::Shop::TransactionItem for this item
|
||||
|
||||
=cut
|
||||
|
||||
sub getPostPurchaseActions {
|
||||
my ( $self, $item ) = @_;
|
||||
my $session = $self->session;
|
||||
my $opts = $self->SUPER::getPostPurchaseActions();
|
||||
if($self->getParent->isRegistrationStaff) {
|
||||
my $i18n = WebGUI::International->new( $session, "Asset_EventManagementSystem" );
|
||||
my $badgeId = $item->get('options')->{badgeId};
|
||||
|
||||
$opts->{ $i18n->get('print') } = $self->getParent->getUrl( "func=printBadge;badgeId=$badgeId" );
|
||||
}
|
||||
return $opts;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPrice
|
||||
|
|
@ -404,11 +427,19 @@ sub view {
|
|||
;
|
||||
|
||||
# instanciate address
|
||||
my $address = WebGUI::Shop::AddressBook->newByUserId($self->session)->getAddress($form->get("addressId")) if ($form->get("addressId"));
|
||||
my $address = undef;
|
||||
my $address_book = WebGUI::Shop::AddressBook->newByUserId($self->session);
|
||||
if ($form->get("addressId")) {
|
||||
$address = $address_book->getAddress($form->get("addressId"));
|
||||
}
|
||||
else {
|
||||
$address = eval{ $address_book->getDefaultAddress }
|
||||
}
|
||||
|
||||
# build the form that the user needs to fill out with badge holder information
|
||||
$vars{formHeader} = WebGUI::Form::formHeader($session, {action => $self->getUrl})
|
||||
. WebGUI::Form::hidden($session, {name=>"func", value =>'addToCart'});
|
||||
. WebGUI::Form::hidden($session, {name=>"func", value =>'addToCart'})
|
||||
. WebGUI::Form::hidden($session, {name=>"addressId", value=>(defined $address ? $address->getId : "" )});;
|
||||
$vars{formFooter} = WebGUI::Form::formFooter($session);
|
||||
$vars{name} = WebGUI::Form::text($session, {
|
||||
name => 'name',
|
||||
|
|
@ -457,9 +488,21 @@ sub view {
|
|||
if($self->getQuantityAvailable() > 0){
|
||||
$vars{submitAddress} = WebGUI::Form::submit($session, {value => $i18n->get('add to cart'),});
|
||||
}
|
||||
$vars{resetButton} = q{<input type="button" value="}.$i18n->get('clear form'). q{" onclick="WebGUI.Form.clearForm(this.form)" />};
|
||||
$vars{title} = $self->getTitle;
|
||||
$vars{description} = $self->description;
|
||||
|
||||
$vars{search_url } = $self->getUrl("shop=address;method=ajaxSearch");
|
||||
|
||||
my $shopAdmin = WebGUI::Shop::Admin->new($session);
|
||||
my $isStaff = $self->getParent->isRegistrationStaff;
|
||||
my $canManageShop = $shopAdmin->canManage;
|
||||
my $isCashier = $shopAdmin->isCashier;
|
||||
|
||||
if($isStaff && ($canManageShop || $isCashier)) {
|
||||
$vars{canSearch} = 1;
|
||||
}
|
||||
|
||||
# render the page;
|
||||
return $self->processTemplate(\%vars, undef, $self->{_viewTemplate});
|
||||
}
|
||||
|
|
@ -495,13 +538,46 @@ sub www_addToCart {
|
|||
if ($badgeInfo{name} eq "") {
|
||||
$error = sprintf $i18n->get('is required'), $i18n->get('name','Shop');
|
||||
}
|
||||
|
||||
|
||||
# return them back to the previous screen if they messed up
|
||||
if ($error) {
|
||||
$self->{_errorMessage} = $error;
|
||||
return $self->www_view($error);
|
||||
}
|
||||
|
||||
|
||||
#check to see if address has changed - if so, create a new address and set it to the default
|
||||
my $address_id = $form->get("addressId");
|
||||
if($address_id) {
|
||||
my $address = undef;
|
||||
my $address_book = WebGUI::Shop::AddressBook->newByUserId($self->session);
|
||||
$address = $address_book->getAddress($address_id);
|
||||
my $has_changes = 0;
|
||||
my $new_address = {};
|
||||
foreach my $field_name (qw/name address1 address2 address3 city state country code phoneNumber organization email/) {
|
||||
my $form_field_name = $field_name;
|
||||
$form_field_name = "zipcode" if ($field_name eq "code");
|
||||
if($field_name eq "name") {
|
||||
if($address->get('firstName')." ".$address->get('lastName') ne $badgeInfo{name}) {
|
||||
$has_changes = 1;
|
||||
}
|
||||
($new_address->{firstName},$new_address->{lastName}) = split(" ",$badgeInfo{name});
|
||||
next;
|
||||
}
|
||||
elsif($address->get($field_name) ne $badgeInfo{$form_field_name}) {
|
||||
$has_changes = 1;
|
||||
}
|
||||
$new_address->{$field_name} = $badgeInfo{$form_field_name};
|
||||
}
|
||||
|
||||
if($has_changes) {
|
||||
my $address_book = WebGUI::Shop::AddressBook->newByUserId($self->session);
|
||||
$new_address->{label} = $form->get("label")." New";
|
||||
my $new_address = $address_book->addAddress($new_address);
|
||||
$address_book->update({defaultAddressId => $new_address->getId });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# add it to the cart
|
||||
$self->addToCart(\%badgeInfo);
|
||||
return $self->getParent->www_buildBadge($self->getOptions->{badgeId});
|
||||
|
|
|
|||
|
|
@ -2590,9 +2590,10 @@ sub www_printBadge {
|
|||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return $session->privilege->insufficient unless ($self->isRegistrationStaff);
|
||||
my $form = $session->form;
|
||||
my $registrant = $self->getRegistrant($form->get('badgeId'));
|
||||
my $badge = WebGUI::Asset::Sku::EMSBadge->newById($session, $registrant->{badgeAssetId});
|
||||
my $form = $session->form;
|
||||
my $badgeId = $form->get('badgeId');
|
||||
my $registrant = $self->getRegistrant($badgeId);
|
||||
my $badge = WebGUI::Asset::Sku::EMSBadge->newById($session, $registrant->{badgeAssetId});
|
||||
$registrant->{badgeTitle} = $badge->getTitle;
|
||||
|
||||
# Add badge metadata
|
||||
|
|
@ -2601,6 +2602,42 @@ sub www_printBadge {
|
|||
$registrant->{ "badgeMeta_" . $key } = $meta->{ $key };
|
||||
}
|
||||
|
||||
#Add tickets
|
||||
my @tickets = $session->db->buildArray(
|
||||
q{select ticketAssetId from EMSRegistrantTicket where badgeId=?},
|
||||
[$badgeId]
|
||||
);
|
||||
|
||||
$registrant->{ticket_loop} = [];
|
||||
foreach my $ticketId (@tickets) {
|
||||
my $ticket = WebGUI::Asset::Sku::EMSTicket->newById($session, $ticketId);
|
||||
push (@{$registrant->{ticket_loop}}, $ticket->get);
|
||||
}
|
||||
|
||||
#Add ribbons
|
||||
my @ribbons = $session->db->buildArray(
|
||||
q{select ribbonAssetId from EMSRegistrantRibbon where badgeId=?},
|
||||
[$badgeId]
|
||||
);
|
||||
|
||||
$registrant->{ribbon_loop} = [];
|
||||
foreach my $ribbonId (@ribbons) {
|
||||
my $ribbon = WebGUI::Asset::Sku::EMSRibbon->newById($session, $ribbonId);
|
||||
push (@{$registrant->{ribbon_loop}}, $ribbon->get);
|
||||
}
|
||||
|
||||
## Add tokens
|
||||
my @tokens = $session->db->buildArray(
|
||||
q{select tokenAssetId from EMSRegistrantToken where badgeId=?},
|
||||
[$badgeId]
|
||||
);
|
||||
|
||||
$registrant->{token_loop} = [];
|
||||
foreach my $tokenId (@tokens) {
|
||||
my $token = WebGUI::Asset::Sku::EMSToken->newById($session, $tokenId);
|
||||
push (@{$registrant->{token_loop}}, $token->get);
|
||||
}
|
||||
|
||||
return $self->processTemplate($registrant,$self->printBadgeTemplateId);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -643,7 +643,7 @@ sub editThingDataSave {
|
|||
}
|
||||
if ($field->{status} eq "required" && ($fieldValue =~ /^\s$/x || $fieldValue eq "" || !(defined $fieldValue))) {
|
||||
push (@errors,{
|
||||
"error_message"=>$field->{label}." ".$i18n->get('is required error').".",
|
||||
"error_message"=>$field->{label}." ".$i18n->get('is required error').".", "field_name"=>$fieldName,
|
||||
});
|
||||
}
|
||||
if ($field->{status} eq "hidden") {
|
||||
|
|
@ -659,7 +659,7 @@ sub editThingDataSave {
|
|||
|
||||
unless ( $self->isUniqueEntry($thingId,$fieldName,$fieldValue,$thingDataId)) {
|
||||
push (@errors,{
|
||||
"error_message"=>$field->{label}. $i18n->get('needs to be unique error'),
|
||||
"error_message"=>$field->{label}. $i18n->get('needs to be unique error'),"field_name"=>$fieldName,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ sub www_editMetaDataField {
|
|||
label=>$i18n->get(486),
|
||||
hoverHelp=>$i18n->get('Data Type description'),
|
||||
value=>$fieldInfo->{fieldType} || "text",
|
||||
types=> [ qw /text integer yesNo selectBox radioList checkList/ ]
|
||||
types=> [ qw /text integer yesNo selectBox radioList checkList dateTime/ ]
|
||||
);
|
||||
|
||||
my $default = ref WebGUI::Asset->assetName eq 'ARRAY'
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ use WebGUI::International;
|
|||
use WebGUI::Asset::Template;
|
||||
use WebGUI::User;
|
||||
use WebGUI::Workflow::Instance;
|
||||
use WebGUI::Shop::AddressBook;
|
||||
use WebGUI::Inbox;
|
||||
use WebGUI::Friends;
|
||||
use WebGUI::Deprecate;
|
||||
|
|
@ -910,9 +911,6 @@ sub www_createAccountSave {
|
|||
my $userId = $u->userId;
|
||||
$u->username($username);
|
||||
$u->authMethod($self->authMethod);
|
||||
$self->session->log->info( " override: " . $self->session->scratch->getLanguageOverride );
|
||||
use Data::Dumper;
|
||||
$self->session->log->info( Dumper $profile );
|
||||
|
||||
if (!$profile->{'language'} && $self->session->scratch->getLanguageOverride) {
|
||||
$profile->{'language'} = $self->session->scratch->getLanguageOverride;
|
||||
|
|
@ -921,6 +919,34 @@ sub www_createAccountSave {
|
|||
$u->updateProfileFields($profile) if ($profile);
|
||||
$self->update($properties);
|
||||
|
||||
my $address = {};
|
||||
my $address_mappings = WebGUI::Shop::AddressBook->getProfileAddressMappings;
|
||||
foreach my $fieldId (keys %$profile) {
|
||||
#set the shop address fields
|
||||
my $address_key = $address_mappings->{$fieldId};
|
||||
$address->{$address_key} = $profile->{$fieldId} if ($address_key);
|
||||
}
|
||||
|
||||
#Update or create and update the shop address
|
||||
if ( keys %$address ) {
|
||||
$address->{'isProfile' } = 1;
|
||||
|
||||
#Get home address only mappings to avoid creating addresses with just firstName, lastName, email
|
||||
my %home_address_map = %{$address_mappings};
|
||||
foreach my $exclude ( qw{ firstName lastName email } ) {
|
||||
delete $home_address_map{$exclude};
|
||||
}
|
||||
#Add the profile address for the user if there are homeAddress fields
|
||||
if( grep { $address->{$_} } values %home_address_map ) {
|
||||
#Create the address book for the user
|
||||
my $addressBook = WebGUI::Shop::AddressBook->newByUserId($self->session,$userId);
|
||||
$address->{label} = "Profile Address";
|
||||
my $new_address = $addressBook->addAddress($address);
|
||||
#Set this as the default address if one doesn't already exist
|
||||
$addressBook->update( { defaultAddressId => $new_address->getId } );
|
||||
}
|
||||
}
|
||||
|
||||
if ($self->getSetting("sendWelcomeMessage")){
|
||||
my $var;
|
||||
$var->{welcomeMessage} = $self->getSetting("welcomeMessage");
|
||||
|
|
|
|||
|
|
@ -40,7 +40,25 @@ The following methods are specifically available from this class. Check the supe
|
|||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, [ additionalTerms ] )
|
||||
|
||||
Add another field so we can provide extras to the text area vs the selectBox
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift || [];
|
||||
push(@{$definition}, {
|
||||
textExtras=>{
|
||||
defaultValue=>undef
|
||||
},
|
||||
});
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
|
|
@ -127,7 +145,8 @@ sub toHtml {
|
|||
.WebGUI::Form::Text->new($self->session,
|
||||
size=>$self->session->setting->get("textBoxSize")-5,
|
||||
name=>$self->get("name")."_new",
|
||||
id=>$self->get('id')."_new"
|
||||
id=>$self->get('id')."_new",
|
||||
extras=>$self->get('textExtras'),
|
||||
)->toHtml;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ sub getValue {
|
|||
|
||||
=head2 getDefaultValue ( )
|
||||
|
||||
Returns the either the "value" ore "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
Returns the either the "value" or "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ sub getDefaultValue {
|
|||
|
||||
=head2 getOriginalValue ( )
|
||||
|
||||
Returns the either the "value" ore "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
Returns the either the "value" or "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ sub getValue {
|
|||
|
||||
=head2 getDefaultValue ( )
|
||||
|
||||
Returns the either the "value" ore "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
Returns the either the "value" or "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ sub getDefaultValue {
|
|||
|
||||
=head2 getOriginalValue ( )
|
||||
|
||||
Returns the either the "value" ore "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
Returns the either the "value" or "defaultValue" passed in to the object in that order, and doesn't take into account form processing.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
|
|||
|
|
@ -419,7 +419,11 @@ sub processReplacements {
|
|||
}
|
||||
foreach my $searchFor (keys %{$replacements}) {
|
||||
my $replaceWith = $replacements->{$searchFor};
|
||||
$content =~ s/\b\Q$searchFor\E\b/$replaceWith/gs;
|
||||
my $pattern = qr/\Q$searchFor\E/;
|
||||
if ($searchFor =~ /^\w+/) {
|
||||
$pattern = qr/\b$pattern\b/;
|
||||
}
|
||||
$content =~ s/$pattern/$replaceWith/gs;
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -790,7 +790,7 @@ sub www_editUser {
|
|||
size=>15,
|
||||
value=>\@groupsToDelete
|
||||
);
|
||||
return '<h1>' . $i18n->get(168) . '</h1>' . $f->toHtml;
|
||||
return '<h1>' . $i18n->get(168) . '</h1>' . $error . $f->toHtml;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -818,7 +818,7 @@ sub www_editUserSave {
|
|||
|
||||
return $session->privilege->adminOnly() unless ($isAdmin || $isSecondary) && $session->form->validToken;
|
||||
|
||||
# Check to see if
|
||||
# Check to see if
|
||||
# 1) the userId associated with the posted username matches the posted userId (we're editing an account)
|
||||
# or that the userId is new and the username selected is unique (creating new account)
|
||||
# or that the username passed in isn't assigned a userId (changing a username)
|
||||
|
|
@ -829,11 +829,11 @@ sub www_editUserSave {
|
|||
my $postedUsername = $session->form->process("username");
|
||||
$postedUsername = WebGUI::HTML::filter($postedUsername, "all");
|
||||
|
||||
if (($existingUserId eq $postedUserId || ($postedUserId eq "new" && !$existingUserId) || $existingUserId eq '')
|
||||
if (($existingUserId eq $postedUserId || ($postedUserId eq "new" && !$existingUserId) || $existingUserId eq '')
|
||||
&& $postedUsername ne '')
|
||||
{
|
||||
# Create a user object with the id passed in. If the Id is 'new', the new method will return a new user,
|
||||
# otherwise return the existing users properties
|
||||
# Create a user object with the id passed in. If the Id is 'new', the new method will return a new user,
|
||||
# otherwise return the existing users properties
|
||||
my $u = WebGUI::User->new($session,$postedUserId);
|
||||
$actualUserId = $u->userId;
|
||||
|
||||
|
|
@ -851,10 +851,59 @@ sub www_editUserSave {
|
|||
}
|
||||
|
||||
# Loop through all profile fields, and update them with new values.
|
||||
foreach my $field (@{WebGUI::ProfileField->getFields($session)}) {
|
||||
my $address = {};
|
||||
my $address_mappings = WebGUI::Shop::AddressBook->getProfileAddressMappings;
|
||||
foreach my $field (@{WebGUI::ProfileField->getFields($session)}) {
|
||||
next if $field->getId =~ /contentPositions/;
|
||||
$u->profileField($field->getId,$field->formProcess($u));
|
||||
my $field_value = $field->formProcess($u);
|
||||
$u->update({ $field->getId => $field_value} );
|
||||
|
||||
#set the shop address fields
|
||||
my $address_key = $address_mappings->{$field->getId};
|
||||
$address->{$address_key} = $field_value if ($address_key);
|
||||
}
|
||||
|
||||
#Update or create and update the shop address
|
||||
if ( keys %$address ) {
|
||||
$address->{'isProfile' } = 1;
|
||||
|
||||
#Get the address book for the user (one is created if it does not exist)
|
||||
my $addressBook = WebGUI::Shop::AddressBook->newByUserId($session, $actualUserId,);
|
||||
my $profileAddress = eval { $addressBook->getProfileAddress() };
|
||||
|
||||
my $e;
|
||||
if($e = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
|
||||
#Get home address only mappings to avoid creating addresses with just firstName, lastName, email
|
||||
my %home_address_map = %{$address_mappings};
|
||||
delete $home_address_map{qw/firstName lastName email/};
|
||||
#Add the profile address for the user if there are homeAddress fields
|
||||
if( grep { $address->{$_} } values %home_address_map ) {
|
||||
$address->{label} = "Profile Address";
|
||||
my $new_address = $addressBook->addAddress($address);
|
||||
#Set this as the default address if one doesn't already exist
|
||||
my $defaultAddress = eval{ $addressBook->getDefaultAddress };
|
||||
if(WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
|
||||
$addressBook->update( {
|
||||
defaultAddressId => $new_address->getId
|
||||
} );
|
||||
}
|
||||
else {
|
||||
$session->log->warn("The default address exists, and it should not.");
|
||||
}
|
||||
}
|
||||
}
|
||||
elsif ($e = WebGUI::Error->caught) {
|
||||
#Bad stuff happened - log an error but don't fail since this isn't a vital function
|
||||
$session->log->error(
|
||||
q{Could not update Shop Profile Address for user }
|
||||
.$u->username.q{ : }.$e->error
|
||||
);
|
||||
}
|
||||
else {
|
||||
#Update the profile address for the user
|
||||
$profileAddress->update($address);
|
||||
}
|
||||
}
|
||||
|
||||
# Update group assignements
|
||||
my @groups = $session->form->group("groupsToAdd");
|
||||
|
|
|
|||
|
|
@ -88,6 +88,11 @@ property "addressBookId" => (
|
|||
required => 1,
|
||||
);
|
||||
|
||||
property "isProfile" => (
|
||||
noFormPost => 1,
|
||||
required => 0,
|
||||
);
|
||||
|
||||
has [ qw/addressId addressBook/] => (
|
||||
is => 'ro',
|
||||
required => 1,
|
||||
|
|
@ -196,6 +201,10 @@ An email address for this user.
|
|||
|
||||
The organization or company that this user is a part of.
|
||||
|
||||
=head4 isProfile
|
||||
|
||||
Whether or not this address is linked to the user profile. Defaults to 0
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
|
|
@ -357,5 +366,4 @@ sub write {
|
|||
$book->session->db->setRow("address","addressId",$properties);
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ require WebGUI::Asset::Template;
|
|||
use WebGUI::Exception::Shop;
|
||||
use WebGUI::Form;
|
||||
use WebGUI::International;
|
||||
use WebGUI::Shop::Admin;
|
||||
use WebGUI::Shop::Address;
|
||||
use Scalar::Util qw/blessed/;
|
||||
|
||||
|
|
@ -101,7 +102,7 @@ around BUILDARGS => sub {
|
|||
}
|
||||
my ($addressBookId) = $class->_init($session);
|
||||
$properties->{addressBookId} = $addressBookId;
|
||||
$properties->{userId} = $session->user->userId;
|
||||
$properties->{userId} ||= $session->user->userId;
|
||||
return $class->$orig($properties);
|
||||
}
|
||||
my $session = shift;
|
||||
|
|
@ -369,6 +370,55 @@ sub getDefaultAddress {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getProfileAddress ()
|
||||
|
||||
Returns the profile address for this address book if there is one. Otherwise throws a WebGUI::Error::ObjectNotFound exception.
|
||||
|
||||
=cut
|
||||
|
||||
sub getProfileAddress {
|
||||
my ($self) = @_;
|
||||
my $id = $self->session->db->quickScalar(q{ select addressId from address where addressBookId=? and isProfile=1 },[$self->getId]);
|
||||
if (!$id) {
|
||||
WebGUI::Error::ObjectNotFound->throw(error=>"No profile address.");
|
||||
}
|
||||
my $address = eval { $self->getAddress($id) };
|
||||
my $e;
|
||||
if ($e = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
|
||||
$e->rethrow;
|
||||
}
|
||||
elsif ($e = WebGUI::Error->caught) {
|
||||
$e->rethrow;
|
||||
}
|
||||
else {
|
||||
return $address;
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getProfileAddressMappings ( )
|
||||
|
||||
Class or object method which returns the profile address field mappings
|
||||
|
||||
=cut
|
||||
|
||||
sub getProfileAddressMappings {
|
||||
return {
|
||||
homeAddress => 'address1',
|
||||
homeCity => 'city',
|
||||
homeState => 'state',
|
||||
homeZip => 'code',
|
||||
homeCountry => 'country',
|
||||
homePhone => 'phoneNumber',
|
||||
email => 'email',
|
||||
firstName => 'firstName',
|
||||
lastName => 'lastName'
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getId ()
|
||||
|
||||
Returns the unique id for this addressBook.
|
||||
|
|
@ -458,7 +508,9 @@ sub newByUserId {
|
|||
}
|
||||
else {
|
||||
# nope create one for the user
|
||||
return $class->new($session);
|
||||
my $book = $class->new({session => $session, userId => $userId});
|
||||
$book->write;
|
||||
return $book
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -481,19 +533,19 @@ sub processAddressForm {
|
|||
$prefix ||= '';
|
||||
my $form = $self->session->form;
|
||||
my %addressData = (
|
||||
label => $form->get($prefix . "label"),
|
||||
firstName => $form->get($prefix . "firstName"),
|
||||
lastName => $form->get($prefix . "lastName"),
|
||||
address1 => $form->get($prefix . "address1"),
|
||||
address2 => $form->get($prefix . "address2"),
|
||||
address3 => $form->get($prefix . "address3"),
|
||||
city => $form->get($prefix . "city"),
|
||||
state => $form->get($prefix . "state"),
|
||||
code => $form->get($prefix . "code", "zipcode"),
|
||||
country => $form->get($prefix . "country", "country"),
|
||||
phoneNumber => $form->get($prefix . "phoneNumber", "phone"),
|
||||
email => $form->get($prefix . "email", "email"),
|
||||
organization => $form->get($prefix . "organization"),
|
||||
label => $form->get($prefix . "label") || '',
|
||||
firstName => $form->get($prefix . "firstName") || '',
|
||||
lastName => $form->get($prefix . "lastName") || '',
|
||||
address1 => $form->get($prefix . "address1") || '',
|
||||
address2 => $form->get($prefix . "address2") || '',
|
||||
address3 => $form->get($prefix . "address3") || '',
|
||||
city => $form->get($prefix . "city") || '',
|
||||
state => $form->get($prefix . "state") || '',
|
||||
code => $form->get($prefix . "code", "zipcode") || '',
|
||||
country => $form->get($prefix . "country", "country") || '',
|
||||
phoneNumber => $form->get($prefix . "phoneNumber", "phone") || '',
|
||||
email => $form->get($prefix . "email", "email") || '',
|
||||
organization => $form->get($prefix . "organization") || '',
|
||||
);
|
||||
|
||||
##Label is optional in the form, but required for the UI and API.
|
||||
|
|
@ -559,6 +611,80 @@ sub www_ajaxSave {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_ajaxSearch ( )
|
||||
|
||||
Gets a JSON object with addresses returned based on the search
|
||||
parameters from the form.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_ajaxSearch {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
|
||||
my $name = $form->get('name');
|
||||
my $fields = {
|
||||
firstName => (split(" ",$name))[0] || "",
|
||||
lastName => (split(" ",$name))[1] || "",
|
||||
organization => $form->get('organization') || "",
|
||||
address1 => $form->get('address1') || "",
|
||||
address2 => $form->get('address2') || "",
|
||||
address3 => $form->get('address3') || "",
|
||||
city => $form->get('city') || "",
|
||||
state => $form->get('state') || "",
|
||||
code => $form->get('zipcode') || "",
|
||||
country => $form->get('country') || "",
|
||||
email => $form->get('email') || "",
|
||||
phoneNumber => $form->get('phone') || "",
|
||||
};
|
||||
|
||||
my $clause = [];
|
||||
my $params = [];
|
||||
|
||||
foreach my $field (keys %$fields) {
|
||||
my $field_value = $fields->{$field};
|
||||
if($field_value) {
|
||||
$field = $session->db->dbh->quote_identifier($field);
|
||||
$field_value = $field_value."%";
|
||||
push(@$clause,qq{$field like ?});
|
||||
push(@$params,$field_value);
|
||||
}
|
||||
}
|
||||
|
||||
my $admin = WebGUI::Shop::Admin->new($session);
|
||||
unless ($session->user->isAdmin || $admin->canManage || $admin->isCashier) {
|
||||
push(@$clause,qq{users.userId=?});
|
||||
push(@$params,$session->user->getId);
|
||||
}
|
||||
|
||||
my $where = "";
|
||||
$where = "where ".join(" and ",@$clause) if scalar(@$clause);
|
||||
|
||||
my $query = qq{
|
||||
select
|
||||
address.*,
|
||||
users.username
|
||||
from
|
||||
address
|
||||
join addressBook on address.addressBookId = addressBook.addressBookId
|
||||
join users on addressBook.userId = users.userId
|
||||
$where
|
||||
limit 3
|
||||
};
|
||||
|
||||
my $sth = $session->db->read($query,$params);
|
||||
my $var = [];
|
||||
while (my $hash = $sth->hashRef) {
|
||||
push(@$var,$hash);
|
||||
}
|
||||
|
||||
$session->http->setMimeType('text/plain');
|
||||
return JSON->new->encode($var);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_deleteAddress ( )
|
||||
|
||||
Deletes an address from the book.
|
||||
|
|
@ -567,7 +693,10 @@ Deletes an address from the book.
|
|||
|
||||
sub www_deleteAddress {
|
||||
my $self = shift;
|
||||
$self->getAddress($self->session->form->get("addressId"))->delete;
|
||||
my $address = $self->getAddress($self->session->form->get("addressId"));
|
||||
if (defined $address && !$address->isProfile) {
|
||||
$address->delete;
|
||||
}
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
|
|
@ -726,8 +855,20 @@ sub www_editAddressSave {
|
|||
$self->addAddress(\%addressData);
|
||||
}
|
||||
else {
|
||||
$self->getAddress($form->get('addressId'))->update(\%addressData);
|
||||
my $addressId = $form->get('addressId');
|
||||
my $address = $self->getAddress($addressId);
|
||||
$address->update(\%addressData);
|
||||
if($address->isProfile) {
|
||||
my $u = WebGUI::User->new($self->session, $self->get("userId"));
|
||||
my $address_mappings = $self->getProfileAddressMappings;
|
||||
foreach my $field (keys %$address_mappings) {
|
||||
my $addr_field = $address_mappings->{$field};
|
||||
$u->profileField($field,$address->get($addr_field));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#profile fields updated in WebGUI::Shop::Address->update
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
|
|
@ -758,12 +899,12 @@ sub www_view {
|
|||
return $self->www_editAddress;
|
||||
}
|
||||
foreach my $address (@availableAddresses) {
|
||||
|
||||
push(@addresses, {
|
||||
%{$address->get},
|
||||
address => $address->getHtmlFormatted,
|
||||
isDefault => ($self->get('defaultAddressId') eq $address->getId),
|
||||
deleteButton =>
|
||||
WebGUI::Form::formHeader( $session )
|
||||
deleteButton => $address->get("isProfile") ? undef : WebGUI::Form::formHeader( $session )
|
||||
. WebGUI::Form::hidden( $session, { name => 'shop', value => 'address' } )
|
||||
. WebGUI::Form::hidden( $session, { name => 'method', value => 'deleteAddress' } )
|
||||
. WebGUI::Form::hidden( $session, { name => 'addressId', value => $address->getId } )
|
||||
|
|
|
|||
|
|
@ -766,8 +766,11 @@ sub requiresShipping {
|
|||
my $self = shift;
|
||||
|
||||
# Look for recurring items in the cart
|
||||
foreach my $item (@{ $self->getItems }) {
|
||||
return 1 if $item->getSku->isShippingRequired;
|
||||
ITEM: foreach my $item (@{ $self->getItems }) {
|
||||
my $sku = $item->getSku;
|
||||
next ITEM unless $sku;
|
||||
return 1 if $sku->isShippingRequired;
|
||||
|
||||
}
|
||||
|
||||
# No recurring items in cart so return false
|
||||
|
|
@ -1113,6 +1116,13 @@ sub www_view {
|
|||
$self->update({shippingAddressId=>''});
|
||||
}
|
||||
|
||||
#get the billing address
|
||||
my $billingAddress = eval { $self->getBillingAddress };
|
||||
if (my $e = WebGUI::Error->caught("WebGUI::Error::ObjectNotFound") && $self->get('billingAddressId')) {
|
||||
# choose another address cuz we've got a problem
|
||||
$self->update({billingAddressId=>''});
|
||||
}
|
||||
|
||||
# generate template variables for the items in the cart
|
||||
my @items = ();
|
||||
tie my %addressOptions, 'Tie::IxHash';
|
||||
|
|
@ -1274,9 +1284,11 @@ sub www_view {
|
|||
$addressBook->appendAddressFormVars(\%var, 'shipping_', $shippingAddressData);
|
||||
$addressBook->appendAddressFormVars(\%var, 'billing_', $billingAddressData);
|
||||
|
||||
my $has_billing_addr = $self->get('billingAddressId') ? 1 : 0;
|
||||
|
||||
$var{sameShippingAsBilling} = WebGUI::Form::yesNo($session, {
|
||||
name => 'sameShippingAsBilling',
|
||||
value => $self->billingAddressId && $self->billingAddressId eq $self->shippingAddressId,
|
||||
value => (($has_billing_addr && $self->billingAddressId eq $self->shippingAddressId) || !$has_billing_addr),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
240
lib/WebGUI/Shop/PayDriver/CreditCard.pm
Normal file
240
lib/WebGUI/Shop/PayDriver/CreditCard.pm
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
package WebGUI::Shop::PayDriver::CreditCard;
|
||||
|
||||
use strict;
|
||||
use Readonly;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WebGUI::Shop::PayDriver::CreditCard
|
||||
|
||||
=head2 DESCRIPTION
|
||||
|
||||
A base class for credit card payment drivers. They all need pretty much the
|
||||
same information, the only difference is the servers you talk to. Leaves you
|
||||
to handle recurring payments, processPayment, www_edit, and whatever else you
|
||||
want to - but the user-facing code is pretty much taken care of.
|
||||
|
||||
=head2 METHODS
|
||||
|
||||
The following methods are available from this class.
|
||||
|
||||
=cut
|
||||
|
||||
use base qw/WebGUI::Shop::PayDriver/;
|
||||
|
||||
Readonly my $I18N => 'PayDriver_CreditCard';
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub _monthYear {
|
||||
my $session = shift;
|
||||
my $form = $session->form;
|
||||
|
||||
tie my %months, "Tie::IxHash";
|
||||
tie my %years, "Tie::IxHash";
|
||||
%months = map { sprintf( '%02d', $_ ) => sprintf( '%02d', $_ ) } 1 .. 12;
|
||||
%years = map { $_ => $_ } 2004 .. 2099;
|
||||
|
||||
my $monthYear =
|
||||
WebGUI::Form::selectBox( $session, {
|
||||
name => 'expMonth',
|
||||
options => \%months,
|
||||
value => [ $form->process("expMonth") ]
|
||||
})
|
||||
. " / "
|
||||
. WebGUI::Form::selectBox( $session, {
|
||||
name => 'expYear',
|
||||
options => \%years,
|
||||
value => [ $form->process("expYear") ]
|
||||
});
|
||||
|
||||
return $monthYear;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 appendCredentialVars
|
||||
|
||||
Add template vars for www_getCredentials. Override this to add extra fields.
|
||||
|
||||
=cut
|
||||
|
||||
sub appendCredentialVars {
|
||||
my ($self, $var) = @_;
|
||||
my $session = $self->session;
|
||||
my $u = $session->user;
|
||||
my $form = $session->form;
|
||||
my $i18n = WebGUI::International->new($session, $I18N);
|
||||
|
||||
$var->{formHeader} = WebGUI::Form::formHeader($session)
|
||||
. $self->getDoFormTags('pay');
|
||||
|
||||
$var->{formFooter} = WebGUI::Form::formFooter();
|
||||
|
||||
my @fieldLoop;
|
||||
|
||||
# Credit card information
|
||||
$var->{cardNumberField} = WebGUI::Form::text($session, {
|
||||
name => 'cardNumber',
|
||||
value => $self->session->form->process("cardNumber"),
|
||||
});
|
||||
$var->{monthYearField} = WebGUI::Form::readOnly($session, {
|
||||
value => _monthYear( $session ),
|
||||
});
|
||||
$var->{cvv2Field} = WebGUI::Form::integer($session, {
|
||||
name => 'cvv2',
|
||||
value => $self->session->form->process("cvv2"),
|
||||
}) if $self->get('useCVV2');
|
||||
|
||||
$var->{checkoutButton} = WebGUI::Form::submit($session, {
|
||||
value => $i18n->get('checkout button', 'Shop'),
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub definition {
|
||||
my ($class, $session, $definition) = @_;
|
||||
|
||||
my $i18n = WebGUI::International->new($session, $I18N);
|
||||
|
||||
tie my %fields, 'Tie::IxHash', (
|
||||
useCVV2 => {
|
||||
fieldType => 'yesNo',
|
||||
label => $i18n->get('use cvv2'),
|
||||
hoverHelp => $i18n->get('use cvv2 help'),
|
||||
},
|
||||
credentialsTemplateId => {
|
||||
fieldType => 'template',
|
||||
label => $i18n->get('credentials template'),
|
||||
hoverHelp => $i18n->get('credentials template help'),
|
||||
namespace => 'Shop/Credentials',
|
||||
defaultValue => 'itransact_credentials1',
|
||||
},
|
||||
);
|
||||
|
||||
push @{ $definition }, {
|
||||
name => 'Credit Card Base Class',
|
||||
properties => \%fields,
|
||||
};
|
||||
|
||||
return $class->SUPER::definition($session, $definition);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 processCredentials
|
||||
|
||||
Process the form where credentials (name, address, phone number and credit card information)
|
||||
are entered.
|
||||
|
||||
=cut
|
||||
|
||||
sub processCredentials {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
my $i18n = WebGUI::International->new($session, $I18N);
|
||||
my @error;
|
||||
|
||||
# Check credit card data
|
||||
push @error, $i18n->get( 'invalid card number' ) unless $form->integer('cardNumber');
|
||||
push @error, $i18n->get( 'invalid cvv2' ) if ($self->get('useCVV2') && !$form->integer('cvv2'));
|
||||
|
||||
# Check if expDate and expYear have sane values
|
||||
my ($currentYear, $currentMonth) = $self->session->datetime->localtime;
|
||||
my $expires = $form->integer( 'expYear' ) . sprintf '%02d', $form->integer( 'expMonth' );
|
||||
my $now = $currentYear . sprintf '%02d', $currentMonth;
|
||||
|
||||
push @error, $i18n->get('invalid expiration date') unless $expires =~ m{^\d{6}$};
|
||||
push @error, $i18n->get('expired expiration date') unless $expires >= $now;
|
||||
|
||||
return \@error if scalar @error;
|
||||
# Everything ok process the actual data
|
||||
$self->{ _cardData } = {
|
||||
acct => $form->integer( 'cardNumber' ),
|
||||
expMonth => $form->integer( 'expMonth' ),
|
||||
expYear => $form->integer( 'expYear' ),
|
||||
cvv2 => $form->integer( 'cvv2' ),
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_getCredentials ( $errors )
|
||||
|
||||
Build a templated form for asking the user for their credentials.
|
||||
|
||||
=head3 $errors
|
||||
|
||||
An array reference of errors to show the user.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_getCredentials {
|
||||
my $self = shift;
|
||||
my $errors = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
my $i18n = WebGUI::International->new($session, $I18N);
|
||||
my $var = {};
|
||||
|
||||
# Process form errors
|
||||
$var->{errors} = [];
|
||||
if ($errors) {
|
||||
$var->{error_message} = $i18n->get('error occurred message');
|
||||
foreach my $error (@{ $errors} ) {
|
||||
push @{ $var->{errors} }, { error => $error };
|
||||
}
|
||||
}
|
||||
|
||||
$self->appendCredentialVars($var);
|
||||
$self->appendCartVariables($var);
|
||||
|
||||
my $template = WebGUI::Asset::Template->new($session, $self->get("credentialsTemplateId"));
|
||||
my $output;
|
||||
if (defined $template) {
|
||||
$template->prepare;
|
||||
$output = $template->process($var);
|
||||
}
|
||||
else {
|
||||
$output = $i18n->get('template gone');
|
||||
}
|
||||
|
||||
return $session->style->userStyle($output);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_pay
|
||||
|
||||
Makes sure that the user has all the requirements for checking out, including
|
||||
getting credentials, it processes the transaction and then displays a thank
|
||||
you screen.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_pay {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
# Check whether the user filled in the checkout form and process those.
|
||||
my $credentialsErrors = $self->processCredentials;
|
||||
|
||||
# Go back to checkout form if credentials are not ok
|
||||
return $self->www_getCredentials( $credentialsErrors ) if $credentialsErrors;
|
||||
|
||||
# Payment time!
|
||||
my $transaction = $self->processTransaction( );
|
||||
|
||||
if ($transaction->get('isSuccessful')) {
|
||||
return $transaction->thankYou();
|
||||
}
|
||||
|
||||
# Payment has failed...
|
||||
return $self->displayPaymentError($transaction);
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
267
lib/WebGUI/Shop/PayDriver/CreditCard/AuthorizeNet.pm
Normal file
267
lib/WebGUI/Shop/PayDriver/CreditCard/AuthorizeNet.pm
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
package WebGUI::Shop::PayDriver::CreditCard::AuthorizeNet;
|
||||
|
||||
use strict;
|
||||
|
||||
use base qw/WebGUI::Shop::PayDriver::CreditCard/;
|
||||
|
||||
use DateTime;
|
||||
use Readonly;
|
||||
use Business::OnlinePayment;
|
||||
|
||||
Readonly my $I18N => 'PayDriver_AuthorizeNet';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
WebGUI::Shop::PayDriver::CreditCard::AuthorizeNet
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Payment driver that uses Business::OnlinePayment to process transactions
|
||||
through Authorize.net
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
# in webgui config file...
|
||||
|
||||
"paymentDrivers" : [
|
||||
"WebGUI::Shop::PayDriver::Cash",
|
||||
"WebGUI::Shop::PayDriver::CreditCard::AuthorizeNet",
|
||||
...
|
||||
],
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
The following methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 appendCredentialVars ( var )
|
||||
|
||||
Overridden to add the card type field
|
||||
|
||||
=cut
|
||||
|
||||
sub appendCredentialVars {
|
||||
my ( $self, $var ) = @_;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new( $session, $I18N );
|
||||
$self->SUPER::appendCredentialVars($var);
|
||||
|
||||
$var->{cardTypeField} = WebGUI::Form::selectBox(
|
||||
$session, {
|
||||
name => 'cardType',
|
||||
options => { map { $_ => $_ } ( 'Visa', 'MasterCard', 'American Express', 'Discover', ) },
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
} ## end sub appendCredentialVars
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 cancelRecurringPayment ( transaction )
|
||||
|
||||
Cancels a recurring transaction. Returns an array containing ( isSuccess, gatewayStatus, gatewayError).
|
||||
|
||||
=head3 transaction
|
||||
|
||||
The instanciated recurring transaction object.
|
||||
|
||||
=cut
|
||||
|
||||
sub cancelRecurringPayment {
|
||||
my ( $self, $transaction ) = @_;
|
||||
my $session = $self->session;
|
||||
|
||||
my $tx = $self->gatewayObject;
|
||||
$tx->content(
|
||||
subscription => $transaction->get('transactionCode'),
|
||||
login => $self->get('login'),
|
||||
password => $self->get('transaction_key'),
|
||||
action => 'Cancel Recurring Authorization',
|
||||
);
|
||||
$tx->submit;
|
||||
|
||||
return $self->gatewayResponse($tx);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
sub definition {
|
||||
my ( $class, $session, $definition ) = @_;
|
||||
|
||||
my $i18n = WebGUI::International->new( $session, $I18N );
|
||||
|
||||
tie my %fields, 'Tie::IxHash', (
|
||||
login => {
|
||||
fieldType => 'text',
|
||||
label => $i18n->get('login'),
|
||||
hoverHelp => $i18n->get('login help'),
|
||||
},
|
||||
transaction_key => {
|
||||
fieldType => 'text',
|
||||
label => $i18n->get('transaction key'),
|
||||
hoverHelp => $i18n->get('transaction key help'),
|
||||
},
|
||||
testMode => {
|
||||
fieldType => 'YesNo',
|
||||
label => $i18n->get('test mode'),
|
||||
hoverHelp => $i18n->get('test mode help'),
|
||||
},
|
||||
);
|
||||
|
||||
push @{$definition}, {
|
||||
name => $i18n->get('name'),
|
||||
properties => \%fields,
|
||||
};
|
||||
|
||||
return $class->SUPER::definition( $session, $definition );
|
||||
} ## end sub definition
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 gatewayObject ( params )
|
||||
|
||||
Returns a Business::OnlinePayment object, possibly with options set from the
|
||||
paydriver properties. params can be a hashref of the options that would
|
||||
normally be passed to tx->content, in which case these will be passed along.
|
||||
|
||||
=cut
|
||||
|
||||
sub gatewayObject {
|
||||
my ( $self, $params ) = @_;
|
||||
|
||||
my $tx = Business::OnlinePayment->new('AuthorizeNet');
|
||||
if ( $self->get('testMode') ) {
|
||||
|
||||
# Yes, we need to do both these things. The BOP interfaces tend to
|
||||
# ony honor one or the other of them.
|
||||
$tx->test_transaction(1);
|
||||
$tx->server('test.authorize.net');
|
||||
}
|
||||
$tx->content(%$params) if $params;
|
||||
|
||||
return $tx;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 gatewayResponse ( tx )
|
||||
|
||||
Returns the various responses required by the PayDriver interface from the
|
||||
passed Business::OnlinePayment object.
|
||||
|
||||
=cut
|
||||
|
||||
sub gatewayResponse {
|
||||
my ( $self, $tx ) = @_;
|
||||
return ( $tx->is_success, $tx->order_number, $tx->result_code, $tx->error_message );
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub handlesRecurring {1}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 paymentParams
|
||||
|
||||
Returns a hashref of the billing address and card information, translated into
|
||||
a form that Business::OnlinePayment likes
|
||||
|
||||
=cut
|
||||
|
||||
sub paymentParams {
|
||||
my $self = shift;
|
||||
my $card = $self->{_cardData};
|
||||
my $bill = $self->getCart->getBillingAddress->get();
|
||||
|
||||
my %params = (
|
||||
type => $card->{type},
|
||||
login => $self->get('login'),
|
||||
transaction_key => $self->get('transaction_key'),
|
||||
first_name => $bill->{firstName},
|
||||
last_name => $bill->{lastName},
|
||||
address => $bill->{address1},
|
||||
city => $bill->{city},
|
||||
state => $bill->{state},
|
||||
zip => $bill->{code},
|
||||
card_number => $card->{acct},
|
||||
expiration => sprintf '%2d/%2d',
|
||||
@{$card}{ 'expMonth', 'expYear' },
|
||||
);
|
||||
$params{cvv2} = $card->{cvv2} if $self->get('useCVV2');
|
||||
return \%params;
|
||||
} ## end sub paymentParams
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub processCredentials {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $i18n = WebGUI::International->new( $session, $I18N );
|
||||
my $error = $self->SUPER::processCredentials;
|
||||
|
||||
my $type = $session->form->process('cardType');
|
||||
|
||||
unless ($type) {
|
||||
$error ||= [];
|
||||
push @$error, $i18n->get('invalid cardType');
|
||||
}
|
||||
|
||||
return $error if defined $error;
|
||||
|
||||
$self->{_cardData}->{type} = $type;
|
||||
|
||||
return;
|
||||
} ## end sub processCredentials
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
sub processPayment {
|
||||
my ( $self, $transaction ) = @_;
|
||||
my $params = $self->paymentParams;
|
||||
|
||||
if ( $transaction->isRecurring ) {
|
||||
my $items = $transaction->getItems;
|
||||
if ( @$items > 1 ) {
|
||||
WebGUI::Error::InvalidParam->throw(
|
||||
error => 'This payment gateway can only handle one recurring item at a time' );
|
||||
}
|
||||
|
||||
my $item = $items->[0];
|
||||
my $sku = $item->getSku;
|
||||
|
||||
my %translateInterval = (
|
||||
Weekly => '7 days',
|
||||
BiWeekly => '14 days',
|
||||
FourWeekly => '28 days',
|
||||
Monthly => '1 month',
|
||||
Quarterly => '3 months',
|
||||
HalfYearly => '6 months',
|
||||
Yearly => '12 months',
|
||||
);
|
||||
|
||||
# BOP::AuthorizeNet::ARB has an API that's inconsistant with the AIM
|
||||
# api -- it wants password instead of transaction_key. Go figure.
|
||||
$params->{password} = delete $params->{transaction_key};
|
||||
|
||||
$params->{action} = 'Recurring Authorization';
|
||||
$params->{interval} = $translateInterval{ $sku->getRecurInterval };
|
||||
$params->{start} = DateTime->today->ymd;
|
||||
$params->{periods} = '9999'; # magic value that means 'never stop'
|
||||
$params->{description} = $item->get('configuredTitle');
|
||||
} ## end if ( $transaction->isRecurring)
|
||||
else {
|
||||
$params->{action} = 'Normal Authorization';
|
||||
}
|
||||
|
||||
$params->{amount} = $transaction->get('amount');
|
||||
my $tx = $self->gatewayObject($params);
|
||||
$tx->submit;
|
||||
return $self->gatewayResponse($tx);
|
||||
} ## end sub processPayment
|
||||
|
||||
1;
|
||||
|
||||
|
|
@ -1475,8 +1475,8 @@ sub update {
|
|||
delete $properties->{privacyFields};
|
||||
|
||||
# $self->{_user} contains all fields in `users` table
|
||||
my @userFields = ();
|
||||
my @userValues = ();
|
||||
my @userFields = ();
|
||||
my @userValues = ();
|
||||
for my $key ( keys %{$self->{_user}} ) {
|
||||
if ( exists $properties->{$key} ) {
|
||||
# Delete the value because it's not a profile field
|
||||
|
|
@ -1487,15 +1487,16 @@ sub update {
|
|||
}
|
||||
}
|
||||
# No matter what we update properties
|
||||
my $userFields = join ", ", @userFields;
|
||||
my $userFields = join ", ", @userFields;
|
||||
$db->write(
|
||||
"UPDATE users SET $userFields WHERE userId=?",
|
||||
[@userValues, $self->{_userId}]
|
||||
);
|
||||
|
||||
# Everything else must be a profile field
|
||||
my @profileFields = ();
|
||||
my @profileValues = ();
|
||||
my @profileFields = ();
|
||||
my @profileValues = ();
|
||||
|
||||
for my $key ( keys %{$properties} ) {
|
||||
if (!exists $self->{_profile}{$key} && !WebGUI::ProfileField->exists($session,$key)) {
|
||||
$self->session->log->warn("No such profile field: $key");
|
||||
|
|
@ -1506,7 +1507,7 @@ sub update {
|
|||
$self->{_profile}->{$key} = $properties->{ $key };
|
||||
}
|
||||
if ( @profileFields ) {
|
||||
my $profileFields = join ", ", @profileFields;
|
||||
my $profileFields = join ", ", @profileFields;
|
||||
$db->write(
|
||||
"UPDATE userProfileData SET $profileFields WHERE userId=?",
|
||||
[@profileValues, $self->{_userId}]
|
||||
|
|
|
|||
|
|
@ -2307,6 +2307,12 @@ normal templates.|,
|
|||
context => q{Error message when trying to add too many tickets to a badge},
|
||||
},
|
||||
|
||||
'clear form' => {
|
||||
message => q|Clear|,
|
||||
lastUpdated => 0,
|
||||
context => q|a button on the add badge to clear the form|,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
|
|
|
|||
50
lib/WebGUI/i18n/English/PayDriver_AuthorizeNet.pm
Normal file
50
lib/WebGUI/i18n/English/PayDriver_AuthorizeNet.pm
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package WebGUI::i18n::English::PayDriver_AuthorizeNet;
|
||||
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
'cardType' => {
|
||||
message => q{Card Type},
|
||||
lastUpdated => 1101772177,
|
||||
context => q{Form label in the checkout form of the AuthorizeNet module.},
|
||||
},
|
||||
'login' => {
|
||||
message => q{API Login},
|
||||
lastUpdated => 1247613128,
|
||||
context => q{Form label in the configuration form of the AuthorizeNet module.},
|
||||
},
|
||||
'login help' => {
|
||||
message => q{The API login id for your Authorize.net account},
|
||||
lastUpdated => 1247613146,
|
||||
context => q{Hover help for the login field of the AuthorizeNet module},
|
||||
},
|
||||
'name' => {
|
||||
message => q{Credit Card (Authorize.net)},
|
||||
lastUpdated => 0,
|
||||
context => q{Name of the Authorize.net module},
|
||||
},
|
||||
'test mode' => {
|
||||
message => q{Test Mode},
|
||||
lastUpdated => 0,
|
||||
context => q{Form label for test mode toggle in AuthroizeNet module},
|
||||
},
|
||||
'test mode help' => {
|
||||
message => q{Whether calls using this gateway should be made in test mode},
|
||||
lastUpdated => 0,
|
||||
context => q{Hover help for test mode form field},
|
||||
},
|
||||
'transaction key' => {
|
||||
message => q{Transaction Key},
|
||||
lastUpdated => 1247613060,
|
||||
context => q{Form label in the configuration form of the AuthorizeNet module.},
|
||||
},
|
||||
'transaction key help' => {
|
||||
message => q{The Transaction Key for your Authorize.net account},
|
||||
lastUpdated => 1247613119,
|
||||
context => q{Hover help for the password field of the AuthorizeNet module},
|
||||
},
|
||||
};
|
||||
|
||||
1;
|
||||
|
||||
#vim:ft=perl
|
||||
161
lib/WebGUI/i18n/English/PayDriver_CreditCard.pm
Normal file
161
lib/WebGUI/i18n/English/PayDriver_CreditCard.pm
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
package WebGUI::i18n::English::PayDriver_CreditCard;
|
||||
use strict;
|
||||
|
||||
our $I18N = {
|
||||
'cardNumber' => {
|
||||
message => q|Credit card number|,
|
||||
lastUpdated => 1101772177,
|
||||
context => q|Form label in the checkout form of the Credit Card module.|
|
||||
},
|
||||
'credentials template' => {
|
||||
message => q|Credentials Template|,
|
||||
lastUpdated => 0,
|
||||
context => q|Form label in the configuration form of the Credit Card module.|
|
||||
},
|
||||
'credentials template help' => {
|
||||
message => q|Pick a template to display the form where the user will enter in their billing information and credit card information.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Hover help for the credentials template field in the configuration form of the Credit Card module.|
|
||||
},
|
||||
'cvv2' => {
|
||||
message => q|Verification number (ie. CVV2)|,
|
||||
lastUpdated => 1101772182,
|
||||
context => q|Form label in the checkout form of the Credit Card module.|
|
||||
},
|
||||
'error occurred message' => {
|
||||
message => q|The following errors occurred:|,
|
||||
lastUpdated => 0,
|
||||
context => q|The message that tell the user that there were some errors in their submitted credentials.|,
|
||||
},
|
||||
'expiration date' => {
|
||||
message => q|Expiration date|,
|
||||
lastUpdated => 1101772180,
|
||||
context => q|Form label in the checkout form of the Credit Card module.|
|
||||
},
|
||||
'expired expiration date' => {
|
||||
message => q|The expiration date on your card has already passed.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an an expired card was used.|
|
||||
},
|
||||
'invalid firstName' => {
|
||||
message => q|You have to enter a valid first name.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid first name has been entered.|
|
||||
},
|
||||
'invalid lastName' => {
|
||||
message => q|You have to enter a valid last name.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid last name has been entered.|
|
||||
},
|
||||
'invalid address' => {
|
||||
message => q|You have to enter a valid address.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid street has been entered.|
|
||||
},
|
||||
'invalid city' => {
|
||||
message => q|You have to enter a valid city.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid city has been entered.|
|
||||
},
|
||||
'invalid zip' => {
|
||||
message => q|You have to enter a valid zipcode.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid zipcode has been entered.|
|
||||
},
|
||||
'invalid email' => {
|
||||
message => q|You have to enter a valid email address.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid email address has been entered.|
|
||||
},
|
||||
'invalid card number' => {
|
||||
message => q|You have to enter a valid credit card number.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid credit card number has been entered.|
|
||||
},
|
||||
'invalid cvv2' => {
|
||||
message => q|You have to enter a valid card security code (ie. cvv2).|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid card security code has been entered.|
|
||||
},
|
||||
'invalid expiration date' => {
|
||||
message => q|You have to enter a valid expiration date.|,
|
||||
lastUpdated => 0,
|
||||
context => q|An error indicating that an invalid expiration date has been entered.|
|
||||
},
|
||||
'template gone' => {
|
||||
message => q|The template for entering in credentials has been deleted. Please notify the site administrator.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Error message when the getCredentials template cannot be accessed.|
|
||||
},
|
||||
'use cvv2' => {
|
||||
message => q|Use CVV2|,
|
||||
lastUpdated => 0,
|
||||
context => q|Form label in the configuration form of the Credit Card module.|
|
||||
},
|
||||
'use cvv2 help' => {
|
||||
message => q|Set this option to yes if you want to use CVV2.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Form label in the configuration form of the Credit Card module.|
|
||||
},
|
||||
|
||||
'edit credentials template' => {
|
||||
message => q|Edit Credentials Template|,
|
||||
lastUpdated => 0,
|
||||
context => q|Title of the help page.|
|
||||
},
|
||||
'edit credentials template help' => {
|
||||
message => q|This template is used to display a form to the user where they can enter in contact and credit card billing information.|,
|
||||
lastUpdated => 0,
|
||||
context => q|Title of the help page.|
|
||||
},
|
||||
|
||||
'errors help' => {
|
||||
message => q{A template loop containing a list of errors from processing the form.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'error help' => {
|
||||
message => q{One error from the errors loop. It will have minimal markup.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'addressField help' => {
|
||||
message => q{A single text field for the user to enter in their street address.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'emailField help' => {
|
||||
message => q{A single text field for the user to enter in their email address.},
|
||||
lastUpdated => 1231192368,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'cardNumberField help' => {
|
||||
message => q{A single text field for the user to enter in their credit card number.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'monthYearField help' => {
|
||||
message => q{A combination form field for the user to enter in the month and year of the expiration date for the credit card.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'cvv2Field help' => {
|
||||
message => q{A single text field for the user to enter in their credit card verification number. If the PayDriver is not configured to use CVV2, then this field will be empty.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
'checkoutButton help' => {
|
||||
message => q{A button with an internationalized label to submit the form and continue the checkout process.},
|
||||
lastUpdated => 0,
|
||||
context => q{Template variable help.},
|
||||
},
|
||||
|
||||
'fields help' => {
|
||||
message => q{A loop of all the available fields for convenience. Each
|
||||
entry in the loop contains name (field name), label (an internationalized
|
||||
label for the field), and field (the same as in stateField, cityField, etc).},
|
||||
lastUpdated => 0,
|
||||
},
|
||||
};
|
||||
|
||||
1;
|
||||
Loading…
Add table
Add a link
Reference in a new issue