Catalyst::Helper::Controller::Handel::Checkout - Helper for Handel::Checkout Controllers


Handel documentation Contained in the Handel distribution.

Index


Code Index:

NAME

Top

Catalyst::Helper::Controller::Handel::Checkout - Helper for Handel::Checkout Controllers

SYNOPSIS

Top

    script/create.pl controller <newclass> Handel::Checkout [<cartmodel> <ordermodel> <cartcontroller> <ordercontroller>]
    script/create.pl controller Checkout Handel::Checkout

DESCRIPTION

Top

A Helper for creating controllers based on Handel::Checkout objects. IF no cartmodel or ordermodel was specified, ::M::Cart and ::M::Orders is assumed.

The cartmode, ordermodel, cartcontroller and ordercontroller arguments try to do the right thing with the names given to them.

For example, you can pass the shortened class name without the MyApp::M/C, or pass the fully qualified package name:

    MyApp::M::CartModel
    MyApp::Model::CartModel
    CartModel

In all three cases everything before M{odel)|C(ontroller) will be stripped and the class CartModel will be used.

The code generated by this helper requires FormValidator::Simple, HTML::FIllInForm and YAML to be installed to operate.

METHODS

Top

mk_compclass

Makes a Handel::Checkout Controller class and template files for you.

mk_comptest

Makes a Handel::Checkout Controller test for you.

SEE ALSO

Top

Catalyst::Manual, Catalyst::Helper, Handel::Checkout

AUTHOR

Top

    Christopher H. Laco
    CPAN ID: CLACO
    claco@chrislaco.com
    http://today.icantfocus.com/blog/


Handel documentation Contained in the Handel distribution.
# $Id$
## no critic (ProhibitCaptureWithoutTest)
package Catalyst::Helper::Controller::Handel::Checkout;
use strict;
use warnings;

BEGIN {
    use Catalyst 5.7001;
    use Catalyst::Utils;
    use Path::Class;
};

sub mk_compclass {
    my ($self, $helper, $cmodel, $omodel, $ccontroller, $ocontroller) = @_;
    my $file = $helper->{'file'};
    my $dir  = dir($helper->{'base'}, 'root', $helper->{'uri'});

    $cmodel      ||= 'Cart';
    $omodel      ||= 'Order';
    $ccontroller ||= 'Cart';
    $ocontroller ||= 'Order';

    $ccontroller =~ /^(.*::C(ontroller)?::)?(.*)$/i;
    $ccontroller = $3 ? $3 : 'Cart';
    $helper->{'ccontroller'} = $ccontroller;

    $ocontroller =~ /^(.*::C(ontroller)?::)?(.*)$/i;
    $ocontroller = $3 ? $3 : 'Order';
    $helper->{'ocontroller'} = $ocontroller;

    $cmodel =~ /^(.*::M(odel)?::)?(.*)$/i;
    $cmodel = $3 ? $3 : 'Cart';
    $helper->{'cmodel'} = $cmodel;

    $omodel =~ /^(.*::M(odel)?::)?(.*)$/i;
    $omodel = $3 ? $3 : 'Order';
    $helper->{'omodel'} = $omodel;

    #$ccontroller =~ /^(.*::C(ontroller)?::)?(.*)$/i;
    my $curi = $ccontroller;
    $curi =~ s/::/\//g;
    $helper->{'curi'} = $curi;

    #$ocontroller =~ /^(.*::C(ontroller)?::)?(.*)$/i;
    my $ouri = $ocontroller;
    $ouri =~ s/::/\//g;
    $helper->{'ouri'} = $ouri;

    $helper->{'action'} = Catalyst::Utils::class2prefix($helper->{'class'});

    $helper->mk_dir($dir);
    $helper->render_file('controller', $file);

    $helper->render_file('default', file($dir, 'default'));
    $helper->render_file('billing', file($dir, 'billing'));
    $helper->render_file('billing', file($dir, 'billing'));
    $helper->render_file('preview', file($dir, 'preview'));
    $helper->render_file('payment', file($dir, 'payment'));
    $helper->render_file('complete', file($dir, 'complete'));

    $helper->render_file('errors', file($dir, 'errors'));
    $helper->render_file('profiles', file($dir, 'profiles.yml'));
    $helper->render_file('messages', file($dir, 'messages.yml'));

    return 1;
};

