The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Apache::iNcom::CartManager - Object responsible for managing the user shopping cart.

SYNOPSIS

    $Cart->order( \%item );
    my $items = $Cart->items;
    $Cart->empty;

DESCRIPTION

This is the part of the Apache::iNcom framework that is responsible for managing the user shopping cart. It keep tracks of the ordered items and is also responsible for the pricing of the order. It this is module that computes taxes, discount, price, shipping, etc.

DESIGN RATIONALE

Well not completly since all these operations are delegated to user implemented functions implemented in a pricing profile. The idea behind it is to make policy external to the framework. One thing that varies considerably between different applications is the pricing, discount, taxes, etc. So this is left to the implementation of the application programmer.

PRICING PROFILE

The pricing profile is a file which is C{eval}-ed at runtime. (It is also reloaded whenever it changes on disk. It should return an hash reference which may contains the following key :

item_price

The function should return the price of the item. The function is passed only one parameter : the item which we should compute the price.

    Ex: item_price => sub {
        my $item = shift;
        my $data = $DB->template_get( "product", $item->{code} );
        return $data->{price};
    }
item_discount

The function should return the discounts that apply for that particular item. It can return zero or more discounts. It returning more that one discount return a an array reference. Discount are substracted from the item price so don't return a percentage.

    Ex: item_discount => sub {
        my $item = shift;

        # Discount are relative to item and quantity
        my $data = $DB->template_get( "discount", $item->{code},
                                      $item->{quantity} );
        return unless $data; # No discount

        # Discount is proportional to the price
        return $item->{price} * $data->{discount};
    }

The subtotal of the cart is equal to the sum of

        ($item->{price} - $item->{discount}) * $item->{quantity}
shipping

This function determines the shipping charges that will be added to the subtotal. The function receives as arguments the subtotal of the cart and an array ref to the cart's items. It should return zero or more shipping charges that will be added to the subtotal. If returning more that one charges, return an array reference.

    Ex: shipping => sub {
            # Flat fee based shipping charges
            if ( $Session{shipping} eq "ONE_NIGHT" ) {
                return 45;
            } else {
                return 15;
            }
        }
discount

That function determines discount that will be substracted from the subtotal. Function is called with 3 arguments, the subtotal of the cart, the shipping charges and an array reference to the cart's items. Again the function may elect to return zero or more discounts and should return an array reference if returning more that one discounts.

    Ex: discount => sub {
        my $subtotal = shift;
        my $user = $Request->user;
        return unless $user->{discount};

        return $subtotal * $user->{discount};
    }
taxes

That functions determines the taxes charges that will be added to the order. It should return zero or more taxes. If the functions returns more that one taxes, it should return an array reference. The functions receives 4 arguments, the cart's subtotal, the shipping charges, the discount and the cart's items as an array reference.

    Ex: taxes => sub {
        my ( $sub, $ship, $disc ) = @_;

        # We only charges taxes to Quebec's resident. All our
        # items are taxable and is shipping.
        if ( ${$Request->user}->{province} eq "QC" ) {
            my $taxable = $sub + $ship - $disc;
            my $gst = $taxable * 0.07
            my $gsp = ($taxable + $gst) * 0.075

            return [ $gst, $gsp ];
        } else {
            return undef;
        }
    }

If one of these functions is left undefined. The framework will create one on the fly which will return 0. (No taxes, no discount, no shipping charges, item is free, etc).

All those functions are defined and execute in the namespace of the pages which will use the $Cart object. This means that those functions have access to the standard Apache::iNcom globals ($Request, %Session, $Localizer, $Locale, etc ). DONT ABUSE IT. Also, don't call any methods on the $Cart object or you'll die of infinite recursion.

WHAT IS AN ITEM

An item is simply an hash with some reserved key names. All other keys are ignored by the CartManager. Each item with the same (non reserved) key values is assumed to be identic in terms of price, discount, etc.

This design was chosen to handle the infinite variety of item attributes (color, size, variant, ...). The framework doesn't need knowledge of those, only the application specific part. (The pricing functions.)

These are reserved names and can't be used as item attributes : quantity, price, discount, subtotal

INITIALIZATION

An object is automatically initialized on each request by the Apache::iNcom framework. It is accessible through the $Cart global variable in Apache::iNcom pages.

METHODS

order ( \%item, ... )

This method will add all the specified items (hash reference) to the Cart. The quantity ordered should be specified in the quantity attribute. (If unspecified, it is assumed to be one). If an identical item is already in the cart, the quantity will be added.

Use a negative quantity to remove from the quantity ordered. If the new quantity is lower or equal to zero it will be removed.

Use a quantity of 0 to remove an item.

empty

Removes all items from the cart.

is_empty

Return true if no items are in the cart.

items

Return all the ordered items as an array. Each item have the following attribute set :

quantity

The quantity of the item ordered.

price

The price of that item.

discount

The discounts applied to this item.

subtotal

That item subtotal.

subtotal

Returns the cart subtotal. (This is before global discount, shipping charges and taxes.)

taxes

Returns the taxes that will be added to the order.

total

Returns the order total. (subtotal + shipping charges - discounts + taxes ).

discount

Returns the overall discount that applied to this order.

shipping

Returns the shipping charges for this order.

item_price ( \%item )

Returns the price of the item specified. If no quantity is specified, a quantity of 1 is assumed. This method doesn't modify the cart.

item_discount ( \%item )

Returns the discounts associated with the specified item. It no quantity is specified, a quantity of 1 is assumed. This method doesn't modify the cart.

item_pricing ( \%item )

Returns the item as it would be added to the cart. quantity, price, discount and subtotal will be set in the returned item. This method doesn't modify the cart.

AUTHOR

Copyright (c) 1999 Francis J. Lacoste and iNsu Innovations Inc. All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

SEE ALSO

Apache::iNcom(3) Apache::iNcom::Request(3) Apache::iNcom::OrderManager(3)