Suitecoder just got more awesome

personal

New version of Suite Coder has been released. Yay!!

Some salient features of this release are

  • New UI with better support for small screens.
  • Manage personal files. These files are not connected to any Netsuite account so you can access them anytime without Netsuite credentials
  • Unicode support. Now you can save files having unicode characters like © or ¥
  • Several minor bug fixes
Tagged with: , , , ,
Posted in Google App Engine, Programming & Development, Python

Setup Selenium Web driver on WAMP environment

Recently I configured Selenium web driver on multiple systems having WAMP environment. There’s an excellent tutorial for it here. However I had to do some additional configurations mentioned below.

Step 2.1 mentioned there is a bit tricky, you may have to try these

pear clear-cache

pear install -a -f phpunit/PHPUnit

Source: http://stackoverflow.com/questions/6272264/windows-installing-phpunit-via-pear-installing-phpunit-via-pear

pear install –force phpunit/PHPUnit_Selenium

Source: http://stackoverflow.com/questions/8495839/phpunit-not-recognizing-curl-extension-cant-install-selenium-test

Also make sure that cURL is working. You may have to replace your curl extension file

http://stackoverflow.com/questions/10939248/php-curl-not-working-wamp-on-windows-7-64-bit

Also WAMP contains multiple php.ini files

  1. /wamp/bin/php/php5.x.x
  2. /wamp/bin/apache/apache2.x.x/bin

Make sure to enable cURL in both the files so that PHP CLI picks the cURL extension

Integrate Web Driver

Selenium Webdriver doesn’t support PHP. However there are several third party implementations. I prefer https://github.com/facebook/php-webdriver. Download the repo and copy the lib folder in your tests folder. Here’s a sample file that you can use to verify your installation

<?php

require_once('lib/__init__.php');

class First extends PHPUnit_Framework_TestCase {

protected function setUp() {
$host = 'http://localhost:4444/wd/hub'; // this is the default
$capabilities = array(WebDriverCapabilityType::BROWSER_NAME => 'firefox');
$this->driver = RemoteWebDriver::create($host, $capabilities, 1000);
}

public function testLogin(){

$this->driver->get('http://localhost/mysite/');

}
?>

Run command “phpunit first.php First”. This would open a firefox window and navigate to http://localhost/mysite/.

Extend the script using both the Selenium webdriver API and PHP Unit assertions.

Tagged with: , , , , , ,
Posted in PHP, Programming & Development

AWS PHP SDK logging using Guzzle

Recently I’ve been working on AWS PHP SDK. I found out that there is a simple code snippet to enable wire logging in the API

use Guzzle\Plugin\Log\LogPlugin;

// Create an Amazon S3 client
$s3Client = S3Client::factory();

// Add a debug log plugin
$s3Client->addSubscriber(LogPlugin::getDebugPlugin());

However according to FAQs on the AWS docs site, we have to create our own plugin for logging in a file. I had a look at the code and found that you just have to provide the 2nd parameter to getDebugPlugin function and it wil start logging in the file

// Create an Amazon S3 client
$s3Client = S3Client::factory();

$logPlugin = LogPlugin::getDebugPlugin(TRUE,
  //Don't provide this parameter to show the log in PHP output
  fopen(APPPATH . 'logs/wire.log', 'a')
 );
$client->addSubscriber($logPlugin);

Later if you want to stop the logging you have to use the following snippet.

//Remove this log plugin to the client
 $client->getEventDispatcher()->removeSubscriber($logPlugin);
Tagged with: , , , ,
Posted in Amazon, Programming & Development

Using GetSelectValue in Netsuite PHP Toolkit

Nowadays I am working on porting one of my Suite Talk projects to the newer version of Netsuite PHP Toolkit.

In my previous version I use the getSelectValue operation using following code.

$myNSClient->getSelectValue(
new nsComplexObject(
    "GetSelectValueFieldDescription",
        array('recordType' => $record,'field' => $field)
    )
);

I converted the code accordingly but the new toolkit was returning this error

No such operation ‘getSelectValue’

After some debugging I found that pageIndex is now a Required Attribute, so I had to add the following line

$request->pageIndex = 0;

Here’s the complete working code

$obj = new GetSelectValueFieldDescription();
$obj->recordType = $recordType;
$obj->field = $field;

$request = new getSelectValueRequest();
$request->fieldDescription = $obj;
$request->pageIndex = 0;

$getResponse = $service->getSelectValue($request);
Posted in Netsuite, Programming & Development

Integrating Netsuite PHP Toolkit in Yii

