Repository: kurusugawa-computer/annofab-cli (language: python)

Issue:
`statistics visualize`：完了の定義を受入完了または受入未着手に変更できるようにする
タスク完了の定義を変更できるようにする
* 受入フェーズの完了：status=="completed" 
* 検査フェーズの完了： phase=="acceptance"
* 教師付フェーズの完了： phase=="inspection" or phase=="acceptance"


「日ごとの生産量と生産性」をプロットするグラフでは、大量のタスクが差し戻されると、グラフが正しくプロットされないので、初めて「～フェーズが完了した日」でプロットする。




Discussion / hints:

Fix patch:
diff --git a/annofabcli/stat_visualization/mask_visualization_dir.py b/annofabcli/stat_visualization/mask_visualization_dir.py
index 87d3105c..ac4549ab 100755
--- a/annofabcli/stat_visualization/mask_visualization_dir.py
+++ b/annofabcli/stat_visualization/mask_visualization_dir.py
@@ -33,7 +33,7 @@
 from annofabcli.statistics.visualization.dataframe.task_worktime_by_phase_user import TaskWorktimeByPhaseUser
 from annofabcli.statistics.visualization.dataframe.user_performance import UserPerformance
 from annofabcli.statistics.visualization.dataframe.worktime_per_date import WorktimePerDate
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 from annofabcli.statistics.visualization.project_dir import ProjectDir
 
 logger = logging.getLogger(__name__)
@@ -223,12 +223,15 @@ def main(args: argparse.Namespace) -> None:
         create_custom_production_volume_list(args.custom_production_volume) if args.custom_production_volume is not None else None
     )
 
+    task_completion_criteria = TaskCompletionCriteria(args.task_completion_criteria)
     input_project_dir = ProjectDir(
         args.dir,
+        task_completion_criteria,
         custom_production_volume_list=custom_production_volume_list,
     )
     output_project_dir = ProjectDir(
         args.output_dir,
+        task_completion_criteria,
         metadata=input_project_dir.read_metadata(),
     )
     mask_visualization_dir(
@@ -271,6 +274,16 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
         "column_list": [{"value": "video_duration_minute", "name": "動画長さ"}],
     }
 
+    parser.add_argument(
+        "--task_completion_criteria",
+        type=str,
+        choices=[e.value for e in TaskCompletionCriteria],
+        default=TaskCompletionCriteria.ACCEPTANCE_COMPLETED.value,
+        help="タスクの完了条件を指定します。\n"
+        "* ``acceptance_completed``: タスクが受入フェーズの完了状態であれば「タスクの完了」とみなす\n"
+        "* ``acceptance_reached``: タスクが受入フェーズに到達したら「タスクの完了」とみなす\n",
+    )
+
     parser.add_argument(
         "--custom_production_volume",
         type=str,
diff --git a/annofabcli/stat_visualization/merge_visualization_dir.py b/annofabcli/stat_visualization/merge_visualization_dir.py
index cd5b4add..fd359d83 100755
--- a/annofabcli/stat_visualization/merge_visualization_dir.py
+++ b/annofabcli/stat_visualization/merge_visualization_dir.py
@@ -35,7 +35,7 @@
     WholeProductivityPerFirstAnnotationStartedDate,
 )
 from annofabcli.statistics.visualization.dataframe.worktime_per_date import WorktimePerDate
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 from annofabcli.statistics.visualization.project_dir import MergingInfo, ProjectDir
 
 logger = logging.getLogger(__name__)
@@ -45,11 +45,13 @@ class WritingVisualizationFile:
     def __init__(
         self,
         output_project_dir: ProjectDir,
+        task_completion_criteria: TaskCompletionCriteria,
         *,
         user_id_list: Optional[List[str]] = None,
         minimal_output: bool = False,
     ) -> None:
         self.output_project_dir = output_project_dir
+        self.task_completion_criteria = task_completion_criteria
         self.user_id_list = user_id_list
         self.minimal_output = minimal_output
 
@@ -126,13 +128,13 @@ def write_task_worktime_by_phase_user(self, task_worktime_by_phase_user: TaskWor
 
     @_catch_exception
     def write_performance_per_first_annotation_started_date(self, task: Task) -> None:
-        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task)
+        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task, self.task_completion_criteria)
         self.output_project_dir.write_whole_productivity_per_first_annotation_started_date(obj)
         self.output_project_dir.write_whole_productivity_line_graph_per_annotation_started_date(obj)
 
     @_catch_exception
     def write_merge_performance_per_date(self, task: Task, worktime_per_date: WorktimePerDate) -> None:
-        obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date)
+        obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date, task_completion_criteria=self.task_completion_criteria)
         self.output_project_dir.write_whole_productivity_per_date(obj)
         self.output_project_dir.write_whole_productivity_line_graph_per_date(obj)
 
@@ -176,7 +178,7 @@ def merge_task_worktime_by_phase_user(self) -> TaskWorktimeByPhaseUser:
         merged_obj = TaskWorktimeByPhaseUser.merge(*tmp_list, custom_production_volume_list=self.custom_production_volume_list)
         return merged_obj
 
-    def create_merging_info(self) -> MergingInfo:
+    def create_merging_info(self, task_completion_criteria: TaskCompletionCriteria) -> MergingInfo:
         """
         `project_info.json`の内容から、どのようにマージしたかを示す情報を作成する。
         """
@@ -186,12 +188,15 @@ def create_merging_info(self) -> MergingInfo:
             project_info = project_dir.read_project_info()
             project_info_list.append(project_info)
 
