You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@devlake.apache.org by wa...@apache.org on 2022/11/21 11:08:35 UTC

[incubator-devlake] branch feat-plugin-zentao updated: Feat zentao account (#3771)

This is an automated email from the ASF dual-hosted git repository.

warren pushed a commit to branch feat-plugin-zentao
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/feat-plugin-zentao by this push:
     new 79fff9519 Feat zentao account (#3771)
79fff9519 is described below

commit 79fff95191c08785957fa2cf463c6ebd6c36a68f
Author: Warren Chen <yi...@merico.dev>
AuthorDate: Mon Nov 21 19:08:30 2022 +0800

    Feat zentao account (#3771)
    
    * fix(zentao): use const to indicate status and type
    
    * feat(zentao): add account
    
    * feat(zentao): add account subtasks
    
    * fix(zentao): modify issues
---
 plugins/helper/iso8601time.go                      |   7 +
 .../e2e/raw_tables/_raw_zentao_api_executions.csv  |   3 +-
 .../raw_tables/_raw_zentao_api_executions_real.csv |   2 +
 .../e2e/raw_tables/_raw_zentao_api_stories.csv     |  14 +-
 .../snapshot_tables/_tool_zentao_executions.csv    |   2 +-
 .../e2e/snapshot_tables/_tool_zentao_stories.csv   |  14 +-
 .../e2e/snapshot_tables/_tool_zentao_tasks.csv     |   6 +-
 plugins/zentao/e2e/snapshot_tables/issues_bug.csv  |   8 +-
 plugins/zentao/impl/impl.go                        |   6 +
 .../zentao/{tasks/shared.go => models/account.go}  |  26 +-
 .../shared.go => models/archived/account.go}       |  26 +-
 plugins/zentao/models/archived/bug.go              | 124 ++++----
 plugins/zentao/models/archived/department.go       |  39 +++
 plugins/zentao/models/archived/execution.go        |  75 +++--
 plugins/zentao/models/archived/product.go          |  30 +-
 plugins/zentao/models/archived/project.go          |  84 ++---
 plugins/zentao/models/archived/story.go            |  44 +--
 plugins/zentao/models/archived/task.go             |  64 ++--
 plugins/zentao/models/bug.go                       | 279 ++++++++---------
 plugins/zentao/models/department.go                |  41 +++
 plugins/zentao/models/execution.go                 | 337 +++++++++------------
 ..._init_tables.go => 20221121_add_init_tables.go} |  22 +-
 plugins/zentao/models/product.go                   |  96 +++---
 plugins/zentao/models/project.go                   |  84 ++---
 plugins/zentao/models/story.go                     | 179 +++++------
 plugins/zentao/models/task.go                      | 209 ++++++-------
 .../{story_collector.go => account_collector.go}   |  23 +-
 .../{product_convertor.go => account_convertor.go} |  45 ++-
 .../{story_collector.go => account_extractor.go}   |  58 ++--
 plugins/zentao/tasks/bug_convertor.go              |  14 +-
 plugins/zentao/tasks/bug_extractor.go              |  14 +-
 ...{story_collector.go => department_collector.go} |  23 +-
 ...roduct_convertor.go => department_convertor.go} |  42 ++-
 ...{story_collector.go => department_extractor.go} |  58 ++--
 plugins/zentao/tasks/execution_convertor.go        |   2 +-
 plugins/zentao/tasks/execution_extractor.go        |  17 +-
 plugins/zentao/tasks/product_convertor.go          |   2 +-
 plugins/zentao/tasks/product_extractor.go          |   8 +-
 plugins/zentao/tasks/shared.go                     |  15 +
 plugins/zentao/tasks/story_collector.go            |   2 +-
 plugins/zentao/tasks/story_convertor.go            |  16 +-
 plugins/zentao/tasks/story_extractor.go            |  14 +-
 plugins/zentao/tasks/task_convertor.go             |  18 +-
 plugins/zentao/tasks/task_extractor.go             |  19 +-
 44 files changed, 1079 insertions(+), 1132 deletions(-)

diff --git a/plugins/helper/iso8601time.go b/plugins/helper/iso8601time.go
index 3029adb19..564d7f739 100644
--- a/plugins/helper/iso8601time.go
+++ b/plugins/helper/iso8601time.go
@@ -64,6 +64,10 @@ func init() {
 			Matcher: regexp.MustCompile(`[+-][\d]{2}:[\d]{2}$`),
 			Format:  "2006-01-02T15:04:05-07:00",
 		},
