:::: MENU ::::

2 ½ day workweek – Coping with Weekends in the Middle East

The Problem

As a part of my work, I’m in direct contact with accounts in Turkey and a number of countries in the Middle East. Being located in Turkey means that I “enjoy” Saturdays and Sundays as my days off, but in UAE, for example, Fridays and Saturdays are holidays. To make the matters more complicated, Iranian weekend is on Thursdays and Fridays, limiting the workable days between these countries to just 3 days, from Monday to Wednesday. Add to it about 2 hours of timezone difference and you’ll end up with almost 2 ½ days of common workweek, especially if you need to work with banks and government offices.

Band-aid Solutions; More Problems

To mitigate this issue people doing business in this part of the world often resort to the following:

  • sacrificing their own downtime to cope with conflicting weekends
  • using alternative channels of communication, such as:
    • personal mobile numbers and email addresses, and
    • messaging apps and social networks such as WhatsApp and Viber.

This organic and uncontrolled way of communication, causes interesting yet predictable dynamics to emerge around the issue of 2 ½ day workweek:

  • People feel the need to respond to emails/calls during weekends based on their organizational hierarchy. To my experience higher ranking staff tend to respond quicker as they often have more at stake. Others usually take the “Not my problem” route and wait until they go to work, which could be a Saturday, Sunday, or a Monday based on where they live.
  • Reciprocity is rare. If a team member feels the need to respond promptly and not stall work, their sacrifice is unlikely to be rewarded with quick response from the peers.
  • Employers hardly appreciate the staff who sacrifice their much deserved downtime and often consider it employees’ duty to be responsive round-the-clock.
  • Families of employees do not appreciate such (often routine) sacrifices.
  • Gradually chronic side-effects come to surface, such as:
    • lower efficiency of directly or indirectly impacted business processes
    • employee burnout and attrition caused by disappearing work-life balance
    • increased information chaos due to widened and unmanaged communication channels, and
    • increased business risk caused by all of the above.

Seeking a Practical Solution

We can’t change the system. We can only hope that those few countries with non Saturday-Sunday weekends change it for the sake of efficiency and sanity. But that itself means years of planning at government level and millions of dollars spent on something that may or may not work.

Given the current state of constraints, our team has adopted a number of easy and practical ways to lower the impacts of the 2 ½ day workweek:

  • Reciprocity – Employees who communicate internationally must respect their counterparts’ extra work. If your peer in the other company is responsive to your communication, return the favour by being responsive to their requests.
  • Timezone Awareness – You can’t expect everybody to respond to your calls and emails outside their working hours. If you send an urgent request at 5:45pm (destination time) chances are you won’t get the response you were hoping for on time.
    An easy way to mitigate this is to add all the timezones you are working with to a world clock app on your smartphone and check the destination time in advance. After some time your brain will work with different timezones effortlessly.
  • Delegation – Plan realistic and rotating shifts for employees who are in constant contact with international offices. Sharing tasks and alternating weekends, even among executives, could prove quite useful.
  • Collaboration – Practical collaboration often seems so unattainable, but with proper time management, right attitude, and the right tools international teams can work seamlessly.
  • Information Management – Have strong information and communication policies in place. You don’t want employees to use personal emails for work-related communications. Provide them with business-only smartphones if necessary and govern every shred of information transmitted.
  • Reward Programs – Make sure your employees know that you appreciate their extra efforts. Occasional time-offs and little promotions go a long way.
  • Balance – Employers should be cognizant of the staff who overwork and are in danger of a burnout. Not paying attention to work-life balance may cause irreversible damages to both business and personal lives.
  • Change Management – Employees are naturally used to 5-day workweeks. You can’t expect to throw a new set of rules at your employees and they get onboard immediately. It takes time for everybody to tweak their routine. Having a plan and being patient and consistent during any transition is the key to achieve goals.

None of the above are new concepts or disruptive ideas. The point is to put these well-known (and less utilized) methods in practice while coaching the team and yourself to overcome the challenges of 2 ½ day workweek.