  • Download PHP Toolkit from here.
  • Copy the PHP Toolkit from the zip archive into protected/vendors folder
  • Make the Config variables global in NSconfig.php . i.e. add following code in beginning of the file
    global $nsendpoint;
    global $nshost;
    global $nsemail;
    global $nspassword;
    global $nsrole;
    global $nsaccount;
    
  • Create a new file in protected/models and name it as NSEntity.php. Below are its contents
    class NSEntity {
    
    	private $service;
    
    	public function __construct() {
    
    		Yii::$enableIncludePath = false;
    		Yii::import('application.vendors.PHPToolkit.NetSuiteService', true);
    
    		$this->service = new NetSuiteService();
    		if (!Yii::app()->session['nshost']) {
    			global $nshost,$nsaccount;
    
    			$params = new GetDataCenterUrlsRequest();
    			$params->account = $nsaccount;
    			$response = $this->service->getDataCenterUrls($params);
    			Yii::app()->session['nshost'] = $response->getDataCenterUrlsResult->dataCenterUrls->webservicesDomain;
    
    			$nshost = Yii::app()->session['nshost'];
    
    		}
    	}
    
    	function search($searchRequest, $searchId, $pageNum) {
    
    		$this->service->setSearchPreferences(false, 10);
    
    		if ($searchId && $pageNum) {
    			$req = new SearchMoreWithIdRequest();
    			$req->searchId = $searchId;
    			$req->pageIndex = $pageNum;
    			$searchResponse = $this->service->searchMoreWithId($req);
    		} else {
    			$searchResponse = $this->service->search($searchRequest);
    		}
    
    		$response = array();
    		if (!$searchResponse->searchResult->status->isSuccess) {
    			$response['status'] = FALSE;
    			$response['error'] = '';
    		} else {
    			$response['status'] = TRUE;
    			$response['recordCount'] = $searchResponse->searchResult->totalRecords;
    			$response['pageCount'] = $searchResponse->searchResult->totalPages;
    			$response['searchId'] = $searchResponse->searchResult->searchId;
    			$response['records'] = array();
    			foreach ($searchResponse->searchResult->recordList->record as $record) {
    
    				$response['records'][] = $this->map($record);
    			}
    		}
    		return $response;
    	}
    
    	function load($id, $type) {
    
    		if ($id) {
    			$request = new GetRequest();
    
    			$request->baseRef = new RecordRef();
    			$request->baseRef->type = $type;
    			$request->baseRef->internalId = $id;
    			$getResponse = $this->service->get($request);
    
    			if ($getResponse && $getResponse->readResponse->status->isSuccess) {
    				return array('status' => TRUE, 'record' => $this->map($getResponse->readResponse->record));
    			} else {
    
    				return array('status' => FALSE, 'msg' => $getResponse->readResponse->status->statusDetail[0]->message);
    			}
    		}
    	}
    
    	function map($record) {
    		return $record;
    	}
    
    	function getCustomField($record, $fieldName) {
    		foreach ($record->customFieldList->customField as $field)
    			if ($field->internalId == $fieldName)
    				return $field->value;
    		return '';
    	}
    
    	function update($record) {
    		$request = new UpdateRequest();
    		$request->record = $record;
    		$updateResponse = $this->service->update($request);
    		if ($updateResponse->writeResponse->status->isSuccess) {
    			return array('status' => TRUE);
    		} else {
    			return array('status' => FALSE, 'msg' => $updateResponse->writeResponse->status->statusDetail[0]->message);
    		}
    	}
    
    }
    
  • Most of the magic lies in the constructor where Netsuite Service is intialized and and we get the dynamic Date Center URL, once for a session.
  • NSEntity.php serves as the base class for any entity that you want to use in the app. For e.g. here is a class for Items.
    Yii::import('application.models.NSEntity');
    class Item extends NSEntity {
    
    	public $record;
    
    	public function __construct() {
    		parent::__construct();
    	}
    
    	function map($record) {
    		$thumb = $this->getCustomField($record, 'custitem_internalimagethumb');
    		if ($thumb && $thumb->internalId)
    			$thumb = $thumb->internalId;
    
    		return array(
    			'type' => lcfirst(get_class($record))
    			, 'internal_id' => $record->internalId
    			, 'item_id' => $record->itemId
    			, 'image_thumb' => $thumb
    		);
    	}
    
