View from inside the viper

Cart Viper Release 1.4.1 Available Now!

  September 23, 2011 10:25
by Mark

After a busy couple of months development we are pleased to have released a new version of Cart Viper today. Version 1.4.1 comes with a host of new features and bug fixes, the major points are listed below.

  • Variant Image support, display a different image when the customer selects a variant for a product
  • Ability to define the display order of products within each category
  • A new module Search Input has been created to allow the search box to be display anywhere in the page
  • Products can define price breaks based on the quantity order
  • Search results are now sorted by relevance by default
  • Limit a coupon to apply discount only to products within a given category
  • The Mini Cart Module has be converted to be template based so you are now free to style and change this as you require
  • Products can be assigned to a supplier
  • The Store Admin is able to moderate and edit order created with the offline payment provider
  • The category description edit control is now a rich HTML editor
  • CSV Product import now supports the ability to import the PDF datasheet for a product
  • Order Numbers can be prefixed with a code based on the user account which created the order

We’ll be blogging about the new features in the next few days, so stayed tuned find out more.

Existing customers can download the latest version and upgrade by following the instructions in the PDF user manual.



Liberate Online–Testimonial

  September 15, 2011 11:26
by Mark

Getting feedback and reviews for our online store module is great, WSI Captivating Web Solutions have created an online store for Liberate a Shamanic Healing and Theta Healing practitioner in Hertfordshire.

Shamanic Healing, Theta Healing and Soul Retrieval in Hertfordshire

“I have used this product for a small shopping cart on http://www.liberate-online.co.uk/Online-Store/c/spiritual-art.aspx The module was integrated seamlessly without difficulty within minutes. The client does not have a large number of products just a few limited edition prints but is now going to add jewellery to the store too. I’ve just found out that I can upgrade the module and the latest version includes zoom functionality which is exactly what the client has been asking for.”

WSI Captivating Web Solutions



Wendy Warren Jewellery–Testimonial

  September 14, 2011 20:01
by Mark

Its always great to hear from our clients, recently Sharon Ensbury from WSI Captivating Web Solutions created the ecommerce store Wendy Warren Jewellery using Cart Viper. Here is what Sharon has to say about the experience.

“I have used Cart Viper on www.wendywarrenjewellery.co.uk a uk based jewellery site that to date has 500 products.  The module was very cost effective, and installation straight forward.  The module comes with a .CSV file for importing the products and categories and linking to images and we found that to be easy to use too. Further down the line the client decided they wanted to change the categories of the products and on a Bank Holiday Monday afternoon, I contacted cart viper who responded within hours telling me how to do it. I really would recommend this product to anyone searching for an e commerce solution for DNN.”

Wendy Warren Jewellery



Release 1.4.1 Coming Soon!

  September 12, 2011 12:14
by Nigel

Here at Cart Viper the DNN shopping cart we are putting the finishes touches to version 1.4.1 and hope to complete our final testing and do a general release  by the end of September 2011. This new version is packed full of new features and improvements.

Some of the major new features we have added are:

  • Variant Images – Now you can define a different image for each variant combination, for example a different image for a red, blue or green t-shirt. When the user selects that variant combination the image will be displayed to them.
  • Moderate Offline Orders – optionally choose that offline orders require moderation before being accepted by the store, allows store admin to add, remove and update items in an order.
  • Mini-Cart Template Driven – alter the “Mini Cart” module to use the advanced templating system of Cart Viper allowing you to easily alter the look and feel of the mini cart.
  • Qty Discounts – allow the store admin to define discounts based on the number of items the user is purchasing.
  • Supplier Management – allows suppliers to be entered into Cart Viper and then optionally assign each product to a supplier.

There are many more features and improvements in version 1.4.1, to view the full list of features and to view what we have planned for release 1.5 please checkout our roadmap.

If you have any feature requests please let us know and we would be happy to discuss them with you.



Checkout With Prepaid Credit

  September 8, 2011 14:29
by Nigel

