Showing posts with label Webstore. Show all posts
Showing posts with label Webstore. Show all posts

Tuesday, August 2, 2011

Couple things NetSuite Documentation Doesn't Tell You

We've MOVED!!!! www.codeboxllc.com/ksc

NetSuite most likely doesn't care what I complain to them about. I'm no body. I'm just a guy trying to make in this world.

However, I think these two items they may listen and PUT it on the documentation or make it more clearer.

Point 1: Check out customization URLs
There is ONLY ONE usable checkout URL in Sandbox Environment. That is https://checkout.sandbox.netsuite.com. All other selections are used ONLY for production.
I came across this issue while making our second webstore in Sandbox. When ever we refresh our Sandbox from Prod, this error occured. I initially thought it was just a flook. However, when second brand new Webstore I started on began to throw "Page Not Found" or "Internal Server Error" with other customizable check out URL, that's when it got me concerned.

Point 2: Domain IS required to be able to use Descriptive URLs
I'm sure some of you already knew this. I couldn't find anything on documentation about this specific statement. However, If you are having issues with Descriptive URL you set up for Items and Presentation Tabs, you need to set up your own domain.

CORRECTION:
Apparently, Point 2 is wrong on my part. You can find it under this Path of documentation:
Web Site : Searching & Search Engine Optimization : Search Engine Optimization (SEO) : Setting Up Descriptive URLs


It says:
To use descriptive URLs in NetSuite, first, set up a domain at Setup > Web Site > Set Up Domains. Next, turn on the Advanced Site Customization feature, and the Descriptive URLs feature at Setup > Company > Enable Features, on the Web Presence subtab. 

Saturday, July 30, 2011

Webstore Main Menu Customization

We've MOVED!!!! www.codeboxllc.com/ksc

Who uses out of the box template for website any more? If you are using NetSuite Advanced Site Customization, you have the option to custom build the main navigation bar.

I've seen some posting on NetSuite Forum where fellow NetSuite users were asking for ability to build out dynamic menu system on their Webstore without heavy scripting. I am one of them.
Standard "Tabs" just doesn't do justice for my brilliant site layout. (I'm seriously being sarcastic here...)

So, how do you build this in WITHOUT heavy scripting? Well... unfortunately, you still need to do SOME scripting but method I found seems to work out without too much headache.

For my little project, I wanted to build dynamic horizontal menu layout.

In NetSuite, you can use <NLPAGETABS> to generate he horizontal tab menu layout. If you sue this tag nested between <table> and </table> tags in Logo and Tabs Template section under Body tab of your Theme.
As long as you have your tabs marked as "Show on Website", that one tag will render everything for you.

Here is sample menu tree I wanted to achieve:
Home page Products (Presentation Tab 0) Shopping Cart My Account
  Product Page 1 (Presentation Tab A)    
  Product Page 2 (Presentation Tab B)    
  Product Page 3 (Presentation Tab C)    

When visitor mouse over to Products, I want three sub pages to show up. As noted above, each page is a presentation tab with different items. 

If you were to ONLY use out of the box <NLPAGETABS>, those sub pages will get rendered as main navigation and will NOT look good.

Here is how I implemented dynamic custom main menu:
Step 1: Find the script you like.
I found a very handy, easy to use dynamic menu from Dynamic Drive. The script I found is very simple and not much modification is needed. Details of this script can be found here. Be sure to read their Terms of Use before using it. =)
I made some modifications to the CSS file to match the theme of my website. 

Step 2: Upload script files, CSS files and any images to your NetSuite Document folder.
What ever file you decide to use, you need to first upload it to your documents folder to be referenced on your Webstore. Script that I found from Dynamic Drive is fairly small and simple which I really like.

Step 3: Implement. (This is implementation using the Script from Dynamic Drive)
  • Make sure .js and .css files are referenced at the Header. [Your Theme] > General > Additon to <head> section.
Go to [Your Theme] > Body > Logo and Tabs Template section and add in your navigation.
Code Sample:
Main Navigation Code:
<div class="chromestyle" id="chromemenu">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#" rel="dropmenu1">Products</a></li>
<li><a href="#">Shopping Cart</a></li>
<li><a href="#">My Account</a></li>
</ul>
</div>
** red="dropmenu1" indicates a reference to sub menu items.
Sub Menu Navigation Code:
<div id="dropmenu1" class="dropmenudiv">
<a href="#">Product Page 1</a>
<a href="#">Product Page 2</a>
<a href="#">Product Page 3</a>
</div>
Script Tag:
** Add this after you've placed all your menu item
<script type="text/javascript">
cssdropdown.startchrome("chromemenu")
</script>

