Archive for the ‘Koha’ Category

Showing item type counts on the checkout screen

Friday, July 30th, 2010

Does your library limit your patrons to a certain number of checkouts for certain item types? At the Athens County Public Libraries, for instance, we limit patrons to 10 audio books, 10 music CDs, 10 videos, and 5 DVDs at a time. If a patron tries to check out more than 5 DVDs, Koha will show a warning. But what if you want to be able to tell at a glance how many a patron has?

This functionality was available to us in our 2.x installation, but when we upgraded to 3.0 our support company at the time told us it wasn’t a customization they would support. This wasn’t a feature we were willing to give up, so I set out to duplicate it using the tools available to me: system preferences and JavaScript.

Information there for the taking

All the information we need can be found on the patron checkout screen, we just need to figure out how to get it. The page lists all the items checked out to the patron, and it shows the item type for each:

List of items checked out on the checkout screen

With this available to us we can use jQuery to count each instance of each item type. We need to build a count for each item type in our system, so the script isn’t very portable. It looks for table cells (“<td>“) containing the description of each of our item types:


var itypes = {'circ': 0, 'avid': 0, 'avbk': 0, 'avmu': 0, 'advd':0 };
$("#issuest td:contains('Circulating')").each(function(){
itypes["circ"]++;
});
$("#issuest td:contains('Videos')").each(function(){
itypes["avid"]++;
});
$("#issuest td:contains('DVDs')").each(function(){
itypes["advd"]++;
});
$("#issuest td:contains('Audio Books')").each(function(){
itypes["avbk"]++;
});
$("#issuest td:contains('Music CDs')").each(function(){
itypes["avmu"]++;
});

The script starts by setting up an array of all my item types (“circ,” “avid,” etc.) and giving each a value of zero. Then the script looks for instances of each item type description on the page,  “Circulating,” “Videos,” etc., using jQuery’s :contains selector. Each time it finds an instance of one of those text strings the script increments the count for that item type. At the end of the process the script will have the count for each item type.

Displaying the counts on the page

In order to show the item type counts on the page we need to lay some groundwork by adding some markup. I want to add the count information right after the “Checking out to…” heading, so I’ll find that element’s ID using FireBug and jQuery’s after() function:


$("#circ_circulation_issue label[for='barcode']").after( ... );

The HTML I’m going to add is the default state, so it shows a zero count for everything:


<p style="margin-top:1em;">
<span id="avmuout">0</span> Music CDs out, <span id="avmuok">10</span> More Allowed
</p>
<p>
<span id="avbkout">0</span> Audio Books out, <span id="avbkok">10</span> More Allowed
</p>
<p>
<span id="avidout">0</span> Videos out, <span id="avidok">10</span> More Allowed
</p>
<p style="margin-bottom:1em;">
<span id="advdout">0</span> DVDs out, <span id="advdok">5</span> More Allowed
</p>

I’ve  included unique IDs for the “count” spans so that I can easily update them with my script:


$("#avidout").html(String(itypes["avid"]));
$("#advdout").html(String(itypes["advd"]));
$("#avbkout").html(String(itypes["avbk"]));
$("#avmuout").html(String(itypes["avmu"]));

$("#avidok").html( 10 - itypes["avid"] );
$("#advdok").html( 5 - itypes["advd"] );
$("#avbkok").html( 10 - itypes["avbk"] );
$("#avmuok").html( 10 - itypes["avmu"] );

In the first of the two sections above I take the count I got earlier, itypes['avid'] and set the content of the corresponding <span> using the html() function. I also want to show how many more the patron can check out, so I subtract the count from the limits I’ve set in my Koha installation.

If you have patrons who have exceeded their checkout limit you’ll see a problem: The page will tell you they’re allowed to check out a negative number more items. We can correct the script to accommodate:


$("#avidok").html((10-itypes["avid"] > 0) ? 10-itypes["avid"] : 0);
$("#advdok").html((5-itypes["advd"] > 0) ? 5-itypes["advd"] : 0);
$("#avbkok").html((10-itypes["avbk"] > 0) ? 10-itypes["avbk"] : 0);
$("#avmuok").html((10-itypes["avmu"] > 0) ? 10-itypes["avmu"] : 0);

Final version

Here’s what the results look like:

The final version includes proper escaping of the HTML content and wraps the whole process into a function (“itemTypeCount”). This function will be called on page load only if jQuery finds that the table of checkouts, which has an ID “issuest” is being displayed. The whole script goes into Koha’s intranetuserjs system preference.


