Here's the answer I got posted directly into our site based on our help chat with Cart Throb. It's a one page does it all example, but well commented.
There's been no changes made to core (CT didn't have FTP access), and this was posted in after we closed the skype call, so I haven't had the chance to talk it through with them. I think the only change as far as I can tell is the option price field being option_price
and not price:plus_tax
.
The other difference I can see is that we were trying to output the tax applicable to each line item, whereas this example simply calculates a % amount, based on the rate set in the settings. So perhaps at a line item level, the calculation is incorrect, but at a cart level, it is correct. This seems a little inconsistent but must admit I haven't had an opportunity to test this fully in our environment.
{preload_replace:template_group="test"}
{preload_replace:template="tax-test"}
<html>
<head>
<title>Tax Test</title>
</head>
<body>
<h1>Single Page Store</h1>
<p>This single page is an example of how you can use one page to add, update, and delete items, as well as checkout.
This is the most in depth single page sample
</p>
{!-- ORDER COMPLETE MESSAGES --}
{!-- the submitted_order_info tag outputs information from the last attempted order.
Even if the customer leaves this page and returns, the information from the customer's
last attempted purchase will be output.
--}
{exp:cartthrob:submitted_order_info}
<div class="store_block">
{if authorized}
{!-- This content displays if the purchase was successful--}
Your transaction is complete!<br />
Transaction ID: {transaction_id}<br />
Your total: {cart_total}<br />
Your order ID: {order_id}
{!-- This content displays if the purchase is only partly completed--}
{if:elseif processing}
Your transaction is being processed!<br />
Transaction ID: {transaction_id}<br />
Your total: {cart_total}<br />
Your order ID: {order_id}
{if:elseif declined}
{!-- This content displays if the purchase was declined--}
Your credit card was declined: {error_message}
{if:elseif failed}
{!-- This content displays if the purchase completely fails--}
Your payment failed: {error_message}
{/if}
</div>
{/exp:cartthrob:submitted_order_info}
{!-- ADD A PRODUCT --}
<div class="store_block">
<h2>Add Products</h2>
{!-- outputting products stored in one of the "products" channels.
Product channels are no different than standard channels. --}
{exp:channel:entries channel="products" limit="10"}
{!--
The add_to_cart_form adds 1 or more of a product to the cart
parameters
return: the page the customer will be redirected to after adding this item to the cart
entry_id: the product's entry_id
--}
{exp:cartthrob:add_to_cart_form
entry_id="{entry_id}"
return="{template_group}/{template}"}
<p>
Product name: {title} Price: {pm_base_price}<br />
Quantity: <input type="text" name="quantity" size="5" value="" />
<br />
{exp:cartthrob:item_options entry_id="{entry_id}"}
{if dynamic}
<div class="control-group">
<label class="control-label" for="{option_field}">{option_label}</label>
<div class="controls">
{input}
</div>
</div>
{if:else}
{if options_exist}
<div class="control-group">
<label class="control-label" for="{option_field}">{option_label}</label>
<div class="controls">
{select class="input-medium"}
<option {selected} value="{option_value}">
{option_name}{if option_price_numeric != 0} +{option_price}{/if}
</option>
{/select}
</div>
</div>
{/if}
{/if}
{/exp:cartthrob:item_options}
<input type="submit" value="Add to Cart">
</p>
{/exp:cartthrob:add_to_cart_form}
{/exp:channel:entries}
</div>
{!-- VIEW CART CONTENTS / UPDATE QUANTITIES --}
<div class="store_block">
<h2>Cart Contents</h2>
{!-- cart_items_info outputs information about your current cart, including products in the cart, weight, and prices.
you can combine this with update_cart_form, to output cart item data, and update cart info
--}
{exp:cartthrob:cart_items_info}
{if no_results}
<p>There is nothing in your cart</p>
{/if}
{!-- outputting content that's only applicable for the first item. --}
{if first_row}
{!-- adding an update_cart_form to the first row. --}
{!-- update_cart_form allows you to edit the information of one or more items in the cart at the same time
as well as save customer information, and shipping options. --}
{exp:cartthrob:update_cart_form
return="{template_group}/{template}"}
<h3>Customer Info</h3>
{!-- customer_info outputs customer info that is current stored in session.
update_cart_form, checkout_form, save_customer_info form and other forms
can all save customer data.
--}
{exp:cartthrob:customer_info}
First Name: <input type="text" name="first_name" value="{customer_first_name}" /><br />
Last Name: <input type="text" name="last_name" value="{customer_last_name}" /><br />
Email Address: <input type="text" name="email_address" value="{customer_email_address}" /><br />
State: <input type="text" name="state" value="{customer_state}" /><br />
Country: <input type="text" name="country_code" value="{customer_country_code}" /><br />
Zip: <input type="text" name="zip" value="{customer_zip}" /><br />
{/exp:cartthrob:customer_info}
<table>
<thead>
<tr>
<td>Item</td>
<td colspan="2">Quantity</td>
</tr>
</thead>
<tbody>
{/if}
<tr>
<td>{title}</td>
<td>
{!-- you can reference products by entry_id and row_id. If you sell configurable
items (like t-shirts with multiple sizes) you should use row_id to edit and
delete items, otherwise, all items with that entry id
are affected, regardless of configuration --}
<input type="text" name="quantity[{row_id}]" size="2" value="{quantity}" />
</td>
<td>
{!-- This deletes one item (row_id) at a time--}
<input type="checkbox" name="delete[{row_id}]"> Delete this item
</td>
</tr>
{if last_row}
{!-- outputting content that's only applicable for the last item. --}
<tr>
<td>
{!-- these are just some of the variables available within the cart_items_info tag --}
<p>
Subtotal: {cart_subtotal}<br />
Shipping: {cart_shipping}<br />
Tax: {cart_tax}<br />
{!--tax is updated based on user's location. To create a default tax price, set a default tax region in the backend --}
Shipping Option: {shipping_option}<br />
Tax Name: {cart_tax_name}<br />
Tax %: {cart_tax_rate}<br />
Discount: {cart_discount}<br />
<strong>Total: {cart_total}</strong>
</p>
<p>
{!-- total quantity of all items in cart --}
Total Items: {exp:cartthrob:total_items_count}<br />
{!-- total items in cart --}
Total Unique Items: {exp:cartthrob:unique_items_count}
</p>
</td>
<td colspan="2"> </td>
</tr>
</tbody>
</table>
<input type="submit" value="Update Cart" />
{/exp:cartthrob:update_cart_form}
{/if}
{/exp:cartthrob:cart_items_info}
</div>
</body>
</html>
It's also worth adding that they guys at Cart Throb are really helpful. The support sessions are paid and booked in advance, but a half-hour session means you can talk through your scenario with another developer who really understands the product.
item_tax
. This still shows the tax on the base price only, so I'm guessing this is a bug. Will raise with Cart Throb.