You can customize it further to your liking. Please read the details on Dynamic Drive regarding this script.

It's not that bad. I changed the CSS just a bit to match my pages' colors and didn't touch the original script file. 

If you'd like to see this page in action, please contact me by email. mhson1978@gmail.com

Oh yah, one note. If you customize the navigation this way, URL to pages will be a bit hard to manage. I've been looking into using Descriptive URL feature but its not working for me at the moment.
I've done some research on the Forum and some one DID say this:
You must have domain set up in order to use it.
I've actually asked my network admin to put in a CNAME for me. So if it works, I'll let you guys know.

Let me know if you have any questions. NetSuite, do you guys know when you'll add this as Part of NetSuite feature?

Thursday, June 9, 2011

IE Annoyance - "Do you want to Only show secure elements?"

We've MOVED!!!! www.codeboxllc.com/ksc

I got nothing against Internet Explorer but this is really annoying. Have you ever come across websites where you get system popup window asking you permission to display non-secure elements on secure website? going from IE 7 to 8, they changed the message of popup. With IE 7, it used to be something in the line of "Do you want to display both secure and non-secure elements?". With IE 8, they changed it to "Do ONLY want to display secure elements?" With IE 9, it now displays a notice message that looks like part of website at the bottom center.

Dear Microsoft, stop confusing people and start helping people!!!!

How does this apply to us NetSuite folks? You guys might already have fix for this on your webstores but I just recently found this as an issue.

If you are like me, you are most likely using small part or all elements of jQuery. You may also use external form to process customer registration data.If this is you, you may have come across this IE annoyance during your cross browser testing.

What does this error mean? Well, simply put, your URL is https:// but content of the page contains none https elements. Most likely it'll be reference to external image, javascript and css.

Solution? Tell your customer to read the message before clicking.

Better solution? Change reference to these elements to https.
Every time you upload a script or an image to NetSuite, you will notice that NetSuite provides you with several different URLs for your uploded items.

I just realized why they provide these. It's to help you avoid IE's confusing messages. =)

Go to Documents in your NetSuite account and drill down to folder you uploaded your item. Click on Edit to view details of that items you'll notice these different URLs.

Hope this helps... if not, hope I've given you something to laugh about.

Saturday, May 28, 2011

Alternate more efficient way to Debug Webstore Scriptable Cart

We've MOVED!!!! www.codeboxllc.com/ksc

Recently, I had a nice email conversation with Jason K. from NetSuite. He thought my workaround for debugging scriptable cart/checkout was very clever. It means alot coming from him. However, he actually came up with even better way of debugging scriptable cart/checkout. Jason, you are the MAN!

His method resolves the issue of eating away at script metering in my version of workaround. Using nlapiRequestURL() eats 10 governance from allowance and it causes issue during form testing. He also mentioned something very important as well. With v2011.1, NetSuite relaxed the rules on type of Sales Order form that can be used for scriptable cart/checkout. This means, you are not restricted to using External Sales Order. You can customize Standard Sales Order and use it for the scriptable cart.

Here is how you go about doing this: Thank you Jason K. for coming up with this workaround!

Step 1: Create custom sales order forms for both Invoice and CashSales from standard invoice sales order and standard cashsale sales order.
Setup > Customization > Transaction Forms
** Make sure you do NOT put anything under custom code tab for both forms!!!
After you create the two new forms, make a note of their Internal IDs. You will need them in step 2.

Step 2: Create alternate version of your scriptable cart script. Keep currently working version as your backup. You may need it.
At the top of every event functions, add following line of code:
if (nlapiGetFieldValue('customform') != '[InternalID of SO Invoice from Step 1]'
&&   nlapiGetFieldValue('customform') != 'InternalID of SO CashSale from Step 1') {
  return;
}
This ensures that script only fires for the sales order forms you are using on Webstore.
Make sure every time you want to print debugging message, you use nlapiLogExecution() call to do so.

Step 3: Create new "Client Script" file and deploy it for all Sales Order.
Creating new script file: Set > Customization > Script > New > Client Script
Don't for get to fill out all your event functions and attach any library scripts. Deploying this script for Sales order is up to your preference. I usually do "Save & Deploy".
When you are deploying your client script for sales order, make sure list of audience includes Customer Center and perhaps most obvious thing, make sure it Applies to Sales Order.

Step 4: Attach newly created Sales Order forms to your webstore
Setup > Web Site > Set up web site. 
Under the Setup Tab > Preferences section, select new invoice sales order for Scripting Template (Invoice) and new cash sale sales order for Scripting Template (Credit Card).

