Budget Screen

I've just uploaded a new release of the Redmine Budget plugin. The Budget plugin is a plugin for Redmine to manage the set of deliverables for each project, automatically calculating key performance indicators. This is a long awaited release that will fix many of the outstanding bugs and incompatibilities that have cropped up.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

If you are currently working on a Redmine plugin and need help or have an idea for a plugin you would like developed, please contact me. My company, Little Stream Software, specializes in the development of custom Redmine features and Redmine plugins.

Eric

Tagged: open source plugin redmine redmine plugins ruby on rails

I've got a new Redmine plugin I'm Open Sourcing, the Redmine Rate plugin. This plugin will store billable rates for Users and will relate the amount of time worked to a specific amount. This was extracted out of the Budget plugin, once it was discovered that tracking historic rates was needed. Now if someone's billable rate changes, the plugin will adapt to that change without affecting past transactions.

User rate history

Features

  • Track rates for a user based on
    • Date Rate came into effect and
    • the Project
  • Store historic rate amounts
  • Lock rates to preserve historic calculations
  • Rate.for API for other plugins
  • Integration with the Billing plugin
  • Integration with the Budget plugin

Getting the plugin

A copy of the plugin can be downloaded from Little Stream Software or from GitHub

Installation and Setup

This plugin will convert existing data in the Budget or Billing plugins. To prevent data loss, I recommend you read the README that is included with the release.

Project member rates

Usage

There are a couple of ways to use this plugin:

Enter new rate for a project

There are two ways to set rates for a Member of a Project.

  1. Browse to the Project Settings page
  2. Select the Members tab
  3. Enter the rate for the Member and click the set Rate

Alternatively, Rates can be set in the User Administration panel

  1. Browse to the Administration panel
  2. Select Users
  3. Select the specific user to add a rate for
  4. Select the Membership tab and enter a rate for each project
  5. Or, select the Rate History and enter a new rate in the form

Enter default rate for a user

A default rate is a user's Rate that doesn't correspond to a specific project. It can be set in the User Administration panel:

  1. Browse to the Administration panel
  2. Select Users
  3. Select the specific user to add a rate for
  4. Select the Rate History and enter a new rate in the form, keep the Project field set to Default Rate.

Lock a Rate

Currently this feature is only available through the Rate API. A Rate will become locked once a valid TimeEntry is assigned to the Rate. This is used to make sure historical amounts are not changed.

User rates per project

License

This plugin is licensed under the GNU GPL v2.

Project help

If you need help you can contact me or create an issue in the Bug Tracker.

Thanks

I would like to thank Shane and Peter, Inc for sponsoring this plugin. If you find it useful, send your appreciation his way.

If you are currently working on a Redmine plugin and need help or have an idea for a plugin you would like developed, please contact me. My company, Little Stream Software, specializes in the development of custom Redmine features and Redmine plugins.

Eric

Tagged: open source redmine redmine plugins

I've been writing Redmine plugins since 2007 and one thing that stumped me was how to add new methods to Redmine's core classes and have them working in development. The standard Ruby on Rails way of including a module into the class works great except in development mode. Thanks to Thomas Löber, I found a way to overcome this error by making Ruby on Rails reload specific plugin classes.

Patching the core for fun and profit

I'm going to create a quick plugin that shows an example. Lets say you have a method called moo that you want to add to the Issue class. The standard Ruby on Rails plugin way would be to create a module and call Issue.send(:include).

# lib/my_moo_patch.rb
module MyMooPatch
  def self.included(base)
    base.send(:include, InstanceMethods)
  end

  module InstanceMethods
    def moo
      logger.info 'moo'
    end
  end    
end

# init.rb
require 'my_moo_patch'
Issue.send(:include, MyMooPatch)

This is a pretty standard case and would be used anytime your plugin needs to relate to the core classes. To illustrate this example and some errors that are caused, I added a call to @issue.moo on the Issue show page. Typically you would use the Redmine Hooks to have Redmine run your plugin's code.

Running the code