sub mk_comptest {
    my ($self, $helper) = @_;
    my $test = $helper->{'test'};

    $helper->render_file('test', $test);

    return 1;
};

1;
__DATA__

sub COMPONENT {
    my $self = shift->NEXT::COMPONENT(@_);

    $self->{'validator'} = FormValidator::Simple->new;
    $self->{'validator'}->set_messages(
        $_[0]->path_to('root', '[% action %]', 'messages.yml')
    );

    $self->{'fif'} = HTML::FillInForm->new;

    $self->{'profiles'} = YAML::LoadFile($_[0]->path_to('root', '[% action %]', 'profiles.yml'));

    return $self;
};

sub default : Private {
    my ($self, $c) = @_;
    $c->stash->{'template'} = '[% action %]/default';

    if ($c->forward('load')) {
        $c->res->redirect($c->uri_for('[% uri %]/billing/'));
    };

    return;
};

sub billing : Local {
    my ($self, $c) = @_;
    $c->stash->{'template'} = '[% action %]/billing';

    if (my $order = $c->forward('load')) {
        $c->stash->{'order'} = $order;

        if ($c->req->method eq 'POST') {
            if ($c->forward('validate')) {
                my $checkout = Handel::Checkout->new({
                    order  => $order,
                    phases => 'CHECKOUT_PHASE_VALIDATE'
                });

                if ($checkout->process == CHECKOUT_STATUS_OK) {
                    if ($checkout->order->update($c->req->params)) {
                        $c->res->redirect($c->uri_for('[% uri %]/preview/'));
                    };
                } else {
                    $c->stash->{'errors'} = $checkout->messages;
                };
            };
        };
    } else {
        $c->res->redirect($c->uri_for('[% uri %]/'));
    };

    return;
};

sub load : Private {
    my ($self, $c) = @_;

    if ($c->sessionid && $c->session->{'shopper'}) {
        if (my $order = $c->forward($c->controller('[% ocontroller %]'), 'load')) {
            $order->reconcile(
                $c->forward($c->controller('[% ccontroller %]'), 'load')
            );

            return $order;
        } elsif (my $cart = $c->forward($c->controller('[% ccontroller %]'), 'load')) {
            if ($cart->count) {
                if (my $order = $c->forward($c->controller('[% ocontroller %]'), 'create', [$cart])) {
                    
                    my $checkout = Handel::Checkout->new({
                        order   => $order,
                        phases => 'CHECKOUT_PHASE_INITIALIZE'
                    });

                    if ($checkout->process != CHECKOUT_STATUS_OK) {
                        $c->stash->{'errors'} = $checkout->messages;
                    };                    
                    
                    return $checkout->order;
                };
            };
        };
    };

    return;
};

sub payment : Local {
    my ($self, $c) = @_;
    $c->stash->{'template'} = '[% action %]/payment';

    if (my $order = $c->forward('load')) {
        $c->stash->{'order'} = $order;

        if ($c->req->method eq 'POST') {
            if ($c->forward('validate')) {
                my $checkout = Handel::Checkout->new({
                    order  => $order,
                    phases => 'CHECKOUT_PHASE_AUTHORIZE, CHECKOUT_PHASE_FINALIZE, CHECKOUT_PHASE_DELIVER'
                });

                if ($checkout->process == CHECKOUT_STATUS_OK) {
                    if ($checkout->order->update) {
                        eval {
                            $c->model('[% cmodel %]')->destroy({
                                shopper => $c->session->{'shopper'},
                                type    => CART_TYPE_TEMP
                            });
                        };
                        $c->stash->{'order'} = $checkout->order;
                        $c->forward('complete');
                    };
                } else {
                    $c->stash->{'errors'} = $checkout->messages;
                };
            };
        };
    } else {
        $c->res->redirect($c->uri_for('[% uri %]/'));
    };

    return;
};