function itemTypeCount(){
$("#circ_circulation_issue label[for='barcode']").after("<p style=\"margin-top:1em;\" class=\"icount\"><span id=\"avmuout\">0</span> Music CDs out, <span id=\"avmuok\">10</span> More Allowed</p> <p class=\"icount\"><span id=\"avbkout\">0</span> Audio Books out, <span id=\"avbkok\">10</span> More Allowed</p> <p class=\"icount\"><span id=\"avidout\">0</span> Videos out, <span id=\"avidok\">10</span> More Allowed</p> <p style=\"margin-bottom:1em;\" class=\"icount\"><span id=\"advdout\">0</span> DVDs out, <span id=\"advdok\">5</span> More Allowed</p>");

var itypes = {'circ': 0, 'avid': 0, 'avbk': 0, 'avmu': 0, 'advd':0 };
$("#issuest td:contains('Circulating')").each(function(){
itypes["circ"]++;
});
$("#issuest td:contains('Videos')").each(function(){
itypes["avid"]++;
});
$("#issuest td:contains('DVD')").each(function(){
itypes["advd"]++;
});
$("#issuest td:contains('Audio Books')").each(function(){
itypes["avbk"]++;
});
$("#issuest td:contains('Music CDs')").each(function(){
itypes["avmu"]++;
});
$("#avidout").html(String(itypes["avid"]));
$("#advdout").html(String(itypes["advd"]));
$("#avbkout").html(String(itypes["avbk"]));
$("#avmuout").html(String(itypes["avmu"]));
$("#avidok").html((10-itypes["avid"] > 0) ? 10-itypes["avid"] : 0);
$("#advdok").html((5-itypes["advd"] > 0) ? 5-itypes["advd"] : 0);
$("#avbkok").html((10-itypes["avbk"] > 0) ? 10-itypes["avbk"] : 0);
$("#avmuok").html((10-itypes["avmu"] > 0) ? 10-itypes["avmu"] : 0);
}
$(document).ready(function(){
if(document.getElementById("issuest")){
itemTypeCount();
}
});

Caveats

This system works very well for my library, but it comes with a few caveats:

It requires that you hard-code, in the script, handling for each of your Koha item types.

Besides being tedious, it also requires that you modify the script each time you change your item types.

It requires that you hard-code the correct item type limits.

Also tedious, and requires that you modify the script each time you change your circulation rules.

It creates a potential collision with both call numbers and titles.

If my item type description is “DVD” and my call number includes the text “DVD” as well I’ll get an inaccurate count. If my item type description is “Audio Books” and a patron has checked out a print book entitled Audio Books for long trips I’ll get an inaccurate count.

For us the disadvantages are not unwieldy and the collision problem has never caused a problem. The advantage we get is being able to tell at a glance whether the patron is going to be able to check out that stack of DVDs or whether we need to ask them to put some back. Better to ask them to pick their favorites up front rather than after we’ve already checked out some of them.

Developing with branches

Thursday, July 22nd, 2010

There was recently some discussion on the Koha mailing list about how “branches” fit into the development process. I replied with a description of how I use branches in my development process, and this post is an expansion of that.

In my discussion of Koha’s bug-reporting process I mentioned that a developer who wants to work on a bug will “accepts” a bug in Bugzilla before beginning work on it. There is a lot more to the developer’s workflow going on behind the scenes. I’ll describe what my process is.

When I first begin to work on fixing a bug, I create a “branch” in the git version control system. When I do so git creates a separate working copy of the main branch, “master.”  This copy is of the very latest version of Koha available. I create a separate branch for each distinct change I want to make to Koha. That change might be defined as a bug fix for a particular bug, or a new feature. The changes to each branch might include modifications to many different files, but the changes should all be related to that one subject.

It’s vitally important that I keep my branches clean and separate from each other because the Release Manager is relying on me to make it easy for him to apply and test my patches. If I submit a patch that covers more than one “subject,” that makes it all the more difficult to test it properly. If I introduce a bug to one aspect of my update, the whole patch may have to be rejected. Keeping things as simple as possible makes it easier for everyone.

To see how this looks in my workflow, here’s a selection of my current working branches:

ip-Bug-3125-IE-selects-2010-05-18
ip-Bug-4173-restricted-status-2010-03-18
ip-Bug-4901-Zotero-subtitles-2010-07-09
ip-hold-interface-test-2010-07-19
* master
ps-Bug-2307-calendar-i8n-2010-07-13
ps-Bug-2704-440-Display-2010-07-13
ps-Bug-2981-alternate-solution-2010-05-18
ps-Bug-3459-topissues-2010-06-29