+		{
+			Matcher: regexp.MustCompile(`[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2}$`),
+			Format:  "2006-01-02 15:04:05",
+		},
 		{
 			Matcher: regexp.MustCompile(`[+-][\d]{2}-[\d]{2}$`),
 			Format:  "2006-01-02",
@@ -96,6 +100,9 @@ func (jt *Iso8601Time) UnmarshalJSON(b []byte) error {
 	if timeString == "null" {
 		return nil
 	}
+	if strings.Contains(timeString, "0000-00-00") {
+		return nil
+	}
 	timeString = strings.Trim(timeString, `"`)
 	t, err := ConvertStringToTime(timeString)
 	if err != nil {
diff --git a/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions.csv b/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions.csv
index 6f48b125c..7df7b5849 100644
--- a/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions.csv
+++ b/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions.csv
@@ -1,2 +1,3 @@
 id,params,data,url,input,created_at
-1,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":1,""project"":7,""model"":"""",""type"":""sprint"",""lifetime"":""sprint"",""budget"":""0"",""budgetUnit"":""CNY"",""attribute"":"""",""percent"":0,""milestone"":""0"",""output"":"""",""auth"":"""",""parent"":7,""path"":"",7,1,"",""grade"":1,""name"":""\u4f01\u4e1a\u7f51\u7ad9\u7b2c\u4e00\u671f"",""code"":""coWeb1"",""begin"":""2020-06-05"",""end"":""2021-12-04"",""realBegan"":null,""realEnd"":null,""days [...]
+1,"{""ConnectionId"":1,""ProductId"":1,""ExecutionId"":12,""ProjectId"":1}","{""id"":12,""project"":1091,""model"":"""",""type"":""sprint"",""lifetime"":""short"",""budget"":""0"",""budgetUnit"":""CNY"",""attribute"":"""",""percent"":0,""milestone"":""0"",""output"":"""",""auth"":"""",""parent"":1091,""path"":"",1091,12,"",""grade"":1,""name"":""TR5"",""code"":""0.1.3"",""begin"":""2022-11-01"",""end"":""2022-11-03"",""realBegan"":""2022-07-07"",""realEnd"":null,""days"":"""",""status"": [...]
+2,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":1,""project"":7,""model"":"""",""type"":""sprint"",""lifetime"":""short"",""budget"":""0"",""budgetUnit"":""CNY"",""attribute"":"""",""percent"":0,""milestone"":""0"",""output"":"""",""auth"":"""",""parent"":7,""path"":"",7,1,"",""grade"":1,""name"":""\u4f01\u4e1a\u7f51\u7ad9\u7b2c\u4e00\u671f"",""code"":""coWeb1"",""begin"":""2022-05-01"",""end"":""2022-06-01"",""realBegan"":null,""realEnd"":null,""days" [...]
diff --git a/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions_real.csv b/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions_real.csv
new file mode 100644
index 000000000..9c755cee3
--- /dev/null
+++ b/plugins/zentao/e2e/raw_tables/_raw_zentao_api_executions_real.csv
@@ -0,0 +1,2 @@
+id,params,data,url,input,created_at
+1,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":1,""project"":1091,""model"":"""",""type"":""sprint"",""lifetime"":""short"",""budget"":""0"",""budgetUnit"":""CNY"",""attribute"":"""",""percent"":0,""milestone"":""0"",""output"":"""",""auth"":"""",""parent"":1091,""path"":"",1091,12,"",""grade"":1,""name"":""TR5"",""code"":""0.1.3"",""begin"":""2022-11-01"",""end"":""2022-11-03"",""realBegan"":""2022-07-07"",""realEnd"":null,""days"":0,""status"":""don [...]
diff --git a/plugins/zentao/e2e/raw_tables/_raw_zentao_api_stories.csv b/plugins/zentao/e2e/raw_tables/_raw_zentao_api_stories.csv
index dd79bc2f1..b346e0450 100644
--- a/plugins/zentao/e2e/raw_tables/_raw_zentao_api_stories.csv
+++ b/plugins/zentao/e2e/raw_tables/_raw_zentao_api_stories.csv
@@ -1,8 +1,8 @@
 id,params,data,url,input,created_at
-1,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":7,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":7,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u5173\u4e8e\u6211\u4eec\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""reviewing"",""subStatus"":"""",""color"":"""",""stage"":""planned"",""stagedB [...]
-2,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":6,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":6,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u5408\u4f5c\u6d3d\u8c08\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""reviewing"",""subStatus"":"""",""color"":"""",""stage"":""planned"",""stagedB [...]
-3,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":5,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":5,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u8bda\u8058\u82f1\u624d\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""reviewing"",""subStatus"":"""",""color"":"""",""stage"":""planned"",""stagedB [...]
-4,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":4,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":4,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u552e\u540e\u670d\u52a1\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""developed"",""stagedBy [...]
-5,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":3,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":3,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u6210\u679c\u5c55\u793a\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":0,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""developing"",""stagedB [...]
-6,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":2,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":2,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u65b0\u95fb\u4e2d\u5fc3\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1\u3002"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""projected"",""st [...]
-7,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":1,""vision"":""rnd"",""parent"":0,""product"":1,""branch"":0,""module"":1,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u9996\u9875\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""developing"",""stagedBy"":"""",""mailto" [...]
+1,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":7,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":7,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u5173\u4e8e\u6211\u4eec\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""reviewing"",""subStatus"":"""",""color"":"""",""stage"":""planned"",""stagedB [...]
+2,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":6,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":6,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u5408\u4f5c\u6d3d\u8c08\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""reviewing"",""subStatus"":"""",""color"":"""",""stage"":""planned"",""stagedB [...]
+3,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":5,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":5,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u8bda\u8058\u82f1\u624d\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""reviewing"",""subStatus"":"""",""color"":"""",""stage"":""planned"",""stagedB [...]
+4,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":4,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":4,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u552e\u540e\u670d\u52a1\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""developed"",""stagedBy [...]
+5,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":3,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":3,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u6210\u679c\u5c55\u793a\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":0,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""developing"",""stagedB [...]
+6,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":2,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":2,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u65b0\u95fb\u4e2d\u5fc3\u7684\u8bbe\u8ba1\u548c\u5f00\u53d1\u3002"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""projected"",""st [...]
+7,"{""ConnectionId"":1,""ProductId"":3,""ExecutionId"":1,""ProjectId"":1}","{""id"":1,""vision"":""rnd"",""parent"":0,""product"":3,""branch"":0,""module"":1,""plan"":""1"",""source"":""po"",""sourceNote"":"""",""fromBug"":0,""feedback"":0,""title"":""\u9996\u9875\u8bbe\u8ba1\u548c\u5f00\u53d1"",""keywords"":"""",""type"":""story"",""category"":""feature"",""pri"":1,""estimate"":1,""status"":""active"",""subStatus"":"""",""color"":"""",""stage"":""developing"",""stagedBy"":"""",""mailto" [...]
diff --git a/plugins/zentao/e2e/snapshot_tables/_tool_zentao_executions.csv b/plugins/zentao/e2e/snapshot_tables/_tool_zentao_executions.csv
index 74ccea041..10e80b83e 100644
--- a/plugins/zentao/e2e/snapshot_tables/_tool_zentao_executions.csv
+++ b/plugins/zentao/e2e/snapshot_tables/_tool_zentao_executions.csv
@@ -1,2 +1,2 @@
 connection_id,id,project,model,type,lifetime,budget,budget_unit,attribute,percent,milestone,output,auth,parent,path,grade,name,code,plan_begin,plan_end,real_began,real_end,days,status,sub_status,pri,description,version,parent_version,plan_duration,real_duration,opened_by_id,opened_date,opened_version,last_edited_by_id,last_edited_date,closed_by_id,closed_date,canceled_by_id,canceled_date,suspended_date,po_id,pm_id,qd_id,rd_id,team,acl,order_in,vision,display_cards,fluid_board,deleted,tot [...]
-1,1,7,,sprint,sprint,0,CNY,,0,0,,,7,",7,1,",1,企业网站第一期,coWeb1,2020-06-05,2021-12-04,,,391,doing,,1,开发企业网站的基本雏形。<br />,0,0,0,0,0,,,0,,0,,0,,0000-00-00,2,3,10,2,公司开发团队,open,5,rnd,0,0,0,11753,52,40,29,0,58.921,0
+1,1,7,,sprint,short,0,CNY,,0,0,,,7,",7,1,",1,企业网站第一期,coWeb1,2022-05-01T00:00:00.000+00:00,2022-06-01T00:00:00.000+00:00,,,0,doing,,1,开发企业网站的基本雏形。<br />,0,0,0,0,0,,,1,2022-11-21T06:00:56.000+00:00,0,,0,,,2,3,10,2,公司开发团队,open,5,rnd,0,0,0,11753,52,51.5,27.5,0,65.2,0
diff --git a/plugins/zentao/e2e/snapshot_tables/_tool_zentao_stories.csv b/plugins/zentao/e2e/snapshot_tables/_tool_zentao_stories.csv
index c36663ef0..2ece4f19a 100644
--- a/plugins/zentao/e2e/snapshot_tables/_tool_zentao_stories.csv
+++ b/plugins/zentao/e2e/snapshot_tables/_tool_zentao_stories.csv
@@ -1,8 +1,8 @@
 connection_id,id,product,branch,version,order_in,vision,parent,module,plan,source,source_note,from_bug,feedback,title,keywords,type,category,pri,estimate,status,sub_status,color,stage,lib,from_story,from_version,opened_by_id,opened_by_name,opened_date,assigned_to_id,assigned_to_name,assigned_date,approved_date,last_edited_id,last_edited_date,changed_date,reviewed_by_id,reviewed_date,closed_id,closed_date,closed_reason,activated_date,to_bug,child_stories,link_stories,link_requirements,dup [...]
-1,1,1,0,1,0,rnd,0,1,1,po,,0,0,首页设计和开发,,story,feature,1,1,active,,,developing,0,0,1,2,产品经理,2012-06-05T02:09:49.000+00:00,2,产品经理,,0000-00-00,2,2012-06-05T02:25:19.000+00:00,0000-00-00 00:00:00,0,2012-06-04T16:00:00.000+00:00,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
-1,2,1,0,1,0,rnd,0,2,1,po,,0,0,新闻中心的设计和开发。,,story,feature,1,1,active,,,projected,0,0,1,2,产品经理,2012-06-05T02:16:37.000+00:00,2,产品经理,2012-06-05T02:16:37.000+00:00,0000-00-00,2,2012-06-05T02:25:33.000+00:00,0000-00-00 00:00:00,0,2012-06-04T16:00:00.000+00:00,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
-1,3,1,0,2,0,rnd,0,3,1,po,,0,0,成果展示的设计和开发,,story,feature,1,0,active,,,developing,0,0,1,2,产品经理,2012-06-05T02:18:10.000+00:00,2,产品经理,2012-06-05T02:18:10.000+00:00,0000-00-00,2,2012-06-05T02:25:38.000+00:00,0000-00-00 00:00:00,0,2012-06-04T16:00:00.000+00:00,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
-1,4,1,0,1,0,rnd,0,4,1,po,,0,0,售后服务的设计和开发,,story,feature,1,1,active,,,developed,0,0,1,2,产品经理,2012-06-05T02:20:16.000+00:00,2,产品经理,2012-06-05T02:20:16.000+00:00,0000-00-00,2,2012-06-05T02:25:42.000+00:00,0000-00-00 00:00:00,0,2012-06-04T16:00:00.000+00:00,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
-1,5,1,0,1,0,rnd,0,5,1,po,,0,0,诚聘英才的设计和开发,,story,feature,1,1,reviewing,,,planned,0,0,1,2,产品经理,2012-06-05T02:21:39.000+00:00,2,产品经理,2012-06-05T02:21:39.000+00:00,0000-00-00,0,,0000-00-00 00:00:00,0,,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
-1,6,1,0,1,0,rnd,0,6,1,po,,0,0,合作洽谈的设计和开发,,story,feature,1,1,reviewing,,,planned,0,0,1,2,产品经理,2012-06-05T02:23:11.000+00:00,2,产品经理,2012-06-05T02:23:11.000+00:00,0000-00-00,0,,0000-00-00 00:00:00,0,,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
-1,7,1,0,1,0,rnd,0,7,1,po,,0,0,关于我们的设计和开发,,story,feature,1,1,reviewing,,,planned,0,0,1,2,产品经理,2012-06-05T02:24:19.000+00:00,2,产品经理,2012-06-05T02:24:19.000+00:00,0000-00-00,0,,0000-00-00 00:00:00,0,,0,,,0000-00-00 00:00:00,0,,,,0,0,,,0,0,1,1.0版本 
+1,1,3,0,1,0,rnd,0,1,1,po,,0,0,首页设计和开发,,story,feature,1,1,active,,,developing,0,0,1,2,产品经理,2012-06-05T02:09:49.000+00:00,2,产品经理,,,2,2012-06-05T02:25:19.000+00:00,,0,2012-06-04T16:00:00.000+00:00,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
+1,2,3,0,1,0,rnd,0,2,1,po,,0,0,新闻中心的设计和开发。,,story,feature,1,1,active,,,projected,0,0,1,2,产品经理,2012-06-05T02:16:37.000+00:00,2,产品经理,2012-06-05T02:16:37.000+00:00,,2,2012-06-05T02:25:33.000+00:00,,0,2012-06-04T16:00:00.000+00:00,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
+1,3,3,0,2,0,rnd,0,3,1,po,,0,0,成果展示的设计和开发,,story,feature,1,0,active,,,developing,0,0,1,2,产品经理,2012-06-05T02:18:10.000+00:00,2,产品经理,2012-06-05T02:18:10.000+00:00,,2,2012-06-05T02:25:38.000+00:00,,0,2012-06-04T16:00:00.000+00:00,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
+1,4,3,0,1,0,rnd,0,4,1,po,,0,0,售后服务的设计和开发,,story,feature,1,1,active,,,developed,0,0,1,2,产品经理,2012-06-05T02:20:16.000+00:00,2,产品经理,2012-06-05T02:20:16.000+00:00,,2,2012-06-05T02:25:42.000+00:00,,0,2012-06-04T16:00:00.000+00:00,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
+1,5,3,0,1,0,rnd,0,5,1,po,,0,0,诚聘英才的设计和开发,,story,feature,1,1,reviewing,,,planned,0,0,1,2,产品经理,2012-06-05T02:21:39.000+00:00,2,产品经理,2012-06-05T02:21:39.000+00:00,,0,,,0,,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
+1,6,3,0,1,0,rnd,0,6,1,po,,0,0,合作洽谈的设计和开发,,story,feature,1,1,reviewing,,,planned,0,0,1,2,产品经理,2012-06-05T02:23:11.000+00:00,2,产品经理,2012-06-05T02:23:11.000+00:00,,0,,,0,,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
+1,7,3,0,1,0,rnd,0,7,1,po,,0,0,关于我们的设计和开发,,story,feature,1,1,reviewing,,,planned,0,0,1,2,产品经理,2012-06-05T02:24:19.000+00:00,2,产品经理,2012-06-05T02:24:19.000+00:00,,0,,,0,,0,,,,0,,,,0,0,,,0,0,1,1.0版本 
diff --git a/plugins/zentao/e2e/snapshot_tables/_tool_zentao_tasks.csv b/plugins/zentao/e2e/snapshot_tables/_tool_zentao_tasks.csv
index 6604084b3..c2c174cef 100644
--- a/plugins/zentao/e2e/snapshot_tables/_tool_zentao_tasks.csv
+++ b/plugins/zentao/e2e/snapshot_tables/_tool_zentao_tasks.csv
@@ -1,4 +1,4 @@
 connection_id,id,execution_id,project,parent,execution,module,design,story,story_version,design_version,from_bug,feedback,from_issue,name,type,mode,pri,estimate,consumed,deadline,status,sub_status,color,description,version,opened_by_id,opened_by_name,opened_date,assigned_to_id,assigned_to_name,assigned_date,est_started,real_started,finished_id,finished_date,finished_list,canceled_id,canceled_date,closed_by_id,closed_date,plan_duration,real_duration,closed_reason,last_edited_id,last_edite [...]
-1,1,1,13,0,9,0,0,0,1,0,0,0,0,任务名称,devel,,3,0,0,2022-10-01,wait,,,任务描述<span> </span><br /><div><br /></div>,1,1,devlake,2022-09-19T01:50:37.000+00:00,5,开发乙,2022-09-19T01:50:37.000+00:00,2022-09-20,,0,,,0,,0,,0,0,,0,,0000-00-00 00:00:00,0,0,0,,,,,0,rnd,0,,0,0,,开发乙,3,0,21.11
-1,2,1,13,0,9,0,0,0,1,0,0,0,0,任务名称,devel,,3,12.1,2.1,2022-10-01,wait,,,任务描述<span> </span><br /><div><br /></div>,1,1,devlake,2022-09-19T01:50:37.000+00:00,5,开发乙,2022-09-19T01:50:37.000+00:00,2022-09-20,,0,,,0,,0,,0,0,,0,,0000-00-00 00:00:00,0,0,0,,,,,0,rnd,0,,0,0,,开发乙,3,0,3
-1,3,1,13,0,9,0,0,0,1,0,0,0,0,任务名称,devel,,3,11.2,0,2022-10-01,wait,,,任务描述<span> </span><br /><div><br /></div>,1,1,devlake,2022-09-19T01:50:37.000+00:00,5,开发乙,2022-09-19T01:50:37.000+00:00,2022-09-20,,0,,,0,,0,,0,0,,0,,0000-00-00 00:00:00,0,0,0,,,,,0,rnd,0,,0,0,,开发乙,3,0,43.22121
+1,1,1,13,0,9,0,0,0,1,0,0,0,0,任务名称,devel,,3,0,0,2022-10-01,wait,,,任务描述<span> </span><br /><div><br /></div>,1,1,devlake,2022-09-19T01:50:37.000+00:00,5,开发乙,2022-09-19T01:50:37.000+00:00,2022-09-20,,0,,,0,,0,,0,0,,0,,,0,0,0,,,,,0,rnd,0,,0,0,,开发乙,3,0,21.11
+1,2,1,13,0,9,0,0,0,1,0,0,0,0,任务名称,devel,,3,12.1,2.1,2022-10-01,wait,,,任务描述<span> </span><br /><div><br /></div>,1,1,devlake,2022-09-19T01:50:37.000+00:00,5,开发乙,2022-09-19T01:50:37.000+00:00,2022-09-20,,0,,,0,,0,,0,0,,0,,,0,0,0,,,,,0,rnd,0,,0,0,,开发乙,3,0,3
+1,3,1,13,0,9,0,0,0,1,0,0,0,0,任务名称,devel,,3,11.2,0,2022-10-01,wait,,,任务描述<span> </span><br /><div><br /></div>,1,1,devlake,2022-09-19T01:50:37.000+00:00,5,开发乙,2022-09-19T01:50:37.000+00:00,2022-09-20,,0,,,0,,0,,0,0,,0,,,0,0,0,,,,,0,rnd,0,,0,0,,开发乙,3,0,43.22121
diff --git a/plugins/zentao/e2e/snapshot_tables/issues_bug.csv b/plugins/zentao/e2e/snapshot_tables/issues_bug.csv
index 0bb589b18..9a3babe2a 100644
--- a/plugins/zentao/e2e/snapshot_tables/issues_bug.csv
+++ b/plugins/zentao/e2e/snapshot_tables/issues_bug.csv
@@ -1,5 +1,5 @@
 id,url,icon_url,issue_key,title,description,epic_key,type,status,original_status,story_point,resolution_date,created_date,updated_date,lead_time_minutes,parent_issue_id,priority,original_estimate_minutes,time_spent_minutes,time_remaining_minutes,creator_id,creator_name,assignee_id,assignee_name,severity,component,deployment_id
-zentao:ZentaoBug:1:1,,,1,首页页面问题,,,codeerror,IN_PROGRESS,active,0,,2012-06-05T02:56:11.000+00:00,2021-04-28T03:09:08.000+00:00,0,zentao:ZentaoStory:1:1,,0,0,0,7,测试甲,4,开发甲,,,
-zentao:ZentaoBug:1:2,,,2,新闻中心页面问题,,,codeerror,IN_PROGRESS,delay,0,,2012-06-05T02:57:11.000+00:00,2022-10-05T04:19:22.000+00:00,0,zentao:ZentaoStory:1:2,,0,0,0,7,测试甲,0,,,,
-zentao:ZentaoBug:1:3,,,3,成果展示页面问题,,,codeerror,IN_PROGRESS,active,0,,2012-06-05T02:58:22.000+00:00,2021-04-28T03:09:08.000+00:00,0,zentao:ZentaoStory:1:3,,0,0,0,8,测试乙,4,开发甲,,,
-zentao:ZentaoBug:1:4,,,4,售后服务页面问题,,,codeerror,DONE,resolved,0,,2012-06-05T03:00:19.000+00:00,2022-10-05T04:10:08.000+00:00,0,zentao:ZentaoStory:1:4,,0,0,0,9,测试丙,9,测试丙,,,
+zentao:ZentaoBug:1:1,,,1,首页页面问题,,,BUG,IN_PROGRESS,active,0,,2012-06-05T02:56:11.000+00:00,2021-04-28T03:09:08.000+00:00,0,zentao:ZentaoStory:1:1,,0,0,0,7,测试甲,4,开发甲,,,
+zentao:ZentaoBug:1:2,,,2,新闻中心页面问题,,,BUG,IN_PROGRESS,delay,0,,2012-06-05T02:57:11.000+00:00,2022-10-05T04:19:22.000+00:00,0,zentao:ZentaoStory:1:2,,0,0,0,7,测试甲,0,,,,
+zentao:ZentaoBug:1:3,,,3,成果展示页面问题,,,BUG,IN_PROGRESS,active,0,,2012-06-05T02:58:22.000+00:00,2021-04-28T03:09:08.000+00:00,0,zentao:ZentaoStory:1:3,,0,0,0,8,测试乙,4,开发甲,,,
+zentao:ZentaoBug:1:4,,,4,售后服务页面问题,,,BUG,DONE,resolved,0,,2012-06-05T03:00:19.000+00:00,2022-10-05T04:10:08.000+00:00,0,zentao:ZentaoStory:1:4,,0,0,0,9,测试丙,9,测试丙,,,
diff --git a/plugins/zentao/impl/impl.go b/plugins/zentao/impl/impl.go
index 573b8eb16..8b10c1e9e 100644
--- a/plugins/zentao/impl/impl.go
+++ b/plugins/zentao/impl/impl.go
@@ -67,6 +67,12 @@ func (plugin Zentao) SubTaskMetas() []core.SubTaskMeta {
 		tasks.CollectTaskMeta,
 		tasks.ExtractTaskMeta,
 		tasks.ConvertTaskMeta,
+		tasks.CollectAccountMeta,
+		tasks.ExtractAccountMeta,
+		tasks.ConvertAccountMeta,
+		tasks.CollectDepartmentMeta,
+		tasks.ExtractDepartmentMeta,
+		tasks.ConvertDepartmentMeta,
 	}
 }
 
diff --git a/plugins/zentao/tasks/shared.go b/plugins/zentao/models/account.go
similarity index 53%
copy from plugins/zentao/tasks/shared.go
copy to plugins/zentao/models/account.go
index 2dc63d789..98fb5cf6c 100644
--- a/plugins/zentao/tasks/shared.go
+++ b/plugins/zentao/models/account.go
@@ -15,21 +15,23 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package tasks
+package models
 
 import (
-	"github.com/apache/incubator-devlake/errors"
-	"net/http"
-
-	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/apache/incubator-devlake/models/common"
 )
 
-func GetTotalPagesFromResponse(res *http.Response, args *helper.ApiCollectorArgs) (int, errors.Error) {
-	body := &ZentaoPagination{}
-	err := helper.UnmarshalResponse(res, body)
-	if err != nil {
-		return 0, err
-	}
-	return body.Page, nil
+type ZentaoAccount struct {
+	common.NoPKModel
+	ConnectionId uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID           uint64 `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL" `
+	Account      string `json:"account" gorm:"type:varchar(100);index"`
+	Avatar       string `json:"avatar" gorm:"type:varchar(255)"`
+	Realname     string `json:"realname" gorm:"type:varchar(100);index"`
+	Role         string `json:"role" gorm:"type:varchar(100);index"`
+	Dept         uint64 `json:"dept" gorm:"type:BIGINT  NOT NULL;index"`
+}
 
+func (ZentaoAccount) TableName() string {
+	return "_tool_zentao_accounts"
 }
diff --git a/plugins/zentao/tasks/shared.go b/plugins/zentao/models/archived/account.go
similarity index 54%
copy from plugins/zentao/tasks/shared.go
copy to plugins/zentao/models/archived/account.go
index 2dc63d789..105b97766 100644
--- a/plugins/zentao/tasks/shared.go
+++ b/plugins/zentao/models/archived/account.go
@@ -15,21 +15,23 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package tasks
+package archived
 
 import (
-	"github.com/apache/incubator-devlake/errors"
-	"net/http"
-
-	"github.com/apache/incubator-devlake/plugins/helper"
+	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
 )
 
-func GetTotalPagesFromResponse(res *http.Response, args *helper.ApiCollectorArgs) (int, errors.Error) {
-	body := &ZentaoPagination{}
-	err := helper.UnmarshalResponse(res, body)
-	if err != nil {
-		return 0, err
-	}
-	return body.Page, nil
+type ZentaoAccount struct {
+	archived.NoPKModel
+	ConnectionId uint64  `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID           uint64  `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL" `
+	Account  string `json:"account" gorm:"type:varchar(100);index"`
+	Avatar   string `json:"avatar" gorm:"type:varchar(255)"`
+	Realname string `json:"realname" gorm:"type:varchar(100);index"`
+	Role string `json:"role" gorm:"type:varchar(100);index"`
+	Dept uint64 `json:"dept" gorm:"type:BIGINT  NOT NULL;index"`
+}
 
+func (ZentaoAccount) TableName() string {
+	return "_tool_zentao_accounts"
 }
diff --git a/plugins/zentao/models/archived/bug.go b/plugins/zentao/models/archived/bug.go
index 84dd06945..364d319f6 100644
--- a/plugins/zentao/models/archived/bug.go
+++ b/plugins/zentao/models/archived/bug.go
@@ -19,79 +19,79 @@ package archived
 
 import (
 	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoBug struct {
 	archived.NoPKModel
-	ConnectionId   uint64     `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	ID             uint64     `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Project        uint64     `json:"project"`
-	Product        uint64     `json:"product"`
-	Injection      int        `json:"injection"`
-	Identify       int        `json:"identify"`
-	Branch         int        `json:"branch"`
-	Module         int        `json:"module"`
-	Execution      uint64     `json:"execution"`
-	Plan           int        `json:"plan"`
-	Story          uint64     `json:"story"`
-	StoryVersion   int        `json:"storyVersion"`
-	Task           int        `json:"task"`
-	ToTask         int        `json:"toTask"`
-	ToStory        uint64     `json:"toStory"`
-	Title          string     `json:"title"`
-	Keywords       string     `json:"keywords"`
-	Severity       int        `json:"severity"`
-	Pri            int        `json:"pri"`
-	Type           string     `json:"type"`
-	Os             string     `json:"os"`
-	Browser        string     `json:"browser"`
-	Hardware       string     `json:"hardware"`
-	Found          string     `json:"found"`
-	Steps          string     `json:"steps"`
-	Status         string     `json:"status"`
-	SubStatus      string     `json:"subStatus"`
-	Color          string     `json:"color"`
-	Confirmed      int        `json:"confirmed"`
-	ActivatedCount int        `json:"activatedCount"`
-	ActivatedDate  *time.Time `json:"activatedDate"`
-	FeedbackBy     string     `json:"feedbackBy"`
-	NotifyEmail    string     `json:"notifyEmail"`
+	ConnectionId   uint64              `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID             uint64              `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Project        uint64              `json:"project"`
+	Product        uint64              `json:"product"`
+	Injection      int                 `json:"injection"`
+	Identify       int                 `json:"identify"`
+	Branch         int                 `json:"branch"`
+	Module         int                 `json:"module"`
+	Execution      uint64              `json:"execution"`
+	Plan           int                 `json:"plan"`
+	Story          uint64              `json:"story"`
+	StoryVersion   int                 `json:"storyVersion"`
+	Task           int                 `json:"task"`
+	ToTask         int                 `json:"toTask"`
+	ToStory        uint64              `json:"toStory"`
+	Title          string              `json:"title"`
+	Keywords       string              `json:"keywords"`
+	Severity       int                 `json:"severity"`
+	Pri            int                 `json:"pri"`
+	Type           string              `json:"type"`
+	Os             string              `json:"os"`
+	Browser        string              `json:"browser"`
+	Hardware       string              `json:"hardware"`
+	Found          string              `json:"found"`
+	Steps          string              `json:"steps"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Color          string              `json:"color"`
+	Confirmed      int                 `json:"confirmed"`
+	ActivatedCount int                 `json:"activatedCount"`
+	ActivatedDate  *helper.Iso8601Time `json:"activatedDate"`
+	FeedbackBy     string              `json:"feedbackBy"`
+	NotifyEmail    string              `json:"notifyEmail"`
 	OpenedById     uint64
 	OpenedByName   string
-	OpenedDate     *time.Time `json:"openedDate"`
-	OpenedBuild    string     `json:"openedBuild"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedBuild    string              `json:"openedBuild"`
 	AssignedToId   uint64
 	AssignedToName string
-	AssignedDate   *time.Time `json:"assignedDate"`
-	Deadline       string     `json:"deadline"`
+	AssignedDate   *helper.Iso8601Time `json:"assignedDate"`
+	Deadline       string              `json:"deadline"`
 	ResolvedById   uint64
-	Resolution     string     `json:"resolution"`
-	ResolvedBuild  string     `json:"resolvedBuild"`
-	ResolvedDate   *time.Time `json:"resolvedDate"`
+	Resolution     string              `json:"resolution"`
+	ResolvedBuild  string              `json:"resolvedBuild"`
+	ResolvedDate   *helper.Iso8601Time `json:"resolvedDate"`
 	ClosedById     uint64
-	ClosedDate     *time.Time `json:"closedDate"`
-	DuplicateBug   int        `json:"duplicateBug"`
-	LinkBug        string     `json:"linkBug"`
-	Feedback       int        `json:"feedback"`
-	Result         int        `json:"result"`
-	Repo           int        `json:"repo"`
-	Mr             int        `json:"mr"`
-	Entry          string     `json:"entry"`
-	NumOfLine      string     `json:"lines"`
-	V1             string     `json:"v1"`
-	V2             string     `json:"v2"`
-	RepoType       string     `json:"repoType"`
-	IssueKey       string     `json:"issueKey"`
-	Testtask       int        `json:"testtask"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	DuplicateBug   int                 `json:"duplicateBug"`
+	LinkBug        string              `json:"linkBug"`
+	Feedback       int                 `json:"feedback"`
+	Result         int                 `json:"result"`
+	Repo           int                 `json:"repo"`
+	Mr             int                 `json:"mr"`
+	Entry          string              `json:"entry"`
+	NumOfLine      string              `json:"lines"`
+	V1             string              `json:"v1"`
+	V2             string              `json:"v2"`
+	RepoType       string              `json:"repoType"`
+	IssueKey       string              `json:"issueKey"`
+	Testtask       int                 `json:"testtask"`
 	LastEditedById uint64
-	LastEditedDate *time.Time `json:"lastEditedDate"`
-	Deleted        bool       `json:"deleted"`
-	PriOrder       string     `json:"priOrder"`
-	SeverityOrder  int        `json:"severityOrder"`
-	Needconfirm    bool       `json:"needconfirm"`
-	StatusName     string     `json:"statusName"`
-	ProductStatus  string     `json:"productStatus"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	Deleted        bool                `json:"deleted"`
+	PriOrder       string              `json:"priOrder"`
+	SeverityOrder  int                 `json:"severityOrder"`
+	Needconfirm    bool                `json:"needconfirm"`
+	StatusName     string              `json:"statusName"`
+	ProductStatus  string              `json:"productStatus"`
 }
 
 func (ZentaoBug) TableName() string {
diff --git a/plugins/zentao/models/archived/department.go b/plugins/zentao/models/archived/department.go
new file mode 100644
index 000000000..b97fcbb00
--- /dev/null
+++ b/plugins/zentao/models/archived/department.go
@@ -0,0 +1,39 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package archived
+
+import "github.com/apache/incubator-devlake/models/migrationscripts/archived"
+
+type ZentaoDepartment struct {
+	ConnectionId uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID           uint64 `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL" `
+	Name         string `json:"name" gorm:"type:varchar(100);index"`
+	Parent       int    `json:"parent" gorm:"type:varchar(100)"`
+	Path         string `json:"path" gorm:"type:varchar(100)"`
+	Grade        int    `json:"grade"`
+	Order        int    `json:"order"`
+	Position     string `json:"position" gorm:"type:varchar(100)"`
+	Function     string `json:"function" gorm:"type:varchar(100)"`
+	Manager      string `json:"manager" gorm:"type:varchar(100)"`
+	ManagerName  string `json:"managerName" gorm:"type:varchar(100)"`
+	archived.NoPKModel
+}
+
+func (ZentaoDepartment) TableName() string {
+	return "_tool_zentao_departments"
+}
diff --git a/plugins/zentao/models/archived/execution.go b/plugins/zentao/models/archived/execution.go
index 859c13208..7eb8c6a0a 100644
--- a/plugins/zentao/models/archived/execution.go
+++ b/plugins/zentao/models/archived/execution.go
@@ -19,51 +19,50 @@ package archived
 
 import (
 	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoExecution struct {
-	ConnectionId   uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Id             uint64 `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Project        uint64 `json:"project"`
-	Model          string `json:"model"`
-	Type           string `json:"type"`
-	Lifetime       string `json:"lifetime"`
-	Budget         string `json:"budget"`
-	BudgetUnit     string `json:"budgetUnit"`
-	Attribute      string `json:"attribute"`
-	Percent        int    `json:"percent"`
-	Milestone      string `json:"milestone"`
-	Output         string `json:"output"`
-	Auth           string `json:"auth"`
-	Parent         uint64 `json:"parent"`
-	Path           string `json:"path"`
-	Grade          int    `json:"grade"`
-	Name           string `json:"name"`
-	Code           string `json:"code"`
-	PlanBegin      string `json:"begin"`
-	PlanEnd        string `json:"end"`
-	RealBegan      string `json:"realBegan"`
-	RealEnd        string `json:"realEnd"`
-	Days           int    `json:"days"`
-	Status         string `json:"status"`
-	SubStatus      string `json:"subStatus"`
-	Pri            string `json:"pri"`
-	Description    string `json:"desc"`
-	Version        int    `json:"version"`
-	ParentVersion  int    `json:"parentVersion"`
-	PlanDuration   int    `json:"planDuration"`
-	RealDuration   int    `json:"realDuration"`
+	ConnectionId   uint64              `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Id             uint64              `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Project        uint64              `json:"project"`
+	Model          string              `json:"model"`
+	Type           string              `json:"type"`
+	Lifetime       string              `json:"lifetime"`
+	Budget         string              `json:"budget"`
+	BudgetUnit     string              `json:"budgetUnit"`
+	Attribute      string              `json:"attribute"`
+	Percent        int                 `json:"percent"`
+	Milestone      string              `json:"milestone"`
+	Output         string              `json:"output"`
+	Auth           string              `json:"auth"`
+	Parent         uint64              `json:"parent"`
+	Path           string              `json:"path"`
+	Grade          int                 `json:"grade"`
+	Name           string              `json:"name"`
+	Code           string              `json:"code"`
+	PlanBegin      *helper.Iso8601Time `json:"begin"`
+	PlanEnd        *helper.Iso8601Time `json:"end"`
+	RealBegan      string              `json:"realBegan"`
+	RealEnd        *helper.Iso8601Time `json:"realEnd"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Pri            string              `json:"pri"`
+	Description    string              `json:"desc"`
+	Version        int                 `json:"version"`
+	ParentVersion  int                 `json:"parentVersion"`
+	PlanDuration   int                 `json:"planDuration"`
+	RealDuration   int                 `json:"realDuration"`
 	OpenedById     uint64
-	OpenedDate     *time.Time `json:"openedDate"`
-	OpenedVersion  string     `json:"openedVersion"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedVersion  string              `json:"openedVersion"`
 	LastEditedById uint64
-	LastEditedDate *time.Time `json:"lastEditedDate"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
 	ClosedById     uint64
-	ClosedDate     *time.Time `json:"closedDate"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
 	CanceledById   uint64
-	CanceledDate   *time.Time `json:"canceledDate"`
-	SuspendedDate  string     `json:"suspendedDate"`
+	CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+	SuspendedDate  *helper.Iso8601Time `json:"suspendedDate"`
 	POId           uint64
 	PMId           uint64
 	QDId           uint64
diff --git a/plugins/zentao/models/archived/product.go b/plugins/zentao/models/archived/product.go
index f99872a7a..36d4e6655 100644
--- a/plugins/zentao/models/archived/product.go
+++ b/plugins/zentao/models/archived/product.go
@@ -19,7 +19,7 @@ package archived
 
 import (
 	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoProduct struct {
@@ -40,20 +40,20 @@ type ZentaoProduct struct {
 	Acl            string `json:"acl"`
 	Reviewer       string `json:"reviewer"`
 	CreatedById    uint64
-	CreatedDate    *time.Time `json:"createdDate"`
-	CreatedVersion string     `json:"createdVersion"`
-	OrderIn        int        `json:"order"`
-	Deleted        string     `json:"deleted"`
-	Plans          int        `json:"plans"`
-	Releases       int        `json:"releases"`
-	Builds         int        `json:"builds"`
-	Cases          int        `json:"cases"`
-	Projects       int        `json:"projects"`
-	Executions     int        `json:"executions"`
-	Bugs           int        `json:"bugs"`
-	Docs           int        `json:"docs"`
-	Progress       float64    `json:"progress"`
-	CaseReview     bool       `json:"caseReview"`
+	CreatedDate    *helper.Iso8601Time `json:"createdDate"`
+	CreatedVersion string              `json:"createdVersion"`
+	OrderIn        int                 `json:"order"`
+	Deleted        string              `json:"deleted"`
+	Plans          int                 `json:"plans"`
+	Releases       int                 `json:"releases"`
+	Builds         int                 `json:"builds"`
+	Cases          int                 `json:"cases"`
+	Projects       int                 `json:"projects"`
+	Executions     int                 `json:"executions"`
+	Bugs           int                 `json:"bugs"`
+	Docs           int                 `json:"docs"`
+	Progress       float64             `json:"progress"`
+	CaseReview     bool                `json:"caseReview"`
 	archived.NoPKModel
 }
 
diff --git a/plugins/zentao/models/archived/project.go b/plugins/zentao/models/archived/project.go
index 0121599ca..fcd2314b0 100644
--- a/plugins/zentao/models/archived/project.go
+++ b/plugins/zentao/models/archived/project.go
@@ -19,53 +19,53 @@ package archived
 
 import (
 	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoProject struct {
 	archived.NoPKModel
-	ConnectionId  uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	ID            uint64 `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Project       uint64 `json:"project"`
-	Model         string `json:"model"`
-	Type          string `json:"type"`
-	Lifetime      string `json:"lifetime"`
-	Budget        string `json:"budget"`
-	BudgetUnit    string `json:"budgetUnit"`
-	Attribute     string `json:"attribute"`
-	Percent       int    `json:"percent"`
-	Milestone     string `json:"milestone"`
-	Output        string `json:"output"`
-	Auth          string `json:"auth"`
-	Parent        uint64 `json:"parent"`
-	Path          string `json:"path"`
-	Grade         int    `json:"grade"`
-	Name          string `json:"name"`
-	Code          string `json:"code"`
-	PlanBegin     string `json:"begin"`
-	PlanEnd       string `json:"end"`
-	RealBegan     string `json:"realBegan"`
-	RealEnd       string `json:"realEnd"`
-	Days          int    `json:"days"`
-	Status        string `json:"status"`
-	SubStatus     string `json:"subStatus"`
-	Pri           string `json:"pri"`
-	Description   string `json:"desc"`
-	Version       int    `json:"version"`
-	ParentVersion int    `json:"parentVersion"`
-	PlanDuration  int    `json:"planDuration"`
-	RealDuration  int    `json:"realDuration"`
+	ConnectionId  uint64              `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID            uint64              `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Project       uint64              `json:"project"`
+	Model         string              `json:"model"`
+	Type          string              `json:"type"`
+	Lifetime      string              `json:"lifetime"`
+	Budget        string              `json:"budget"`
+	BudgetUnit    string              `json:"budgetUnit"`
+	Attribute     string              `json:"attribute"`
+	Percent       int                 `json:"percent"`
+	Milestone     string              `json:"milestone"`
+	Output        string              `json:"output"`
+	Auth          string              `json:"auth"`
+	Parent        uint64              `json:"parent"`
+	Path          string              `json:"path"`
+	Grade         int                 `json:"grade"`
+	Name          string              `json:"name"`
+	Code          string              `json:"code"`
+	PlanBegin     *helper.Iso8601Time `json:"begin"`
+	PlanEnd       *helper.Iso8601Time `json:"end"`
+	RealBegan     string              `json:"realBegan"`
+	RealEnd       *helper.Iso8601Time `json:"realEnd"`
+	Days          int                 `json:"days"`
+	Status        string              `json:"status"`
+	SubStatus     string              `json:"subStatus"`
+	Pri           string              `json:"pri"`
+	Description   string              `json:"desc"`
+	Version       int                 `json:"version"`
+	ParentVersion int                 `json:"parentVersion"`
+	PlanDuration  int                 `json:"planDuration"`
+	RealDuration  int                 `json:"realDuration"`
 	//OpenedBy       string    `json:"openedBy"`
-	OpenedDate     *time.Time  `json:"openedDate"`
-	OpenedVersion  string      `json:"openedVersion"`
-	LastEditedBy   string      `json:"lastEditedBy"`
-	LastEditedDate **time.Time `json:"lastEditedDate"`
-	ClosedBy       string      `json:"closedBy"`
-	ClosedDate     **time.Time `json:"closedDate"`
-	CanceledBy     string      `json:"canceledBy"`
-	CanceledDate   **time.Time `json:"canceledDate"`
-	SuspendedDate  string      `json:"suspendedDate"`
-	PO             string      `json:"PO"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedVersion  string              `json:"openedVersion"`
+	LastEditedBy   string              `json:"lastEditedBy"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	ClosedBy       string              `json:"closedBy"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	CanceledBy     string              `json:"canceledBy"`
+	CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+	SuspendedDate  *helper.Iso8601Time `json:"suspendedDate"`
+	PO             string              `json:"PO"`
 	PM             `json:"PM"`
 	QD             string `json:"QD"`
 	RD             string `json:"RD"`
diff --git a/plugins/zentao/models/archived/story.go b/plugins/zentao/models/archived/story.go
index 4488e1029..65fc7b950 100644
--- a/plugins/zentao/models/archived/story.go
+++ b/plugins/zentao/models/archived/story.go
@@ -19,7 +19,7 @@ package archived
 
 import (
 	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoStory struct {
@@ -57,31 +57,31 @@ type ZentaoStory struct {
 	FromVersion      int    `json:"fromVersion"`
 	OpenedById       uint64
 	OpenedByName     string
-	OpenedDate       *time.Time `json:"openedDate"`
+	OpenedDate       *helper.Iso8601Time `json:"openedDate"`
 	AssignedToId     uint64
 	AssignedToName   string
-	AssignedDate     *time.Time `json:"assignedDate"`
-	ApprovedDate     string     `json:"approvedDate"`
+	AssignedDate     *helper.Iso8601Time `json:"assignedDate"`
+	ApprovedDate     *helper.Iso8601Time `json:"approvedDate"`
 	LastEditedId     uint64
-	LastEditedDate   *time.Time `json:"lastEditedDate"`
-	ChangedDate      string     `json:"changedDate"`
-	ReviewedById     uint64     `json:"reviewedBy"`
-	ReviewedDate     *time.Time `json:"reviewedDate"`
+	LastEditedDate   *helper.Iso8601Time `json:"lastEditedDate"`
+	ChangedDate      *helper.Iso8601Time `json:"changedDate"`
+	ReviewedById     uint64              `json:"reviewedBy"`
+	ReviewedDate     *helper.Iso8601Time `json:"reviewedDate"`
 	ClosedId         uint64
-	ClosedDate       *time.Time `json:"closedDate"`
-	ClosedReason     string     `json:"closedReason"`
-	ActivatedDate    string     `json:"activatedDate"`
-	ToBug            int        `json:"toBug"`
-	ChildStories     string     `json:"childStories"`
-	LinkStories      string     `json:"linkStories"`
-	LinkRequirements string     `json:"linkRequirements"`
-	DuplicateStory   uint64     `json:"duplicateStory"`
-	StoryChanged     string     `json:"storyChanged"`
-	NotifyEmail      string     `json:"notifyEmail"`
-	URChanged        string     `json:"URChanged"`
-	Deleted          bool       `json:"deleted"`
-	PriOrder         string     `json:"priOrder"`
-	PlanTitle        string     `json:"planTitle"`
+	ClosedDate       *helper.Iso8601Time `json:"closedDate"`
+	ClosedReason     string              `json:"closedReason"`
+	ActivatedDate    *helper.Iso8601Time `json:"activatedDate"`
+	ToBug            int                 `json:"toBug"`
+	ChildStories     string              `json:"childStories"`
+	LinkStories      string              `json:"linkStories"`
+	LinkRequirements string              `json:"linkRequirements"`
+	DuplicateStory   uint64              `json:"duplicateStory"`
+	StoryChanged     string              `json:"storyChanged"`
+	NotifyEmail      string              `json:"notifyEmail"`
+	URChanged        string              `json:"URChanged"`
+	Deleted          bool                `json:"deleted"`
+	PriOrder         string              `json:"priOrder"`
+	PlanTitle        string              `json:"planTitle"`
 }
 
 func (ZentaoStory) TableName() string {
diff --git a/plugins/zentao/models/archived/task.go b/plugins/zentao/models/archived/task.go
index cd23e7dae..9942d575a 100644
--- a/plugins/zentao/models/archived/task.go
+++ b/plugins/zentao/models/archived/task.go
@@ -19,7 +19,7 @@ package archived
 
 import (
 	"github.com/apache/incubator-devlake/models/migrationscripts/archived"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoTask struct {
@@ -53,43 +53,43 @@ type ZentaoTask struct {
 	Version            int    `json:"version"`
 	OpenedById         uint64
 	OpenedByName       string
-	OpenedDate         *time.Time `json:"openedDate"`
+	OpenedDate         *helper.Iso8601Time `json:"openedDate"`
 	AssignedToId       uint64
 	AssignedToName     string
-	AssignedDate       *time.Time `json:"assignedDate"`
-	EstStarted         string     `json:"estStarted"`
-	RealStarted        *time.Time `json:"realStarted"`
+	AssignedDate       *helper.Iso8601Time `json:"assignedDate"`
+	EstStarted         string              `json:"estStarted"`
+	RealStarted        *helper.Iso8601Time `json:"realStarted"`
 	FinishedId         uint64
-	FinishedDate       *time.Time `json:"finishedDate"`
-	FinishedList       string     `json:"finishedList"`
+	FinishedDate       *helper.Iso8601Time `json:"finishedDate"`
+	FinishedList       string              `json:"finishedList"`
 	CanceledId         uint64
-	CanceledDate       *time.Time `json:"canceledDate"`
+	CanceledDate       *helper.Iso8601Time `json:"canceledDate"`
 	ClosedById         uint64
-	ClosedDate         *time.Time `json:"closedDate"`
-	PlanDuration       int        `json:"planDuration"`
-	RealDuration       int        `json:"realDuration"`
-	ClosedReason       string     `json:"closedReason"`
+	ClosedDate         *helper.Iso8601Time `json:"closedDate"`
+	PlanDuration       int                 `json:"planDuration"`
+	RealDuration       int                 `json:"realDuration"`
+	ClosedReason       string              `json:"closedReason"`
 	LastEditedId       uint64
-	LastEditedDate     *time.Time `json:"lastEditedDate"`
-	ActivatedDate      string     `json:"activatedDate"`
-	OrderIn            int        `json:"order"`
-	Repo               int        `json:"repo"`
-	Mr                 int        `json:"mr"`
-	Entry              string     `json:"entry"`
-	NumOfLine          string     `json:"lines"`
-	V1                 string     `json:"v1"`
-	V2                 string     `json:"v2"`
-	Deleted            bool       `json:"deleted"`
-	Vision             string     `json:"vision"`
-	StoryID            uint64     `json:"storyID"`
-	StoryTitle         string     `json:"storyTitle"`
-	Branch             int        `json:"branch"`
-	LatestStoryVersion int        `json:"latestStoryVersion"`
-	StoryStatus        string     `json:"storyStatus"`
-	AssignedToRealName string     `json:"assignedToRealName"`
-	PriOrder           string     `json:"priOrder"`
-	NeedConfirm        bool       `json:"needConfirm"`
-	Progress           float64    `json:"progress"`
+	LastEditedDate     *helper.Iso8601Time `json:"lastEditedDate"`
+	ActivatedDate      *helper.Iso8601Time `json:"activatedDate"`
+	OrderIn            int                 `json:"order"`
+	Repo               int                 `json:"repo"`
+	Mr                 int                 `json:"mr"`
+	Entry              string              `json:"entry"`
+	NumOfLine          string              `json:"lines"`
+	V1                 string              `json:"v1"`
+	V2                 string              `json:"v2"`
+	Deleted            bool                `json:"deleted"`
+	Vision             string              `json:"vision"`
+	StoryID            uint64              `json:"storyID"`
+	StoryTitle         string              `json:"storyTitle"`
+	Branch             int                 `json:"branch"`
+	LatestStoryVersion int                 `json:"latestStoryVersion"`
+	StoryStatus        string              `json:"storyStatus"`
+	AssignedToRealName string              `json:"assignedToRealName"`
+	PriOrder           string              `json:"priOrder"`
+	NeedConfirm        bool                `json:"needConfirm"`
+	Progress           float64             `json:"progress"`
 }
 
 func (ZentaoTask) TableName() string {
diff --git a/plugins/zentao/models/bug.go b/plugins/zentao/models/bug.go
index a04fedac6..da39ee41f 100644
--- a/plugins/zentao/models/bug.go
+++ b/plugins/zentao/models/bug.go
@@ -19,172 +19,147 @@ package models
 
 import (
 	"github.com/apache/incubator-devlake/models/common"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoBugRes struct {
-	ID             uint64     `json:"id"`
-	Project        uint64     `json:"project"`
-	Product        uint64     `json:"product"`
-	Injection      int        `json:"injection"`
-	Identify       int        `json:"identify"`
-	Branch         int        `json:"branch"`
-	Module         int        `json:"module"`
-	Execution      uint64     `json:"execution"`
-	Plan           int        `json:"plan"`
-	Story          uint64     `json:"story"`
-	StoryVersion   int        `json:"storyVersion"`
-	Task           int        `json:"task"`
-	ToTask         int        `json:"toTask"`
-	ToStory        uint64     `json:"toStory"`
-	Title          string     `json:"title"`
-	Keywords       string     `json:"keywords"`
-	Severity       int        `json:"severity"`
-	Pri            int        `json:"pri"`
-	Type           string     `json:"type"`
-	Os             string     `json:"os"`
-	Browser        string     `json:"browser"`
-	Hardware       string     `json:"hardware"`
-	Found          string     `json:"found"`
-	Steps          string     `json:"steps"`
-	Status         string     `json:"status"`
-	SubStatus      string     `json:"subStatus"`
-	Color          string     `json:"color"`
-	Confirmed      int        `json:"confirmed"`
-	ActivatedCount int        `json:"activatedCount"`
-	ActivatedDate  *time.Time `json:"activatedDate"`
-	FeedbackBy     string     `json:"feedbackBy"`
-	NotifyEmail    string     `json:"notifyEmail"`
-	OpenedBy       struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"openedBy"`
-	OpenedDate  *time.Time `json:"openedDate"`
-	OpenedBuild string     `json:"openedBuild"`
-	AssignedTo  struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"assignedTo"`
-	AssignedDate *time.Time `json:"assignedDate"`
-	Deadline     string     `json:"deadline"`
-	ResolvedBy   struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"resolvedBy"`
-	Resolution    string     `json:"resolution"`
-	ResolvedBuild string     `json:"resolvedBuild"`
-	ResolvedDate  *time.Time `json:"resolvedDate"`
-	ClosedBy      struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"closedBy"`
-	ClosedDate   *time.Time `json:"closedDate"`
-	DuplicateBug int        `json:"duplicateBug"`
-	LinkBug      string     `json:"linkBug"`
-	Feedback     int        `json:"feedback"`
-	Result       int        `json:"result"`
-	Repo         int        `json:"repo"`
-	Mr           int        `json:"mr"`
-	Entry        string     `json:"entry"`
-	NumOfLine    string     `json:"lines"`
-	V1           string     `json:"v1"`
-	V2           string     `json:"v2"`
-	RepoType     string     `json:"repoType"`
-	IssueKey     string     `json:"issueKey"`
-	Testtask     int        `json:"testtask"`
-	LastEditedBy struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"lastEditedBy"`
-	LastEditedDate *time.Time `json:"lastEditedDate"`
-	Deleted        bool       `json:"deleted"`
-	PriOrder       string     `json:"priOrder"`
-	SeverityOrder  int        `json:"severityOrder"`
-	Needconfirm    bool       `json:"needconfirm"`
-	StatusName     string     `json:"statusName"`
-	ProductStatus  string     `json:"productStatus"`
+	ID             uint64              `json:"id"`
+	Project        uint64              `json:"project"`
+	Product        uint64              `json:"product"`
+	Injection      int                 `json:"injection"`
+	Identify       int                 `json:"identify"`
+	Branch         int                 `json:"branch"`
+	Module         int                 `json:"module"`
+	Execution      uint64              `json:"execution"`
+	Plan           int                 `json:"plan"`
+	Story          uint64              `json:"story"`
+	StoryVersion   int                 `json:"storyVersion"`
+	Task           int                 `json:"task"`
+	ToTask         int                 `json:"toTask"`
+	ToStory        uint64              `json:"toStory"`
+	Title          string              `json:"title"`
+	Keywords       string              `json:"keywords"`
+	Severity       int                 `json:"severity"`
+	Pri            int                 `json:"pri"`
+	Type           string              `json:"type"`
+	Os             string              `json:"os"`
+	Browser        string              `json:"browser"`
+	Hardware       string              `json:"hardware"`
+	Found          string              `json:"found"`
+	Steps          string              `json:"steps"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Color          string              `json:"color"`
+	Confirmed      int                 `json:"confirmed"`
+	ActivatedCount int                 `json:"activatedCount"`
+	ActivatedDate  *helper.Iso8601Time `json:"activatedDate"`
+	FeedbackBy     string              `json:"feedbackBy"`
+	NotifyEmail    string              `json:"notifyEmail"`
+	OpenedBy       *ZentaoAccount      `json:"openedBy"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedBuild    string              `json:"openedBuild"`
+	AssignedTo     *ZentaoAccount      `json:"assignedTo"`
+	AssignedDate   *helper.Iso8601Time `json:"assignedDate"`
+	Deadline       string              `json:"deadline"`
+	ResolvedBy     *ZentaoAccount      `json:"resolvedBy"`
+	Resolution     string              `json:"resolution"`
+	ResolvedBuild  string              `json:"resolvedBuild"`
+	ResolvedDate   *helper.Iso8601Time `json:"resolvedDate"`
+	ClosedBy       *ZentaoAccount      `json:"closedBy"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	DuplicateBug   int                 `json:"duplicateBug"`
+	LinkBug        string              `json:"linkBug"`
+	Feedback       int                 `json:"feedback"`
+	Result         int                 `json:"result"`
+	Repo           int                 `json:"repo"`
+	Mr             int                 `json:"mr"`
+	Entry          string              `json:"entry"`
+	NumOfLine      string              `json:"lines"`
+	V1             string              `json:"v1"`
+	V2             string              `json:"v2"`
+	RepoType       string              `json:"repoType"`
+	IssueKey       string              `json:"issueKey"`
+	Testtask       int                 `json:"testtask"`
+	LastEditedBy   *ZentaoAccount      `json:"lastEditedBy"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	Deleted        bool                `json:"deleted"`
+	PriOrder       string              `json:"priOrder"`
+	SeverityOrder  int                 `json:"severityOrder"`
+	Needconfirm    bool                `json:"needconfirm"`
+	StatusName     string              `json:"statusName"`
+	ProductStatus  string              `json:"productStatus"`
 }
 
 type ZentaoBug struct {
 	common.NoPKModel
-	ConnectionId   uint64     `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	ID             uint64     `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Project        uint64     `json:"project"`
-	Product        uint64     `json:"product"`
-	Injection      int        `json:"injection"`
-	Identify       int        `json:"identify"`
-	Branch         int        `json:"branch"`
-	Module         int        `json:"module"`
-	Execution      uint64     `json:"execution"`
-	Plan           int        `json:"plan"`
-	Story          uint64     `json:"story"`
-	StoryVersion   int        `json:"storyVersion"`
-	Task           int        `json:"task"`
-	ToTask         int        `json:"toTask"`
-	ToStory        uint64     `json:"toStory"`
-	Title          string     `json:"title"`
-	Keywords       string     `json:"keywords"`
-	Severity       int        `json:"severity"`
-	Pri            int        `json:"pri"`
-	Type           string     `json:"type"`
-	Os             string     `json:"os"`
-	Browser        string     `json:"browser"`
-	Hardware       string     `json:"hardware"`
-	Found          string     `json:"found"`
-	Steps          string     `json:"steps"`
-	Status         string     `json:"status"`
-	SubStatus      string     `json:"subStatus"`
-	Color          string     `json:"color"`
-	Confirmed      int        `json:"confirmed"`
-	ActivatedCount int        `json:"activatedCount"`
-	ActivatedDate  *time.Time `json:"activatedDate"`
-	FeedbackBy     string     `json:"feedbackBy"`
-	NotifyEmail    string     `json:"notifyEmail"`
+	ConnectionId   uint64              `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID             uint64              `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Project        uint64              `json:"project"`
+	Product        uint64              `json:"product"`
+	Injection      int                 `json:"injection"`
+	Identify       int                 `json:"identify"`
+	Branch         int                 `json:"branch"`
+	Module         int                 `json:"module"`
+	Execution      uint64              `json:"execution"`
+	Plan           int                 `json:"plan"`
+	Story          uint64              `json:"story"`
+	StoryVersion   int                 `json:"storyVersion"`
+	Task           int                 `json:"task"`
+	ToTask         int                 `json:"toTask"`
+	ToStory        uint64              `json:"toStory"`
+	Title          string              `json:"title"`
+	Keywords       string              `json:"keywords"`
+	Severity       int                 `json:"severity"`
+	Pri            int                 `json:"pri"`
+	Type           string              `json:"type"`
+	Os             string              `json:"os"`
+	Browser        string              `json:"browser"`
+	Hardware       string              `json:"hardware"`
+	Found          string              `json:"found"`
+	Steps          string              `json:"steps"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Color          string              `json:"color"`
+	Confirmed      int                 `json:"confirmed"`
+	ActivatedCount int                 `json:"activatedCount"`
+	ActivatedDate  *helper.Iso8601Time `json:"activatedDate"`
+	FeedbackBy     string              `json:"feedbackBy"`
+	NotifyEmail    string              `json:"notifyEmail"`
 	OpenedById     uint64
 	OpenedByName   string
-	OpenedDate     *time.Time `json:"openedDate"`
-	OpenedBuild    string     `json:"openedBuild"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedBuild    string              `json:"openedBuild"`
 	AssignedToId   uint64
 	AssignedToName string
-	AssignedDate   *time.Time `json:"assignedDate"`
-	Deadline       string     `json:"deadline"`
+	AssignedDate   *helper.Iso8601Time `json:"assignedDate"`
+	Deadline       string              `json:"deadline"`
 	ResolvedById   uint64
-	Resolution     string     `json:"resolution"`
-	ResolvedBuild  string     `json:"resolvedBuild"`
-	ResolvedDate   *time.Time `json:"resolvedDate"`
+	Resolution     string              `json:"resolution"`
+	ResolvedBuild  string              `json:"resolvedBuild"`
+	ResolvedDate   *helper.Iso8601Time `json:"resolvedDate"`
 	ClosedById     uint64
-	ClosedDate     *time.Time `json:"closedDate"`
-	DuplicateBug   int        `json:"duplicateBug"`
-	LinkBug        string     `json:"linkBug"`
-	Feedback       int        `json:"feedback"`
-	Result         int        `json:"result"`
-	Repo           int        `json:"repo"`
-	Mr             int        `json:"mr"`
-	Entry          string     `json:"entry"`
-	NumOfLine      string     `json:"lines"`
-	V1             string     `json:"v1"`
-	V2             string     `json:"v2"`
-	RepoType       string     `json:"repoType"`
-	IssueKey       string     `json:"issueKey"`
-	Testtask       int        `json:"testtask"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	DuplicateBug   int                 `json:"duplicateBug"`
+	LinkBug        string              `json:"linkBug"`
+	Feedback       int                 `json:"feedback"`
+	Result         int                 `json:"result"`
+	Repo           int                 `json:"repo"`
+	Mr             int                 `json:"mr"`
+	Entry          string              `json:"entry"`
+	NumOfLine      string              `json:"lines"`
+	V1             string              `json:"v1"`
+	V2             string              `json:"v2"`
+	RepoType       string              `json:"repoType"`
+	IssueKey       string              `json:"issueKey"`
+	Testtask       int                 `json:"testtask"`
 	LastEditedById uint64
-	LastEditedDate *time.Time `json:"lastEditedDate"`
-	Deleted        bool       `json:"deleted"`
-	PriOrder       string     `json:"priOrder"`
-	SeverityOrder  int        `json:"severityOrder"`
-	Needconfirm    bool       `json:"needconfirm"`
-	StatusName     string     `json:"statusName"`
-	ProductStatus  string     `json:"productStatus"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	Deleted        bool                `json:"deleted"`
+	PriOrder       string              `json:"priOrder"`
+	SeverityOrder  int                 `json:"severityOrder"`
+	Needconfirm    bool                `json:"needconfirm"`
+	StatusName     string              `json:"statusName"`
+	ProductStatus  string              `json:"productStatus"`
 }
 
 func (ZentaoBug) TableName() string {
diff --git a/plugins/zentao/models/department.go b/plugins/zentao/models/department.go
new file mode 100644
index 000000000..b22344a0e
--- /dev/null
+++ b/plugins/zentao/models/department.go
@@ -0,0 +1,41 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package models
+
+import (
+	"github.com/apache/incubator-devlake/models/common"
+)
+
+type ZentaoDepartment struct {
+	ConnectionId uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID           uint64 `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL" `
+	Name         string `json:"name" gorm:"type:varchar(100);index"`
+	Parent       uint64 `json:"parent" gorm:"type:varchar(100)"`
+	Path         string `json:"path" gorm:"type:varchar(100)"`
+	Grade        int    `json:"grade"`
+	Order        int    `json:"order"`
+	Position     string `json:"position" gorm:"type:varchar(100)"`
+	Function     string `json:"function" gorm:"type:varchar(100)"`
+	Manager      string `json:"manager" gorm:"type:varchar(100)"`
+	ManagerName  string `json:"managerName" gorm:"type:varchar(100)"`
+	common.NoPKModel
+}
+
+func (ZentaoDepartment) TableName() string {
+	return "_tool_zentao_departments"
+}
diff --git a/plugins/zentao/models/execution.go b/plugins/zentao/models/execution.go
index 74fc0aa30..52db4d498 100644
--- a/plugins/zentao/models/execution.go
+++ b/plugins/zentao/models/execution.go
@@ -19,164 +19,117 @@ package models
 
 import (
 	"github.com/apache/incubator-devlake/models/common"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoExecutionRes struct {
-	ID            uint64     `json:"id"`
-	Project       uint64     `json:"project"`
-	Model         string     `json:"model"`
-	Type          string     `json:"type"`
-	Lifetime      string     `json:"lifetime"`
-	Budget        string     `json:"budget"`
-	BudgetUnit    string     `json:"budgetUnit"`
-	Attribute     string     `json:"attribute"`
-	Percent       int        `json:"percent"`
-	Milestone     string     `json:"milestone"`
-	Output        string     `json:"output"`
-	Auth          string     `json:"auth"`
-	Parent        uint64     `json:"parent"`
-	Path          string     `json:"path"`
-	Grade         int        `json:"grade"`
-	Name          string     `json:"name"`
-	Code          string     `json:"code"`
-	PlanBegin     string     `json:"begin"`
-	PlanEnd       string     `json:"end"`
-	RealBegan     *time.Time `json:"realBegan"`
-	RealEnd       *time.Time `json:"realEnd"`
-	Days          int        `json:"days"`
-	Status        string     `json:"status"`
-	SubStatus     string     `json:"subStatus"`
-	Pri           string     `json:"pri"`
-	Description   string     `json:"desc"`
-	Version       int        `json:"version"`
-	ParentVersion int        `json:"parentVersion"`
-	PlanDuration  int        `json:"planDuration"`
-	RealDuration  int        `json:"realDuration"`
-	OpenedBy      struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"openedBy"`
-	OpenedDate    *time.Time `json:"openedDate"`
-	OpenedVersion string     `json:"openedVersion"`
-	LastEditedBy  struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"lastEditedBy"`
-	LastEditedDate *time.Time `json:"lastEditedDate"`
-	ClosedBy       struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"closedBy"`
-	ClosedDate *time.Time `json:"closedDate"`
-	CanceledBy struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"canceledBy"`
-	CanceledDate  *time.Time `json:"canceledDate"`
-	SuspendedDate string     `json:"suspendedDate"`
-	PO            struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"PO"`
-	PM struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"PM"`
-	QD struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"QD"`
-	RD struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"RD"`
-	Team      string `json:"team"`
-	Acl       string `json:"acl"`
-	Whitelist []struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"whitelist"`
-	OrderIn       int     `json:"order"`
-	Vision        string  `json:"vision"`
-	DisplayCards  int     `json:"displayCards"`
-	FluidBoard    string  `json:"fluidBoard"`
-	Deleted       bool    `json:"deleted"`
-	TotalHours    float64 `json:"totalHours"`
-	TotalEstimate float64 `json:"totalEstimate"`
-	TotalConsumed float64 `json:"totalConsumed"`
-	TotalLeft     float64 `json:"totalLeft"`
-	ProjectInfo   struct {
-		ID             uint64 `json:"id"`
-		Project        uint64 `json:"project"`
-		Model          string `json:"model"`
-		Type           string `json:"type"`
-		Lifetime       string `json:"lifetime"`
-		Budget         string `json:"budget"`
-		BudgetUnit     string `json:"budgetUnit"`
-		Attribute      string `json:"attribute"`
-		Percent        int    `json:"percent"`
-		Milestone      string `json:"milestone"`
-		Output         string `json:"output"`
-		Auth           string `json:"auth"`
-		Parent         uint64 `json:"parent"`
-		Path           string `json:"path"`
-		Grade          int    `json:"grade"`
-		Name           string `json:"name"`
-		Code           string `json:"code"`
-		PlanBegin      string `json:"begin"`
-		PlanEnd        string `json:"end"`
-		RealBegan      string `json:"realBegan"`
-		RealEnd        string `json:"realEnd"`
-		Days           int    `json:"days"`
-		Status         string `json:"status"`
-		SubStatus      string `json:"subStatus"`
-		Pri            string `json:"pri"`
-		Description    string `json:"desc"`
-		Version        int    `json:"version"`
-		ParentVersion  int    `json:"parentVersion"`
-		PlanDuration   int    `json:"planDuration"`
-		RealDuration   int    `json:"realDuration"`
-		OpenedBy       string `json:"openedBy"`
-		OpenedDate     string `json:"openedDate"`
-		OpenedVersion  string `json:"openedVersion"`
-		LastEditedBy   string `json:"lastEditedBy"`
-		LastEditedDate string `json:"lastEditedDate"`
-		ClosedBy       string `json:"closedBy"`
-		ClosedDate     string `json:"closedDate"`
-		CanceledBy     string `json:"canceledBy"`
-		CanceledDate   string `json:"canceledDate"`
-		SuspendedDate  string `json:"suspendedDate"`
-		PO             string `json:"PO"`
-		PM             string `json:"PM"`
-		QD             string `json:"QD"`
-		RD             string `json:"RD"`
-		Team           string `json:"team"`
-		Acl            string `json:"acl"`
-		Whitelist      string `json:"whitelist"`
-		OrderIn        int    `json:"order"`
-		Vision         string `json:"vision"`
-		DisplayCards   int    `json:"displayCards"`
-		FluidBoard     string `json:"fluidBoard"`
-		Deleted        string `json:"deleted"`
+	ID             uint64              `json:"id"`
+	Project        uint64              `json:"project"`
+	Model          string              `json:"model"`
+	Type           string              `json:"type"`
+	Lifetime       string              `json:"lifetime"`
+	Budget         string              `json:"budget"`
+	BudgetUnit     string              `json:"budgetUnit"`
+	Attribute      string              `json:"attribute"`
+	Percent        int                 `json:"percent"`
+	Milestone      string              `json:"milestone"`
+	Output         string              `json:"output"`
+	Auth           string              `json:"auth"`
+	Parent         uint64              `json:"parent"`
+	Path           string              `json:"path"`
+	Grade          int                 `json:"grade"`
+	Name           string              `json:"name"`
+	Code           string              `json:"code"`
+	PlanBegin      *helper.Iso8601Time `json:"begin"`
+	PlanEnd        *helper.Iso8601Time `json:"end"`
+	RealBegan      *helper.Iso8601Time `json:"realBegan"`
+	RealEnd        *helper.Iso8601Time `json:"realEnd"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Pri            string              `json:"pri"`
+	Description    string              `json:"desc"`
+	Version        int                 `json:"version"`
+	ParentVersion  int                 `json:"parentVersion"`
+	PlanDuration   int                 `json:"planDuration"`
+	RealDuration   int                 `json:"realDuration"`
+	OpenedBy       *ZentaoAccount      `json:"openedBy"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedVersion  string              `json:"openedVersion"`
+	LastEditedBy   *ZentaoAccount      `json:"lastEditedBy"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	ClosedBy       *ZentaoAccount      `json:"closedBy"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	CanceledBy     *ZentaoAccount      `json:"canceledBy"`
+	CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+	SuspendedDate  *helper.Iso8601Time `json:"suspendedDate"`
+	PO             *ZentaoAccount      `json:"PO"`
+	PM             *ZentaoAccount      `json:"PM"`
+	QD             *ZentaoAccount      `json:"QD"`
+	RD             *ZentaoAccount      `json:"RD"`
+	Team           string              `json:"team"`
+	Acl            string              `json:"acl"`
+	Whitelist      []*ZentaoAccount    `json:"whitelist"`
+	OrderIn        int                 `json:"order"`
+	Vision         string              `json:"vision"`
+	DisplayCards   int                 `json:"displayCards"`
+	FluidBoard     string              `json:"fluidBoard"`
+	Deleted        bool                `json:"deleted"`
+	TotalHours     float64             `json:"totalHours"`
+	TotalEstimate  float64             `json:"totalEstimate"`
+	TotalConsumed  float64             `json:"totalConsumed"`
+	TotalLeft      float64             `json:"totalLeft"`
+	ProjectInfo    struct {
+		ID             uint64              `json:"id"`
+		Project        uint64              `json:"project"`
+		Model          string              `json:"model"`
+		Type           string              `json:"type"`
+		Lifetime       string              `json:"lifetime"`
+		Budget         string              `json:"budget"`
+		BudgetUnit     string              `json:"budgetUnit"`
+		Attribute      string              `json:"attribute"`
+		Percent        int                 `json:"percent"`
+		Milestone      string              `json:"milestone"`
+		Output         string              `json:"output"`
+		Auth           string              `json:"auth"`
+		Parent         uint64              `json:"parent"`
+		Path           string              `json:"path"`
+		Grade          int                 `json:"grade"`
+		Name           string              `json:"name"`
+		Code           string              `json:"code"`
+		PlanBegin      *helper.Iso8601Time `json:"begin"`
+		PlanEnd        *helper.Iso8601Time `json:"end"`
+		RealBegan      string              `json:"realBegan"`
+		RealEnd        *helper.Iso8601Time `json:"realEnd"`
+		Status         string              `json:"status"`
+		SubStatus      string              `json:"subStatus"`
+		Pri            string              `json:"pri"`
+		Description    string              `json:"desc"`
+		Version        int                 `json:"version"`
+		ParentVersion  int                 `json:"parentVersion"`
+		PlanDuration   int                 `json:"planDuration"`
+		RealDuration   int                 `json:"realDuration"`
+		OpenedBy       string              `json:"openedBy"`
+		OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+		OpenedVersion  string              `json:"openedVersion"`
+		LastEditedBy   string              `json:"lastEditedBy"`
+		LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+		ClosedBy       string              `json:"closedBy"`
+		ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+		CanceledBy     string              `json:"canceledBy"`
+		CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+		SuspendedDate  *helper.Iso8601Time `json:"suspendedDate"`
+		PO             string              `json:"PO"`
+		PM             string              `json:"PM"`
+		QD             string              `json:"QD"`
+		RD             string              `json:"RD"`
+		Team           string              `json:"team"`
+		Acl            string              `json:"acl"`
+		Whitelist      string              `json:"whitelist"`
+		OrderIn        int                 `json:"order"`
+		Vision         string              `json:"vision"`
+		DisplayCards   int                 `json:"displayCards"`
+		FluidBoard     string              `json:"fluidBoard"`
+		Deleted        string              `json:"deleted"`
 	} `json:"projectInfo"`
 	Progress    float64 `json:"progress"`
 	TeamMembers []struct {
@@ -188,7 +141,6 @@ type ZentaoExecutionRes struct {
 		Position   string  `json:"position"`
 		Limited    string  `json:"limited"`
 		Join       string  `json:"join"`
-		Days       int     `json:"days"`
 		Hours      int     `json:"hours"`
 		Estimate   string  `json:"estimate"`
 		Consumed   string  `json:"consumed"`
@@ -207,47 +159,46 @@ type ZentaoExecutionRes struct {
 }
 
 type ZentaoExecution struct {
-	ConnectionId   uint64     `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Id             uint64     `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Project        uint64     `json:"project"`
-	Model          string     `json:"model"`
-	Type           string     `json:"type"`
-	Lifetime       string     `json:"lifetime"`
-	Budget         string     `json:"budget"`
-	BudgetUnit     string     `json:"budgetUnit"`
-	Attribute      string     `json:"attribute"`
-	Percent        int        `json:"percent"`
-	Milestone      string     `json:"milestone"`
-	Output         string     `json:"output"`
-	Auth           string     `json:"auth"`
-	Parent         uint64     `json:"parent"`
-	Path           string     `json:"path"`
-	Grade          int        `json:"grade"`
-	Name           string     `json:"name"`
-	Code           string     `json:"code"`
-	PlanBegin      string     `json:"begin"`
-	PlanEnd        string     `json:"end"`
-	RealBegan      *time.Time `json:"realBegan"`
-	RealEnd        *time.Time `json:"realEnd"`
-	Days           int        `json:"days"`
-	Status         string     `json:"status"`
-	SubStatus      string     `json:"subStatus"`
-	Pri            string     `json:"pri"`
-	Description    string     `json:"desc"`
-	Version        int        `json:"version"`
-	ParentVersion  int        `json:"parentVersion"`
-	PlanDuration   int        `json:"planDuration"`
-	RealDuration   int        `json:"realDuration"`
+	ConnectionId   uint64              `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Id             uint64              `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Project        uint64              `json:"project"`
+	Model          string              `json:"model"`
+	Type           string              `json:"type"`
+	Lifetime       string              `json:"lifetime"`
+	Budget         string              `json:"budget"`
+	BudgetUnit     string              `json:"budgetUnit"`
+	Attribute      string              `json:"attribute"`
+	Percent        int                 `json:"percent"`
+	Milestone      string              `json:"milestone"`
+	Output         string              `json:"output"`
+	Auth           string              `json:"auth"`
+	Parent         uint64              `json:"parent"`
+	Path           string              `json:"path"`
+	Grade          int                 `json:"grade"`
+	Name           string              `json:"name"`
+	Code           string              `json:"code"`
+	PlanBegin      *helper.Iso8601Time `json:"begin"`
+	PlanEnd        *helper.Iso8601Time `json:"end"`
+	RealBegan      *helper.Iso8601Time `json:"realBegan"`
+	RealEnd        *helper.Iso8601Time `json:"realEnd"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Pri            string              `json:"pri"`
+	Description    string              `json:"desc"`
+	Version        int                 `json:"version"`
+	ParentVersion  int                 `json:"parentVersion"`
+	PlanDuration   int                 `json:"planDuration"`
+	RealDuration   int                 `json:"realDuration"`
 	OpenedById     uint64
-	OpenedDate     *time.Time `json:"openedDate"`
-	OpenedVersion  string     `json:"openedVersion"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedVersion  string              `json:"openedVersion"`
 	LastEditedById uint64
-	LastEditedDate *time.Time `json:"lastEditedDate"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
 	ClosedById     uint64
-	ClosedDate     *time.Time `json:"closedDate"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
 	CanceledById   uint64
-	CanceledDate   *time.Time `json:"canceledDate"`
-	SuspendedDate  string     `json:"suspendedDate"`
+	CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+	SuspendedDate  *helper.Iso8601Time `json:"suspendedDate"`
 	POId           uint64
 	PMId           uint64
 	QDId           uint64
diff --git a/plugins/zentao/models/migrationscripts/20220906_add_init_tables.go b/plugins/zentao/models/migrationscripts/20221121_add_init_tables.go
similarity index 74%
rename from plugins/zentao/models/migrationscripts/20220906_add_init_tables.go
rename to plugins/zentao/models/migrationscripts/20221121_add_init_tables.go
index 5d6e3cb23..732f960e8 100644
--- a/plugins/zentao/models/migrationscripts/20220906_add_init_tables.go
+++ b/plugins/zentao/models/migrationscripts/20221121_add_init_tables.go
@@ -27,6 +27,24 @@ import (
 type addInitTables struct{}
 
 func (*addInitTables) Up(basicRes core.BasicRes) errors.Error {
+	db := basicRes.GetDal()
+	err := db.DropTables(
+		&archived.ZentaoConnection{},
+		&archived.ZentaoProject{},
+		&archived.ZentaoProduct{},
+		&archived.ZentaoExecution{},
+		&archived.ZentaoStory{},
+		&archived.ZentaoBug{},
+		&archived.ZentaoTask{},
+		"_tool_zentao_bugs`",
+		"_tool_zentao_executions`",
+		"_tool_zentao_products`",
+		"_tool_zentao_stories`",
+		"_tool_zentao_tasks`",
+	)
+	if err != nil {
+		return err
+	}
 	return migrationhelper.AutoMigrateTables(
 		basicRes,
 		&archived.ZentaoConnection{},
@@ -36,11 +54,13 @@ func (*addInitTables) Up(basicRes core.BasicRes) errors.Error {
 		&archived.ZentaoStory{},
 		&archived.ZentaoBug{},
 		&archived.ZentaoTask{},
+		&archived.ZentaoAccount{},
+		&archived.ZentaoDepartment{},
 	)
 }
 
 func (*addInitTables) Version() uint64 {
-	return 20220910000001
+	return 20221121000001
 }
 
 func (*addInitTables) Name() string {
diff --git a/plugins/zentao/models/product.go b/plugins/zentao/models/product.go
index ef5cd8418..85c57b2bd 100644
--- a/plugins/zentao/models/product.go
+++ b/plugins/zentao/models/product.go
@@ -19,53 +19,33 @@ package models
 
 import (
 	"github.com/apache/incubator-devlake/models/common"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoProductRes struct {
-	ID          uint64 `json:"id"`
-	Program     int    `json:"program"`
-	Name        string `json:"name"`
-	Code        string `json:"code"`
-	Bind        string `json:"bind"`
-	Line        int    `json:"line"`
-	Type        string `json:"type"`
-	Status      string `json:"status"`
-	SubStatus   string `json:"subStatus"`
-	Description string `json:"desc"`
-	PO          struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"PO"`
-	QD struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"QD"`
-	RD struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"RD"`
-	Feedback  interface{}   `json:"feedback"`
-	Acl       string        `json:"acl"`
-	Whitelist []interface{} `json:"whitelist"`
-	Reviewer  string        `json:"reviewer"`
-	CreatedBy struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"createdBy"`
-	CreatedDate    *time.Time `json:"createdDate"`
-	CreatedVersion string     `json:"createdVersion"`
-	OrderIn        int        `json:"order"`
-	Vision         string     `json:"vision"`
-	Deleted        string     `json:"deleted"`
+	ID             uint64              `json:"id"`
+	Program        int                 `json:"program"`
+	Name           string              `json:"name"`
+	Code           string              `json:"code"`
+	Bind           string              `json:"bind"`
+	Line           int                 `json:"line"`
+	Type           string              `json:"type"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Description    string              `json:"desc"`
+	PO             *ZentaoAccount      `json:"PO"`
+	QD             *ZentaoAccount      `json:"QD"`
+	RD             *ZentaoAccount      `json:"RD"`
+	Feedback       interface{}         `json:"feedback"`
+	Acl            string              `json:"acl"`
+	Whitelist      []interface{}       `json:"whitelist"`
+	Reviewer       string              `json:"reviewer"`
+	CreatedBy      *ZentaoAccount      `json:"createdBy"`
+	CreatedDate    *helper.Iso8601Time `json:"createdDate"`
+	CreatedVersion string              `json:"createdVersion"`
+	OrderIn        int                 `json:"order"`
+	Vision         string              `json:"vision"`
+	Deleted        string              `json:"deleted"`
 	Stories        struct {
 		Active    int `json:"active"`
 		Reviewing int `json:"reviewing"`
@@ -104,20 +84,20 @@ type ZentaoProduct struct {
 	Acl            string `json:"acl"`
 	Reviewer       string `json:"reviewer"`
 	CreatedById    uint64
-	CreatedDate    *time.Time `json:"createdDate"`
-	CreatedVersion string     `json:"createdVersion"`
-	OrderIn        int        `json:"order"`
-	Deleted        string     `json:"deleted"`
-	Plans          int        `json:"plans"`
-	Releases       int        `json:"releases"`
-	Builds         int        `json:"builds"`
-	Cases          int        `json:"cases"`
-	Projects       int        `json:"projects"`
-	Executions     int        `json:"executions"`
-	Bugs           int        `json:"bugs"`
-	Docs           int        `json:"docs"`
-	Progress       float64    `json:"progress"`
-	CaseReview     bool       `json:"caseReview"`
+	CreatedDate    *helper.Iso8601Time `json:"createdDate"`
+	CreatedVersion string              `json:"createdVersion"`
+	OrderIn        int                 `json:"order"`
+	Deleted        string              `json:"deleted"`
+	Plans          int                 `json:"plans"`
+	Releases       int                 `json:"releases"`
+	Builds         int                 `json:"builds"`
+	Cases          int                 `json:"cases"`
+	Projects       int                 `json:"projects"`
+	Executions     int                 `json:"executions"`
+	Bugs           int                 `json:"bugs"`
+	Docs           int                 `json:"docs"`
+	Progress       float64             `json:"progress"`
+	CaseReview     bool                `json:"caseReview"`
 	common.NoPKModel
 }
 
diff --git a/plugins/zentao/models/project.go b/plugins/zentao/models/project.go
index 3432c5b3f..ef854d0a6 100644
--- a/plugins/zentao/models/project.go
+++ b/plugins/zentao/models/project.go
@@ -19,53 +19,53 @@ package models
 
 import (
 	"github.com/apache/incubator-devlake/models/common"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoProject struct {
 	common.NoPKModel
-	ConnectionId  uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	ID            uint64 `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
-	Project       uint64 `json:"project"`
-	Model         string `json:"model"`
-	Type          string `json:"type"`
-	Lifetime      string `json:"lifetime"`
-	Budget        string `json:"budget"`
-	BudgetUnit    string `json:"budgetUnit"`
-	Attribute     string `json:"attribute"`
-	Percent       int    `json:"percent"`
-	Milestone     string `json:"milestone"`
-	Output        string `json:"output"`
-	Auth          string `json:"auth"`
-	Parent        uint64 `json:"parent"`
-	Path          string `json:"path"`
-	Grade         int    `json:"grade"`
-	Name          string `json:"name"`
-	Code          string `json:"code"`
-	PlanBegin     string `json:"begin"`
-	PlanEnd       string `json:"end"`
-	RealBegan     string `json:"realBegan"`
-	RealEnd       string `json:"realEnd"`
-	Days          int    `json:"days"`
-	Status        string `json:"status"`
-	SubStatus     string `json:"subStatus"`
-	Pri           string `json:"pri"`
-	Description   string `json:"desc"`
-	Version       int    `json:"version"`
-	ParentVersion int    `json:"parentVersion"`
-	PlanDuration  int    `json:"planDuration"`
-	RealDuration  int    `json:"realDuration"`
+	ConnectionId  uint64              `gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	ID            uint64              `json:"id" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+	Project       uint64              `json:"project"`
+	Model         string              `json:"model"`
+	Type          string              `json:"type"`
+	Lifetime      string              `json:"lifetime"`
+	Budget        string              `json:"budget"`
+	BudgetUnit    string              `json:"budgetUnit"`
+	Attribute     string              `json:"attribute"`
+	Percent       int                 `json:"percent"`
+	Milestone     string              `json:"milestone"`
+	Output        string              `json:"output"`
+	Auth          string              `json:"auth"`
+	Parent        uint64              `json:"parent"`
+	Path          string              `json:"path"`
+	Grade         int                 `json:"grade"`
+	Name          string              `json:"name"`
+	Code          string              `json:"code"`
+	PlanBegin     *helper.Iso8601Time `json:"begin"`
+	PlanEnd       *helper.Iso8601Time `json:"end"`
+	RealBegan     string              `json:"realBegan"`
+	RealEnd       *helper.Iso8601Time `json:"realEnd"`
+	Days          int                 `json:"days"`
+	Status        string              `json:"status"`
+	SubStatus     string              `json:"subStatus"`
+	Pri           string              `json:"pri"`
+	Description   string              `json:"desc"`
+	Version       int                 `json:"version"`
+	ParentVersion int                 `json:"parentVersion"`
+	PlanDuration  int                 `json:"planDuration"`
+	RealDuration  int                 `json:"realDuration"`
 	//OpenedBy       string    `json:"openedBy"`
-	OpenedDate     *time.Time  `json:"openedDate"`
-	OpenedVersion  string      `json:"openedVersion"`
-	LastEditedBy   string      `json:"lastEditedBy"`
-	LastEditedDate **time.Time `json:"lastEditedDate"`
-	ClosedBy       string      `json:"closedBy"`
-	ClosedDate     **time.Time `json:"closedDate"`
-	CanceledBy     string      `json:"canceledBy"`
-	CanceledDate   **time.Time `json:"canceledDate"`
-	SuspendedDate  string      `json:"suspendedDate"`
-	PO             string      `json:"PO"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	OpenedVersion  string              `json:"openedVersion"`
+	LastEditedBy   string              `json:"lastEditedBy"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	ClosedBy       string              `json:"closedBy"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	CanceledBy     string              `json:"canceledBy"`
+	CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+	SuspendedDate  *helper.Iso8601Time `json:"suspendedDate"`
+	PO             string              `json:"PO"`
 	PM             `json:"PM"`
 	QD             string `json:"QD"`
 	RD             string `json:"RD"`
diff --git a/plugins/zentao/models/story.go b/plugins/zentao/models/story.go
index e919d58d8..8df779f0a 100644
--- a/plugins/zentao/models/story.go
+++ b/plugins/zentao/models/story.go
@@ -19,89 +19,64 @@ package models
 
 import (
 	"github.com/apache/incubator-devlake/models/common"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoStoryRes struct {
-	ID          uint64        `json:"id"`
-	Vision      string        `json:"vision"`
-	Parent      uint64        `json:"parent"`
-	Product     uint64        `json:"product"`
-	Branch      int           `json:"branch"`
-	Module      int           `json:"module"`
-	Plan        string        `json:"plan"`
-	Source      string        `json:"source"`
-	SourceNote  string        `json:"sourceNote"`
-	FromBug     int           `json:"fromBug"`
-	Feedback    int           `json:"feedback"`
-	Title       string        `json:"title"`
-	Keywords    string        `json:"keywords"`
-	Type        string        `json:"type"`
-	Category    string        `json:"category"`
-	Pri         int           `json:"pri"`
-	Estimate    float64       `json:"estimate"`
-	Status      string        `json:"status"`
-	SubStatus   string        `json:"subStatus"`
-	Color       string        `json:"color"`
-	Stage       string        `json:"stage"`
-	Mailto      []interface{} `json:"mailto"`
-	Lib         int           `json:"lib"`
-	FromStory   uint64        `json:"fromStory"`
-	FromVersion int           `json:"fromVersion"`
-	OpenedBy    struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"openedBy"`
-	OpenedDate *time.Time `json:"openedDate"`
-	AssignedTo struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"assignedTo"`
-	AssignedDate *time.Time `json:"assignedDate"`
-	ApprovedDate string     `json:"approvedDate"`
-	LastEditedBy struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"lastEditedBy"`
-	LastEditedDate *time.Time `json:"lastEditedDate"`
-	ChangedBy      string     `json:"changedBy"`
-	ChangedDate    string     `json:"changedDate"`
-	ReviewedBy     struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"reviewedBy"`
-	ReviewedDate *time.Time `json:"reviewedDate"`
-	ClosedBy     struct {
-		ID       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"closedBy"`
-	ClosedDate       *time.Time `json:"closedDate"`
-	ClosedReason     string     `json:"closedReason"`
-	ActivatedDate    string     `json:"activatedDate"`
-	ToBug            int        `json:"toBug"`
-	ChildStories     string     `json:"childStories"`
-	LinkStories      string     `json:"linkStories"`
-	LinkRequirements string     `json:"linkRequirements"`
-	DuplicateStory   uint64     `json:"duplicateStory"`
-	Version          int        `json:"version"`
-	StoryChanged     string     `json:"storyChanged"`
-	FeedbackBy       string     `json:"feedbackBy"`
-	NotifyEmail      string     `json:"notifyEmail"`
-	URChanged        string     `json:"URChanged"`
-	Deleted          bool       `json:"deleted"`
-	PriOrder         string     `json:"priOrder"`
-	PlanTitle        string     `json:"planTitle"`
-	ProductStatus    string     `json:"productStatus"`
+	ID               uint64              `json:"id"`
+	Vision           string              `json:"vision"`
+	Parent           uint64              `json:"parent"`
+	Product          uint64              `json:"product"`
+	Branch           int                 `json:"branch"`
+	Module           int                 `json:"module"`
+	Plan             string              `json:"plan"`
+	Source           string              `json:"source"`
+	SourceNote       string              `json:"sourceNote"`
+	FromBug          int                 `json:"fromBug"`
+	Feedback         int                 `json:"feedback"`
+	Title            string              `json:"title"`
+	Keywords         string              `json:"keywords"`
+	Type             string              `json:"type"`
+	Category         string              `json:"category"`
+	Pri              int                 `json:"pri"`
+	Estimate         float64             `json:"estimate"`
+	Status           string              `json:"status"`
+	SubStatus        string              `json:"subStatus"`
+	Color            string              `json:"color"`
+	Stage            string              `json:"stage"`
+	Mailto           []interface{}       `json:"mailto"`
+	Lib              int                 `json:"lib"`
+	FromStory        uint64              `json:"fromStory"`
+	FromVersion      int                 `json:"fromVersion"`
+	OpenedBy         *ZentaoAccount      `json:"openedBy"`
+	OpenedDate       *helper.Iso8601Time `json:"openedDate"`
+	AssignedTo       *ZentaoAccount      `json:"assignedTo"`
+	AssignedDate     *helper.Iso8601Time `json:"assignedDate"`
+	ApprovedDate     *helper.Iso8601Time `json:"approvedDate"`
+	LastEditedBy     *ZentaoAccount      `json:"lastEditedBy"`
+	LastEditedDate   *helper.Iso8601Time `json:"lastEditedDate"`
+	ChangedBy        string              `json:"changedBy"`
+	ChangedDate      *helper.Iso8601Time `json:"changedDate"`
+	ReviewedBy       *ZentaoAccount      `json:"reviewedBy"`
+	ReviewedDate     *helper.Iso8601Time `json:"reviewedDate"`
+	ClosedBy         *ZentaoAccount      `json:"closedBy"`
+	ClosedDate       *helper.Iso8601Time `json:"closedDate"`
+	ClosedReason     string              `json:"closedReason"`
+	ActivatedDate    *helper.Iso8601Time `json:"activatedDate"`
+	ToBug            int                 `json:"toBug"`
+	ChildStories     string              `json:"childStories"`
+	LinkStories      string              `json:"linkStories"`
+	LinkRequirements string              `json:"linkRequirements"`
+	DuplicateStory   uint64              `json:"duplicateStory"`
+	Version          int                 `json:"version"`
+	StoryChanged     string              `json:"storyChanged"`
+	FeedbackBy       string              `json:"feedbackBy"`
+	NotifyEmail      string              `json:"notifyEmail"`
+	URChanged        string              `json:"URChanged"`
+	Deleted          bool                `json:"deleted"`
+	PriOrder         string              `json:"priOrder"`
+	PlanTitle        string              `json:"planTitle"`
+	ProductStatus    string              `json:"productStatus"`
 }
 
 type ZentaoStory struct {
@@ -136,32 +111,32 @@ type ZentaoStory struct {
 	FromVersion      int    `json:"fromVersion"`
 	OpenedById       uint64
 	OpenedByName     string
-	OpenedDate       *time.Time `json:"openedDate"`
+	OpenedDate       *helper.Iso8601Time `json:"openedDate"`
 	AssignedToId     uint64
 	AssignedToName   string
-	AssignedDate     *time.Time `json:"assignedDate"`
-	ApprovedDate     string     `json:"approvedDate"`
+	AssignedDate     *helper.Iso8601Time `json:"assignedDate"`
+	ApprovedDate     *helper.Iso8601Time `json:"approvedDate"`
 	LastEditedId     uint64
-	LastEditedDate   *time.Time `json:"lastEditedDate"`
-	ChangedDate      string     `json:"changedDate"`
-	ReviewedById     uint64     `json:"reviewedBy"`
-	ReviewedDate     *time.Time `json:"reviewedDate"`
+	LastEditedDate   *helper.Iso8601Time `json:"lastEditedDate"`
+	ChangedDate      *helper.Iso8601Time `json:"changedDate"`
+	ReviewedById     uint64              `json:"reviewedBy"`
+	ReviewedDate     *helper.Iso8601Time `json:"reviewedDate"`
 	ClosedId         uint64
-	ClosedDate       *time.Time `json:"closedDate"`
-	ClosedReason     string     `json:"closedReason"`
-	ActivatedDate    string     `json:"activatedDate"`
-	ToBug            int        `json:"toBug"`
-	ChildStories     string     `json:"childStories"`
-	LinkStories      string     `json:"linkStories"`
-	LinkRequirements string     `json:"linkRequirements"`
-	DuplicateStory   uint64     `json:"duplicateStory"`
-	StoryChanged     string     `json:"storyChanged"`
-	FeedbackBy       string     `json:"feedbackBy"`
-	NotifyEmail      string     `json:"notifyEmail"`
-	URChanged        string     `json:"URChanged"`
-	Deleted          bool       `json:"deleted"`
-	PriOrder         string     `json:"priOrder"`
-	PlanTitle        string     `json:"planTitle"`
+	ClosedDate       *helper.Iso8601Time `json:"closedDate"`
+	ClosedReason     string              `json:"closedReason"`
+	ActivatedDate    *helper.Iso8601Time `json:"activatedDate"`
+	ToBug            int                 `json:"toBug"`
+	ChildStories     string              `json:"childStories"`
+	LinkStories      string              `json:"linkStories"`
+	LinkRequirements string              `json:"linkRequirements"`
+	DuplicateStory   uint64              `json:"duplicateStory"`
+	StoryChanged     string              `json:"storyChanged"`
+	FeedbackBy       string              `json:"feedbackBy"`
+	NotifyEmail      string              `json:"notifyEmail"`
+	URChanged        string              `json:"URChanged"`
+	Deleted          bool                `json:"deleted"`
+	PriOrder         string              `json:"priOrder"`
+	PlanTitle        string              `json:"planTitle"`
 }
 
 func (ZentaoStory) TableName() string {
diff --git a/plugins/zentao/models/task.go b/plugins/zentao/models/task.go
index 94411c295..4f9be832f 100644
--- a/plugins/zentao/models/task.go
+++ b/plugins/zentao/models/task.go
@@ -19,100 +19,65 @@ package models
 
 import (
 	"github.com/apache/incubator-devlake/models/common"
-	"time"
+	"github.com/apache/incubator-devlake/plugins/helper"
 )
 
 type ZentaoTaskRes struct {
-	Id            uint64  `json:"id"`
-	Project       uint64  `json:"project"`
-	Parent        uint64  `json:"parent"`
-	Execution     uint64  `json:"execution"`
-	Module        int     `json:"module"`
-	Design        int     `json:"design"`
-	Story         uint64  `json:"story"`
-	StoryVersion  int     `json:"storyVersion"`
-	DesignVersion int     `json:"designVersion"`
-	FromBug       int     `json:"fromBug"`
-	Feedback      int     `json:"feedback"`
-	FromIssue     int     `json:"fromIssue"`
-	Name          string  `json:"name"`
-	Type          string  `json:"type"`
-	Mode          string  `json:"mode"`
-	Pri           int     `json:"pri"`
-	Estimate      float64 `json:"estimate"`
-	Consumed      float64 `json:"consumed"`
-	Deadline      string  `json:"deadline"`
-	Status        string  `json:"status"`
-	SubStatus     string  `json:"subStatus"`
-	Color         string  `json:"color"`
-	Mailto        []struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"mailto"`
-	Description string `json:"desc"`
-	Version     int    `json:"version"`
-	OpenedBy    struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"openedBy"`
-	OpenedDate *time.Time `json:"openedDate"`
-	AssignedTo struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"assignedTo"`
-	AssignedDate *time.Time `json:"assignedDate"`
-	EstStarted   string     `json:"estStarted"`
-	RealStarted  *time.Time `json:"realStarted"`
-	FinishedBy   struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"finishedBy"`
-	FinishedDate *time.Time `json:"finishedDate"`
-	FinishedList string     `json:"finishedList"`
-	CanceledBy   struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"canceledBy"`
-	CanceledDate *time.Time `json:"canceledDate"`
-	ClosedBy     struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"closedBy"`
-	ClosedDate   *time.Time `json:"closedDate"`
-	PlanDuration int        `json:"planDuration"`
-	RealDuration int        `json:"realDuration"`
-	ClosedReason string     `json:"closedReason"`
-	LastEditedBy struct {
-		Id       uint64 `json:"id"`
-		Account  string `json:"account"`
-		Avatar   string `json:"avatar"`
-		Realname string `json:"realname"`
-	} `json:"lastEditedBy"`
-	LastEditedDate *time.Time `json:"lastEditedDate"`
-	ActivatedDate  string     `json:"activatedDate"`
-	OrderIn        int        `json:"order"`
-	Repo           int        `json:"repo"`
-	Mr             int        `json:"mr"`
-	Entry          string     `json:"entry"`
-	NumOfLine      string     `json:"lines"`
-	V1             string     `json:"v1"`
-	V2             string     `json:"v2"`
-	Deleted        bool       `json:"deleted"`
-	Vision         string     `json:"vision"`
-	StoryID        uint64     `json:"storyID"`
-	StoryTitle     string     `json:"storyTitle"`
+	Id             uint64              `json:"id"`
+	Project        uint64              `json:"project"`
+	Parent         uint64              `json:"parent"`
+	Execution      uint64              `json:"execution"`
+	Module         int                 `json:"module"`
+	Design         int                 `json:"design"`
+	Story          uint64              `json:"story"`
+	StoryVersion   int                 `json:"storyVersion"`
+	DesignVersion  int                 `json:"designVersion"`
+	FromBug        int                 `json:"fromBug"`
+	Feedback       int                 `json:"feedback"`
+	FromIssue      int                 `json:"fromIssue"`
+	Name           string              `json:"name"`
+	Type           string              `json:"type"`
+	Mode           string              `json:"mode"`
+	Pri            int                 `json:"pri"`
+	Estimate       float64             `json:"estimate"`
+	Consumed       float64             `json:"consumed"`
+	Deadline       string              `json:"deadline"`
+	Status         string              `json:"status"`
+	SubStatus      string              `json:"subStatus"`
+	Color          string              `json:"color"`
+	Mailto         []*ZentaoAccount    `json:"mailto"`
+	Description    string              `json:"desc"`
+	Version        int                 `json:"version"`
+	OpenedBy       *ZentaoAccount      `json:"openedBy"`
+	OpenedDate     *helper.Iso8601Time `json:"openedDate"`
+	AssignedTo     *ZentaoAccount      `json:"assignedTo"`
+	AssignedDate   *helper.Iso8601Time `json:"assignedDate"`
+	EstStarted     string              `json:"estStarted"`
+	RealStarted    *helper.Iso8601Time `json:"realStarted"`
+	FinishedBy     *ZentaoAccount      `json:"finishedBy"`
+	FinishedDate   *helper.Iso8601Time `json:"finishedDate"`
+	FinishedList   string              `json:"finishedList"`
+	CanceledBy     *ZentaoAccount      `json:"canceledBy"`
+	CanceledDate   *helper.Iso8601Time `json:"canceledDate"`
+	ClosedBy       *ZentaoAccount      `json:"closedBy"`
+	ClosedDate     *helper.Iso8601Time `json:"closedDate"`
+	PlanDuration   int                 `json:"planDuration"`
+	RealDuration   int                 `json:"realDuration"`
+	ClosedReason   string              `json:"closedReason"`
+	LastEditedBy   *ZentaoAccount      `json:"lastEditedBy"`
+	LastEditedDate *helper.Iso8601Time `json:"lastEditedDate"`
+	ActivatedDate  *helper.Iso8601Time `json:"activatedDate"`
+	OrderIn        int                 `json:"order"`
+	Repo           int                 `json:"repo"`
+	Mr             int                 `json:"mr"`
+	Entry          string              `json:"entry"`
+	NumOfLine      string              `json:"lines"`
+	V1             string              `json:"v1"`
+	V2             string              `json:"v2"`
+	Deleted        bool                `json:"deleted"`
+	Vision         string              `json:"vision"`
+	StoryID        uint64              `json:"storyID"`
+	StoryTitle     string              `json:"storyTitle"`
 	Branch         interface {
 	} `json:"branch"`
 	LatestStoryVersion interface {
@@ -157,43 +122,43 @@ type ZentaoTask struct {
 	Version            int    `json:"version"`
 	OpenedById         uint64
 	OpenedByName       string
-	OpenedDate         *time.Time `json:"openedDate"`
+	OpenedDate         *helper.Iso8601Time `json:"openedDate"`
 	AssignedToId       uint64
 	AssignedToName     string
-	AssignedDate       *time.Time `json:"assignedDate"`
-	EstStarted         string     `json:"estStarted"`
-	RealStarted        *time.Time `json:"realStarted"`
+	AssignedDate       *helper.Iso8601Time `json:"assignedDate"`
+	EstStarted         string              `json:"estStarted"`
+	RealStarted        *helper.Iso8601Time `json:"realStarted"`
 	FinishedId         uint64
-	FinishedDate       *time.Time `json:"finishedDate"`
-	FinishedList       string     `json:"finishedList"`
+	FinishedDate       *helper.Iso8601Time `json:"finishedDate"`
+	FinishedList       string              `json:"finishedList"`
 	CanceledId         uint64
-	CanceledDate       *time.Time `json:"canceledDate"`
+	CanceledDate       *helper.Iso8601Time `json:"canceledDate"`
 	ClosedById         uint64
-	ClosedDate         *time.Time `json:"closedDate"`
-	PlanDuration       int        `json:"planDuration"`
-	RealDuration       int        `json:"realDuration"`
-	ClosedReason       string     `json:"closedReason"`
+	ClosedDate         *helper.Iso8601Time `json:"closedDate"`
+	PlanDuration       int                 `json:"planDuration"`
+	RealDuration       int                 `json:"realDuration"`
+	ClosedReason       string              `json:"closedReason"`
 	LastEditedId       uint64
-	LastEditedDate     *time.Time `json:"lastEditedDate"`
-	ActivatedDate      string     `json:"activatedDate"`
-	OrderIn            int        `json:"order"`
-	Repo               int        `json:"repo"`
-	Mr                 int        `json:"mr"`
-	Entry              string     `json:"entry"`
-	NumOfLine          string     `json:"lines"`
-	V1                 string     `json:"v1"`
-	V2                 string     `json:"v2"`
-	Deleted            bool       `json:"deleted"`
-	Vision             string     `json:"vision"`
-	StoryID            uint64     `json:"storyID"`
-	StoryTitle         string     `json:"storyTitle"`
-	Branch             int        `json:"branch"`
-	LatestStoryVersion int        `json:"latestStoryVersion"`
-	StoryStatus        string     `json:"storyStatus"`
-	AssignedToRealName string     `json:"assignedToRealName"`
-	PriOrder           string     `json:"priOrder"`
-	NeedConfirm        bool       `json:"needConfirm"`
-	Progress           float64    `json:"progress"`
+	LastEditedDate     *helper.Iso8601Time `json:"lastEditedDate"`
+	ActivatedDate      *helper.Iso8601Time `json:"activatedDate"`
+	OrderIn            int                 `json:"order"`
+	Repo               int                 `json:"repo"`
+	Mr                 int                 `json:"mr"`
+	Entry              string              `json:"entry"`
+	NumOfLine          string              `json:"lines"`
+	V1                 string              `json:"v1"`
+	V2                 string              `json:"v2"`
+	Deleted            bool                `json:"deleted"`
+	Vision             string              `json:"vision"`
+	StoryID            uint64              `json:"storyID"`
+	StoryTitle         string              `json:"storyTitle"`
+	Branch             int                 `json:"branch"`
+	LatestStoryVersion int                 `json:"latestStoryVersion"`
+	StoryStatus        string              `json:"storyStatus"`
+	AssignedToRealName string              `json:"assignedToRealName"`
+	PriOrder           string              `json:"priOrder"`
+	NeedConfirm        bool                `json:"needConfirm"`
+	Progress           float64             `json:"progress"`
 }
 
 func (ZentaoTask) TableName() string {
diff --git a/plugins/zentao/tasks/story_collector.go b/plugins/zentao/tasks/account_collector.go
similarity index 80%
copy from plugins/zentao/tasks/story_collector.go
copy to plugins/zentao/tasks/account_collector.go
index d7db9c4f7..a7f664462 100644
--- a/plugins/zentao/tasks/story_collector.go
+++ b/plugins/zentao/tasks/account_collector.go
@@ -27,11 +27,11 @@ import (
 	"net/url"
 )
 
-const RAW_STORY_TABLE = "zentao_api_stories"
+const RAW_ACCOUNT_TABLE = "zentao_api_accounts"
 
-var _ core.SubTaskEntryPoint = CollectStory
+var _ core.SubTaskEntryPoint = CollectAccount
 
-func CollectStory(taskCtx core.SubTaskContext) errors.Error {
+func CollectAccount(taskCtx core.SubTaskContext) errors.Error {
 	data := taskCtx.GetData().(*ZentaoTaskData)
 	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
 		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
@@ -42,30 +42,29 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 				ExecutionId:  data.Options.ExecutionId,
 				ProjectId:    data.Options.ProjectId,
 			},
-			Table: RAW_STORY_TABLE,
+			Table: RAW_ACCOUNT_TABLE,
 		},
 		ApiClient: data.ApiClient,
 
 		PageSize: 100,
 		// TODO write which api would you want request
-		UrlTemplate: "/products/{{ .Params.ProjectId }}/stories",
+		UrlTemplate: "/users",
 		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
 			query := url.Values{}
 			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
 			query.Set("limit", fmt.Sprintf("%v", reqData.Pager.Size))
-			query.Set("status", "allstory")
 			return query, nil
 		},
 		GetTotalPages: GetTotalPagesFromResponse,
 		ResponseParser: func(res *http.Response) ([]json.RawMessage, errors.Error) {
 			var data struct {
-				Story []json.RawMessage `json:"stories"`
+				Users []json.RawMessage `json:"users"`
 			}
 			err := helper.UnmarshalResponse(res, &data)
 			if err != nil {
 				return nil, errors.Default.Wrap(err, "error reading endpoint response by Zentao bug collector")
 			}
-			return data.Story, nil
+			return data.Users, nil
 		},
 	})
 	if err != nil {
@@ -75,9 +74,9 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 	return collector.Execute()
 }
 
-var CollectStoryMeta = core.SubTaskMeta{
-	Name:             "CollectStory",
-	EntryPoint:       CollectStory,
+var CollectAccountMeta = core.SubTaskMeta{
+	Name:             "CollectAccount",
+	EntryPoint:       CollectAccount,
 	EnabledByDefault: true,
-	Description:      "Collect Story data from Zentao api",
+	Description:      "Collect Account data from Zentao api",
 }
diff --git a/plugins/zentao/tasks/product_convertor.go b/plugins/zentao/tasks/account_convertor.go
similarity index 65%
copy from plugins/zentao/tasks/product_convertor.go
copy to plugins/zentao/tasks/account_convertor.go
index 83fa41154..be17d1172 100644
--- a/plugins/zentao/tasks/product_convertor.go
+++ b/plugins/zentao/tasks/account_convertor.go
@@ -20,8 +20,8 @@ package tasks
 import (
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
 	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
-	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/core/dal"
 	"github.com/apache/incubator-devlake/plugins/helper"
@@ -29,57 +29,56 @@ import (
 	"reflect"
 )
 
-var _ core.SubTaskEntryPoint = ConvertProducts
+var _ core.SubTaskEntryPoint = ConvertAccount
 
-var ConvertProductMeta = core.SubTaskMeta{
-	Name:             "convertProducts",
-	EntryPoint:       ConvertProducts,
+var ConvertAccountMeta = core.SubTaskMeta{
+	Name:             "convertAccount",
+	EntryPoint:       ConvertAccount,
 	EnabledByDefault: true,
-	Description:      "convert Zentao products",
+	Description:      "convert Zentao account",
 	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
 }
 
-func ConvertProducts(taskCtx core.SubTaskContext) errors.Error {
+func ConvertAccount(taskCtx core.SubTaskContext) errors.Error {
 	data := taskCtx.GetData().(*ZentaoTaskData)
 	db := taskCtx.GetDal()
-	boardIdGen := didgen.NewDomainIdGenerator(&models.ZentaoProduct{})
+	accountIdGen := didgen.NewDomainIdGenerator(&models.ZentaoAccount{})
+	deptIdGen := didgen.NewDomainIdGenerator(&models.ZentaoDepartment{})
 	cursor, err := db.Cursor(
-		dal.From(&models.ZentaoProduct{}),
-		dal.Where(`_tool_zentao_products.id = ? and 
-			_tool_zentao_products.connection_id = ?`, data.Options.ProductId, data.Options.ConnectionId),
+		dal.From(&models.ZentaoAccount{}),
+		dal.Where(`_tool_zentao_accounts.connection_id = ?`, data.Options.ConnectionId),
 	)
 	if err != nil {
 		return err
 	}
 	defer cursor.Close()
 	convertor, err := helper.NewDataConverter(helper.DataConverterArgs{
-		InputRowType: reflect.TypeOf(models.ZentaoProduct{}),
+		InputRowType: reflect.TypeOf(models.ZentaoAccount{}),
 		Input:        cursor,
 		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
 			Ctx: taskCtx,
 			Params: ZentaoApiParams{
 				ConnectionId: data.Options.ConnectionId,
-				ExecutionId:  data.Options.ExecutionId,
 				ProductId:    data.Options.ProductId,
+				ExecutionId:  data.Options.ExecutionId,
 				ProjectId:    data.Options.ProjectId,
 			},
-			Table: RAW_PRODUCT_TABLE,
+			Table: RAW_ACCOUNT_TABLE,
 		},
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
-			toolProduct := inputRow.(*models.ZentaoProduct)
+			toolEntity := inputRow.(*models.ZentaoAccount)
 
-			domainBoard := &ticket.Board{
+			domainEntity := &crossdomain.Account{
 				DomainEntity: domainlayer.DomainEntity{
-					Id: boardIdGen.Generate(toolProduct.ConnectionId, toolProduct.Id),
+					Id: accountIdGen.Generate(toolEntity.ConnectionId, toolEntity.ID),
 				},
-				Name:        toolProduct.Name,
-				Description: toolProduct.Description,
-				CreatedDate: toolProduct.CreatedDate,
-				Type:        toolProduct.Type,
+				FullName:     toolEntity.Realname,
+				UserName:     toolEntity.Account,
+				AvatarUrl:    toolEntity.Avatar,
+				Organization: deptIdGen.Generate(toolEntity.ConnectionId, toolEntity.Dept),
 			}
-
 			results := make([]interface{}, 0)
-			results = append(results, domainBoard)
+			results = append(results, domainEntity)
 			return results, nil
 		},
 	})
diff --git a/plugins/zentao/tasks/story_collector.go b/plugins/zentao/tasks/account_extractor.go
similarity index 52%
copy from plugins/zentao/tasks/story_collector.go
copy to plugins/zentao/tasks/account_extractor.go
index d7db9c4f7..f982d837e 100644
--- a/plugins/zentao/tasks/story_collector.go
+++ b/plugins/zentao/tasks/account_extractor.go
@@ -19,21 +19,25 @@ package tasks
 
 import (
 	"encoding/json"
-	"fmt"
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/helper"
-	"net/http"
-	"net/url"
+	"github.com/apache/incubator-devlake/plugins/zentao/models"
 )
 
-const RAW_STORY_TABLE = "zentao_api_stories"
+var _ core.SubTaskEntryPoint = ExtractAccount
 
-var _ core.SubTaskEntryPoint = CollectStory
+var ExtractAccountMeta = core.SubTaskMeta{
+	Name:             "extractAccount",
+	EntryPoint:       ExtractAccount,
+	EnabledByDefault: true,
+	Description:      "extract Zentao account",
+	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
+}
 
-func CollectStory(taskCtx core.SubTaskContext) errors.Error {
+func ExtractAccount(taskCtx core.SubTaskContext) errors.Error {
 	data := taskCtx.GetData().(*ZentaoTaskData)
-	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
 		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
 			Ctx: taskCtx,
 			Params: ZentaoApiParams{
@@ -42,42 +46,24 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 				ExecutionId:  data.Options.ExecutionId,
 				ProjectId:    data.Options.ProjectId,
 			},
-			Table: RAW_STORY_TABLE,
+			Table: RAW_ACCOUNT_TABLE,
 		},
-		ApiClient: data.ApiClient,
-
-		PageSize: 100,
-		// TODO write which api would you want request
-		UrlTemplate: "/products/{{ .Params.ProjectId }}/stories",
-		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
-			query := url.Values{}
-			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
-			query.Set("limit", fmt.Sprintf("%v", reqData.Pager.Size))
-			query.Set("status", "allstory")
-			return query, nil
-		},
-		GetTotalPages: GetTotalPagesFromResponse,
-		ResponseParser: func(res *http.Response) ([]json.RawMessage, errors.Error) {
-			var data struct {
-				Story []json.RawMessage `json:"stories"`
-			}
-			err := helper.UnmarshalResponse(res, &data)
+		Extract: func(row *helper.RawData) ([]interface{}, errors.Error) {
+			account := &models.ZentaoAccount{}
+			err := json.Unmarshal(row.Data, account)
 			if err != nil {
-				return nil, errors.Default.Wrap(err, "error reading endpoint response by Zentao bug collector")
+				return nil, errors.Default.WrapRaw(err)
 			}
-			return data.Story, nil
+			account.ConnectionId = data.Options.ConnectionId
+			results := make([]interface{}, 0)
+			results = append(results, account)
+			return results, nil
 		},
 	})
+
 	if err != nil {
 		return err
 	}
 
-	return collector.Execute()
-}
-
-var CollectStoryMeta = core.SubTaskMeta{
-	Name:             "CollectStory",
-	EntryPoint:       CollectStory,
-	EnabledByDefault: true,
-	Description:      "Collect Story data from Zentao api",
+	return extractor.Execute()
 }
diff --git a/plugins/zentao/tasks/bug_convertor.go b/plugins/zentao/tasks/bug_convertor.go
index c58c332f1..882a1fe2a 100644
--- a/plugins/zentao/tasks/bug_convertor.go
+++ b/plugins/zentao/tasks/bug_convertor.go
@@ -76,11 +76,11 @@ func ConvertBug(taskCtx core.SubTaskContext) errors.Error {
 				},
 				IssueKey:       strconv.FormatUint(toolEntity.ID, 10),
 				Title:          toolEntity.Title,
-				Type:           toolEntity.Type,
+				Type:           ticket.BUG,
 				OriginalStatus: toolEntity.Status,
-				ResolutionDate: toolEntity.ClosedDate,
-				CreatedDate:    toolEntity.OpenedDate,
-				UpdatedDate:    toolEntity.LastEditedDate,
+				ResolutionDate: toolEntity.ClosedDate.ToNullableTime(),
+				CreatedDate:    toolEntity.OpenedDate.ToNullableTime(),
+				UpdatedDate:    toolEntity.LastEditedDate.ToNullableTime(),
 				ParentIssueId:  storyIdGen.Generate(data.Options.ConnectionId, toolEntity.Story),
 				Priority:       string(rune(toolEntity.Pri)),
 				CreatorId:      strconv.FormatUint(toolEntity.OpenedById, 10),
@@ -91,12 +91,12 @@ func ConvertBug(taskCtx core.SubTaskContext) errors.Error {
 			}
 			switch toolEntity.Status {
 			case "resolved":
-				domainEntity.Status = "DONE"
+				domainEntity.Status = ticket.DONE
 			default:
-				domainEntity.Status = "IN_PROGRESS"
+				domainEntity.Status = ticket.IN_PROGRESS
 			}
 			if toolEntity.ClosedDate != nil {
-				domainEntity.LeadTimeMinutes = int64(toolEntity.ClosedDate.Sub(*toolEntity.OpenedDate).Minutes())
+				domainEntity.LeadTimeMinutes = int64(toolEntity.ClosedDate.ToNullableTime().Sub(toolEntity.OpenedDate.ToTime()).Minutes())
 			}
 			domainBoardIssue := &ticket.BoardIssue{
 				BoardId: boardIdGen.Generate(data.Options.ConnectionId, data.Options.ProductId),
diff --git a/plugins/zentao/tasks/bug_extractor.go b/plugins/zentao/tasks/bug_extractor.go
index 085e2a342..7935c5a17 100644
--- a/plugins/zentao/tasks/bug_extractor.go
+++ b/plugins/zentao/tasks/bug_extractor.go
@@ -88,19 +88,19 @@ func ExtractBug(taskCtx core.SubTaskContext) errors.Error {
 				ActivatedDate:  res.ActivatedDate,
 				FeedbackBy:     res.FeedbackBy,
 				NotifyEmail:    res.NotifyEmail,
-				OpenedById:     res.OpenedBy.ID,
-				OpenedByName:   res.OpenedBy.Realname,
+				OpenedById:     getAccountId(res.OpenedBy),
+				OpenedByName:   getAccountName(res.OpenedBy),
 				OpenedDate:     res.OpenedDate,
 				OpenedBuild:    res.OpenedBuild,
-				AssignedToId:   res.AssignedTo.ID,
-				AssignedToName: res.AssignedTo.Realname,
+				AssignedToId:   getAccountId(res.AssignedTo),
+				AssignedToName: getAccountName(res.AssignedTo),
 				AssignedDate:   res.AssignedDate,
 				Deadline:       res.Deadline,
-				ResolvedById:   res.ResolvedBy.ID,
+				ResolvedById:   getAccountId(res.ResolvedBy),
 				Resolution:     res.Resolution,
 				ResolvedBuild:  res.ResolvedBuild,
 				ResolvedDate:   res.ResolvedDate,
-				ClosedById:     res.ClosedBy.ID,
+				ClosedById:     getAccountId(res.ClosedBy),
 				ClosedDate:     res.ClosedDate,
 				DuplicateBug:   res.DuplicateBug,
 				LinkBug:        res.LinkBug,
@@ -115,7 +115,7 @@ func ExtractBug(taskCtx core.SubTaskContext) errors.Error {
 				RepoType:       res.RepoType,
 				IssueKey:       res.IssueKey,
 				Testtask:       res.Testtask,
-				LastEditedById: res.LastEditedBy.ID,
+				LastEditedById: getAccountId(res.LastEditedBy),
 				LastEditedDate: res.LastEditedDate,
 				Deleted:        res.Deleted,
 				PriOrder:       res.PriOrder,
diff --git a/plugins/zentao/tasks/story_collector.go b/plugins/zentao/tasks/department_collector.go
similarity index 80%
copy from plugins/zentao/tasks/story_collector.go
copy to plugins/zentao/tasks/department_collector.go
index d7db9c4f7..eacc2779e 100644
--- a/plugins/zentao/tasks/story_collector.go
+++ b/plugins/zentao/tasks/department_collector.go
@@ -27,11 +27,11 @@ import (
 	"net/url"
 )
 
-const RAW_STORY_TABLE = "zentao_api_stories"
+const RAW_DEPARTMENT_TABLE = "zentao_api_departments"
 
-var _ core.SubTaskEntryPoint = CollectStory
+var _ core.SubTaskEntryPoint = CollectDepartment
 
-func CollectStory(taskCtx core.SubTaskContext) errors.Error {
+func CollectDepartment(taskCtx core.SubTaskContext) errors.Error {
 	data := taskCtx.GetData().(*ZentaoTaskData)
 	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
 		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
@@ -42,30 +42,29 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 				ExecutionId:  data.Options.ExecutionId,
 				ProjectId:    data.Options.ProjectId,
 			},
-			Table: RAW_STORY_TABLE,
+			Table: RAW_DEPARTMENT_TABLE,
 		},
 		ApiClient: data.ApiClient,
 
 		PageSize: 100,
 		// TODO write which api would you want request
-		UrlTemplate: "/products/{{ .Params.ProjectId }}/stories",
+		UrlTemplate: "/users",
 		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
 			query := url.Values{}
 			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
 			query.Set("limit", fmt.Sprintf("%v", reqData.Pager.Size))
-			query.Set("status", "allstory")
 			return query, nil
 		},
 		GetTotalPages: GetTotalPagesFromResponse,
 		ResponseParser: func(res *http.Response) ([]json.RawMessage, errors.Error) {
 			var data struct {
-				Story []json.RawMessage `json:"stories"`
+				Users []json.RawMessage `json:"users"`
 			}
 			err := helper.UnmarshalResponse(res, &data)
 			if err != nil {
 				return nil, errors.Default.Wrap(err, "error reading endpoint response by Zentao bug collector")
 			}
-			return data.Story, nil
+			return data.Users, nil
 		},
 	})
 	if err != nil {
@@ -75,9 +74,9 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 	return collector.Execute()
 }
 
-var CollectStoryMeta = core.SubTaskMeta{
-	Name:             "CollectStory",
-	EntryPoint:       CollectStory,
+var CollectDepartmentMeta = core.SubTaskMeta{
+	Name:             "CollectDepartment",
+	EntryPoint:       CollectDepartment,
 	EnabledByDefault: true,
-	Description:      "Collect Story data from Zentao api",
+	Description:      "Collect Department data from Zentao api",
 }
diff --git a/plugins/zentao/tasks/product_convertor.go b/plugins/zentao/tasks/department_convertor.go
similarity index 66%
copy from plugins/zentao/tasks/product_convertor.go
copy to plugins/zentao/tasks/department_convertor.go
index 83fa41154..b892bc822 100644
--- a/plugins/zentao/tasks/product_convertor.go
+++ b/plugins/zentao/tasks/department_convertor.go
@@ -20,8 +20,8 @@ package tasks
 import (
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/models/domainlayer"
+	"github.com/apache/incubator-devlake/models/domainlayer/crossdomain"
 	"github.com/apache/incubator-devlake/models/domainlayer/didgen"
-	"github.com/apache/incubator-devlake/models/domainlayer/ticket"
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/core/dal"
 	"github.com/apache/incubator-devlake/plugins/helper"
@@ -29,57 +29,53 @@ import (
 	"reflect"
 )
 
-var _ core.SubTaskEntryPoint = ConvertProducts
+var _ core.SubTaskEntryPoint = ConvertDepartment
 
-var ConvertProductMeta = core.SubTaskMeta{
-	Name:             "convertProducts",
-	EntryPoint:       ConvertProducts,
+var ConvertDepartmentMeta = core.SubTaskMeta{
+	Name:             "convertDepartment",
+	EntryPoint:       ConvertDepartment,
 	EnabledByDefault: true,
-	Description:      "convert Zentao products",
+	Description:      "convert Zentao department",
 	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
 }
 
-func ConvertProducts(taskCtx core.SubTaskContext) errors.Error {
+func ConvertDepartment(taskCtx core.SubTaskContext) errors.Error {
 	data := taskCtx.GetData().(*ZentaoTaskData)
 	db := taskCtx.GetDal()
-	boardIdGen := didgen.NewDomainIdGenerator(&models.ZentaoProduct{})
+	departmentIdGen := didgen.NewDomainIdGenerator(&models.ZentaoDepartment{})
 	cursor, err := db.Cursor(
-		dal.From(&models.ZentaoProduct{}),
-		dal.Where(`_tool_zentao_products.id = ? and 
-			_tool_zentao_products.connection_id = ?`, data.Options.ProductId, data.Options.ConnectionId),
+		dal.From(&models.ZentaoDepartment{}),
+		dal.Where(`_tool_zentao_departments.connection_id = ?`, data.Options.ConnectionId),
 	)
 	if err != nil {
 		return err
 	}
 	defer cursor.Close()
 	convertor, err := helper.NewDataConverter(helper.DataConverterArgs{
-		InputRowType: reflect.TypeOf(models.ZentaoProduct{}),
+		InputRowType: reflect.TypeOf(models.ZentaoDepartment{}),
 		Input:        cursor,
 		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
 			Ctx: taskCtx,
 			Params: ZentaoApiParams{
 				ConnectionId: data.Options.ConnectionId,
-				ExecutionId:  data.Options.ExecutionId,
 				ProductId:    data.Options.ProductId,
+				ExecutionId:  data.Options.ExecutionId,
 				ProjectId:    data.Options.ProjectId,
 			},
-			Table: RAW_PRODUCT_TABLE,
+			Table: RAW_DEPARTMENT_TABLE,
 		},
 		Convert: func(inputRow interface{}) ([]interface{}, errors.Error) {
-			toolProduct := inputRow.(*models.ZentaoProduct)
+			toolEntity := inputRow.(*models.ZentaoDepartment)
 
-			domainBoard := &ticket.Board{
+			domainEntity := &crossdomain.Team{
 				DomainEntity: domainlayer.DomainEntity{
-					Id: boardIdGen.Generate(toolProduct.ConnectionId, toolProduct.Id),
+					Id: departmentIdGen.Generate(toolEntity.ConnectionId, toolEntity.ID),
 				},
-				Name:        toolProduct.Name,
-				Description: toolProduct.Description,
-				CreatedDate: toolProduct.CreatedDate,
-				Type:        toolProduct.Type,
+				Name:     toolEntity.Name,
+				ParentId: departmentIdGen.Generate(toolEntity.ConnectionId, toolEntity.Parent),
 			}
-
 			results := make([]interface{}, 0)
-			results = append(results, domainBoard)
+			results = append(results, domainEntity)
 			return results, nil
 		},
 	})
diff --git a/plugins/zentao/tasks/story_collector.go b/plugins/zentao/tasks/department_extractor.go
similarity index 52%
copy from plugins/zentao/tasks/story_collector.go
copy to plugins/zentao/tasks/department_extractor.go
index d7db9c4f7..8ec1a6355 100644
--- a/plugins/zentao/tasks/story_collector.go
+++ b/plugins/zentao/tasks/department_extractor.go
@@ -19,21 +19,25 @@ package tasks
 
 import (
 	"encoding/json"
-	"fmt"
 	"github.com/apache/incubator-devlake/errors"
 	"github.com/apache/incubator-devlake/plugins/core"
 	"github.com/apache/incubator-devlake/plugins/helper"
-	"net/http"
-	"net/url"
+	"github.com/apache/incubator-devlake/plugins/zentao/models"
 )
 
-const RAW_STORY_TABLE = "zentao_api_stories"
+var _ core.SubTaskEntryPoint = ExtractDepartment
 
-var _ core.SubTaskEntryPoint = CollectStory
+var ExtractDepartmentMeta = core.SubTaskMeta{
+	Name:             "extractDepartment",
+	EntryPoint:       ExtractDepartment,
+	EnabledByDefault: true,
+	Description:      "extract Zentao department",
+	DomainTypes:      []string{core.DOMAIN_TYPE_TICKET},
+}
 
-func CollectStory(taskCtx core.SubTaskContext) errors.Error {
+func ExtractDepartment(taskCtx core.SubTaskContext) errors.Error {
 	data := taskCtx.GetData().(*ZentaoTaskData)
-	collector, err := helper.NewApiCollector(helper.ApiCollectorArgs{
+	extractor, err := helper.NewApiExtractor(helper.ApiExtractorArgs{
 		RawDataSubTaskArgs: helper.RawDataSubTaskArgs{
 			Ctx: taskCtx,
 			Params: ZentaoApiParams{
@@ -42,42 +46,24 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 				ExecutionId:  data.Options.ExecutionId,
 				ProjectId:    data.Options.ProjectId,
 			},
-			Table: RAW_STORY_TABLE,
+			Table: RAW_DEPARTMENT_TABLE,
 		},
-		ApiClient: data.ApiClient,
-
-		PageSize: 100,
-		// TODO write which api would you want request
-		UrlTemplate: "/products/{{ .Params.ProjectId }}/stories",
-		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
-			query := url.Values{}
-			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
-			query.Set("limit", fmt.Sprintf("%v", reqData.Pager.Size))
-			query.Set("status", "allstory")
-			return query, nil
-		},
-		GetTotalPages: GetTotalPagesFromResponse,
-		ResponseParser: func(res *http.Response) ([]json.RawMessage, errors.Error) {
-			var data struct {
-				Story []json.RawMessage `json:"stories"`
-			}
-			err := helper.UnmarshalResponse(res, &data)
+		Extract: func(row *helper.RawData) ([]interface{}, errors.Error) {
+			department := &models.ZentaoDepartment{}
+			err := json.Unmarshal(row.Data, department)
 			if err != nil {
-				return nil, errors.Default.Wrap(err, "error reading endpoint response by Zentao bug collector")
+				return nil, errors.Default.WrapRaw(err)
 			}
-			return data.Story, nil
+			department.ConnectionId = data.Options.ConnectionId
+			results := make([]interface{}, 0)
+			results = append(results, department)
+			return results, nil
 		},
 	})
+
 	if err != nil {
 		return err
 	}
 
-	return collector.Execute()
-}
-
-var CollectStoryMeta = core.SubTaskMeta{
-	Name:             "CollectStory",
-	EntryPoint:       CollectStory,
-	EnabledByDefault: true,
-	Description:      "Collect Story data from Zentao api",
+	return extractor.Execute()
 }
diff --git a/plugins/zentao/tasks/execution_convertor.go b/plugins/zentao/tasks/execution_convertor.go
index a53ebb802..b663dfec0 100644
--- a/plugins/zentao/tasks/execution_convertor.go
+++ b/plugins/zentao/tasks/execution_convertor.go
@@ -75,7 +75,7 @@ func ConvertExecutions(taskCtx core.SubTaskContext) errors.Error {
 				Name:        toolExecution.Name,
 				Description: toolExecution.Description,
 				Url:         toolExecution.Path,
-				CreatedDate: toolExecution.OpenedDate,
+				CreatedDate: toolExecution.OpenedDate.ToNullableTime(),
 				Type:        toolExecution.Type,
 			}
 
diff --git a/plugins/zentao/tasks/execution_extractor.go b/plugins/zentao/tasks/execution_extractor.go
index 3e1094c6c..6ed94b870 100644
--- a/plugins/zentao/tasks/execution_extractor.go
+++ b/plugins/zentao/tasks/execution_extractor.go
@@ -77,7 +77,6 @@ func ExtractExecutions(taskCtx core.SubTaskContext) errors.Error {
 				PlanEnd:        res.PlanEnd,
 				RealBegan:      res.RealBegan,
 				RealEnd:        res.RealEnd,
-				Days:           res.Days,
 				Status:         res.Status,
 				SubStatus:      res.SubStatus,
 				Pri:            res.Pri,
@@ -86,20 +85,20 @@ func ExtractExecutions(taskCtx core.SubTaskContext) errors.Error {
 				ParentVersion:  res.ParentVersion,
 				PlanDuration:   res.PlanDuration,
 				RealDuration:   res.RealDuration,
-				OpenedById:     res.OpenedBy.ID,
+				OpenedById:     getAccountId(res.OpenedBy),
 				OpenedDate:     res.OpenedDate,
 				OpenedVersion:  res.OpenedVersion,
-				LastEditedById: res.LastEditedBy.ID,
+				LastEditedById: getAccountId(res.LastEditedBy),
 				LastEditedDate: res.LastEditedDate,
-				ClosedById:     res.ClosedBy.ID,
+				ClosedById:     getAccountId(res.ClosedBy),
 				ClosedDate:     res.ClosedDate,
-				CanceledById:   res.CanceledBy.ID,
+				CanceledById:   getAccountId(res.CanceledBy),
 				CanceledDate:   res.CanceledDate,
 				SuspendedDate:  res.SuspendedDate,
-				POId:           res.PO.ID,
-				PMId:           res.PM.ID,
-				QDId:           res.QD.ID,
-				RDId:           res.RD.ID,
+				POId:           getAccountId(res.PO),
+				PMId:           getAccountId(res.PM),
+				QDId:           getAccountId(res.QD),
+				RDId:           getAccountId(res.RD),
 				Team:           res.Team,
 				Acl:            res.Acl,
 				OrderIn:        res.OrderIn,
diff --git a/plugins/zentao/tasks/product_convertor.go b/plugins/zentao/tasks/product_convertor.go
index 83fa41154..afbb94631 100644
--- a/plugins/zentao/tasks/product_convertor.go
+++ b/plugins/zentao/tasks/product_convertor.go
@@ -74,7 +74,7 @@ func ConvertProducts(taskCtx core.SubTaskContext) errors.Error {
 				},
 				Name:        toolProduct.Name,
 				Description: toolProduct.Description,
-				CreatedDate: toolProduct.CreatedDate,
+				CreatedDate: toolProduct.CreatedDate.ToNullableTime(),
 				Type:        toolProduct.Type,
 			}
 
diff --git a/plugins/zentao/tasks/product_extractor.go b/plugins/zentao/tasks/product_extractor.go
index 21a624846..d5d38582d 100644
--- a/plugins/zentao/tasks/product_extractor.go
+++ b/plugins/zentao/tasks/product_extractor.go
@@ -66,12 +66,12 @@ func ExtractProducts(taskCtx core.SubTaskContext) errors.Error {
 				Status:         res.Status,
 				SubStatus:      res.SubStatus,
 				Description:    res.Description,
-				POId:           res.PO.ID,
-				QDId:           res.QD.ID,
-				RDId:           res.RD.ID,
+				POId:           getAccountId(res.PO),
+				QDId:           getAccountId(res.QD),
+				RDId:           getAccountId(res.RD),
 				Acl:            res.Acl,
 				Reviewer:       res.Reviewer,
-				CreatedById:    res.CreatedBy.ID,
+				CreatedById:    getAccountId(res.CreatedBy),
 				CreatedDate:    res.CreatedDate,
 				CreatedVersion: res.CreatedVersion,
 				OrderIn:        res.OrderIn,
diff --git a/plugins/zentao/tasks/shared.go b/plugins/zentao/tasks/shared.go
index 2dc63d789..eb6afafe2 100644
--- a/plugins/zentao/tasks/shared.go
+++ b/plugins/zentao/tasks/shared.go
@@ -19,6 +19,7 @@ package tasks
 
 import (
 	"github.com/apache/incubator-devlake/errors"
+	"github.com/apache/incubator-devlake/plugins/zentao/models"
 	"net/http"
 
 	"github.com/apache/incubator-devlake/plugins/helper"
@@ -33,3 +34,17 @@ func GetTotalPagesFromResponse(res *http.Response, args *helper.ApiCollectorArgs
 	return body.Page, nil
 
 }
+
+func getAccountId(account *models.ZentaoAccount) uint64 {
+	if account != nil {
+		return account.ID
+	}
+	return 0
+}
+
+func getAccountName(account *models.ZentaoAccount) string {
+	if account != nil {
+		return account.Realname
+	}
+	return ""
+}
diff --git a/plugins/zentao/tasks/story_collector.go b/plugins/zentao/tasks/story_collector.go
index d7db9c4f7..368e375d3 100644
--- a/plugins/zentao/tasks/story_collector.go
+++ b/plugins/zentao/tasks/story_collector.go
@@ -48,7 +48,7 @@ func CollectStory(taskCtx core.SubTaskContext) errors.Error {
 
 		PageSize: 100,
 		// TODO write which api would you want request
-		UrlTemplate: "/products/{{ .Params.ProjectId }}/stories",
+		UrlTemplate: "/products/{{ .Params.ProductId }}/stories",
 		Query: func(reqData *helper.RequestData) (url.Values, errors.Error) {
 			query := url.Values{}
 			query.Set("page", fmt.Sprintf("%v", reqData.Pager.Page))
diff --git a/plugins/zentao/tasks/story_convertor.go b/plugins/zentao/tasks/story_convertor.go
index 95b713535..391346b92 100644
--- a/plugins/zentao/tasks/story_convertor.go
+++ b/plugins/zentao/tasks/story_convertor.go
@@ -48,7 +48,7 @@ func ConvertStory(taskCtx core.SubTaskContext) errors.Error {
 	cursor, err := db.Cursor(
 		dal.From(&models.ZentaoStory{}),
 		dal.Where(`_tool_zentao_stories.product = ? and 
-			_tool_zentao_stories.connection_id = ?`, data.Options.ExecutionId, data.Options.ConnectionId),
+			_tool_zentao_stories.connection_id = ?`, data.Options.ProductId, data.Options.ConnectionId),
 	)
 	if err != nil {
 		return err
@@ -78,9 +78,9 @@ func ConvertStory(taskCtx core.SubTaskContext) errors.Error {
 				Title:          toolEntity.Title,
 				Type:           toolEntity.Type,
 				OriginalStatus: toolEntity.Stage,
-				ResolutionDate: toolEntity.ClosedDate,
-				CreatedDate:    toolEntity.OpenedDate,
-				UpdatedDate:    toolEntity.LastEditedDate,
+				ResolutionDate: toolEntity.ClosedDate.ToNullableTime(),
+				CreatedDate:    toolEntity.OpenedDate.ToNullableTime(),
+				UpdatedDate:    toolEntity.LastEditedDate.ToNullableTime(),
 				ParentIssueId:  storyIdGen.Generate(data.Options.ConnectionId, toolEntity.Parent),
 				Priority:       string(rune(toolEntity.Pri)),
 				CreatorId:      strconv.FormatUint(toolEntity.OpenedById, 10),
@@ -90,12 +90,14 @@ func ConvertStory(taskCtx core.SubTaskContext) errors.Error {
 			}
 			switch toolEntity.Stage {
 			case "closed":
-				domainEntity.Status = "DONE"
+				domainEntity.Status = ticket.DONE
+			case "wait":
+				domainEntity.Status = ticket.TODO
 			default:
-				domainEntity.Status = "IN_PROGRESS"
+				domainEntity.Status = ticket.IN_PROGRESS
 			}
 			if toolEntity.ClosedDate != nil {
-				domainEntity.LeadTimeMinutes = int64(toolEntity.ClosedDate.Sub(*toolEntity.OpenedDate).Minutes())
+				domainEntity.LeadTimeMinutes = int64(toolEntity.ClosedDate.ToNullableTime().Sub(toolEntity.OpenedDate.ToTime()).Minutes())
 			}
 			domainBoardIssue := &ticket.BoardIssue{
 				BoardId: boardIdGen.Generate(data.Options.ConnectionId, data.Options.ProductId),
diff --git a/plugins/zentao/tasks/story_extractor.go b/plugins/zentao/tasks/story_extractor.go
index b144d738a..9495b9b63 100644
--- a/plugins/zentao/tasks/story_extractor.go
+++ b/plugins/zentao/tasks/story_extractor.go
@@ -82,19 +82,19 @@ func ExtractStory(taskCtx core.SubTaskContext) errors.Error {
 				Lib:              res.Lib,
 				FromStory:        res.FromStory,
 				FromVersion:      res.FromVersion,
-				OpenedById:       res.OpenedBy.ID,
-				OpenedByName:     res.OpenedBy.Realname,
+				OpenedById:       getAccountId(res.OpenedBy),
+				OpenedByName:     getAccountName(res.OpenedBy),
 				OpenedDate:       res.OpenedDate,
-				AssignedToId:     res.AssignedTo.ID,
-				AssignedToName:   res.AssignedTo.Realname,
+				AssignedToId:     getAccountId(res.AssignedTo),
+				AssignedToName:   getAccountName(res.AssignedTo),
 				AssignedDate:     res.AssignedDate,
 				ApprovedDate:     res.ApprovedDate,
-				LastEditedId:     res.LastEditedBy.ID,
+				LastEditedId:     getAccountId(res.LastEditedBy),
 				LastEditedDate:   res.LastEditedDate,
 				ChangedDate:      res.ChangedDate,
-				ReviewedById:     res.ReviewedBy.ID,
+				ReviewedById:     getAccountId(res.ReviewedBy),
 				ReviewedDate:     res.ReviewedDate,
-				ClosedId:         res.ClosedBy.ID,
+				ClosedId:         getAccountId(res.ClosedBy),
 				ClosedDate:       res.ClosedDate,
 				ClosedReason:     res.ClosedReason,
 				ActivatedDate:    res.ActivatedDate,
diff --git a/plugins/zentao/tasks/task_convertor.go b/plugins/zentao/tasks/task_convertor.go
index 9063289fe..d719c36bc 100644
--- a/plugins/zentao/tasks/task_convertor.go
+++ b/plugins/zentao/tasks/task_convertor.go
@@ -78,11 +78,11 @@ func ConvertTask(taskCtx core.SubTaskContext) errors.Error {
 				IssueKey:       strconv.FormatUint(toolEntity.ID, 10),
 				Title:          toolEntity.Name,
 				Description:    toolEntity.Description,
-				Type:           toolEntity.Type,
+				Type:           "TASK",
 				OriginalStatus: toolEntity.Status,
-				ResolutionDate: toolEntity.ClosedDate,
-				CreatedDate:    toolEntity.OpenedDate,
-				UpdatedDate:    toolEntity.LastEditedDate,
+				ResolutionDate: toolEntity.ClosedDate.ToNullableTime(),
+				CreatedDate:    toolEntity.OpenedDate.ToNullableTime(),
+				UpdatedDate:    toolEntity.LastEditedDate.ToNullableTime(),
 				ParentIssueId:  storyIdGen.Generate(data.Options.ConnectionId, toolEntity.Parent),
 				Priority:       string(rune(toolEntity.Pri)),
 				CreatorId:      strconv.FormatUint(toolEntity.OpenedById, 10),
@@ -91,13 +91,15 @@ func ConvertTask(taskCtx core.SubTaskContext) errors.Error {
 				AssigneeName:   toolEntity.AssignedToName,
 			}
 			switch toolEntity.Status {
-			case "done", "closed":
-				domainEntity.Status = "DONE"
+			case "done", "closed", "cancel":
+				domainEntity.Status = ticket.DONE
+			case "wait":
+				domainEntity.Status = ticket.TODO
 			default:
-				domainEntity.Status = "IN_PROGRESS"
+				domainEntity.Status = ticket.IN_PROGRESS
 			}
 			if toolEntity.ClosedDate != nil {
-				domainEntity.LeadTimeMinutes = int64(toolEntity.ClosedDate.Sub(*toolEntity.OpenedDate).Minutes())
+				domainEntity.LeadTimeMinutes = int64(toolEntity.ClosedDate.ToNullableTime().Sub(toolEntity.OpenedDate.ToTime()).Minutes())
 			}
 			domainBoardIssue := &ticket.BoardIssue{
 				BoardId: boardIdGen.Generate(data.Options.ConnectionId, data.Options.ProductId),
diff --git a/plugins/zentao/tasks/task_extractor.go b/plugins/zentao/tasks/task_extractor.go
index 7fea9f0d6..df1318950 100644
--- a/plugins/zentao/tasks/task_extractor.go
+++ b/plugins/zentao/tasks/task_extractor.go
@@ -81,25 +81,25 @@ func ExtractTask(taskCtx core.SubTaskContext) errors.Error {
 				Color:              res.Color,
 				Description:        res.Description,
 				Version:            res.Version,
-				OpenedById:         res.OpenedBy.Id,
-				OpenedByName:       res.OpenedBy.Realname,
+				OpenedById:         getAccountId(res.OpenedBy),
+				OpenedByName:       getAccountName(res.OpenedBy),
 				OpenedDate:         res.OpenedDate,
-				AssignedToId:       res.AssignedTo.Id,
-				AssignedToName:     res.AssignedTo.Realname,
+				AssignedToId:       getAccountId(res.AssignedTo),
+				AssignedToName:     getAccountName(res.AssignedTo),
 				AssignedDate:       res.AssignedDate,
 				EstStarted:         res.EstStarted,
 				RealStarted:        res.RealStarted,
-				FinishedId:         res.FinishedBy.Id,
+				FinishedId:         getAccountId(res.FinishedBy),
 				FinishedDate:       res.FinishedDate,
 				FinishedList:       res.FinishedList,
-				CanceledId:         res.CanceledBy.Id,
+				CanceledId:         getAccountId(res.CanceledBy),
 				CanceledDate:       res.CanceledDate,
-				ClosedById:         res.ClosedBy.Id,
+				ClosedById:         getAccountId(res.ClosedBy),
 				ClosedDate:         res.ClosedDate,
 				PlanDuration:       res.PlanDuration,
 				RealDuration:       res.RealDuration,
 				ClosedReason:       res.ClosedReason,
-				LastEditedId:       res.LastEditedBy.Id,
+				LastEditedId:       getAccountId(res.LastEditedBy),
 				LastEditedDate:     res.LastEditedDate,
 				ActivatedDate:      res.ActivatedDate,
 				OrderIn:            res.OrderIn,
@@ -113,9 +113,8 @@ func ExtractTask(taskCtx core.SubTaskContext) errors.Error {
 				Vision:             res.Vision,
 				StoryID:            res.Story,
 				StoryTitle:         res.StoryTitle,
-				Branch:             0,
 				LatestStoryVersion: 0,
-				//Product:            res.Product.Id,
+				//Product:            getAccountId(res.Product),
 				//Branch:             res.Branch,
 				//LatestStoryVersion: res.LatestStoryVersion,
 				//StoryStatus:        res.StoryStatus,