-        merge_info = MergingInfo(target_dir_list=target_dir_list, project_info_list=project_info_list)
+        merge_info = MergingInfo(
+            target_dir_list=target_dir_list, project_info_list=project_info_list, task_completion_criteria=task_completion_criteria
+        )
         return merge_info
 
 
 def merge_visualization_dir(  # pylint: disable=too-many-statements
     project_dir_list: List[ProjectDir],
+    task_completion_criteria: TaskCompletionCriteria,
     output_project_dir: ProjectDir,
     *,
     custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None,
@@ -200,7 +205,7 @@ def merge_visualization_dir(  # pylint: disable=too-many-statements
 ) -> None:
     merging_obj = MergingVisualizationFile(project_dir_list, custom_production_volume_list=custom_production_volume_list)
 
-    merging_info = merging_obj.create_merging_info()
+    merging_info = merging_obj.create_merging_info(task_completion_criteria)
     output_project_dir.metadata = merging_info.to_dict(encode_json=True)
 
     # 基本となるCSVファイルを読み込みマージする
@@ -210,7 +215,9 @@ def merge_visualization_dir(  # pylint: disable=too-many-statements
 
     user_performance = UserPerformance.from_df_wrapper(task_worktime_by_phase_user=task_worktime_by_phase_user, worktime_per_date=worktime_per_date)
     whole_performance = WholePerformance.from_df_wrapper(task_worktime_by_phase_user=task_worktime_by_phase_user, worktime_per_date=worktime_per_date)
-    writing_obj = WritingVisualizationFile(output_project_dir, user_id_list=user_id_list, minimal_output=minimal_output)
+    writing_obj = WritingVisualizationFile(
+        output_project_dir, user_id_list=user_id_list, minimal_output=minimal_output, task_completion_criteria=task_completion_criteria
+    )
 
     writing_obj.write_task_list_and_histogram(task)
     writing_obj.write_worktime_per_date(worktime_per_date)
@@ -258,13 +265,14 @@ def main(args: argparse.Namespace) -> None:
     custom_production_volume_list = (
         create_custom_production_volume_list(args.custom_production_volume) if args.custom_production_volume is not None else None
     )
-
+    task_completion_criteria = TaskCompletionCriteria(args.task_completion_criteria)
     merge_visualization_dir(
-        project_dir_list=[ProjectDir(e) for e in args.dir],
+        project_dir_list=[ProjectDir(e, task_completion_criteria) for e in args.dir],
+        task_completion_criteria=task_completion_criteria,
         user_id_list=user_id_list,
         custom_production_volume_list=custom_production_volume_list,
         minimal_output=args.minimal,
-        output_project_dir=ProjectDir(args.output_dir),
+        output_project_dir=ProjectDir(args.output_dir, task_completion_criteria),
     )
 
 
@@ -272,6 +280,16 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
     parser.add_argument("--dir", type=Path, nargs="+", required=True, help="マージ対象ディレクトリ。2つ以上指定してください。")
     parser.add_argument("-o", "--output_dir", type=Path, required=True, help="出力先ディレクトリ。配下にプロジェクト名のディレクトリが出力される。")
 
+    parser.add_argument(
+        "--task_completion_criteria",
+        type=str,
+        choices=[e.value for e in TaskCompletionCriteria],
+        default=TaskCompletionCriteria.ACCEPTANCE_COMPLETED.value,
+        help="タスクの完了条件を指定します。\n"
+        "* ``acceptance_completed``: タスクが受入フェーズの完了状態であれば「タスクの完了」とみなす\n"
+        "* ``acceptance_reached``: タスクが受入フェーズに到達したら「タスクの完了」とみなす\n",
+    )
+
     parser.add_argument(
         "-u",
         "--user_id",
diff --git a/annofabcli/stat_visualization/summarize_whole_performance_csv.py b/annofabcli/stat_visualization/summarize_whole_performance_csv.py
index a7926eef..d01aa61c 100644
--- a/annofabcli/stat_visualization/summarize_whole_performance_csv.py
+++ b/annofabcli/stat_visualization/summarize_whole_performance_csv.py
@@ -11,7 +11,7 @@
     get_json_from_args,
 )
 from annofabcli.statistics.visualization.dataframe.project_performance import ProjectPerformance
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 from annofabcli.statistics.visualization.project_dir import ProjectDir
 
 logger = logging.getLogger(__name__)
@@ -31,7 +31,10 @@ def create_custom_production_volume_list(cli_value: str) -> list[ProductionVolum
 
 def main(args: argparse.Namespace) -> None:
     root_dir: Path = args.dir
-    project_dir_list = [ProjectDir(elm) for elm in root_dir.iterdir() if elm.is_dir()]
+    # task_completion_criteriaは何でもよいので、とりあえずACCEPTANCE_COMPLETEDを指定
+    project_dir_list = [
+        ProjectDir(elm, task_completion_criteria=TaskCompletionCriteria.ACCEPTANCE_COMPLETED) for elm in root_dir.iterdir() if elm.is_dir()
+    ]
 
     custom_production_volume_list = (
         create_custom_production_volume_list(args.custom_production_volume) if args.custom_production_volume is not None else None
diff --git a/annofabcli/stat_visualization/write_graph.py b/annofabcli/stat_visualization/write_graph.py
index 89192b7f..ac2ec245 100755
--- a/annofabcli/stat_visualization/write_graph.py
+++ b/annofabcli/stat_visualization/write_graph.py
@@ -21,7 +21,7 @@
     InspectorProductivityPerDate,
 )
 from annofabcli.statistics.visualization.dataframe.task import Task
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 from annofabcli.statistics.visualization.project_dir import ProjectDir
 
 logger = logging.getLogger(__name__)
@@ -129,8 +129,9 @@ def main(args: argparse.Namespace) -> None:
         create_custom_production_volume_list(args.custom_production_volume) if args.custom_production_volume is not None else None
     )
 
-    input_project_dir = ProjectDir(args.dir, custom_production_volume_list=custom_production_volume_list)
-    output_project_dir = ProjectDir(args.output_dir, metadata=input_project_dir.read_metadata())
+    task_completion_criteria = TaskCompletionCriteria(args.task_completion_criteria)
+    input_project_dir = ProjectDir(args.dir, task_completion_criteria, custom_production_volume_list=custom_production_volume_list)
+    output_project_dir = ProjectDir(args.output_dir, task_completion_criteria, metadata=input_project_dir.read_metadata())
     main_obj = WritingGraph(
         project_dir=input_project_dir,
         output_project_dir=output_project_dir,
@@ -164,6 +165,16 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
         help="必要最小限のファイルを出力します。",
     )
 
+    parser.add_argument(
+        "--task_completion_criteria",
+        type=str,
+        choices=[e.value for e in TaskCompletionCriteria],
+        default=TaskCompletionCriteria.ACCEPTANCE_COMPLETED.value,
+        help="タスクの完了条件を指定します。\n"
+        "* ``acceptance_completed``: タスクが受入フェーズの完了状態であれば「タスクの完了」とみなす\n"
+        "* ``acceptance_reached``: タスクが受入フェーズに到達したら「タスクの完了」とみなす\n",
+    )
+
     custom_production_volume_sample = {
         "column_list": [{"value": "video_duration_minute", "name": "動画長さ"}],
     }
diff --git a/annofabcli/stat_visualization/write_performance_rating_csv.py b/annofabcli/stat_visualization/write_performance_rating_csv.py
index 1696364c..573c62b0 100755
--- a/annofabcli/stat_visualization/write_performance_rating_csv.py
+++ b/annofabcli/stat_visualization/write_performance_rating_csv.py
@@ -21,7 +21,7 @@
     ProjectPerformance,
     ProjectWorktimePerMonth,
 )
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn, WorktimeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria, WorktimeColumn
 from annofabcli.statistics.visualization.project_dir import ProjectDir
 
 logger = logging.getLogger(__name__)
@@ -326,7 +326,11 @@ def create_rating_df(
                 custom_production_volume_list_by_directory.get(p_project_dir.name) if custom_production_volume_list_by_directory is not None else None
             )
             project_title = p_project_dir.name
-            project_dir = ProjectDir(p_project_dir, custom_production_volume_list=custom_production_volume_list)
+            project_dir = ProjectDir(
+                p_project_dir,
+                task_completion_criteria=TaskCompletionCriteria.ACCEPTANCE_COMPLETED,
+                custom_production_volume_list=custom_production_volume_list,
+            )
             project_dir_list.append(project_dir)
 
             try:
@@ -471,7 +475,8 @@ def create_user_df(target_dir: Path) -> pandas.DataFrame:
         if not p_project_dir.is_dir():
             continue
 
-        project_dir = ProjectDir(p_project_dir)
+        # task_completion_criteriaは何でもよいので、とりあえずACCEPTANCE_COMPLETEDを指定
+        project_dir = ProjectDir(p_project_dir, task_completion_criteria=TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
 
         try:
             user_performance = project_dir.read_user_performance()
diff --git a/annofabcli/statistics/visualization/dataframe/task.py b/annofabcli/statistics/visualization/dataframe/task.py
index fa7939f0..e6064edd 100644
--- a/annofabcli/statistics/visualization/dataframe/task.py
+++ b/annofabcli/statistics/visualization/dataframe/task.py
@@ -110,7 +110,8 @@ def columns(self) -> list[str]:
             "first_acceptance_username",
             "first_acceptance_worktime_hour",
             "first_acceptance_started_datetime",
-            # 最後の受入
+            # 受入フェーズの日時
+            "first_acceptance_reached_datetime",
             "first_acceptance_completed_datetime",
             # 作業時間に関する内容
             "worktime_hour",
@@ -229,6 +230,7 @@ def empty(cls, *, custom_production_volume_list: Optional[list[ProductionVolumeC
             "first_acceptance_user_id",
             "first_acceptance_username",
             "first_acceptance_started_datetime",
+            "first_acceptance_reached_datetime",
             "first_acceptance_completed_datetime",
         ]
 
diff --git a/annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py b/annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py
index b7a8e877..510f2f1e 100644
--- a/annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py
+++ b/annofabcli/statistics/visualization/dataframe/whole_productivity_per_date.py
@@ -14,7 +14,7 @@
 import bokeh.layouts
 import bokeh.palettes
 import pandas
-from annofabapi.models import TaskStatus
+from annofabapi.models import TaskPhase, TaskStatus
 from bokeh.models import DataRange1d
 from bokeh.models.ui import UIElement
 from bokeh.models.widgets.markups import Div
@@ -22,6 +22,7 @@
 from dateutil.parser import parse
 
 from annofabcli.common.bokeh import create_pretext_from_metadata
+from annofabcli.common.type_util import assert_noreturn
 from annofabcli.common.utils import datetime_to_date, print_csv
 from annofabcli.statistics.linegraph import (
     LineGraph,
@@ -32,7 +33,7 @@
 )
 from annofabcli.statistics.visualization.dataframe.task import Task
 from annofabcli.statistics.visualization.dataframe.worktime_per_date import WorktimePerDate
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 
 logger = logging.getLogger(__name__)
 
@@ -91,10 +92,17 @@ def _plot_and_moving_average(
 
 
 class WholeProductivityPerCompletedDate:
-    """受入完了日ごとの全体の生産量と生産性に関する情報"""
+    """完了日ごとの全体の生産量と生産性に関する情報"""
 
-    def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> None:
+    def __init__(
+        self,
+        df: pandas.DataFrame,
+        task_completion_criteria: TaskCompletionCriteria,
+        *,
+        custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None,
+    ) -> None:
         self.df = df
+        self.task_completion_criteria = task_completion_criteria
         self.custom_production_volume_list = custom_production_volume_list if custom_production_volume_list is not None else []
 
     def _validate_df_for_output(self, output_file: Path) -> bool:
@@ -105,11 +113,15 @@ def _validate_df_for_output(self, output_file: Path) -> bool:
 
     @classmethod
     def from_csv(
-        cls, csv_file: Path, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None
+        cls,
+        csv_file: Path,
+        task_completion_criteria: TaskCompletionCriteria,
+        *,
+        custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None,
     ) -> WholeProductivityPerCompletedDate:
         """CSVファイルからインスタンスを生成します。"""
         df = pandas.read_csv(str(csv_file))
-        return cls(df, custom_production_volume_list=custom_production_volume_list)
+        return cls(df, task_completion_criteria, custom_production_volume_list=custom_production_volume_list)
 
     @staticmethod
     def _create_df_date(date_index1: pandas.Index, date_index2: pandas.Index) -> pandas.DataFrame:
@@ -129,9 +141,11 @@ def _create_df_date(date_index1: pandas.Index, date_index2: pandas.Index) -> pan
         return pandas.DataFrame(index=[e.strftime("%Y-%m-%d") for e in pandas.date_range(start_date, end_date)])
 
     @classmethod
-    def from_df_wrapper(cls, task: Task, worktime_per_date: WorktimePerDate) -> WholeProductivityPerCompletedDate:
+    def from_df_wrapper(
+        cls, task: Task, worktime_per_date: WorktimePerDate, task_completion_criteria: TaskCompletionCriteria
+    ) -> WholeProductivityPerCompletedDate:
         """
-        受入完了日毎の全体の生産量、生産性を算出する。
+        完了日毎の全体の生産量、生産性を算出する。
 
         Args:
             task: タスク情報が格納されたDataFrameをラップするクラスのインスタンス
@@ -148,21 +162,25 @@ def from_df_wrapper(cls, task: Task, worktime_per_date: WorktimePerDate) -> Whol
         # 生産量を表す列名
         production_volume_columns = ["input_data_count", "annotation_count", *[e.value for e in task.custom_production_volume_list]]
 
-        df_sub_task = task.df[["task_id", "first_acceptance_completed_datetime", *production_volume_columns]].copy()
-        df_sub_task["first_acceptance_completed_date"] = df_sub_task["first_acceptance_completed_datetime"].map(
-            lambda e: datetime_to_date(e) if not pandas.isna(e) else None
-        )
+        if task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_COMPLETED:
+            datetime_column = "first_acceptance_completed_datetime"
+        elif task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_REACHED:
+            datetime_column = "first_acceptance_reached_datetime"
+        else:
+            assert_noreturn(task_completion_criteria)
+
+        df_sub_task = task.df[["task_id", datetime_column, *production_volume_columns]].copy()
+        date_column = datetime_column.replace("_datetime", "_date")
+        df_sub_task[date_column] = df_sub_task[datetime_column].map(lambda e: datetime_to_date(e) if not pandas.isna(e) else None)
 
-        # タスク完了日を軸にして集計する
+        # 完了日を軸にして集計する
         df_agg_sub_task = df_sub_task.pivot_table(
             values=production_volume_columns,
-            index="first_acceptance_completed_date",
+            index=date_column,
             aggfunc="sum",
         ).fillna(0)
         if len(df_agg_sub_task) > 0:
-            df_agg_sub_task["task_count"] = df_sub_task.pivot_table(
-                values=["task_id"], index="first_acceptance_completed_date", aggfunc="count"
-            ).fillna(0)
+            df_agg_sub_task["task_count"] = df_sub_task.pivot_table(values=["task_id"], index=date_column, aggfunc="count").fillna(0)
         else:
             # 列だけ作る
             df_agg_sub_task = df_agg_sub_task.assign(**{key: 0 for key in production_volume_columns}, task_count=0)
@@ -212,7 +230,7 @@ def from_df_wrapper(cls, task: Task, worktime_per_date: WorktimePerDate) -> Whol
         df_date["date"] = df_date.index
 
         cls._add_velocity_columns(df_date, production_volume_columns)
-        return cls(df_date, custom_production_volume_list=task.custom_production_volume_list)
+        return cls(df_date, task_completion_criteria, custom_production_volume_list=task.custom_production_volume_list)
 
     @classmethod
     def _add_velocity_columns(cls, df: pandas.DataFrame, production_volume_columns: list[str]) -> None:
@@ -248,16 +266,17 @@ def add_velocity_column(df: pandas.DataFrame, numerator_column: str, denominator
             for unit in production_volume_columns:
                 add_velocity_column(df, numerator_column=f"{category}_worktime_hour", denominator_column=unit)
 
-    @staticmethod
-    def _create_div_element() -> Div:
+    def _create_div_element(self) -> Div:
         """
         HTMLページの先頭に付与するdiv要素を生成する。
         """
-        return Div(
-            text="""<h4>用語</h4>
-            <p>「X日のタスク数」とは、X日に初めて受入完了状態になったタスクの個数です。</p>
-            """
-        )
+        if self.task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_COMPLETED:
+            str_task = "受入フェーズ完了状態"
+        elif self.task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_REACHED:
+            str_task = "受入フェーズ"
+        else:
+            assert_noreturn(self.task_completion_criteria)
+        return Div(text="<h4>注意</h4>" f"<p>「X日のタスク数」は、X日に初めて{str_task}になったタスクの個数です。</p>")
 
     def plot(
         self,
@@ -735,9 +754,11 @@ def create_worktime_line_graph() -> LineGraph:
         write_bokeh_graph(bokeh.layouts.column(element_list), output_file)
 
     @classmethod
-    def empty(cls, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> WholeProductivityPerCompletedDate:
+    def empty(
+        cls, *, task_completion_criteria: TaskCompletionCriteria, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None
+    ) -> WholeProductivityPerCompletedDate:
         df = pandas.DataFrame(columns=cls.get_columns(custom_production_volume_list=custom_production_volume_list))
-        return cls(df, custom_production_volume_list=custom_production_volume_list)
+        return cls(df, task_completion_criteria, custom_production_volume_list=custom_production_volume_list)
 
     @property
     def columns(self) -> list[str]:
@@ -807,17 +828,28 @@ def to_csv(self, output_file: Path) -> None:
 class WholeProductivityPerFirstAnnotationStartedDate:
     """教師付開始日ごとの全体の生産量と生産性に関する情報"""
 
-    def __init__(self, df: pandas.DataFrame, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> None:
+    def __init__(
+        self,
+        df: pandas.DataFrame,
+        task_completion_criteria: TaskCompletionCriteria,
+        *,
+        custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None,
+    ) -> None:
+        self.task_completion_criteria = task_completion_criteria
         self.custom_production_volume_list = custom_production_volume_list if custom_production_volume_list is not None else []
         self.df = df
 
     @classmethod
     def from_csv(
-        cls, csv_file: Path, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None
+        cls,
+        csv_file: Path,
+        task_completion_criteria: TaskCompletionCriteria,
+        *,
+        custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None,
     ) -> WholeProductivityPerFirstAnnotationStartedDate:
         """CSVファイルからインスタンスを生成します。"""
         df = pandas.read_csv(str(csv_file))
-        return cls(df, custom_production_volume_list=custom_production_volume_list)
+        return cls(df, task_completion_criteria, custom_production_volume_list=custom_production_volume_list)
 
     @classmethod
     def _add_velocity_columns(cls, df: pandas.DataFrame, production_volume_columns: list[str]) -> None:
@@ -840,12 +872,19 @@ def add_velocity_column(df: pandas.DataFrame, numerator_column: str, denominator
             add_velocity_column(df, numerator_column="acceptance_worktime_hour", denominator_column=column)
 
     @classmethod
-    def from_task(cls, task: Task) -> WholeProductivityPerFirstAnnotationStartedDate:
+    def from_task(cls, task: Task, task_completion_criteria: TaskCompletionCriteria) -> WholeProductivityPerFirstAnnotationStartedDate:
         # 生産量を表す列名
         production_volume_columns = ["input_data_count", "annotation_count", *[e.value for e in task.custom_production_volume_list]]
 
         df_task = task.df
-        df_sub_task = df_task[df_task["status"] == TaskStatus.COMPLETE.value][
+        if task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_COMPLETED:
+            df_sub_task = df_task[df_task["status"] == TaskStatus.COMPLETE.value]
+        elif task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_REACHED:
+            df_sub_task = df_task[df_task["phase"] == TaskPhase.ACCEPTANCE.value]
+        else:
+            assert_noreturn(task_completion_criteria)
+
+        df_sub_task = df_sub_task[
             [
                 "task_id",
                 "first_annotation_started_datetime",
@@ -893,7 +932,7 @@ def from_task(cls, task: Task) -> WholeProductivityPerFirstAnnotationStartedDate
         df_date["first_annotation_started_date"] = df_date.index
         # 生産性情報などの列を追加する
         cls._add_velocity_columns(df_date, production_volume_columns)
-        return cls(df_date, custom_production_volume_list=task.custom_production_volume_list)
+        return cls(df_date, task_completion_criteria, custom_production_volume_list=task.custom_production_volume_list)
 
     def _validate_df_for_output(self, output_file: Path) -> bool:
         if len(self.df) == 0:
@@ -902,9 +941,11 @@ def _validate_df_for_output(self, output_file: Path) -> bool:
         return True
 
     @classmethod
-    def empty(cls, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> WholeProductivityPerFirstAnnotationStartedDate:
+    def empty(
+        cls, task_completion_criteria: TaskCompletionCriteria, *, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None
+    ) -> WholeProductivityPerFirstAnnotationStartedDate:
         df = pandas.DataFrame(columns=cls.get_columns(custom_production_volume_list=custom_production_volume_list))
-        return cls(df, custom_production_volume_list=custom_production_volume_list)
+        return cls(df, task_completion_criteria, custom_production_volume_list=custom_production_volume_list)
 
     @staticmethod
     def get_columns(*, custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None) -> list[str]:
@@ -973,12 +1014,16 @@ def create_div_element() -> Div:
             """
             HTMLページの先頭に付与するdiv要素を生成する。
             """
+            if self.task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_COMPLETED:
+                str_task = "受入フェーズ完了状態"
+            elif self.task_completion_criteria == TaskCompletionCriteria.ACCEPTANCE_REACHED:
+                str_task = "受入フェーズ"
+            else:
+                assert_noreturn(self.task_completion_criteria)
             return Div(
-                text="""<h4>注意</h4>
-                <p>「X日の作業時間」とは、「X日に教師付開始したタスクにかけた作業時間」です。
-                「X日に作業した時間」ではありません。
-                </p>
-                """
+                text="<h4>注意</h4>"
+                f"<p>「X日のタスク数」は、X日に教師付フェーズを開始したタスクの内、{str_task}であるタスクの個数です。</p>"
+                f"<p>「X日の作業時間」は、X日のタスク数にかけた作業時間です。X日に作業した時間ではないことに注意してください。</p>"
             )
 
         def create_line_graph(title: str, y_axis_label: str, tooltip_columns: list[str]) -> LineGraph:
diff --git a/annofabcli/statistics/visualization/model.py b/annofabcli/statistics/visualization/model.py
index 75a60c29..fe9a01ae 100644
--- a/annofabcli/statistics/visualization/model.py
+++ b/annofabcli/statistics/visualization/model.py
@@ -21,3 +21,14 @@ class ProductionVolumeColumn:
     """CSVの列名"""
     name: str
     """列の名前。グラフに表示する名前などに使用する"""
+
+
+class TaskCompletionCriteria(Enum):
+    """
+    タスクの完了の条件
+    """
+
+    ACCEPTANCE_COMPLETED = "acceptance_completed"
+    """タスクが受入フェーズの完了状態であれば「タスクの完了」とみなす"""
+    ACCEPTANCE_REACHED = "acceptance_reached"
+    """タスクが受入フェーズに到達したら「タスクの完了」とみなす"""
diff --git a/annofabcli/statistics/visualization/project_dir.py b/annofabcli/statistics/visualization/project_dir.py
index 8d5a4e0c..274a89b6 100644
--- a/annofabcli/statistics/visualization/project_dir.py
+++ b/annofabcli/statistics/visualization/project_dir.py
@@ -25,7 +25,7 @@
 )
 from annofabcli.statistics.visualization.dataframe.worktime_per_date import WorktimePerDate
 from annofabcli.statistics.visualization.filtering_query import FilteringQuery
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 
 logger = logging.getLogger(__name__)
 
@@ -53,11 +53,13 @@ class ProjectDir(DataClassJsonMixin):
     def __init__(
         self,
         project_dir: Path,
+        task_completion_criteria: TaskCompletionCriteria,
         *,
         metadata: Optional[dict[str, Any]] = None,
         custom_production_volume_list: Optional[list[ProductionVolumeColumn]] = None,
     ) -> None:
         self.project_dir = project_dir
+        self.task_completion_criteria = task_completion_criteria
         self.metadata = metadata
         self.custom_production_volume_list = custom_production_volume_list
 
@@ -223,10 +225,14 @@ def read_whole_productivity_per_date(self) -> WholeProductivityPerCompletedDate:
         file = self.project_dir / self.FILENAME_WHOLE_PRODUCTIVITY_PER_DATE
         if file.exists():
             return WholeProductivityPerCompletedDate.from_csv(
-                self.project_dir / self.FILENAME_WHOLE_PRODUCTIVITY_PER_DATE, custom_production_volume_list=self.custom_production_volume_list
+                self.project_dir / self.FILENAME_WHOLE_PRODUCTIVITY_PER_DATE,
+                task_completion_criteria=self.task_completion_criteria,
+                custom_production_volume_list=self.custom_production_volume_list,
             )
         else:
-            return WholeProductivityPerCompletedDate.empty(custom_production_volume_list=self.custom_production_volume_list)
+            return WholeProductivityPerCompletedDate.empty(
+                task_completion_criteria=self.task_completion_criteria, custom_production_volume_list=self.custom_production_volume_list
+            )
 
     def write_whole_productivity_per_date(self, obj: WholeProductivityPerCompletedDate) -> None:
         """
@@ -249,10 +255,13 @@ def read_whole_productivity_per_first_annotation_started_date(self) -> WholeProd
         if file.exists():
             return WholeProductivityPerFirstAnnotationStartedDate.from_csv(
                 file,
+                self.task_completion_criteria,
                 custom_production_volume_list=self.custom_production_volume_list,
             )
         else:
-            return WholeProductivityPerFirstAnnotationStartedDate.empty(custom_production_volume_list=self.custom_production_volume_list)
+            return WholeProductivityPerFirstAnnotationStartedDate.empty(
+                self.task_completion_criteria, custom_production_volume_list=self.custom_production_volume_list
+            )
 
     def write_whole_productivity_per_first_annotation_started_date(self, obj: WholeProductivityPerFirstAnnotationStartedDate) -> None:
         """
@@ -453,6 +462,8 @@ class ProjectInfo(DataClassJsonMixin):
     """入力データの種類"""
     measurement_datetime: str
     """計測日時。（2004-04-01T12:00+09:00形式）"""
+    task_completion_criteria: TaskCompletionCriteria
+    """タスクの完了条件"""
     query: FilteringQuery
     """集計対象を絞り込むためのクエリ"""
 
@@ -465,3 +476,5 @@ class MergingInfo(DataClassJsonMixin):
     """マージ対象のディレクトリ名"""
     project_info_list: List[ProjectInfo]
     """マージ対象のプロジェクト情報"""
+    task_completion_criteria: TaskCompletionCriteria
+    """タスクの完了条件"""
diff --git a/annofabcli/statistics/visualize_statistics.py b/annofabcli/statistics/visualize_statistics.py
index b0d4b4e1..8e01a723 100644
--- a/annofabcli/statistics/visualize_statistics.py
+++ b/annofabcli/statistics/visualize_statistics.py
@@ -48,7 +48,7 @@
 )
 from annofabcli.statistics.visualization.dataframe.worktime_per_date import WorktimePerDate
 from annofabcli.statistics.visualization.filtering_query import FilteringQuery, filter_tasks
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn, WorktimeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria, WorktimeColumn
 from annofabcli.statistics.visualization.project_dir import ProjectDir, ProjectInfo
 from annofabcli.statistics.visualization.visualization_source_files import VisualizationSourceFiles
 
@@ -60,10 +60,11 @@ def get_project_output_dir(project_title: str) -> str:
 
 
 class WriteCsvGraph:
-    def __init__(
+    def __init__(  # noqa: PLR0913
         self,
         service: annofabapi.Resource,
         project_id: str,
+        task_completion_criteria: TaskCompletionCriteria,
         filtering_query: FilteringQuery,
         visualization_source_files: VisualizationSourceFiles,
         project_dir: ProjectDir,
@@ -76,6 +77,7 @@ def __init__(
     ) -> None:
         self.service = service
         self.project_id = project_id
+        self.task_completion_criteria = task_completion_criteria
         self.project_dir = project_dir
         self.filtering_query = filtering_query
         self.visualize_source_files = visualization_source_files
@@ -212,11 +214,15 @@ def write_worktime_per_date(self, user_id_list: Optional[List[str]] = None) -> N
         self.project_dir.write_worktime_per_date_user(worktime_per_date_obj)
 
         task = self._get_task()
-        productivity_per_completed_date_obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date_obj)
+        productivity_per_completed_date_obj = WholeProductivityPerCompletedDate.from_df_wrapper(
+            task, worktime_per_date_obj, task_completion_criteria=self.task_completion_criteria
+        )
 
         self.project_dir.write_whole_productivity_per_date(productivity_per_completed_date_obj)
 
-        productivity_per_started_date_obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task)
+        productivity_per_started_date_obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(
+            task, task_completion_criteria=self.task_completion_criteria
+        )
         self.project_dir.write_whole_productivity_per_first_annotation_started_date(productivity_per_started_date_obj)
 
         if not self.output_only_text:
@@ -250,6 +256,7 @@ def __init__(  # noqa: PLR0913
         *,
         temp_dir: Path,
         # タスクの絞り込み関係
+        task_completion_criteria: TaskCompletionCriteria,
         task_query: Optional[TaskQuery],
         start_date: Optional[str] = None,
         end_date: Optional[str] = None,
@@ -268,7 +275,7 @@ def __init__(  # noqa: PLR0913
         self.service = service
         self.facade = AnnofabApiFacade(service)
         self.temp_dir = temp_dir
-
+        self.task_completion_criteria = task_completion_criteria
         self.filtering_query = FilteringQuery(task_query=task_query, start_date=start_date, end_date=end_date)
         self.minimal_output = minimal_output
         self.output_only_text = output_only_text
@@ -289,6 +296,7 @@ def get_project_info(self, project_id: str) -> ProjectInfo:
             project_title=project_title,
             input_data_type=project_info["input_data_type"],
             measurement_datetime=annofabapi.utils.str_now(),
+            task_completion_criteria=self.task_completion_criteria,
             query=self.filtering_query,
         )
         return project_summary
@@ -307,7 +315,7 @@ def visualize_statistics(self, project_id: str, output_project_dir: Path) -> Non
         project_info = self.get_project_info(project_id)
         logger.info(f"project_title='{project_info.project_title}'")
 
-        project_dir = ProjectDir(output_project_dir, metadata=project_info.to_dict(encode_json=True))
+        project_dir = ProjectDir(output_project_dir, self.task_completion_criteria, metadata=project_info.to_dict(encode_json=True))
         project_dir.write_project_info(project_info)
 
         if self.actual_worktime is not None:
@@ -347,6 +355,7 @@ def visualize_statistics(self, project_id: str, output_project_dir: Path) -> Non
         write_obj = WriteCsvGraph(
             self.service,
             project_id,
+            task_completion_criteria=self.task_completion_criteria,
             filtering_query=self.filtering_query,
             visualization_source_files=visualization_source_files,
             project_dir=project_dir,
@@ -452,6 +461,7 @@ def visualize_statistics(  # noqa: PLR0913  # pylint: disable=too-many-positiona
         self,
         temp_dir: Path,
         task_query: Optional[TaskQuery],
+        task_completion_criteria: TaskCompletionCriteria,
         user_id_list: Optional[list[str]],
         actual_worktime: ActualWorktime,
         annotation_count: Optional[AnnotationCount],
@@ -470,6 +480,7 @@ def visualize_statistics(  # noqa: PLR0913  # pylint: disable=too-many-positiona
         main_obj = VisualizingStatisticsMain(
             service=self.service,
             temp_dir=temp_dir,
+            task_completion_criteria=task_completion_criteria,
             task_query=task_query,
             user_ids=user_id_list,
             actual_worktime=actual_worktime,
@@ -496,7 +507,7 @@ def visualize_statistics(  # noqa: PLR0913  # pylint: disable=too-many-positiona
             )
 
             if len(output_project_dir_list) > 0:
-                project_dir_list = [ProjectDir(e) for e in output_project_dir_list]
+                project_dir_list = [ProjectDir(e, task_completion_criteria) for e in output_project_dir_list]
                 custom_production_volume_list = (
                     custom_production_volume.custom_production_volume_list if custom_production_volume is not None else None
                 )
@@ -554,11 +565,13 @@ def main(self) -> None:  # pylint: disable=too-many-branches
             create_custom_production_volume(args.custom_production_volume) if args.custom_production_volume is not None else None
         )
 
+        task_completion_criteria = TaskCompletionCriteria(args.task_completion_criteria)
         if args.temp_dir is None:
             with tempfile.TemporaryDirectory() as str_temp_dir:
                 self.visualize_statistics(
                     temp_dir=Path(str_temp_dir),
                     task_query=task_query,
+                    task_completion_criteria=task_completion_criteria,
                     user_id_list=user_id_list,
                     actual_worktime=actual_worktime,
                     annotation_count=annotation_count,
@@ -578,6 +591,7 @@ def main(self) -> None:  # pylint: disable=too-many-branches
         else:
             self.visualize_statistics(
                 temp_dir=args.temp_dir,
+                task_completion_criteria=task_completion_criteria,
                 task_query=task_query,
                 user_id_list=user_id_list,
                 actual_worktime=actual_worktime,
@@ -614,6 +628,16 @@ def parse_args(parser: argparse.ArgumentParser) -> None:
         ),
     )
 
+    parser.add_argument(
+        "--task_completion_criteria",
+        type=str,
+        choices=[e.value for e in TaskCompletionCriteria],
+        default=TaskCompletionCriteria.ACCEPTANCE_COMPLETED.value,
+        help="タスクの完了条件を指定します。\n"
+        "* ``acceptance_completed``: タスクが受入フェーズの完了状態であれば「タスクの完了」とみなす\n"
+        "* ``acceptance_reached``: タスクが受入フェーズに到達したら「タスクの完了」とみなす\n",
+    )
+
     parser.add_argument("-o", "--output_dir", type=Path, required=True, help="出力先ディレクトリのパスを指定してください。")
 
     parser.add_argument(
diff --git a/annofabcli/task/list_tasks_added_task_history.py b/annofabcli/task/list_tasks_added_task_history.py
index bfcad902..78ccd5ad 100644
--- a/annofabcli/task/list_tasks_added_task_history.py
+++ b/annofabcli/task/list_tasks_added_task_history.py
@@ -115,6 +115,25 @@ def get_first_acceptance_completed_datetime(task_histories: list[TaskHistory]) -
 
         return None
 
+    @staticmethod
+    def get_first_acceptance_reached_datetime(task_histories: list[TaskHistory]) -> Optional[str]:
+        """はじめて受入フェーズに到達した日時を取得する。
+        受入フェーズを着手した日時とは異なる。
+        必ず`first_acceptance_started_datetime`よりも前の日時になる。
+
+        Args:
+            task_histories (List[TaskHistory]): [description]
+
+        """
+        for index, history in enumerate(task_histories):
+            if history["phase"] != TaskPhase.ACCEPTANCE.value:
+                continue
+
+            first_acceptance_reached_datetime = task_histories[index - 1]["ended_datetime"]
+            assert first_acceptance_reached_datetime is not None
+            return first_acceptance_reached_datetime
+        return None
+
     @staticmethod
     def is_acceptance_phase_skipped(task_histories: list[TaskHistory]) -> bool:
         """抜取受入によって、受入フェーズでスキップされたことがあるかを取得する。
@@ -269,6 +288,7 @@ def add_task_history_additional_info_to_task(self, task: dict[str, Any], task_hi
         self._add_task_history_info_by_phase(task, task_histories, phase=TaskPhase.ACCEPTANCE)
 
         # 初めて受入が完了した日時
+        task["first_acceptance_reached_datetime"] = self.get_first_acceptance_reached_datetime(task_histories)
         task["first_acceptance_completed_datetime"] = self.get_first_acceptance_completed_datetime(task_histories)
 
         # 受入完了日時を設定
@@ -339,6 +359,7 @@ def _get_output_target_columns() -> List[str]:
             # 差し戻し回数
             "number_of_rejections_by_inspection",
             "number_of_rejections_by_acceptance",
+            "first_acceptance_reached_datetime",
             "first_acceptance_completed_datetime",
             "completed_datetime",
             "inspection_is_skipped",
diff --git "a/docs/command_reference/statistics/visualize_output_rst/\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst" "b/docs/command_reference/statistics/visualize_output_rst/\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst"
index 58578f1b..111f12fe 100644
--- "a/docs/command_reference/statistics/visualize_output_rst/\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst"
+++ "b/docs/command_reference/statistics/visualize_output_rst/\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst"
@@ -4,7 +4,7 @@ line-graph/折れ線-横軸_日-全体.html
 
 
 タスク数や作業時間、生産性などを、日毎にプロットした折れ線グラフです。
-グラフのデータは ``日毎の生産量と生産性.csv`` を参照しています。
+グラフのデータは :doc:`日毎の生産量と生産性_csv` を参照しています。
 
 日毎のタスク数や作業時間、生産性などをの推移が分かります。
 
diff --git "a/docs/command_reference/statistics/visualize_output_rst/\346\225\231\345\270\253\344\273\230\351\226\213\345\247\213\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst" "b/docs/command_reference/statistics/visualize_output_rst/\346\225\231\345\270\253\344\273\230\351\226\213\345\247\213\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst"
index 1545334c..7f4c174a 100644
--- "a/docs/command_reference/statistics/visualize_output_rst/\346\225\231\345\270\253\344\273\230\351\226\213\345\247\213\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst"
+++ "b/docs/command_reference/statistics/visualize_output_rst/\346\225\231\345\270\253\344\273\230\351\226\213\345\247\213\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst"
@@ -9,13 +9,27 @@
 
 参照頻度が高い列の詳細を、以下に記載します。
 
-* worktime_hour: その日に教師付を開始したタスクにかけた作業時間[hour]。
-* task_count: その日に教師付開始したタスクの個数。
-* input_data_count: その日に教師付開始したタスクに含まれている入力データの個数。
-* worktime_hour/annotation_count: アノテーションあたりの計測作業時間[hour]。生産性の指標になる。
+* ``first_annotation_started_date`` : 教師付フェーズを開始した日
+* ``worktime_hour`` : その日に教師付フェーズを開始して、現在作業が完了したタスクにかけた計測作業時間（アノテーションエディタ画面を触っていた作業の時間）。単位は時間。
+* ``task_count`` : 作業が完了したタスクの数
+* ``input_data_count`` : 作業が完了したタスクに含まれている入力データの数
+* ``annotation_count`` : 作業が完了したタスクに含まれているアノテーションの数
+* ``worktime_hour/annotation_count`` : アノテーションあたりの計測作業時間。単位は時間。
+
 
 
 .. note::
 
+    ``worktime`` は、その日に教師付フェーズを開始したタスクにかけた作業時間です。その日に作業した時間ではないことに注意してください。
+
+
+``task_count`` の算出方法
+=================================
+``--task_completion_criteria`` で指定した値によって、 ``task_count`` の算出方法が異なります。
+
+``--task_completion_criteria acceptance_completed`` を指定すると、 ``task_count`` は、受入フェーズ完了状態のタスクの数になります。
+
+``--task_completion_criteria acceptance_reached`` を指定すると、 ``task_count`` は、受入フェーズタスクの数になります。
+
+
 
-    ``worktime`` （作業時間）は、その日に教師付を開始したタスクにかけた作業時間です。その日に作業した時間ではないことに、注意してください。
diff --git "a/docs/command_reference/statistics/visualize_output_rst/\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst" "b/docs/command_reference/statistics/visualize_output_rst/\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst"
index 245f88ac..cb3f9f38 100644
--- "a/docs/command_reference/statistics/visualize_output_rst/\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst"
+++ "b/docs/command_reference/statistics/visualize_output_rst/\346\227\245\346\257\216\343\201\256\347\224\237\347\224\243\351\207\217\343\201\250\347\224\237\347\224\243\346\200\247_csv.rst"
@@ -7,17 +7,39 @@
 
 `日毎の生産量と生産性.csv <https://github.com/kurusugawa-computer/annofab-cli/blob/main/docs/command_reference/statistics/visualize/out_dir/日毎の生産量と生産性.csv>`_
 
-参照頻度が高い列の詳細を、以下に記載します。
 
-* monitored_worktime_hour: 計測作業時間[hour](アノテーションエディタ画面を触っていた作業時間）
-* actual_worktime_hour: 実績作業時間[hour](労務管理画面から入力した作業時間）
-* task_count: 作業したタスク数。タスクが初めて受入完了状態になったときに「作業した」とみなしている。
-* input_data_count: 作業したタスクに含まれている入力データ数
-* actual_worktime/annotation_count: アノテーションあたりの実績作業時間[hour]。生産性の指標になる。
 
+* ``actual_worktime_hour`` : 実績作業時間（ ``--labor_csv`` で渡された実際の作業時間）。単位は時間。
+* ``monitored_worktime_hour`` : 計測作業時間（アノテーションエディタ画面を触っていた作業の時間）。単位は時間。
+* ``task_count`` : 作業が完了したタスクの数
+* ``input_data_count`` : 作業が完了したタスクに含まれている入力データの数
+* ``annotation_count`` : 作業が完了したタスクに含まれているアノテーションの数
+* ``actual_worktime_hour/annotation_count`` : アノテーションあたりの実績作業時間。単位は時間。
+* ``working_user_count`` : 作業したユーザーの数
 
-.. note::
 
-    task_count は「その日に初めて受入完了状態になったタスクの個数」です。受入完了状態のタスクが差し戻されても、task_countは変わりません。
-    受入完了状態の差し戻し後の作業量が多い場合、task_countの値が実際と合わないケースがあります。
+``task_count`` の算出方法
+=================================
+``--task_completion_criteria`` で指定した値によって、 ``task_count`` の算出方法が異なります。
+
+``--task_completion_criteria acceptance_completed`` を指定すると、 ``task_count`` は、初めて受入フェーズ完了状態になったタスクの数になります。
+受入取消によって完了状態でないタスクも、「作業が完了したタスク」に含まれます。
+
+``--task_completion_criteria acceptance_reached`` を指定すると、 ``task_count`` は、初めて受入フェーズになったタスクの数になります。
+受入フェーズでの差し戻しによって受入フェーズでないタスクも、「作業が完了したタスク」に含まれます。
+
+
+
+.. note:: 
+
+     
+    以下のタスクが多いと、 ``task_count`` の推移は実際よりも早い日にタスクが完了したように見えます。
+    
+    * 受入取消されたタスク（ ``--task_completion_criteria acceptance_completed`` の場合）
+    * 受入フェーズで差し戻されたタスク（ ``--task_completion_criteria acceptance_reached`` の場合）
+    
+    その場合は :doc:`教師付開始日毎の生産量と生産性_csv` も参照することをお勧めします。
+    :doc:`教師付開始日毎の生産量と生産性_csv` の ``task_count`` は、教師付フェーズを開始した日ごとに集計しています。
+    一度に大量のタスクの教師付けフェーズを開始する運用でなければ、 :doc:`教師付開始日毎の生産量と生産性_csv` の方が生産量の推移を正しく表しているかもしれません。
     
+    
\ No newline at end of file
diff --git "a/docs/command_reference/statistics/visualize_output_rst/\347\264\257\347\251\215\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst" "b/docs/command_reference/statistics/visualize_output_rst/\347\264\257\347\251\215\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst"
index fbf7f673..e9dd14bf 100644
--- "a/docs/command_reference/statistics/visualize_output_rst/\347\264\257\347\251\215\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst"
+++ "b/docs/command_reference/statistics/visualize_output_rst/\347\264\257\347\251\215\346\212\230\343\202\214\347\267\232-\346\250\252\350\273\270_\346\227\245-\345\205\250\344\275\223_html.rst"
@@ -3,7 +3,7 @@ line-graph/累積折れ線-横軸_日-全体.html
 ==========================================
 
 タスク数や作業時間の累積値をプロットした折れ線グラフです。
-グラフのデータは ``日毎の生産量と生産性.csv`` を参照しています。
+グラフのデータは :doc:`日毎の生産量と生産性_csv` を参照しています。
 
 
 `累積折れ線-横軸_日-全体.html <https://kurusugawa-computer.github.io/annofab-cli/command_reference/statistics/visualize/out_dir/line-graph/%E7%B4%AF%E7%A9%8D%E6%8A%98%E3%82%8C%E7%B7%9A-%E6%A8%AA%E8%BB%B8_%E6%97%A5-%E5%85%A8%E4%BD%93.html>`_
diff --git a/docs/command_reference/task/list_added_task_history.rst b/docs/command_reference/task/list_added_task_history.rst
index 570db835..a85ff3f1 100644
--- a/docs/command_reference/task/list_added_task_history.rst
+++ b/docs/command_reference/task/list_added_task_history.rst
@@ -123,6 +123,7 @@ JSON出力
         "first_acceptance_user_id": "alice",
         "first_acceptance_username": "Alice",
         "acceptance_worktime_hour": 0.16520972222222222,
+        "first_acceptance_reached_datetime": "2022-10-24T15:14:18.967+09:00",
         "first_acceptance_completed_datetime": "2022-10-25T15:14:18.967+09:00",
         "completed_datetime": "2022-10-25T15:14:18.967+09:00",
         "inspection_is_skipped": false,
@@ -139,6 +140,7 @@ JSON出力
 * annotation_worktime_hour: 教師付フェーズの作業時間[hour]
 * inspection_worktime_hour: 検査フェーズの作業時間[hour]
 * acceptance_worktime_hour: 受入フェーズの作業時間[hour]
+* first_acceptance_reached_datetime: はじめて受入フェーズに到達した日時。 ``first_annotation_started_datetime`` より前の日時になる
 * first_acceptance_completed_datetime: はじめて受入完了状態になった日時
 * completed_datetime: 受入完了状態になった日時
 * inspection_is_skipped: 抜取検査により検査フェーズがスキップされたかどうか
@@ -147,9 +149,6 @@ JSON出力
 * first_annotation_username: 最初の教師付フェーズを担当したユーザの名前
 * first_annotation_started_datetime: 最初の教師付フェーズを開始した日時
 * ...
-* last_acceptance_user_id: 最後の受入フェーズを担当したユーザのuser_id
-* last_acceptance_username: 最後の受入フェーズを担当したユーザの名前
-* last_acceptance_started_datetime: 最後の受入フェーズを開始した日時
 
 
 


Test patch:
diff --git "a/tests/data/stat_visualization/mask_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv" "b/tests/data/stat_visualization/mask_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv"
index 606db397..0a6ef3e4 100644
--- "a/tests/data/stat_visualization/mask_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv"
+++ "b/tests/data/stat_visualization/mask_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv"
@@ -1,4 +1,4 @@
-﻿project_id,task_id,phase,phase_stage,status,number_of_rejections_by_inspection,number_of_rejections_by_acceptance,created_datetime,first_annotation_user_id,first_annotation_username,first_annotation_worktime_hour,first_annotation_started_datetime,first_inspection_user_id,first_inspection_username,first_inspection_worktime_hour,first_inspection_started_datetime,first_acceptance_user_id,first_acceptance_username,first_acceptance_worktime_hour,first_acceptance_started_datetime,first_acceptance_completed_datetime,worktime_hour,annotation_worktime_hour,inspection_worktime_hour,acceptance_worktime_hour,input_data_count,annotation_count,inspection_comment_count,inspection_comment_count_in_inspection_phase,inspection_comment_count_in_acceptance_phase,inspection_is_skipped,acceptance_is_skipped
-prj1,task1,acceptance,1,complete,0,0,2023-12-27T21:53:53.72+09:00,bob,bob,0.185208888888889,2024-01-09T11:27:00.015+09:00,,,,,alice,alice,0.547898611111111,2024-01-09T13:03:11.715+09:00,2024-01-11T13:04:01.134+09:00,0.7331075,0.185208888888889,0,0.547898611111111,10,20,0,0,0,False,False
-prj1,task2,acceptance,1,complete,0,1,2023-12-27T21:54:09.075+09:00,bob,bob,0.214761944444444,2024-01-09T11:43:19.68+09:00,,,,,alice,alice,0.267357222222222,2024-01-10T15:10:43.647+09:00,2024-01-11T14:23:30.968+09:00,0.538455555555556,0.220598611111111,0,0.317856944444444,10,20,1,0,1,False,False
-prj1,task3,acceptance,1,complete,0,1,2023-12-27T21:54:24.099+09:00,bob,bob,0.195141111111111,2024-01-09T11:56:20.118+09:00,,,,,chris,chris,0.573847777777778,2024-01-09T15:23:53.291+09:00,2024-01-16T11:14:02.961+09:00,1.3610325,0.324384722222222,0,1.03664777777778,10,20,2,0,2,False,False
+﻿project_id,task_id,phase,phase_stage,status,number_of_rejections_by_inspection,number_of_rejections_by_acceptance,created_datetime,first_annotation_user_id,first_annotation_username,first_annotation_worktime_hour,first_annotation_started_datetime,first_inspection_user_id,first_inspection_username,first_inspection_worktime_hour,first_inspection_started_datetime,first_acceptance_user_id,first_acceptance_username,first_acceptance_worktime_hour,first_acceptance_reached_datetime,first_acceptance_started_datetime,first_acceptance_completed_datetime,worktime_hour,annotation_worktime_hour,inspection_worktime_hour,acceptance_worktime_hour,input_data_count,annotation_count,inspection_comment_count,inspection_comment_count_in_inspection_phase,inspection_comment_count_in_acceptance_phase,inspection_is_skipped,acceptance_is_skipped
+prj1,task1,acceptance,1,complete,0,0,2023-12-27T21:53:53.72+09:00,bob,bob,0.185208888888889,2024-01-09T11:27:00.015+09:00,,,,,alice,alice,0.547898611111111,2024-01-08T13:03:11.715+09:00,2024-01-09T13:03:11.715+09:00,2024-01-11T13:04:01.134+09:00,0.7331075,0.185208888888889,0,0.547898611111111,10,20,0,0,0,False,False
+prj1,task2,acceptance,1,complete,0,1,2023-12-27T21:54:09.075+09:00,bob,bob,0.214761944444444,2024-01-09T11:43:19.68+09:00,,,,,alice,alice,0.267357222222222,2024-01-09T15:10:43.647+09:00,2024-01-10T15:10:43.647+09:00,2024-01-11T14:23:30.968+09:00,0.538455555555556,0.220598611111111,0,0.317856944444444,10,20,1,0,1,False,False
+prj1,task3,acceptance,1,complete,0,1,2023-12-27T21:54:24.099+09:00,bob,bob,0.195141111111111,2024-01-09T11:56:20.118+09:00,,,,,chris,chris,0.573847777777778,2024-01-08T15:23:53.291+09:00,2024-01-09T15:23:53.291+09:00,2024-01-16T11:14:02.961+09:00,1.3610325,0.324384722222222,0,1.03664777777778,10,20,2,0,2,False,False
diff --git a/tests/data/stat_visualization/merge_visualization_dir/visualization1/project_info.json b/tests/data/stat_visualization/merge_visualization_dir/visualization1/project_info.json
index 5633a5b6..65c20f00 100644
--- a/tests/data/stat_visualization/merge_visualization_dir/visualization1/project_info.json
+++ b/tests/data/stat_visualization/merge_visualization_dir/visualization1/project_info.json
@@ -3,6 +3,7 @@
   "project_title": "PRJECT1",
   "input_data_type": "image",
   "measurement_datetime": "2024-02-17T01:22:54.025+09:00",
+  "task_completion_criteria": "acceptance_completed",
   "query": {
     "task_query": null,
     "task_ids": null,
diff --git "a/tests/data/stat_visualization/merge_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv" "b/tests/data/stat_visualization/merge_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv"
index 606db397..0a6ef3e4 100644
--- "a/tests/data/stat_visualization/merge_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv"
+++ "b/tests/data/stat_visualization/merge_visualization_dir/visualization1/\343\202\277\343\202\271\343\202\257list.csv"
@@ -1,4 +1,4 @@
-﻿project_id,task_id,phase,phase_stage,status,number_of_rejections_by_inspection,number_of_rejections_by_acceptance,created_datetime,first_annotation_user_id,first_annotation_username,first_annotation_worktime_hour,first_annotation_started_datetime,first_inspection_user_id,first_inspection_username,first_inspection_worktime_hour,first_inspection_started_datetime,first_acceptance_user_id,first_acceptance_username,first_acceptance_worktime_hour,first_acceptance_started_datetime,first_acceptance_completed_datetime,worktime_hour,annotation_worktime_hour,inspection_worktime_hour,acceptance_worktime_hour,input_data_count,annotation_count,inspection_comment_count,inspection_comment_count_in_inspection_phase,inspection_comment_count_in_acceptance_phase,inspection_is_skipped,acceptance_is_skipped
-prj1,task1,acceptance,1,complete,0,0,2023-12-27T21:53:53.72+09:00,bob,bob,0.185208888888889,2024-01-09T11:27:00.015+09:00,,,,,alice,alice,0.547898611111111,2024-01-09T13:03:11.715+09:00,2024-01-11T13:04:01.134+09:00,0.7331075,0.185208888888889,0,0.547898611111111,10,20,0,0,0,False,False
-prj1,task2,acceptance,1,complete,0,1,2023-12-27T21:54:09.075+09:00,bob,bob,0.214761944444444,2024-01-09T11:43:19.68+09:00,,,,,alice,alice,0.267357222222222,2024-01-10T15:10:43.647+09:00,2024-01-11T14:23:30.968+09:00,0.538455555555556,0.220598611111111,0,0.317856944444444,10,20,1,0,1,False,False
-prj1,task3,acceptance,1,complete,0,1,2023-12-27T21:54:24.099+09:00,bob,bob,0.195141111111111,2024-01-09T11:56:20.118+09:00,,,,,chris,chris,0.573847777777778,2024-01-09T15:23:53.291+09:00,2024-01-16T11:14:02.961+09:00,1.3610325,0.324384722222222,0,1.03664777777778,10,20,2,0,2,False,False
+﻿project_id,task_id,phase,phase_stage,status,number_of_rejections_by_inspection,number_of_rejections_by_acceptance,created_datetime,first_annotation_user_id,first_annotation_username,first_annotation_worktime_hour,first_annotation_started_datetime,first_inspection_user_id,first_inspection_username,first_inspection_worktime_hour,first_inspection_started_datetime,first_acceptance_user_id,first_acceptance_username,first_acceptance_worktime_hour,first_acceptance_reached_datetime,first_acceptance_started_datetime,first_acceptance_completed_datetime,worktime_hour,annotation_worktime_hour,inspection_worktime_hour,acceptance_worktime_hour,input_data_count,annotation_count,inspection_comment_count,inspection_comment_count_in_inspection_phase,inspection_comment_count_in_acceptance_phase,inspection_is_skipped,acceptance_is_skipped
+prj1,task1,acceptance,1,complete,0,0,2023-12-27T21:53:53.72+09:00,bob,bob,0.185208888888889,2024-01-09T11:27:00.015+09:00,,,,,alice,alice,0.547898611111111,2024-01-08T13:03:11.715+09:00,2024-01-09T13:03:11.715+09:00,2024-01-11T13:04:01.134+09:00,0.7331075,0.185208888888889,0,0.547898611111111,10,20,0,0,0,False,False
+prj1,task2,acceptance,1,complete,0,1,2023-12-27T21:54:09.075+09:00,bob,bob,0.214761944444444,2024-01-09T11:43:19.68+09:00,,,,,alice,alice,0.267357222222222,2024-01-09T15:10:43.647+09:00,2024-01-10T15:10:43.647+09:00,2024-01-11T14:23:30.968+09:00,0.538455555555556,0.220598611111111,0,0.317856944444444,10,20,1,0,1,False,False
+prj1,task3,acceptance,1,complete,0,1,2023-12-27T21:54:24.099+09:00,bob,bob,0.195141111111111,2024-01-09T11:56:20.118+09:00,,,,,chris,chris,0.573847777777778,2024-01-08T15:23:53.291+09:00,2024-01-09T15:23:53.291+09:00,2024-01-16T11:14:02.961+09:00,1.3610325,0.324384722222222,0,1.03664777777778,10,20,2,0,2,False,False
diff --git a/tests/data/stat_visualization/summarize_whole_performance_csv/visualization1/project_info.json b/tests/data/stat_visualization/summarize_whole_performance_csv/visualization1/project_info.json
index 5633a5b6..65c20f00 100644
--- a/tests/data/stat_visualization/summarize_whole_performance_csv/visualization1/project_info.json
+++ b/tests/data/stat_visualization/summarize_whole_performance_csv/visualization1/project_info.json
@@ -3,6 +3,7 @@
   "project_title": "PRJECT1",
   "input_data_type": "image",
   "measurement_datetime": "2024-02-17T01:22:54.025+09:00",
+  "task_completion_criteria": "acceptance_completed",
   "query": {
     "task_query": null,
     "task_ids": null,
diff --git a/tests/data/stat_visualization/write_performance_rating_csv/visualization1/project_info.json b/tests/data/stat_visualization/write_performance_rating_csv/visualization1/project_info.json
index 5633a5b6..d50fcd34 100644
--- a/tests/data/stat_visualization/write_performance_rating_csv/visualization1/project_info.json
+++ b/tests/data/stat_visualization/write_performance_rating_csv/visualization1/project_info.json
@@ -3,6 +3,7 @@
   "project_title": "PRJECT1",
   "input_data_type": "image",
   "measurement_datetime": "2024-02-17T01:22:54.025+09:00",
+  "task_completion_criteria": "acceptance_completed", 
   "query": {
     "task_query": null,
     "task_ids": null,
diff --git "a/tests/data/stat_visualization/write_performance_rating_csv/visualization1/\343\203\241\343\203\263\343\203\220\343\201\224\343\201\250\343\201\256\347\224\237\347\224\243\346\200\247\343\201\250\345\223\201\350\263\252.csv" "b/tests/data/stat_visualization/write_performance_rating_csv/visualization1/\343\203\241\343\203\263\343\203\220\343\201\224\343\201\250\343\201\256\347\224\237\347\224\243\346\200\247\343\201\250\345\223\201\350\263\252.csv"
index a532e995..d4def0e8 100644
--- "a/tests/data/stat_visualization/write_performance_rating_csv/visualization1/\343\203\241\343\203\263\343\203\220\343\201\224\343\201\250\343\201\256\347\224\237\347\224\243\346\200\247\343\201\250\345\223\201\350\263\252.csv"
+++ "b/tests/data/stat_visualization/write_performance_rating_csv/visualization1/\343\203\241\343\203\263\343\203\220\343\201\224\343\201\250\343\201\256\347\224\237\347\224\243\346\200\247\343\201\250\345\223\201\350\263\252.csv"
@@ -1,14 +1,14 @@
-﻿account_id,user_id,username,biography,first_working_date,last_working_date,working_days,real_monitored_worktime_hour,real_monitored_worktime_hour,real_monitored_worktime_hour,real_monitored_worktime_hour,monitored_worktime_hour,monitored_worktime_hour,monitored_worktime_hour,monitored_worktime_ratio,monitored_worktime_ratio,task_count,task_count,input_data_count,input_data_count,annotation_count,annotation_count,real_actual_worktime_hour,real_monitored_worktime_hour/real_actual_worktime_hour,actual_worktime_hour,actual_worktime_hour,actual_worktime_hour,monitored_worktime_hour/input_data_count,monitored_worktime_hour/input_data_count,actual_worktime_hour/input_data_count,actual_worktime_hour/input_data_count,monitored_worktime_hour/annotation_count,monitored_worktime_hour/annotation_count,actual_worktime_hour/annotation_count,actual_worktime_hour/annotation_count,pointed_out_inspection_comment_count,pointed_out_inspection_comment_count/input_data_count,pointed_out_inspection_comment_count/annotation_count,rejected_count,rejected_count/task_count,stdev__monitored_worktime_hour/input_data_count,stdev__monitored_worktime_hour/input_data_count,stdev__actual_worktime_hour/input_data_count,stdev__actual_worktime_hour/input_data_count,stdev__monitored_worktime_hour/annotation_count,stdev__monitored_worktime_hour/annotation_count,stdev__actual_worktime_hour/annotation_count,stdev__actual_worktime_hour/annotation_count
-,,,,,,,sum,annotation,inspection,acceptance,sum,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,sum,sum,sum,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,annotation,annotation,annotation,annotation,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance
-BW,BW,BW,category-KT,2023-11-21,2023-11-22,2,6.851844166666666,6.851844166666666,0.0,0.0,6.851844166666667,6.851844166666667,0.0,1.0,0.0,6.8896269504352485,0.0,106.31642764870466,0.0,704.6874322762493,0.0,7.083333333,0.9673191765161091,7.083333333000001,7.083333333000001,0.0,0.06444765233559979,,0.06662501261239756,,0.009723238776281494,,0.010051737846550973,,17.751501370050605,0.1669685650904852,0.025190603034753314,5.8896269504352485,0.8548542602968038,0.026679475026360432,,0.027580839576083944,,0.003011881696243145,,0.00311363794842848,
-CW,CW,CW,category-KT,2023-12-29,2023-12-29,1,0.1918455555555555,0.0,0.0,0.1918455555555555,0.1918455555555554,0.0,0.1918455555555554,0.0,1.0,0.0,0.5081261027073752,0.0,7.950989195100896,0.0,49.951637418952345,0.0,inf,0.0,0.0,0.0,,0.024128514182079824,,0.0,,0.0038406259627991003,,0.0,0.0,,,0.0,,,0.006901641498016899,,0.0,,0.0010296655042690527,,0.0
-DB,DB,DB,category-AH,2023-10-26,2023-11-22,11,40.81871361111111,19.350416666666668,0.0,21.46829694444444,40.81871361111111,19.350416666666668,21.468296944444443,0.4740574838056475,0.5259425161943526,24.37134758126235,75.50248589269926,381.31605181319634,1165.1062617307773,2933.576654251046,7997.957713291435,47.0,0.8684832683215129,47.0,22.28070173886543,24.719298261134572,0.050746399409763845,0.01842604202689038,0.05843106166897104,0.021216346588347916,0.0065961857988697786,0.002684222362012152,0.007595063761698017,0.003090701294913665,20.144676943152188,0.05282934418145319,0.006866933889032876,14.180195040232665,0.581838775757109,0.0205619883671736,0.010859332868754762,0.023675744965027397,0.012503790533284785,0.0017076237220000545,0.0011590161490904949,0.001966213724877301,0.001334529047785209
-EM,EM,EM,category-KT,2023-10-25,2024-01-11,9,14.509523055555555,11.46961361111111,0.0,3.039909444444444,14.509523055555555,11.46961361111111,3.0399094444444437,0.7904886719704758,0.20951132802952419,10.0,12.768327488075311,153.0,202.03695764154702,923.0,1640.040348797696,15.000000001,0.9673015369725502,15.000000001,11.857330080347625,3.142669920652374,0.07496479484386347,0.015046303804662492,0.07749888941403676,0.01555492597660317,0.012426450282893945,0.0018535577168409202,0.01284651146299851,0.0019162150022444552,30.0,0.19607843137254902,0.032502708559046585,12.0,1.2,0.028652605322638077,0.008824855452095989,0.029621172124169974,0.009123169058240026,0.0035644133299973977,0.0010819754887946894,0.0036849040281205997,0.001118550366601344
-ML,ML,ML,category-MK,2023-10-27,2024-01-09,9,15.325856111111111,15.325856111111111,0.0,0.0,15.325856111111111,15.325856111111111,0.0,1.0,0.0,9.0,0.0,140.0,0.0,1178.0,0.0,15.399999999,0.9951854618250842,15.399999999,15.399999999,0.0,0.1094704007936508,,0.10999999999285714,,0.013010064610450858,,0.013073005092529712,,39.0,0.2785714285714286,0.03310696095076401,12.0,1.3333333333333333,0.05252036437899548,,0.05277444897826146,,0.0016837689578328727,,0.001691914745966029,
-ND,ND,ND,category-KT,2023-10-26,2023-12-31,7,4.471973055555556,4.471973055555556,0.0,0.0,4.471973055555556,4.471973055555556,0.0,1.0,0.0,6.0881462418786745,0.0,95.3521360018727,0.0,510.08979562286163,0.0,7.75,0.5770287813620072,7.75,7.75,0.0,0.0468995582381891,,0.08127767583358375,,0.008767031008912672,,0.015193403331146063,,9.20623485744993,0.09654985450214898,0.018048263141999067,5.0881462418786745,0.8357463897431904,0.018154105632067503,,0.03146135204766894,,0.0012317972708939186,,0.0021347241431985573,
-NQ,NQ,NQ,category-MK,2023-11-16,2024-01-09,7,8.284593888888889,8.284593888888889,0.0,0.0,8.284593888888889,8.284593888888889,0.0,1.0,0.0,7.075329646405803,0.0,109.15792130391111,0.0,681.6541185465711,0.0,8.866666667,0.9343526942004629,8.866666667,8.866666667,0.0,0.07589548967155033,,0.08122788123011197,,0.012153662192423002,,0.013007574407245693,,23.0753296464058,0.21139400027745872,0.03385196248151074,8.075329646405802,1.1413361708889407,0.03639715076641981,,0.0389544023283042,,0.002675968505040457,,0.0028639811514968834,
-QE,QE,QE,category-KT,2023-10-26,2024-01-10,10,19.636556666666667,19.636556666666667,0.0,0.0,19.636556666666667,19.636556666666667,0.0,1.0,0.0,13.069062790192323,0.0,204.03594185288483,0.0,1534.3594185288484,0.0,20.383333334,0.963363368733823,20.383333334,20.383333334,0.0,0.09624067450246158,,0.09990069959682352,,0.012797885834007717,,0.013284588400769647,,11.207188370576967,0.054927520459398464,0.00730414806025206,7.069062790192322,0.5409005147253022,0.02715101838851306,,0.02818356942946507,,0.006019410129269445,,0.006248327811323088,
-RQ,RQ,RQ,category-MK,2023-11-17,2024-01-03,6,11.732706666666667,11.732706666666667,0.0,0.0,11.732706666666667,11.732706666666667,0.0,1.0,0.0,11.0,0.0,171.0,0.0,1272.0,0.0,12.1,0.9696451790633609,12.1,12.1,0.0,0.06861231968810916,,0.07076023391812865,,0.009223825995807127,,0.009512578616352201,,43.0,0.25146198830409355,0.03380503144654088,11.0,1.0,0.020828611429587012,,0.021480652798899727,,0.0018650764116650278,,0.001923462779928033,
-SK,SK,SK,category-KT,2023-10-27,2024-01-13,11,5.926304444444445,0.6270641666666666,0.0,5.299240277777778,5.926304444444443,0.6270641666666662,5.299240277777777,0.10581031949084246,0.8941896805091576,1.5064867898256038,19.88416237028506,22.821521379430365,309.4089089788781,79.63258077442372,2141.0393928747303,7.416666666999999,0.7990522846082824,7.416666666999998,0.7847598695923514,6.631906797407646,0.027476878348340773,0.017126980264616527,0.034386834100362654,0.02143411713416557,0.00787446746756782,0.0024750783640008576,0.0098547587176077,0.0030975174111594083,0.6150688123645079,0.026951262456975614,0.007723833717091521,0.6976393308552876,0.46309024119358444,0.02150022289202632,0.015643948555234398,0.026907154020048042,0.019578128811562685,0.0014024817882802457,0.0012862304348123643,0.0017551815010050074,0.00160969495937667
-TR,TR,TR,category-KT,2023-10-26,2023-11-22,9,19.23942138888889,19.23942138888889,0.0,0.0,19.23942138888889,19.23942138888889,0.0,1.0,0.0,9.0,0.0,139.0,0.0,1098.0,0.0,19.683333333,0.9774473186730587,19.683333333,19.683333333,0.0,0.13841310351718625,,0.14160671462589927,,0.0175222417020846,,0.017926533090163933,,49.0,0.35251798561151076,0.044626593806921674,11.0,1.2222222222222223,0.08909981711510603,,0.09115562078175651,,0.004185852612146469,,0.0042824329579511326,
-XT,XT,XT,category-MK,2023-10-26,2024-01-15,11,18.969883333333332,18.536526388888888,0.0,0.4333569444444443,18.969883333333332,18.536526388888888,0.43335694444444434,0.9771555292760835,0.022844470723916474,12.0,1.3368981462329987,183.0,20.496882453696607,1077.0,163.01090761718706,20.683333334,0.9171579371178997,20.683333334,20.21083353117843,0.4724998028215687,0.10129249392835457,0.021142578410322518,0.11044171328512803,0.023052276554201223,0.01721125941401011,0.0026584536628808594,0.018765862145940976,0.002898577829719112,39.0,0.21311475409836064,0.036211699164345405,10.0,0.8333333333333334,0.03824212262251798,0.006231775179058627,0.04169633285046956,0.006794658724364872,0.0024773018750205403,0.00026103198405534356,0.002701063551611706,0.00028460963318446223
+﻿account_id,user_id,username,biography,first_working_date,last_working_date,working_days,first_working_date,first_working_date,first_working_date,last_working_date,last_working_date,last_working_date,working_days,working_days,working_days,real_monitored_worktime_hour,real_monitored_worktime_hour,real_monitored_worktime_hour,real_monitored_worktime_hour,monitored_worktime_hour,monitored_worktime_hour,monitored_worktime_hour,monitored_worktime_ratio,monitored_worktime_ratio,task_count,task_count,input_data_count,input_data_count,annotation_count,annotation_count,real_actual_worktime_hour,real_monitored_worktime_hour/real_actual_worktime_hour,actual_worktime_hour,actual_worktime_hour,actual_worktime_hour,monitored_worktime_hour/input_data_count,monitored_worktime_hour/input_data_count,actual_worktime_hour/input_data_count,actual_worktime_hour/input_data_count,monitored_worktime_hour/annotation_count,monitored_worktime_hour/annotation_count,actual_worktime_hour/annotation_count,actual_worktime_hour/annotation_count,pointed_out_inspection_comment_count,pointed_out_inspection_comment_count/input_data_count,pointed_out_inspection_comment_count/annotation_count,rejected_count,rejected_count/task_count,stdev__monitored_worktime_hour/input_data_count,stdev__monitored_worktime_hour/input_data_count,stdev__actual_worktime_hour/input_data_count,stdev__actual_worktime_hour/input_data_count,stdev__monitored_worktime_hour/annotation_count,stdev__monitored_worktime_hour/annotation_count,stdev__actual_worktime_hour/annotation_count,stdev__actual_worktime_hour/annotation_count
+,,,,,,,annotation,inspection,acceptance,annotation,inspection,acceptance,annotation,inspection,acceptance,sum,annotation,inspection,acceptance,sum,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,sum,sum,sum,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,annotation,annotation,annotation,annotation,annotation,acceptance,annotation,acceptance,annotation,acceptance,annotation,acceptance
+BW,BW,BW,category-KT,2023-11-21,2023-11-22,2,,,,,,,,,,6.85184416666667,6.85184416666667,0,0,6.85184416666667,6.85184416666667,0,1,0,6.88962695043525,0,106.316427648705,0,704.687432276249,0,7.083333333,0.967319176516109,7.083333333,7.083333333,0,0.0644476523355998,,0.0666250126123976,,0.00972323877628149,,0.010051737846551,,17.7515013700506,0.166968565090485,0.0251906030347533,5.88962695043525,0.854854260296804,0.0266794750263604,,0.0275808395760839,,0.00301188169624315,,0.00311363794842848,
+CW,CW,CW,category-KT,2023-12-29,2023-12-29,1,,,,,,,,,,0.191845555555556,0,0,0.191845555555556,0.191845555555555,0,0.191845555555555,0,1,0,0.508126102707375,0,7.9509891951009,0,49.9516374189523,0,inf,0,0,0,,0.0241285141820798,,0,,0.0038406259627991,,0,0,,,0,,,0.0069016414980169,,0,,0.00102966550426905,,0
+DB,DB,DB,category-AH,2023-10-26,2023-11-22,11,,,,,,,,,,40.8187136111111,19.3504166666667,0,21.4682969444444,40.8187136111111,19.3504166666667,21.4682969444444,0.474057483805648,0.525942516194353,24.3713475812624,75.5024858926993,381.316051813196,1165.10626173078,2933.57665425105,7997.95771329144,47,0.868483268321513,47,22.2807017388654,24.7192982611346,0.0507463994097638,0.0184260420268904,0.058431061668971,0.0212163465883479,0.00659618579886978,0.00268422236201215,0.00759506376169802,0.00309070129491367,20.1446769431522,0.0528293441814532,0.00686693388903288,14.1801950402327,0.581838775757109,0.0205619883671736,0.0108593328687548,0.0236757449650274,0.0125037905332848,0.00170762372200005,0.00115901614909049,0.0019662137248773,0.00133452904778521
+EM,EM,EM,category-KT,2023-10-25,2024-01-11,9,,,,,,,,,,14.5095230555556,11.4696136111111,0,3.03990944444444,14.5095230555556,11.4696136111111,3.03990944444444,0.790488671970476,0.209511328029524,10,12.7683274880753,153,202.036957641547,923,1640.0403487977,15.000000001,0.96730153697255,15.000000001,11.8573300803476,3.14266992065237,0.0749647948438635,0.0150463038046625,0.0774988894140368,0.0155549259766032,0.0124264502828939,0.00185355771684092,0.0128465114629985,0.00191621500224446,30,0.196078431372549,0.0325027085590466,12,1.2,0.0286526053226381,0.00882485545209599,0.02962117212417,0.00912316905824003,0.0035644133299974,0.00108197548879469,0.0036849040281206,0.00111855036660134
+ML,ML,ML,category-MK,2023-10-27,2024-01-09,9,,,,,,,,,,15.3258561111111,15.3258561111111,0,0,15.3258561111111,15.3258561111111,0,1,0,9,0,140,0,1178,0,15.399999999,0.995185461825084,15.399999999,15.399999999,0,0.109470400793651,,0.109999999992857,,0.0130100646104509,,0.0130730050925297,,39,0.278571428571429,0.033106960950764,12,1.33333333333333,0.0525203643789955,,0.0527744489782615,,0.00168376895783287,,0.00169191474596603,
+ND,ND,ND,category-KT,2023-10-26,2023-12-31,7,,,,,,,,,,4.47197305555556,4.47197305555556,0,0,4.47197305555556,4.47197305555556,0,1,0,6.08814624187867,0,95.3521360018727,0,510.089795622862,0,7.75,0.577028781362007,7.75,7.75,0,0.0468995582381891,,0.0812776758335838,,0.00876703100891267,,0.0151934033311461,,9.20623485744993,0.096549854502149,0.0180482631419991,5.08814624187867,0.83574638974319,0.0181541056320675,,0.0314613520476689,,0.00123179727089392,,0.00213472414319856,
+NQ,NQ,NQ,category-MK,2023-11-16,2024-01-09,7,,,,,,,,,,8.28459388888889,8.28459388888889,0,0,8.28459388888889,8.28459388888889,0,1,0,7.0753296464058,0,109.157921303911,0,681.654118546571,0,8.866666667,0.934352694200463,8.866666667,8.866666667,0,0.0758954896715503,,0.081227881230112,,0.012153662192423,,0.0130075744072457,,23.0753296464058,0.211394000277459,0.0338519624815107,8.0753296464058,1.14133617088894,0.0363971507664198,,0.0389544023283042,,0.00267596850504046,,0.00286398115149688,
+QE,QE,QE,category-KT,2023-10-26,2024-01-10,10,,,,,,,,,,19.6365566666667,19.6365566666667,0,0,19.6365566666667,19.6365566666667,0,1,0,13.0690627901923,0,204.035941852885,0,1534.35941852885,0,20.383333334,0.963363368733823,20.383333334,20.383333334,0,0.0962406745024616,,0.0999006995968235,,0.0127978858340077,,0.0132845884007696,,11.207188370577,0.0549275204593985,0.00730414806025206,7.06906279019232,0.540900514725302,0.0271510183885131,,0.0281835694294651,,0.00601941012926945,,0.00624832781132309,
+RQ,RQ,RQ,category-MK,2023-11-17,2024-01-03,6,,,,,,,,,,11.7327066666667,11.7327066666667,0,0,11.7327066666667,11.7327066666667,0,1,0,11,0,171,0,1272,0,12.1,0.969645179063361,12.1,12.1,0,0.0686123196881092,,0.0707602339181287,,0.00922382599580713,,0.0095125786163522,,43,0.251461988304094,0.0338050314465409,11,1,0.020828611429587,,0.0214806527988997,,0.00186507641166503,,0.00192346277992803,
+SK,SK,SK,category-KT,2023-10-27,2024-01-13,11,,,,,,,,,,5.92630444444445,0.627064166666667,0,5.29924027777778,5.92630444444444,0.627064166666666,5.29924027777778,0.105810319490842,0.894189680509158,1.5064867898256,19.8841623702851,22.8215213794304,309.408908978878,79.6325807744237,2141.03939287473,7.416666667,0.799052284608282,7.416666667,0.784759869592351,6.63190679740765,0.0274768783483408,0.0171269802646165,0.0343868341003627,0.0214341171341656,0.00787446746756782,0.00247507836400086,0.0098547587176077,0.00309751741115941,0.615068812364508,0.0269512624569756,0.00772383371709152,0.697639330855288,0.463090241193584,0.0215002228920263,0.0156439485552344,0.026907154020048,0.0195781288115627,0.00140248178828025,0.00128623043481236,0.00175518150100501,0.00160969495937667
+TR,TR,TR,category-KT,2023-10-26,2023-11-22,9,,,,,,,,,,19.2394213888889,19.2394213888889,0,0,19.2394213888889,19.2394213888889,0,1,0,9,0,139,0,1098,0,19.683333333,0.977447318673059,19.683333333,19.683333333,0,0.138413103517186,,0.141606714625899,,0.0175222417020846,,0.0179265330901639,,49,0.352517985611511,0.0446265938069217,11,1.22222222222222,0.089099817115106,,0.0911556207817565,,0.00418585261214647,,0.00428243295795113,
+XT,XT,XT,category-MK,2023-10-26,2024-01-15,11,,,,,,,,,,18.9698833333333,18.5365263888889,0,0.433356944444444,18.9698833333333,18.5365263888889,0.433356944444444,0.977155529276084,0.0228444707239165,12,1.336898146233,183,20.4968824536966,1077,163.010907617187,20.683333334,0.9171579371179,20.683333334,20.2108335311784,0.472499802821569,0.101292493928355,0.0211425784103225,0.110441713285128,0.0230522765542012,0.0172112594140101,0.00265845366288086,0.018765862145941,0.00289857782971911,39,0.213114754098361,0.0362116991643454,10,0.833333333333333,0.038242122622518,0.00623177517905863,0.0416963328504696,0.00679465872436487,0.00247730187502054,0.000261031984055344,0.00270106355161171,0.000284609633184462
diff --git a/tests/data/statistics/task.csv b/tests/data/statistics/task.csv
index c385a556..e11ba999 100644
--- a/tests/data/statistics/task.csv
+++ b/tests/data/statistics/task.csv
@@ -1,6 +1,6 @@
-project_id,task_id,phase,phase_stage,status,number_of_rejections,number_of_rejections_by_inspection,number_of_rejections_by_acceptance,created_datetime,started_datetime,updated_datetime,first_acceptance_completed_datetime,sampling,first_annotation_user_id,first_annotation_username,first_annotation_worktime_hour,first_annotation_started_datetime,first_inspection_user_id,first_inspection_username,first_inspection_worktime_hour,first_inspection_started_datetime,first_acceptance_user_id,first_acceptance_username,first_acceptance_worktime_hour,first_acceptance_started_datetime,worktime_hour,annotation_worktime_hour,inspection_worktime_hour,acceptance_worktime_hour,input_data_count,annotation_count,inspection_comment_count,inspection_comment_count_in_inspection_phase,inspection_comment_count_in_acceptance_phase,inspection_is_skipped,acceptance_is_skipped,diff_days_to_first_inspection_started,diff_days_to_first_acceptance_started,diff_days_to_first_acceptance_completed,custom_production_volume1,custom_production_volume2
-12345678-abcd-1234-abcd-1234abcd5678,task1,acceptance,1,complete,1,0,1,2019-11-01T00:00:00.000+09:00,2019-11-25T04:18:05.8+09:00,2019-11-25T04:21:32.721+09:00,2019-11-25T04:21:32.56+09:00,,user1,user1,0.458071666666667,2019-11-21T22:35:32.238+09:00,user1,user1,0,2019-11-22T20:26:36.833+09:00,user1,user1,0.209477777777778,2019-11-22T20:26:36.833+09:00,0.787161388888889,0.520250277777778,1,0.266911111111111,10,41,9,0,9,False,True,,0.910469849537037,3.24028150462963,400,50
-12345678-abcd-1234-abcd-1234abcd5678,task2,acceptance,1,complete,2,0,2,2019-11-01T00:00:00.000+09:00,2019-11-15T13:40:32.074+09:00,2019-11-15T13:43:35.02+09:00,2019-11-15T13:43:34.974+09:00,,user1,user1,0.801513055555556,2019-11-13T14:46:41.236+09:00,user2,user2,0,2019-11-15T10:12:26.528+09:00,user2,user2,0.350685555555556,2019-11-15T10:12:26.528+09:00,1.70834722222222,1.25867722222222,2,0.44967,10,65,7,0,7,True,False,,1.80955199074074,1.95617752314815,600,70
-12345678-abcd-1234-abcd-1234abcd5678,task10,acceptance,1,complete,0,0,0,2019-11-01T00:00:00.000+09:00,2019-11-14T09:15:50.754+09:00,2019-11-14T09:18:49.676+09:00,2019-11-14T09:18:49.616+09:00,,user4,user4,0.217835277777778,2019-11-11T13:26:27.456+09:00,user4,user4,0,2019-11-14T09:15:50.754+09:00,user4,user4,0.049683888888889,2019-11-14T09:15:50.754+09:00,0.267519166666667,0.217835277777778,3,0.049683888888889,10,30,0,0,0,False,False,,2.82596409722222,2.82803425925926,300,20
-12345678-abcd-1234-abcd-1234abcd5678,task4,acceptance,1,not_started,0,0,0,2019-11-01T00:00:00.000+09:00,2019-11-25T22:05:23.501+09:00,2019-11-25T22:09:02.157+09:00,,,user4,user4,0.060726388888889,2019-11-25T22:05:23.501+09:00,,,0,,,,0,,0.060726388888889,0.060726388888889,0,0,10,10,0,0,0,False,False,,,,100,5
-12345678-abcd-1234-abcd-1234abcd5678,task5,annotation,1,not_started,0,0,0,2019-11-01T00:00:00.000+09:00,,2019-11-08T22:54:26.981+09:00,,,user5,user5,0.029444166666667,2019-11-26T09:27:22.776+09:00,,,0,,,,0,,0.029444166666667,0.029444166666667,0,0,10,0,0,0,0,False,False,,,,0,0
+project_id,task_id,phase,phase_stage,status,number_of_rejections,number_of_rejections_by_inspection,number_of_rejections_by_acceptance,created_datetime,started_datetime,updated_datetime,first_acceptance_completed_datetime,sampling,first_annotation_user_id,first_annotation_username,first_annotation_worktime_hour,first_annotation_started_datetime,first_inspection_user_id,first_inspection_username,first_inspection_worktime_hour,first_inspection_started_datetime,first_acceptance_reached_datetime,first_acceptance_user_id,first_acceptance_username,first_acceptance_worktime_hour,first_acceptance_started_datetime,worktime_hour,annotation_worktime_hour,inspection_worktime_hour,acceptance_worktime_hour,input_data_count,annotation_count,inspection_comment_count,inspection_comment_count_in_inspection_phase,inspection_comment_count_in_acceptance_phase,inspection_is_skipped,acceptance_is_skipped,diff_days_to_first_inspection_started,diff_days_to_first_acceptance_started,diff_days_to_first_acceptance_completed,custom_production_volume1,custom_production_volume2
+12345678-abcd-1234-abcd-1234abcd5678,task1,acceptance,1,complete,1,0,1,2019-11-01T00:00:00.000+09:00,2019-11-25T04:18:05.8+09:00,2019-11-25T04:21:32.721+09:00,2019-11-25T04:21:32.56+09:00,,user1,user1,0.458071666666667,2019-11-21T22:35:32.238+09:00,user1,user1,0,2019-11-22T20:26:36.833+09:00,2019-11-20T20:26:36.833+09:00,user1,user1,0.209477777777778,2019-11-22T20:26:36.833+09:00,0.787161388888889,0.520250277777778,1,0.266911111111111,10,41,9,0,9,False,True,,0.910469849537037,3.24028150462963,400,50
+12345678-abcd-1234-abcd-1234abcd5678,task2,acceptance,1,complete,2,0,2,2019-11-01T00:00:00.000+09:00,2019-11-15T13:40:32.074+09:00,2019-11-15T13:43:35.02+09:00,2019-11-15T13:43:34.974+09:00,,user1,user1,0.801513055555556,2019-11-13T14:46:41.236+09:00,user2,user2,0,2019-11-15T10:12:26.528+09:00,2019-11-14T10:12:26.528+09:00,user2,user2,0.350685555555556,2019-11-15T10:12:26.528+09:00,1.70834722222222,1.25867722222222,2,0.44967,10,65,7,0,7,True,False,,1.80955199074074,1.95617752314815,600,70
+12345678-abcd-1234-abcd-1234abcd5678,task10,acceptance,1,complete,0,0,0,2019-11-01T00:00:00.000+09:00,2019-11-14T09:15:50.754+09:00,2019-11-14T09:18:49.676+09:00,2019-11-14T09:18:49.616+09:00,,user4,user4,0.217835277777778,2019-11-11T13:26:27.456+09:00,user4,user4,0,2019-11-14T09:15:50.754+09:00,2019-11-13T09:15:50.754+09:00,user4,user4,0.049683888888889,2019-11-14T09:15:50.754+09:00,0.267519166666667,0.217835277777778,3,0.049683888888889,10,30,0,0,0,False,False,,2.82596409722222,2.82803425925926,300,20
+12345678-abcd-1234-abcd-1234abcd5678,task4,acceptance,1,not_started,0,0,0,2019-11-01T00:00:00.000+09:00,2019-11-25T22:05:23.501+09:00,2019-11-25T22:09:02.157+09:00,,,user4,user4,0.060726388888889,2019-11-25T22:05:23.501+09:00,,,0,,,,,0,,0.060726388888889,0.060726388888889,0,0,10,10,0,0,0,False,False,,,,100,5
+12345678-abcd-1234-abcd-1234abcd5678,task5,annotation,1,not_started,0,0,0,2019-11-01T00:00:00.000+09:00,,2019-11-08T22:54:26.981+09:00,,,user5,user5,0.029444166666667,2019-11-26T09:27:22.776+09:00,,,0,,,,,0,,0.029444166666667,0.029444166666667,0,0,10,0,0,0,0,False,False,,,,0,0
diff --git a/tests/data/statistics/visualization-dir1/project_info.json b/tests/data/statistics/visualization-dir1/project_info.json
index c96a2dce..54cde007 100644
--- a/tests/data/statistics/visualization-dir1/project_info.json
+++ b/tests/data/statistics/visualization-dir1/project_info.json
@@ -3,6 +3,7 @@
   "project_title": "test-project",
   "input_data_type": "image",
   "measurement_datetime": "2022-06-14T15:56:10.634+09:00",
+  "task_completion_criteria": "acceptance_reached",
   "query": {
     "task_query": null,
     "task_ids": null,
diff --git a/tests/stat_visualization/test_mask_visualization_dir.py b/tests/stat_visualization/test_mask_visualization_dir.py
index c953e420..32d45871 100644
--- a/tests/stat_visualization/test_mask_visualization_dir.py
+++ b/tests/stat_visualization/test_mask_visualization_dir.py
@@ -1,7 +1,7 @@
 from pathlib import Path
 
 from annofabcli.stat_visualization.mask_visualization_dir import mask_visualization_dir
-from annofabcli.statistics.visualization.project_dir import ProjectDir
+from annofabcli.statistics.visualization.project_dir import ProjectDir, TaskCompletionCriteria
 
 output_dir = Path("./tests/out/stat_visualization/mask_visualization_dir")
 data_dir = Path("./tests/data/stat_visualization/mask_visualization_dir")
@@ -10,7 +10,7 @@
 
 def test__mask_visualization_dir__minimal():
     mask_visualization_dir(
-        project_dir=ProjectDir(data_dir / "visualization1"),
-        output_project_dir=ProjectDir(output_dir / "masked-visualization"),
+        project_dir=ProjectDir(data_dir / "visualization1", TaskCompletionCriteria.ACCEPTANCE_COMPLETED),
+        output_project_dir=ProjectDir(output_dir / "masked-visualization", TaskCompletionCriteria.ACCEPTANCE_COMPLETED),
         minimal_output=True,
     )
diff --git a/tests/statistics/visualization/dataframe/test_project_performance.py b/tests/statistics/visualization/dataframe/test_project_performance.py
index 8fec16b8..c093a7d2 100644
--- a/tests/statistics/visualization/dataframe/test_project_performance.py
+++ b/tests/statistics/visualization/dataframe/test_project_performance.py
@@ -6,7 +6,7 @@
     ProjectPerformance,
     ProjectWorktimePerMonth,
 )
-from annofabcli.statistics.visualization.model import WorktimeColumn
+from annofabcli.statistics.visualization.model import TaskCompletionCriteria, WorktimeColumn
 from annofabcli.statistics.visualization.project_dir import ProjectDir
 
 output_dir = Path("./tests/out/statistics/visualization/dataframe/project_performance")
@@ -16,7 +16,7 @@
 
 class TestProjectPerformance:
     def test__from_project_dirs__and__to_csv(self):
-        actual = ProjectPerformance.from_project_dirs([ProjectDir(data_dir / "visualization-dir1")])
+        actual = ProjectPerformance.from_project_dirs([ProjectDir(data_dir / "visualization-dir1", TaskCompletionCriteria.ACCEPTANCE_COMPLETED)])
         df = actual.df
         assert len(df) == 1
         row = df.iloc[0]
@@ -30,7 +30,7 @@ def test__from_project_dirs__and__to_csv(self):
         actual.to_csv(output_dir / "test__from_project_dirs__and__to_csv.csv")
 
     def test__from_project_dirs__空ディレクトから生成する(self):
-        actual = ProjectPerformance.from_project_dirs([ProjectDir(data_dir / "empty")])
+        actual = ProjectPerformance.from_project_dirs([ProjectDir(data_dir / "empty", TaskCompletionCriteria.ACCEPTANCE_COMPLETED)])
         df = actual.df
         assert len(df) == 1
         row = df.iloc[0]
@@ -46,7 +46,8 @@ def test__from_project_dirs__空ディレクトから生成する(self):
 class TestProjectWorktimePerMonth:
     def test__from_project_dirs__and_to_csv(self):
         actual_worktime = ProjectWorktimePerMonth.from_project_dirs(
-            [ProjectDir(data_dir / "visualization-dir1")], worktime_column=WorktimeColumn.ACTUAL_WORKTIME_HOUR
+            [ProjectDir(data_dir / "visualization-dir1", TaskCompletionCriteria.ACCEPTANCE_COMPLETED)],
+            worktime_column=WorktimeColumn.ACTUAL_WORKTIME_HOUR,
         )
         df = actual_worktime.df
         assert len(df) == 1
@@ -59,7 +60,7 @@ def test__from_project_dirs__and_to_csv(self):
 
     def test__from_project_dirs__空ディレクトリから生成(self):
         actual_worktime = ProjectWorktimePerMonth.from_project_dirs(
-            [ProjectDir(data_dir / "empty")], worktime_column=WorktimeColumn.ACTUAL_WORKTIME_HOUR
+            [ProjectDir(data_dir / "empty", TaskCompletionCriteria.ACCEPTANCE_COMPLETED)], worktime_column=WorktimeColumn.ACTUAL_WORKTIME_HOUR
         )
         df = actual_worktime.df
         assert len(df) == 1
diff --git a/tests/statistics/visualization/dataframe/test_whole_productivity_per_date.py b/tests/statistics/visualization/dataframe/test_whole_productivity_per_date.py
index 51c7de5b..fced0c49 100644
--- a/tests/statistics/visualization/dataframe/test_whole_productivity_per_date.py
+++ b/tests/statistics/visualization/dataframe/test_whole_productivity_per_date.py
@@ -6,7 +6,7 @@
     WholeProductivityPerFirstAnnotationStartedDate,
 )
 from annofabcli.statistics.visualization.dataframe.worktime_per_date import WorktimePerDate
-from annofabcli.statistics.visualization.model import ProductionVolumeColumn
+from annofabcli.statistics.visualization.model import ProductionVolumeColumn, TaskCompletionCriteria
 
 output_dir = Path("./tests/out/statistics/visualization/dataframe/whole_productivity_per_date")
 data_dir = Path("./tests/data/statistics")
@@ -27,22 +27,40 @@ def setup_class(cls) -> None:
             ],
         )
         worktime_per_date = WorktimePerDate.from_csv(data_dir / "ユーザ_日付list-作業時間.csv")
-        cls.main_obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date)
+        cls.main_obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date, TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
 
         cls.output_dir = output_dir / "WholeProductivityPerCompletedDate"
         cls.output_dir.mkdir(exist_ok=True, parents=True)
 
-    def test__from_df_wrapper(cls):
+    def test__from_df_wrapper__task_completion_criteria_is_acceptance_completed(cls):
         task = Task.from_csv(
             data_dir / "task.csv",
         )
         worktime_per_date = WorktimePerDate.from_csv(data_dir / "ユーザ_日付list-作業時間.csv")
-        WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date)
+        obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date, TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
+        df_actual = obj.df
+        assert df_actual["task_count"].sum() == 3
+        assert df_actual[df_actual["date"] == "2019-11-14"].iloc[0]["task_count"] == 1
+        assert df_actual[df_actual["date"] == "2019-11-15"].iloc[0]["task_count"] == 1
+        assert df_actual[df_actual["date"] == "2019-11-25"].iloc[0]["task_count"] == 1
+
+    def test__from_df_wrapper__task_completion_criteria_is_acceptance_reached(cls):
+        task = Task.from_csv(
+            data_dir / "task.csv",
+        )
+        worktime_per_date = WorktimePerDate.from_csv(data_dir / "ユーザ_日付list-作業時間.csv")
+        obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, worktime_per_date, TaskCompletionCriteria.ACCEPTANCE_REACHED)
+        df_actual = obj.df
+
+        assert df_actual["task_count"].sum() == 3
+        assert df_actual[df_actual["date"] == "2019-11-13"].iloc[0]["task_count"] == 1
+        assert df_actual[df_actual["date"] == "2019-11-14"].iloc[0]["task_count"] == 1
+        assert df_actual[df_actual["date"] == "2019-11-20"].iloc[0]["task_count"] == 1
 
     def test_from_df__df_worktime引数が空でもインスタンスを生成できることを確認する(self):
         # 完了タスクが１つもない状態で試す
         task = Task.from_csv(data_dir / "task.csv")
-        obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, WorktimePerDate.empty())
+        obj = WholeProductivityPerCompletedDate.from_df_wrapper(task, WorktimePerDate.empty(), TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
         df_actual = obj.df
 
         # 日毎の完了したタスク数が一致していることの確認
@@ -73,6 +91,22 @@ def setup_class(cls) -> None:
         cls.output_dir = output_dir / "WholeProductivityPerFirstAnnotationStartedDate"
         cls.output_dir.mkdir(exist_ok=True, parents=True)
 
+    def test__from_task__task_completion_criteria_is_acceptance_completed(self):
+        task = Task.from_csv(
+            data_dir / "task.csv",
+        )
+        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task, TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
+        df_actual = obj.df
+        assert df_actual["task_count"].sum() == 3
+
+    def test__from_task__task_completion_criteria_is_acceptance_reached(cls):
+        task = Task.from_csv(
+            data_dir / "task.csv",
+        )
+        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task, TaskCompletionCriteria.ACCEPTANCE_REACHED)
+        df_actual = obj.df
+        assert df_actual["task_count"].sum() == 4
+
     def test__from_task__and__to_csv(self):
         task = Task.from_csv(
             data_dir / "task.csv",
@@ -81,7 +115,7 @@ def test__from_task__and__to_csv(self):
                 ProductionVolumeColumn("custom_production_volume2", "custom_生産量2"),
             ],
         )
-        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task)
+        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task, TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
         obj.to_csv(self.output_dir / "test__from_task__and__to_csv.csv")
 
     def test__from_task__and__plot(self):
@@ -92,5 +126,5 @@ def test__from_task__and__plot(self):
                 ProductionVolumeColumn("custom_production_volume2", "custom_生産量2"),
             ],
         )