sub preview : Local {
    my ($self, $c) = @_;
    $c->stash->{'template'} = '[% action %]/preview';

    if (my $order = $c->forward('load')) {
        $c->stash->{'order'} = $order;
    } else {
        $c->res->redirect($c->uri_for('[% uri %]/'));
    };

    return;
};

sub complete : Local {
    my ($self, $c) = @_;
    $c->stash->{'template'} = '[% action %]/complete';

    if (!$c->stash->{'order'}) {
        $c->res->redirect($c->uri_for('[% uri %]/'));
    };
};

sub render : ActionClass('RenderView') {};

sub end : Private { 
    my ($self, $c) = @_;
    $c->forward('render');

    if ($c->req->method eq 'POST') {
        $c->res->output(
            $self->{'fif'}->fill(
                scalarref => \$c->response->{body},
                fdat => $c->req->params
            )
        );
    };
};

sub validate : Private {
    my ($self, $c) = @_;

    $self->{'validator'}->results->clear;

    my $results = $self->{'validator'}->check(
        $c->req,
        $self->{'profiles'}->{$c->action}
    );

    if ($results->success) {
        return $results;
    } else {
        $c->stash->{'errors'} = $results->messages($c->action);
    };

    return;
};

1;
__test__
use Test::More tests => 3;
use strict;
use warnings;

use_ok('Catalyst::Test', '[% app %]');
use_ok('[% class %]');

