Cart Viper now has the ability to define products as request a quote. this allows you to list expensive items which you need to quote for on a user by user basis.
Users can assemble a special type of cart that we refer to as “quote cart”, each item that the user wants to get a quote for is added to this cart, along with the quantity of each item. Once the user has added all the items they want to receive a quote they then continue to the checkout page.
At the checkout stage the user simply completes the form, this then generates an email which is set to the store administrator.
To define which products are “request a quote” the administrator simple checks the box in the product admin page.
To make the checkout process simple we only allow the user to have either a normal cart or a quote cart at anyone time. If a user were to attempt to create a quote while they had a normal cart they would receive a warning tell them to complete the checkout process before creating a quote and vice versa.
b3c9775f-abb1-4969-a051-7717004f4421|0|.0|27604f05-86ad-47ef-9e05-950bb762570c
Continuing the series about new features coming in release 1.0.3 of Cart Viper today I’m going to talk about the additional currency support that has been added.
In the initial release transaction where limited to Euros, GBPs or USDs. However in 1.0.3 of the shopping cart we’ve added support for Australian dollars (AUD), Canadian dollars (CAD), Mexican peso (MXN) and Swiss francs (CHF).
We’ve also moved the currency symbols for each currency into the SharedResources.resx file in App_LocalResources so this give you complete control on how you you would like to display the currency symbol. You can simply edit the default entries as required.
Resource Key | Currency | Value |
Currency_AUD.Text | AUD | AUD $ |
Currency_CAD.Text | CAD | CAD $ |
Currency_CHF.Text | CHF | CHF |
Currency_EURO.Text | EURO | € |
Currency_GBP.Text | GBP | £ |
Currency_MXN.Text | MXN | Mex $ |
Currency_USD.Text | USD | $ |
If you would like additional currencies add just get in touch and we’ll try our best to help you out.
Stay tuned for more posts about up coming features!
f222b8c0-e2f0-49e4-857c-59f10824747b|0|.0|27604f05-86ad-47ef-9e05-950bb762570c
Continuing the series of posts about new features in release 1.0.3 of Cart Viper its time to look at the Wish List feature.
This allows users to store a list of items they would like to purchase.
On the product details page a user would simple click the Add to Wishlist link to have the item store for them in their wish list.
The wish list is display on the My Account page with the ability for the user to add an item into their cart directly from the wish list.
All wish lists are private and only the user that created the list is able to view it.
Allowing your users to create wish lists is an optional feature, you can disable wish lists by unchecking the Enable Wishlist in the store admin.
6f6e7d2b-1379-4b25-85b5-f2244d3e963c|0|.0|27604f05-86ad-47ef-9e05-950bb762570c
Here at Cart Viper we have been busy working on version 1.0.3 of our DotNetNuke shopping cart that is full of new features , over the next few days leading up to the release of version 1.0.3 Mark and myself are going to do a series of posts discussing the new features. This post will discuss “Email A Friend”.
Due to the flexibility of Cart Vipers template driven display simply by including the [EMAILAFRIEND] tag in your productDetail.htm template you output the necessary control onto your page that allows a user to send an email relating to a product on your site.
Example template:
Example page created from template:
When “Share With A Friend” is clicked upon the email a friend control is displayed via jQuery.
Email a friend control:
The email subject and message are pre-populated with the name of your store and a link to the page with the product on, if the user is logged in the email from is also pre-populated with their email address. All fields can be edited by the user before the message is sent.
Before the message can be sent all fields are checked for profanity if found the user is informed and the message is not sent, furthermore recaptcha has been added to avoid spam being sent.
It is worth noting for privacy reasons a copy of the users message is not stored in the system.
77b1646a-cc27-4286-a56f-97eb4e318a01|0|.0|27604f05-86ad-47ef-9e05-950bb762570c
On our site we list a road map of features for Cart Viper, this comes straight out of Trac in this post I’m going to explain how we do this.
On the Trac server we’ve created a custom query for each version Cart Viper we want to publish the road map for.
The query in affect limits the tickets to a given version of Cart Viper.
Once you’ve created the feeds you can then access the tickets via the RSS feed for each query.
So over in DotNetNuke simple add the News Feed Module to the page and configure it with the URL for the Trac feed and the correct credentials.
Then using our custom XSLT file and a bit of jQuery we get the finished result.
1: <?xml version="1.0"?>
2: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3: <xsl:output method="html" indent="yes"/>
4: <xsl:param name="ItemsToShow"/>
5: <xsl:param name="ShowItemDetails"/>
6: <xsl:param name="ShowItemDate"/>
7: <xsl:param name="Locale"/>
8: <xsl:template match="rss">
9: <xsl:for-each select="channel/item[position()<=$ItemsToShow or $ItemsToShow<1]">
10: <div class="cvRoadMapItem Normal">
11: <p class="cvRoadMapTitle">
12: <a href="#" class="cvRoadMapLink">
13: <xsl:value-of select="title"/>
14: </a>
15: </p>
16: <xsl:if test="$ShowItemDate='true'">
17: <div class="cvRoadMainDate">
18: <xsl:value-of select="pubDate"/>
19: </div>
20: </xsl:if>
21: <xsl:if test="$ShowItemDetails='true'">
22: <div class="cvRoadMainDesc" style="display:none;">
23: <xsl:value-of select="description" disable-output-escaping="yes"/>
24: </div>
25: </xsl:if>
26: </div>
27: </xsl:for-each>
28: </xsl:template>
29: </xsl:stylesheet>
1: jQuery(document).ready(function(){
2:
3: jQuery(".cvRoadMapLink").toggle(function(){
4: jQuery(this).parents().siblings(".cvRoadMainDesc").show('fast');
5: },
6: function(){
7: jQuery(this).parents().siblings(".cvRoadMainDesc").hide('fast');
8: });
9:
10: });
0da8cce1-f028-46dc-bed4-1b97adfdd087|0|.0|27604f05-86ad-47ef-9e05-950bb762570c
One of the ideas we had for this blog was to post the lessons we had learnt during the development of Cart Viper. Although we feel as a CMS DotNetNuke is really good, as a platform to develop on the documentation is somewhat lacking. So the aim of this and future posts is to try and save you some time and hours of pulling your hair out if you are developing modules for the DotNetNuke platform by recounting the issues with the framework we have encountered.
In Cart Viper we have made extensive use of jQuery Ajax calls to provide a rich user experience. In order to achieve this we call a HttpHandler which in turn delegated the request to the appropriate class that would then process the request and return the correctly formatted JSON result. It was whilst in this class we ran into an issue.
Whilst in the HttpContext whenever you required the current PortalSettings object you could simple call:
1: PortalSettings portalSettings = Globals.GetPortalSettings();
However as we were not in the HttpContext, PortalSettings was always null. This left us with the problem of how to instantiate the PortalSettings object.
One solution would be to pass in the PortalID as a parameter into the jQuery Ajax request, however a user could easily see the JSON request using firebug and then attempt to pass in a different PortalID into your HttpHandler, which in turn could then lead to cross portal updates. We did not like the security risks in this method so we thought how could we securely pass the current PortalID to the required class?
The solution we devised involved creating a base class that all .ascx controls we use within Cart Viper would implement:
1: public class StoreControlBase : PortalModuleBase
2: {
3: public StoreControlBase()
4: {
5: }
6: }
In this base class we inserted the following method:
1: /// <summary>
2: /// Writes the portalId to an encrypted cookie
3: /// </summary>
4: /// <remarks>this is the used by ajax to determine the correct portalId</remarks>
5: protected void WritePortalIdCookie()
6: {
7: HttpCookie cookie = HttpContext.Current.Request.Cookies["YOUR PORTAL COOKIE"];
8: if (cookie == null)
9: {
10: cookie = new HttpCookie("YOUR PORTAL COOKIE");
11: }
12:
13: string cookieValue;
14:
15: if (SymmetricHelper.CanSafelyEncrypt)
16: cookieValue = SymmetricHelper.Encrypt(this.PortalId.ToString());
17: else
18: cookieValue = PortalId.ToString();
19:
20: cookie["PortalId"] = cookieValue;
21:
22: HttpContext.Current.Response.Cookies.Add(cookie);
23: }
Then in each of the .ascx controls that make a jQuery AJAX request we simple add the following line to the page load event:
1: protected void Page_Load(object sender, System.EventArgs e)
2: {
3: //write out the portal cookie so we have it for the ajax
4: base.WritePortalIdCookie();
5:
6: //page load as normal
7: }
Then in the class it is just a case of getting the PortalID that is stored securely in the cookie and populating the associated PortalSettings object:
1: /// <summary>
2: /// Readonly access to the PortalSettings object for the
3: /// current portal context
4: /// </summary>
5: protected PortalSettings PortalSettings
6: {
7: get
8: {
9: HttpCookie cartCookie = HttpContext.Current.Request.Cookies["YOUR COOKIE NAME"];
10: if (cartCookie != null)
11: {
12: string pid = cartCookie["PortalId"];
13: if (SymmetricHelper.CanSafelyEncrypt &&
14: !string.IsNullOrEmpty(pid))
15: {
16: try
17: {
18: pid = SymmetricHelper.Decrypt(pid);
19: return new PortalSettings(Int32.Parse(pid));
20: }
21: catch (Exception ex)
22: {
23: //the portal cookie is correct, rethrow
24: throw ex;
25: }
26: }
27: }
28:
29: throw new ApplicationException("Portal cookie is not valid");
30: }
31: }
This property should then return a fully populated PortalSettings object.which you can then query to get specific information relating to the Portal the request has originated from.
cd4be3d2-ad50-4681-ab89-063cbc907cef|0|.0|27604f05-86ad-47ef-9e05-950bb762570c
After what seems like weeks and weeks of coding we appear to be closing in on our first release of Cart Viper.
What is Cart Viper?
Cart Viper is an advanced ecommerce module for DotNetNuke. Its allows you create a shop and start selling goods and digital downloads in minutes.
We’ve focused on making Cart Viper simple to start using but powerful for advanced users. We’ll be discussing more about the features in the future.
Why Cart Viper?
We are two developers from the UK that have already had success with creating DNN modules but where disappointed with the current ecommerce modules out there. So we decided to do something about it, hence the blog you’re reading now.
Stay tuned.
4a5d74c7-8010-4a32-8c06-b7abd8685a93|0|.0|27604f05-86ad-47ef-9e05-950bb762570c