    	function createSearchRequest($searchTerm) {
    		$itemIdSearchField = new SearchStringField();
    		$itemIdSearchField->operator = "contains";
    		$itemIdSearchField->searchValue = $searchTerm;
    
    		$search = new ItemSearchBasic();
    		$search->itemId = $itemIdSearchField;
    
    		$request = new SearchRequest();
    		$request->searchRecord = $search;
    		return $request;
    	}
    
    }
    
Tagged with: ,
Posted in Computer And Internet, Netsuite, Programming & Development, Uncategorized

2012 in review

The WordPress.com stats helper monkeys prepared a 2012 annual report for this blog.

Here’s an excerpt:

600 people reached the top of Mt. Everest in 2012. This blog got about 7,800 views in 2012. If every person who reached the top of Mt. Everest viewed this blog, it would have taken 13 years to get that many views.

Click here to see the complete report.

Posted in Uncategorized

Netsuite PHP Toolkit Documentation

Recently Netsuite has uploaded the Netsuite PHP Toolkit version 2012_2. This version is very mature compared to its predecessors.

Now the code is distributed in different classes that makes it possible for IDEs and Documentation generators to parse it. So I decided to generate the documentation and upload it so that anyone can view it. So here the link

http://tellsaqib.github.com/NSPHP-Doc/

Hope it helps

Tagged with: , , ,
Posted in Netsuite, Programming & Development

New Data Centers for Netsuite Accounts

As of September, 2012 Netsuite has started hosting different accounts to different data centers. That means if you are developing SuitTalk Apps for multiple accounts then you have to make sure that you are using correct URL for these.

These two articles can help you make necessary changes in your code

https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteFlex/SuiteScript/SSScriptTypes_UsingtheRESTrolesServicetoReturnUserAccountRoleandDomain.html

https://system.netsuite.com/help/helpcenter/en_US/Output/Help/SuiteFlex/WebServices/STP_getDataCenterUrls.html

Although Netsuite PHP Toolkit 2012_2 has built-in methods to get the URLs but if you are not using that then below is the Sample PHP class that can be used to access Netsuite Rest Roles Service

class AccountsGrabber {

private $curl;

public function __construct($email, $password) {
 $this->curl = curl_init();
 curl_setopt($this->curl, CURLOPT_HTTPHEADER, array(
 'Authorization: NLAuth nlauth_email=' . $email . ', nlauth_signature=' . $password
 ));
 }

public function __destruct() {
 curl_close($this->curl);
 }

public function getAccounts() {
 $url = 'https://system.netsuite.com/rest/roles';
 curl_setopt($this->curl, CURLOPT_URL, $url);
 curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE);
 $result = curl_exec($this->curl);

return json_decode($result);
 }
 }
Tagged with:
Posted in Netsuite, Programming & Development

New features added to Suitecoder

If there were an Olympic coding event, I have no doubt that I would be representing my country in it :)

Jokes apart, lately I had been working to add certain useful features to suitecoder and today these features have been made live.  I really hope that these features would make life easier for all the suite-coders around.

Below is list of new features added

File History

Many suitecoder users asked for SVN feature so that they can view the file Revisions.  So now whenever you save your file using suitecoder a copy is stored that you can view/compare with your current version.

File History (SVN) Feature

Enhanced Intellisense

Intellisense Example 1

Intellisense Example 2

Intellisense is enhanced so that you will be having a minimum need to consult to Netsuite Documentation. Standard parameters that are provided to Netsuite are now a part of intellisense.

Other features

  • Now pressing Control-S within the editor saves the file. No need to click the Save button every time.
  • Each revision history can be labelled so that you can easily find revisions.
  • Latest version of Code mirror is used.

You can view the complete list of features here.

Tagged with: ,
Posted in Computer And Internet, Netsuite, Programming & Development

Netsuite API Explorer

Good things come in small packages. Netsuite API Explorer is one of those good things (I hope so :) )

Being a part of Suite-Coder, API Explorer helps Netsuite Developers to get used to Netsuite API.  As the Netsuite API is very extensive so you may use it as a quick reference guide. It will really help you in the developing Suite scripts.

Don’t believe me? Check yourself https://suitecoder.appspot.com/static/api.html

Tagged with: , ,
Posted in Netsuite, Programming & Development
Follow

Get every new post delivered to your Inbox.

Join 25 other followers