Adding a total order count column to order summary

by Joe Payne 24. September 2008 09:09
Introduction
This modification will add a new column to your AC7 Order Summary page. The contents of the column will be a clickable number showing the total order history count for the customer that placed the order. This gives you the ability to quickly and easily see which customers are repeat customers without having to switch to the reports page.
The total count is all-inclusive and does not restrict by a particular date range. It is also a link. When clicked, it will take you to the Edit User page so the detailed history for that customer can be viewed.

Modifications
The page file we'll be changing is located in ~/Admin/Orders/. You'll need to change both the default.aspx and default.aspx.cs files, so back them both up before going any further.

Edit the ~/Admin/Orders/default.aspx file first. Look for this section of code:
Code:
                            <asp:TemplateField HeaderText="Customer" SortExpression="BillToLastName">
                                <ItemStyle HorizontalAlign="Center" />
                                <ItemTemplate>
                                    <asp:Label ID="CustomerName" runat="server" Text='<%# string.Format("{1}, {0}", Eval("BillToFirstName"), Eval("BillToLastName")) %>'></asp:Label>
                                </ItemTemplate>
                            </asp:TemplateField>


and replace it with this code:
Code:
                            <asp:TemplateField HeaderText="Customer" SortExpression="BillToLastName">
                                <ItemStyle HorizontalAlign="Center" />
                                <ItemTemplate>
                                    <asp:Label ID="CustomerName" runat="server" Text='<%# string.Format("{1}, {0}", Eval("BillToFirstName"), Eval("BillToLastName")) %>'></asp:Label>
                                </ItemTemplate>
                            </asp:TemplateField>


                            <asp:TemplateField HeaderText="History" SortExpression="">
                                <ItemStyle HorizontalAlign="Center" />
                                <ItemTemplate>
                                    <asp:HyperLink ID="OrderCount" runat="server" Text='<%# string.Format("{0}",OrderCount(Container.DataItem)) %>' SkinID="Link" NavigateUrl='<%# Eval("UserId", "~/Admin/People/Users/Edituser.aspx?UserId={0}") %>'></asp:HyperLink>
                                </ItemTemplate>
                            </asp:TemplateField>


Done? Good, save it. Now let's edit the ~/Admin/Orders/default.aspx.cs file. Look for this section of code:
Code:
    protected string GetPaymentStatus(object dataItem)
    {
        Order order = (Order)dataItem;
        if (order.PaymentStatus == OrderPaymentStatus.Paid) return "Paid";
        if (order.Payments.Count > 0)
        {
            order.Payments.Sort("PaymentDate");
            Payment lastPayment = order.Payments[order.Payments.Count - 1];
            return StringHelper.SpaceName(lastPayment.PaymentStatus.ToString());
        }
        return order.PaymentStatus.ToString();
    }


and replace it with this code:
Code:
    protected string GetPaymentStatus(object dataItem)
    {
        Order order = (Order)dataItem;
        if (order.PaymentStatus == OrderPaymentStatus.Paid) return "Paid";
        if (order.Payments.Count > 0)
        {
            order.Payments.Sort("PaymentDate");
            Payment lastPayment = order.Payments[order.Payments.Count - 1];
            return StringHelper.SpaceName(lastPayment.PaymentStatus.ToString());
        }
        return order.PaymentStatus.ToString();
    }

    protected string OrderCount(object dataItem)
    {
        Order order = (Order)dataItem;
        return order.User.Orders.Count.ToString();
    }


Save it when you're done. Upload the changes if you have to, then give it a try!

Conclusion
Knowing more about your customers is what makes a good business owner great. Give yourself another edge over your competition by quickly and easily knowing your repeat customers before their order has even been filled.

Tags: , ,

AC7 Articles

Show Miscellaneous charges on the AC7 invoice

by Joe Payne 13. Mei 2008 00:47
Just a quick modification today, so here goes:

The default AC7 invoice doesn't show credits, discounts, extra charges etc. It has the programming to do so, but the code doesn't work like it should. If you've ever added an extra line item for a Discount and then printed the invoice, you'll see what I mean.