A further new feature added to Cart Viper the DotNetNuke shopping cart is the ability for the user to pay for items in your store with prepaid credit. This checkout option can be selected alongside any combination of Paypal standard, Google Checkout or offline payment method. Giving your customers multiple options on how they would like to purchase their goods.

CropperCapture[10]

In order for a customer to use the prepaid checkout option they must first purchase credit to use in your store, they can do this from the “my prepaid balance” option from the “Cart Viper My Account” module, from here they can also view their current balance:

CropperCapture[11]

Prepaid credit can also be added directly onto a users account by editing their DNN profile, note due to a “quirk” with how DNN stores data in the profile property, the monetary amount need to be entered in cents. So the below would equal $85.60 of prepaid credit – the option to enter credit onto a users profile is only available to users with admin or host permissions to the DNN site:

CropperCapture[12]

Now when the customer views the payment summary page they can chose to pay using their prepaid credits or any of the other payment options that are configured for the store. If they pay via their prepaid credits the amount will be deducted from their balance:

CropperCapture[13]

If however the total cost of the order is greater than their available points balance the prepaid checkout option is hidden and they must select from one of the other configured payment options:

CropperCapture[14]

The prepaid credits feature was developed based on a customization request from one of our customers, if you have any features you would like to see added to Cart Viper please let us know.



New 1.4.0 Features

  September 5, 2011 15:55
by Nigel

Following on our discussion of new features in release 1.4.0 of Cart Viper the DotNetNuke ecommerce solution we are going to discuss several new features that have been added:

Optionally attach order PDF to order confirmation email:

The ability to create a PDF receipt of an order has existed in Cart Viper for some time now, however we have now allowed the store admin to attach this PDF to the email that is sent to the customer to confirm their order. The order PDF can still be downloaded via the order details section, however by sending it along with the order confirmation email the customer will have a copy of this with their order confirmation for their records:

CropperCapture[2]

Record Users IP Address During Checkout:

A further new enhancement is that a customer IP address is now automatically recorded during the checkout process and stored alongside their order. The customer’s IP address is only ever displayed to the store admin when they are viewing a particular order:

CropperCapture[3]

Anonymous Users To Checkout With Digital Downloads:

Previously when an anonymous user attempted to checkout with a digital download in their cart they would be redirected to the login screen. Now in version 1.4.0 anonymous users can now checkout and download their products without having to register/login into your DNN site. This feature should reduce the chance of users abandoning their carts during the checkout process if they are unwilling to share their details with your site.

If you have any feature requests for Cart Viper please contact us.



Using Skin Objects in Cart Viper – Part 2

  August 28, 2011 15:08
by Mark

Part 1 of of using skin object in Cart Viper focused on using an existing skin objects to add content to the templates used in our module. This part will focus on how to create custom skin objects to manipulate the product and category objects in Cart Viper.

Since release 1.4.0 we have add the ability for you to customise the output of the store using skin object, today I want to show you an advanced feature that lets you write custom code in .net to create skin objects which you can use in the store templates.

Lets take an example, I’ve got my store all setup but really want to display the logo for the manufacturer of each product. Cart Viper has no way to do this, however creating a custom skin object we can read the manufacturer value for the product and output a logo with ease.

Display an icon for the manufacturer

 

Displaying a Manufacturer Logo for a Product

Lets take a walk through creating the skin object to see how it works.

First I’ve uploaded my logos into a folder I’ve created in my portal home directory. I’m going to have my skin object display these on the product details page.

Folder contain the logos to use for the products

Next I’m going to create a new project in Visual Studio, I just need a Web Application Project, its important that we create this with in the DesktopModules folder. Notice that we don’t need to check “Create directory for solution”.

Creating the new project for the skin object

In order to create a skin object we need to inherit from a base class in DotNetNuke plus we want to use an interface from Cart Viper to allow the skin object to get Product object.
So we need to add two references to files located in the /bin folder of the portal.

Solution explorer showing the reference and the singel ascx control

