inicio mail me! sindicaci;ón

Archive for Development

Double Entry Accounting with Invoicing in Rails

You may remember a little post i made ages ago about Double Entry Accounting in Rails, in which i went over what one needed in order to make a simple double entry accounting system within the confines of the Ruby on Rails web development framework.

After a few requests by readers, i have decided to write the sequel. Double Entry Accounting with Invoicing in Rails.

To recap…

Last time i identified the following core tables you needed in your database:

  • Account (has many Postings)
  • Asset Type (e.g. £, $, monkeys)
  • Batch (has many Journals, links them into a group of transactions – though not really needed)
  • Journal (has many Postings, links them into a transaction)
  • Posting (associates with Account, Journal, and Asset Type)

Though i failed to elaborate on what you really needed to store in these tables. In truth, it can be as complicated or as simple as you’d like. No need for Batches? Then don’t include them.

As long as you at least store amounts in Posting’s, and practice the art of double entry accounting, you should be fine.

The next major point of note was how does one calculate the balances in the accounts? Well it turned out the solution was rather simple:

credit_amount = postings.sum(:value, :conditions => "amount < 0")
debit_amount = postings.sum(:value, :conditions => "amount > 0")

Coupled in with the balances were the amounts in the Postings, which had to be flipped depending on the type of account they resided in:

def real_amount
return [:asset, :expense].include?(self.account.account_type) ? self.value : -self.value
end

def real_amount=(val)
self.value = [:asset, :expense].include?(self.account.account_type) ? val : -val
end

In simpler terms: if an account is an asset or expense account, a positive value = a positive amount. Otherwise, a positive value = a negative amount. Vice versa.

So how do we factor invoicing into this?

There are two ways in which invoicing can be linked into a double entry accounting system:

  1. Link the payment of each invoice to transactions in the system
  2. Link the amount owed by each client for each invoice to transactions in the system

Realistically though, #1 is a fairly stupid idea as in the real world, clients don’t always pay on time. Or with the correct amount or order. Not only that, they can also pay off multiple invoices at once!

Which brings us to #2 – linking the amount owed by each client for each invoice into the system.

How do we do this? Well to summarise:

  • Have a revenue account which tracks how much you make.
  • Have a checking account which tracks what is in the bank.
  • Make an asset account for each client.
  • When you make out an invoice, record a transaction which transfers the total amount of the invoice from your revenue account into the client account.
  • Link any transaction(s) generated by the invoice to the invoice (so you can revert them later if required)
  • When the client pays, record a transaction which transfers the paid amount from the client account into your checking account.

Which might look like this in the system:

Account Debit Credit
Checking Accounts
Bank 100 0
Invoice Accounts
Microsoft 50 0
Apple 50 0
Revenue Accounts
Revenue 0 200

So…

  • For tax purposes, your revenue account will at least sum up to the total amount in all of your invoices.
  • If the client’s account has a positive balance, they owe you money for any one of your invoices.
  • If the client’s account has a negative balance, they’ve obviously overpaid you. So go party!!

… which more or less concludes this article. Happy accounting!

Making a Real Calendar in Rails

For a while now, i have been looking at the various calendar helpers on Github. One thing stands out over all of them: they all suck.

bad_calendar

Why? well, they all implement the same basic concept – that is, they make a table containing rows for each week, and cells for each day, yielding in case the user wants to display anything other than a day number in the cell.

This is fine if all you want to do is display single-day events, but if you want to go to the next level and display multiple “all day” events it is practically impossible as the events are constrained in their table cell. Instead, another approach is needed.

good_calendar

The approach? Well, put simply the events are placed in a row below each set of day cells. Events which span more than 1 row are repeated, and a layout algorithm handles vertical placement.

Now rather than writing a whole post describing in agonising detail how to implement this approach, i thought i’d post a gist on github describing how to do it. Read it here. Any improvements? Feel free to fork. Comments? feel free to post below!

 

Update: The great guy’s over at elevation have turned this code into a plugin. So if you don’t fancy implementing this all by yourself, just use the easy to install plugin. :)

A good use for “:group” in Rails

Recently i needed to make a custom view for activity logs in my Ruby on Rails app. I wanted to create a summary of the activity grouped by the day, without any duplicates. e.g. if i performed an action an object twice, i didn’t want it to be listed twice.

So how does one do this in Rails? Simple – use the “:group” (i.e. GROUP BY) parameter when doing a find() to combine results into single results.