That's it! To view execution logs, you can to go Script or Script Deployment record and click Execution Log tab.

Hope this works out for you guys. Thank you again Jason K for this workaround!

Tuesday, May 24, 2011

Advanced Webstore Item templates

We've MOVED!!!! www.codeboxllc.com/ksc

I learned something cool last night. Do join me in celebrating my slow learning process of NetSuite.

Did you know you can set custom drill down webstore template at an individual item level?


Route I took to customizing look and feel of our webstore is to take a pre-designed template from NetSuite and modifying it. I can set default product drill down template for both Welcome and Product layouts.
For most folks, product drill down template doesn't have to be "Special", but for me, it had to be special. Especially when item options varies and you have to apply special validations against it.

If items in your webstore requires special attention for item detail page, definitely look into using this.

Try to abstract out different types of item detail page you'd need and group them together. When you create your drill down templates, it'll be based on these grouping.

You can gain access to creating different templates by going to Web Site Item/Category Templates page.
Setup > Web Site > Item/Category Templates


You can set individual drill down template per item by following these steps:

  1. List > Accounting > Items > Select the webstore item you wish to add custom drill down template
  2. Click on Store or Webstore tab. (This depends on the item you've selected)
  3. Next to "Item Drilldown Template", select your newly created template
  4. Save
It's a small things that makes me happy these days. This saved me from coding different javascript validation for each items with varying item options.



Thursday, May 19, 2011

Working with Scriptable Cart in NetSuite Webstore - Lessons Learned

We've MOVED!!!! www.codeboxllc.com/ksc

It's been a while since my last post. I have a good reason. I've been struggling with Scriptable Cart feature in NetSuite advanced Webstore. After close to 9 days of none stop work, I think I've finally have it working.

This is new feature NetSuite released and it's still in an infant stage yet very powerful when coded correctly.
First thing I struggled with the most was not being able to see scripts' behavior when executed from the Webstore. You can read about on "How to debug NetSuite Webstore Scriptable Cart".

This gave me some major insight as to how NetSuite Webstore processes each addition/subtraction of items in the cart.

I want to give shout out to Jason K. for providing massive assistance in getting my cart script to work properly!

Here are some things I've found out that could help you:
  1. You can get execution environment variable using nlapiGetContext().getEnvironment() call. I didn't think this was possible but using this in your cart script actually returns SANDBOX, BETA or PRODUCTION from webstore.
     This will be very handy if you have to switch item ID depending on the environments.

  2. nlapiCommitLineItem('item') Is a MUST Call if you want your recalc to correctly recalculate totals. I tried taking the easy way out by not calling commit. What a newb mistake that was.

  3. nlapiLookupField() call can not be used. Obviously right? Well, I made this mistake as well. You may have an instance where you need to create item list table to add pro grammatically. I highly recommend using JSON object to create your item look up table.

  4. User selected items will ALWAYS be at line number 1 of the cart. The order of items may change after you've been to check out summary page but when it's added to the cart by the user; not script, it'll always be on the first line of item list.

  5. Jason K's trick 1: nlapiSelectLineItem results in an error if there's uncommitted values in the item list. He recommended to commit all items before adding new.
    I especially had issues with this. My work around was to use nlapiInsertLineItem with nlapiSetCurrentLinetItemValue method.

  6. Not sure if this will apply to everyone but IF you end up getting NetSuite Script Notice page during your execution of cart script or you end up getting Webstore maint. screen, it usually means there is an error in your script. For me, it was infinite loop issue. If you see your form re-initializing, it usually indicates error.

  7. Jason K's trick 2: Using global variable in the cart script sometimes fails. The workaround is to create custom body field on your form and use that as temporary global field that you set and get using nlapiGetFieldValue() call.
  8. Jason K's trick 3: When doing extra commit, always check for valid item in the current row. 
Some quick sample code from Jason K on safeSelectLine and safeSelectNewLine

** notEmpty is a custom function which simply checks to see if passed in value is null or empty string

safeSelectNewLine function:
function safeSelectNewLineItem() {
  if (notEmpty(nlapiGetCurrentLineItemValue('item','item'))) {
    nlapiCommitLineItem('item');
  }
  nlapiSelectNewLineItem('item');
}
safeSelectLine function:
function safeSelectLineItem(itemLine) {
  if (notEmpty(nlapiGetCurrentLineItemValue('item','item'))) {
    nlapiCommitLineItem('item');
  }
  nlapiSelectLineItem('item', itemLine);
}
Most important lesson I've learned is that cart script behaves differently in webstore. Do test your code on the external form but be extra careful not to fully trust the result. When testing on webstore, keep close eye on your log execution files. If you ever see page init more than once, you know you have an error somewhere.

As I mentioned before on my previous post, turning on logging on webstore will slow down your cart since it's calling to your external suitelet so keep that in mind as well. 

Hope this helps you. Let me know if you get stuck. I'll try my best to help you out.

Saturday, May 14, 2011

How to debug Netsuite Webstore Scriptable Cart

We've MOVED!!!! www.codeboxllc.com/ksc


Notice:
Blogspot had issues with their server and post I originally wrote got deleted. I do apologize for missing link:

Important Update on this Post: 5/17/2011:
nlapiRequestURL() eats up API Governance meter by 10 points. Testing on External Form, if you have this turned on, you only have 1000 limit. On Webstore, you seem to have 2147483647. Don't ask me where that number came from.

So, Here I go again. How DO you debug scriptable cart executing on webstore? The script itself is attached to the External Sales Order form you create which implies is client level script. You can't use Firebug to step through it either.So how do you debug when your script is not returning the results you want?

I began using this workaround and it has helped me alot.
Workaround: Create Suitelet (Available without Login) to track printing of debug messages and call it using nlapiRequestURL() from your scriptable cart script.

Write Suitelet Script: Save as "sl_writelog.js" and push out to Netsuite 
** Please note, for simplicity, I've written my script to use GET event.
function slExecLog(request, response){
  if (request.getMethod() == 'GET') {
    var log = filterUserInput(request.getParameter('log'));
    var title=filterUserInput(request.getParameter('title'));
    writeLog('DEBUG',title,log);
    response.write('called back');
  }
}
Deploy your script:
  1. Login to Netsuite and go to Setup > Customization > Scripts > Click New
  2. Select Suitelet as script type
  3. Provide Name and ID for this script.
  4. Under Scripts tab, select "sl_writelog.js" for Script File and "slExecLog" as Function
  5. Select "Save and Deploy" option.
  6. Provide Name and ID for this script deployment
  7. Check "Available Without Login" 
  8. Select GET Request as Event Type.
    If you choose to use Post, you should change your script to check for POST and also select POST Request as Event Type
  9. Under Audience tab, select "All Roles"
  10. Save
Once you've deployed your script, copy the External URL for this deployment. According to NetSuite documentation, nlapiRequestURL() does NOT send User Session information. 

Link to your Suitelet from Scriptable cart script:
Open your scriptable cart script and create a function which will call your suitelet. This is how I did it:
Please note that anything enclosed in [ and ] is to be replaced by your code including the brackets.
function wslog(_txt) {
  if (!_txt) {
    return;
  }
  var loginUrl = '[External URL for your Suitelet]&title=[Value of title]&log='+_txt;
  if (wsdebug) {
    nlapiRequestURL(loginUrl, null, null);
    return;
  }else{
    alert(_txt);
  }
}
You will notice above that I check for wsdebug value. This is global boolean value I created so that I can turn on/off calling of my debug suitelet.
When I'm testing on the form, I set this value to false so that I can see the alert messages. Testing/deployment on webstore, I set this value to true.
Check your debug messages:
Once everything is doen, go to your Webstore and add items to your cart so that your scriptable cart script will fire.
To check the log messages, open your Suitelet script record and click on Execution Log.


Monday, May 9, 2011

NetSuite - Item Options on Webstore

We've MOVED!!!! www.codeboxllc.com/ksc

I've been over working my brain on trying to dynamically set item options through Scriptable Checkout on the Webstore.

I've search long and hard on NetSuite forum and from what everyone says, it should work. In fact, I've tested out my code on External Sales Order form and It DOES Work. However, when you actually walk through the process of purchasing an item in Webstore, script never fires.

Here is what I did. I believe you need Advanced Webstore Capability

  1. Under Setup > Customization > Transaction Forms, Create two new Sales Order (External) forms; one for cash sales and one for invoices.
  2. Attached script I want to use to each of the external forms I created.
  3. Under Setup > Web Site > Set up Web site > Setup Tab, I set up the following:
    Scriptable Cart and Checkout: Checked
    Scripting Template (Credit Card): Points to Sales Order (External) Cash Sales form
    Scripting Template (Invoice): Points to Sales Order (External) Invoice form
One of the best tip given by NetSuite developer was this:
"Aways test your external form internally before you begin testing on Web Store"
I followed his advice and began testing my code internally. You can do this by going to Setup > Customization > Transaction Forms, and click on one of the external form link; not the edit link but the form name.  This will bring up empty form.

All your function you defined will fire as you fill in the form. By testing the form internally, I saw that Item Options were being set on the item line item.  HOWEVER, same code, same form doesn't behave the same when executed from Web Store.

I'm really hoping SOMEONE FROM NetSuite WILL ANSWER MY QUESTION!!!!!

The Workaround:
If you guys every need to accomplish something like this, my suggestion is to handle it through User Event Script.
I personally set up my User Event to fire on After Submit.

You create your server-side User Event script and deploy it to Sales Order record. You can code your script to ONLY fire when Sales Order is from your webstore. You can do this by checking for "leadsource" field value.

At this point, you gain access to all server-side script including the ability to manipulate the item list.

Some key points to remember:

  1. Any manipulation you do, make sure it doesn't affect what your customer has already provided. Newly Altered version of Sales Order will be emailed to customer. ** If you have it set up that way
  2. NetSuite support indicated that they fixed a bug with Rev. Rec. Schedule not pulling down from Item record. It is STILL BROKEN FOR US! You can get around it by using this script.
If Anyone has a work around for this issue, PLEASE PLEASE message me. I'd love to hear how you got it fixed!

Friday, May 6, 2011

Separating Name field to First and Last Name in NetSuite Webstore

We've MOVED!!!! www.codeboxllc.com/ksc

NetSuite, I have bones to pick with you! Why would you just put Name field on e-commerce registration form? WHY???!?!?!?!

Well, until they put in a fix for it, I do have a work around for those who wish to use it.
If you have already customized your webstore, most likely you have script files you are placing on the header of your web site theme.

For this purpose, create a new JavaScript file. For now create a function called checkPage().
function checkPage() {
}
 Save and load it to your live hosting folder and place a reference to it at the header of your website theme.

Append functions to body tag:
Open your theme by going to Setup > Website > Theme > [Your Theme]
Under General tab, please reference to your new javascript file on "Addition to <head>".
Also under general tab, append your new function call next to "page_init()".

Your body tags' onload call should look like this: onload="page_init(); checkPage();"

Doing this will call your checkPage() every time different sections of your webstore is loaded.

Finding field info:
The name text box should have id and name of "name".

Sudo Coding:
What we wanna do is this:
1. Find name text box and do the following:
- Change type from text to hidden
- Clear onfocus and onchange. This may not be necessary
2. Create first name text box element
- Add id of fname (your choice)
3. Create last name text box element
- Add id of lname(your choice)
4. Place the two elements where original name text box was
5. Write validation script to check for missing values for the two.
6. IF validation passes, set the value of now HIDDEN name field with first and last name provided. (VERY IMPORTANT STEP)

Lets add the meat to our script:
I found that registration page has specific form called "newcust". Checking for existence of this form will be our queue to begin our modification process.
Oh BTW, if you know jQuery, more power to ya. It'll be much easier

Here is the code:

function checkPage() {
//find out if registration form exists
var regform = document.forms['newcust'];
if (regform !=null) {
var ntx = regform.name;
ntx.setAttribute('type','hidden');
ntx.onfocus='';
ntx.onchange='';
//get span node that wraps name text box
var cellspan = ntx.parentNode;


var fnamebox = document.createElement('input');
var txtNode = document.createTextNode(' ');
var lnamebox = document.createElement('input');
fnamebox.setAttribute('type','text');
fnamebox.setAttribute('id','fname');
fnamebox.setAttribute('onfocus',"txtChange('fname','First Name');");
fnamebox.setAttribute('onblur',"txtChange('fname','First Name');");
fnamebox.value='First Name';
lnamebox.setAttribute('type','text');
lnamebox.setAttribute('id','lname');
lnamebox.value='Last Name';
lnamebox.setAttribute('onfocus',"txtChange('lname','Last Name');");
lnamebox.setAttribute('onblur',"txtChange('lname','Last Name');");
cellspan.appendChild(fnamebox);
cellspan.appendChild(txtNode);
cellspan.appendChild(lnamebox);
}
}


//just helper function to switch between default values.
function txtChange(_id, _text) {
var el = document.getElementById(_id);
if (el && el.value == _text) {
el.value='';
}else if(el && el.value=='') {
el.value=_text;
}
}

This should do it. You just need to now add validation script (Sudo code step 5 & 6) for onsubmit.
If validtion passes, you can do something like this.

var fname=document.getElementById('fname').value;
var lname=document.getElementById('lname').value;
document.getElementById('name').value = fname+' '+lname;

This isn't the only way you can do this. I just wanted to show you guys that it IS possible to do this.