When I first sit down to work I create a branch with a prefix “ip-” for “in progress,” give it a short title and bug number if I have one, and add the date I started working on it. You can see I might have quite a view branches in progress at a time. This might be because I’m working on a big update which is time-consuming, or it might mean I’m stumped about what the solution is.

Each time I sit down to do more work on a bug I switch to that branch, download the latest updates which have been submitted and approved on the master branch, and tell git to “rebase” my branch. The rebase process merges my changes with the latest updates. If there are any problems with the merge git will warn me and ask me to make manual changes. Usually the process is automatic. I do this every time I sit down to work on an in-progress branch. This ensures that the changes I’m making are compatible with the latest version of Koha.

Once I have finished my work I check it and test it as carefully as I can. I make sure I’ve rebased against the very latest update in git, and I submit a patch. Submitting a patch takes the changes I’ve made and distills them down to a single text file which can be “applied” by the Release Manager or any other Koha developer to their own git installations. I also attach a copy of my patch to the bug report, if there is one, as I described in my bug reporting post. This is another way to get the patch out into the open where others can review it and test it.

After I’ve submitted a patch I rename the branch I was working on with “ps-” for “patch sent” and keep the branch until my patch is approved (fingers-crossed).

All this is on my computer in a virtual machine, so in my case I’m not being open as I might. If I had the resources to work on a real server, or if I kept my work on a service like GitHub I could share all these branches with everyone, from the time I first started working on it to the time my patch was submitted.

If some time has passed and I see that my patch from one of my “patch sent” branches hasn’t been approved I’ll switch to that branch and rebase: I’ll tell git to grab the most recent Koha commits and merge them with the changes in my patch. If not too much time has passed, or the files I changed haven’t been worked on by others the rebase will be successful and I’ll know I’m still on track. If not I might have to manually make changes to my original commit so that it fits in again with the work others have been doing. If manually merging was required, that tells me the Release Manager would have to do the same. I should consider resubmitting a revised version of my patch which can apply cleanly to the latest version.

Keeping all my “patch sent” branches intact until my patch has been approved is important to my workflow because it’s the easiest way for me to keep track of what has been approved and what hasn’t. I can see at a glance which patches of mine have not been approved. If it’s been a while, I might try to find out why not. If there was a problem with the patch I might be able to revise it to the RM’s satisfaction.

I can’t submit a patch and expect it to automatically work a month from now, a week from now, or even a day from now. I’m responsible for keeping up.

I’m not a git expert, and I’ve had lots of help and advice along the way to get me to this workflow. It works really well for me, and I hope it works as well from the point of view of our Release Manager and fellow developers.

Customizing the staff client login logo: Addendum

Thursday, July 22nd, 2010

I left something out of my post on Customizing the staff client login logo that I wanted to be sure to add: Once you’ve changed the logo you may want to change where it links to as well. By default it links to the Koha web site (or the deprecated version if your installation is an older one). We can use a little snippet of jQuery to change that link.

Using jQuery to change the URL to which the staff client logo links

$("#login h1 a").attr("href","http://www.myacpl.org");

That looks for an <a> tag inside an <h1> inside <div id="login">, which is specific enough to only catch the login form. This snippet goes inside your intranetuserjs system preference. Assuming the only thing you’ve added to intranetuserjs is the code I covered in the previous post, this would be the revised version:

$(document).ready(function(){
$("#login h1 a").attr("href","http://www.myacpl.org");
});
// ]]>

<!--
/* Custom styles here */
#login h1 a {
height:71px;
}
#login h1 {
background:url("http://www.myacpl.org/sites/all/themes/npl/logo.png") no-repeat scroll center top transparent;
}
-->
<script type="text/javascript">// <![CDATA[
// <![CDATA[

The revised version adds our new JavaScript snippet inside jQuery's standard "$(document).ready()" to be triggered upon page load.
]]>

Customizing the staff client login logo

Wednesday, July 21st, 2010

A Koha user (from Tanzania!) asked today on the Koha mailing list, “I need some help on how to customize the staff client login page/replace koha logo with a new one.” I haven’t heard this request before, so it’s a good opportunity to investigate.

If this were the OPAC we could use a system preference, opacsmallimage, to change the logo. We don’t have that option in the staff client, so we’ll have to see if we can use the available customization options to accomplish the same thing.