The nitty gritty

For reference i used the following schema on my logs:


  create_table "application_logs" do |t|
    t.integer  "rel_object_id"
    t.text     "object_name"
    t.string   "rel_object_type"
    t.datetime "created_on",
    t.integer  "created_by_id",
    t.boolean  "is_private",
    t.boolean  "is_silent",
    t.integer  "action_id",
    t.integer  "page_id",
  end

In my case, most of my objects were linked to pages. And for those, i only wanted page activity to be listed once. e.g. “Modified page X” instead of “Modified object 1 on page X”, “Modified object 2 on page X”.

So i needed to group by page_id, created_by_id, created_on (as a date), and both rel_object_id and rel_object_id.

First i came up with the following :group :


"created_by_id,
 date(created_on),
 page_id,
 rel_object_type || rel_object_id"

Note: the “||” operator in SQLite and PostgreSQL concatenates strings.

Unfortunately that doesn’t work properly since i have other objects which aren’t linked to a page, and they would only get listed once (since for all of them page_id would be NULL). So i needed to use the “CASE” statement to differentiate between the two:


"created_by_id,
 date(created_on),
 CASE page_id ISNULL
   WHEN 1 THEN rel_object_type || rel_object_id
   ELSE page_id
 END"

So now both the page objects and the regular objects were listed once per day. But there was another problem.

After the query i used the group_by method to group everything into blocks based on the date. But i also use the time zone support in Rails 2.1, and since the database stores its dates in UTC, i got this rather odd issue where in certain circumstances objects were listed twice.

In reality they were the same date, in UTC. But not in the current timezone i was using. So after a bit of investigation i came up with a solution. I needed to offset the date in the query by the UTC offset for the current timezone.

It turns out that there are a ton of different ways to do it, depending on which database you are using. In my case i was testing with SQLite, so the following sufficed:


date(created_on, '+#{Time.zone.utc_offset} seconds')

And for MYSQL (and perhaps others), using INTERVAL works:


date(created_on + INTERVAL #{Time.zone.utc_offset} SECOND)

Of course, this still has its problems. Like what about daylight savings time?

Unfortunately, since there doesn’t seem to be any set standard for specifying what timezone to evaluate times in, you are either going to have to write a specific case for it, or just put up with the dates potentially being off for an hour or two.

The end result

Well, it looks something like this:

Fuzzy Times

Recently i have been writing a simple web-based reminder app which requires one to input dates and times. To input the date and time, normally one would add some sort of calendar widget which pops up.

But personally i think this tends to be really awkward, especially if you don’t want to be specific about dates or times. e.g. Speculative Opportunities. It also requires a lot of mouse clicking to find and enter the correct date and time.

Fortunately, there are libraries about which aim to solve this issue by allowing you to specify the time in English. Typically they are referred to as “Natural language” date/time parsers. In my case, i found one called Chronic which is distributed as a gem for Ruby. It has even got a nice screencast.

sudo gem install chronic

Consisting of only one public function, Chronic is really easy to use:


require 'chronic'
Chronic.parse("tomorrow at 5")
 #=> Fri Aug 08 17:00:00 +0100 2008

See? Nice and simple. We can also use the options to help chronic get the right time. e.g. If i really meant to say “Tomorrow at 5 AM”, i could fix it like this:


require 'chronic'
Chronic.parse("tomorrow at 5", :ambiguous_time_range => :none)
 #=> Fri Aug 08 5:00:00 +0100 2008

The options you can choose from are as follows:

  • :context – the context in which the time is assessed (:past or :future).
  • :now – current time.
  • :guess – if false, this returns a time range instead of guessing at a specific time.
  • :ambiguous_time_range – range in hours in which an ambiguous time will be resolved. Best to think of it as hours to skip in the day when picking a time. e.g. setting this to 18 and inputting 5 will result in 5am the next day being chosen.

Sadly i couldn’t seem to find any way of setting which time zone to evaluate the time in. This would have been useful when working with Ruby on Rails 2.1′s new TimeZone support. Fortunately though, i figured out a workaround which is as follows:


# grab time using current time zone as reference
ctime = Chronic.parse(value, :now => Time.zone.now)
# re-interpret time in current timezone
ctime = Time.zone.local(ctime.year, ctime.mon, ctime.day, ctime.hour, ctime.min, ctime.sec)

Basically this gives Chronic the time in the current time zone, which deals with relative times (e.g. “tomorrow”). It also re-interprets the calculated time in case you are a bit more specific (e.g. “5AM”).

For something a bit less hackish, one might want to check out technoweenie’s fork on github. This appears to allow you to tell Chronic to use a different Time class for calculating times, which should solve the problem.

So to conclude, i think Chronic is a nice and simple solution that works rather nicely for common cases.

Other libraries

If you aren’t using Ruby, have no fear. There are similar “Natural language” parsers available for other programming environments which work in a similar fashion to Chronic.

An Analogue Clock using Safari Transforms

Recently Safari 3.1 has been released for Mac and Windows, boasting a whole load of useful new features. One of these is support for CSS transforms – i.e. you can translate, scale, and rotate HTML elements in a web page.

CSS transforms can come in quite handy for making complex dynamic objects, without the need for 3rd party plugins or applets. For example i was able to make the following BBC-esque analogue clock, using only DIV’s and JavaScript :

(Note that currently this only works in Safari 3.1)

EDIT: Now works in FireFox too!

Yes, DIV’s and JavaScript. No Canvas, no Flash, no SilverLight, no Java Applets, no Plugins.

It makes me wonder, considering that browsers seem to be getting so powerful nowadays, should one really bother using Flash & co anymore?

What not to write in haXe, Part II

I decided to have another go at writing some awe-inspiring haXe code again. This time, i picked up from where i left off – that was trying to get my infamous SCUMM interpreter working on additional platforms which haXe supports.

For reference, i concentrated on getting it to work on the neko platform.

To start off with, i took notice of a suggestion to simplify the import statements which littered the top of the source code. So instead of this:


#if flash9
import flash.display.Bitmap;
...
#else neko
import noflash.Bitmap;
...
#end

I consolidated everything into a single file which looked like this:


#if flash9
typedef Bitmap = flash.display.Bitmap;
...
#else neko
typedef ByteArray = noflash.ByteArray;
...
#end

So when i used “import hiscumm.Common”, i could now access all of the classes listed with little fuss!

Another change i made was to re-factor the way resources were loaded. Before, i just used flash 9’s ByteArray. However as there is no direct equivalent of this on the neko platform, i had to implement my own.

Thinking more, i determined that only a relatively small portion of my code actually needed to use all of the features of ByteArray, so instead i changed all of the IO code to use the neko api’s Input & Output classes.

Finally i made all 32bit integers Int32’s. Consequently, i had to re-implement the Int32 class for the flash platform, but all things considered it was the best solution.

Problems

As before, i ran into a fair share of problems. Most were minor, and others were solved when i upgraded from haXe 1.17 to 1.18. Here are some of the more notable ones i came across.

“No arrays larger than 115 elements”

I ended up finding a rather obvious solution to this problem which worked transparently with the other platforms. All one has to do is split up the troublesome array into several smaller arrays and then concatenate them together. e.g.


var longarray = [1,2,3].concat([4,5,6]).concat(7,8,9); // works

Problem solved.

“Beware of classes extending Int”

In an earlier implementation of my Int32 class, i had it extending Int. This turned out to be a fatal mistake, as when i tested out the code absolutely nothing worked.

The solution of course was just to not extend from Int.

“haxe.Timer does not have a constructor”

I kept getting a rather odd compile error. It seemed that no constructor was defined for the Timer class, which i used to run the game loop. This was very odd, as the API documentation didn’t state anything unusual about the Timer class on the neko platform.

However after checking out the code to the Timer, i soon came to realise the horrifying truth: the Timer class wasn’t implemented for the neko platform. Arrrgh! I got this far and now i’m stopped by something as simple as this?

Thankfully i figured out a rather obvious workaround. Instead of using the timer, i merely made a typical run-of-the-mill game loop. Problem solved.


while (true)
{
onTime();
neko.Sys.sleep(0.01);
}

The result

As the output below shows, the interpreter now actually runs on neko. Unfortunately there appears to be a rather nasty bug when decoding the room image. But then again i’ve not implemented any video code for the neko platform yet, so the usefulness of this is questionable to say the least.


$ neko test.n
NekoTest.hx:42: Engine init
SCUMM.hx:486: boot state
SPUTMResource.hx:308: Loading resource 1 from file 1, room 2 (SCRIPT)
SCUMM.hx:488: Started
SCUMM6.hx:1249: ARRAY = ""
SCUMM6.hx:1249: ARRAY = "ScummC Paused !"
SCUMM6.hx:1249: ARRAY = "Are you sure you want to quit ? (Y/N)Y"
SCUMM6.hx:1249: ARRAY = "Are you sure you want to restart ? (Y/N)Y"
SCUMM6.hx:1249: ARRAY = "Save it"
SCUMM6.hx:1249: ARRAY = "Load it"
SCUMM6.hx:1249: ARRAY = "Continue"
SCUMM6.hx:1249: ARRAY = "Cancel"
SCUMM6.hx:1249: ARRAY = "Quit"
SCUMM6.hx:1249: ARRAY = "Ok"
SCUMM6.hx:1249: ARRAY = "Saveing '%s'"
SCUMM6.hx:1249: ARRAY = "Loading '%s'"
SCUMM6.hx:1249: ARRAY = "ScummC test Menu"
SCUMM6.hx:1249: ARRAY = "Save game"
SCUMM6.hx:1249: ARRAY = "Load game"
SCUMM6.hx:1249: ARRAY = "Game NOT saved"
SCUMM6.hx:1249: ARRAY = "Game NOT loaded"
SCUMM6.hx:1249: ARRAY = "Insert disk %c"
SCUMM6.hx:1249: ARRAY = "You must enter a name"
SCUMM6.hx:1249: ARRAY = "Insert your save disk"
SCUMM6.hx:1249: ARRAY = "Failed to open %s (%c%d)"
SCUMM6.hx:1249: ARRAY = "Read error on disk %c (%c%d)"
SCUMM6.hx:788: 103, 645
SPUTMResource.hx:308: Loading resource 2 from file 1, room 2 (ROOM)
SPUTMRoom.hx:173: RMIM == RMIM
SPUTMImage.hx:109: smap size == 8
SPUTM.hx:1096: Internal exception, aborting! (state=SPUTM_RUNNING)
SPUTM.hx:1097: >>

As before, the hiscumm code is available for reference. Unlike last time however, the code is now hosted in a git repository so you can now see all the nitty gritty changes i have made to it. Great!

Click here to check it out!

What not to write in haXe

You might have notice that during the past few months i’ve written a few articles about haXe, a language and compiler which pits itself as a “toolbox for the web developer”.

Recently i decided to test out haXe’s platform support. I did this by taking my SCUMM interpreter code – which i had previously written for flash 9 – and tried to get it to work on the other two major platforms haXe supports, javascript and neko.

To start off with, i had to remove its dependency on flash. This was achieved by making replacement classes and switching between the two using the conditional pre-processor. i.e.:


#if flash9
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.ByteArray;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.Timer;
import flash.events.TimerEvent;
#else neko
import noflash.ByteArray;
import noflash.Bitmap;
import noflash.BitmapData;
import noflash.Point;
import noflash.Rectangle;
import noflash.Timer;
import noflash.TimerEvent;
#end

Most of the modifications to the code looked like this, with liberal sprinklings of ”#if flash9 … #end” round the flash specific code.

Eventually i got to the point where things started to look like they were going to compile, or so i thought

Problems

“Array too big”

The first problem i encountered was that it wouldn’t compile.


hiscumm/SCUMM6.hx:1870: lines 1870-2127 : This array declaration is too big, try to split it

Array declaration too big? What on earth was it going on about?


| TArrayDecl el ->
if List.length el > 115 then error "This array declaration is too big, try to split it" e.epos;
call p (field p (ident p "Array") "new1") [array p (List.map (gen_expr ctx) el); int p (List.length el)]

Oh, right. Seems i cannot have arrays declared with more than 115 elements. A seemingly arbitrary limitation that is not referenced anywhere in the documentation – great!

Not needing the opcode table for my little experiment, i commented most of it out. Problem solved.

“32bit? no, 31bit!”

Now the first time i got the interpreter to compile for neko, i thought “Wow, great! Looks like this is going to work.” Unfortunately though, it didn’t. Instead, i got a rather odd exception when reading out of my replacement ByteArray:


Uncaught exception - Overflow

Turns out the problem was with this code here, in neko.Input:


public function readInt32() {
var ch1 = readChar();
var ch2 = readChar();
var ch3 = readChar();
var ch4 = readChar();
if( (ch4 & 128) != 0 ) {
if( ch4 & 64 == 0 ) throw Error.Overflow;
return ch1 | (ch2 << 8) | (ch3 << 16) | ((ch4 & 127) << 24);
} else {
if( ch4 & 64 != 0 ) throw Error.Overflow;
return ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
}
}

So basically the reader was trying to stuff the whole 32 bit value into a neko Integer, which is actually 31 bits. Oddly enough though, the value being read was identical to a value i specified in the code.

But haXe never bothered to complain about an overflow!

This can be demonstrated by the following code, which prints “-766623411” instead of the expected “1380860237”.


trace(1380860237);

Thankfully, a solution exists. There is an “Int32” type which properly handles 32bit integers. However there is a really big snag with it – it’s a class.

That means you cannot use any fancy inbuilt operators with it – you have to use a set of functions instead.


import neko.Int32;

var result: Int = 1 + 2; // simple
var result32: Int32 = Int32.add(Int32.ofInt(1), Int32.ofInt(2)); // aaaarrrghh!!!

result += 1; // simple
result32 += 1; // don't even think about it, it won't work

And to top it all off, this “Int32” class only exists for the neko platform, you cannot use it with flash or javascript. Unless you write it yourself, but that is besides the point. It should at least have been there to fill in the gap.

Conclusion

If you are looking at writing code in haXe and want it to work across all 3 of its supported platforms (flash*, neko and javascript), then beware if you are reading, writing, or otherwise processing 32bit integers.

In addition watch out for mysterious arbitrary limitations such as the 115 item limit for declared arrays.

A Wiki written in haXe

A while ago now, i writ a piece about haXe, a language and compiler which pits itself as a “toolbox for the web developer”.

Now i thought haXe was a great idea, with a great potential for consolidating the mess that is web development. But at the time, i couldn’t find any examples of its full use out in the field.

That was until today, when i discovered MyMiniCity!

I have heard that MyMiniCity is the first example of a web based game completely written using haXe. The back-end appears to run on mod_neko, while the front-end uses a mix of JavaScript and Flash, both compiled using haXe (from what i can tell at least).

Getting to the point…

Now i shall get to the point. I was so impressed with MyMiniCity that i decided to have a go at writing a Wiki in haXe. This pretty much took me most of the day as i had to make heads and tails of haXe’s library’s.

In any case, ended up with something which kind of works. For the code, see overleaf.

<!-more->

The code

Beware! this code ain’t pretty. But it works for the most part. Note that you might also have to make a dummy file called “macros.mtt”.

index.hxml


-cp /usr/lib/haxe/lib/mtwin/1,2,6
-neko Index.n
-main Index

Index.hx



// Main web application class.

import mtwin.web.Handler;

class Page extends neko.db.Object {
public var id : Int;
public var name : String;
public var content : String;

public var last_edited : Date;

public function toHTML() : String
{
return mtwin.text.Text2Xhtml.transform(content);
}

public static var manager = new neko.db.Manager<Page>(Page);
}

class Index {
// mtwin.web.Request represents the current http request with url, parameters, etc...
static var request : mtwin.web.Request;
// for this example we will use mtwin.templo XHTML template engine
static public var template : mtwin.templo.Loader;
// this is some dynamic template context for templo
static public var context : Dynamic;

// Instance vars
static var cnx : neko.db.Connection;

public static function main(){
mtwin.templo.Loader.BASE_DIR = "/Users/jamesu/Projects/Experiments/haxe/web/";
mtwin.templo.Loader.TMP_DIR = "/tmp/";
context = Reflect.empty();
template = null;

request = new mtwin.web.Request();

// connect to database
cnx = neko.db.Mysql.connect({
host : "localhost",
port : 3306,
database : "HaxeWiki",
user : "root",
pass : "",
socket : null
});

neko.db.Manager.cnx = cnx;
neko.db.Manager.initialize();

// creates the main application handler
var handler = new WikiHandler();

// little check to avoid index.n in path
var level = if (request.getPathInfoPart(0) == "index.n") 1 else 0;

// start processing the request starting from specified path info part
handler.execute(request, level);

// if the templo template is defined, we execute it
if (template != null){
neko.Web.setHeader("Context-Type", "text/html; charset=UTF-8");
neko.Lib.print(template.execute(context));
}

// close database connection
neko.db.Manager.cleanup();
cnx.close();
}
}

class WikiHandler extends Handler<String> {

public function new(){
super();

// Edit page
free("edit", "editpage.mtt", doEditWikiPage);
}

// Overide execute so we can process wiki pages
override public function execute( request:mtwin.web.Request, ?pathLevel:Int ){
if (pathLevel == null)
pathLevel = 0;

var part = request.getPathInfoPart(pathLevel);

this.request = request;
this.level = pathLevel;

if (part == "")
part = "default";

part = part.toLowerCase();
initialize();

// Check for special wiki pages
if (actions.exists(part)){
actions.get(part)();
return;
}

doWikiPage(part);
}

function doWikiPage(title: String){
var context = Index.context;

// Search for wiki page in database
var wikipages = Page.manager.search({name : title}, true);
var wikipage : Page = wikipages.isEmpty() ? null : wikipages.first();

if (wikipage == null)
{
context.wikipage = new Page();
context.wikipage.name = title;
context.wikipage.content = '';
context.wikipage_new = true;
prepareTemplate("editpage.mtt");
}
else
{
context.wikipage = wikipage;
prepareTemplate("viewpage.mtt");
}
}

function doEditWikiPage(){
var context = Index.context;

var realtitle = request.get('name').toLowerCase();
var wikipages = Page.manager.search({name : realtitle}, true);
var wikipage : Page = wikipages.isEmpty() ? null : wikipages.first();

if (wikipage == null)
{
context.wikipage_new = true;
wikipage = new Page();
wikipage.name = realtitle;
}
else
{
context.wikipage_new = false;
}
context.wikipage = wikipage;

if (request.get('content') != null)
wikipage.content = request.get('content');

// Skip rest if not POST'ing
if (neko.Web.getPostData() == null)
return;

if (context.wikipage_new)
{
// Make page
wikipage.last_edited = Date.now();

wikipage.insert();
neko.Web.redirect("/" + wikipage.name);
}
else
{
// Edit page
wikipage.last_edited = Date.now();

wikipage.update();
neko.Web.redirect("/" + wikipage.name);
}
}

// same as above
override function prepareTemplate( t:String ){
Index.template = new mtwin.templo.Loader(t);
}
}


database.sql

MySQL schema.

CREATE TABLE Page (
id int(10) unsigned NOT NULL auto_increment,
name varchar(40) NOT NULL,
content TEXT NOT NULL DEFAULT '',
last_edited datetime default NULL,
PRIMARY KEY (id)
);

viewpage.mtt



<html>
<head>
<title>Viewing page ::wikipage.name::</title>
</head>

<body>
<h1>::wikipage.name::</h1>
<div id="content">
::raw wikipage.toHTML()::
</div>
<p><a href="/edit?name=::wikipage.name::">Edit page</a> (Last edited : ::wikipage.last_edited::)</p>
</body>
</html>

editpage.mtt


<html>
<head>
::if (!wikipage_newl)::
<title>Editing page ::wikipage.name::</title>
::else::
<title>New page</title>
::end::
</head>

<body>
<h1>Edit page</h1>
<form method="post" action="/edit">
<input type="hidden" name="name" value="::wikipage.name::"/>
<textarea name="content" rows="10" cols="50">::wikipage.content::</textarea>
::if !wikipage_new::
<input type="submit" value="Edit"/>
::else::
<input type="submit" value="Save"/>
::end::
</form>
</body>
</html>

Instructions

Assuming you have got haXe installed, but never got the web stuff working you might want to do the following:

  1. sudo haxelib install mtwin
  2. cd /usr/lib/haxe/lib/mtwin/1,2,6/mtwin/templo
  3. sudo haxe temploc.hxml
  4. sudo cp temploc /usr/bin/

Then something like this should suffice to get the wiki code running:

  1. mysql -u root HaxeWiki < database.sql
  2. haxe index.hxml
  3. nekotools server -rewrite

And you can make wiki

Double Entry Accounting in Rails

The first helpful article i found, Double Entry Accounting in a Relational Database, suggests i need at least the following models in my system:

  • Account (has many Postings)
  • Asset Type (e.g. £, $, monkeys)
  • Batch (has many Journals, though not really needed)
  • Journal (has many Postings)
  • Posting (associates with Account, Journal, and Asset Type)

However one problem i noticed with the article was that instead of separate “credit” and “debit” fields, everything is consolidated into an “amount” field. This meant that the abstraction between debiting and crediting needed to be handled in the model rather than the actual database.

Puzzled by this, i decided to look at the database schema used in other Accounting products: LedgerSMB and jGnash.

LedgerSMB Logo

LedgerSMB uses a rather complex database schema. I couldn’t make much sense of it, apart from like the aforementioned article it consolidated credits and debits into an “amount” field rather than have them as separate fields.

jGnash Logo

jGnash was a bit different as instead of a proper database it uses an XML file to store its data. Still, there were a few distinctive elements which are the equivalent of models:

  • Account (linked to Transaction and CurrencyNode)
  • SingleEntryTransaction (linked to Account, used to insert money out of thin air)
  • DoubleEntryTransaction (linked to 2 Accounts ‘credit’ and ‘debit’. Also links with CurrencyNode)
  • SplitTransaction (used to link multiple SplitEntryTransaction’s together to indicate a split transaction)
  • SplitEntryTransaction (linked to SplitTransaction, otherwise the same as DoubleEntryTransaction)
  • CurrencyNode (e.g. £, $, giraffes)

Personally i found jGnash’s XML format needlessly complicated, though much more comprehensible than LedgerSMB’s database schema.

Though really, the approach i liked the best was the one mentioned in the article. It made the most sense, and wasn’t needlessly complicated. So i decided to implement it.

While implementing it however, i became a bit stuck on how to abstract the credit and debit in the Posting entries.

Whenever i have looked at Double Entry Accounting in the past, i always assumed that when you take money out of one account, you need to put the same amount back into another account. Thus i made this rather mistaken test data:


# Begin asset types

gbp = AssetType.new(:name => 'GBP', :symbol => '£')
gbp.save!

# Begin accounts

assets = Account.new(:parent_account => nil,
:asset_type => gbp,
:name => 'Assets',
:account_type => :asset)
assets.save!
equipment = Account.new(:parent_account => assets,
:asset_type => gbp,
:name => 'Equipment',
:account_type => :asset)
equipment.save!

liabilities = Account.new(:parent_account => nil,
:asset_type => gbp,
:name => 'Liabilities',
:account_type => :liability)
liabilities.save!
fred = Account.new(:parent_account => liabilities,
:asset_type => gbp,
:name => 'Fred',
:account_type => :liability)
fred.save!
george = Account.new(:parent_account => liabilities,
:asset_type => gbp,
:name => 'George',
:account_type => :liability)
george.save!

# Begin transactions

first_transaction = Journal.new(:transaction_type => :transfer, :start_date => Time.now)
first_transaction.save!
Posting.new(:account => george,
:asset_type => gbp,
:journal => first_transaction,
:account_period => 0,
:description => 'Funding',
:amount => -250.00).save!
Posting.new(:account => equipment,
:asset_type => gbp,
:journal => first_transaction,
:account_period => 0,
:description => 'Funding',
:amount => +250.00).save!
first_transaction.end_date = Time.now
first_transaction.save!

second_transaction = Journal.new(:transaction_type => :transfer, :start_date => Time.now)
second_transaction.save!
Posting.new(:account => equipment,
:asset_type => gbp,
:journal => second_transaction,
:account_period => 0,
:description => 'Payback',
:amount => -100.00).save!
Posting.new(:account => george,
:asset_type => gbp,
:journal => second_transaction,
:account_period => 0,
:description => 'Payback',
:amount => +100.00).save!
second_transaction.end_date = Time.now
second_transaction.save!

third_transaction = Journal.new(:transaction_type => :transfer, :start_date => Time.now)
third_transaction.save!
Posting.new(:account => fred,
:asset_type => gbp,
:journal => third_transaction,
:account_period => 0,
:description => 'Investment',
:amount => -300.00).save!
Posting.new(:account => equipment,
:asset_type => gbp,
:journal => third_transaction,
:account_period => 0,
:description => 'Investment',
:amount => +300.00).save!
third_transaction.end_date = Time.now
third_transaction.save!

Which actually appeared to work fine (as in everything sum’d to 0, and if i ignored the minus then Assets = Liabilities) before i started to delve into what debiting and crediting means in relation to whether or not an account is classed as an Asset or a Liability.

(Note that to simplify things when i say Asset i could alternatively be meaning Expenses, and when i say Liability i could alternatively be meaning Shareholder Equity or Revenue)

Account Debit Credit
Assets + -
Expenses + (-)
Liabilities - +
Shareholder Equity - +
Revenue (-) +

After applying the logic from the above table (courtesy of Wikipedia), i noticed something rather odd. The credit and debit columns on my printout didn’t match. For reference, i was using the following queries to grab the credit and debit amounts for each account.:


credit_amount = Posting.sum(:amount, :conditions => "amount #{account_type == :asset ? '<' : '>'} 0")
debit_amount = Posting.sum(:amount, :conditions => "amount #{account_type == :asset ? '>' : '<'} 0")

However if i modified the code slightly:


credit_amount = Posting.sum(:amount, :conditions => "amount < 0")
debit_amount = Posting.sum(:amount, :conditions => "amount > 0")

The credit and debit columns mysteriously matched. So what happened?

Well i puzzled over this for a while, until i read Wikipedia’s article on Double Entry Accounting again. This rather simple summary was very insightful:

Purchase of a Computer

  • Debit Computer A/c (Fixed Asset A/c)
  • Credit Creditors A/c (Liability A/c)

(A/c being an abbreviation of “account current”)

Paying supplier for the computer

  • Debit Creditors A/c (Liability A/c) You are reducing a Liability A/c
  • Credit Bank A/c (Asset A/c) Money going Out, an asset account is being reduced

So in fact all the transactions in my test data should have been increasing the amount in the liability accounts rather than decreasing it (and vice versa when paying back).

It makes sense now i think about it. The second approach worked because in effect i flipped the meaning of debit and credit by decreasing the amount in the liability accounts and calling it credit rather than increasing the amount in the liability accounts and calling it credit (and vice versa).

Now i could just go ahead and fix my test data. But then my amounts would cease to sum up to zero, and i would have to run multiple queries (each for debit and credit) to ensure integrity of the data.

Thus what i really need to do is make an attribute in the Posting model which stores and retrieves the correct “amount” depending on what type of account it is. Something like this should suffice:


def real_amount
return self.account.account_type == :asset ? self.amount : -self.amount
end

def real_amount=(val)
self.amount = self.account.account_type == :asset ? val : -val
end

So to sum it up, the only thing i really have to do with liability accounts to satisfy accounting rules is to subtract when i really mean add, and then flip the balance when calculating it. Confusion eliminated!

Now lets hope i don’t get confused again when i start to think “Did i get this right?”.

Currently i am looking into how i can effectively incorporate business concepts such as Invoices, Taxation, and so on into my little Double Entry Accounting system. So expect to see a “Double Entry Accounting with Invoicing in Rails” post in the near future.

Rotating OpenLaszlo with Internet Explorer

In my Rotating OpenLaszlo with Webkit post, i showed how it was possible to rotate OpenLaszlo elements using a recent build of Webkit, the HTML engine used in Safari.

Soon after i came across some very interesting documents on MSDN. It seems that Internet Explorer has support for visual filters and transitions.

These “visual filters and transitions” cover anything from simple Photoshop effects (including blur which i used in my Flash only Flex-style dialog blur in OpenLaszlo) to more complex transformations. More interestingly, like WebKit you can rotate elements!

An example which rotates by 270 degrees is as follows. Make sure you are viewing this page in Internet Explorer 5 or later, else this won’t work!

Click here

Unfortunately there are rather strange limitations with Internet Explorer’s rotation support.

You can only rotate in increments of 90 degrees, as opposed to Webkit which allows you to rotate by any angle. I guess they figured back in Web 1.0 that nobody wanted to rotate their elements using arbitrary angles.

Another thing is that elements you want to rotate need to have absolute positioning. Although this isn’t really a problem with OpenLaszlo as all the div’s it produces use absolute positioning.

Another perhaps more worrying problem is that with a 270 degree rotation one would expect an element to appear above the initial position. Although this could be worked around by altering the positioning in the CSS accordingly.

I guess that coupled with the apparent lack of support for changing the center of rotation and bugs with form controls limits the full effectiveness of this rotation support.


<canvas>
<class name="itrotatable" extends="view">
<attribute name="wrot" type="number" value="0"
setter="this.wrot = wrot; this.updateRot(wrot);"/>

<method name="updateRot" args="val">
var real_rot = Math.round(val / 90.0) % 4;
this.sprite.__LZdiv.style['filter'] = 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + val + ')';
</method>
</class>

<itrotatable name="item" x="20" y="10" width="100" height="25" bgcolor="blue">
<text>Test</text>
<animatorgroup name="move" process="sequential"
duration="1000" start="true" repeat="Infinity">
<animator attribute="wrot" to="4" />
<animator attribute="wrot" to="2" />
<animator attribute="wrot" to="0" />
</animatorgroup>
</itrotatable >
</canvas>

Still, that’s one more Web Browser i can sort-of rotate OpenLaszlo elements in!

Next entries »