Importing data from FTP server into Zoho Creator

Zoho Creator has grown to be a great cloud-based app creation platform. You can build simple apps in the matter of hours or have complex solutions up and running much quicker than a from-scratch project.

Manipulating data is a core capability of (Zoho) Creator . There is a rich toolset of UI elements, business logic components, and reporting tools to make your life easier. If you need more functionality you can always create custom functions and behaviours using the powerful Deluge scripting language. To take it even further there is a rather capable REST API to connect your app to the outside world.

In this post I’ll show you how to import data from an FTP server into a Creator app using a Deluge function and a little middleware.

Note: I assume that you are familiar with Creator and Deluge. We will also get some help from a PHP script, so some PHP knowledge is helpful too, but not necessary. You can use the code in this tutorial without changing anything other than the FTP url and account.

Problem

You have created a sales management app that keeps track of sales. The app is working great and users are able to place orders and record each transaction. There is, however, a small bottleneck.

The company uses a legacy inventory management system to keep track of all the goods and material available to sell. The only way this system can communicate with the outside world is via FTP.

Every morning at 1:00AM EST the legacy system exports a list of all products and available stock to a CSV file and places it on company’s FTP server. Other software systems in the organization consume that file by importing it manually every morning.

Your sales management app is no exception either and needs to import this CSV file every morning to have the updated product list available.

Solution

Deluge offers getURL(), a function that allows apps to retrieve data from external sources using HTTP protocol. In our example, this data is CSV, but it could very well be JSON, or plain text.

Since getURL() can only send HTTP requests, connecting to a secure (password protected) FTP server is not directly possible. For this purpose you need to either place the remote file(s) on a non-secure site, or use a middleware to extract data for you. Placing private company data in a non-secure location is never recommended. So the only solution is to create a small middleware that takes care of extracting data from the FTP server and sends it back to the Creator app. Now, a middleware can do way more than that, but for the purpose of our tutorial all it needs to do is to connect to the FTP server, load the CSV file, and send its contents back via a HTTP response.

Step 1 – The Data File

Before everything make sure you have the demo CSV file, inventory.csv, ready and uploaded to the FTP server. A sample file is shown below:

Step 2 – The Middleware

First, we need to create the middleware and deploy it on a web server. Note that you can’t store this in Creator and you will need to have access to a web server, such as where your company site is hosted. For this purpose we are going to use the good old PHP because it is easy to code and maintain and works on pretty much any web server.

On your local machine create a PHP file, ftp.php, and paste the code below in it. Make sure you change the values in lines 5-7 and line 9 to reflect your server settings.

Now upload ftp.php to the web server. Test if the script works properly. Simply open the PHP file in the browser. It should return the contents of the CSV file and display it in the browser similar to the following figure.

Note: Depending on the version of PHP on your web server, there is a memory limit to how big of a CSV file you can load up in one go. If you need to access massive CSV files, you may need to change the code in the middleware.

Step 3 – The Creator App

For our little demo, we are going to create a simple app featuring 2 forms:

  1. Products – This form contains the latest products available in stock. Our deluge script will pull the inventory every morning and update the list of products in this form.
  2. Add Order – This form allows users to place new orders. It collects order, customer, and products information. A list of available products will be populated from Products to make sure employees are selling what is in stock.

I assume you know how to create forms in Creator, but to make sure you have all the necessary fields for the deluge function to work, here is how the Products form should look like:

import_ftp_csv_zoho_creator_03

Now our app is ready to receive data. By creating a form, the data storage mechanism behind it is also created. I’m reluctant to use the term table here because unlike other environments, in Creator each form represents both the visual and the data layer of each entity.

Step 4 – The Deluge Function

To create a function in Creator follow these steps:
import_ftp_csv_zoho_creator_02

  1. Click on Workflow button on the left sidebar.
  2. Select Functions tab.
  3. Select Write script / Copy same function button.
  4. Type in the code below in the text area.
  5. Click Create the Function.