-        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task)
+        obj = WholeProductivityPerFirstAnnotationStartedDate.from_task(task, TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
         obj.plot(self.output_dir / "test__from_task__and__plot.html")
diff --git a/tests/statistics/visualization/test_write_performance_rating_csv.py b/tests/statistics/visualization/test_write_performance_rating_csv.py
index d55d360d..7db11152 100644
--- a/tests/statistics/visualization/test_write_performance_rating_csv.py
+++ b/tests/statistics/visualization/test_write_performance_rating_csv.py
@@ -14,7 +14,7 @@
     create_quality_indicator_by_directory,
     create_threshold_infos_per_project,
 )
-from annofabcli.statistics.visualization.project_dir import ProjectDir
+from annofabcli.statistics.visualization.project_dir import ProjectDir, TaskCompletionCriteria
 
 data_dir = Path("tests/data/stat_visualization")
 
@@ -41,7 +41,7 @@ def test__create_quality_indicator_by_directory():
         ("biography", ""): ["category-KK", "category-KT", "category-KT", "category-KT"],
     }
 )
-project_dir = ProjectDir(data_dir / "visualization-dir")
+project_dir = ProjectDir(data_dir / "visualization-dir", TaskCompletionCriteria.ACCEPTANCE_COMPLETED)
 
 user_performance = project_dir.read_user_performance()