June 18th, 2010 by Duane Jackson
Now we have proper programmers focusing on building, improving and maintaining our accounting application, I’m meant to be focusing on marketing whilst we are waiting to fill a marketing manager vacancy we have.
I’m finding that a little bit of programming skill goes a long way with digital marketing.
I have my personal twitter account that I tweet from and we also have @kashflow, the company twitter account. @kashflow uses Google to automatcally parse and tweet RSS feeds of this blog, our changelog and press releases.
But I wanted to also have it send a couple of tweets a day from a pool of a hundred or so pre-written tweets promoting aspects of the software followers may not be aware of.
Building a table of tweets and a stored procedure to select one at random was the easy bit. The tricky bit was getting a stored procedure to actually talk to twitter and send the message. But I managed it. To save anyone else having to write ths from scratch I’m sharing my code here.
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE PROCEDURE p_SendTweet @username nvarchar(100), @password nvarchar(200), @msg nvarchar(140), @STATUS int output AS BEGIN SET NOCOUNT ON; --create the XMLHTTP object declare @RETURN int declare @object int exec @RETURN = sp_oacreate 'Microsoft.XMLHTTP', @object output --SELECT @return --Open the connection DECLARE @param nvarchar(500) SET @param = 'open("POST", "http://twitter.com/statuses/update.xml", false, "' + @username + '", "' + @password + '")' exec @RETURN = sp_oamethod @object, @param SET @param = 'send("status=' + @msg + '")' exec @RETURN = sp_oamethod @object, @param declare @output int exec @RETURN = sp_oamethod @object, 'status', @output output exec sp_oadestroy @object SET @STATUS = @output END GO
There you have it. Now to send a tweet from any other stored procedure all you have to do is
EXEC p_SendTweet 'your_screenname','your_password','the message',@output output
If all went well then @output will contain “200″
As a side note, I’ve only written one really techie post before on this blog. I’ve deliberately refrained from doing too many as I’m assuming the majority of readers aren’t too interested in this stuff. If I’m wrong and you’d like more like this then let me know using the comments box below.
Posted in Programming, Technology | 1 Comment »
January 13th, 2010 by Duane Jackson
When KashFlow was first available back in 2005 it was a very, very basic invoicing tool. It produced invoices with sequential numbers and you could mark them as either “paid” or “not paid”. Nothing more. This was intentional. We (or “I” as it was then) didn’t want to make assumptions about what businesses wanted from what was to be a fully functional accounting software
We were lucky with our timing. There weren’t any other web-based accounting apps worth mentioning at the time and we weren’t under the level of scrutiny new entrants in this market place are today.
So we took our time and asked our customers to tell us what they wanted added. Once we’d covered the main bases we’d only add new features it if they passed 4 tests:
1) Customers must be asking for it – so not just something we think would be cool to have
2) It mustn’t distract from the simplicity of the software
3) It shouldn’t remove any existing functionality
4) Wherever possible it should be off-and-onable, defaulting to off so as not to confuse or distract customers
Rule 4 can cause a problem as people taking an initial look at the software today can be fooled into thinking it doesn’t have many features when in fact there’s probably no other accounting app, online or offline, with the depth of functionality we now have.
This is why we tell people that if they think it can’t do something they need, they should get in touch with support as it probably does do it.
The result is that we now have an application that’s got lots of features that are of genuine use to small business owners, rather then lots of confusing menus full of jargon and options you never use – the main thing that put me off other programs available when we started.
We’ve kept our approach the same over the years; actively soliciting suggestions and sticking to the rules above. You’ve not let us down. We have a list of great feature requests and we’re constantly improving the software based on those suggestions.
Until relatively recently we’d pick the features we (myself and one other developer) were going to work on and just go for it. This meant we’d get new functionality released very quickly and this kept us ahead of the emerging competition.
Now we have thousands and thousands of customers and a team of developers (they rarely let me touch code these days) we needed to implement a more methodical approach to developing the application. So this is how one of your suggestions goes from initially being received to being live in the software.
The suggestions we receive from you are all logged on a database, nothing is discarded no matter how silly or complicated.
Once every 4 weeks I sit down with the development team and let them know which suggestions I want implemented over the next 4 weeks.
The way I decide what I want them to do is based on how many people are asking for a particular feature and how complex it is. I’d be lying if I said I don’t take into account who’s asking for it too. We have some Partners who spend tens of thousands of pounds a year with us and I’d be silly not to give more weight to their requests than I do to others.
They go away and develop the features on a development server we have in the office. Once they’ve finished, the new features are copied to a separate test server we have here and it’s tested by non-technical end users. Assuming the features work as planned they then go on to the “live” system where you get access to them.
This works really well and means we can still get new features out quickly and regularly.
The down-side is that if you make a suggestion for us, it’s virtually impossible for us to tell you how long it’ll be before it’s available. It may be a great idea and we plan to add it in the next development cycle. But as requests flood in each week, the list changes all the time so your suggestion may get put back if other requests become more popular or more pressing.
An observation. The basic invoicing tool we launched with cost £13.99/month. Since then, despite going from a basic tool to a full accounts package that’s winning awards all over the place, and spending 100’s of thousands of pounds developing the software and infrastructure, we’ve only upped the price once – to £15.99/month. And that was only for new customers. If you joined us back when it was £13.99, that’s what you’re still paying.
Tags: agile, development, sprint, suggestions
Posted in Programming, Technology, Uncategorized | 6 Comments »
May 21st, 2009 by Duane Jackson
Sage CEO Paul Walker recently told silicon.com:
In the back office accounting area, business solutions, we’re seeing very small, slow growth in terms of demand [for cloud computing]. We have a number of products that meet that demand that so far is relatively modest
It didn’t sound right to me at the time. Why spend 18 months developing Sage Live, (their software-as-a-service offering that later got pulled) if the demand for it is so small and their current product range meets that demand?
Motasim Najeeb, relatively new CTO for Sage North America, made some interesting comments at their Partner event in Nashville. He talked about making Sage products an alternative to cloud-based offerings like salesforce.com.
In the article linked to at the start of this post, Walker told Silicon:
in two or three years time I’d be very surprised if 50 to 60 per cent of our customers were on [cloud-based applications] but it could be more like 15 or 20 per cent
But Najeeb is quoted as saying that in three to five years Software-as-a-Service will probably surpass on-premise software. You can guess who I agree with.
Sage also seems to be some confused about what their soon-to-be-ex customers actually want. Walker talks about delivering more ”cloud computing” apps - which is a catch-all term that includes just delivering the same old software over the internet (not the same as “the web”) using remote access software. The ex Sage customers we and other SaaS accounting companies are picking up aren’t looking for cloud computing solutions. They specifically want true SaaS applications that will pass The Touring Test.
Sage say they’re meeting the existing demand from their customers. Here’s a quote from a direct message I received on Twitter today which is typical of the kind of thing we’re hearing all the time:
I’m historically Sage oriented but willing to look at online solutions as well and Sage’s offering is ****. Perhaps demo ?
The sender doesn’t want to be named as he still has a relationship with Sage. But needless to say he has now seen our software and it’s the only product he’s recommending to his clients for web-based accounting. He only came to us because Sage have nothing suitable – ie, they’re NOT meeting the demand.
It’s not only Sage resellers, consultant and accountants that are telling us Sage can’t fulfill their needs, but some of their bigger international commercial partners are too – more about that another time perhaps.
The demand from the Sage reseller channel for a SaaS app has been so great since the start of this year that we had to develop a reseller programme specifically to be able to capitalise on it. We don’t have anything online promoting it just yet, but it’s up, running and being used. (Contact Neil Ballard on 0800 848 8301 if you’re a reseller interested in this)
I made a post last year with the title Sage Prove They’re Both Worried and Clueless. The “clueless” in the title was about their lack of understanding of the ‘net and specifically social networks. Since then I’ve been really impressed with the way they are using Twitter to engage with clients. And now it seems Sage, in the US and the UK, are reaching out to industry commentators, like Ben Kepes, that really know their stuff.
I guess it takes a while for a juggernaut to change direction. But all the signs now are that Sage are (very) slowly moving in the right direction. Hopefully the CEO will listen to his CTO about the technology (the clue is in the T!) and we’ll see a viable product from them one day soon which will give a lift to the whole SaaS accounting industry.
As Sage seem to be soliciting opinions on their approach, here’s mine just in case anyone is still reading.
They seem to have two major problems:
To me the solution to both problems is pretty simple:
They need to get a new company up and running, owned and funded by Sage PLC (although I know a few VC’s who would happily pour money in) – give it a big fat budget and some good project managers and let it run independently.
Then recruit developers that are real web developers, not desktop developers. These people can’t be from within Sage - they need to be people that know the web but aren’t tainted by exposure to old-school software houses, their methodologies and blinkered approach. They need to build an app from the ground up using pure web technologies – PHP, .Net, Ruby, whatever.
The new company should be able to access Sage’s expertise on the accounting side of things – but not make use of ANY of their existing technology, code,database structures or concepts of how software should work. That last bit is so important. I can understand how tempting it must be to re-use code and database structures to save time and money. But that would be like a cancer in the new product. Don’t do it!
I reckon they could easily put together something good enough to take to market within 6 months.
From then on, they can revive what I suspect was part of the Sage Live game plan: release the app sooner rather than later and improve it based on feedback from actual users. Improve and release again ad infinitum (a web-app is rarely finished) and price it very aggressively.
Once the product is working well, let them tap in to the marketing machine that is Sage PLC as well as having their own budgets for online marketing.
If done correctly the new business will very quickly start taking customers away from it’s parent company. But these customers were going to be tempted away anyway – better for Sage that they leave for a Sage-owned subsidiary than elsewhere.
Or there’s always Option B. If Sage want to save some time and make a very serious web play that will keep them relevant to the fast changing market then they should just buy 37Signals. That’d shake things up a bit!
Tags: Cloud Computing, SaaS, Sage, SageLive
Posted in Cloud Computing / SaaS, Programming, Small Business, Technology | 8 Comments »
January 7th, 2009 by Duane Jackson
Another techie post, sorry!
We’ve just added multicurrency invoicing and quotes to our online accounting software. We’re supporting a wide range of currencies and wanted to also allow customers to enter their own.
So you select a currency, by name, from a drop down list. The software then sends out an AJAX request to our server, the server looks up the currency in our database and automatically fills in text boxes with the name, symbol and exchange rate of that currency. You can then overwrite the content of those boxes if you want to.
The Euro symbol and a few others caused us no end of problems. Writing document.getElementById(‘curSymbol’).value=’€’; works fine if the javascript code is on page or in a .js file referenced in the <head> area. However, when it’s sent over http using AJAX, it refused to work and just gave us weird symbols instead.
Google was no help whatsoever so we were left to our own devices.
The first work around we tried was to use javascripts native String.fromCharCode() function with the code for the symbol. This worked for some currency symbols, but not for the Euro.
We finally found a workaround that works for us, so I thought I’d detail it here in the hope it helps some other poor soul.
Our pages already have a .js file that’s included on virtually all of them. So we added a line to this to set up a variable: var symbol_euro=’€’;.
In our database with the currencies, we added a new field called “JSVariable”.
In our AJAX that gets the symbol, we also retrieve the contents of the JSVariable field.
If JSVariable is empty, then we proceed as normal. But if it does contain anything then instead of setting the text box to contain the raw symbol as per the database, we instead set it to the variable.
So instead of document.getElementById(‘curSymbol’).value=’€’;, our code would return document.getElementById(‘curSymbol’).value= symbol_euro; for the Euro symbol.
I hope that makes sense and I hope it saves someone some time.
Tags: AJAX, javascript
Posted in Programming, Technology, Uncategorized | 2 Comments »
December 12th, 2008 by Duane Jackson
If you write C# code, then you’ve probably felt the frustration of trying to debug a SQL Command. Especially as it has lots of parameters. There doesn’t seem to be any native way of getting out an exact SQL command for you to execute yourself in SQL Management Studio.
Well, fret no more. I just threw together the following function for exactly that purpose:
public string sqlCommandToString(SqlCommand c,Boolean bVerbose) { string retval = c.CommandText + " "; SqlParameter p; for (int i = 0; i < c.Parameters.Count; i++) { p = c.Parameters[i]; if (bVerbose) { retval = retval + p.ParameterName + "(" + p.SqlDbType.ToString() + ")=" + p.Value.ToString() + ", "; } else { retval = retval + "'" + p.Value.ToString() + "',"; } } return retval; }
Just pass in a SQLCommand object. If you want more info, such as the parameter name and type then make the second argument True.
Tags: C#, SQL
Posted in Programming | 1 Comment »
November 27th, 2008 by Duane Jackson
This is probably the most technical post I’ve made to date – so unless the title makes sense to you, the rest of this is likely to be a foreign laguage too.
We had a meeting today with some great guys with an even greater service that we’re going to be integrating with our online accounting software (more on that another time). Their service is exposed as a .Net SOAP webservice. Now you’d think that wouldn’t be a problem for us as our own accounting API uses the same technology. Well, you’d be wrong. Our core product is still coded in classic ASP / VBScript.
So the challenge was to talk to a SOAP webservice from VBScript. Google threw up a few results, none of them exactly what I needed. The closest was a blog post by Ken Hughes. So I took his approach and re-wrote it for my needs. It’s not the prettiest piece of code I’ve ever written, and would certainly be nicer as a class. But it does the job.
Enough talk, here are the goods. First an include file with all the functions, etc:
Download: _consumewebservice.asp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <% SOAP_ENDPOINT = "" SOAP_NS = "" SOAP_FUNCTION = "" SOAP_REQUEST = "" SOAP_RESPONSE = "" function SOAP_StartRequest(sEndPoint, sNameSpace, sFunction) SOAP_ENDPOINT = sEndPoint SOAP_NS = sNameSpace SOAP_FUNCTION = sFunction 'do the SOAP envelope SOAP_REQUEST = "<?xml version=""1.0"" encoding=""utf-8""?>" SOAP_REQUEST = SOAP_REQUEST + "<soap12:Envelope " SOAP_REQUEST = SOAP_REQUEST + "xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" " SOAP_REQUEST = SOAP_REQUEST + "xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" " SOAP_REQUEST = SOAP_REQUEST + "xmlns:soap12=""http://www.w3.org/2003/05/soap-envelope""> " 'start the SOAP body SOAP_REQUEST = SOAP_REQUEST + "<soap12:Body>" 'start function SOAP_REQUEST = SOAP_REQUEST + "<" + SOAP_FUNCTION + " xmlns=""" + SOAP_NS + """>" end function Function SOAP_AddParameter(byval strParam, byval strValue) Dim strSoap SOAP_REQUEST = SOAP_REQUEST + "<" + strParam + ">" SOAP_REQUEST = SOAP_REQUEST + strValue SOAP_REQUEST = SOAP_REQUEST + "</" + strParam + ">" End Function function SOAP_SendRequest() 'end function, body and envelope SOAP_REQUEST = SOAP_REQUEST + "</" + SOAP_FUNCTION + ">" SOAP_REQUEST = SOAP_REQUEST + "</soap12:Body>" SOAP_REQUEST = SOAP_REQUEST + "</soap12:Envelope>" Dim oHttp Dim strResult Set oHttp = CreateObject("Msxml2.XMLHTTP") oHttp.open "POST", SOAP_ENDPOINT, false oHttp.setRequestHeader "Content-Type", "text/xml" oHttp.setRequestHeader "SOAPAction", SOAP_NS + "/" & SOAP_FUNCTION oHttp.send SOAP_REQUEST SOAP_RESPONSE = oHttp.responseText end function Function SOAP_GetResult(resultParam) Dim oXml Set oXml = CreateObject("Msxml2.DOMDocument") oXml.Async = true oXml.LoadXml SOAP_RESPONSE Dim strPath strPath = "/*/*//" + resultParam Dim oNode Set oNode = oXml.documentElement.SelectSingleNode(strPath) SOAP_GetResult = oNode.Text End Function %> |
And now a quick demo. This connects to our accounting API, calls the GetInvoice function and gives you a couple of the return values.
Download: tryit.asp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <!--#include virtual="_consumeWebservice.asp"--> <% SOAP_StartRequest "https://secure.kashflow.co.uk/api/service.asmx", "KashFlow", "GetInvoice" SOAP_AddParameter "UserName", "yourusername" SOAP_AddParameter "Password", "yourpassword" SOAP_AddParameter "InvoiceNumber", "37" SOAP_SendRequest %> <html> <head> </head> <body> Status: <%=SOAP_GetResult("Status")%><br /> NetAmount: <%=SOAP_GetResult("NetAmount")%><br /> VATAmount: <%=SOAP_GetResult("VATAmount")%><br /> </body> </html> |
There are some limitations – it doesn’t handle complex types in the request. But it does what I need it to do and hopefully it’ll be of use to someone else out there.
Tags: Programming, SOAP, VBScript
Posted in Programming, Technology | 4 Comments »