When first creating the project Visual Studio will create some default folders and files which we don’t need so I’ve deleted those and added a single web User Control called ManfacturerLogo.ascx.

An important setting you need to make is to have the build output directly into the /bin folder of the portal.

Setting the build output path to the /bin folder

Lets take a look at the code in the ascx file, I’ve just got an image control which will output the logo for the manufacturer.

<%@ Control Language="C#" AutoEventWireup="true" 
CodeBehind="ManufacturerLogo.ascx.cs" 
Inherits="ManufacturerLogoSkinObject.ManufacturerLogo" %>

<asp:Image runat="server" ID="imgManLogo" Visible="false"/>

Looking at the code behind file shows how the skin object works.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DotNetNuke.UI.Skins;
using CartViper.Modules.Store.Components.SkinObject;

namespace ManufacturerLogoSkinObject
{
    public partial class ManufacturerLogo : SkinObjectBase, ICartViperSkinObject
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Product != null)
            {
                //get the manufacturer value, if its not null or empty
                //make into the path to the url for the logos folder
                string manufacturer = Product.Manufacturer;
                if (!string.IsNullOrEmpty(manufacturer))
                {
                    imgManLogo.ImageUrl = string.Format(
											PortalSettings.HomeDirectory + 
											"ManufacturerLogos/{0}.jpg", 
											manufacturer.Replace(" ", ""));

                    imgManLogo.AlternateText = manufacturer;
                    imgManLogo.Visible = true;
                }
            }
        }


        public CartViper.Modules.Store.Catalog.CategoryInfo Category
        {
            get;
            set;
        }

        public CartViper.Modules.Store.Catalog.ProductInfo Product
        {
            get;
            set;
        }
    }
}

Looking at the code the important parts to notice the class inheritance, we need to use SkinObjectBase which is located in the DotNetNuke.UI.Skins as the base class.
We are also implementing the interface CartViper.Modules.Store.Components.SkinObject.ICartViperSkinObject this interface allows the template engine in Cart Viper the ability to set the properties Category and Product with the current product data.

Note its only in the following templates that the ICartViperSkinObject properties will be set by the template engine.

  • ProductDetail.htm
  • ProductList.htm

In other templates the Category and Product properties will not be set and will be null.

The main work is completed in the Page_Load method, we check to see if we have Product object and then if the product has a value for the manufacturer property. We then remove all spaces from the manufacturer value and load that as the image source.

To use the module in DotNetNuke we need to have a DNN file to install the skin object.

<?xml version="1.0" encoding="utf-8" ?>

<dotnetnuke type="Package" version="5.0">
    <packages>      
        
    <package name="ManufacturerLogo" type="SkinObject" version="01.00.00">
        <friendlyName>ManufacturerLogo</friendlyName>
        <description>ManufacturerLogo</description>
        <owner>
            <name>Cart Viper</name>
            <organization>CartViper</organization>
            <url>www.cartviper.com</url>
            <email>mark@cartviper.com</email>
        </owner>
        <license/>
        <releaseNotes/>
        <components>
            <component type="SkinObject">
                <moduleControl>
                    <controlKey>MANUFACTURERLOGO</controlKey>
                    <controlSrc>
			DesktopModules\ManufacturerLogoSkinObject\ManufacturerLogo.ascx
					</controlSrc>
                    <supportsPartialRendering>False</supportsPartialRendering>
                </moduleControl>
            </component>
            <component type="File">
                <files>
                    <basePath>
					DesktopModules\ManufacturerLogoSkinObject
					</basePath>
                    <file>
                        <name>ManufacturerLogo.ascx</name>
                    </file>
                </files>
            </component>
            <component type="Assembly">
                <assemblies>
                    <assembly>
                        <path>bin</path>
                        <name>ManufacturerLogoSkinObject.dll</name>
                        <version>01.00.00</version>
                    </assembly>
                </assemblies>
            </component>
        </components>
    </package>
      
    </packages>
</dotnetnuke>