Our first stop, as usual, is FireBug. I opened up the staff client to examine how the default Koha logo is displayed on the login form. Using the Inspect tool I highlight the logo and view the results in the FireBug HTML inspector window:

FireBug details for the login logo anchor tag

The logo is constructed by nesting a link (“anchor”) tag (<a>) inside a top-level heading tag (<h1>). The above screenshot shows the HTML and style details for the <a>, here are the results for the <h1>:

FireBug details for the login logo heading tag

From this we can collect all the CSS information we need to control the display of the login logo:

#login h1 a {
border-bottom:medium none;
display:block;
height:74px;
text-indent:-1000px;
}

#login h1 {
background:url("../../img/koha-logo.gif") no-repeat scroll center top transparent;
margin-bottom:0.5em;
margin-top:0;
}

The staff client logo is displayed using an image-replacement technique similar to the one used to display the Koha logo in the OPAC. The style of the anchor tag sets an explicit height which matches the logo image, and it sets a negative text-indent property which moves the text contents of the tag off the screen. These two properties create a blank space inside the anchor tag in which to display the logo.

The style of the heading tag does the work of displaying the logo. The background property points to the URL of the logo image. In the default case this is an image file on the Koha server’s file system. The URL doesn’t have to be a relative one, though. It can be a full URL pointing to anywhere on the internet.

Customizing the logo CSS

In order to change the image we need to make very simple changes to two CSS properties:

  1. The background-image of the <h1> tag.
  2. The height of the <a> tag.

Let’s use as an example the logo on the Athens County Public Libraries site. I can right-click the image in Firefox and choose “View image” to find the details I need. The location bar shows the URL I need, and the title bar shows the dimensions of the image. I just need to note the height.

Since we only need to change two properties, our custom CSS is simpler than the original. We only need to specify the properties which we need to override:

#login h1 a {
height:71px;
}

#login h1 {
background:url("http://www.myacpl.org/sites/all/themes/npl/logo.png") no-repeat scroll center top transparent;
}

Applying the custom CSS

We’ve got our custom CSS, now what do we do with it? We don’t have an opacsmallimage preference for the staff client, and we don’t even have an option like OPACUserCSS. We do have a couple of options which will work.

intranetcolorstylesheet

If you have access to your Koha server’s file system you can add a stylesheet there and tell Koha to apply it in addition to the default staff client stylesheet. For example, you could create a new CSS file called custom.css and save it alongside staff-global.css and the other staff client CSS files. Then you can specify that filename, custom.css, in the intranetcolorstylesheet system preference.

intranetuserjs

If you don’t have access to your Koha server’s file system, there’s a way to insert custom CSS into your staff client pages, but it’s a bit of a hack. Lacking an “intranetusercss” preference we’re going to hijack an existing preference, intranetuserjs, to do the job for us.

When you insert custom JavaScript into the intranetuserjs preference, Koha detects this and adds it to the header of each staff client page, wrapped in the appropriate <script> tags:

<script type="text/javascript">
// <![CDATA[
/* BEGIN INTRANETUSERJS CONTENTS */
$(document).ready(function(){
alert("Hello world!");     });
/* END INTRANETUSERJS CONTENTS */
// ]]>
</script>

Since Koha automatically wraps the intranetuserjs content in opening and closing <script> tags, we’ll have to do a little bit of roundabout coding to embed a <style> block:

<script type="text/javascript">
//<![CDATA[
/* BEGIN INTRANETUSERJS CONTENTS */
// ]]>
</script>
<style type="text/css">
/* Custom styles here */
</style>
<script type="text/javascript">
// <![CDATA[
/* END INTRANETUSERJS CONTENTS */
// ]]>
</script>

Let’s run down what’s happening here. Lines 1 and 2 have been inserted automatically by Koha in order to properly embed the custom JavaScript it expects from the intranetuserjs preference. Line 3 is the first line of the contents of intranetuserjs. Lines 4 and 5 we have added manually to close the automatically-embedded <script> tag. With the script tag closed we can go on to add just about any HTML we want, really, but this is all inside the <head> of the HTML document, so few things would be valid.

Lines 6, 7, and 8 show the <style> tag we’re adding. This is where we’re going to put our custom CSS. Lines 9, 10, and 11 are the last lines of our custom intranetuserjs. Knowing that Koha wants to close the <script> tag it opened on line 1, we have to re-open a new <script> tag so that when Koha closes it we’ll have valid markup.

Putting it all together, here’s what the contents of our intranetuserjs preference will be:

// ]]>
</script>