Here's how to fix it so the line shows every time. As I said, this is a quick fix (I was in a hurry today) so the "Other:" charge line will show on every invoice whether it has a zero amount or not. Perhaps when I have more time I can make it fully functional as Able intended.

Edit the ~/Admin/Orders/Print/Invoices.aspx page and find this line:

Code:
                            <tr id="trOther" runat="server" visible='<%# GetTotal(Container.DataItem, OrderItemType.Charge, OrderItemType.Coupon, OrderItemType.Credit, OrderItemType.Discount, OrderItemType.GiftCertificate, OrderItemType.GiftWrap) > 0) %>'  >


And remove the entire visible= parameter so the line looks like this:

Code:
                            <tr id="trOther" runat="server" >


Now go display an invoice for an order. You should see a line for "Other:" and it will contain the proper dollars for any discounts, coupons, additional charges etc that are part of the order line items.

Tags: , ,

AC7 Articles

Add custom settings available store wide

by Joe Payne 15. April 2008 00:22
Introduction
As you get deeper into programming in AC7, you might find the need have a parameter specified on the Admin side that needs to be acted upon on the store side. All of the AC7 store-wide settings are stored in the ac_StoreSettings table. What's interesting is the CommerceBuilder API gives you some *very* easy methods to store and retrieve your own custom settings.

An Example Goal
The best way to learn is by-example, so let's make up a need and accomplish that need using this technique. For today's example, we have a request to create a catch-all AC7 page for visitors who request a missing product. Apparently the site admin recently decided to rebuild part of the product catalog. Well, that "broke" all those product URLs since the Product ID is tied to the URL and alot of visitor landings are getting the generic IIS "page missing" errors. The sales manager says "fix it, make it clean and don't you dare hard-code it!". Pffft like the sales manager even KNOWS what hard-coding means, but that's a debate for another time.

Project Definition
1. Failed product lookups must redirect to an AC7-controlled page. The server administrator doesn't want you playing with IIS site settings.

2. The designated redirect page must be configurable on the Admin side. The only other thing managers do well besides creating unrealistic expectations is changing their minds AFTER you coded everything.

3. Programming testing if the value has been specified on the Admin side should be easy to do. You're the one stuck with this project and that Friday night trip to the riverboat casino didn't help getting you up for work this morning.

The Admin Side Changes
Every good project has an even better foundation. We're going to integrate this change right into the main AC7 Store, Configure menu option. The site admin will be pleased. Let's start by editing the ~/Admin/Store/StoreSettings.aspx and adding a text box control with label to the page. Look for this code in the page near the bottom:

Code:
                        <asp:Label ID="ProductPurchasingDisabledLabel" runat="server" Text="Enabling this feature will hide the add to basket button for all products, so customers can browse your catalog but are unable to purchase directly online."></asp:Label><br />
                        <asp:CheckBox ID="ProductPurchasingDisabled" runat="server" Text="Enable Catalog Mode"/>


and replace it with this code:

Code:
                        <asp:Label ID="ProductPurchasingDisabledLabel" runat="server" Text="Enabling this feature will hide the add to basket button for all products, so customers can browse your catalog but are unable to purchase directly online."></asp:Label><br />
                        <asp:CheckBox ID="ProductPurchasingDisabled" runat="server" Text="Enable Catalog Mode"/>
                        <br />
                        <asp:Label ID="lbl_ProductMovedPage" runat="server" Text="Redirect page for invalid Products (blank redirects to home page):"></asp:Label><br />
                        &nbsp;<asp:TextBox ID="txt_ProductMovedPage" runat="server" Width="310px"></asp:TextBox><br />


Once you've added the text box, we have to modify both the Load section and the Save section of the page. The site admin will be able to always see what the current setting is and make changes to it all on the same page. Look towards the top of the page in the Page_Load function for this code:

Code:
         //GIFT CERTIFICATE EXPIRY
            GiftCertExpireDays.Text = settings.GiftCertificateDaysToExpire.ToString();