Then finally we just add the skin object into our ProductDetail.htm to get the manufacturer logo into the product details page.

<div class="StoreDetailContainer">
  <div class="StoreDetailContainer-Content">
    <div class="Normal productDetailPadding">[EDIT][MODELNAME] - [MODELNUMBERVALUE]</div>
    <div style="float:right">[SKINOBJECT:MANUFACTURERLOGO]</div>
    <div class="Normal productDetailPadding">
        [MEDIUMIMAGE]    
        <div style="clear:both;"></div>
        [ADDITIONALIMAGESGALLERY]
        <div style="clear:both;"></div>
        [DESCRIPTION]
    </div>
    <div class="StoreClear productDetailPadding">[MSRP]</div>
    <div class="StoreClear productDetailPadding">[PRICE] [VATPRICE]</div>
	<div class="Normal genericColour productDetailPadding">[AVERAGERATING]</div>
    <div class="productDetailPadding">[ADDTOCOMPARISONLIST]</div>
    <div>[EMAILAFRIEND]</div>
    <div>[PRODUCTVARIANTS]</div>
    <div class="productDetailPadding">[PRODUCTVISUAZLIER]</div>
    <div class="genericColour addToCartWrapper">[ADDQUANTITY] [ADDTOCART]</div>
     <div>[ADDTOWISHLIST]</div>
    <div style="clear:both;"></div>
    <div class="Normal productDetailPadding">[FACEBOOKLIKEBUTTON]</div>
  </div>
</div>

Conclusion

Using skin objects is a great way to customise Cart Viper, its lets you inject your own code and UI controls into the templates. Using this feature will let you tailor Cart Viper to your requirements with ease.

Download the source file



Using Skin Objects in Cart Viper Templates – Part 1

  August 26, 2011 18:28
by Mark

Since the first release of Cart Viper our DotNetNuke store we have supported a template based design and layout within our module. This allows the module to fit perfectly within a site simply by customising some XHTML files. Within the template files we have tokens which are replaced with data by the template engine when viewing the the store in a browser.

With the release of 1.4.0 we’ve taken this a step further and now allow you to insert skin objects into a template. The skin object will then be rendered into the template when browsing the store just like how we replace tokens.

Simple Skin Object Example

An existing skin object which comes as standard with DNN is the CURRENTDATE skin object, this when added to a template will output the current date.

A list of existing skin objects in DNN

As a very simple demo I’m going to modify the Product Detail (ProductDetail.htm) template to output this skin object after the model number at the top of the page.

To inject a skin object into a template we use [SKINOBJECT:NAME] where name is the skin object name, in this case CURRENTDATE.

<div class="StoreDetailContainer">
  <div class="StoreDetailContainer-Content">
    <div class="Normal productDetailPadding">[EDIT][MODELNAME] - [MODELNUMBERVALUE] [SKINOBJECT:CURRENTDATE]</div>
    <div class="Normal productDetailPadding">
        [MEDIUMIMAGE]    
        <div style="clear:both;"></div>
        [ADDITIONALIMAGESGALLERY]
        <div style="clear:both;"></div>
        [DESCRIPTION]
    </div>
    <div class="StoreClear productDetailPadding">[MSRP]</div>
    <div class="StoreClear productDetailPadding">[PRICE] [VATPRICE]</div>
	<div class="Normal genericColour productDetailPadding">[AVERAGERATING]</div>
    <div class="productDetailPadding">[ADDTOCOMPARISONLIST]</div>
    <div>[EMAILAFRIEND]</div>
    <div>[PRODUCTVARIANTS]</div>
    <div class="productDetailPadding">[PRODUCTVISUAZLIER]</div>
    <div class="genericColour addToCartWrapper">[ADDQUANTITY] [ADDTOCART]</div>
     <div>[ADDTOWISHLIST]</div>
    <div style="clear:both;"></div>
    <div class="Normal productDetailPadding">[FACEBOOKLIKEBUTTON]</div>
  </div>
</div>

When we then view the product details page you can see we’ve added the current date to the template.