<style type="text/css">
/* Custom styles here */
#login h1 a {
height:71px;
}
#login h1 {
background:url("http://www.myacpl.org/sites/all/themes/npl/logo.png") no-repeat scroll center top transparent;
}
</style>
<script type="text/javascript">
// <![CDATA[

If all goes well, this is what you should see when you log out and look at your login screen:

Customized login form

Note: I've published a quick addendum to this post which covers using jQuery to change the URL to which the logo links

Interface test: Placing a quick hold

Monday, July 19th, 2010

I was thinking about ease of use, and what we could to to improve the Koha OPAC from the point of view of the patrons, and the first thing my mind jumped to was the process of placing holds. For many patrons placing a hold is the goal of their visit to the OPAC. They’re looking for something they want, they find it in the catalog, and they want to get it. On Amazon.com the next step would be to buy it. In the OPAC they can place a hold.

What’s the first thing they see when they click one of those “place hold” links? Potentially this:

Place hold interface with all options turned on

I hate it. It’s an ugly table with too many options. True, you can turn off some of those options for a simpler process. Turn off the OPACItemHolds system preference to eliminate the option of choosing a specific copy. Turn off OPACAllowHoldDateInFuture to hide the Hold Starts on Date column. Turn off OPACDisplayRequestPriority to hide the hold request’s rank in the queue. Now it’s a little simpler:

With optional settings turned off

I’m still not crazy about it, and that’s why holds came to mind when I thought about what we could do to improve interactions in Koha. How can we make that interaction simpler? How about [almost] one-click “ordering?”

Click the "Place hold" link in the right sidebar

When you click the “Place hold” link you can see my idea demonstrated. Clicking the link would use JavaScript to display a simple form: Place hold? Yes/No. Embedded in the HTML would be all the required form fields, hidden, for placing a single hold with no options set, using the patron’s home library as the destination for the hold. If the patron wanted to set additional options they could click the “more options” link and be taken to the standard form.

How hard would this be to implement? It depends how far you want to take it. I could see  this being a JavaScript-only enhancement, assuming all the information we need is found on this page. In this version clicking the “Yes” button would submit the form to the same script the standard form does, but bypass the hold confirmation screen. The user would be redirected to their summary page showing current holds.

A fancier version would submit the form in the background. Clicking the “Yes” button would triggers a sequence of events:

  1. The hold would be submitted in the background.
  2. The interface would display some kind of “Working” indicator.
  3. Upon completion of the background submission, the interface would indicate success.

This is more complicated because the reserve script would have to be modified to work in new way. Error-handling would have to be incorporated so that if for some reason the hold couldn’t be processed the user could be warned. The advantage to this interaction is that the user never leaves the page, making it easier for them to find their way back to their original search–something which, incidentally, is also on our to-do list of ways to make things easier for the user.

Koha bugs workflow

Thursday, July 15th, 2010

As the Koha project has grown our workflow has evolved to meet the demands of a wider pool of developers. We’re better today at collaborating thanks to Git, our version control system. We’re better at communicating with each other through the Koha wiki and Koha’s Bugzilla database. It has helped a lot that we’ve worked to establish some consistent steps to handle both bugs and new features.

Filing a bug report

When you’ve discovered a bug in Koha the first stop is Bugzilla. Bugzilla is an open-source bug-tracking system developed by the folks who brought you Mozilla Firefox. We have our own installation of Bugzilla, generously hosted on a donated server. Anyone can file a bug, whether you’re a Koha developer or a Koha user.

If you find a bug the first step is to report it. Even a developer intending to immediately fix a bug should file a bug report. Doing so will mean others won’t duplicate your efforts in isolating the bug. When you file a bug report Bugzilla will offer to assign the bug by default to the person who has volunteered for bugs of that category. For instance, I am assigned by default any OPAC bugs. That doesn’t mean I’ll be able to fix them all, but I’m notified of each one and I can always reassign them if I find they’re beyond my capabilities.

You can also assign the bug a “severity” setting. If you’re not sure, use the “normal” severity for bugs, and “enhancement” if you’re asking for a feature to be added. There are brief descriptions of Bugzilla’s severity levels for review if you’re not sure how to classify something.

There are much more detailed bug reporting guidelines on the Koha Wiki.

Now the bug is in the database. With any luck, anyone else who discovers the same bug will search Bugzilla first before reporting it. If you find an existing report for a bug you’re experiencing, review it to make sure all the pertinent details are there. Feel free to leave comments expressing in specific terms how the bug is affecting your library’s workflow. Understanding the impact of a bug might help others prioritize efforts to fix it.