ok(request('[% uri %]')->is_success, 'Request should succeed');
__default__
<h1>Checkout</h1>
<p>Your shopping cart is empty.</p>
__billing__
[% TAGS [- -] -%]
[% USE HTML %]
<h1>Billing/Shipping Information</h1>
[% INCLUDE [- action -]/errors %]
<form action="[% c.uri_for('[- uri -]/billing/') %]" method="POST">
    <table border="0" cellpadding="3" cellspacing="5">
        <tr>
            <th colspan="2" align="left">Billing</th>
            <th width="25"></th>
            <th colspan="2" align="left">Shipping</th>
        </tr>
        <tr>
            <td colspan="5" height="5">&nbsp;</td>
        </tr>
        <tr>
            <td align="right">First Name:</td>
            <td align="left"><input type="text" name="billtofirstname" value="[% HTML.escape(order.billtofirstname) %]" tabindex="1"></td>
            <td></td>
            <td align="right">First Name:</td>
            <td align="left"><input type="text" name="shiptofirstname" value="[% HTML.escape(order.shiptofirstname) %]" tabindex="14"></td>
        </tr>
        <tr>
            <td align="right">Last Name:</td>
            <td align="left"><input type="text" name="billtolastname" value="[% HTML.escape(order.billtolastname) %]" tabindex="2"></td>
            <td></td>
            <td align="right">Last Name:</td>
            <td align="left"><input type="text" name="shiptolastname" value="[% HTML.escape(order.shiptolastname) %]" tabindex="15"></td>
        </tr>
        <tr>
            <td colspan="5" height="5">&nbsp;</td>
        </tr>
        <tr>
            <td align="right">Address:</td>
            <td align="left"><input type="text" name="billtoaddress1" value="[% HTML.escape(order.billtoaddress1) %]" tabindex="3"></td>
            <td></td>
            <td align="right">Address:</td>
            <td align="left"><input type="text" name="shiptoaddress1" value="[% HTML.escape(order.shiptoaddress1) %]" tabindex="16"></td>
        </tr>
        <tr>
            <td align="right"></td>
            <td align="left"><input type="text" name="billtoaddress2" value="[% HTML.escape(order.billtoaddress2) %]" tabindex="4"></td>
            <td></td>
            <td align="right"></td>
            <td align="left"><input type="text" name="shiptoaddress2" value="[% HTML.escape(order.shiptoaddress2) %]" tabindex="17"></td>
        </tr>
        <tr>
            <td align="right"></td>
            <td align="left"><input type="text" name="billtoaddress3" value="[% HTML.escape(order.billtoaddress3) %]" tabindex="5"></td>
            <td></td>
            <td align="right"></td>
            <td align="left"><input type="text" name="shiptoaddress3" value="[% HTML.escape(order.shiptoaddress3) %]" tabindex="18"></td>
        </tr>
        <tr>
            <td align="right">City:</td>
            <td align="left"><input type="text" name="billtocity" value="[% HTML.escape(order.billtocity) %]" tabindex="6"></td>
            <td></td>
            <td align="right">City:</td>
            <td align="left"><input type="text" name="shiptocity" value="[% HTML.escape(order.shiptocity) %]" tabindex="19"></td>
        </tr>
        <tr>
            <td align="right">State/Province:</td>
            <td align="left"><input type="text" name="billtostate" value="[% HTML.escape(order.billtostate) %]" tabindex="7"></td>
            <td></td>
            <td align="right">State/Province:</td>
            <td align="left"><input type="text" name="shiptostate" value="[% HTML.escape(order.shiptostate) %]" tabindex="20"></td>
        </tr>
        <tr>
            <td align="right">Zip/Postal Code:</td>
            <td align="left"><input type="text" name="billtozip" value="[% HTML.escape(order.billtozip) %]" tabindex="8"></td>
            <td></td>
            <td align="right">Zip/Postal Code:</td>
            <td align="left"><input type="text" name="shiptozip" value="[% HTML.escape(order.shiptozip) %]" tabindex="21"></td>
        </tr>
        <tr>
            <td align="right">Country:</td>
            <td align="left"><input type="text" name="billtocountry" value="[% HTML.escape(order.billtocountry) %]" tabindex="9"></td>
            <td></td>
            <td align="right">Country:</td>
            <td align="left"><input type="text" name="shiptocountry" value="[% HTML.escape(order.shiptocountry) %]" tabindex="22"></td>
        </tr>
        <tr>
            <td align="right">Day Phone:</td>
            <td align="left"><input type="text" name="billtodayphone" value="[% HTML.escape(order.billtodayphone) %]" tabindex="10"></td>
            <td></td>
            <td align="right">Day Phone:</td>
            <td align="left"><input type="text" name="shiptodayphone" value="[% HTML.escape(order.shiptodayphone) %]" tabindex="23"></td>
        </tr>
        <tr>
            <td align="right">Night Phone:</td>
            <td align="left"><input type="text" name="billtonightphone" value="[% HTML.escape(order.billtonightphone) %]" tabindex="11"></td>
            <td></td>
            <td align="right">Night Phone:</td>
            <td align="left"><input type="text" name="shiptonightphone" value="[% HTML.escape(order.shiptonightphone) %]" tabindex="24"></td>
        </tr>
        <tr>
            <td align="right">Fax:</td>
            <td align="left"><input type="text" name="billtofax" value="[% HTML.escape(order.billtofax) %]" tabindex="12"></td>
            <td></td>
            <td align="right">Fax:</td>
            <td align="left"><input type="text" name="shiptofax" value="[% HTML.escape(order.shiptofax) %]" tabindex="25"></td>
        </tr>
        <tr>
            <td align="right">Email:</td>
            <td align="left"><input type="text" name="billtoemail" value="[% HTML.escape(order.billtoemail) %]" tabindex="13"></td>
            <td></td>
            <td align="right">Email:</td>
            <td align="left"><input type="text" name="shiptoemail" value="[% HTML.escape(order.shiptoemail) %]" tabindex="26"></td>
        </tr>
        <tr>
            <td colspan="5" height="10">&nbsp;</td>
        </tr>
        <tr>
            <td align="right" valign="top">Comments:</td>
            <td colspan="4" valign="top">
                <textarea name="comments" cols="45" rows="10" tabindex="27">[% HTML.escape(order.comments) %]</textarea>
            </td>
        </tr>
        <tr>
            <td colspan="5" height="10">&nbsp;</td>
        </tr>
        <tr>
            <td colspan="5" align="right"><input type="submit" value="Continue" tabindex="28"></td>
        </tr>
    </table>