The code above simply sends a request to ftp.php and loads the results, i.e. the content of the CSV file, into variable csv. Then it displays the loaded data showing that everything works as intended.

Go ahead and click on Execute Script and see the results. The content of inventory.csv, which you have placed on the FTP server earlier will be displayed in a dialog box. You have successfully imported data from a remote FTP server into Zoho Creator, but there still remains a very import step: Storing imported data in Products form.

Step 5 – Storing Imported Information

The next step is to parse the CSV data and insert each row into Products.

Update importInventory() function with the following code:

The code is self-explanatory, but let’s revisit a few points here:

  • Line 7: To break the CSV data and put each line into a Deluge list item, “\n” (Lf) is used as a separation indicator. Sometimes CSV lines are not broken with “\n”. If you experience an issue when importing try using “\r” (Cr) instead.
  • Line 10-13: If you skip emptying Products before each import, new data will be appended to the existing list of products, which is not what we want. In other scenarios appending may make perfect sense and you can omit these lines.
  • Line 34-41: The actual insertion of a record into Products happen here. So make sure you are finished with data processing or cleanup before this point.

Save the changes by clicking Save Script and execute. Hopefully you will get a message that script executed successfully.

Now run the application and open Products Report view (created automatically). Newly imported rows should be displayed in the report.

import_ftp_csv_zoho_creator_04

Step 6 – Scheduling the Imports

One last thing remaining is to make sure this magical script runs every morning and imports an updated list of products. Creator offers a convenient scheduler to help automate various processes.

To schedule importing products on daily basis, follow these steps:

  1. Select Schedules tab. You will see 3 different types of schedules available.
  2. Create a custom schedule by clicking the Create button in the Custom Schedule box.import_ftp_csv_zoho_creator_05
  3. Under When to do? tab fill in the boxes as shown below and then click Next.import_ftp_csv_zoho_creator_06
  4. Under What to do? tab enter the function name we want to run, i.e. importInventory(), save the changes, and click Execute Now to ensure everything works.import_ftp_csv_zoho_creator_07

That is it. Creator will run the importInventory() function every morning at 2:00 AM EST and import the latest inventory list into Products.

Summary

Congratulations! You have just created a solution for one of the common challenges of today’s database apps in a few hours, thanks to Zoho Creator. By getting a little help from a simple middleware written in PHP we were able to access information on a secured FTP server. For HTTP requests (common with JSON and XML data sources) you don’t need a middleware and you can pretty much do all the work from within Creator. This means one less piece of software to maintain and that is always good news.

If you know a better way to import data into Creator, or an improvement to the current method, please share it in the comments.


Bulk exporting Word documents to other formats with JavaScript

JavaScript is hot commodity for server and client side web development. But when it comes to command line programming it is unlikely to ditch the likes of Python and Ruby for JavaScript.

I don’t have the luxury of picking my toolset at work. I’m a business consultant with no access to anything beyond the essential enterprise software. Heck, I don’t even have access to PowerShell. All I have left with is JavaScript. Life is fun.

I assume that I’m not the only one facing this challenge, so it may be worth sharing how I do some basic automation at work using JavaScript.

Problem

The team needed to convert a big number (200+) of Word documents saved in different formats into a single format, DOTX to be specific.

Assumptions

You have access to a Windows machine with Microsoft Office 2010 installed.

Solution

  1. Open up a text editor, paste the code in Listing 1, and save the file as bulk_word_exporter.js.
  2. Set the value of sourcePath (line 10) to the folder containing the source files. Use double backslash to separate the folders.
    In my example different file types (DOC, DOCX, DOT, etc.) are stored in different source folders and that’s why extension is added to the sourcePath. Feel free to change this.
  3. Set the value of destPath (line 11) to the folder where you want the exported files to be saved. Create the folder if it doesn’t exist.
  4. open command line and run the script:
    CScript.exe bulk_word_exporter.js

Listing 1

alert = function(s) { WScript.Echo(s) }