and replace it with:
Code:
         //GIFT CERTIFICATE EXPIRY
            GiftCertExpireDays.Text = settings.GiftCertificateDaysToExpire.ToString();

            //BEGIN: Solunar.com Mod
            // Moved Product Page URL
            txt_ProductMovedPage.Text = settings.GetValueByKey("CUSTOM:BadProductPage");
            //END: Solunar Mod


All done? Perfect. But we still have to make the system save any changes made. So let's move down into the SaveSettings() function and find this section of code:

Code:
        //Gift Certificate Days to Expire
        settings.GiftCertificateDaysToExpire = AlwaysConvert.ToInt(GiftCertExpireDays.Text);
       
        //BEGIN: Solunar Mod
        //Missing Page URL
        settings.SetValueByKey("CUSTOM:BadProductPage", txt_ProductMovedPage.Text);
        //END: Solunar Mod


Save your changes and test the page. You should have a new text box field located on the bottom-right of the Configure, Store page. Enter something (anything) in the field and save the settings. Now switch to another page and then back again to the Configure, Store page to ensure the changes you made were saved. If you did everything right, you'll see the test value you entered already populated in the text box.

The Store Side
So all this work just to store one value on the Admin side was fun, but how does it help you? Well, we now have a custom user-specified value that is easily editable on the Admin side. All we have to do now is know how to retrieve that value on the store side. For our example today, we're going to edit the BuyProductDialog.ascx user control. Every product page uses it, so it's a good place to put in a test for an invalid product and redirect to our new custom URL.

Let's start by editing the BuyProductDialog.ascx.cs code file located in the ~/ConLib/ folder. Look for this code at the end of the Page_Init function, directly above the start of the next subroutine UpdateInventoryDetails():

Code:
        else
        {
                Response.Redirect(NavigationHelper.GetHomeUrl());
        }


and replace it with:

Code:
        else
        {
            //BEGIN: Solunar Mod
            // ProductId not found, redirect to the badproductpage
            // Retrieve redirect URL for missing products
            StoreSettingCollection settings = Token.Instance.Store.Settings;
            string _BadProductPage = settings.GetValueByKey("CUSTOM:BadProductPage");
            if (string.IsNullOrEmpty(_BadProductPage))
            {
                Response.Redirect(NavigationHelper.GetHomeUrl());
            }
            else
            {
                Response.Redirect(_BadProductPage);
            }
            //this.Controls.Clear();
            //END: Solunar Mod
        }


Save it.

What's Happening?
Study the above code for a minute. Retrieving a value in the StoreSettings table is incredibly easy. It's always available because the Store data class is always available. So first things first, we grab the store settings collection from the Store data class and assign it to a seperate variable. While this is an extra step, it makes for easy-to-read code and that's always a good programming practice.
By calling the GetValuebyKey() function, we've told the data class to search the ac_StoreSettings table for a key named "CUSTOM:BadProductPage" and return the value assigned to that key. If no value is returned i.e. the key couldn't be found, the code will simply redirect the user to the home page. But if a value is returned, then use that value as the destination redirect page. Cool!

Testing
Let's test all of this now. Build a web page you want to be displayed for missing products. Call it MovedProduct.aspx and store in the root of your store. Now go back into the Admin side of the store and enter ~/MovedProduct.aspx as the value for the your new custom field in the Configure, Store page.
Finally, the test. Fire up your browser and enter your store URL with a bad ProductId value like
http://www.mystore.com/Product.aspx?ProductId=99999 and see what happens. The original AC7 design would have dumped you back to the home page - not terribly intuitive from a visitor perspective. But you should be redirected to your brand new MovedProduct page instead. Now you can offer the visitor additional search options, explain why they got there or even offer to sell a substitute product.

Conclusion
Creating admin-side custom settings that can be retrieved on the store side is very powerful. It gives the developer the ability to offer admin-manageable features without hard-coding or repeated programming changes. AC7 gives you all the tools you need to create and access customized settings from anywhere within the store front.

Tags: ,

Add a comment field for each customer

by Joe Payne 29. Maart 2008 05:00

