Merge commit '41575d24bb' into webgui8. Some tests still failing.
Conflicts: docs/gotcha.txt lib/WebGUI.pm lib/WebGUI/Asset.pm lib/WebGUI/Asset/File/GalleryFile/Photo.pm lib/WebGUI/Asset/Post.pm lib/WebGUI/Asset/Template.pm lib/WebGUI/Asset/WikiPage.pm lib/WebGUI/Asset/Wobject/WikiMaster.pm lib/WebGUI/Cache.pm lib/WebGUI/Content/Setup.pm lib/WebGUI/Role/Asset/Subscribable.pm lib/WebGUI/Shop/Cart.pm lib/WebGUI/Shop/Pay.pm lib/WebGUI/Shop/PayDriver/ITransact.pm sbin/testEnvironment.pl t/Asset/WikiPage.t t/Shop/PayDriver.t t/Shop/PayDriver/ITransact.t t/Shop/PayDriver/Ogone.t t/Shop/TaxDriver/EU.t t/Shop/TaxDriver/Generic.t t/Workflow/Activity/RemoveOldCarts.t t/lib/WebGUI/Test.pm
This commit is contained in:
commit
5febc0ebbc
258 changed files with 5528 additions and 2230 deletions
|
|
@ -12,9 +12,11 @@ use WebGUI::Shop::AddressBook;
|
|||
use WebGUI::Shop::CartItem;
|
||||
use WebGUI::Shop::Credit;
|
||||
use WebGUI::Shop::Ship;
|
||||
use WebGUI::Shop::Pay;
|
||||
use WebGUI::Shop::Tax;
|
||||
use WebGUI::User;
|
||||
use Tie::IxHash;
|
||||
use Data::Dumper;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
|
@ -38,7 +40,7 @@ These subroutines are available from this package:
|
|||
|
||||
readonly session => my %session;
|
||||
private properties => my %properties;
|
||||
private error => my %error;
|
||||
public error => my %error;
|
||||
private addressBookCache => my %addressBookCache;
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -76,15 +78,11 @@ The amount to calculate the deduction against. Defaults to calculateTotal().
|
|||
|
||||
sub calculateShopCreditDeduction {
|
||||
my ($self, $total) = @_;
|
||||
# cannot use in-shop credit on recurring items
|
||||
foreach my $item (@{$self->getItems}) {
|
||||
if ($item->getSku->isRecurring) {
|
||||
return $self->formatCurrency(0);
|
||||
}
|
||||
}
|
||||
unless (defined $total) {
|
||||
$total = $self->calculateTotal
|
||||
}
|
||||
# cannot use in-shop credit on recurring items
|
||||
return $self->formatCurrency(0) if $self->requiresRecurringPayment;
|
||||
return $self->formatCurrency(WebGUI::Shop::Credit->new($self->session, $self->get('posUserId'))->calculateDeduction($total));
|
||||
}
|
||||
|
||||
|
|
@ -263,13 +261,45 @@ sub getAddressBook {
|
|||
my $self = shift;
|
||||
my $id = id $self;
|
||||
unless (exists $addressBookCache{$id}) {
|
||||
$addressBookCache{$id} = WebGUI::Shop::AddressBook->newBySession($self->session);
|
||||
$addressBookCache{$id} = WebGUI::Shop::AddressBook->newByUserId($self->session);
|
||||
}
|
||||
return $addressBookCache{$id};
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getBillingAddress ()
|
||||
|
||||
Returns the WebGUI::Shop::Address object that is attached to this cart for billing.
|
||||
|
||||
=cut
|
||||
|
||||
sub getBillingAddress {
|
||||
my $self = shift;
|
||||
my $book = $self->getAddressBook;
|
||||
if (my $addressId = $self->get("billingAddressId")) {
|
||||
return $book->getAddress($addressId);
|
||||
}
|
||||
my $address = $book->getDefaultAddress;
|
||||
$self->update({billingAddressId=>$address->getId});
|
||||
return $address;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getPaymentGateway ()
|
||||
|
||||
Returns the WebGUI::Shop::PayDriver object that is attached to this cart for payment.
|
||||
|
||||
=cut
|
||||
|
||||
sub getPaymentGateway {
|
||||
my $self = shift;
|
||||
return WebGUI::Shop::Pay->new($self->session)->getPaymentGateway($self->get("gatewayId"));
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 getId ()
|
||||
|
||||
Returns the unique id for this cart.
|
||||
|
|
@ -285,7 +315,9 @@ sub getId {
|
|||
|
||||
=head2 getItem ( itemId )
|
||||
|
||||
Returns a reference to a WebGUI::Shop::CartItem object.
|
||||
Returns a reference to a WebGUI::Shop::CartItem object. Throws an WebGUI::Error::InvalidParam
|
||||
exception if no itemId is passed, or if an invalid itemId is passed. It will not catch any
|
||||
exceptions thrown by actually creating the CartItem, the caller of this method should do that.
|
||||
|
||||
=head3 itemId
|
||||
|
||||
|
|
@ -295,7 +327,7 @@ The id of the item to retrieve.
|
|||
|
||||
sub getItem {
|
||||
my ($self, $itemId) = @_;
|
||||
unless (defined $itemId && $itemId =~ m/^[A-Za-z0-9_-]{22}$/) {
|
||||
unless (defined $itemId && $self->session->id->valid($itemId)) {
|
||||
WebGUI::Error::InvalidParam->throw(error=>"Need an itemId.");
|
||||
}
|
||||
my $item = WebGUI::Shop::CartItem->new($self, $itemId);
|
||||
|
|
@ -499,30 +531,76 @@ Returns whether all the required properties of the the cart are set.
|
|||
|
||||
sub readyForCheckout {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $book = $self->getAddressBook;
|
||||
|
||||
# Check if the billing address is set and correct
|
||||
my $address = eval{$self->getBillingAddress};
|
||||
if (WebGUI::Error->caught) {
|
||||
$self->error('no billing address');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (my @missingFields = $book->missingFields($address->get)) {
|
||||
$self->error($missingFields[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Check if the shipping address is set and correct
|
||||
my $address = eval{$self->getShippingAddress};
|
||||
return 0 if WebGUI::Error->caught;
|
||||
my $shipAddress = eval{$self->getShippingAddress};
|
||||
if (WebGUI::Error->caught) {
|
||||
$self->error('no shipping address');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (my @missingFields = $book->missingFields($shipAddress->get)) {
|
||||
$self->error($missingFields[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($self->requiresShipping) {
|
||||
##Must have a configured shipping id.
|
||||
if (! $self->get('shipperId')) {
|
||||
$self->error('no shipping method set');
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $shipper = eval { WebGUI::Shop::ShipDriver->new($session, $self->get('shipperId'))};
|
||||
if (my $e = WebGUI::Error->caught) {
|
||||
$self->error($e->error);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
# Check if the cart has items
|
||||
return 0 unless scalar @{ $self->getItems };
|
||||
|
||||
# fail if there are multiple recurring items or if
|
||||
# fail if there are multiple recurring items
|
||||
return 0 if ($self->hasMixedItems);
|
||||
|
||||
# Check minimum cart checkout requirement
|
||||
my $total = eval { $self->calculateTotal };
|
||||
if (my $e = WebGUI::Error->caught) {
|
||||
$error{id $self} = $e->error;
|
||||
$self->error($e->error);
|
||||
return 0;
|
||||
}
|
||||
my $requiredAmount = $self->session->setting->get( 'shopCartCheckoutMinimum' );
|
||||
if ( $requiredAmount > 0 ) {
|
||||
return 0 if $total < $requiredAmount;
|
||||
if ( $requiredAmount > 0 && $total < $requiredAmount) {
|
||||
$self->error('required amount not met in cart');
|
||||
return 0;
|
||||
}
|
||||
|
||||
##Must have a configured shipping id.
|
||||
return 0 if ! $self->get('shipperId');
|
||||
##Must have a configured payment method.
|
||||
if (! $self->get('gatewayId')) {
|
||||
$self->error('no payment gateway set');
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $gateway = eval { WebGUI::Shop::PayDriver->new($session, $self->get('gatewayId'))};
|
||||
if (my $e = WebGUI::Error->caught) {
|
||||
$self->error($e->error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
##Check for any other logged errors
|
||||
return 0 if $error{ id $self };
|
||||
|
|
@ -553,6 +631,26 @@ sub requiresRecurringPayment {
|
|||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 requiresShipping ( )
|
||||
|
||||
Returns whether any item in this cart requires shipping.
|
||||
|
||||
=cut
|
||||
|
||||
sub requiresShipping {
|
||||
my $self = shift;
|
||||
|
||||
# Look for recurring items in the cart
|
||||
foreach my $item (@{ $self->getItems }) {
|
||||
return 1 if $item->getSku->isShippingRequired;
|
||||
}
|
||||
|
||||
# No recurring items in cart so return false
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 update ( properties )
|
||||
|
||||
Sets properties in the cart.
|
||||
|
|
@ -565,6 +663,10 @@ A hash reference that contains one of the following:
|
|||
|
||||
The unique id for a shipping address attached to this cart.
|
||||
|
||||
=head4 billingAddressId
|
||||
|
||||
The unique id for a billing address attached to this cart.
|
||||
|
||||
=head4 shipperId
|
||||
|
||||
The unique id of the configured shipping driver that will be used to ship these goods.
|
||||
|
|
@ -585,7 +687,7 @@ sub update {
|
|||
WebGUI::Error::InvalidParam->throw(error=>"Need a properties hash ref.");
|
||||
}
|
||||
my $id = id $self;
|
||||
foreach my $field (qw(shippingAddressId posUserId shipperId creationDate)) {
|
||||
foreach my $field (qw(billingAddressId shippingAddressId posUserId gatewayId shipperId creationDate)) {
|
||||
$properties{$id}{$field} = (exists $newProperties->{$field}) ? $newProperties->{$field} : $properties{$id}{$field};
|
||||
}
|
||||
$self->session->db->setRow("cart","cartId",$properties{$id});
|
||||
|
|
@ -595,7 +697,7 @@ sub update {
|
|||
|
||||
=head2 updateFromForm ( )
|
||||
|
||||
Updates the cart totals.
|
||||
Updates the cart totals, the address fields and the shipping and billing options from form data.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -613,49 +715,154 @@ sub updateFromForm {
|
|||
$error{id $self} = "An unknown error has occured: ".$e->message;
|
||||
}
|
||||
}
|
||||
if (my $itemAddressId = $form->get("itemAddress_".$item->getId)) {
|
||||
$item->update({shippingAddressId => $itemAddressId});
|
||||
}
|
||||
}
|
||||
if ($self->hasMixedItems) {
|
||||
my $i18n = WebGUI::International->new($self->session, "Shop");
|
||||
$error{id $self} = $i18n->get('mixed items warning');
|
||||
}
|
||||
|
||||
my $book = $self->getAddressBook;
|
||||
|
||||
my $cartProperties = {};
|
||||
$cartProperties->{ shipperId } = $form->process( 'shipperId' ) if $form->process( 'shipperId' );
|
||||
my %billingData = $book->processAddressForm('billing_');
|
||||
my @missingBillingFields = $book->missingFields(\%billingData);
|
||||
my $billingAddressId = $form->process('billingAddressId');
|
||||
if ($billingAddressId eq 'new_address' && ! @missingBillingFields) {
|
||||
##Add a new address
|
||||
my $newAddress = $book->addAddress(\%billingData);
|
||||
$cartProperties->{billingAddressId} = $newAddress->get('addressId');
|
||||
}
|
||||
elsif ($billingAddressId eq 'update_address' && $self->get('billingAddressId') && ! @missingBillingFields) {
|
||||
##User updated the current address
|
||||
my $address = $self->getBillingAddress();
|
||||
$address->update(\%billingData);
|
||||
}
|
||||
elsif ($billingAddressId ne 'new_address' && $billingAddressId) {
|
||||
##User changed the address selector to another address field
|
||||
$cartProperties->{billingAddressId} = $billingAddressId;
|
||||
}
|
||||
elsif (@missingBillingFields) {
|
||||
$self->error('missing billing '.$missingBillingFields[0]);
|
||||
}
|
||||
else {
|
||||
$self->session->log->warn('billing address: something else: ');
|
||||
}
|
||||
##Update now, so that you can add an address AND set the shipping address to be the same at the same time.
|
||||
$self->update($cartProperties);
|
||||
|
||||
if ($self->requiresShipping) {
|
||||
if ($form->process('sameShippingAsBilling', 'yesNo')) {
|
||||
$cartProperties->{shippingAddressId} = $self->get('billingAddressId');
|
||||
}
|
||||
else {
|
||||
my %shippingData = $book->processAddressForm('shipping_');
|
||||
my @missingShippingFields = $book->missingFields(\%shippingData);
|
||||
my $shippingAddressId = $form->process('shippingAddressId');
|
||||
##No missing shipping fields, if we set to the same as the billing fields
|
||||
if (@missingShippingFields) {
|
||||
$self->error('missing shipping '.$missingShippingFields[0]);
|
||||
}
|
||||
if ($shippingAddressId eq 'new_address' && ! @missingShippingFields) {
|
||||
##Add a new address
|
||||
my $newAddress = $book->addAddress(\%shippingData);
|
||||
$cartProperties->{shippingAddressId} = $newAddress->get('addressId');
|
||||
}
|
||||
elsif ($shippingAddressId eq 'update_address' && $self->get('shippingAddressId') && ! @missingShippingFields) {
|
||||
##User changed the address selector
|
||||
my $address = $self->getBillingAddress();
|
||||
$address->update(\%shippingData);
|
||||
}
|
||||
elsif ($shippingAddressId ne 'new_address' && $shippingAddressId) {
|
||||
$cartProperties->{shippingAddressId} = $shippingAddressId;
|
||||
}
|
||||
else {
|
||||
$self->session->log->warn('shipping address: something else: ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cartProperties->{ shipperId } = $form->process( 'shipperId' ) if $form->process( 'shipperId' );
|
||||
$cartProperties->{ gatewayId } = $form->process( 'gatewayId' ) if $form->process( 'gatewayId' );
|
||||
$self->update( $cartProperties );
|
||||
|
||||
my @cartItemIds = $form->process('remove_item', 'checkList');
|
||||
foreach my $cartItemId (@cartItemIds) {
|
||||
my $item = eval { $self->getItem($cartItemId); };
|
||||
$item->remove if ! Exception::Class->caught();
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_checkout ( )
|
||||
=head2 www_ajaxPrices
|
||||
|
||||
Update the cart and then redirect the user to the payment gateway screen.
|
||||
Input: shippingId (an addressId)
|
||||
billingId (an addressId)
|
||||
|
||||
Output: {
|
||||
tax : 1.25,
|
||||
subtotal : 12.00,
|
||||
shipping : {
|
||||
slfjaldjfalfja: {
|
||||
label : 'USPS',
|
||||
price : 12.50,
|
||||
hasPrice : 1 || 0
|
||||
},
|
||||
{ ... },
|
||||
{ ... }
|
||||
}
|
||||
}
|
||||
|
||||
Takes an addressId and returns JSON shipping options for it, in the form .
|
||||
|
||||
=cut
|
||||
|
||||
sub www_checkout {
|
||||
my $self = shift;
|
||||
$self->updateFromForm;
|
||||
if ($error{id $self} ne "") {
|
||||
return $self->www_view;
|
||||
}
|
||||
$self->session->http->setRedirect($self->session->url->page('shop=pay;method=selectPaymentGateway'));
|
||||
return undef;
|
||||
sub www_ajaxPrices {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
my $billing = $form->get('billingId');
|
||||
my $shipping = $form->get('shippingId');
|
||||
my $response = {
|
||||
subtotal => $self->calculateSubtotal(),
|
||||
|
||||
tax => eval {
|
||||
my $addr = $shipping || $billing or die;
|
||||
$self->update({ shippingAddressId => $addr });
|
||||
$self->calculateTaxes();
|
||||
} || 0,
|
||||
|
||||
shipping => eval {
|
||||
die unless $shipping;
|
||||
$self->update({ shippingAddressId => $shipping });
|
||||
my $ship = WebGUI::Shop::Ship->new($self->session);
|
||||
$ship->getOptions($self);
|
||||
} || [],
|
||||
};
|
||||
$session->http->setMimeType('text/plain');
|
||||
return JSON->new->encode($response);
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_continueShopping ( )
|
||||
=head2 www_ajaxSetCartItemShippingId
|
||||
|
||||
Update the cart and the return the user back to the asset.
|
||||
Sets the shippingAddressId for a particular cartItem
|
||||
|
||||
=cut
|
||||
|
||||
sub www_continueShopping {
|
||||
my $self = shift;
|
||||
$self->updateFromForm;
|
||||
if ($error{id $self} ne "") {
|
||||
return $self->www_view;
|
||||
}
|
||||
return undef;
|
||||
sub www_ajaxSetCartItemShippingId {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $session->form;
|
||||
my $item = $self->getItem($form->get('itemId'));
|
||||
my $address = $form->get('addressId') || undef;
|
||||
$item && $item->update({ shippingAddressId => $address });
|
||||
$session->http->setMimeType('text/plain');
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
|
@ -683,53 +890,47 @@ sub www_lookupPosUser {
|
|||
return $self->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_removeItem ( )
|
||||
|
||||
Remove an item from the cart and then display the cart again.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_removeItem {
|
||||
my $self = shift;
|
||||
my $item = $self->getItem($self->session->form->get("itemId"));
|
||||
$item->remove;
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_setShippingAddress ()
|
||||
|
||||
Sets the shipping address for the cart or for a cart item if itemId is one of the form params.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_setShippingAddress {
|
||||
my $self = shift;
|
||||
my $form = $self->session->form;
|
||||
if ($form->get("itemId") ne "") {
|
||||
$self->getItem($form->get("itemId"))->update({shippingAddressId=>$form->get('addressId')});
|
||||
}
|
||||
else {
|
||||
$self->update({shippingAddressId=>$form->get('addressId')});
|
||||
}
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 www_update ( )
|
||||
|
||||
Updates the cart totals and then displays the cart again.
|
||||
Updates the cart totals, addresses, shipping driver and payment gateway. If requested, and the
|
||||
cart is ready, calls the www_getCredentials method from the selected payment gateway.
|
||||
|
||||
If the cart total, after taxes, shipping, coupons and shop credit is zero, does the checkout
|
||||
immediately without calling a payment gateway.
|
||||
|
||||
Otherwise, returns the user back to the cart.
|
||||
|
||||
=cut
|
||||
|
||||
sub www_update {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
$self->updateFromForm;
|
||||
if ($session->form->get('continue_shopping')) {
|
||||
return undef;
|
||||
}
|
||||
elsif ($session->form->get('checkout')) {
|
||||
##Setting a shipping address greatly simplifies the Transaction
|
||||
if (! $self->requiresShipping && ! $self->get('shippingAddressId')) {
|
||||
$self->update({shippingAddressId => $self->get('billingAddressId')});
|
||||
}
|
||||
if ($self->readyForCheckout()) {
|
||||
my $total = $self->calculateTotal;
|
||||
##Handle rounding errors, and checkout immediately if the amount is 0 since
|
||||
##at least the ITransact driver won't accept $0 checkout.
|
||||
if (sprintf('%.2f', $total + $self->calculateShopCreditDeduction($total)) eq '0.00') {
|
||||
my $transaction = WebGUI::Shop::Transaction->create($session, {self => $self});
|
||||
$transaction->completePurchase('zero', 'success', 'success');
|
||||
$self->onCompletePurchase;
|
||||
$transaction->sendNotifications();
|
||||
return $transaction->thankYou();
|
||||
}
|
||||
my $gateway = $self->getPaymentGateway;
|
||||
return $gateway->www_getCredentials;
|
||||
}
|
||||
}
|
||||
return $self->www_view;
|
||||
}
|
||||
|
||||
|
|
@ -742,28 +943,16 @@ Displays the shopping cart.
|
|||
=cut
|
||||
|
||||
sub www_view {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $url = $session->url;
|
||||
my $i18n = WebGUI::International->new($session, "Shop");
|
||||
my @items = ();
|
||||
my $url = $session->url;
|
||||
my $form = $session->form;
|
||||
my $i18n = WebGUI::International->new($session, "Shop");
|
||||
my $taxDriver = WebGUI::Shop::Tax->getDriver( $session );
|
||||
|
||||
if($url->forceSecureConnection()){
|
||||
return "redirect";
|
||||
}
|
||||
# set up html header
|
||||
$session->style->setRawHeadTags(q|
|
||||
<script type="text/javascript">
|
||||
function setCallbackForAddressChooser (form, itemId) {
|
||||
form.shop.value='address';
|
||||
form.method.value='view';
|
||||
itemId = (itemId == undefined) ? 'null' : "'" + itemId + "'";
|
||||
form.callback.value='{"url":"|.$url->page.q|","params":[{"name":"shop","value":"cart"},{"name":"method","value":"setShippingAddress"},{"name":"itemId","value":'+itemId+'}]}';
|
||||
form.submit();
|
||||
}
|
||||
</script>
|
||||
|);
|
||||
|
||||
my @cartItems = @{$self->getItems};
|
||||
if(scalar(@cartItems) < 1) {
|
||||
|
|
@ -776,133 +965,242 @@ sub www_view {
|
|||
my $template = WebGUI::Asset::Template->newById($session, $session->setting->get("shopCartTemplateId"));
|
||||
return $session->style->userStyle($template->process(\%var));
|
||||
}
|
||||
|
||||
|
||||
my %var = (
|
||||
%{$self->get},
|
||||
formHeader => WebGUI::Form::formHeader($session)
|
||||
. WebGUI::Form::hidden($session, {name=>"shop", value=>"cart"})
|
||||
. WebGUI::Form::hidden($session, {name=>"method", value=>"update"})
|
||||
. WebGUI::Form::hidden($session, {name=>"itemId", value=>""})
|
||||
,
|
||||
formFooter => WebGUI::Form::formFooter($session),
|
||||
updateButton => WebGUI::Form::submit($session, {value=>$i18n->get("update cart button"), id=>"updateCartButton"}),
|
||||
checkoutButton => WebGUI::Form::submit($session, {name => 'checkout', value=>$i18n->get("checkout button"), id=>"checkoutButton"}),
|
||||
continueShoppingButton => WebGUI::Form::submit($session, {
|
||||
name => 'continue_shopping',
|
||||
value => $i18n->get("continue shopping button"),
|
||||
id => 'continueShoppingButton',
|
||||
}),
|
||||
minimumCartAmount => $session->setting->get( 'shopCartCheckoutMinimum' ) > 0
|
||||
? sprintf( '%.2f', $session->setting->get( 'shopCartCheckoutMinimum' ) )
|
||||
: 0
|
||||
,
|
||||
userIsVisitor => $session->user->isVisitor,
|
||||
shippableItemsInCart => $self->requiresShipping,
|
||||
);
|
||||
|
||||
|
||||
# get the shipping address
|
||||
my $address = eval { $self->getShippingAddress };
|
||||
if (my $e = WebGUI::Error->caught("WebGUI::Error::ObjectNotFound") && $self->get('shippingAddressId')) {
|
||||
# choose another address cuz we've got a problem
|
||||
$self->update({shippingAddressId=>''});
|
||||
}
|
||||
|
||||
# generate template variables for the items in the cart
|
||||
my @items = ();
|
||||
tie my %addressOptions, 'Tie::IxHash';
|
||||
if (! $var{userIsVisitor}) {
|
||||
my $addressBook = $self->getAddressBook;
|
||||
my $addresses = $addressBook->getAddresses;
|
||||
foreach my $address (@{ $addresses }) {
|
||||
$addressOptions{$address->get('addressId')} = $address->get('label');
|
||||
}
|
||||
}
|
||||
|
||||
tie my %specialAddressOptions, 'Tie::IxHash';
|
||||
$specialAddressOptions{''} = $i18n->get("Special shipping");
|
||||
%specialAddressOptions = (%specialAddressOptions, %addressOptions);
|
||||
|
||||
foreach my $item (@cartItems) {
|
||||
my $sku = $item->getSku;
|
||||
$sku->applyOptions($item->get("options"));
|
||||
my %properties = (
|
||||
%{$item->get},
|
||||
url => $sku->getUrl("shop=cart;method=viewItem;itemId=".$item->getId),
|
||||
quantityField => WebGUI::Form::integer($session, {name=>"quantity-".$item->getId, value=>$item->get("quantity")}),
|
||||
isUnique => ($sku->getMaxAllowedInCart == 1),
|
||||
isShippable => $sku->isShippingRequired,
|
||||
extendedPrice => $self->formatCurrency($sku->getPrice * $item->get("quantity")),
|
||||
price => $self->formatCurrency($sku->getPrice),
|
||||
removeButton => WebGUI::Form::submit($session, {value=>$i18n->get("remove button"),
|
||||
extras=>q|onclick="this.form.method.value='removeItem';this.form.itemId.value='|.$item->getId.q|';this.form.submit;"|}),
|
||||
shipToButton => WebGUI::Form::submit($session, {value=>$i18n->get("ship to button"),
|
||||
extras=>q|onclick="setCallbackForAddressChooser(this.form,'|.$item->getId.q|');"|}),
|
||||
);
|
||||
my $address = eval {$item->getShippingAddress};
|
||||
unless (WebGUI::Error->caught) {
|
||||
$properties{shippingAddress} = $address->getHtmlFormatted;
|
||||
url => $sku->getUrl("shop=cart;method=viewItem;itemId=".$item->getId),
|
||||
quantityField => WebGUI::Form::integer($session, {name=>"quantity-".$item->getId, value=>$item->get("quantity"), size=>5,}),
|
||||
isUnique => ($sku->getMaxAllowedInCart == 1),
|
||||
isShippable => $sku->isShippingRequired,
|
||||
extendedPrice => $self->formatCurrency($sku->getPrice * $item->get("quantity")),
|
||||
price => $self->formatCurrency($sku->getPrice),
|
||||
removeBox => WebGUI::Form::checkbox($session, {name => 'remove_item', value => $item->get('itemId')}),
|
||||
);
|
||||
my $itemAddress = eval {$item->getShippingAddress};
|
||||
my $itemAddressId;
|
||||
if ((!WebGUI::Error->caught) && $itemAddress && $address && $itemAddress->getId ne $address->getId) {
|
||||
$properties{shippingAddress} = $itemAddress->getHtmlFormatted;
|
||||
$itemAddressId = $itemAddress->getId;
|
||||
}
|
||||
else {
|
||||
$properties{shippingAddress} = '';
|
||||
$itemAddressId = '';
|
||||
}
|
||||
if (! $var{userIsVisitor} && @cartItems > 1) {
|
||||
$properties{itemAddressChooser} = WebGUI::Form::selectBox($session, {
|
||||
name => "itemAddress_".$item->getId,
|
||||
value => $itemAddressId,
|
||||
options => \%specialAddressOptions,
|
||||
extras => q|class="itemAddressMenu"|,
|
||||
});
|
||||
}
|
||||
|
||||
$taxDriver->appendCartItemVars( \%properties, $item );
|
||||
|
||||
push(@items, \%properties);
|
||||
}
|
||||
my %var = (
|
||||
%{$self->get},
|
||||
items => \@items,
|
||||
formHeader => WebGUI::Form::formHeader($session)
|
||||
. WebGUI::Form::hidden($session, {name=>"shop", value=>"cart"})
|
||||
. WebGUI::Form::hidden($session, {name=>"method", value=>"update"})
|
||||
. WebGUI::Form::hidden($session, {name=>"itemId", value=>""})
|
||||
. WebGUI::Form::hidden($session, {name=>"callback", value=>""}),
|
||||
formFooter => WebGUI::Form::formFooter($session),
|
||||
updateButton => WebGUI::Form::submit($session, {value=>$i18n->get("update cart button"), extras=>q|id="updateCartButton"|}),
|
||||
checkoutButton => WebGUI::Form::submit($session, {value=>$i18n->get("checkout button"),
|
||||
extras=>q|onclick="this.form.method.value='checkout';this.form.submit;" id="checkoutButton"|}),
|
||||
continueShoppingButton => WebGUI::Form::submit($session, {value=>$i18n->get("continue shopping button"),
|
||||
extras=>q|onclick="this.form.method.value='continueShopping';this.form.submit;" id="continueShoppingButton"|}),
|
||||
chooseShippingButton => WebGUI::Form::submit($session, {value=>$i18n->get("choose shipping button"),
|
||||
extras=>q|onclick="setCallbackForAddressChooser(this.form);" id="chooseAddressButton"|}),
|
||||
shipToButton => WebGUI::Form::submit($session, {value=>$i18n->get("ship to button"),
|
||||
extras=>q|onclick="setCallbackForAddressChooser(this.form);"|}),
|
||||
subtotalPrice => $self->formatCurrency($self->calculateSubtotal()),
|
||||
minimumCartAmount => $session->setting->get( 'shopCartCheckoutMinimum' ) > 0
|
||||
? sprintf( '%.2f', $session->setting->get( 'shopCartCheckoutMinimum' ) )
|
||||
: 0
|
||||
,
|
||||
);
|
||||
|
||||
# get the shipping address
|
||||
my $address = eval { $self->getShippingAddress };
|
||||
if (my $e = WebGUI::Error->caught("WebGUI::Error::ObjectNotFound")) {
|
||||
# choose another address cuz we've got a problem
|
||||
$self->update({shippingAddressId=>''});
|
||||
|
||||
}
|
||||
|
||||
# if there is no shipping address we can't check out
|
||||
if (WebGUI::Error->caught) {
|
||||
$var{shippingPrice} = $var{tax} = $self->formatCurrency(0);
|
||||
}
|
||||
|
||||
# if there is a shipping address calculate tax and shipping options
|
||||
else {
|
||||
$var{hasShippingAddress} = 1;
|
||||
$var{shippingAddress} = $address->getHtmlFormatted;
|
||||
my $ship = WebGUI::Shop::Ship->new(session => $self->session);
|
||||
$var{items} = \@items;
|
||||
if ($var{shippableItemsInCart}) {
|
||||
my $ship = WebGUI::Shop::Ship->new($self->session);
|
||||
my $options = $ship->getOptions($self);
|
||||
my $numberOfOptions = scalar keys %{ $options };
|
||||
if ($numberOfOptions < 1) {
|
||||
if (! $numberOfOptions) {
|
||||
$var{shippingOptions} = '';
|
||||
$var{shippingPrice} = 0;
|
||||
$error{id $self} = $i18n->get("No shipping plugins configured");
|
||||
}
|
||||
elsif ($numberOfOptions == 1) {
|
||||
my ($option) = keys %{ $options };
|
||||
$self->update({ shipperId => $option });
|
||||
$var{shippingPrice} = $options->{$self->get("shipperId")}->{price};
|
||||
$var{shippingPrice} = $self->formatCurrency($var{shippingPrice});
|
||||
$self->error($i18n->get("No shipping plugins configured"));
|
||||
}
|
||||
else {
|
||||
tie my %formOptions, 'Tie::IxHash';
|
||||
$formOptions{''} = $i18n->get('Choose a shipping method');
|
||||
foreach my $option (keys %{$options}) {
|
||||
$formOptions{$option} = $options->{$option}{label}." (".$self->formatCurrency($options->{$option}{price}).")";
|
||||
foreach my $optionId (keys %{$options}) {
|
||||
$formOptions{$optionId} = $options->{$optionId}{label};
|
||||
if ($options->{$optionId}->{hasPrice}) {
|
||||
$formOptions{$optionId} .= ' ('.$self->formatCurrency($options->{$optionId}{price}).')';
|
||||
}
|
||||
}
|
||||
$var{shippingOptions} = WebGUI::Form::selectBox($session, {name=>"shipperId", options=>\%formOptions, value=>$self->get("shipperId")});
|
||||
if (!exists $options->{$self->get('shipperId')}) {
|
||||
my $shipperId = $self->get('shipperId');
|
||||
if (!$shipperId && $numberOfOptions == 1) {
|
||||
my ($option) = keys %{ $options };
|
||||
$self->update({shipperId => $option});
|
||||
$shipperId = $option;
|
||||
}
|
||||
$var{shippingOptions} = WebGUI::Form::selectBox($session, {name=>"shipperId", options=>\%formOptions, value=>$shipperId || ''});
|
||||
if (!exists $options->{$shipperId}) {
|
||||
$self->update({shipperId => ''});
|
||||
$shipperId = '';
|
||||
}
|
||||
if (my $shipperId = $self->get('shipperId')) {
|
||||
if ($shipperId) {
|
||||
$var{shippingPrice} = $options->{$shipperId}->{price};
|
||||
}
|
||||
else {
|
||||
$var{shippingPrice} = 0;
|
||||
$error{id $self} = ($i18n->get('Choose a shipping method and update the cart to checkout'));
|
||||
$self->error($i18n->get('Choose a shipping method and update the cart to checkout'));
|
||||
}
|
||||
$var{shippingPrice} = $self->formatCurrency($var{shippingPrice});
|
||||
$var{shippingPrice} = $shipperId && $options->{$shipperId}->{hasPrice} ? $self->formatCurrency($var{shippingPrice}) : '';
|
||||
$var{tax} = $self->calculateTaxes;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
$var{shippingPrice} = $var{tax} = $self->formatCurrency(0);
|
||||
}
|
||||
|
||||
|
||||
# Tax variables
|
||||
$var{tax} = $self->calculateTaxes;
|
||||
|
||||
#Address form variables
|
||||
if ($var{userIsVisitor}) {
|
||||
$var{loginFormHeader} = WebGUI::Form::formHeader($session, {action => $session->url->page})
|
||||
. WebGUI::Form::hidden($session,{ name => 'op', value => 'auth'})
|
||||
. WebGUI::Form::hidden($session,{ name => 'method', value => 'login'})
|
||||
;
|
||||
$var{loginFormUsername} = WebGUI::Form::text($session, { name => 'username', size => 12, });
|
||||
$var{loginFormPassword} = WebGUI::Form::password($session, { name => 'identifier', size => 12, });
|
||||
$var{loginFormButton} = WebGUI::Form::submit($session, { value => $i18n->get(52,'WebGUI'), });
|
||||
$var{registerLink} = $session->url->page('op=auth;method=createAccount');
|
||||
$session->scratch->set('redirectAfterLogin', $session->url->page('shop=cart'));
|
||||
$var{loginFormFooter} = WebGUI::Form::formFooter($session)
|
||||
}
|
||||
else {
|
||||
##Address form variables
|
||||
tie my %billingAddressOptions, 'Tie::IxHash';
|
||||
$billingAddressOptions{'new_address'} = $i18n->get('Add new address');
|
||||
|
||||
my $billingAddressId = $self->get('billingAddressId');
|
||||
if ($billingAddressId) {
|
||||
$billingAddressOptions{'update_address'} = $i18n->get('Update this address');
|
||||
}
|
||||
|
||||
%billingAddressOptions = (%billingAddressOptions, %addressOptions);
|
||||
|
||||
$var{'billingAddressChooser'} = WebGUI::Form::selectBox($session, {
|
||||
name => 'billingAddressId',
|
||||
options => \%billingAddressOptions,
|
||||
value => $billingAddressId ? $billingAddressId : 'new_address',
|
||||
});
|
||||
|
||||
tie my %shippingAddressOptions, 'Tie::IxHash';
|
||||
$shippingAddressOptions{'new_address'} = $i18n->get('Add new address');
|
||||
|
||||
my $shippingAddressId = $self->get('shippingAddressId');
|
||||
if ($shippingAddressId) {
|
||||
$shippingAddressOptions{'update_address'} = $i18n->get('Update this address');
|
||||
}
|
||||
%shippingAddressOptions = (%shippingAddressOptions, %addressOptions);
|
||||
|
||||
$var{'shippingAddressChooser'} = WebGUI::Form::selectBox($session, {
|
||||
name => 'shippingAddressId',
|
||||
options => \%shippingAddressOptions,
|
||||
value => $shippingAddressId ? $shippingAddressId : 'new_address',
|
||||
});
|
||||
|
||||
my $shippingAddressData = $self->get('shippingAddressId') ? $self->getShippingAddress->get() : {};
|
||||
my $billingAddressData = $self->get('billingAddressId') ? $self->getBillingAddress->get() : {};
|
||||
my $addressBook = $self->getAddressBook;
|
||||
$addressBook->appendAddressFormVars(\%var, 'shipping_', $shippingAddressData);
|
||||
$addressBook->appendAddressFormVars(\%var, 'billing_', $billingAddressData);
|
||||
|
||||
$var{sameShippingAsBilling} = WebGUI::Form::yesNo($session, {
|
||||
name => 'sameShippingAsBilling',
|
||||
value => $self->get('billingAddressId') && $self->get('billingAddressId') eq $self->get('shippingAddressId'),
|
||||
});
|
||||
}
|
||||
|
||||
# Payment methods
|
||||
my $pay = WebGUI::Shop::Pay->new($session);
|
||||
tie my %paymentOptions, 'Tie::IxHash';
|
||||
$paymentOptions{''} = $i18n->get('Choose a payment method');
|
||||
my $gateways = $pay->getOptions($self);
|
||||
while (my ($gatewayId, $label) = each %{ $gateways }) {
|
||||
$paymentOptions{$gatewayId} = $label;
|
||||
}
|
||||
$var{paymentOptions} = WebGUI::Form::selectBox($session, {
|
||||
name => 'gatewayId',
|
||||
options => \%paymentOptions,
|
||||
value => $self->get('gatewayId') || $form->get('gatewayId') || '',
|
||||
});
|
||||
|
||||
# POS variables
|
||||
$var{isCashier} = WebGUI::Shop::Admin->new($session)->isCashier;
|
||||
$var{isCashier} = WebGUI::Shop::Admin->new($session)->isCashier;
|
||||
$var{posLookupForm} = WebGUI::Form::email($session, {name=>"posEmail"})
|
||||
.WebGUI::Form::submit($session, {value=>$i18n->get('search for email'),
|
||||
extras=>q|onclick="this.form.method.value='lookupPosUser';this.form.submit;"|});
|
||||
my $posUser = $self->getPosUser;
|
||||
my $posUser = $self->getPosUser;
|
||||
$var{posUsername} = $posUser->username;
|
||||
$var{posUserId} = $posUser->userId;
|
||||
$var{posUserId} = $posUser->userId;
|
||||
|
||||
# calculate price adjusted for in-store credit
|
||||
$var{totalPrice} = $var{subtotalPrice} + $var{shippingPrice} + $var{tax};
|
||||
$var{subtotalPrice} = $self->formatCurrency($self->calculateSubtotal());
|
||||
$var{totalPrice} = $var{subtotalPrice} + $var{shippingPrice} + $var{tax};
|
||||
my $credit = WebGUI::Shop::Credit->new($session, $posUser->userId);
|
||||
$var{ inShopCreditAvailable } = $credit->getSum;
|
||||
$var{ inShopCreditDeduction } = $credit->calculateDeduction($var{totalPrice});
|
||||
$var{ totalPrice } = $self->formatCurrency($var{totalPrice} + $var{inShopCreditDeduction});
|
||||
$var{ readyForCheckout } = $self->readyForCheckout;
|
||||
$var{ error } = $error{id $self};
|
||||
foreach my $field (qw/subtotalPrice inShopCreditAvailable inShopCreditDeduction totalPrice shippingPrice tax/) {
|
||||
$var{$field} = sprintf q|<span id="%sWrap">%s</span>|, $field, $var{$field};
|
||||
}
|
||||
$var{ error } = $self->error;
|
||||
|
||||
# render the cart
|
||||
my $template = WebGUI::Asset::Template->newById($session, $session->setting->get("shopCartTemplateId"));
|
||||
my $template = WebGUI::Asset->newById($session, $session->setting->get("shopCartTemplateId"));
|
||||
|
||||
my $style = $session->style;
|
||||
my $yui = $url->extras('/yui/build');
|
||||
$style->setScript("$yui/yahoo/yahoo-min.js");
|
||||
$style->setScript("$yui/json/json-min.js");
|
||||
$style->setScript("$yui/event/event-min.js");
|
||||
$style->setScript("$yui/connection/connection-min.js");
|
||||
$style->setScript($url->extras('underscore/underscore-min.js'));
|
||||
$style->setScript($url->extras('shop/cart.js'), undef, 1);
|
||||
return $session->style->userStyle($template->process(\%var));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue