Store

Introduction

Reinos Store (formerly Reinos Simple Store) is a powerful and easy-to-use e-commerce module for ExpressionEngine, letting you create a fully functional webshop in minutes. With support for multi-currency, products and orders as entries, seamless payment integration and more. It's the ultimate solution for low to mid-range online stores—and even some larger ones!

Banner

While most essential features for a basic webshop are included, additional functionality can be unlocked with Store extensions.

Store supports the following features:

With this feature set, we likely support the entire low to mid-range of webshops. However, even some large webshops run on the Store module for ExpressionEngine.

Documentation versions

Installation

Prerequisites

Make sure your system meets the minimum requirements:

Installation Instructions

Update instructions

License

For every paid addon you need to validate your license in order to activate the module.

On a local environment, like *.dev *.local *.localhost *.test the license is valid for testing and building a new or existing sites. For every other domain, you need to have a valid license.

Process of validating

Once installed, you will asked to enter your license key. When you entered a valid license you can hit the "Save license" button. This will start validating your license and will redirect you to addons.reinos.nl to login into your account. You can also register a new account in this process.

Control panel overview

Once logged in, you are asked to use your current account or to login with another one.

Control panel overview

Using the current logged in account, the server will check all info related to your license and once valid, it will redirect you back to your site where you see either a success message or an error message.

Control panel overview

License field

This module is using a license field to check if the license for the module is valid or not. On addons.reinos.nl you can check your license and add your valid domains.

Control panel overview

In the Module CP you can enter then your license Control panel overview

When you enter a wrong license, the module will not work and it shows you an warning Control panel overview

Invalid license

Sometimes it happens that the license system says you have an invalid license. When this happens, make sure you have entered your domain url in your account, next to your license on addons.reinos.nl.

If this will not fix your license problem, please contact us on https://addons.reinos.nl/support

CP Overview

On the CP page you can modify a couple of things.

Settings

Frontend order url

Set this to the url where your order is shown on the frontend.

By setting this url, you are able to view the order in the admin panel just the way the user its seeing the order.

(By default we always show the native Order view)

Shipping price

Set the price for shipping

Tax settings

(high) TAX rate

Set the first (high) tax rate

(low) TAX rate

The second (low) tax rate

TAX default rate

Set the default rate

shipping TAX rate

The TAX rate for the shipping

TAX Type

Is the price of a product incl TAX or excl TAX or none?

Currency settings

Currency

Set the default currency

Decimal point

Set the decimal point value to format the price

Thousand separator

Set the thousand separator

Email settings

Email from

The From address

Email from Name

The from name

BCC

Send the mail also to notification one or more addresses.

Email type

Send it as text or HTML

Country settings

Default country

Set a default country

Allowed countries

Select the countries that are allowed for the shop

Store settings

This is the field where you can put your store info (can be HTML for formatting the data). This data will be printed in your invoices (top right)

Discount calculation

Make a sum of all discount of just the first.

If not enabled, it will pick the highest value.

Logging

What should we log?

Channel settings

There are some settings that you can set on a global level. These settings live here.

Channel settings

Inventory Field name

In order to update your inventory, you should have at least a field that is of type text - number. Here you can select that field.

After you have selected that field, we are updating this field when an order is created. But also we update this field once an order is cancelled.

Inventory management

Example Templates

The module comes with some default predefined templates that can be used for your shop. On this page you can install them.

Discount

Create a discount coupon or add a discount per member ID with a fixed amount or order percentage.

(Note: discount code can only be used one time)

discount

Logging

This is where you can track all error logs

Orders

The order overview page. For the detail page we connect the url of your frontend to the order. If you did not set an order template (we suggest you do), it will show the details in a simple page.

orders

License

Enter your license key to activate your module

Setup the store

In order to setup the store you have to follow the following steps.

Payment Gateways

We use the following off-site gateways. The following gateways can be enabled and configured in the control panel and after that you can use the following tag (inside your checkout tag) to loop over your enabled gateways.

{exp:reinos_store:checkout}
    {!-- This is a select list, but your can convert it to anything you like. As long we have an input[gateway] field in the checkout tag  --}
    <select name="gateway">
        <option value="">Choose your gateway</option>
        {exp:reinos_store:gateway_list}
        <option value="{gateway:name}">{gateway:label}</option>
        {/exp:reinos_store:gateway_list}
    </select>
{/exp:reinos_store:checkout}

Manual

By using this Gateway you can order any product without doing a real payment. Mostly this is used to send the customer a custom invoice. But it can also be used when developing your site where you cannot use the real provider.

Mollie

This is a Dutch payment provider that support a large amount of payment methods.

Usage

Go to your dashboard --> Developers --> API Keys. There you see an API key for either testing or for production. Both API keys are needed, so you can copy both.

Multisafepay

This is another Dutch payment provider that support a large amount of payment methods.

Usage

Go to your dashboard --> Settings --> Website --> API Keys. By default you have a production account, but you can also create a developer account via https://testmerchant.multisafepay.com to obtain a test API key

Paypal

For Paypal we use the REST client to give the best Paypal experience.

Usage

Stripe (Checkout)

We support Stripe checkout. See the official documentation https://stripe.com/docs/payments/checkout

Usage

not listed

If you'd like to use a different Gateway, please let me know, so I can add this for you (not free).

Inventory management

(Added in v3.0.0)

By default, the Store module provides a simple solution for managing your order inventory. The current setup allows you to select a channel field for inventory tracking. This field must be part of your product channel, and shoulb be a Text type, and configured withAllowed Content set to Number.

When an order is placed, the module updates this field by subtracting the purchased quantity. If an order is canceled, the field is updated again, adding back the quantity of the canceled items (this is optional and can be configured).

As shown below, you can manage these settings in Reinos Store CP -> Channel Settings.

Channel settings

Inventory management

Add to Cart tag

The tag for adding items to the cart

The tag

{exp:reinos_store:add_to_cart}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

return_url

The return url, default to the current url

return_url=""

sku

The SKU for a product. If omitted, it allows you to add multiple lines of the same products in to your cart.

sku=""

entry_id

Set the entry_id of your product. This way we can reference the product to your entry.

entry_id=""

name

Set your product name

name=""

price

Set the price of the product.

price="0.00"

sale_price

Set the sales price of the product. This will be the price for the product and you can show this in your cart where for example you strike-through the {price}.

sale_price="0.00"

tax_rate

Set the tax.

This can either low or high and load the value that has been set in your settings

If omit the param, it will fallback on the default tax rate set in the settings.

tax_rate="low"

weight

Set the weight of the product. Mostly used when using the Shipping module

product_price="70" {!-- This set a weight of 70kg or 70lbs --}

clear_cart

When adding a product, your can clear the cart to have a cart with always one product.

clear_cart="no"

disable_shipping

If you have no shipping cost, you can disable it for a product

disable_shipping="no"

form_class

Set the form class

form_class=""

form_id

Set the form id

form_id=""

custom_fields:

Set custom fields

custom_fields:test="value"
custom_fields:or_an_other_value="value"

custom_fields_label:

Set nice labels for your custom fields.

This also works for input elements.

custom_fields_label:test="Your nice label for field TEST"

Input fields

qty

<input name="qty" value="1"/><br>

custom_fields

<input name="custom_fields[yet_another]" value="custom value"/><br>
<input name="custom_fields[and_another]" value="other custom value"/><br>

Tag Variables

error:invalid_price

Return the error when an invalid price is given.

{if error:invalid_price}
    <p style="color:red;">You have entered an invalid price</p>
{/if}

error:invalid_sale_price

Return the error when an invalid sales price is given.

{if error:invalid_sale_price}
    <p style="color:red;">You have entered an invalid sales price</p>
{/if}

Example

Below a small example how you can add a product to your cart

<div class="grid grid-cols-3 gap-3">
  {exp:channel:entries channel="products"}
    <div class="border p-5 rounded-md bg-gray-100 space-y-3">
      <h2 class="font-medium text-lg">{title}</h2>
      <h3>
        <span {if product_sale_price > 0}class="line-through"{/if}>{product_price:formatted}</span>
        {if product_sale_price > 0}<span>{product_sale_price:formatted}</span>{/if}
      </h3>
      <img class="w-full" src="http://via.placeholder.com/640x360" alt="Card image cap">
      <p>Some quick example text to build on the card title and make up the bulk of the card's content.</p>
      {exp:reinos_store:add_to_cart
        form_class="space-y-3"
        entry_id="{entry_id}"
        sku="{entry_id}"
        name="{title}"
        price="{product_price}"
        sale_price="{product_sale_price}"
        weight="10"
        disable_shipping="{product_disable_shipping}"
        return_url="store/cart"
        custom_fields:test="test custom field"
        tax_rate="high"
        {!-- set a label for your custom fields --}
        custom_fields_label:test="Testing"
        custom_fields_label:field_from_input="Field from Input"
        }
          {if error:invalid_price}
          <p style="color:red;">You have entered an invalid price</p>
          {/if}

          {if error:invalid_sale_price}
          <p style="color:red;">You have entered an invalid sale price</p>
          {/if}

          <div class="flex flex-col space-y-1">
             <label class="font-medium">Custom Field</label>
            <input class="input" type="text" name="custom_fields[field_from_input]" placeholder="custom field"/>
          </div>

          <div class="flex flex-col space-y-1">
            <label class="font-medium" for="qty">Aantal</label>
            <input class="input" type="number" id="qty" name="qty" value="1"/><br>
          </div>

          <input type="submit" class="button" value="Add to Cart"/>
        {/exp:reinos_store:add_to_cart}
    </div>
    {/exp:channel:entries}
</div>

Cart tag

The cart tag is responsible for creating a cart overview.

The tag

{exp:reinos_store:cart}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

return_url

The return url, default to the current url

return_url=""

form_class

Set the form class

form_class=""

form_id

Set the form id

form_id=""

prefix

Set a prefix for your variables

prefix="cart:"

can_update

Mark the cart so it can be updated. We add a <form/> tag in the html.

can_update="yes"

Tag Variable

Below are the Tag Variables. Those Variables can be used in the tag described above

cart:no_items

Check if there are no_items

{if cart:no_items}...{/if}

cart:items

Loop over the items in the cart

{cart:items}
    {cart:name}
    {cart:price}
    {cart:price:formatted}
    {cart:old_price} // when dealing with a sale price, this is the original_price
    {cart:old_price:formatted} // when dealing with a sale price, this is the original_price
    {cart:price_plus_tax}
    {cart:price_plus_tax:formatted}
    {cart:old_price_plus_tax} // when dealing with a sale price, this is the original_price
    {cart:old_price_plus_tax:formatted} // when dealing with a sale price, this is the original_price
    {cart:qty}
    {cart:sku}
    {cart:entry_id}
    {cart:disable_shipping}
    {cart:price_total}
    {cart:price_total:formatted}
    {cart:old_price_total} // when dealing with a sale price, this is the original_price
    {cart:old_price_total:formatted} // when dealing with a sale price, this is the original_price
    {cart:price_total_plus_tax}
    {cart:price_total_plus_tax:formatted}
    {cart:old_price_total_plus_tax} // when dealing with a sale price, this is the original_price
    {cart:old_price_total_plus_tax:formatted} // when dealing with a sale price, this is the original_price
    {cart:custom_fields}<strong>{custom_fields:label}:</strong> {custom_fields:value}{/cart:custom_fields}
    {cart:on_sale} // bool if the product is on sale
{/cart:items}

cart:total_items

The total number of different products in the cart

{cart:total_items}

cart:total_items_qty

The total qty of all items in the cart

{cart:total_items_qty}

cart:subtotal

{cart:subtotal}
{cart:subtotal:formatted}

cart:subtotal_plus_tax

{cart:subtotal_plus_tax}
{cart:subtotal_plus_tax:formatted}

cart:discount

To use the coupon code, simply add the field <input type="text" name="coupon_code" value="{cart:coupon_code}"/>. (see the examples for details)

{cart:discount}
{cart:discount:formatted}

cart:total

{cart:total}
{cart:total:formatted}

cart:total_plus_tax

{cart:total_plus_tax}
{cart:total_plus_tax:formatted}

cart:tax

{cart:tax}
{cart:tax:formatted}

cart:shipping

{cart:shipping}
{cart:shipping:formatted}

cart:shipping_plus_tax

{cart:shipping_plus_tax}
{cart:shipping_plus_tax:formatted}

cart:entry_ids

Hold all entry_ids as a pipeline delimited string

{cart:entry_ids}

Example

{exp:reinos_store:cart prefix="cart:" can_update="yes" return_url="store/cart"}
  <h1 class="font-bold mt-5 text-2xl">Your cart</h1>
  {if cart:no_items}
      <p>No cart items</p>
  {if:else}
    <p class="mb-10 text-italic">({cart:total_items} products in cart and {cart:total_items_qty} items in cart)</p>
    <table class="w-full table-auto mt-4 mb-4">
        <thead class="border-b-2">
        <tr>
            <th align="left">Name</th>
            <th align="left">Qty</th>
            <th align="left">Price</th>
            <th align="left">Subtotal</th>
            <th />
        </tr>
        </thead>
        <tbody>
        {cart:items}
            {exp:channel:entries entry_id="{cart:entry_id}" dynamic="no"}
                <tr class="border-b">
                    <td>
                      <div class="py-3">
                          <a href="{page_uri}">{title}</a>
                          {if cart:sku != ''}<small>sku: {cart:sku}</small>{/if}
                          {cart:custom_fields}<br><strong>{custom_fields:label}:</strong> {custom_fields:value}{/cart:custom_fields}
                      </div>
                    </td>
                    <td><input class="border p-1 rounded" type="number" value="{cart:qty}" name="qty[{cart:id}]"></td>
                    <td>
                        {cart:price_plus_tax:formatted}
                        {if cart:on_sale}&nbsp;<strike>{cart:old_price_plus_tax:formatted}</strike>{/if}
                    </td>
                    <td>
                        {cart:price_total_plus_tax:formatted}
                        {if cart:on_sale}&nbsp;<strike>{cart:old_price_total_plus_tax:formatted}</strike>{/if}
                    </td>
                    <td align="right">
                        {exp:reinos_store:delete_cart_item cart_item_id="{cart:id}" return_url="/store"}
                            <a class="button" href="{remove_cart_item_url}">Remove</a>
                        {/exp:reinos_store:delete_cart_item}
                    </td>
                </tr>
            {/exp:channel:entries}
        {/cart:items}
        </tbody>
      </table>

      <div class="w-1/2 flex flex-col ml-auto">
        <h3 class="text-lg font-medium mt-5">Coupon code</h3>
        <div class="flex gap-x-1 mb-5">
          <input class="w-full border p-1 rounded" type="text" name="coupon_code" value="{cart:coupon_code}"/>
          <input type="submit" name="update" value="Apply" class="button"/>
        </div>

        <table>
          <tbody>
          <tr>
              <td align="right"><strong>Subtotal</strong></td>
              <td align="right">{cart:subtotal_plus_tax:formatted}</td>
          </tr>
          {if cart:discount > 0}
              <tr>
                  <td align="right"><strong>Discount</strong></td>
                  <td align="right">{cart:discount:formatted}</td>
              </tr>
          {/if}
          {if cart:tax > 0}
          <tr>
              <td align="right"><strong>TAX</strong></td>
              <td align="right">{cart:tax:formatted}</td>
          </tr>
          {/if}
          {if cart:shipping_plus_tax > 0}
              <tr>
                  <td align="right"><strong>Shipping</strong></td>
                  <td align="right">{cart:shipping_plus_tax:formatted}</td>
              </tr>
          {/if}
          <tr>
              <td align="right"><strong>Total excl</strong></td>
              <td align="right">{cart:total:formatted}</td>
          </tr>
          <tr>
              <td align="right"><strong>Total</strong></td>
              <td align="right">{cart:total_plus_tax:formatted}</td>
          </tr>
          </tbody>
        </table>
      </div>

      <input type="submit" name="update" value="Update" class="button"/>
      <input type="submit" name="clear" value="Clear cart" class="button"/>
      <a class="button" href="/index.php/store/checkout">Checkout</a>
  {/if}
{/exp:reinos_store:cart}

Remove Cart item Tag

With the remove Cart Item Tag your are able to remove a single item from the cart

The tag

{exp:reinos_store:delete_cart_item}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

cart_item_id

The unique cart item ID

cart_item_id=""

Tag Variable

Below are the Tag Variables. Those Variables can be used in the tag described above

remove_cart_item_url

The actual url that can be used to delete the cart item

Example

{exp:reinos_store:cart prefix="cart:" can_update="yes"}
    {cart:items}
        {exp:reinos_store:delete_cart_item cart_item_id="{cart:id}"}
            <a href="{remove_cart_item_url}">Remove</a>
        {/exp:reinos_store:delete_cart_item}
    {/cart:items}
{/exp:reinos_store:cart}

Checkout tag

The Checkout tag. This is the tag that is responsible for the whole checkout process.

The moulde is shipped with a ready-to-go template, however, you can still change everything to your needs.

The tag

{exp:reinos_store:checkout}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

customer_phone_required

Set the customer phone as required.

customer_phone_required="false"

customer_company_required

Set the customer company name as required.

customer_company_required="false"

return_url

The return url, default to the current url

return_url=""

form_class

Set the form class

form_class=""

form_id

Set the form id

form_id=""

enable_billing_address

Control wether the billing address fields are required or not.

enable_billing_address="yes" (default)

enable_shipping_address

Control wether the shipping address fields are required or not.

enable_shipping_address="yes" (default)

Tag Variable

Below are the Tag Variables. Those Variables can be used in the tag described above

global_errors

Global errors

{global_errors}
    {global_errors:error}
{/global_errors}

But we also have them as separated error variables

{global_error:no_items_to_checkout}
{global_error:gateway_not_exists}
{global_error:no_gateway_selected}
{global_error:transaction_error}
{global_error:shipping_type_missing} // coming from the shipping module

has_global_errors

Check for global errors

{if has_global_errors}
   {global_error}
{/if}

has_field_errors

Check for field errors

{if has_field_errors}
   ...
{/if}

field_name:error

Error, if there is one, per field

{customer_first_name:error}
{customer_last_name:error}
{customer_email:error}
{customer_phone:error}
{customer_company:error}
{billing_address:error}
{billing_address2:error}
{billing_zip:error}
{billing_city:error}
{billing_country:error}
{shipping_address:error}
{shipping_address2:error}
{shipping_zip:error}
{shipping_city:error}
{shipping_country:error}

{!-- for example --}
{if customer_company:error != ''}<span class="text-red">{customer_company:error}</span>{/if}

field_name:value

Values, if there is something, per field

{customer_first_name:value}
{customer_last_name:value}
{customer_email:value}
{customer_phone:value}
{customer_company:value}
{billing_address:value}
{billing_address2:value}
{billing_zip:value}
{billing_city:value}
{billing_country:value}
{shipping_address:value}
{shipping_address2:value}
{shipping_zip:value}
{shipping_city:value}
{shipping_country:value}

extra_fields

Add extra fields to your checkout process.

You need to define the field names in extra_fields and in the body of {exp:reinos_store:checkout} you can add the actual HTML

{exp:reinos_store:checkout
    extra_fields="agree_with_terms|name|email"
}
    <input name="name" placeholder="extra[name]" />
    <input name="email" type="extra[email]" placeholder="email" />
    <input type="checkbox" name="extra[agree_with_terms]" value="yes"/> Agree with the terms
{/exp:reinos_store:checkout}

Steps

The example templates are using the stepping technique. Each step Personal and billing and shipping adress, Shipping and payment are a step in the order process. We enable this by adding the name name="step-1" name="step-2" or name="step-3" to the next button as you can seen in the example template

    <button name="step-2" type="submit" class="button">Next step</button>

Country tag

This tag will convert your ISO-2 lang code to a readable one.

The tag

{exp:reinos_store:country}DE{/exp:reinos_store:country}

Country List tag

Get a select HTML list of all your countries, and also checking the settings for default and allowed countries

The tag

{exp:reinos_store:country_list type="billing" class="form-control" value=""}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

class

Set the CLASS for the select

class=""

id

Set the ID for the select

id=""

type

Set to billing or shipping

type="billing"

value

set the default value

value=""

Format tag

Format the price to the correct decimals and currency symbol

The tag

{exp:reinos_store:format}9.95{/exp:reinos_store:format}

Global variables

Below the global variables that can be used anywhere.

reinos_store_total_products_in_cart

The total number of different products in the cart

{reinos_store_total_products_in_cart}

reinos_store_total_items_in_cart

The total qty of all items in the cart

{reinos_store_total_items_in_cart}

reinos_store_shipping_module_installed

Check if the shipping module is installed

{reinos_store_shipping_module_installed}

reinos_store_tax_module_installed

Check if the Tax module is installed

{reinos_store_tax_module_installed}

reinos_store_update_checkout_details_ajax_url

Return the ajax url for updating the checkout details. See the example template for the usage.

{reinos_store_update_checkout_details_ajax_url}

Order tag

The order tag. It comes in 2 flavours, one for getting a single order {exp:reinos_store:order} and one for getting a list of orders {exp:reinos_store:orders}. Both tags have the same parameters and variables.

The tag

{exp:reinos_store:order}
{exp:reinos_store:orders}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

prefix

Prefix the variables

prefix="order:"

order_id

Set a order_id for the order you want to fetch

order_id=""

hash

Set a hash for the order you want to fetch

hash=""

member_id

Select all orders for the given member_id

member_id=""

status

Filter based on the status.

Possible options: open paid pending failed expired cancelled refunded paid_chargeback

status="open"

Tag Variable

Below are the Tag Variables. Those Variables can be used in the tag described above

no_results

Check if there is any result

{if no_results}...{/if}

order:can_complete

Check if we still cancan pay the order.

Some providers support to pay after the order has been created but somehow is now paid and still open

{if order:can_complete }
    Your order is not yet payed, finish your order by clicking <a href="{order:payment_url}">here</a>.
{/if}

order:payment_url

The payment url, used when the order is open and should be paid

{if order:can_complete }
    Your order is not yet payed, finish your order by clicking <a href="{order:payment_url}">here</a>.
{/if}

order:order_id

{order:order_id}

order:time

{order:time format="%d %M %Y"}

order:transaction_id

{order:transaction_id}

order:status

{order:status}

order:customer_company

{order:customer_company}

order:customer_first_name

{order:status}

order:customer_last_name

{order:customer_last_name}

order:customer_email

{order:customer_email}

order:customer_phone

{order:customer_phone}

order:billing_address

{order:billing_address}

order:billing_address2

{order:billing_address2}

order:billing_zip

{order:billing_zip}

order:billing_city

{order:billing_city}

order:billing_country

The ISO-2 lang code. Convert it with {exp:reinos_store:country} to get a readable name

{exp:reinos_mollie:country}{order:billing_country}{/exp:reinos_mollie:country}

order:shipping_address

{order:shipping_address}

order:shipping_address2

{order:shipping_address2}

order:shipping_zip

{order:shipping_zip}

order:shipping_city

{order:shipping_city}

order:shipping_country

The ISO-2 lang code. Convert it with {exp:reinos_store:country} to get a readable name

{exp:reinos_store:country}{order:shipping_country}{/exp:reinos_store:country}

order:items

Loop over the items in the order

{order:items}
    {order:name}
    {order:price}
    {order:price:formatted}
    {order:old_price} // when dealing with a sale price, this is the original_price
    {order:old_price:formatted} // when dealing with a sale price, this is the original_price
    {order:price_plus_tax}
    {order:price_plus_tax:formatted}
    {order:old_price_plus_tax} // when dealing with a sale price, this is the original_price
    {order:old_price_plus_tax:formatted} // when dealing with a sale price, this is the original_price
    {order:qty}
    {order:sku}
    {order:entry_id}
    {order:disable_shipping}
    {order:price_total}
    {order:price_total:formatted}
    {order:old_price_total} // when dealing with a sale price, this is the original_price
    {order:old_price_total:formatted} // when dealing with a sale price, this is the original_price
    {order:price_total_plus_tax}
    {order:price_total_plus_tax:formatted}
    {order:old_price_total_plus_tax} // when dealing with a sale price, this is the original_price
    {order:old_price_total_plus_tax:formatted} // when dealing with a sale price, this is the original_price
    {order:items:custom_fields}<strong>{custom_fields:label}:</strong> {custom_fields:value}{/order:items:custom_fields}
    {order:items:on_sale} // bool if the product is on sale
{/order:items}

order:subtotal

{order:subtotal}
{order:subtotal:formatted}

order:subtotal_plus_tax

{order:subtotal_plus_tax}
{order:subtotal_plus_tax:formatted}

order:discount

{order:discount}
{order:discount:formatted}

order:total

{order:total}
{order:total:formatted}

order:total_plus_tax

{order:total_plus_tax}
{order:total_plus_tax:formatted}

order:tax

{order:tax}
{order:tax:formatted}

order:shipping

{order:shipping}
{order:shipping:formatted}

order:shipping_plus_tax

{order:shipping_plus_tax}
{order:shipping_plus_tax:formatted}

order:entry_ids

Hold all entry_ids as a pipeline delimited string

{order:entry_ids}

order:extra_fields

Get the extra fields that are used in the checkout tag

{order:extra_fields}
    {extra_field:name}: {extra_field:value}
{/order:extra_fields}

Price Fieldtype

The price fieldtype is a special fieldtype that can hold currency values.

By default the fieldtype field output a numeric value that can be used for the {exp:reinos_mollie:add_to_cart product_price=""} parameter.

Fieldtype Modifiers

Below are the Fieldtype Modifiers. Those Variables can be used in the tag described above

:no_tax

Output the price without TAX and formatted

{your-field-name:no_tax}

:plus_tax

Output the price with TAX and formatted

{your-field-name:plus_tax} //fall back on the default tax value
{your-field-name:plus_tax tax="low"}
{your-field-name:plus_tax tax="high"}
{your-field-name:plus_tax tax="22"} //custom numeric value

:plus_tax_numeric

Output the price with TAX as a numeric value

{your-field-name:plus_tax_numeric} //fall back on the default tax value
{your-field-name:plus_tax_numeric tax="low"}
{your-field-name:plus_tax_numeric tax="high"}
{your-field-name:plus_tax_numeric tax="22"} //custom numeric value

:no_tax_numeric

Output the price without TAX as a numeric value

{your-field-name:no_tax_numeric}

:numeric

Output the price, as given as a numeric value

{your-field-name:numeric} //fall back on the default tax value
{your-field-name:numeric tax="low"}
{your-field-name:numeric tax="high"}
{your-field-name:numeric tax="22"} //custom numeric value

:formatted

Output the price, as given formatted

{your-field-name:formatted} //fall back on the default tax value
{your-field-name:formatted tax="low"}
{your-field-name:formatted tax="high"}
{your-field-name:formatted tax="22"} //custom numeric value

Shipping methods tag

Get the available shipping methods

(Added in v3.0.0)

Due to the integration of the shipping module we are also making the shipping methods available via a template tag.

Without the shipping module, there is always one option.

The tag

{exp:reinos_store:shipping_methods}...{/exp:reinos_store:shipping_methods}

Tag Parameters

Below are the Tag Parameters. Those parameters can be used in the tag described above

prefix

class=":shipping_methods"

Tag Variables

{exp:reinos_store:shipping_methods}
    {shipping_methods:name}
    {shipping_methods:title}
    {shipping_methods:selected}
    {shipping_methods:price}
    {shipping_methods:price:formatted}
    {shipping_methods:price_plus_tax}
    {shipping_methods:price_plus_tax:formatted}
{/exp:reinos_store:shipping_methods}

You can use it as following in your checkout tag, just as the example template

{exp:reinos_store:shipping_methods}
    <div class="border rounded p-4 flex items-center gap-x-4">
        <input {if shipping_methods:selected}checked{/if} id="{shipping_methods:name}" type="radio" name='shipping_type' value='{shipping_methods:name}' />
        <label for="{shipping_methods:name}">{shipping_methods:title}</label>
    </div>
{/exp:reinos_store:shipping_methods}

Sync to Entries

Starting with version 2.x.x, it is possible to sync your Orders and Order Items with your regular Entry Channels. This gives you the flexibility to use regular Entry tags and the option to add extra fields if needed.

Once you configure the settings, syncing happens automatically in the background. Orders will be synced to the Entries, and if you make changes to an order within an Entry, it will be synced back to the module. This ensures that the module and the entries remain in sync.

Note: If you upgraded from an older version before 2.x.x. You have to manually sync the entries. Please go to you Order overview and click "Sync Order Status". On this page you can sync your entries.
Remember, syncing a lot of order can take a while.

Fields and Channels

First you need to create your channels and your fields. For the Order Channel you can sync the following fields:

As of v3.0.0 we added a folder that can be zipped and imported into EE. Simply zip the folder ee_reinos_store/system/user/addons/reinos_store/custom_channels/order_items/ChannelSet --> <give-it-a-name>.zip and import it into ExpressionEngine.

Order

The following fields should be created for an Order Channel

Address fields
Customer fields
Price fields
Other fields

Order Items

The following fields should be created for the Order Items Channel

Default fields
Price fields
Other fields

Orders settings

The following fields needs to configured in order to sync your Orders to Entries.

Field Description
Channel Choose the channel where we should save the Order to.
Order Title Prefix Set a prefix for the title. By default we will use #order-{orderId}
URL Title Prefix Set prefix for your URL Title
Order Status Select the Status from your Channel that we should map
Order Fields Select a Field from your Channel that we should map

Order Items Settings

Just like the orders, Order Items needs to be configured in the same way as Orders.

Field Description
Channel Choose the channel where we should save the Order Item to.
Order Title Prefix Set a prefix for the title
Order Status Select the Status from your Channel that we should map
Order Fields Select a Field from your Channel that we should map

Sync: Order & Order Items custom fields

The custom_field fieldtype is a special fieldtype that can read out the custom fields of a synced item. It will render a table in the Channel Entry view and has a tagpair to render the custom_fields in your HTML.

You should use

Fieldtype Tag pair

{order_custom_fields}
    {custom_fields:label}
    {custom_fields:value}
{/order_custom_fields}

Sync: Order Items Fieldtype

The order_items fieldtype is a special fieldtype that can read out the Order Items of a synced item. It will render a table in the Channel Entry view and has a tagpair to render the order_items in your HTML.

You should use

Fieldtype Tag pair

{order_items_field}
    {order_item:entry_id}
{/order_items_field}

Inventory management

(Added in v3.0.0)

By default, the Store module comes with a simple solution for managing your order inventory. Currently, we have a straightforward setup that allows you to select a channel field used for inventory tracking. This field is part of your product channel.

When an order is placed, we update this field by subtracting the quantity from this custom field. If an order is canceled, we update the field again by adding back the quantity of the canceled items (this is an option).

As shown below, you can manage these settings in the Reinos Store CP -> Channel Settings.

Inventory overview

Inventory overview

Changelog

3.0.2 (18-12-2024)

3.0.1 (13-12-2024)

3.0.0 (09-12-2024)

Breaking changes See https://addons.reinos.nl/news/store-module-v3

You need at least v2.x.x to upgrade to this version. Inside all v3.x.x releases, there is a v2.x.x. release. You can use this version to upgrade to the latest v2.x.x and after that upgrade you are good to go to update to v3.x.x.

As we renamed the module from reinos_simple_store to reinos_store we also added a migration script. This file is located here --> system/user/addons/reinos_store/mysql-migrate-200--300.sql. Its just a sql script that can be executed right after you are on the latest version.

  1. Make a mysql backup
  2. Update to the latest v2.x version.
  3. Run the mysql script system/user/addons/reinos_store/mysql-migrate-200--300.sql
  4. Delete the reinos_simple_store files
  5. Upload the new reinos_store files (both themes and system folder)
  6. Run the module updater as you normally should do.

We are not including the migration process within the module itself, as it is prone to errors. Since the module's name has changed, ExpressionEngine cannot directly handle this update. By following the steps above, your transition should be smooth.

2.0.0 (11-05-2024)

1.12.0 (11-10-2023)

1.11.3 (09-08-2023)

1.11.2 (03-08-2023)

1.11.1 (24-07-2023)

1.11.0 (11-07-2023)

1.10.0 (01-06-2023)

1.9.0 (03-05-2023)

1.8.3 (27-01-2023)

1.8.2 (10-01-2023)

1.8.1 (29-12-2022)

1.8.0 (16-11-2022)

1.7.1 (30-08-2022)

1.7.0 (26-07-2022)

1.6.1 (06-07-2022)

1.6.0 (18-05-2022)

1.5.1 (01-11-2021)

1.5.0 (23-10-2021)

1.4.1 (25-08-2021)

1.4.0 (30-07-2021)

1.3.0 (14-07-2021)

1.2.0 (08-07-2021)

1.1.0 (09-06-2021)

1.0.0 (01-06-2021)