What happens to your bug?

What happens to a bug report after it gets filed? If the report was filed without any plans to address it (that is, if you’re not a developer filing the bug, with plans to fix it right away), nothing may happen for a while. Ideally the default assignee of the bug will review it and take some action if necessary: Correcting the bug’s severity, asking clarifying questions, reassigning if necessary. Unfortunately there is no guarantee that anything will happen with a bug report once it is filed. If no one else is affected by (or cares about) the bug, there won’t be any incentive to fix it. Developers are often working on projects assigned to them by their customers, and if they’re not getting paid to fix a particular bug they may not choose to work on it.

Your bug finds acceptance

If someone decides to work on your bug report, the first thing they should do is “accept” the bug in Bugzilla. If the bug isn’t already assigned to them, they edit the bug to assign it to themselves and update the status of the bug from “New,” the default for all new bugs, to “Assigned.” This tells anyone browsing Bugzilla that someone has agreed to work on the bug. Careful use of bug assignment and the use of the “assigned” status helps prevent duplication of effort: I won’t spend time working on a bug if I think someone else is actively working on it already.

If the developer who took on your bug discovers a fix for it, the next step is to submit a patch. A patch is a special file which can be understood by our version control system. Just as a patch on a piece of clothing is just a small piece of cloth to fix a hole, a software patch is just a small piece of code which can be applied to a whole file (or even multiple files). The patch includes instructions to add certain lines or remove certain lines of code.

The developer who has come up with a patch will do two things with it: First, the patch gets submitted to a special Koha mailing list for all Koha patches. Koha’s Release Manager monitors this list and evaluates each patch and evaluates it for inclusion in the next version of Koha. The second place the patch will go is into the Bugzilla bug report. The developer will attach the patch to the bug report so that others can see that a patch was submitted and maybe review the patch themselves. Since the patch file is easily understood by the Git version control system, anyone running an installation of Koha from a Git repository can apply patches and test bug fixes. A bug in Bugzilla which has has a patch filed for it will be marked with a special priority, “PATCH-sent.”

Your bug found acceptance, but what about the patch?

Galen Charlton, the Koha 3.2 Release Manager, has the task of evaluating each patch that is submitted for inclusion in 3.2. He reviews patches, tests them, and approves them if he finds them worthwhile. If a patch refers to a specific bug report, Galen will usually also update the bug report with a note that the patch was “pushed.” If a patch doesn’t seem to work, or if it includes mistakes which should be corrected before inclusion he will let the patch submitter know so they can rework the patch.

Right now we’re getting so close to the release of 3.2 that we’re under both a “feature freeze” and a “string freeze.” A feature freeze means that no new features are being accepted for inclusion in 3.2: only bug-fixes. Rejecting new features at this point in the process reduces the possibility that major new bugs will be introduced. The “string freeze” means that patches submitted for inclusion in 3.2 should no include changes to any text in the interface. These text strings must be painstakingly translated. The Koha translation-tracking system Pootle lists 63 different languages which have at least begun to have translations done. Putting on a string freeze means that translators preparing for the release of 3.2 will have a fixed target.

The patch for your bug made the cut. It’s going into 3.2!

You reported the bug, so your job isn’t done yet. It’s time to test the fix. Update your test installation and try to follow the same steps that led to the bug before. Is the bug still there, or is something still left undone? Then update the bug and explain what you found.

On the other hand, if you find the bug has been fixed then you can mark it as such in Bugzilla. Change the status of the bug from “Assigned” to “Resolved (Fixed).”

Congratulations, and welcome to the team.

Nearing Koha 3.2

Thursday, July 8th, 2010

It has been six months since my Preparing for Koha 3.2 post! It’s been a while, but a lot of progress has been made. If my Bugzilla query is correct, we’ve resolved almost 200 bug reports in that time. Over 1000 commits have been made to Koha’s code repository for version 3.2. We’ve released two Alphas and a Beta. As of today we still have some “blocker” bugs, meaning bugs which are so severe that they must be fixed before an official release.

Yesterday we had one of our monthly Koha General Meetings on the #koha IRC channel and our 3.2 Release Manager Galen Charlton stuck his neck out and made this promise: “In no event will general release happen later than the general meeting next month.”

Let the final sprint begin!

Bean counting

Friday, April 30th, 2010

One of the many things I love about Koha is the easy access I have to statistics. I’m a do-it-yourselfer, so I seldom use Koha’s built-in reports. Instead I go directly to the source: Koha’s statistics table.