Introduction
I have seen a few requests from folks who would like a way to store comments for a particular user. It may be something like "What a swell guy" or it could even be "Problem customer: high RMA rate".
Regardless of your reasons, it would be nice to have such a feature. Fortunately, the field exists in the database. It's just been left off the Edit User page for some reason. This modification describes how to easily add the field to the screen.

I know I said I was going to be away for a while. Well, I wound up with some spare time and needed this particular change. Once I realized how simple it was, I recalled others wanted it too, so I decided to document it.

As always, make a backup of the files involved in case something bad happens.

HTML Changes
The file we're going to change is ~/Admin/People/Users/EditUser.aspx. There is no code-behind file, so all the changes will occur in the same file.

Edit the file and find this section of code in the HTML section towards the end of the file:

Code:
                            <asp:DropDownList ID="Residence" runat="server">
                                <asp:ListItem Text="This is a residence" Value="1"></asp:ListItem>
                                <asp:ListItem Text="This is a business" Value="0"></asp:ListItem>
                            </asp:DropDownList>
                        </td>
                    </tr>


and replace all of it with this code:

Code:
                            <asp:DropDownList ID="Residence" runat="server">
                                <asp:ListItem Text="This is a residence" Value="1"></asp:ListItem>
                                <asp:ListItem Text="This is a business" Value="0"></asp:ListItem>
                            </asp:DropDownList>
                        </td>
                    </tr>
                    <tr>
                        <th class="rowHeader">
                            Comment:</th>
                        <td colspan="3">
                            <asp:TextBox ID="Comment" runat="server" Height="95px" TextMode="MultiLine" Width="445px"></asp:TextBox></td>
                    </tr>


We've changed the screen display but the page doesn't know how to save or load the actual field contents. Let's do that next....

Code Changes
There are two changes to made in the code. One reads the existing Comment field value into the page. The other writes it back to the User record before the record is saved.

First, find this line of code in the InitializeForm function near the beginning:

Code:
            Residence.SelectedIndex = (address.Residence ? 0 : 1);


and add this line immediately below it:

Code:
            Comment.Text = _User.Comment;


Now, find this line of code further down in the SaveUser() function:
Code:
            address.Residence = (Residence.SelectedIndex == 0);


and add this line immediately below it:
Code:
            _User.Comment = Comment.Text;


Save the page.

Testing
Go ahead and pull up your User page and edit any user. You should now see a large, unlimited text box below the address area. Try it out and type something into it, then Save the user. Return to your Dashboard, then again to the User page. Pull up the User and see if your changes were saved.

Conclusion
Having the ability to store comments with a particular user account can give an admin useful insight into the customer. Any opportunity to know more about who you are dealing with is an opportunity to succeed. Knowledge truly is power.

Tags:

AC7 Articles

Creating a new category display page

by Joe Payne 6. Maart 2008 12:30
Introduction
There are about a billion reasons to create a new category page, so I won't go into the why or what-for. Suffice it to say, you may want one so here is how to do it.

Copy the file
Pick the category display page you'd like to use as your starting point. For this document, let's assume it's CategoryGrid2.aspx. Let's assume your new file name will be "CustomGrid2.aspx". Avoid using new category page filenames of "CategoryGrid?.aspx" as future AC7 updates might include additions that overwrite your page.

Copy the file ~/CategoryGrid2.aspx to "CustomGrid2.aspx". Now you have to edit the new file so AC7 will know to treat it as a category display page.

Modifying the file
Category display pages are identified in the system using this comment line in the beginning of the .aspx file:

[quote] 
<%--
<DisplayPage>
    <Name>Category Grid (Deep Item Display)</Name>
    <NodeType>Category</NodeType>
    <Description>The defualt category page that displays products in a grid format. All sub-products in all sub-categories of the category are displayed. Allows customers to browse your catalog.</Description>
</DisplayPage>
--%>
[/quote]

In your new file copy, be sure to change the name and description values of the comment section as shown above to differentiate yours from the included pages.

Save it.

Conclusion
You now have a new choice in the drop downs for category display pages. If you've modified the comment section correctly at the beginning of the new file, AC7 will recognize it and use it just like any other category display page.

Tags: ,

AC7 Articles

Month List