Outputting the CURRENTDATE skin object in a template

Skin objects are regular ASP.Net objects so they can contain properties, using our template we can set values for the properties using this syntax.

[SKINOBJECT:MYSKINOBJECT(propertyName1,propertyValue1,propertyName2,propertyValue2,…)]

So we could set the property DateFormat on the CURRENTDATE skin object to allow us to just display the year.

Here is our template with the property set.

<div class="StoreDetailContainer">
  <div class="StoreDetailContainer-Content">
    <div class="Normal productDetailPadding">[EDIT][MODELNAME] - [MODELNUMBERVALUE] [SKINOBJECT:CURRENTDATE(DateFormat,"yyyy")]</div>
    <div class="Normal productDetailPadding">
        [MEDIUMIMAGE]    
        <div style="clear:both;"></div>
        [ADDITIONALIMAGESGALLERY]
        <div style="clear:both;"></div>
        [DESCRIPTION]
    </div>
    <div class="StoreClear productDetailPadding">[MSRP]</div>
    <div class="StoreClear productDetailPadding">[PRICE] [VATPRICE]</div>
	<div class="Normal genericColour productDetailPadding">[AVERAGERATING]</div>
    <div class="productDetailPadding">[ADDTOCOMPARISONLIST]</div>
    <div>[EMAILAFRIEND]</div>
    <div>[PRODUCTVARIANTS]</div>
    <div class="productDetailPadding">[PRODUCTVISUAZLIER]</div>
    <div class="genericColour addToCartWrapper">[ADDQUANTITY] [ADDTOCART]</div>
     <div>[ADDTOWISHLIST]</div>
    <div style="clear:both;"></div>
    <div class="Normal productDetailPadding">[FACEBOOKLIKEBUTTON]</div>
  </div>
</div>

The output now simply shows the current year.

Setting a property of a SKINOBJECT

The ability to add skin objects into your templates opens up the range of possibilities and ideas you can now implement.

We aren’t finished there we have one more Skin Object trick which you can use to make great ecommerce sites, take a look at Using Skin Objects in Cart Viper – Part 2 to see how you can extend Cart Viper using templates.



Using the Subversion Revision Number in NAnt

  August 20, 2011 18:37
by Mark

We have recently updated our NAnt build script used to build Cart Viper to include the revision number from Subversion. So now when we build the project it will update all the build numbers of the DLLs to have a revision number equal to the revision number from Subversion.

DLL build number as set using NAnt script

In the example above the major, minor and build numbers come from a property we define in the NAnt script, so we just need to change this to increment all the DLLs to the new number.

The revision number of 2250 is the revision number from Subversion, so in the future we now that this DLL was compiled using revision 2250 of our code base. This is automatically read from Subversion using the script below.

Read the Revision Number from Subversion

Note we use TortoiseSVN so we are using a binary from that program to get the revision number.

First we need to commit a special text file to the Subversion repo, this file contains a token which when we output the file from the repo will be replaced with the latest SVN revision number.
The file should just contain the token

$WCREV$

Contents of the rev.txt

Make sure you commit the file into the repo, my file is call rev.txt

For our build process we have a sub folder off the root of the project called build which contains the NAnt script and the revision file.

In the NAnt build script we have the init target which handles updating the build number.

<target name="init">
    <!-- basic verison number to set for the DLLs -->
    <property name="shortVersion" value="1.4.1"/>
    
    <property name="build.version.revision" value="0" />

	<exec program="subwcrev" basedir="C:\Program Files\TortoiseSVN\bin" 
		commandline='./ rev.txt revvalue.txt' failonerror="false"/>

The part that does the work is the exec element, this calls the subwcrev command line tool to output the rev.txt file to a file called revvalue.txt. This will have the effect of replacing the token with the reversion number.

Now we need to read the contents of the file into a property in NAnt.

    <loadfile file="./revvalue.txt" property="build.version.revision"/> 

Updating the AssemblyInfo.cs Files in NAnt