Field Type Null Key Default Extra
datetime datetime YES MUL NULL
branch varchar(10) YES NULL
proccode varchar(4) YES NULL
value double(16,4) YES NULL
type varchar(16) YES NULL
other mediumtext YES NULL
usercode varchar(10) YES NULL
itemnumber int(11) YES NULL
itemtype varchar(10) YES NULL
borrowernumber int(11) YES NULL
associatedborrower int(11) YES NULL

The statistics table is long-term memory storage for circulation transactions: checkouts, check-ins, renewals, and payments. The kind of reports we depend on most are circulation reports, so I usually focus on checkouts and renewals.

Just a few of these fields are relevant to most of my circulation reports:

  • datetime stores the date and time of the transaction.
  • branch stores the three-letter code for the branch where the transaction took place.
  • type records whether the statistic is a checkout (“issue”), check-in (“return”), renewal (“renew”), payment (“payment”), or write-off (“writeoff”).
  • itemnumber, which records the id of the item in Koha’s catalog.

Using these pieces we can put together a query which counts circulations per branch for a given month:

SELECT branch,count(*) FROM statistics WHERE year(datetime) = 2009 AND month(datetime) = 12 AND (type = 'issue' OR type = 'renew') GROUP BY branch ORDER BY branch;
branch count(*)
ALB 2762
APL 21475
COV 1746
CPL 616
GPL 2725
NPL 5475
PPL 5391

7 rows in set (37.16 sec)

One important thing to note about the results of that query: It took over thirty-seven seconds to execute. That’s ages in MySQL terms, and a cause for caution. We’ve been using Koha since 2003, so our statistics table is huge: almost nine million rows. For that reason I don’t run my statistics queries directly on our production Koha server. I back up the statistics table to a separate database where it won’t interfere with the performance of our Koha operations.

Getting fancy

Querying MySQL directly can get you many of the numbers you want, but if you want to aggregate data and manipulate it in fun ways you have to add a scripting layer to the process. For Koha that’s Perl, for me it’s PHP. The end result that I want to share is a report of circulations per month for all branches. This report shows not just the raw numbers from Koha but also formats them as a graph using Google’s Chart API.

This was just a quick look at the kind of work I’ve been doing recently. There are a lot of pieces of the puzzle that I’ve glossed over. I hope at the very least it’s an interesting glimpse of what is possible when you have easy access to your data and the tools to manipulate it.

Koha-Community.org

Tuesday, March 2nd, 2010

I’ve made some changes to the links in the “Blogroll” over in the right column. I’ve taken out Koha.org and added an important new one: Koha-Community.org.

A little history

Koha.org has been around since the creation of Koha. It was initially owned and managed by Katipo Communications, the company which developed Koha 1.0 for the Horowhenua Library Trust. When Katipo’s Koha assets were acquired by LibLime, possession and control of the domain passed into LibLime’s hands. LibLime oversaw significant improvements to the site and appeared to have good intentions to improve access to authors from around the community.

Complaints

However, in recent months LibLime’s interest in conscientious stewardship of the site seems to have waned. Information on the site is, little by little, becoming out of date. The home page lists Koha 3.0.4 as the latest stable release, when Koha 3.0.5 was released two months ago now. It’s even worse on the “Download” page, which lists Koha 3.0.2 from June 4 2009 as the latest stable release. This kind of misinformation is irresponsible.

Besides providing information about Koha software, the site also provides users with information about commercial options for Koha support and hosting through its “Pay for Support” page. For months new companies offering Koha hosting and support have waited for their information to appear on the site. The submission form companies are asked to use is broken.

Remedies

The Koha community has attempted to communicate with LibLime about the situation without success. The Koha community has nominated the Horowhenua Library Trust to act as an independent steward of Koha-related assets like the Koha.org and the Koha trademark. We have proposed to LibLime that, given their lack of care and interest in Koha.org, transfer the domain and its management to HLT and let the Koha community take back control. LibLime has not responded to these requests.

The community was left with no choice:  we had to create a new home for the Koha project. We can no longer depend on the good will of LibLime. Koha-community.org came together quickly and beautifully thanks to all involved. Thanks are owed especially to Liz at the Northeast Kansas Library System for all her hard work.

If you want to share a link to the real open source Koha, please use http://koha-community.org

Custom printed overdue postcards

Monday, February 22nd, 2010