</form>
__preview__
[% TAGS [- -] -%]
[% USE HTML %]
<h1>Order Preview</h1>
<table border="0" cellpadding="3" cellspacing="5">
    <tr>
        <th colspan="2" align="left">Billing</th>
        <th width="50"></th>
        <th colspan="2" align="left">Shipping</th>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right">First Name:</td>
        <td align="left">[% HTML.escape(order.billtofirstname) %]</td>
        <td></td>
        <td align="right">First Name:</td>
        <td align="left">[% HTML.escape(order.shiptofirstname) %]</td>
    </tr>
    <tr>
        <td align="right">Last Name:</td>
        <td align="left">[% HTML.escape(order.billtolastname) %]</td>
        <td></td>
        <td align="right">Last Name:</td>
        <td align="left">[% HTML.escape(order.shiptolastname) %]</td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right">Address:</td>
        <td align="left">[% HTML.escape(order.billtoaddress1) %]</td>
        <td></td>
        <td align="right">Address:</td>
        <td align="left">[% HTML.escape(order.shiptoaddress1) %]</td>
    </tr>
    <tr>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.billtoaddress2) %]</td>
        <td></td>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.shiptoaddress2) %]</td>
    </tr>
    <tr>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.billtoaddress3) %]</td>
        <td></td>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.shiptoaddress3) %]</td>
    </tr>
    <tr>
        <td align="right">City:</td>
        <td align="left">[% HTML.escape(order.billtocity) %]</td>
        <td></td>
        <td align="right">City:</td>
        <td align="left">[% HTML.escape(order.shiptocity) %]</td>
    </tr>
    <tr>
        <td align="right">State/Province:</td>
        <td align="left">[% HTML.escape(order.billtostate) %]</td>
        <td></td>
        <td align="right">State/Province:</td>
        <td align="left">[% HTML.escape(order.shiptostate) %]</td>
    </tr>
    <tr>
        <td align="right">Zip/Postal Code:</td>
        <td align="left">[% HTML.escape(order.billtozip) %]</td>
        <td></td>
        <td align="right">Zip/Postal Code:</td>
        <td align="left">[% HTML.escape(order.shiptozip) %]</td>
    </tr>
    <tr>
        <td align="right">Country:</td>
        <td align="left">[% HTML.escape(order.billtocountry) %]</td>
        <td></td>
        <td align="right">Country:</td>
        <td align="left">[% HTML.escape(order.shiptocountry) %]</td>
    </tr>
    <tr>
        <td align="right">Day Phone:</td>
        <td align="left">[% HTML.escape(order.billtodayphone) %]</td>
        <td></td>
        <td align="right">Day Phone:</td>
        <td align="left">[% HTML.escape(order.shiptodayphone) %]</td>
    </tr>
    <tr>
        <td align="right">Night Phone:</td>
        <td align="left">[% HTML.escape(order.billtonightphone) %]</td>
        <td></td>
        <td align="right">Night Phone:</td>
        <td align="left">[% HTML.escape(order.shiptonightphone) %]</td>
    </tr>
    <tr>
        <td align="right">Fax:</td>
        <td align="left">[% HTML.escape(order.billtofax) %]</td>
        <td></td>
        <td align="right">Fax:</td>
        <td align="left">[% HTML.escape(order.shiptofax) %]</td>
    </tr>
    <tr>
        <td align="right">Email:</td>
        <td align="left">[% HTML.escape(order.billtoemail) %]</td>
        <td></td>
        <td align="right">Email:</td>
        <td align="left">[% HTML.escape(order.shiptoemail) %]</td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right" valign="top">Comments:</td>
        <td colspan="4" valign="top">[% HTML.escape(order.comments) %]</td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td colspan="5">
            <table border="0" cellpadding="3" cellspacing="5" width="100%">
                <tr>
                    <th align="left">SKU</th>
                    <th align="left">Description</th>
                    <th align="right">Price</th>
                    <th align="center">Quantity</th>
                    <th align="right">Total</th>
                </tr>
            [% FOREACH item = order.items %]
                <tr>
                        <td align="left">[% HTML.escape(item.sku) %]</td>
                        <td align="left">[% HTML.escape(item.description) %]</td>
                        <td align="right">[% HTML.escape(item.price.as_string('FMT_SYMBOL')) %]</td>
                        <td align="center">[% HTML.escape(item.quantity) %]</td>
                        <td align="right">[% HTML.escape(item.total.as_string('FMT_SYMBOL')) %]</td>
                </tr>
            [% END %]
                <tr>
                        <td align="right" colspan="4">Subtotal:</td>
                        <td align="right">[% HTML.escape(order.subtotal.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Tax:</td>
                        <td align="right">[% HTML.escape(order.tax.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Shipping:</td>
                        <td align="right">[% HTML.escape(order.shipping.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Handling:</td>
                        <td align="right">[% HTML.escape(order.handling.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Total:</td>
                        <td align="right">[% HTML.escape(order.total.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                    <td colspan="5" height="5">&nbsp;</td>
                </tr>
                <tr>
                    <td colspan="5" align="right">
                        <form action="[% c.uri_for('[- uri -]/payment/') %]" method="GET">
                            <input type="submit" value="Continue">
                        </form>
                    </td>
                </tr>
            </table>
        </td>
    </td>
</table>
__payment__
[% TAGS [- -] -%]
[% USE HTML %]
<h1>Payment Information</h1>
[% INCLUDE [- action -]/errors %]
<form action="[% c.uri_for('[- uri -]/payment/') %]" method="POST">
    <table border="0" cellpadding="3" cellspacing="5">
        <tr>
            <td align="right">Name On Card:</td>
            <td align="left"><input type="text" name="ccname" value=""></td>
        </tr>
        <tr>
            <td align="right">Credit Card Type:</td>
            <td align="left">
                <select name="cctype">
                    <option>Visa</option>
                    <option>Mastercard</option>
                    <option>American Express</option>
                    <option>Discover</option>
                </select>
            </td>
        </tr>
        <tr>
            <td align="right">Credit Card Number:</td>
            <td align="left"><input type="text" name="ccn" value=""></td>
        </tr>
        <tr>
            <td align="right">Credit Card Expiration:</td>
            <td align="left"><input type="text" size="3" name="ccm" maxlength="2" value=""> / <input type="text" size="3" name="ccy" maxlength="2" value=""></td>
        </tr>
        <tr>
            <td align="right">Credit Card Verificaton Number:</td>
            <td align="left"><input type="text" name="ccvn" value="" maxlength="4" size="5"></td>
        </tr>
        <tr>
            <td colspan="2" align="right"><input type="submit" value="Complete Order"></td>
        </tr>
    </table>
</form>
__complete__
[% TAGS [- -] -%]
[% USE HTML %]
<h1>Order Complete!</h1>
<table border="0" cellpadding="3" cellspacing="5">
    <tr>
        <th colspan="2" align="left">Billing</th>
        <th width="50"></th>
        <th colspan="2" align="left">Shipping</th>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right">Order Number:</td>
        <td align="left">[% HTML.escape(order.number) %]</td>
        <td colspan="3"></td>
    </tr>
    <tr>
        <td align="right">Order Created:</td>
        <td align="left">[% HTML.escape(order.updated) %]</td>
        <td colspan="3"></td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right">First Name:</td>
        <td align="left">[% HTML.escape(order.billtofirstname) %]</td>
        <td></td>
        <td align="right">First Name:</td>
        <td align="left">[% HTML.escape(order.shiptofirstname) %]</td>
    </tr>
    <tr>
        <td align="right">Last Name:</td>
        <td align="left">[% HTML.escape(order.billtolastname) %]</td>
        <td></td>
        <td align="right">Last Name:</td>
        <td align="left">[% HTML.escape(order.shiptolastname) %]</td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right">Address:</td>
        <td align="left">[% HTML.escape(order.billtoaddress1) %]</td>
        <td></td>
        <td align="right">Address:</td>
        <td align="left">[% HTML.escape(order.shiptoaddress1) %]</td>
    </tr>
    <tr>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.billtoaddress2) %]</td>
        <td></td>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.shiptoaddress2) %]</td>
    </tr>
    <tr>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.billtoaddress3) %]</td>
        <td></td>
        <td align="right"></td>
        <td align="left">[% HTML.escape(order.shiptoaddress3) %]</td>
    </tr>
    <tr>
        <td align="right">City:</td>
        <td align="left">[% HTML.escape(order.billtocity) %]</td>
        <td></td>
        <td align="right">City:</td>
        <td align="left">[% HTML.escape(order.shiptocity) %]</td>
    </tr>
    <tr>
        <td align="right">State/Province:</td>
        <td align="left">[% HTML.escape(order.billtostate) %]</td>
        <td></td>
        <td align="right">State/Province:</td>
        <td align="left">[% HTML.escape(order.shiptostate) %]</td>
    </tr>
    <tr>
        <td align="right">Zip/Postal Code:</td>
        <td align="left">[% HTML.escape(order.billtozip) %]</td>
        <td></td>
        <td align="right">Zip/Postal Code:</td>
        <td align="left">[% HTML.escape(order.shiptozip) %]</td>
    </tr>
    <tr>
        <td align="right">Country:</td>
        <td align="left">[% HTML.escape(order.billtocountry) %]</td>
        <td></td>
        <td align="right">Country:</td>
        <td align="left">[% HTML.escape(order.shiptocountry) %]</td>
    </tr>
    <tr>
        <td align="right">Day Phone:</td>
        <td align="left">[% HTML.escape(order.billtodayphone) %]</td>
        <td></td>
        <td align="right">Day Phone:</td>
        <td align="left">[% HTML.escape(order.shiptodayphone) %]</td>
    </tr>
    <tr>
        <td align="right">Night Phone:</td>
        <td align="left">[% HTML.escape(order.billtonightphone) %]</td>
        <td></td>
        <td align="right">Night Phone:</td>
        <td align="left">[% HTML.escape(order.shiptonightphone) %]</td>
    </tr>
    <tr>
        <td align="right">Fax:</td>
        <td align="left">[% HTML.escape(order.billtofax) %]</td>
        <td></td>
        <td align="right">Fax:</td>
        <td align="left">[% HTML.escape(order.shiptofax) %]</td>
    </tr>
    <tr>
        <td align="right">Email:</td>
        <td align="left">[% HTML.escape(order.billtoemail) %]</td>
        <td></td>
        <td align="right">Email:</td>
        <td align="left">[% HTML.escape(order.shiptoemail) %]</td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td align="right" valign="top">Comments:</td>
        <td colspan="4" valign="top">[% HTML.escape(order.comments) %]</td>
    </tr>
    <tr>
        <td colspan="5" height="5">&nbsp;</td>
    </tr>
    <tr>
        <td colspan="5">
            <table border="0" cellpadding="3" cellspacing="5" width="100%">
                <tr>
                    <th align="left">SKU</th>
                    <th align="left">Description</th>
                    <th align="right">Price</th>
                    <th align="center">Quantity</th>
                    <th align="right">Total</th>
                </tr>
            [% FOREACH item = order.items %]
                <tr>
                        <td align="left">[% HTML.escape(item.sku) %]</td>
                        <td align="left">[% HTML.escape(item.description) %]</td>
                        <td align="right">[% HTML.escape(item.price.as_string('FMT_SYMBOL')) %]</td>
                        <td align="center">[% HTML.escape(item.quantity) %]</td>
                        <td align="right">[% HTML.escape(item.total.as_string('FMT_SYMBOL')) %]</td>
                </tr>
            [% END %]
                <tr>
                        <td align="right" colspan="4">Subtotal:</td>
                        <td align="right">[% HTML.escape(order.subtotal.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Tax:</td>
                        <td align="right">[% HTML.escape(order.tax.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Shipping:</td>
                        <td align="right">[% HTML.escape(order.shipping.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Handling:</td>
                        <td align="right">[% HTML.escape(order.handling.as_string('FMT_SYMBOL')) %]</td>
                </tr>
                <tr>
                        <td align="right" colspan="4">Total:</td>
                        <td align="right">[% HTML.escape(order.total.as_string('FMT_SYMBOL')) %]</td>
                </tr>
            </table>
        </td>
    </td>
</table>
__errors__
[% TAGS [- -] -%]
[% IF errors %]
	<ul class="errors">
	[% FOREACH error IN errors %]
		<li>[% HTML.escape(error) %]</li>
	[% END %]
	</ul>
[% END %]
__messages__
[% action %]/view:
  id:
    REGEX: The id field is in the wrong format.
[% action %]/billing:
  billtofirstname:
    NOT_BLANK: The bill to first name field cannot be blank.
  billtolastname:
    NOT_BLANK: The bill to last name field cannot be blank.
  billtoaddress1:
    NOT_BLANK: The bill to address line 1 field cannot be blank.
  billtocity:
    NOT_BLANK: The bill to city field cannot be blank.
  billtostate:
    NOT_BLANK: The bill to state field cannot be blank.
  billtozip:
    NOT_BLANK: The bill to zip/postal code field cannot be blank.
  billtocountry:
    NOT_BLANK: The bill to country field cannot be blank.
  billtoemail:
    NOT_BLANK: The bill to email address field cannot be blank.
  shiptofirstname:
    NOT_BLANK: The ship to first name field cannot be blank.
  shiptolastname:
    NOT_BLANK: The ship to last name field cannot be blank.
  shiptoaddress1:
    NOT_BLANK: The ship to address line 1 field cannot be blank.
  shiptocity:
    NOT_BLANK: The ship to city field cannot be blank.
  shiptostate:
    NOT_BLANK: The ship to state field cannot be blank.
  shiptozip:
    NOT_BLANK: The ship to zip/postal code field cannot be blank.
  shiptocountry:
    NOT_BLANK: The ship to country field cannot be blank.
  shiptoemail:
    NOT_BLANK: The ship to email field cannot be blank.
[% action %]/payment:
  ccname:
    NOT_BLANK: The credit card name field is required.
  cctype:
    NOT_BLANK: The credit card type field is required.
  ccn:
    NOT_BLANK: The credit card number is required.
    LENGTH: The credit card number must be between 12 to 16 digits.
    UINT: The credit cart number must contain numbers only.
  ccm:
    NOT_BLANK: The credit card expiration month field is required.
    BETWEEN: The credot card month must be between 1 and 12.
  ccy:
    NOT_BLANK: The credit card expiration year is required.
    LENGTH: The credit card expiration year must be 2 digits long.
    UINT: The credit cart expiration year must contain numbers only.
  ccvn:
    NOT_BLANK: The credit card verification number is required.
    LENGTH: The credit card verification number must be 3 to 4 digits long.
    UINT: The credit cart verification number must contain numbers only.
__profiles__
[% action %]/view:
  - id
  -
    -
      - REGEX
      - !!perl/regexp (?i-xsm:^[a-f0-9]{8}-([a-f0-9]{4}-){3}[a-f0-9]{12}$)
[% action %]/billing:
  - billtofirstname
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - billtolastname
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - billtoaddress1
  - [ ['NOT_BLANK'], ['LENGTH', 1, 50] ]
  - billtocity
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - billtostate
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - billtozip
  - [ ['NOT_BLANK'], ['LENGTH', 1, 10] ]
  - billtocountry
  -  [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - billtoemail
  - [ ['NOT_BLANK'], ['LENGTH', 1, 50] ]
  - shiptofirstname
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - shiptolastname
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - shiptoaddress1
  - [ ['NOT_BLANK'], ['LENGTH', 1, 50] ]
  - shiptocity
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - shiptostate
  - [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - shiptozip
  - [ ['NOT_BLANK'], ['LENGTH', 1, 10] ]
  - shiptocountry
  -  [ ['NOT_BLANK'], ['LENGTH', 1, 25] ]
  - shiptoemail
  - [ ['NOT_BLANK'], ['LENGTH', 1, 50] ]
[% action %]/payment:
  - ccname
  - [ ['NOT_BLANK'] ]
  - cctype
  - [ ['NOT_BLANK'] ]
  - ccn
  - [ ['NOT_BLANK'], ['LENGTH', 12, 16], ['UINT'] ]
  - ccm
  - [ ['NOT_BLANK'], ['BETWEEN', 1, 12] ]
  - ccy
  - [ ['NOT_BLANK'], ['LENGTH', 2], ['UINT'] ]
  - ccvn
  - [ ['NOT_BLANK'], ['LENGTH', 3, 4], ['UINT'] ]
__END__