Redmine의 DB를 Metabase로 분석하여 필요한 시간을 예측합니다.

Redmine 준비



Redmine에는 Agile 플러그인을 설치하여 티켓에 스토리 포인트를 부여할 수 있습니다. 스토리 포인트는 표준 필드의 예정 공수에서도 대체 가능하므로 필수는 아닙니다.

Redmine에서 Agile 플러그인 (Light 버전) 사용 - Qiita

Redmine DB에 읽기 전용 사용자를 만드는 것이 좋습니다.

Metabase 준비



Metabase와 Redmine을 연결하십시오.
Metabase에서 Redmine으로 읽기 전용 사용자로 액세스하는 것이 좋습니다.

OpenProject에 Metabase를 도킹하면 최강의 대시 보드를 만들 수 있습니다 - Qiita
DIY 업무 시스템의 보기에 Metabase 어떻습니까 - Qiita

쿼리 만들기



아래의 기사에서 말한 생각을 이용하여 종료된 티켓의 견적(=스토리 포인트)과 실적(=입력한 작업 시간)의 상관을 해석하고, 미완료 티켓의 견적으로부터 필요한 공수를 예측합니다.

99% 확률로 납기를 지키려면 - Qiita

Metabase 네이티브 쿼리에 다음을 입력합니다.
시각화를 설정하면 결과를 그래프로 표현할 수 있습니다.
-- 二次集計
SELECT
    `closed_on_date`,
    `消化ポイント`,
    `残ポイント`,
    `消費時間`,
    `平均` * `残ポイント` AS `期待値`,
    SQRT( `分散` * `残ポイント` ) AS `標準偏差`
FROM
    (
        -- 一次集計
        SELECT
            `issues3`.`closed_on_date`,
            SUM(CASE WHEN `issues3`.`was_closed` THEN `issues3`.`story_points` ELSE 0 END) AS `消化ポイント`,
            SUM(CASE WHEN `issues3`.`was_closed` THEN 0 ELSE `issues3`.`story_points` END) AS `残ポイント`,
            SUM(CASE WHEN `issues3`.`was_closed` THEN `issues3`.`hours_sum` ELSE 0 END) AS `消費時間`,
            AVG(CASE WHEN `issues3`.`was_closed` THEN `issues3`.`hours_par_point` ELSE NULL END) AS `平均`,
            VARIANCE(CASE WHEN `issues3`.`was_closed` THEN `issues3`.`hours_par_point` ELSE NULL END)  AS `分散`
        FROM
            (
                -- 動きがあった日付において終了していたか判定する
                SELECT
                    `issues1`.`closed_on_date`,
                    `issues2`.`is_closed` AND `issues1`.`closed_on_date` >= `issues2`.`closed_on_date` AS `was_closed`,
                    `issues2`.`story_points`,
                    `issues2`.`hours_sum`,
                    `issues2`.`hours_sum` / `issues2`.`story_points` AS `hours_par_point`
                FROM
                    (
                        -- 動きがあった日付のリストを生成する
                        SELECT
                            DATE(`issues`.`closed_on`) AS `closed_on_date`
                        FROM
                            `issues`
                        GROUP BY
                            `closed_on_date`
                    ) `issues1`
                    INNER JOIN
                        (
                            -- 下記のデータを動きがあった日付ごとに集計する
                            SELECT
                                `projects`.`name`,
                                -- 終了したチケットか
                                `issue_statuses`.`is_closed`,
                                -- 工数合計
                                `time_entries_sum`.`hours_sum`,
                                -- ストーリーポイント(予定工数で代替可能)
                                `agile_data`.`story_points`,
                                -- 終了日
                                DATE(`issues`.`closed_on`) AS `closed_on_date`
                            FROM
                                `issues`
                                LEFT JOIN
                                    (
                                        -- 工数入力をチケット別に集計する
                                        SELECT
                                            `issue_id`,
                                            SUM(`hours`) AS `hours_sum`
                                        FROM
                                            `time_entries`
                                        GROUP BY
                                            `issue_id`
                                    ) `time_entries_sum`
                                ON  `issues`.`id` = `time_entries_sum`.`issue_id`
                                LEFT JOIN
                                    `agile_data`
                                ON  `issues`.`id` = `agile_data`.`issue_id`
                                LEFT JOIN
                                    `issue_statuses`
                                ON  `issues`.`status_id` = `issue_statuses`.`id`
                                LEFT JOIN
                                    `projects`
                                ON  `issues`.`project_id` = `projects`.`id`
                                LEFT JOIN
                                    `versions`
                                ON  `issues`.`fixed_version_id` = `versions`.`id`
                            -- フィールドフィルター
                            WHERE {{project_name}}
                                [[AND {{version_name}}]]
                        ) `issues2`
            ) `issues3`
        GROUP BY
            `issues3`.`closed_on_date`
    ) `issues4`


필드 필터는 Metabase 관련 설명입니다. 네이티브 쿼리로 입력할 뿐만 아니라 변수의 값 유형 등을 설정해야 합니다.





쿼리를 대시보드에 추가



생성한 쿼리를 대시보드에 추가할 때 필터를 추가하고 필드 필터와 연결하여 모든 프로젝트 및 모든 버전에 대한 예측을 볼 수 있습니다.

프로젝트 이름의 필드 필터는 필수 항목이므로 연결하기 전에 쿼리를 대시보드에 추가해도 오류가 표시됩니다.

좋은 웹페이지 즐겨찾기