The final thing we need to do is take the version numbers we have and replace these in all the AssemblyInfo.cs files in our project.
To do this we need to use some custom code in the script. Remember we have our build file in a sub folder off the root of the main project file. So we need to move up one level, you may need to change this in relation to the location of the NAnt build file and the project root (see line 12).

<!-- run some custom code to find all the files then 
         update the rev number to the one we've just read from 
         subversion --> 
     <script language="C#"> 
          <references> 
              <include name="System.dll" /> 
          </references> 
          <imports> 
              <import namespace="System.Text.RegularExpressions" /> 
          </imports> 
          <code> 
            <![CDATA[ 
              public static void ScriptMain(Project project) { 
                  DirectoryInfo baseDirectory =  new DirectoryInfo(project.BaseDirectory); 
                  DirectoryInfo rootDirectory = baseDirectory.Parent; 
                  
                  string buildNumber = project.Properties["shortVersion"].Replace("\r\n", ""); 
                  string revisionBuild = project.Properties["build.version.revision"].Replace("\r\n", ""); 
                  StringBuilder buffer = new StringBuilder(); 
                  
                  var files = rootDirectory.EnumerateFiles("AssemblyInfo.cs", SearchOption.AllDirectories); 
                  
                  foreach(FileInfo fi in files){ 
                    string fileContents; 
                  
                    using(FileStream stream = fi.Open(FileMode.Open, FileAccess.ReadWrite )){ 
                      using(StreamReader reader = new StreamReader(stream)){ 
                        fileContents = reader.ReadToEnd(); 
                        
                        //set the assemblyVersion 
                        string assemVersion = Regex.Match(fileContents, @"\[assembly: AssemblyVersion.*").Value; 
                        
                        if(!string.IsNullOrEmpty(assemVersion)){ 
                          buffer.Append(assemVersion.Substring(0, assemVersion.IndexOf('"') + 1)); 
                          buffer.Append(buildNumber); 
                          buffer.Append("."); 
                          buffer.Append(revisionBuild); 
                          buffer.Append("\")]"); 
                          
                          fileContents = fileContents.Replace(assemVersion, buffer.ToString()); 
                          buffer.Clear(); 
                        } 
                        
                        //set the AssemblyFileVersion 
                        string assemFileVersion = Regex.Match(fileContents, @"\[assembly: AssemblyFileVersion.*").Value; 
                        if(!string.IsNullOrEmpty(assemFileVersion)){ 
                          buffer.Append(assemFileVersion.Substring(0, assemFileVersion.IndexOf('"') + 1)); 
                          buffer.Append(buildNumber); 
                          buffer.Append("."); 
                          buffer.Append(revisionBuild); 
                          buffer.Append("\")]"); 
                          fileContents = fileContents.Replace(assemFileVersion, buffer.ToString()); 
                          buffer.Clear(); 
                        } 
                      } 
                    } 
                    
                    using(FileStream stream = fi.Open(FileMode.Truncate, FileAccess.Write)){ 
                      using(StreamWriter writer = new StreamWriter(stream)){ 
                        writer.Write(fileContents); 
                      } 
                    } 
                    
              } 
            } 
            ]]> 
          </code> 
      </script> 
</target>

Now when you build the script the build numbers will be updated automatically.



Improved Sale Stats Page

  August 16, 2011 15:11
by Mark

Running an online shop means you need to be able monitor your store and see how well it performing, in previous versions of Cart Viper we had the Sales Stats page within the Store Admin. This page displays information about your sales, we’ve improved this in Cart Viper 1.4.0 to be even better.

  • More graphs for at a glance performance indication.
  • More data to get a better understanding of how your store is doing
  • We’ve also included a graph which shows abandoned carts, these are carts which have been created but the customer never completed the checkout process.

New and improved Sales Stats page

Rolling over the graphs then displays a popup.

Graph showing hovering over a data point

The graphs are rendered using Javascript and no data is ever sent to a 3rd party. The graphs are created locally on the server.