var fso,
   folder,
	wordDoc,
	wordApp, 
	extension = 'DOT',
	fileFormat = 1, //see http://msdn.microsoft.com/en-us/library/office/ff839952.aspx
	sourcePath = "\\SOURCE\\PATH\\" + extension + "\\",
	destPath = "\\DESTINATION\\PATH\\";

try {
	fso = new ActiveXObject("Scripting.FileSystemObject");

	wordApp = new ActiveXObject("Word.Application");
	wordApp.Visible = false;

	folder = fso.GetFolder(sourcePath); 
	files = new Enumerator(folder.files);
	
   alert("Preparing ...");
	
   var fileURI, fileName;
	for(var files = new Enumerator(folder.files); !files.atEnd(); files.moveNext()) {
		fileURI = '' + files.item();
		fileName = fileURI.substr(fileURI.lastIndexOf("\\") + 1, fileURI.length - 
            fileURI.lastIndexOf("\\") -  (fileURI.length - fileURI.lastIndexOf(".") + 1));
		
      alert("exporting '" + fileName + "'...");
		
      wordDoc = wordApp.Documents.open(fileURI);
		
      alert("opened '" + fileName + "'...");
		
      wordDoc.SaveAs(destPath + fileName + "." + extension, fileFormat);
		wordDoc.close();
		
      alert("exported '" + fileName + "' to " + extension);
	}

	alert("\n\nDone!\n");

} catch (error) {
	alert(serialize(error));
} finally {
	//close handles and cleanup the memory
	fso = null;
	if (wordDoc) {
		wordDoc.Close(0);
	}
	if (wordApp) {
		wordApp.Quit();
	}
	wordDoc = null;
	wordApp = null;
	fso = null;
}

/* serialize function, thanks to http://blog.stchur.com/2007/04/06/serializing-objects-in-javascript/ */
function serialize(_obj)
{
   // Let Gecko browsers do this the easy way
   if (typeof _obj.toSource !== 'undefined' && typeof _obj.callee === 'undefined')
   {
      return _obj.toSource();
   }

   // Other browsers must do it the hard way
   switch (typeof _obj)
   {
      // numbers, booleans, and functions are trivial:
      // just return the object itself since its default .toString()
      // gives us exactly what we want
      case 'number':
      case 'boolean':
      case 'function':
         return _obj;
         break;

      // for JSON format, strings need to be wrapped in quotes
      case 'string':
         return '\'' + _obj + '\'';
         break;

      case 'object':
         var str;
         if (_obj.constructor === Array || typeof _obj.callee !== 'undefined')
         {
            str = '[';
            var i, len = _obj.length;
            for (i = 0; i < len-1; i++) { str += serialize(_obj[i]) + ','; }
            str += serialize(_obj[i]) + ']';
         }
         else
         {
            str = '{';
            var key;
            for (key in _obj) { str += key + ':' + serialize(_obj[key]) + ','; }
            str = str.replace(/\,$/, '') + '}';
         }
         return str;
         break;

      default:
         return 'UNKNOWN';
         break;
   }
}

This code utilizes Scripting.FileSystemObject library to access the file system:
13. fso = new ActiveXObject("Scripting.FileSystemObject");

It also uses Word.Application for opening and saving Word documents:
15. wordApp = new ActiveXObject("Word.Application");

Note: You can refactor and move the whole extension setting part to the command line arguments. That would be more elegant.

Bonus

Set extension to ‘PDF’ (line 7) and fileFormat (line 8) to 17  and run the code. It will bulk export a batch of Word documents to PDFs. This could be a life saver if you deal with managing information and records.

Other Tools of the Trade

Don’t forget about MS-Excel and MS-Access when you;re working on more serious automation projects. Both applications provide structured data storage and offer programming using VBA. You can utilize many libraries and do really cool things with these tools.

Efficiency as a goal

When my colleagues ask me how long it will take for me to automate job X by writing a script, I always ask them how long will it take if we do it manually?

