Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Note を拡張して作業時間を記録できるように #5

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/Redmine/Chan.pm
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use Class::Accessor::Lite (
recipe
issue_fields
status_commands
activity_commands
custom_field_prefix
) ],
);
Expand All @@ -46,6 +47,7 @@ sub init {
$api->api_key($self->redmine_api_key);
$api->issue_fields($self->issue_fields);
$api->status_commands($self->status_commands);
$api->activity_commands($self->activity_commands);
$api->custom_field_prefix($self->custom_field_prefix);
$api->reload;
$self->api($api);
Expand Down
68 changes: 65 additions & 3 deletions lib/Redmine/Chan/API.pm
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ my @keys;
BEGIN { @keys = qw/ users issue_statuses trackers / }

use Class::Accessor::Lite (
rw => [ qw(api_key issue_fields status_commands who custom_field_prefix), map { '_'.$_, $_.'_regexp_hash' } @keys ],
rw => [ qw(api_key issue_fields status_commands activity_commands activity_commands_mixed who custom_field_prefix), map { '_'.$_, $_.'_regexp_hash' } @keys ],
);

__PACKAGE__->config(
Expand Down Expand Up @@ -83,6 +83,20 @@ sub reload {
}
$self->$regexp($hash);
}

{
# activity の定義を取得して,既存設定に混ぜ込む
my $uri = 'enumerations/TimeEntryActivities.json';
my $data = (eval {
$self->get( $uri => { key => $self->api_key_as($self->who) } )->parse_response;
} || +{})->{time_entry_activities} || [];
my %hash = %{$self->activity_commands || +{}};
for my $i (@$data) {
my ($id, $name) = @$i{qw/id name/};
$hash{$id} = [@{$hash{$id} || []}, $name];
}
$self->activity_commands_mixed(\%hash);
}
}

sub issue {
Expand All @@ -97,8 +111,9 @@ sub issue_detail {
my $issue = $self->issue(shift) or return;
my $fiedls = $self->issue_fields || [qw/subject assigned_to status/];
my $subject = join ' ', map {"[$_]"} grep {$_} map {
/^\d+$/ ? $issue->{custom_fields}->[$_]->{value}
: ref($issue->{$_}) ? $issue->{$_}->{name} : $issue->{$_}
if (/^\d+$/) { $issue->{custom_fields}->[$_]->{value} }
elsif ( $_ eq 'spent_hours' ) { sprintf '%.2f', $issue->{$_} }
else { ref($issue->{$_}) ? $issue->{$_}->{name} : $issue->{$_} }
} @$fiedls;
my $uri = $self->base_url->clone;
my $authority = $uri->authority;
Expand Down Expand Up @@ -180,6 +195,25 @@ sub detect_custom_field_values {
return ($custom_field_values, $msg);
}

my %activity_id_cache;
sub detect_activity_id {
my $self = shift;
my $act = shift;
my $hash = $self->activity_commands_mixed;
my $activity_id = $activity_id_cache{$act};
return $activity_id if $activity_id;
for my $id (%$hash) {
my @acts = map decode_utf8($_), @{$hash->{$id} || []};
my $re = "^(?:@{[join '|', @acts]})\$";
if ($act =~ /$re/) {
$activity_id = $id;
$activity_id_cache{$act} = $id;
last;
}
}
return ($activity_id, $act);
}

sub create_issue {
my ($self, $msg, $project_id) = @_;
my $issue = {};
Expand Down Expand Up @@ -243,6 +277,34 @@ sub detect_issue {
return ($msg, $issue);
}

sub create_time_entry {
my ($self, $issue_id, $date, $hours, $activity, $comments) = @_;
my ($activity_id) = $self->detect_activity_id($activity);
if (! $activity_id) {
warn qq{activity "$activity" could not be mapped to activity_id.};
}
if (! defined $date) {
my @ymd = (localtime(time))[5,4,3];
$ymd[0] += 1900;
$ymd[1] += 1;
$date = sprintf '%04d-%02d-%02d', @ymd;
}
return $self->post(
'time_entries.json',
Content_Type => 'application/json',
Content => encode_json +{
key => $self->api_key_as($self->who),
time_entry => {
issue_id => $issue_id,
spent_on => $date,
hours => $hours,
activity_id => $activity_id,
comments => $comments,
}
},
);
}

sub note_issue {
my ($self, $issue_id, $note) = @_;

Expand Down
7 changes: 7 additions & 0 deletions lib/Redmine/Chan/Recipe.pm
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ sub cook {
} elsif ($msg =~ /^(.+?)\s*>\s*\#(\d+)$/) {
# note 追加
my ($note, $issue_id) = ($1, $2);
if (my @m = $note =~ /^\s*\[\s*(\d+(?:\.\d+)?|\.\d+)\s+(\S+)(?:\s+([\S\n]+))?\s*\]\s*(.*)$/s) {
# 作業時間登録
my ($hours, $activity, $comments, $note_) = @m;
$comments = '' if ! defined $comments;
$api->create_time_entry($issue_id, undef, $hours, $activity, $comments);
$note = $note_;
}
$api->note_issue($issue_id, $note);
$reply = $api->issue_detail($issue_id);
} elsif ($msg =~ /\#(\d+)/) {
Expand Down