Note that now, all transactions are logged, whether they fail or not. Failed transactions are logged with status canceled. ITransact transactions have additional data logged.
1363 lines
50 KiB
Perl
1363 lines
50 KiB
Perl
package WebGUI::Operation::Commerce;
|
|
|
|
use strict;
|
|
use WebGUI::SQL;
|
|
use WebGUI::Commerce::Transaction;
|
|
use WebGUI::Commerce::ShoppingCart;
|
|
use WebGUI::Commerce::Payment;
|
|
use WebGUI::Commerce::Shipping;
|
|
use WebGUI::AdminConsole;
|
|
use WebGUI::TabForm;
|
|
use WebGUI::Commerce;
|
|
use WebGUI::Operation;
|
|
use WebGUI::Operation::Shared;
|
|
use WebGUI::International;
|
|
use WebGUI::Asset::Template;
|
|
use WebGUI::Paginator;
|
|
use WebGUI::Form;
|
|
use WebGUI::Utility;
|
|
use Storable;
|
|
use Locale::US;
|
|
use Tie::IxHash;
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _submenu ( $session )
|
|
|
|
Returns a rendered Admin Console view, with a standard list of five submenu items.
|
|
|
|
=head3 $session
|
|
|
|
The current WebGUI session object.
|
|
|
|
=head3 workarea
|
|
|
|
A scalar of HTML that defines the current workarea.
|
|
|
|
=head3 title
|
|
|
|
The i18n key of the title of this workarea.
|
|
|
|
=cut
|
|
|
|
sub _submenu {
|
|
my $session = shift;
|
|
my $i18n = WebGUI::International->new($session, "Commerce");
|
|
my $workarea = shift;
|
|
my $title = shift;
|
|
$title = $i18n->get($title) if ($title);
|
|
my $ac = WebGUI::AdminConsole->new($session,"commerce");
|
|
$ac->addSubmenuItem($session->url->page('op=editCommerceSettings'), $i18n->get('manage commerce settings'));
|
|
$ac->addSubmenuItem($session->url->page('op=listTransactions'), $i18n->get('list transactions'));
|
|
$ac->addSubmenuItem($session->url->page('op=listPendingTransactions'), $i18n->get('list pending transactions'));
|
|
return $ac->render($workarea, $title);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _clearCheckoutScratch ( $session )
|
|
|
|
A wrapper around _clearShippingScratch and _clearPaymentScratch.
|
|
|
|
=cut
|
|
|
|
sub _clearCheckoutScratch {
|
|
my $session = shift;
|
|
_clearShippingScratch($session);
|
|
_clearPaymentScratch($session);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _clearPaymentScratch ( $session )
|
|
|
|
Clears the C<paymentGateway> scratch variable.
|
|
|
|
=cut
|
|
|
|
sub _clearPaymentScratch {
|
|
my $session = shift;
|
|
$session->scratch->delete('paymentGateway');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _clearShippingScratch ( $session )
|
|
|
|
Clear the C<shippingMethod> and C<shippingOptions> scratch variables.
|
|
|
|
=cut
|
|
|
|
sub _clearShippingScratch {
|
|
my $session = shift;
|
|
$session->scratch->delete('shippingMethod');
|
|
$session->scratch->delete('shippingOptions');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _paymentSelected ( $session )
|
|
|
|
A utility method to tell if the C<paymentGateway> scratch variable is
|
|
set, that it points to a valid payment plugin that can be loaded and
|
|
is enabled.
|
|
|
|
=cut
|
|
|
|
sub _paymentSelected {
|
|
my $session = shift;
|
|
return 0 unless ($session->scratch->get('paymentGateway'));
|
|
my $plugin = WebGUI::Commerce::Payment->load($session, $session->scratch->get('paymentGateway'));
|
|
return 1 if ($plugin && $plugin->enabled);
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _shippingSelected ( $session )
|
|
|
|
|
|
A utility method to tell if the C<shippingMethod> scratch variable is
|
|
set, that it points to a valid shipping plugin that can be loaded and
|
|
is enabled and whose C<optionsOk> method returns true.
|
|
|
|
=cut
|
|
|
|
sub _shippingSelected {
|
|
my $session = shift;
|
|
return 0 unless ($session->scratch->get('shippingMethod'));
|
|
|
|
my $plugin = WebGUI::Commerce::Shipping->load($session, $session->scratch->get('shippingMethod'));
|
|
if ($plugin) {
|
|
$plugin->setOptions(Storable::thaw($session->scratch->get('shippingOptions'))) if ($session->scratch->get('shippingOptions'));
|
|
return 1 if ($plugin->enabled && $plugin->optionsOk);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 _validateState ( $state )
|
|
|
|
A utility method to tell if $state is a valid US state for determining
|
|
sales tax. Returns either the name of a US state in ALL CAPS or '' if
|
|
it isn't a valid US state.
|
|
|
|
=cut
|
|
|
|
sub _validateState {
|
|
my $state = shift;
|
|
$state = uc($state);
|
|
my $stateObj = Locale::US->new;
|
|
if (exists $stateObj->{code2state}->{$state}) {
|
|
##An abbreviation was used, translate back to state name
|
|
$state = $stateObj->{code2state}->{$state};
|
|
}
|
|
##Next, we validate the state. If it isn't a valid US state, null out
|
|
##the state field so we don't do sales tax.
|
|
$state = '' unless exists $stateObj->{state2code}->{$state};
|
|
return $state;
|
|
}
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
=head2 canView ( session [, user] )
|
|
|
|
Returns true if the user can administrate this operation. user defaults to
|
|
the current user.
|
|
|
|
=cut
|
|
|
|
sub canView {
|
|
my $session = shift;
|
|
my $user = shift || $session->user;
|
|
return $user->isInGroup( $session->setting->get("groupIdAdminCommerce") );
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_addToCart ( $session )
|
|
|
|
Adds the requested item to the user's shopping cart and creates a cart if necessary.
|
|
|
|
Uses these form variables:
|
|
|
|
=over 4
|
|
|
|
=item C<itemId>
|
|
|
|
The id of the item to add.
|
|
|
|
=item C<itemType>
|
|
|
|
The type (namespace) of the item that's to be added to the cart.
|
|
|
|
=item C<quantity>
|
|
|
|
The number of items to add. Defaults to 1 if quantity is not given.
|
|
|
|
=back
|
|
|
|
=cut
|
|
|
|
sub www_addToCart {
|
|
my $session = shift;
|
|
WebGUI::Commerce::ShoppingCart->new($session)->add($session->form->process("itemId"), $session->form->process("itemType","className"), $session->form->process("quantity"));
|
|
return WebGUI::Operation::execute($session,'viewCart');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_cancelTransaction ( $session )
|
|
|
|
Cancel the transaction described by the form varialbe C<tid> if the
|
|
transaction status is C<Completed>. Display an internationalized
|
|
message to the user using the C<commerceCheckoutCanceledTemplateId> template from the site settings.
|
|
|
|
=cut
|
|
|
|
sub www_cancelTransaction {
|
|
my $session = shift;
|
|
my ($transaction, %var);
|
|
|
|
$transaction = WebGUI::Commerce::Transaction->new($session, $session->form->process("tid"));
|
|
unless ($transaction->status eq 'Completed') {
|
|
$transaction->cancelTransaction;
|
|
}
|
|
|
|
my $i18n = WebGUI::International->new($session, 'Commerce');
|
|
$var{message} = $i18n->get('checkout canceled message');
|
|
|
|
return $session->style->userStyle(WebGUI::Asset::Template->new($session,$session->setting->get("commerceCheckoutCanceledTemplateId"))->process(\%var));
|
|
}
|
|
|
|
# This operation is here for easier future extensions to the commerce system.
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_checkout ( $session )
|
|
|
|
A wrapper around the selectShippingMethod, selectPaymentGateway and
|
|
checkoutConform methods. selectShippingMethod and selectPaymentGateway
|
|
are only executed if their respective scratch variables are not set.
|
|
|
|
=cut
|
|
|
|
sub www_checkout {
|
|
my $session = shift;
|
|
return WebGUI::Operation::execute($session,'selectShippingMethod') unless (_shippingSelected($session));
|
|
|
|
return WebGUI::Operation::execute($session,'selectPaymentGateway') unless (_paymentSelected($session));
|
|
|
|
return WebGUI::Operation::execute($session,'checkoutConfirm');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_checkoutConfirm ( $session )
|
|
|
|
Show the user the contents of their shopping cart and a button to pay for the contents. Form
|
|
controls are provided to delete items from the cart, change quantities on items, and to
|
|
change payment and shipping plugins. All information is placed in variables and styled
|
|
using the C<commerceConfirmCheckoutTemplateId> template.
|
|
|
|
If no plugins have been chosen yet, then they are redirected back to www_checkout.
|
|
|
|
If the user continues, the next sub called is www_checkoutSubmit.
|
|
|
|
=cut
|
|
|
|
sub www_checkoutConfirm {
|
|
my $session = shift;
|
|
my ($plugin, $f, %var, $errors, $i18n, $shoppingCart, $normal, $recurring, $shipping, $total, $subTotal);
|
|
$errors = shift;
|
|
my $inVars = shift;
|
|
%var = %{$inVars} if (defined $inVars);
|
|
|
|
$i18n = WebGUI::International->new($session, 'Commerce');
|
|
|
|
# If the user isn't logged in yet, let him do so or have him create an account
|
|
if ($session->user->userId eq '1') {
|
|
$session->scratch->set('redirectAfterLogin', $session->url->page('op=checkout'));
|
|
return WebGUI::Operation::execute($session,'auth');
|
|
}
|
|
|
|
# If no payment gateway has been selected yet, have the user do so now.
|
|
return WebGUI::Operation::execute($session,'checkout') unless (_paymentSelected($session) && _shippingSelected($session));
|
|
|
|
$var{errorLoop} = [ map {{message => $_}} @{$errors} ] if $errors;
|
|
|
|
my $enableSalesTax = $var{useSalesTax} = $session->setting->get('commerceEnableSalesTax');
|
|
my $salesTaxRate = 0;
|
|
my $state = $session->form->process('state') || $session->user->profileField('homeState');
|
|
$state = _validateState($state);
|
|
if ($state and $enableSalesTax) {
|
|
($salesTaxRate) = $session->db->quickArray("select salesTax from commerceSalesTax where regionIdentifier=?",[$state]);
|
|
}
|
|
$var{salesTaxRate} = sprintf "%6.4f%%", $salesTaxRate;
|
|
$salesTaxRate /= 100; ##convert from percent to float
|
|
|
|
# Put contents of cart in template vars
|
|
$shoppingCart = WebGUI::Commerce::ShoppingCart->new($session);
|
|
($normal, $recurring) = $shoppingCart->getItems($salesTaxRate);
|
|
my @copyOfNormal = @$normal;
|
|
my $totalSalesTax = 0;
|
|
##Note, if the special casing in the normal loop can be pushed back into the item,
|
|
##then the loops can be combined and collapsed.
|
|
foreach (@$normal) {
|
|
my $amount;
|
|
$_->{deleteIcon} = $session->icon->delete('op=deleteCartItem;itemId='.$_->{item}->id.';itemType='.$_->{item}->type);
|
|
$_->{'quantity.form'} = WebGUI::Form::integer($session,{
|
|
name => 'quantity~'.$_->{item}->type.'~'.$_->{item}->id,
|
|
value => $_->{quantity},
|
|
size => 3,
|
|
});
|
|
my $priceLineItem = ($_->{item}->{priceLineItem}) ? ($_->{item}->priceLineItem($_->{quantity},\@copyOfNormal)) : undef; # pass in the quantity and the normal items in the cart.
|
|
# use the item plugin's lineItem method for price override
|
|
# situations.
|
|
$amount = ($priceLineItem ne "") ? ($priceLineItem) : ($_->{totalPrice});
|
|
if ($priceLineItem ne "") { ##There was a discount, fix the amount and tax
|
|
$amount = $priceLineItem;
|
|
$_->{salesTax} = sprintf "%.2f", $priceLineItem * $salesTaxRate * $_->{item}->useSalesTax;
|
|
}
|
|
else {
|
|
$amount = $_->{totalPrice};
|
|
}
|
|
$_->{item}->{price} = $amount;
|
|
$total += $amount; # tracks discount
|
|
$subTotal += $_->{totalPrice}; # ignores discount (we need this to show them an accurate subtotal and to calculate the discount given.)
|
|
$totalSalesTax += $_->{salesTax};
|
|
}
|
|
foreach (@$recurring) {
|
|
$_->{deleteIcon} = $session->icon->delete('op=deleteCartItem;itemId='.$_->{item}->id.';itemType='.$_->{item}->type);
|
|
$_->{'quantity.form'} = WebGUI::Form::integer($session,{
|
|
name => 'quantity~'.$_->{item}->type.'~'.$_->{item}->id,
|
|
value => $_->{quantity},
|
|
size => 3,
|
|
});
|
|
$total += $_->{totalPrice};
|
|
$totalSalesTax += $_->{salesTax};
|
|
}
|
|
|
|
$var{normalItemsLoop} = $normal;
|
|
$var{normalItems} = scalar(@$normal);
|
|
$var{recurringItemsLoop} = $recurring;
|
|
$var{recurringItems} = scalar(@$recurring);
|
|
|
|
$var{subTotal} = sprintf('%.2f', $subTotal);
|
|
$var{totalSalesTax} = sprintf('%.2f', $totalSalesTax);
|
|
|
|
$shipping = WebGUI::Commerce::Shipping->load($session, $session->scratch->get('shippingMethod'));
|
|
$shipping->setOptions(Storable::thaw($session->scratch->get('shippingOptions'))) if ($session->scratch->get('shippingOptions'));
|
|
$var{shippingName} = $shipping->name;
|
|
$var{shippingCost} = sprintf('%.2f', $shipping->calc);
|
|
|
|
$var{total} = sprintf('%.2f', $total + $shipping->calc + $totalSalesTax);
|
|
|
|
$var{discountsApplied} = sprintf('%.2f', $total - $subTotal - $shipping->calc);
|
|
$var{'discountsApplied.label'} = $i18n->echo("Discount Applied");
|
|
$plugin = WebGUI::Commerce::Payment->load($session, $session->scratch->get('paymentGateway'));
|
|
|
|
$f = WebGUI::HTMLForm->new($session);
|
|
$f->hidden(
|
|
-name => 'op',
|
|
-value => 'checkoutSubmit'
|
|
);
|
|
$f->raw($plugin->checkoutForm);
|
|
$f->submit(value=>$i18n->get('pay button'));
|
|
|
|
$var{form} = $f->print;
|
|
$var{title} = $i18n->get('checkout confirm title');
|
|
|
|
$var{'changePayment.url'} = $session->url->page('op=selectPaymentGateway');
|
|
$var{'changePayment.label'} = $i18n->get('change payment gateway');
|
|
|
|
my $plugins = WebGUI::Commerce::Shipping->getEnabledPlugins($session);
|
|
if (scalar(@$plugins) > 1) {
|
|
$var{'changeShipping.url'} = $session->url->page('op=selectShippingMethod');
|
|
$var{'changeShipping.label'} = $i18n->get('change shipping method');
|
|
$var{'hasMultipleShipping'} = "true";
|
|
}
|
|
|
|
$var{'viewShoppingCart.url'} = $session->url->page('op=viewCart');
|
|
$var{'viewShoppingCart.label'} = $i18n->get('view shopping cart');
|
|
|
|
return $session->style->userStyle(WebGUI::Asset->newByDynamicClass($session,$session->setting->get("commerceConfirmCheckoutTemplateId"))->process(\%var));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_checkoutSubmit ( $session )
|
|
|
|
This is the real, final checkout routine. Requires that the user be logged in and have
|
|
valid Shipping and Payment plugins set.
|
|
|
|
Processes all transactions using the appropriate method for each one, and then return
|
|
any templated errors via C<commerceTransactionErrorTemplateId>.
|
|
|
|
If everything is okay, clears all scratch variables and returns the user to the
|
|
C<viewPurchaseHistory> operation.
|
|
|
|
=cut
|
|
|
|
sub www_checkoutSubmit {
|
|
my $session = shift;
|
|
my ($plugin, $shoppingCart, $transaction, $var, $amount, @cartItems, $i18n, @transactions,
|
|
@normal, $checkoutError, @resultLoop, %param, $normal, $recurring,
|
|
$formError, $shipping, $shippingCost, $shippingDescription);
|
|
|
|
$i18n = WebGUI::International->new($session, 'Commerce');
|
|
|
|
# check if user has already logged in
|
|
if ($session->user->userId eq '1') {
|
|
$session->scratch->set('redirectAfterLogin', $session->url->page('op=checkout'));
|
|
return WebGUI::Operation::execute($session,'auth');
|
|
}
|
|
|
|
# Check if a valid payment gateway has been selected. If not have the user do so.
|
|
return WebGUI::Operation::execute($session,'checkout') unless (_paymentSelected($session) && _shippingSelected($session));
|
|
|
|
# Load shipping plugin.
|
|
$shipping = WebGUI::Commerce::Shipping->load($session, $session->scratch->get('shippingMethod'));
|
|
$shipping->setOptions(Storable::thaw($session->scratch->get('shippingOptions'))) if ($session->scratch->get('shippingOptions'));
|
|
|
|
# Load payment plugin.
|
|
$plugin = WebGUI::Commerce::Payment->load($session, $session->scratch->get('paymentGateway'));
|
|
$shoppingCart = WebGUI::Commerce::ShoppingCart->new($session);
|
|
my $enableSalesTax = $session->setting->get('commerceEnableSalesTax');
|
|
my $state = $session->form->process('state') || $session->user->profileField('homeState');
|
|
$state = _validateState($state);
|
|
my $salesTaxRate = 0;
|
|
if ($state and $enableSalesTax) {
|
|
($salesTaxRate) = $session->db->quickArray("select salesTax from commerceSalesTax where regionIdentifier=?",[$state]);
|
|
}
|
|
$salesTaxRate /= 100; ##convert from percent to float
|
|
($normal, $recurring) = $shoppingCart->getItems($salesTaxRate);
|
|
my @copyOfNormal = @$normal;
|
|
# Check if shoppingcart contains any items. If not the user probably clicked reload, so we redirect to the current page.
|
|
unless (@$normal || @$recurring) {
|
|
$session->http->setRedirect($session->url->page);
|
|
return undef;
|
|
}
|
|
|
|
# check submitted form params
|
|
$formError = $plugin->validateFormData;
|
|
return www_checkoutConfirm($session,$formError) if ($formError);
|
|
|
|
# Combine all non recurring item in one transaction and combine with all recurring ones
|
|
map {push(@transactions, {recurring => 1, items => [$_]})} @$recurring;
|
|
push(@transactions, {recurring => 0, items => [@$normal]}) if (@$normal);
|
|
|
|
foreach my $currentPurchase (@transactions) {
|
|
$amount = 0;
|
|
$var = {};
|
|
|
|
$shipping->setShippingItems($currentPurchase->{items});
|
|
$shippingCost = $shipping->calc;
|
|
$shippingDescription = $shipping->description;
|
|
|
|
$plugin->shippingCost($shippingCost);
|
|
$plugin->shippingDescription($shippingDescription);
|
|
|
|
# Write transaction to the log with status pending
|
|
$transaction = WebGUI::Commerce::Transaction->new($session, 'new');
|
|
|
|
my $salesTaxTotal = 0;
|
|
foreach (@{$currentPurchase->{items}}) {
|
|
my $priceLineItem = ($_->{item}->{priceLineItem}) ? ($_->{item}->priceLineItem($_->{quantity},\@copyOfNormal)) : undef; # pass in the quantity and the normal items in the cart.
|
|
$transaction->addItem($_->{item}, $_->{quantity},$priceLineItem);
|
|
# use the item plugin's lineItem method for price override
|
|
# situations.
|
|
$amount += ($priceLineItem ne "")? $priceLineItem :
|
|
($_->{item}->price * $_->{quantity});
|
|
$var->{purchaseDescription} .= $_->{quantity}.' x '.$_->{item}->name.'<br />';
|
|
$salesTaxTotal += $_->{salesTax};
|
|
}
|
|
# Oy, the kludge.
|
|
$transaction->addItem(WebGUI::Commerce::Item::Fake->new($session, $salesTaxTotal.',Sales Tax'), 1, $salesTaxTotal);
|
|
$transaction->shippingCost($shippingCost);
|
|
$transaction->shippingMethod($shipping->namespace);
|
|
$transaction->shippingOptions($shipping->getOptions);
|
|
$transaction->shippingStatus('NotSent');
|
|
|
|
$var->{purchaseAmount} = sprintf('%.2f', $amount);
|
|
|
|
# submit
|
|
if ($currentPurchase->{recurring}) {
|
|
$transaction->isRecurring(1);
|
|
$plugin->recurringTransaction({
|
|
amount => $amount,
|
|
id => $transaction->transactionId,
|
|
term => 0,
|
|
payPeriod => $currentPurchase->{items}->[0]->{item}->duration,
|
|
profilename => $currentPurchase->{items}->[0]->{item}->name,
|
|
checkCard => 1,
|
|
});
|
|
} else {
|
|
$plugin->normalTransaction({
|
|
amount => $amount,
|
|
id => $transaction->transactionId,
|
|
});
|
|
}
|
|
|
|
$transaction->gatewayId($plugin->gatewayId);
|
|
$transaction->gateway($plugin->namespace);
|
|
|
|
##New transaction logging code for ITransact module
|
|
##goes here.
|
|
$plugin->logExtraTransactionData($transaction);
|
|
|
|
# check transaction result
|
|
unless ($plugin->connectionError) {
|
|
unless ($plugin->transactionError) {
|
|
$transaction->completeTransaction if ($plugin->transactionCompleted);
|
|
$var->{status} = $i18n->get('ok');
|
|
} elsif ($plugin->transactionPending) {
|
|
$checkoutError = 1;
|
|
$var->{status} = $i18n->get('pending');
|
|
$var->{error} = $plugin->transactionError;
|
|
$var->{errorCode} = $plugin->errorCode;
|
|
} else {
|
|
$checkoutError = 1;
|
|
$var->{status} = $i18n->get('transaction error');
|
|
$var->{error} = $plugin->transactionError;
|
|
$var->{errorCode} = $plugin->errorCode;
|
|
$transaction->status('Canceled');
|
|
#$transaction->delete;
|
|
}
|
|
} else {
|
|
$checkoutError = 1;
|
|
$var->{status} = $i18n->get('connection error');
|
|
$var->{error} = $plugin->connectionError;
|
|
$var->{errorCode} = $plugin->errorCode;
|
|
$transaction->status('Canceled');
|
|
#$transaction->delete;
|
|
}
|
|
|
|
push(@resultLoop, $var);
|
|
}
|
|
|
|
if($checkoutError) {
|
|
$param{'title' } = $i18n->get('transaction error title');
|
|
$param{'statusExplanation'} = $i18n->get('status codes information');
|
|
$param{'resultLoop' } = \@resultLoop;
|
|
$param{'purchaseError' } = "true";
|
|
return www_checkoutConfirm($session,undef,\%param);
|
|
}
|
|
|
|
#Empty shopping cart
|
|
$shoppingCart->empty;
|
|
#Clear Checkout Scratch
|
|
_clearCheckoutScratch($session);
|
|
|
|
# If everythings ok show the purchase history
|
|
return WebGUI::Operation::TransactionLog::www_viewPurchaseHistory($session);
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_completePendingTransaction ( $session )
|
|
|
|
Completes the transaction specified in the form variable C<tid> by calling
|
|
WebGUI::Commerce::Transaction->completeTransaction. Returns the user
|
|
to the C<listPendingTransactions> operation.
|
|
|
|
=cut
|
|
|
|
sub www_completePendingTransaction {
|
|
my $session = shift;
|
|
return $session->privilege->adminOnly unless canView($session);
|
|
|
|
WebGUI::Commerce::Transaction->new($session, $session->form->process("tid"))->completeTransaction;
|
|
|
|
return WebGUI::Operation::execute($session,'listPendingTransactions');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_confirmRecurringTransaction ( $session )
|
|
|
|
Using the Payment plugin from the C<gateway> form variable and attempts to complete a
|
|
recurring transaction, but only if the plugin is valid.
|
|
|
|
=cut
|
|
|
|
sub www_confirmRecurringTransaction {
|
|
my $session = shift;
|
|
my($plugin, %var);
|
|
|
|
$plugin = WebGUI::Commerce::Payment->load($session, $session->form->process("gateway","className"));
|
|
if ($plugin) {
|
|
$plugin->confirmRecurringTransaction;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_confirmTransaction ( $session )
|
|
|
|
Using the Payment plugin from the C<pg> form variable and attempts to complete the
|
|
transaction, but only if the plugin's C<confirmTransaction> returns true.
|
|
|
|
=cut
|
|
|
|
sub www_confirmTransaction {
|
|
my $session = shift;
|
|
my $plugin = WebGUI::Commerce::Payment->load($session, $session->form->process("pg","className"));
|
|
|
|
if ($plugin->confirmTransaction) {
|
|
WebGUI::Commerce::Transaction->new($session, $plugin->getTransactionId)->completeTransaction;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_deleteCartItem ( $session )
|
|
|
|
Delete an item, C<itemId>, from the user's cart. Returns the user to
|
|
the C<viewCart> operation.
|
|
|
|
=cut
|
|
|
|
sub www_deleteCartItem {
|
|
my $session = shift;
|
|
WebGUI::Commerce::ShoppingCart->new($session)->delete($session->form->process("itemId"), $session->form->process("itemType"));
|
|
|
|
return WebGUI::Operation::execute($session,'viewCart');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_editCommerceSettings ( $session )
|
|
|
|
Site wide setting for commerce, including payment plugins, shipping plugins
|
|
and templates.
|
|
|
|
Calls C<www_editCommerceSettingsSave> on form submission.
|
|
|
|
=cut
|
|
|
|
sub www_editCommerceSettings {
|
|
my $session = shift;
|
|
my (%tabs, $tabform, $ac, $jscript, $i18n,
|
|
$paymentPlugin, @paymentPlugins, %paymentPlugins, @failedPaymentPlugins, $plugin,
|
|
$shippingPlugin, @shippingPlugins, %shippingPlugins, @failedShippingPlugins);
|
|
return $session->privilege->adminOnly unless canView($session);
|
|
|
|
$i18n = WebGUI::International->new($session, 'Commerce');
|
|
|
|
tie %tabs, 'Tie::IxHash';
|
|
%tabs = (
|
|
general=>{label=>$i18n->get('general tab')},
|
|
payment=>{label=>$i18n->get('payment tab')},
|
|
shipping=>{label=>$i18n->get('shipping tab')},
|
|
salesTax=>{label=>$i18n->get('salesTax tab')},
|
|
);
|
|
|
|
$paymentPlugin = $session->config->get("paymentPlugins")->[0];
|
|
$shippingPlugin = $session->config->get("shippingPlugins")->[0];
|
|
|
|
$tabform = WebGUI::TabForm->new($session,\%tabs);
|
|
$tabform->hidden({name => 'op', value => 'editCommerceSettingsSave'});
|
|
|
|
# general
|
|
$tabform->getTab('general')->template(
|
|
-name => 'commerceConfirmCheckoutTemplateId',
|
|
-label => $i18n->get('confirm checkout template'),
|
|
-hoverHelp => $i18n->get('confirm checkout template description'),
|
|
-value => $session->setting->get("commerceConfirmCheckoutTemplateId"),
|
|
-namespace => 'Commerce/ConfirmCheckout'
|
|
);
|
|
$tabform->getTab('general')->template(
|
|
-name => 'commercePurchaseHistoryTemplateId',
|
|
-label => $i18n->get('purchase history template'),
|
|
-hoverHelp => $i18n->get('purchase history template description'),
|
|
-value => $session->setting->get('commercePurchaseHistoryTemplateId'),
|
|
-namespace => 'Commerce/ViewPurchaseHistory'
|
|
);
|
|
$tabform->getTab('general')->template(
|
|
-name => 'commerceCheckoutCanceledTemplateId',
|
|
-label => $i18n->get('checkout canceled template'),
|
|
-hoverHelp => $i18n->get('checkout canceled template description'),
|
|
-value => $session->setting->get("commerceCheckoutCanceledTemplateId"),
|
|
-namespace => 'Commerce/CheckoutCanceled'
|
|
);
|
|
$tabform->getTab('general')->template(
|
|
-name => 'commerceSelectPaymentGatewayTemplateId',
|
|
-label => $i18n->get('checkout select payment template'),
|
|
-hoverHelp => $i18n->get('checkout select payment template description'),
|
|
-value => $session->setting->get("commerceSelectPaymentGatewayTemplateId"),
|
|
-namespace => 'Commerce/SelectPaymentGateway'
|
|
);
|
|
$tabform->getTab('general')->template(
|
|
-name => 'commerceSelectShippingMethodTemplateId',
|
|
-label => $i18n->get('checkout select shipping template'),
|
|
-hoverHelp => $i18n->get('checkout select shipping template description'),
|
|
-value => $session->setting->get("commerceSelectShippingMethodTemplateId"),
|
|
-namespace => 'Commerce/SelectShippingMethod'
|
|
);
|
|
$tabform->getTab('general')->template(
|
|
-name => 'commerceViewShoppingCartTemplateId',
|
|
-label => $i18n->get('view shopping cart template'),
|
|
-hoverHelp => $i18n->get('view shopping cart template description'),
|
|
-value => $session->setting->get("commerceViewShoppingCartTemplateId"),
|
|
-namespace => 'Commerce/ViewShoppingCart'
|
|
);
|
|
|
|
$tabform->getTab('general')->email(
|
|
-name => 'commerceSendDailyReportTo',
|
|
-label => $i18n->get('daily report email'),
|
|
-hoverHelp => $i18n->get('daily report email description'),
|
|
-value => $session->setting->get("commerceSendDailyReportTo")
|
|
);
|
|
|
|
$tabform->getTab('salesTax')->yesNo(
|
|
-name => 'commerceEnableSalesTax',
|
|
-label => $i18n->get('enable sales tax'),
|
|
-hoverHelp => $i18n->get('enable sales tax description'),
|
|
-value => $session->setting->get("commerceEnableSalesTax") || 0,
|
|
);
|
|
$tabform->getTab('salesTax')->raw('<tr><td colspan="2">');
|
|
$session->style->setScript($session->url->extras('/js/at/AjaxRequest.js'), {type=>"text/javascript"});
|
|
$session->style->setScript($session->url->extras('/operations/salesTaxAjax.js'), {type=>"text/javascript"});
|
|
my $stateForm = www_salesTaxTable($session);
|
|
$tabform->getTab('salesTax')->raw('<div id="salesTaxFormDiv">'.$stateForm.'</div>');
|
|
$tabform->getTab('salesTax')->raw('</td></tr>');
|
|
# Check which payment plugins will compile, and load them.
|
|
foreach (@{$session->config->get("paymentPlugins")}) {
|
|
$plugin = WebGUI::Commerce::Payment->load($session, $_);
|
|
if ($plugin) {
|
|
push(@paymentPlugins, $plugin);
|
|
$paymentPlugins{$_} = $plugin->name;
|
|
} else {
|
|
push(@failedPaymentPlugins, $_);
|
|
}
|
|
}
|
|
|
|
# payment plugin
|
|
if (%paymentPlugins) {
|
|
$session->style->setRawHeadTags('<script type="text/javascript">var activePayment="'.$paymentPlugin.'";</script>');
|
|
$tabform->getTab("payment")->selectBox(
|
|
-name => 'commercePaymentPlugin',
|
|
-options => \%paymentPlugins,
|
|
-label => $i18n->get('payment plugin'),
|
|
-hoverHelp => $i18n->get('payment plugin description'),
|
|
-value => $paymentPlugin,
|
|
-extras => 'onchange="activePayment=operateHidden(this.options[this.selectedIndex].value,activePayment)"'
|
|
);
|
|
|
|
foreach my $currentPlugin (@paymentPlugins) {
|
|
my $style = '" style="display: none;' unless ($currentPlugin->namespace eq $paymentPlugin);
|
|
$tabform->getTab('payment')->raw('<tr id="'.$currentPlugin->namespace.$style.'"><td colspan="2" width="100%">'.
|
|
'<table border="0" cellspacing="0" cellpadding="0" width="100%">'.
|
|
$currentPlugin->configurationForm.'<tr><td width="304"> </td><td width="496"> </td></tr></table></td></tr>');
|
|
}
|
|
} else {
|
|
$tabform->getTab('payment')->raw('<tr><td colspan="2" align="left">'.$i18n->get('no payment plugins selected').'</td></tr>');
|
|
}
|
|
|
|
if (@failedPaymentPlugins) {
|
|
$tabform->getTab('payment')->raw('<tr><td colspan="2" align="left"><br />'.$i18n->get('failed payment plugins').
|
|
'<br /><ul><li>'.join('</li><li>', @failedPaymentPlugins).'</li></ul></td></tr>');
|
|
}
|
|
|
|
# Shipping plugins...
|
|
# Check which payment plugins will compile, and load them.
|
|
foreach (@{$session->config->get("shippingPlugins")}) {
|
|
$plugin = WebGUI::Commerce::Shipping->load($session, $_);
|
|
if ($plugin) {
|
|
push(@shippingPlugins, $plugin);
|
|
$shippingPlugins{$_} = $plugin->name;
|
|
} else {
|
|
push(@failedShippingPlugins, $_);
|
|
}
|
|
}
|
|
|
|
# shipping plugin
|
|
if (%shippingPlugins) {
|
|
$session->style->setRawHeadTags('<script type="text/javascript">var activeShipping="'.$shippingPlugin.'";</script>');
|
|
$tabform->getTab('shipping')->selectBox(
|
|
-name => 'commerceShippingPlugin',
|
|
-options=> \%shippingPlugins,
|
|
-label => $i18n->get('shipping plugin label'),
|
|
-hoverHelp => $i18n->get('shipping plugin label description'),
|
|
-value => $shippingPlugin,
|
|
-extras => 'onchange="activeShipping=operateHidden(this.options[this.selectedIndex].value,activeShipping)"'
|
|
);
|
|
|
|
foreach my $currentPlugin (@shippingPlugins) {
|
|
my $style = '" style="display: none;' unless ($currentPlugin->namespace eq $shippingPlugin);
|
|
$tabform->getTab('shipping')->raw('<tr id="'.$currentPlugin->namespace.$style.'"><td colspan="2" width="100%">'.
|
|
'<table border="0" cellspacing="0" cellpadding="0" width="100%">'.
|
|
$currentPlugin->configurationForm.'<tr><td width="304"> </td><td width="496"> </td></tr></table></td></tr>');
|
|
}
|
|
} else {
|
|
$tabform->getTab('shipping')->raw('<tr><td colspan="2" align="left">'.$i18n->get('no shipping plugins selected').'</td></tr>');
|
|
}
|
|
|
|
$tabform->submit;
|
|
|
|
$session->style->setScript($session->url->extras('swapLayers.js'),{type=>"text/javascript"});
|
|
|
|
return _submenu($session,$tabform->print, 'edit commerce settings title');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_editCommerceSettingsSave ( $session )
|
|
|
|
Form post processor for C<www_editCommerceSettings>. Plugin
|
|
configuration data is stored in a special table for security and all
|
|
other settings in the WebGUI settings table for easy access.
|
|
|
|
Returns the user to C<www_editCommerceSettings>.
|
|
|
|
=cut
|
|
|
|
sub www_editCommerceSettingsSave {
|
|
my $session = shift;
|
|
return $session->privilege->adminOnly() unless canView($session);
|
|
|
|
PARAM: foreach ($session->form->param) {
|
|
|
|
##Sales tax form parameters will also be in this list, but they
|
|
##should NOT be handled here. We'll skip them.
|
|
next PARAM if isIn($_, qw/stateChooser taxRate addTaxInfo/);
|
|
|
|
# Store the plugin configuration data in a special table for security and the general settings in the
|
|
# normal settings table for easy access.
|
|
if (/([^_]*)_([^_]*)_([^_]*)/) {
|
|
WebGUI::Commerce::setCommerceSetting($session,{
|
|
type => $1,
|
|
namespace => $2,
|
|
fieldName => $3,
|
|
fieldValue => $session->form->process($_)
|
|
});
|
|
} elsif ($_ ne 'op') {
|
|
$session->setting->set($_,$session->form->process($_));
|
|
}
|
|
}
|
|
|
|
return WebGUI::Operation::execute($session,'editCommerceSettings');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_listPendingTransactions ( $session )
|
|
|
|
Only users in group Admin (3) can execute the subroutine.
|
|
|
|
Show a paginated list of all transactions with status, Pending. Provide
|
|
links so the Admin can complete any pending transaction.
|
|
|
|
=cut
|
|
|
|
sub www_listPendingTransactions {
|
|
my $session = shift;
|
|
my ($p, $transactions, $output, $properties, $i18n);
|
|
return $session->privilege->adminOnly() unless canView($session);
|
|
|
|
$i18n = WebGUI::International->new($session, "Commerce");
|
|
|
|
$p = WebGUI::Paginator->new($session,$session->url->page('op=listPendingTransactions'));
|
|
$p->setDataByArrayRef(WebGUI::Commerce::Transaction->pendingTransactions($session));
|
|
|
|
$transactions = $p->getPageData;
|
|
|
|
$output = $p->getBarTraditional($session->form->process("pn"));
|
|
$output .= '<table border="1" cellpadding="5" cellspacing="0" align="center">';
|
|
$output .= '<tr><th>'.$i18n->get('transactionId').'</th><th>' . $i18n->get('username') . '</th><th>'.$i18n->get('gateway').'</th>'.
|
|
'<th>'.$i18n->get('gatewayId').'</th><th>'.$i18n->get('init date').'</th></tr>';
|
|
foreach (@{$transactions}) {
|
|
$properties = $_->get;
|
|
$output .= '<tr>';
|
|
$output .= '<td>'.$properties->{transactionId}.'</td>';
|
|
|
|
my $userId = $properties->{userId};
|
|
my $username = WebGUI::User->new($session, $userId)->username;
|
|
$output .= '<td><a href="' . $session->url->page('op=editUser;uid=' . $userId) . '">' . $username . '</a></td>';
|
|
$output .= '<td>'.$properties->{gatewayId}.'</td>';
|
|
$output .= '<td>'.$properties->{gateway}.'</td>';
|
|
$output .= '<td>'.$session->datetime->epochToHuman($properties->{initDate}).'</td>';
|
|
$output .= '<td><a href="'.$session->url->page('op=completePendingTransaction;tid='.$properties->{transactionId}).'">'.$i18n->get('complete pending transaction').'</a></td>';
|
|
$output .= '</tr>';
|
|
}
|
|
$output .= '</table>';
|
|
$output .= $p->getBarTraditional($session->form->process("pn"));
|
|
|
|
_submenu($session,$output, 'list pending transactions');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_listTransactions ( $session )
|
|
|
|
Show all transactions in the system and allow them to be managed.
|
|
|
|
You must be in group Admin (3) in order to access this screen.
|
|
|
|
The screen is not templated.
|
|
|
|
=cut
|
|
|
|
sub www_listTransactions {
|
|
my $session = shift;
|
|
my ($output, %criteria, @transactions);
|
|
|
|
return $session->privilege->insufficient unless canView($session);
|
|
|
|
my $i18n = WebGUI::International->new($session, 'TransactionLog');
|
|
|
|
my $transactionOptions = {
|
|
'' => $i18n->get('any'),
|
|
'Pending' => $i18n->get('pending'),
|
|
'Completed' => $i18n->get('completed'),
|
|
};
|
|
|
|
my $shippingOptions = {
|
|
'' => $i18n->get('any'),
|
|
'Shipped' => $i18n->get('shipped'),
|
|
'NotShipped' => $i18n->get('not shipped'),
|
|
'Delivered' => $i18n->get('delivered'),
|
|
};
|
|
|
|
my $initStart = $session->form->date('initStart');
|
|
my $initStop = $session->datetime->addToTime($session->form->date('initStop'),23,59);
|
|
my $completionStart = $session->form->date('completionStart');
|
|
my $completionStop = $session->datetime->addToTime($session->form->date('completionStop'),23,59);
|
|
|
|
$output .= $i18n->get('selection message');
|
|
|
|
$output .= WebGUI::Form::formHeader($session);
|
|
$output .= WebGUI::Form::hidden($session,{name=>'op', value=>'listTransactions'});
|
|
$output .= '<table>';
|
|
$output .= '<td>'.WebGUI::Form::radio($session,{name=>'selection', value => 'init', checked=>($session->form->process("selection") eq 'init')}).'</td>';
|
|
$output .= '<td align="left">'.$i18n->get('init date').'</td>';
|
|
$output .= '<td>'.WebGUI::Form::date($session,{name=>'initStart', value=>$initStart}).' '.$i18n->get('and').' '.WebGUI::Form::date($session,{name=>'initStop', value=>$initStop}).'</td>';
|
|
$output .= '</tr><tr>';
|
|
$output .= '<td>'.WebGUI::Form::radio($session,{name=>'selection', value => 'completion', checked=>($session->form->process("selection") eq 'completion')}).'</td>';
|
|
$output .= '<td align="left">'.$i18n->get('completion date').'</td>';
|
|
$output .= '<td>'.WebGUI::Form::date($session,{name=>'completionStart', value=>$completionStart}).' '.$i18n->get('and').' '.WebGUI::Form::date($session,{name=>'completionStop', value=>$completionStop}).'</td>';
|
|
$output .= '</tr><tr>';
|
|
$output .= '<td></td>';
|
|
$output .= '<td align="left">'.$i18n->get('transaction status').'</td>';
|
|
$output .= '<td>'.WebGUI::Form::selectBox($session,{name => 'tStatus', value => [$session->form->process("tStatus")], options => $transactionOptions});
|
|
$output .= '</tr><tr>';
|
|
|
|
$output .= '<td></td>';
|
|
$output .= '<td align="left">'.$i18n->get('shipping status').'</td>';
|
|
$output .= '<td>'.WebGUI::Form::selectBox($session,{name => 'sStatus', value => [$session->form->process("sStatus")], options => $shippingOptions});
|
|
$output .= '</tr><tr>';
|
|
|
|
$output .= '<td></td>';
|
|
$output .= '<td>'.WebGUI::Form::submit($session,{value=>$i18n->get('select')}).'</td>';
|
|
$output .= '</tr>';
|
|
$output .= '</table>';
|
|
$output .= WebGUI::Form::formFooter;
|
|
|
|
$criteria{initStart} = $session->form->date('initStart') if ($session->form->process("initStart") && ($session->form->process("selection") eq 'init'));
|
|
$criteria{initStop} = $session->form->date('initStop') if ($session->form->process("initStop") && ($session->form->process("selection") eq 'init'));
|
|
$criteria{completionStart} = $session->form->date('completionStart') if ($session->form->process("completionStart") && ($session->form->process("selection") eq 'completion'));
|
|
$criteria{completionStop} = $session->form->date('completionStop') if ($session->form->process("completionStop") && ($session->form->process("selection") eq 'completion'));
|
|
$criteria{shippingStatus} = $session->form->process("sStatus") if ($session->form->process("sStatus"));
|
|
$criteria{paymentStatus} = $session->form->process("tStatus") if ($session->form->process("tStatus"));
|
|
|
|
@transactions = WebGUI::Commerce::Transaction->new($session)->getTransactions(\%criteria);
|
|
|
|
$output .= '<table border="1">';
|
|
$output .= '<tr><th></th>'.
|
|
'<th>'. $i18n->get('username'). '</th>'.
|
|
'<th>'. $i18n->get('init date'). '</th>'.
|
|
'<th>'. $i18n->get('completion date'). '</th>'.
|
|
'<th>'. $i18n->get('amount'). '</th>'.
|
|
'<th>'. $i18n->get('shipping cost'). '</th>'.
|
|
'<th>'. $i18n->get('status'). '</th>'.
|
|
'<th>'. $i18n->get('shipping status'). '</th></tr>';
|
|
foreach my $transaction (@transactions) {
|
|
$output .= '<tr bgcolor="#ddd">';
|
|
$output .= '<td>'.$session->icon->delete('op=deleteTransaction;tid='.$transaction->get('transactionId')).'</td>';
|
|
my $userId = $transaction->get('userId');
|
|
my $username = WebGUI::User->new($session, $userId)->username;
|
|
$output .= '<td><a href="' . $session->url->page('op=editUser;uid=' . $userId) . '">' . $username . '</a></td>';
|
|
$output .= '<td>'.$session->datetime->epochToHuman($transaction->get('initDate')).'</td>';
|
|
$output .= '<td>'.$session->datetime->epochToHuman($transaction->get('completionDate')).'</td>';
|
|
$output .= '<td>'.sprintf('%.2f',$transaction->get('amount')).'</td>';
|
|
$output .= '<td>'.sprintf('%.2f',$transaction->get('shippingCost')).'</td>';
|
|
$output .= '<td>'.$transaction->get('status').'</td>';
|
|
$output .= '<td>'.$transaction->get('shippingStatus').'</td>';
|
|
$output .= '</tr>';
|
|
|
|
my @items = @{$transaction->getItems};
|
|
foreach (@items) {
|
|
$output .= '<tr>';
|
|
$output .= '<td></td>';
|
|
$output .= '<td colspan="4">'.
|
|
$session->icon->delete('op=deleteTransactionItem;tid='.$transaction->get('transactionId').';iid='.$_->{itemId}.';itype='.$_->{itemType}).
|
|
$_->{itemName}.'</td>';
|
|
$output .= '<td>'.$_->{quantity}.'</td>';
|
|
$output .= '<td> x </td>';
|
|
$output .= '<td>'.$_->{amount}.'</td>';
|
|
$output .= '</tr>';
|
|
}
|
|
}
|
|
$output .= '</table>';
|
|
|
|
return _submenu($session,$output, 'list transactions')
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_salesTaxTable ( $session )
|
|
|
|
Create the AJAX form for displaying, adding and deleting sales tax information.
|
|
|
|
=cut
|
|
|
|
sub www_salesTaxTable {
|
|
my $session = shift;
|
|
|
|
my $returnTableOnly = 0;
|
|
|
|
if ($session->form->process('addDelete') eq 'add') {
|
|
my $state = $session->form->process('addStateId', 'selectBox');
|
|
my $taxRate = $session->form->process('taxRate', 'float');
|
|
my $commerceSalesTaxId = $session->id->generate();
|
|
if ( $state and $taxRate ) {
|
|
$session->db->write('insert into commerceSalesTax (commerceSalesTaxId,regionIdentifier,salesTax) VALUES (?,?,?)', [$commerceSalesTaxId, $state, $taxRate]);
|
|
}
|
|
$returnTableOnly = 1;
|
|
}
|
|
elsif ($session->form->process('addDelete') eq 'delete') {
|
|
my $commerceSalesTaxId = $session->form->process('entryId');
|
|
$session->db->write('delete from commerceSalesTax where commerceSalesTaxId=?',[$commerceSalesTaxId]);
|
|
$returnTableOnly = 1;
|
|
}
|
|
|
|
my $existingData = $session->db->buildArrayRefOfHashRefs('select * from commerceSalesTax order by regionIdentifier');
|
|
|
|
##To build the form, we need two pieces
|
|
|
|
##1: The table contains all information from the database
|
|
my @existingStates = map { $_->{regionIdentifier} } @{ $existingData };
|
|
my %existingStates = map { $_ => 1 } @existingStates;
|
|
|
|
##2: The list contains all states except for those in the table;
|
|
my $stateObj = Locale::US->new();
|
|
my @stateNames = $stateObj->all_state_names;
|
|
my @newStates = sort grep {! exists $existingStates{$_} } @stateNames;
|
|
|
|
my %orderedStates;
|
|
tie %orderedStates, 'Tie::IxHash';
|
|
my $i18n = WebGUI::International->new($session);
|
|
%orderedStates = map { $_ => $_ } 'Select State', @newStates;
|
|
$orderedStates{'Select State'} = $i18n->get('Select State');
|
|
|
|
my $statesField = WebGUI::Form::selectBox($session,
|
|
-name => 'stateChooser',
|
|
-options => \%orderedStates,
|
|
-default => 'Select State',
|
|
);
|
|
|
|
my $taxField = WebGUI::Form::float($session,
|
|
-name => 'taxRate',
|
|
-value => '',
|
|
-size => 6,
|
|
);
|
|
my $addButton = WebGUI::Form::button($session,
|
|
-name=>"addTaxInfo",
|
|
-value=>"Add Tax Information",
|
|
-extras=>q!align="right" onclick="addState()"!,
|
|
);
|
|
|
|
##build the table to display all existing sales tax
|
|
|
|
my $tableRows = '';
|
|
my $deleteIcon = $session->config->get('extrasURL').'/toolbar/bullet/delete.gif';
|
|
foreach my $sRow ( @{$existingData} ) {
|
|
$tableRows .= sprintf <<EOTR, $deleteIcon, $sRow->{commerceSalesTaxId}, $sRow->{regionIdentifier}, $sRow->{salesTax};
|
|
<tr>
|
|
<td class="cell"><img style="cursor:pointer;" src="%s" onclick="deleteState(event,'%s')"></td>
|
|
<td class="cell"><span>%s</span></td>
|
|
<td class="cell"><span>%6.4f%%</span></td>
|
|
</tr>
|
|
EOTR
|
|
}
|
|
my $stateForm = sprintf <<EOSF, $taxField, $statesField, $addButton;
|
|
<table id="salesTaxEntryTable">
|
|
<tbody>
|
|
<tr>
|
|
<td class="cell">%s %% tax for</td>
|
|
<td class="cell">%s</td>
|
|
<td class="cell">%s</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
EOSF
|
|
|
|
my $stateTable = sprintf <<EOST, $tableRows;
|
|
<table id="salesTaxDataTable" border="1" cellpadding="3">
|
|
<tbody>
|
|
%s
|
|
</tbody>
|
|
</table>
|
|
EOST
|
|
$stateTable = '' unless $tableRows;
|
|
return $stateForm.$stateTable;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_selectPaymentGateway ( $session )
|
|
|
|
Allow the user to select a payment plugin. Uses the C<commerceSelectPaymentGatewayTemplateId>
|
|
template. After form submission, calls www_selectPaymentGatewaySave
|
|
|
|
=cut
|
|
|
|
sub www_selectPaymentGateway {
|
|
my $session = shift;
|
|
my ($plugins, $f, $i18n, @pluginLoop, %var);
|
|
|
|
_clearPaymentScratch($session);
|
|
|
|
$i18n = WebGUI::International->new($session, 'Commerce');
|
|
$plugins = WebGUI::Commerce::Payment->getEnabledPlugins($session);
|
|
if (scalar(@$plugins)) {
|
|
foreach (@$plugins) {
|
|
push(@pluginLoop, {
|
|
name => $_->name,
|
|
label => $_->label,
|
|
namespace => $_->namespace,
|
|
formElement => WebGUI::Form::radio($session,{name=>'paymentGateway', value=>$_->namespace})
|
|
}) if ($session->user->isInGroup($_->get('whoCanUse')));
|
|
}
|
|
}
|
|
# If user is only authorized for one payment gateway, skip this step
|
|
if (scalar(@pluginLoop) == 1) {
|
|
my $paymentGateway = $pluginLoop[0]->{namespace};
|
|
return WebGUI::Operation::Commerce::www_selectPaymentGatewaySave($session, $paymentGateway);
|
|
}
|
|
# If the user is not authorized for any payment gateways, error
|
|
elsif (scalar(@pluginLoop) < 1) {
|
|
return $session->privilege->noAccess();
|
|
}
|
|
|
|
$var{pluginLoop} = \@pluginLoop;
|
|
$var{message} = $i18n->get('select payment gateway');
|
|
$var{pluginsAvailable} = @$plugins;
|
|
$var{noPluginsMessage} = $i18n->get('no payment gateway');
|
|
$var{formHeader} = WebGUI::Form::formHeader($session).WebGUI::Form::hidden($session,{name=>'op', value=>'selectPaymentGatewaySave'});
|
|
$var{formSubmit} = WebGUI::Form::submit($session,{value=>$i18n->get('payment gateway select')});
|
|
$var{formFooter} = WebGUI::Form::formFooter;
|
|
|
|
return $session->style->userStyle(WebGUI::Asset::Template->new($session,$session->setting->get("commerceSelectPaymentGatewayTemplateId"))->process(\%var));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_selectPaymentGatewaySave ( $session )
|
|
|
|
Form processor for www_selectPaymentGateway. If the user selected payment plugin can
|
|
be loaded and enabled, sets the scratch variable C<paymentGateway> so that it can
|
|
be used. Otherwise the value of the scratch variable is cleared.
|
|
|
|
Returns the user to the operation C<checkout> when it is done.
|
|
|
|
=cut
|
|
|
|
sub www_selectPaymentGatewaySave {
|
|
my $session = shift;
|
|
my $paymentGateway = shift || $session->form->process("paymentGateway","className");
|
|
if (WebGUI::Commerce::Payment->load($session, $paymentGateway)->enabled) {
|
|
$session->scratch->set('paymentGateway', $paymentGateway);
|
|
} else {
|
|
$session->scratch->delete('paymentGateway');
|
|
}
|
|
|
|
return WebGUI::Operation::execute($session,'checkout');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_selectShippingMethod ( $session )
|
|
|
|
Allow the user to select a payment plugin. Uses the C<commerceSelectShippingMethodTemplateId>
|
|
template. After form submission, calls www_selectPaymentGatewaySave
|
|
|
|
=cut
|
|
|
|
sub www_selectShippingMethod {
|
|
my $session = shift;
|
|
my ($plugins, $f, $i18n, @pluginLoop, %var);
|
|
|
|
_clearShippingScratch($session);
|
|
|
|
$i18n = WebGUI::International->new($session, 'Commerce');
|
|
$plugins = WebGUI::Commerce::Shipping->getEnabledPlugins($session);
|
|
|
|
if (scalar(@$plugins) > 1) {
|
|
foreach (@$plugins) {
|
|
push(@pluginLoop, {
|
|
name => $_->name,
|
|
namespace => $_->namespace,
|
|
formElement => WebGUI::Form::radio($session,{name=>'shippingMethod', value=>$_->namespace})
|
|
});
|
|
}
|
|
} elsif (scalar(@$plugins) == 1) {
|
|
$session->stow->set('shippingMethod', $plugins->[0]->namespace);
|
|
my $shippingMethod = $plugins->[0]->namespace;
|
|
return WebGUI::Operation::Commerce::www_selectShippingMethodSave($session, $shippingMethod);
|
|
}
|
|
|
|
$var{pluginLoop} = \@pluginLoop;
|
|
$var{message} = $i18n->get('select shipping method');
|
|
$var{pluginsAvailable} = @$plugins;
|
|
$var{noPluginsMessage} = $i18n->get('no shipping methods available');
|
|
$var{formHeader} = WebGUI::Form::formHeader($session).WebGUI::Form::hidden($session,{name=>'op', value=>'selectShippingMethodSave'});
|
|
$var{formSubmit} = WebGUI::Form::submit($session,{value=>$i18n->get('shipping select button')});
|
|
$var{formFooter} = WebGUI::Form::formFooter($session);
|
|
|
|
return $session->style->userStyle(WebGUI::Asset::Template->new($session,$session->setting->get("commerceSelectShippingMethodTemplateId"))->process(\%var));
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_selectShippingMethodSave ( $session )
|
|
|
|
Form processor for www_selectShippingMethod. If the shipping method
|
|
plugin can be loaded and the C<optionsOk> method returns false, then
|
|
takes the user back to the C<selectShipping> operation (probably
|
|
www_selectShippingMethod).
|
|
|
|
If the plugin is enabled, then set scratch variables to be used downstream.
|
|
|
|
Returns the user to the operation C<checkout> when it is done.
|
|
|
|
=cut
|
|
|
|
sub www_selectShippingMethodSave {
|
|
my $session = shift;
|
|
my $shippingMethod = shift || $session->form->process("shippingMethod");
|
|
my $shipping = WebGUI::Commerce::Shipping->load($session, $shippingMethod);
|
|
|
|
$shipping->processOptionsForm;
|
|
return WebGUI::Operation::execute($session,'selectShipping') unless ($shipping->optionsOk);
|
|
|
|
if ($shipping->enabled) {
|
|
$session->scratch->set('shippingMethod', $shipping->namespace);
|
|
$session->scratch->set('shippingOptions', Storable::freeze($shipping->getOptions));
|
|
} else {
|
|
$session->scratch->delete('shippingMethod');
|
|
}
|
|
|
|
return WebGUI::Operation::execute($session,'checkout');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_transactionComplete ( $session )
|
|
|
|
This is wrapper for the C<viewPurchaseHistory> operation, probably
|
|
WebGUI::Operation::TransactionLog::www_viewPurchaseHistory.
|
|
|
|
=cut
|
|
|
|
sub www_transactionComplete {
|
|
my $session = shift;
|
|
return WebGUI::Operation::execute($session,'viewPurchaseHistory');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_updateCart ( $session )
|
|
|
|
Update the shopping cart with new quantities for items. Returns the user
|
|
to the C<viewCart> operation, probably www_viewCart.
|
|
|
|
=cut
|
|
|
|
sub www_updateCart {
|
|
my $session = shift;
|
|
my $shoppingCart = WebGUI::Commerce::ShoppingCart->new($session);
|
|
|
|
foreach my $formElement ($session->form->param) {
|
|
if ($formElement =~ m/^quantity~([^~]*)~([^~]*)$/) {
|
|
$shoppingCart->setQuantity($2, $1, $session->form->process($formElement));
|
|
}
|
|
}
|
|
|
|
return WebGUI::Operation::execute($session,'viewCart');
|
|
}
|
|
|
|
#-------------------------------------------------------------------
|
|
|
|
=head2 www_viewCart ( $session )
|
|
|
|
Display the user's shopping cart to the user using the C<commerceViewShoppingCartTemplateId>
|
|
template, and allow them to delete items or change the quantity of regular items.
|
|
|
|
Will call the C<updateCart> operation, the C<checkout> operation or C<deleteCartItem>
|
|
based on user input.
|
|
|
|
=cut
|
|
|
|
sub www_viewCart {
|
|
my $session = shift;
|
|
my ($shoppingCart, $normal, $recurring, %var, $total, $i18n);
|
|
|
|
$i18n = WebGUI::International->new($session, 'Commerce');
|
|
|
|
# Put contents of cart in template vars
|
|
$shoppingCart = WebGUI::Commerce::ShoppingCart->new($session);
|
|
($normal, $recurring) = $shoppingCart->getItems;
|
|
|
|
foreach (@$normal) {
|
|
$_->{deleteIcon} = $session->icon->delete('op=deleteCartItem;itemId='.$_->{item}->id.';itemType='.$_->{item}->type);
|
|
$_->{'quantity.form'} = WebGUI::Form::integer($session, {
|
|
name => 'quantity~'.$_->{item}->type.'~'.$_->{item}->id,
|
|
value => $_->{quantity},
|
|
size => 3,
|
|
});
|
|
$total += $_->{totalPrice};
|
|
}
|
|
|
|
foreach (@$recurring) {
|
|
$_->{deleteIcon} = $session->icon->delete('op=deleteCartItem;itemId='.$_->{item}->id.';itemType='.$_->{item}->type);
|
|
$_->{'quantity.form'} = WebGUI::Form::integer($session,{
|
|
name => 'quantity~'.$_->{item}->type.'~'.$_->{item}->id,
|
|
value => $_->{quantity},
|
|
size => 3,
|
|
});
|
|
$total += $_->{totalPrice};
|
|
}
|
|
|
|
$var{'cartEmpty'} = !(scalar(@$normal) || scalar(@$recurring));
|
|
$var{'cartEmpty.message'} = $i18n->get('shopping cart empty');
|
|
|
|
$var{'updateForm.header'} = WebGUI::Form::formHeader($session,).
|
|
WebGUI::Form::hidden($session,{name => 'op', value => 'updateCart'});
|
|
$var{'updateForm.button'} = WebGUI::Form::submit($session,{value => $i18n->get('update cart')});
|
|
$var{'updateForm.footer'} = WebGUI::Form::formFooter;
|
|
$var{'checkoutForm.header'} = WebGUI::Form::formHeader($session,).
|
|
WebGUI::Form::hidden($session,{name => 'op', value => 'checkout'});
|
|
$var{'checkoutForm.button'} = WebGUI::Form::submit($session,{value => $i18n->get('checkout')});
|
|
$var{'checkoutForm.footer'} = WebGUI::Form::formFooter($session);
|
|
|
|
$var{normalItemsLoop} = $normal;
|
|
$var{normalItems} = scalar(@$normal);
|
|
$var{recurringItemsLoop} = $recurring;
|
|
$var{recurringItems} = scalar(@$recurring);
|
|
|
|
$var{total} = sprintf('%.2f', $total);
|
|
|
|
return $session->style->userStyle(WebGUI::Asset::Template->new($session,$session->setting->get("commerceViewShoppingCartTemplateId"))->process(\%var));
|
|
}
|
|
|
|
1;
|
|
|