Writing scripts and automating work is fun and rewarding, but some tasks, no matter how mundane, are done faster manually. The main goal here is to improve efficiency, not to write code. So always consider the faster route.

However, if you are about to repeat the same manual process a few times a month or even a few times a year, it is worth spending some time and automating it.

Another added value of automation is when you are not around, or when you’ve moved on (to a better position), others will still be able to automate mundane work thanking you for the years to come. Trust me, you’ll be thanked for some time.

 


World-class Customer Service

In mid October 2013, Apple started recalling mid-2012 Macbook Airs, due to a SSD problem that was apparently and isolated issue to Toshiba drives only.

I found out that my mid-2012 Macbook Air had a Toshiba SSD, so I booked a meeting at the Genius bar of my local Apple Store in Vancouver. The store is always packed with people fiddling with iPhones and iPads and occasionally Macs. Long story short, the Apple Genius handling my case told me that they don’t have any local stock left and I need to wait a couple of weeks. I agreed and he reserved a new 64GB SSD telling me that I’ll receive a call when the drive arrives.

Two weeks later I received a call from Apple Store that I missed. They wanted to let me know that since it took longer than usual for me to get the SSD replacement, they are giving me a brand new mid-2013 Macbook Air. I didn’t call them back until 4 or 5 days later.

A week later, wondering if my SSD has arrived, I called Apple Store. The nice guy on the other side of the line told me the story and the fact that in the meantime my SSD has arrived too. He gave me the choice of either replacing the 64GB SSD with a new one, or get the brand new Haswell Macbook Air with a 128GB SSD (the new minimum capacity). Guess which one I picked.

There is no doubt that I’m very happy and quite impressed with the way Apple handled my case. That’s not just because I got a sweet deal. They could have just hidden the fact that I could get a new replacement laptop for free. I wouldn’t have known and would have still walked away happy with a SSD replacement. It is safe to say that not everybody with a defected SSD got (or will get) a new laptop, but the point is that as a customer I got more than what I asked for and I won’t forget that.

I compare the service* I received from Apple since I bought my very first Mac in 2007 (when I practically threw my Vista workstation out of the window) to other vendors (who either pissed me off in the process or caused more damage than good), and I’m very happy with Apple’s customer service.

Apple is not perfect in customer service. No company is. No matter how hard you try as a business there will always be unhappy customers. For legitimate reasons or not, there is always somebody to complain. I have been on the other side of the customer service table and I promise you it’s no fun.

At the end of the day, if you stay true to your values and vision and deliver excellent customer service, the joy of seeing happy smiling customers is worth all the effort and pain. One way to guarantee this is to surprise customers with delivering more than what they have asked for. One caveat to this is that setting unrealistic expectations will bite you back in the future.

Looking back at my own side-businesses, I can come up with more than a handful of examples where I applied this strategy and received positive comments, thank-you letters, referrals and even more sales.

To sum up:

  • Deliver more than promised. This doesn’t necessarily mean adding a heap of extra features and free goodies. Sometimes a free month of membership, free expert advise, or just handling the situation well will do the trick. If you demonstrate that you are passionate about what you’re doing  clients will appreciate it, which could result in really good things for your business.
  • Deliver earlier than promised. Don’t over inflate the time requirements of the work, but clients usually appreciate if you finish a few days earlier. Set a realistic deadline and work toward delivering excellent work before that deadline.
  • Give an incentive if you are late. An extra month of support, a free added-value feature, and even a Starbucks card will often cool down the client if you are few days (or weeks depending on the size of the work) behind. This shows the client that you respect their time and money and acknowledge the delay.
    Try offering something that brings instant gratification. Promising something that the client can use in the remote future won’t have the same effect and will only add to your future commitments.

* This is not the first time I’m getting excellent support from Apple. Back in 2010 they’ve replaced the logic-board of my out-of-warranty 2007 Macbook Pro, no questions asked. In 2012 I got a free battery replacement for my wife’s 2008 Macbook Air.

 



Pages:12345678