Running in the production environment, everything works fine:

Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 09:57:41) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}
moo
Rendering template within layouts/base
Rendering issues/show.rhtml
Completed in 1037ms (View: 873, DB: 31) | 200 OK [http://localhost/issues/1765]


Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 09:57:44) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}
moo
Rendering template within layouts/base
Rendering issues/show.rhtml
Completed in 257ms (View: 173, DB: 17) | 200 OK [http://localhost/issues/1765]

But in development, the first request will work but the second request will now throw an exception:

# First request
Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 09:59:32) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}
moo
Rendering template within layouts/base
Rendering issues/show.rhtml
Completed in 1285ms (View: 990, DB: 24) | 200 OK [http://localhost/issues/1765]

# Second request
Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 09:59:36) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}

NoMethodError (undefined method `moo' for #<Issue:0xb4ab3d94>):
    /vendor/rails/activerecord/lib/active_record/attribute_methods.rb:260:in `method_missing'
    /app/controllers/issues_controller.rb:98:in `show'
    <<snip>>

Rendering /home/edavis/dev/redmine/redmine-core/vendor/rails/actionpack/lib/action_controller/templates/rescues/layout.erb (internal_server_error)

Debugging the error

The NoMethodError is a standard error thrown by Ruby when a class doesn't have a method defined. But we defined Issue#moo in our plugin, so why is it not found? Lets take a look at what's happening in the Ruby debugger:

# First request
>> MyMooPatch.object_id
=> -621509448
>> @issue.class.object_id
=> -621657688
>> pp @issue.class.included_modules
[MyMooPatch::InstanceMethods,
 MyMooPatch,
 Redmine::Acts::ActivityProvider::InstanceMethods,
 Redmine::Acts::Event::InstanceMethods,
 Redmine::Acts::Searchable::InstanceMethods,
 Redmine::Acts::Watchable::InstanceMethods,
 Redmine::Acts::Customizable::InstanceMethods,
 Redmine::Acts::Attachable::InstanceMethods,
 Redmine::I18n,
 Kernel]
=> nil
>> @issue.class.included_modules.include?(MyMooPatch)
=> true

Nothing out of the ordinary here. Issue has MyMooPatch included and the request processes successfully.

# Second request
>> MyMooPatch.object_id
=> -621509448               # Same id as above
>> @issue.class.object_id
=> -630808728               # Different id from above.
>> pp @issue.class.included_modules
[Redmine::Acts::ActivityProvider::InstanceMethods,
 Redmine::Acts::Event::InstanceMethods,
 Redmine::Acts::Searchable::InstanceMethods,
 Redmine::Acts::Watchable::InstanceMethods,
 Redmine::Acts::Customizable::InstanceMethods,
 Redmine::Acts::Attachable::InstanceMethods,
 Redmine::I18n,
 Kernel]
=> nil
>> @issue.class.included_modules.include?(MyMooPatch)
=> false

But on the second request we notice something wrong. Issue no longer has MyMooPatch included and it also has a different class id from the last request. This means that something created a new Issue class object that is used instead of the original one. In development mode, Ruby on Rails reloads classes after each request so on the second request the Issue class was reloaded but our patch wasn't applied.

Wrapping our monkey-patch in a callback

Fortunately, Ruby on Rails provides a callback method we can use to add our module back, after a class is reloaded. It's called Dispatcher.to_prepare.

Add a preparation callback. Preparation callbacks are run before every request in development mode, and before the first request in production mode. (From: rails/actionpack/lib/action_controller/dispatcher.rb)

So we will need to change the way out module is included in Issue. Instead of just using the straight send, we need to wrap it in the Dispatcher.to_prepare method:

require 'dispatcher'
require 'my_moo_patch'

Dispatcher.to_prepare do
  Issue.send(:include, MyMooPatch)
end

Now if we restart the Ruby on Rails server in development mode, all the requests should be successful.

Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 10:42:58) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}
moo
Rendering template within layouts/base
Rendering issues/show.rhtml
Completed in 1382ms (View: 1056, DB: 26) | 200 OK [http://localhost/issues/1765]


Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 10:43:21) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}
moo
Rendering template within layouts/base
Rendering issues/show.rhtml
Completed in 1266ms (View: 951, DB: 26) | 200 OK [http://localhost/issues/1765]


Processing IssuesController#show (for 127.0.0.1 at 2009-04-13 10:43:25) [GET]
  Parameters: {"action"=>"show", "id"=>"1765", "controller"=>"issues"}
moo
Rendering template within layouts/base
Rendering issues/show.rhtml
Completed in 1210ms (View: 901, DB: 25) | 200 OK [http://localhost/issues/1765]

Success, our Issue is now mooing!

Summary

So if you write a Ruby on Rails or Redmine plugin that needs to patch the core, you should wrap your patches in Dispatcher.to_prepare so that they will work in development mode. I'll be converting all my plugins to use this pattern soon. If you would like to develop a patch for one yourself, fork one of my plugins on GitHub and sent me a pull request.

Eric

Tagged: plugins redmine ruby ruby on rails

Redmine System Notification screenshot

I've just uploaded the latest release of the Redmine System Notification plugin. This is a plugin that will let Administrators send emails to a list of users to let them know of important events (e.g. downtime, upgrades). This release includes some new features for composing the notification, translations, and support for the latest stable and development versions of Redmine.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

Eric

Tagged: open source plugin redmine redmine plugins ruby on rails

Screenshot

After a long wait, I've just uploaded a new release of the Redmine Customer plugin. This is a bug fix and translation release that should support the released version of Redmine as well as the latest trunk version.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

What's next

The next release should have some new features including the start of a CRM type system. If you have an idea for one, leave a comment here or open a feature request.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

Eric

Tagged: plugin redmine ruby on rails

Bulk Time Entry screenshot

I'm happy to announce that I've just uploaded a new release of the Redmine Bulk Time Entry plugin. This is a bug fix release that should support the released version of Redmine as well as the latest trunk version.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

What's next

The next release should have a couple of new features, including some User Interface updates to make entering time even faster. If you have an idea for one, leave a comment here or open a feature request.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

Eric

Tagged: open source redmine redmine plugins

Stuff To Do Screen

I've just uploaded a new release of the Redmine Stuff To Do plugin. This is a bug fix release that should support the released version of Redmine as well as the latest trunk version.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

What's next

The next release should have a couple of new features. If you have an idea for one, leave a comment here or open a feature request.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

Eric

Tagged: open source redmine redmine plugins

Question on an issue

I've just uploaded a new release of the Redmine Question plugin. This is a bug fix release that should support the released version of Redmine as well as the latest trunk version.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

What's next

The next release should have a couple of new features. If you have an idea for one, leave a comment here or open a feature request.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

Eric

Tagged: open source redmine redmine plugins

I've just uploaded a new release of the Redmine Timesheet plugin. This release has a couple of new features, a few bug fixes, and several translation updates.

Download

The plugin can be download from the Little Stream Software project or from GitHub.

Changes

You can see more details on the Changelog and Roadmap pages.

What's next

Michele Franzin has been working on a fork of the Timesheet plugin that has a really nice calendar view and summary features. Since these didn't make it into 0.5.0, I'd like to pull them into the 0.6.0 release.

Help

If you need help, my Redmine bug tracker is open to the public and you are welcome to ask for help there.

Eric

Tagged: open source redmine redmine plugins

I had a question emailed to me about Redmine and I thought it would make a useful blog post:

If I wanted to add a link example.com to the top menu how would I do that?

I've seen this asked several times and most responses are to modify Redmine's source. While this will work, it will make Redmine upgrades harder. The best solution is to create a small Redmine plugin and drop it into the vendor/plugins directory. Only one Ruby file is needed, plus any language translations.

# init.rb
Redmine::Plugin.register :redmine_static_link do
  name 'Redmine link'
  author 'Eric Davis of Little Stream Software'
  description 'Shows a link on the top menu'

  version '0.1.0'

  menu :top_menu, :example_link, "http://www.example.com"
end

You can see that all the init.rb does is to register a new plugin and add a :top_menu link to http://www.example.com. Once Redmine is reloaded, you should see the link on the top menu.

Static link in Redmines top menu

I've uploaded the full plugin, along with English language translations. Go ahead and download it and change the link url to what you need.

If you have any other Redmine or Redmine plugin questions that you would like me to write about, please ask them on my User Voice.

Eric

Tagged: open source redmine redmine plugins