My library has a long and complicated history of how to deal with overdue notifications. We’ve tried a few different forms of printed notices, and at one time we even tried to telephone each patron with overdues. After we switched to Koha we got a new option: sending overdue notices via email. Koha didn’t have a built-in notification system at the time, but the open nature of the application meant we could create our own scripted process to query the Koha database and get the information we needed.

The script, written by our director at the time, Stephen Hedges, queried the Koha database for patrons with overdues and did a few things at once with the results of this query:

  1. Send overdue notices via email.
  2. Create a file of overdues data for patrons without email.
  3. Restrict (“debar”) patrons with items overdue for more than 30 days.

In Koha 3, some of this work can be taken over by new built-in notification functionality. With the Overdue notice/status triggers feature we can define when overdue notices should be sent to patrons and when patrons should be restricted for their overdues (taking care of #3 above).

The drawback to Koha 3′s Notices feature is that it doesn’t give you much help when it comes to printed overdue notices. Koha will send an email notice to any patron who has an email address in their patron record (taking care of  #1 above). For patrons without email, Koha collects all of their overdue notices into a single email which is sent to the Koha administrator. Presumably the idea is that the messages can be printed out and mailed by hand.

Unfortunately this won’t work for us: We don’t want to send letters. It’s too much manual labor to stuff envelopes and stick stamps.  We want to send post cards. They’re cheaper. Of course for privacy reasons (not to mention space constraints) we can’t print out a list of a patron’s overdue items on a postcard. We want to send them a generic reminder which includes our web address (for online renewals) and phone numbers to our branches. So even with improvements in Koha 3 we need to do some work to take care of #2 from the list of tasks performed by the old overdues script.

Let’s take a look at how the old script worked. It began by performing this query:

SELECT issues.borrowernumber, firstname, surname, streetaddress, physstreet, city, zipcode, emailaddress
FROM issues, borrowers
WHERE returndate IS NULL
AND TO_DAYS( NOW( ) ) - TO_DAYS( date_due )
BETWEEN 8 AND 30
AND issues.borrowernumber = borrowers.borrowernumber
AND gonenoaddress < 1
AND borrowers.categorycode != 'HB' ORDER BY issues.borrowernumber

It limited the query to items which were between 8 and 30 days overdue, where the “gonenoaddress” flag was unset (less than one, meaning in this case zero), and where the patron didn’t have the ‘HB’ categorycode (our “homebound” category for home-delivery patrons).

As far as printed notices are concerned, the purpose of the old script was to create a CSV file containing the name and address of each patron with overdues.  Since we’re going to send a non-personalized postcard to each patron, we don’t want the output to include any other personal details. Here’s what the results looked like:

“name” “address1″ “address2″ “city” “zipcode”
“John Smith” “1 Main Street” “” “Nelsonville OH” “45764″

In updating this for Koha 3 we can make that query a little bit more portable by having it check whether the patron in question has a category that requires overdue notices:

SELECT issues.borrowernumber, borrowers.firstname, borrowers.surname, borrowers.address, borrowers.address2, borrowers.city, borrowers.zipcode
FROM issues, borrowers, categories
WHERE issues.returndate IS NULL
AND TO_DAYS( NOW( ) ) - TO_DAYS( issues.date_due )
BETWEEN 8 AND 30
AND issues.borrowernumber = borrowers.borrowernumber
AND borrowers.gonenoaddress < 1
AND borrowers.categorycode = categories.categorycode AND categories.overduenoticerequired = 1
AND borrowers.email IS NOT NULL
AND borrowers.email != ''
ORDER BY borrowers.surname,borrowers.firstname

I’ve added a check that categories.overduenoticerequired is 1, which eliminates the need to hard-code the ‘HB’ patron category. I’ve also added a check to make sure the patron email address field isn’t empty (the old script performed that check elsewhere).

Since I’m more comfortable in PHP than Perl, I use a PHP script to query MySQL and format the results to be saved as a CSV file just like the old script did.

Taking it to the Post Office

We’ve successfully pulled the data we need. What next? We use an online service called Click2Mail, a “trusted and accredited partner to the United States Postal Service.” Click2Mail allows us to define a custom postcard template with our own personalized message. We can then upload our CSV file containing the name and address information for each patron with overdues. The service parses that CSV file, prints one postcard for each patron, and delivers it to the USPS for delivery. Click2Mail even checks your mailing addresses for possible errors and lets you review them.

Their cost estimator puts the cost of sending 100 single-sided postcards at about $30. Considering the time, effort, and cost of stuffing and stamping 100 letters, Click2Mail seems to be a great value.


Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported.