Kimai Forum
Kimai - Time Tracking Community
September 08, 2010, 11:23:43 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Kimai v 0.9.0.1082 final ready for download
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: Redmine Issue Import script  (Read 341 times)
redfox
Kimai Newbie
*
Posts: 2


View Profile
« on: July 07, 2010, 06:14:03 PM »

Hey Guys,

i just spent 2 hours yesterday to get my excel timesheets formatted properly, and that was my sign to find something new. I quickly found kimai and was impressed. The frontend is awesome, super usability!

But the euphory shrunk quickly. I needed three critical features:
  • Grouping data. For the export, i need the hours to be grouped by tasks
  • Own export interfaces. I need the data in an xml format to import into grand total (mac)
  • (from the category 'would be awesome to have'): Automatically import redmine projects/issues into kimai as projects/tasks

Since i really like kimai and being a php developer, i tried to implement them for myself. But (please allow these few words of critic) the code is really awful:
  • There is no developer documentation. You need to hang on it for yourself.
  • The code does NOT document itself. Yes, there are some phpdoc tags, but the variable names are like 3 chars and underscores and stuff, nobody ever will find out what a function or variable is used for without a *huge* amount of time
  • The coding style is not the best. No spaces between operators, bad naming style (also in the templates/css/js), curly brackets only when there are really needed, no (or very less) OOP, The database design (and naming! Hey, 3 char table names, are you serious Huh ), ...
When i figured out that a critical function, which was needed by the export module and which i needed to modify, is declared in a core file, i resigned.

But enouth with the critics, the good thing is: i still like kimai Wink Theres is nothing to compare out there and it has a big potential. If you restyle your code i may contribute some, but at the moment i just needed to find a solution for my problems.

So i thought a bit and chose the following:
The redmine linking doesnt absolutly need to be implemented into kimai. Since i could figure out the database tables (yes, trial and error  Roll Eyes) i wrote a little perl script which access the redmine export function and imports the tasks directly into the kimai database. This works really well for me, and im very happy with it now.

The export problem can also be solved via direct database access. When i finish this script, i will publish it here too.

The script:
Code:
#! /usr/bin/perl

use warnings;
use strict;
use DBI;

# the url to your redmine page which shows the issues (can be a project page, or the "all issues" page)
my $redmineUrl = "https://your.redmine.url/projects/project_name/";
# the redmine autologin cookie, you need this for script access to redmine
my $autoLogin = "f41e8d8a8c42d17551774579b867d636856aae97";
# your redmine filter id
my $filterID = 13;
# the kimai group id which the task should be assigned to (1 is mostly the admin group)
my $groupID = 1;
# database credentials from kimai
my ($database, $username, $password) = ("database", "username", "password");

qx#rm issues.csv#;
qx#wget -q --no-check-certificate --header="Cookie: autologin=$autoLogin" $redmineUrl/issues.csv?query_id=$filterID -O issues.csv#;

if(! -f 'issues.csv') {
  die("Failed to download issues");
}

my %projectHash;
my $dbh = DBI->connect("DBI:mysql:$database", $username, $password)
  or die("Cannot establish connection to mysql server: $DBI::errstr\n");

# Get all project from database
my $sth = $dbh->prepare("SELECT `pct_ID`, `pct_name` FROM `pct`");
$sth->execute();
while(my @row = $sth->fetchrow_array()) {
  $projectHash{$row[1]} = $row[0];
}

# Create filter if not exists
if(! -f 'filter.txt') {
  qx#touch filter.txt#;
}

# Add filters to an array
my @filter;
open FILTER, '<', 'filter.txt';
while(<FILTER>) {
  push @filter, $_;
}
close FILTER;

open FILTER, '+>', 'filter.txt';

open FILE, '<', "issues.csv";
while(<FILE>) {
  # skip the first line in export file
  next if $_ =~ /^#;/;


  # the whole filter. Gets the row you want, its *very* likely that you need to modifcy this for your export rows. Just add parantesis around the row - .*? - which you need
  # the rows in the exportfile depend on the filter you set up in redmine
  # for example, my export rows look like this (german version of redmine but i think you get the point):

  # #;Status;Projekt;Tracker;Priorität;Thema;Zugewiesen an;Kategorie;Zielversion;Autor;Beginn;Abgabedatum;% erledigt;Geschätzter Aufwand;Angelegt;Aktualisiert;Angebot in h;Auftrag erhalten;Beschreibung
  if(/^(.*?);.*?;(.*?);.*?;(.*?);(.*?);.*?;(.*?);.*?;(.*?);.*?;.*?;.*?;.*?;(.*?)/) {
    my ($issue, $project, $priority, $topic, $category, $author, $creationDate) = ($1, $2, $3, $4, $5, $6, $7);
    # skip if already imported
    print "skipping $issue\n" and next if grep /$issue/, @filter;

    # strip formatting quote which are used by redmine and replace them by plaintext quotes
    $topic =~ s/(^"|"$)//g;
    $topic =~ s/""/"/g;

    # only import if the project of the issue exists as a project in kimai (needs to be exact the same spelling!)
    my $pctId;
    if($pctId = $projectHash{$project} or $pctId = $projectHash{$category}) {


      # insert task into the task table
      my $query = "INSERT INTO `evt` SET `evt_name` = CONCAT('#', ?, ': ', ?), `evt_comment` = CONCAT('Created By ', ?, ', Priority: ', ?)";
      $sth = $dbh->prepare($query);
      $sth->execute($issue, $topic, $author, $priority) or die("failed to execute query: $query\n");

      # assign tasks to a group
      $query = "INSERT INTO `grp_evt` SET `grp_ID` = ?, `evt_ID` = ?";
      my $insertId = $dbh->last_insert_id(undef, undef, undef, undef);
      $sth = $dbh->prepare($query);
      $sth->execute($groupID, $insertId) or die("failed to execute query: $query\n");

      # finally assign tasks to a project
      $query = "INSERT INTO `pct_evt` SET `evt_ID` = ?, `pct_ID` = ?";
      $sth = $dbh->prepare($query);
      $sth->execute($insertId, $pctId) or die("failed to execute query: $query\n");

      # add the issue to our filter file for not having duplicates
      print FILTER "$issue\n";
    }
  }
}
close FILTER;
close FILE;

You can add in in a cronjob like this:

Code:
*/15 * * * *      /usr/bin/perl /home/yourname/bin/redmineSync.pl | tee -a /var/log/redminesync.log &> /dev/null

Which will check for new issues every 15 minutes.

A few words you should note:
At first, you need to create the projects (and, if applies, customers) for yourself, this is not covered by this script. The Project names need to be the exact same spelling as in redmine or the script failes to import issues. You can also add redmine categories as projects, since i use redmine this way.

For example you have a redmine Project "Onlineshop" and the categories "Programming", "Accounting", "Support". Then you may add "Onlineshop", "Programming", "Accounting" and "Support" as projects into kimai and assign them to your customer (if applies). Beware the case sensitivity!

The next thing are the filter rows. You really may need to adjust them, because filters can be freely assembled in redmine. Go to your issue page of redmine where the issues are which you want to import. Now click on "CSV" at the bottom of the page and open the file. You open the file and look at the first lines. These are the rows which are needed to adjust for your needs. Go to line 62 in the script and add/remove parantesis for the ".*?" which stands for one row of the file. The needed rows are printed in the next line: "issue, project, priority..." (ok, not all of them are needed, but can be used eg. in the comment field). Adjust the parantesis that it fits the order of the variable names of the next line... $issue is the first (.*?), $project the next one, and so on.

Ah, and of course, the script works as well on windows if you download wget.exe, place it in the script dir and have perl installed.

Sorry for the inconvenience but i quickly hacked that script and added no ui or something. Maybe i'll add it later, if i get response. I dont even know if someone will ever use it but i'll post it anyway Wink

So thanks kimai team and keep up the good work (and please, consider a style rewrite of your code =) )

Best regards,
Thomas
« Last Edit: July 07, 2010, 06:17:27 PM by redfox » Logged
ServiusHack
Global Moderator
Kimai Guru
*****
Posts: 609


View Profile
« Reply #1 on: July 07, 2010, 10:37:20 PM »

Hi Thomas,

nice script, you wrote there. Perhaps I will need something like this in the future as well.

Of course I have to comment on your critics now. Smiley

When I discovered Kimai and started to develop for it the code was in that state. But I didn't find it that bad. Reason might be that I'm German and the creator of Kimai is German as well, so some of those 3 letter things made more sense to me (like knd = Kunde = Customer).

In the last months more and more requests were made by users and my focus was on implementing them, of course. As my time is limited, I didn't get to redesign or even just comment the code.

Still, your points are valid and I should improve the code. But as that takes a look of time which doesn't really benefit any user of Kimai I preferred investing my time in new features. Now, after you wrote that post, I think I will put that Todo higher up in my list. It is important to have clean code and for an open source project the code should invite poeple to develop and not prevent them from doing so.

Best Regards,
Severin Leonhardt
Logged
redfox
Kimai Newbie
*
Posts: 2


View Profile
« Reply #2 on: July 08, 2010, 01:06:01 AM »

Hi Serverin,

thanks for your reply. Please don't get me wrong, i don't want you guys to rewrite the whole app. But a developer doc would be a good start and maybe making the code a bit more readable. And yes, i'm german too and i can partly understand "knd", but "evt" for example for "tasks/tätigkeit"? Well, nevermind. Just my two cents Smiley

A little word for the sync script for those who don't know it:
Redmine is a fully featured web application for project management. It also includes a very good issuetracker which i use with my customers. They create an issue, i accept and solve it, they check it back, and so forth. So my time tracking is based on this issue ids. In past, i used excel sheets to format and calculate the times, but it's too time expensive.
Now i only click on that issue in kimai, start the counter and export the whole data at the end. Thanks kimai, i love you!  Grin
« Last Edit: July 08, 2010, 01:11:06 AM by redfox » Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by SMF | Simple Machines LLC