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

mappjzc pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 48d64131d Zentao fix (#5092)
48d64131d is described below

commit 48d64131d119aa4169646b11d3372549331290c7
Author: mappjzc <[email protected]>
AuthorDate: Fri May 5 18:30:10 2023 +0800

    Zentao fix (#5092)
    
    * fix: fix zentao
    
    fix scope helper for no trans
    support scope for zentao for test.
    
    Nddtfjiang <[email protected]>
    
    * fix: fix zentao ignore half
    
    fix the error that zentao only ignore collect but not extract.
    it made extract run without raw data and panic.
    
    Nddtfjiang <[email protected]>
---
 backend/helpers/pluginhelper/api/scope_helper.go   |   9 +-
 backend/plugins/zentao/api/init.go                 |   9 +-
 .../e2e/raw_tables/_raw_zentao_api_products.csv    |   3 -
 .../e2e/snapshot_tables/_tool_zentao_products.csv  |   4 +-
 .../zentao/e2e/snapshot_tables/boards_product.csv  |   2 +-
 backend/plugins/zentao/impl/impl.go                |   1 +
 backend/plugins/zentao/models/archived/product.go  |  65 ++++-----
 backend/plugins/zentao/models/archived/project.go  | 129 ++++++++---------
 .../migrationscripts/20221121_add_init_tables.go   |   2 +-
 backend/plugins/zentao/models/product.go           | 135 +++++++++---------
 backend/plugins/zentao/models/project.go           | 156 +++++++++++----------
 backend/plugins/zentao/tasks/bug_collector.go      |   8 +-
 backend/plugins/zentao/tasks/bug_extractor.go      |   7 +
 .../plugins/zentao/tasks/execution_collector.go    |  16 ++-
 .../plugins/zentao/tasks/execution_extractor.go    |   7 +
 backend/plugins/zentao/tasks/product_convertor.go  |   5 +-
 backend/plugins/zentao/tasks/project_convertor.go  |   5 +-
 backend/plugins/zentao/tasks/story_collector.go    |   8 +-
 backend/plugins/zentao/tasks/story_extractor.go    |   7 +
 backend/plugins/zentao/tasks/task_collector.go     |  10 +-
 backend/plugins/zentao/tasks/task_extractor.go     |   7 +
 21 files changed, 327 insertions(+), 268 deletions(-)

diff --git a/backend/helpers/pluginhelper/api/scope_helper.go 
b/backend/helpers/pluginhelper/api/scope_helper.go
index d957862f8..10cdc37c5 100644
--- a/backend/helpers/pluginhelper/api/scope_helper.go
+++ b/backend/helpers/pluginhelper/api/scope_helper.go
@@ -37,6 +37,8 @@ import (
        "reflect"
 )
 
+type NoTransformation struct{}
+
 // ScopeApiHelper is used to write the CURD of scopes
 type ScopeApiHelper[Conn any, Scope any, Tr any] struct {
        log        log.Logger
@@ -261,12 +263,14 @@ func (c *ScopeApiHelper[Conn, Scope, Tr]) 
VerifyConnection(connId uint64) errors
 
 func (c *ScopeApiHelper[Conn, Scope, Tr]) addTransformationName(scopes 
[]*Scope) ([]ScopeRes[Scope], errors.Error) {
        var ruleIds []uint64
+
+       apiScopes := make([]ScopeRes[Scope], 0)
        for _, scope := range scopes {
                valueRepoRuleId := 
reflect.ValueOf(scope).Elem().FieldByName("TransformationRuleId")
                if !valueRepoRuleId.IsValid() {
                        break
                }
-               ruleId := 
reflect.ValueOf(scope).Elem().FieldByName("TransformationRuleId").Uint()
+               ruleId := valueRepoRuleId.Uint()
                if ruleId > 0 {
                        ruleIds = append(ruleIds, ruleId)
                }
@@ -283,7 +287,7 @@ func (c *ScopeApiHelper[Conn, Scope, Tr]) 
addTransformationName(scopes []*Scope)
                // Get the reflect.Value of the i-th struct pointer in the slice
                names[reflect.ValueOf(rule).Elem().FieldByName("ID").Uint()] = 
reflect.ValueOf(rule).Elem().FieldByName("Name").String()
        }
-       apiScopes := make([]ScopeRes[Scope], 0)
+
        for _, scope := range scopes {
                field := 
reflect.ValueOf(scope).Elem().FieldByName("TransformationRuleId")
                if field.IsValid() {
@@ -293,6 +297,7 @@ func (c *ScopeApiHelper[Conn, Scope, Tr]) 
addTransformationName(scopes []*Scope)
                }
 
        }
+
        return apiScopes, nil
 }
 
diff --git a/backend/plugins/zentao/api/init.go 
b/backend/plugins/zentao/api/init.go
index 8108249bc..1f3f51bb2 100644
--- a/backend/plugins/zentao/api/init.go
+++ b/backend/plugins/zentao/api/init.go
@@ -28,12 +28,11 @@ type MixScopes struct {
        ZentaoProduct *models.ZentaoProduct `json:"product"`
        ZentaoProject *models.ZentaoProject `json:"project"`
 }
-type NoTransformation struct{}
 
 var vld *validator.Validate
 var connectionHelper *api.ConnectionApiHelper
-var productScopeHelper *api.ScopeApiHelper[models.ZentaoConnection, 
models.ZentaoProduct, NoTransformation]
-var projectScopeHelper *api.ScopeApiHelper[models.ZentaoConnection, 
models.ZentaoProject, NoTransformation]
+var productScopeHelper *api.ScopeApiHelper[models.ZentaoConnection, 
models.ZentaoProduct, api.NoTransformation]
+var projectScopeHelper *api.ScopeApiHelper[models.ZentaoConnection, 
models.ZentaoProject, api.NoTransformation]
 
 var productRemoteHelper *api.RemoteApiHelper[models.ZentaoConnection, 
models.ZentaoProduct, models.ZentaoProductRes, api.BaseRemoteGroupResponse]
 var projectRemoteHelper *api.RemoteApiHelper[models.ZentaoConnection, 
models.ZentaoProject, models.ZentaoProject, api.NoRemoteGroupResponse]
@@ -46,12 +45,12 @@ func Init(br context.BasicRes) {
                basicRes,
                vld,
        )
-       productScopeHelper = api.NewScopeHelper[models.ZentaoConnection, 
models.ZentaoProduct, NoTransformation](
+       productScopeHelper = api.NewScopeHelper[models.ZentaoConnection, 
models.ZentaoProduct, api.NoTransformation](
                basicRes,
                vld,
                connectionHelper,
        )
-       projectScopeHelper = api.NewScopeHelper[models.ZentaoConnection, 
models.ZentaoProject, NoTransformation](
+       projectScopeHelper = api.NewScopeHelper[models.ZentaoConnection, 
models.ZentaoProject, api.NoTransformation](
                basicRes,
                vld,
                connectionHelper,
diff --git a/backend/plugins/zentao/e2e/raw_tables/_raw_zentao_api_products.csv 
b/backend/plugins/zentao/e2e/raw_tables/_raw_zentao_api_products.csv
deleted file mode 100644
index 7e749c20a..000000000
--- a/backend/plugins/zentao/e2e/raw_tables/_raw_zentao_api_products.csv
+++ /dev/null
@@ -1,3 +0,0 @@
-id,params,data,url,input,created_at
-4,"{""ConnectionId"":1,""ProductId"":3,""ProjectId"":1}","{""id"":3,""program"":10,""name"":""\u4ea7\u54c1\u540d\u79f01"",""code"":""\u4ea7\u54c1\u4ee3\u53f72"",""bind"":""0"",""line"":31,""type"":""normal"",""status"":""normal"",""subStatus"":"""",""desc"":""\u003Cspan
 
style=\""background-color:#FFFFFF;\""\u003E\u4ea7\u54c1\u63cf\u8ff01\u003C\/span\u003E"",""PO"":{""id"":1,""account"":""devlake"",""avatar"":"""",""realname"":""devlake""},""QD"":{""id"":1,""account"":""devlake"",""avatar
 [...]
-5,"{""ConnectionId"":2,""ProductId"":2,""ProjectId"":1}","{""id"":3,""program"":10,""name"":""\u4ea7\u54c1\u540d\u79f01"",""code"":""\u4ea7\u54c1\u4ee3\u53f72"",""bind"":""0"",""line"":31,""type"":""normal"",""status"":""normal"",""subStatus"":"""",""desc"":""\u003Cspan
 
style=\""background-color:#FFFFFF;\""\u003E\u4ea7\u54c1\u63cf\u8ff01\u003C\/span\u003E"",""PO"":{""id"":1,""account"":""devlake"",""avatar"":"""",""realname"":""devlake""},""QD"":{""id"":1,""account"":""devlake"",""avatar
 [...]
diff --git 
a/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv 
b/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv
index eff1a9f33..da1c79109 100644
--- a/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv
+++ b/backend/plugins/zentao/e2e/snapshot_tables/_tool_zentao_products.csv
@@ -1,2 +1,2 @@
-connection_id,id,program,name,code,bind,line,type,status,sub_status,description,po_id,qd_id,rd_id,acl,reviewer,created_by_id,created_date,created_version,order_in,deleted,plans,releases,builds,cases,projects,executions,bugs,docs,progress,case_review
-1,3,10,产品名称1,产品代号2,0,31,normal,normal,,"<span 
style=""background-color:#FFFFFF;"">产品描述1</span>",1,1,1,private,"devlake,dev1",1,2022-11-17T06:42:25.000+00:00,17.6,15,0,1,0,0,0,0,0,0,0,12.121,0
+connection_id,id,program,name,code,bind,line,type,product_type,status,sub_status,description,po_id,qd_id,rd_id,acl,reviewer,created_by_id,created_date,created_version,order_in,deleted,plans,releases,builds,cases,projects,executions,bugs,docs,progress,case_review
+1,3,10,产品名称1,产品代号2,0,31,product,normal,normal,,"<span 
style=""background-color:#FFFFFF;"">产品描述1</span>",1,1,1,private,"devlake,dev1",1,2022-11-17T06:42:25.000+00:00,17.6,15,0,1,0,0,0,0,0,0,0,12.121,0
diff --git a/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv 
b/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv
index 1da72455a..11a53ea68 100644
--- a/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv
+++ b/backend/plugins/zentao/e2e/snapshot_tables/boards_product.csv
@@ -1,2 +1,2 @@
 id,name,description,url,created_date,type
-zentao:ZentaoProduct:1:3,产品名称1,"<span 
style=""background-color:#FFFFFF;"">产品描述1</span>",,2022-11-17T06:42:25.000+00:00,normal
+zentao:ZentaoProduct:1:3,产品名称1,"<span 
style=""background-color:#FFFFFF;"">产品描述1</span>",,2022-11-17T06:42:25.000+00:00,product/normal
diff --git a/backend/plugins/zentao/impl/impl.go 
b/backend/plugins/zentao/impl/impl.go
index 617bf1fb1..244984330 100644
--- a/backend/plugins/zentao/impl/impl.go
+++ b/backend/plugins/zentao/impl/impl.go
@@ -19,6 +19,7 @@ package impl
 
 import (
        "fmt"
+
        "github.com/apache/incubator-devlake/core/context"
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
diff --git a/backend/plugins/zentao/models/archived/product.go 
b/backend/plugins/zentao/models/archived/product.go
index 3cc4815e1..5cac2a11c 100644
--- a/backend/plugins/zentao/models/archived/product.go
+++ b/backend/plugins/zentao/models/archived/product.go
@@ -23,38 +23,39 @@ import (
 )
 
 type ZentaoProduct struct {
-       ConnectionId   uint64 `gorm:"primaryKey;type:BIGINT  NOT NULL"`
-       Id             int64  `json:"id" gorm:"primaryKey;type:BIGINT  NOT 
NULL"`
-       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"`
-       POId           int64
-       QDId           int64
-       RDId           int64
-       Acl            string `json:"acl"`
-       Reviewer       string `json:"reviewer"`
-       CreatedById    int64
-       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
+       archived.NoPKModel `json:"-"`
+       ConnectionId       uint64 `json:"connectionid" 
mapstructure:"connectionid" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Id                 int64  `json:"id" mapstructure:"id" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Program            int    `json:"program" mapstructure:"program"`
+       Name               string `json:"name" mapstructure:"name"`
+       Code               string `json:"code" mapstructure:"code"`
+       Bind               string `json:"bind" mapstructure:"bind"`
+       Line               int    `json:"line" mapstructure:"line"`
+       Type               string `json:"type" mapstructure:"type"`
+       ProductType        string `json:"productType" 
mapstructure:"productType"`
+       Status             string `json:"status" mapstructure:"status"`
+       SubStatus          string `json:"subStatus" mapstructure:"subStatus"`
+       Description        string `json:"desc" mapstructure:"desc"`
+       POId               int64
+       QDId               int64
+       RDId               int64
+       Acl                string `json:"acl" mapstructure:"acl"`
+       Reviewer           string `json:"reviewer" mapstructure:"reviewer"`
+       CreatedById        int64
+       CreatedDate        *helper.Iso8601Time `json:"createdDate" 
mapstructure:"createdDate"`
+       CreatedVersion     string              `json:"createdVersion" 
mapstructure:"createdVersion"`
+       OrderIn            int                 `json:"order" 
mapstructure:"order"`
+       Deleted            string              `json:"deleted" 
mapstructure:"deleted"`
+       Plans              int                 `json:"plans" 
mapstructure:"plans"`
+       Releases           int                 `json:"releases" 
mapstructure:"releases"`
+       Builds             int                 `json:"builds" 
mapstructure:"builds"`
+       Cases              int                 `json:"cases" 
mapstructure:"cases"`
+       Projects           int                 `json:"projects" 
mapstructure:"projects"`
+       Executions         int                 `json:"executions" 
mapstructure:"executions"`
+       Bugs               int                 `json:"bugs" mapstructure:"bugs"`
+       Docs               int                 `json:"docs" mapstructure:"docs"`
+       Progress           float64             `json:"progress" 
mapstructure:"progress"`
+       CaseReview         bool                `json:"caseReview" 
mapstructure:"caseReview"`
 }
 
 func (ZentaoProduct) TableName() string {
diff --git a/backend/plugins/zentao/models/archived/project.go 
b/backend/plugins/zentao/models/archived/project.go
index 3a8617f77..aaec9cb86 100644
--- a/backend/plugins/zentao/models/archived/project.go
+++ b/backend/plugins/zentao/models/archived/project.go
@@ -18,75 +18,76 @@ limitations under the License.
 package archived
 
 import (
-       
"github.com/apache/incubator-devlake/core/models/migrationscripts/archived"
+       "github.com/apache/incubator-devlake/core/models/common"
        helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
 )
 
 type ZentaoProject struct {
-       archived.NoPKModel
-       ConnectionId  uint64              `gorm:"primaryKey;type:BIGINT  NOT 
NULL"`
-       ID            int64               `json:"id" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
-       Project       int64               `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        int64               `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"`
-       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     *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"`
-       Team           string `json:"team"`
-       Acl            string `json:"acl"`
-       Whitelist      `json:"whitelist" gorm:"-"`
-       OrderIn        int    `json:"order"`
-       Vision         string `json:"vision"`
-       DisplayCards   int    `json:"displayCards"`
-       FluidBoard     string `json:"fluidBoard"`
-       Deleted        bool   `json:"deleted"`
-       Delay          int    `json:"delay"`
-       Hours          `json:"hours"`
-       TeamCount      int    `json:"teamCount"`
-       LeftTasks      string `json:"leftTasks"`
+       common.NoPKModel `json:"-"`
+       ConnectionId     uint64              `json:"connectionid" 
mapstructure:"connectionid" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Id               int64               `json:"id" mapstructure:"id" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Project          int64               `json:"project" 
mapstructure:"project"`
+       Model            string              `json:"model" mapstructure:"model"`
+       Type             string              `json:"type" mapstructure:"type"`
+       ProjectType      string              `json:"projectType" 
mapstructure:"projectType"`
+       Lifetime         string              `json:"lifetime" 
mapstructure:"lifetime"`
+       Budget           string              `json:"budget" 
mapstructure:"budget"`
+       BudgetUnit       string              `json:"budgetUnit" 
mapstructure:"budgetUnit"`
+       Attribute        string              `json:"attribute" 
mapstructure:"attribute"`
+       Percent          int                 `json:"percent" 
mapstructure:"percent"`
+       Milestone        string              `json:"milestone" 
mapstructure:"milestone"`
+       Output           string              `json:"output" 
mapstructure:"output"`
+       Auth             string              `json:"auth" mapstructure:"auth"`
+       Parent           int64               `json:"parent" 
mapstructure:"parent"`
+       Path             string              `json:"path" mapstructure:"path"`
+       Grade            int                 `json:"grade" mapstructure:"grade"`
+       Name             string              `json:"name" mapstructure:"name"`
+       Code             string              `json:"code" mapstructure:"code"`
+       PlanBegin        *helper.Iso8601Time `json:"begin" mapstructure:"begin"`
+       PlanEnd          *helper.Iso8601Time `json:"end" mapstructure:"end"`
+       RealBegan        *helper.Iso8601Time `json:"realBegan" 
mapstructure:"realBegan"`
+       RealEnd          *helper.Iso8601Time `json:"realEnd" 
mapstructure:"realEnd"`
+       Days             int                 `json:"days" mapstructure:"days"`
+       Status           string              `json:"status" 
mapstructure:"status"`
+       SubStatus        string              `json:"subStatus" 
mapstructure:"subStatus"`
+       Pri              string              `json:"pri" mapstructure:"pri"`
+       Description      string              `json:"desc" mapstructure:"desc"`
+       Version          int                 `json:"version" 
mapstructure:"version"`
+       ParentVersion    int                 `json:"parentVersion" 
mapstructure:"parentVersion"`
+       PlanDuration     int                 `json:"planDuration" 
mapstructure:"planDuration"`
+       RealDuration     int                 `json:"realDuration" 
mapstructure:"realDuration"`
+       //OpenedBy       string    `json:"openedBy" mapstructure:"openedBy"`
+       OpenedDate    *helper.Iso8601Time `json:"openedDate" 
mapstructure:"openedDate"`
+       OpenedVersion string              `json:"openedVersion" 
mapstructure:"openedVersion"`
+       //LastEditedBy   string              `json:"lastEditedBy" 
mapstructure:"lastEditedBy"`
+       LastEditedDate *helper.Iso8601Time `json:"lastEditedDate" 
mapstructure:"lastEditedDate"`
+       ClosedBy       string              `json:"closedBy" 
mapstructure:"closedBy"`
+       ClosedDate     *helper.Iso8601Time `json:"closedDate" 
mapstructure:"closedDate"`
+       CanceledBy     string              `json:"canceledBy" 
mapstructure:"canceledBy"`
+       CanceledDate   *helper.Iso8601Time `json:"canceledDate" 
mapstructure:"canceledDate"`
+       SuspendedDate  *helper.Iso8601Time `json:"suspendedDate" 
mapstructure:"suspendedDate"`
+       PO             string              `json:"po" mapstructure:"po"`
+       PM             `json:"pm" mapstructure:"pm"`
+       QD             string `json:"qd" mapstructure:"qd"`
+       RD             string `json:"rd" mapstructure:"rd"`
+       Team           string `json:"team" mapstructure:"team"`
+       Acl            string `json:"acl" mapstructure:"acl"`
+       Whitelist      `json:"whitelist" mapstructure:"" gorm:"-"`
+       OrderIn        int    `json:"order" mapstructure:"order"`
+       Vision         string `json:"vision" mapstructure:"vision"`
+       DisplayCards   int    `json:"displayCards" mapstructure:"displayCards"`
+       FluidBoard     string `json:"fluidBoard" mapstructure:"fluidBoard"`
+       Deleted        bool   `json:"deleted" mapstructure:"deleted"`
+       Delay          int    `json:"delay" mapstructure:"delay"`
+       Hours          `json:"hours" mapstructure:"hours"`
+       TeamCount      int    `json:"teamCount" mapstructure:"teamCount"`
+       LeftTasks      string `json:"leftTasks" mapstructure:"leftTasks"`
        //TeamMembers   []interface{} `json:"teamMembers" gorm:"-"`
-       TotalEstimate float64 `json:"totalEstimate"`
-       TotalConsumed float64 `json:"totalConsumed"`
-       TotalLeft     float64 `json:"totalLeft"`
-       Progress      float64 `json:"progress"`
-       TotalReal     int     `json:"totalReal"`
+       TotalEstimate float64 `json:"totalEstimate" 
mapstructure:"totalEstimate"`
+       TotalConsumed float64 `json:"totalConsumed" 
mapstructure:"totalConsumed"`
+       TotalLeft     float64 `json:"totalLeft" mapstructure:"totalLeft"`
+       Progress      float64 `json:"progress" mapstructure:"progress"`
+       TotalReal     int     `json:"totalReal" mapstructure:"totalReal"`
 }
 type PM struct {
        PmId       int64  `json:"id"`
diff --git 
a/backend/plugins/zentao/models/migrationscripts/20221121_add_init_tables.go 
b/backend/plugins/zentao/models/migrationscripts/20221121_add_init_tables.go
index e02a07de8..0ad604909 100644
--- a/backend/plugins/zentao/models/migrationscripts/20221121_add_init_tables.go
+++ b/backend/plugins/zentao/models/migrationscripts/20221121_add_init_tables.go
@@ -61,7 +61,7 @@ func (*addInitTables) Up(basicRes context.BasicRes) 
errors.Error {
 }
 
 func (*addInitTables) Version() uint64 {
-       return 20230303000001
+       return 20230505000001
 }
 
 func (*addInitTables) Name() string {
diff --git a/backend/plugins/zentao/models/product.go 
b/backend/plugins/zentao/models/product.go
index 5f1ab2af6..c67fdc39e 100644
--- a/backend/plugins/zentao/models/product.go
+++ b/backend/plugins/zentao/models/product.go
@@ -19,53 +19,54 @@ package models
 
 import (
        "fmt"
+
        "github.com/apache/incubator-devlake/core/models/common"
        "github.com/apache/incubator-devlake/core/plugin"
        helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
 )
 
 type ZentaoProductRes struct {
-       ID             int64               `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"`
+       ID             int64               `json:"id" mapstructure:"id"`
+       Program        int                 `json:"program" 
mapstructure:"program"`
+       Name           string              `json:"name" mapstructure:"name"`
+       Code           string              `json:"code" mapstructure:"code"`
+       Bind           string              `json:"bind" mapstructure:"bind"`
+       Line           int                 `json:"line" mapstructure:"line"`
+       Type           string              `json:"type" mapstructure:"type"`
+       Status         string              `json:"status" mapstructure:"status"`
+       SubStatus      string              `json:"subStatus" 
mapstructure:"subStatus"`
+       Description    string              `json:"desc" mapstructure:"desc"`
+       PO             *ZentaoAccount      `json:"po" mapstructure:"po"`
+       QD             *ZentaoAccount      `json:"qd" mapstructure:"qd"`
+       RD             *ZentaoAccount      `json:"rd" mapstructure:"rd"`
+       Feedback       interface{}         `json:"feedback" 
mapstructure:"feedback"`
+       Acl            string              `json:"acl" mapstructure:"acl"`
+       Whitelist      []interface{}       `json:"whitelist" 
mapstructure:"whitelist"`
+       Reviewer       string              `json:"reviewer" 
mapstructure:"reviewer"`
+       CreatedBy      *ZentaoAccount      `json:"createdBy" 
mapstructure:"createdBy"`
+       CreatedDate    *helper.Iso8601Time `json:"createdDate" 
mapstructure:"createdDate"`
+       CreatedVersion string              `json:"createdVersion" 
mapstructure:"createdVersion"`
+       OrderIn        int                 `json:"order" mapstructure:"order"`
+       Vision         string              `json:"vision" mapstructure:"vision"`
+       Deleted        string              `json:"deleted" 
mapstructure:"deleted"`
        Stories        struct {
-               Active    int `json:"active"`
-               Reviewing int `json:"reviewing"`
+               Active    int `json:"active" mapstructure:"active"`
+               Reviewing int `json:"reviewing" mapstructure:"reviewing"`
                int       `json:""`
-               Draft     int `json:"draft"`
-               Closed    int `json:"closed"`
-               Changing  int `json:"changing"`
+               Draft     int `json:"draft" mapstructure:"draft"`
+               Closed    int `json:"closed" mapstructure:"closed"`
+               Changing  int `json:"changing" mapstructure:"changing"`
        } `json:"stories"`
-       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"`
+       Plans      int     `json:"plans" mapstructure:"plans"`
+       Releases   int     `json:"releases" mapstructure:"releases"`
+       Builds     int     `json:"builds" mapstructure:"builds"`
+       Cases      int     `json:"cases" mapstructure:"cases"`
+       Projects   int     `json:"projects" mapstructure:"projects"`
+       Executions int     `json:"executions" mapstructure:"executions"`
+       Bugs       int     `json:"bugs" mapstructure:"bugs"`
+       Docs       int     `json:"docs" mapstructure:"docs"`
+       Progress   float64 `json:"progress" mapstructure:"progress"`
+       CaseReview bool    `json:"caseReview" mapstructure:"caseReview"`
 }
 
 func getAccountId(account *ZentaoAccount) int64 {
@@ -83,7 +84,8 @@ func (res ZentaoProductRes) ConvertApiScope() 
plugin.ToolLayerScope {
                Code:           res.Code,
                Bind:           res.Bind,
                Line:           res.Line,
-               Type:           `product/` + res.Type,
+               Type:           `product`,
+               ProductType:    res.Type,
                Status:         res.Status,
                SubStatus:      res.SubStatus,
                Description:    res.Description,
@@ -112,37 +114,38 @@ func (res ZentaoProductRes) ConvertApiScope() 
plugin.ToolLayerScope {
 
 type ZentaoProduct struct {
        common.NoPKModel `json:"-"`
-       ConnectionId     uint64 `json:"connectionid" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
-       Id               int64  `json:"id" gorm:"primaryKey;type:BIGINT  NOT 
NULL"`
-       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"`
+       ConnectionId     uint64 `json:"connectionid" 
mapstructure:"connectionid" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Id               int64  `json:"id" mapstructure:"id" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Program          int    `json:"program" mapstructure:"program"`
+       Name             string `json:"name" mapstructure:"name"`
+       Code             string `json:"code" mapstructure:"code"`
+       Bind             string `json:"bind" mapstructure:"bind"`
+       Line             int    `json:"line" mapstructure:"line"`
+       Type             string `json:"type" mapstructure:"type"`
+       ProductType      string `json:"productType" mapstructure:"productType"`
+       Status           string `json:"status" mapstructure:"status"`
+       SubStatus        string `json:"subStatus" mapstructure:"subStatus"`
+       Description      string `json:"desc" mapstructure:"desc"`
        POId             int64
        QDId             int64
        RDId             int64
-       Acl              string `json:"acl"`
-       Reviewer         string `json:"reviewer"`
+       Acl              string `json:"acl" mapstructure:"acl"`
+       Reviewer         string `json:"reviewer" mapstructure:"reviewer"`
        CreatedById      int64
-       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"`
+       CreatedDate      *helper.Iso8601Time `json:"createdDate" 
mapstructure:"createdDate"`
+       CreatedVersion   string              `json:"createdVersion" 
mapstructure:"createdVersion"`
+       OrderIn          int                 `json:"order" mapstructure:"order"`
+       Deleted          string              `json:"deleted" 
mapstructure:"deleted"`
+       Plans            int                 `json:"plans" mapstructure:"plans"`
+       Releases         int                 `json:"releases" 
mapstructure:"releases"`
+       Builds           int                 `json:"builds" 
mapstructure:"builds"`
+       Cases            int                 `json:"cases" mapstructure:"cases"`
+       Projects         int                 `json:"projects" 
mapstructure:"projects"`
+       Executions       int                 `json:"executions" 
mapstructure:"executions"`
+       Bugs             int                 `json:"bugs" mapstructure:"bugs"`
+       Docs             int                 `json:"docs" mapstructure:"docs"`
+       Progress         float64             `json:"progress" 
mapstructure:"progress"`
+       CaseReview       bool                `json:"caseReview" 
mapstructure:"caseReview"`
 }
 
 func (ZentaoProduct) TableName() string {
diff --git a/backend/plugins/zentao/models/project.go 
b/backend/plugins/zentao/models/project.go
index 0c4d3821f..827c53f57 100644
--- a/backend/plugins/zentao/models/project.go
+++ b/backend/plugins/zentao/models/project.go
@@ -19,6 +19,7 @@ package models
 
 import (
        "fmt"
+
        "github.com/apache/incubator-devlake/core/models/common"
        "github.com/apache/incubator-devlake/core/plugin"
        helper "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -26,88 +27,89 @@ import (
 
 type ZentaoProject struct {
        common.NoPKModel `json:"-"`
-       ConnectionId     uint64              `json:"connectionid" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
-       Id               int64               `json:"id" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
-       Project          int64               `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           int64               `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"`
-       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    *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"`
-       Team           string `json:"team"`
-       Acl            string `json:"acl"`
-       Whitelist      `json:"whitelist" gorm:"-"`
-       OrderIn        int    `json:"order"`
-       Vision         string `json:"vision"`
-       DisplayCards   int    `json:"displayCards"`
-       FluidBoard     string `json:"fluidBoard"`
-       Deleted        bool   `json:"deleted"`
-       Delay          int    `json:"delay"`
-       Hours          `json:"hours"`
-       TeamCount      int    `json:"teamCount"`
-       LeftTasks      string `json:"leftTasks"`
+       ConnectionId     uint64              `json:"connectionid" 
mapstructure:"connectionid" gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Id               int64               `json:"id" mapstructure:"id" 
gorm:"primaryKey;type:BIGINT  NOT NULL"`
+       Project          int64               `json:"project" 
mapstructure:"project"`
+       Model            string              `json:"model" mapstructure:"model"`
+       Type             string              `json:"type" mapstructure:"type"`
+       ProjectType      string              `json:"projectType" 
mapstructure:"projectType"`
+       Lifetime         string              `json:"lifetime" 
mapstructure:"lifetime"`
+       Budget           string              `json:"budget" 
mapstructure:"budget"`
+       BudgetUnit       string              `json:"budgetUnit" 
mapstructure:"budgetUnit"`
+       Attribute        string              `json:"attribute" 
mapstructure:"attribute"`
+       Percent          int                 `json:"percent" 
mapstructure:"percent"`
+       Milestone        string              `json:"milestone" 
mapstructure:"milestone"`
+       Output           string              `json:"output" 
mapstructure:"output"`
+       Auth             string              `json:"auth" mapstructure:"auth"`
+       Parent           int64               `json:"parent" 
mapstructure:"parent"`
+       Path             string              `json:"path" mapstructure:"path"`
+       Grade            int                 `json:"grade" mapstructure:"grade"`
+       Name             string              `json:"name" mapstructure:"name"`
+       Code             string              `json:"code" mapstructure:"code"`
+       PlanBegin        *helper.Iso8601Time `json:"begin" mapstructure:"begin"`
+       PlanEnd          *helper.Iso8601Time `json:"end" mapstructure:"end"`
+       RealBegan        *helper.Iso8601Time `json:"realBegan" 
mapstructure:"realBegan"`
+       RealEnd          *helper.Iso8601Time `json:"realEnd" 
mapstructure:"realEnd"`
+       Days             int                 `json:"days" mapstructure:"days"`
+       Status           string              `json:"status" 
mapstructure:"status"`
+       SubStatus        string              `json:"subStatus" 
mapstructure:"subStatus"`
+       Pri              string              `json:"pri" mapstructure:"pri"`
+       Description      string              `json:"desc" mapstructure:"desc"`
+       Version          int                 `json:"version" 
mapstructure:"version"`
+       ParentVersion    int                 `json:"parentVersion" 
mapstructure:"parentVersion"`
+       PlanDuration     int                 `json:"planDuration" 
mapstructure:"planDuration"`
+       RealDuration     int                 `json:"realDuration" 
mapstructure:"realDuration"`
+       //OpenedBy       string    `json:"openedBy" mapstructure:"openedBy"`
+       OpenedDate    *helper.Iso8601Time `json:"openedDate" 
mapstructure:"openedDate"`
+       OpenedVersion string              `json:"openedVersion" 
mapstructure:"openedVersion"`
+       //LastEditedBy   string              `json:"lastEditedBy" 
mapstructure:"lastEditedBy"`
+       LastEditedDate *helper.Iso8601Time `json:"lastEditedDate" 
mapstructure:"lastEditedDate"`
+       ClosedBy       string              `json:"closedBy" 
mapstructure:"closedBy"`
+       ClosedDate     *helper.Iso8601Time `json:"closedDate" 
mapstructure:"closedDate"`
+       CanceledBy     string              `json:"canceledBy" 
mapstructure:"canceledBy"`
+       CanceledDate   *helper.Iso8601Time `json:"canceledDate" 
mapstructure:"canceledDate"`
+       SuspendedDate  *helper.Iso8601Time `json:"suspendedDate" 
mapstructure:"suspendedDate"`
+       PO             string              `json:"po" mapstructure:"po"`
+       PM             `json:"pm" mapstructure:"pm"`
+       QD             string `json:"qd" mapstructure:"qd"`
+       RD             string `json:"rd" mapstructure:"rd"`
+       Team           string `json:"team" mapstructure:"team"`
+       Acl            string `json:"acl" mapstructure:"acl"`
+       Whitelist      `json:"whitelist" mapstructure:"" gorm:"-"`
+       OrderIn        int    `json:"order" mapstructure:"order"`
+       Vision         string `json:"vision" mapstructure:"vision"`
+       DisplayCards   int    `json:"displayCards" mapstructure:"displayCards"`
+       FluidBoard     string `json:"fluidBoard" mapstructure:"fluidBoard"`
+       Deleted        bool   `json:"deleted" mapstructure:"deleted"`
+       Delay          int    `json:"delay" mapstructure:"delay"`
+       Hours          `json:"hours" mapstructure:"hours"`
+       TeamCount      int    `json:"teamCount" mapstructure:"teamCount"`
+       LeftTasks      string `json:"leftTasks" mapstructure:"leftTasks"`
        //TeamMembers   []interface{} `json:"teamMembers" gorm:"-"`
-       TotalEstimate float64 `json:"totalEstimate"`
-       TotalConsumed float64 `json:"totalConsumed"`
-       TotalLeft     float64 `json:"totalLeft"`
-       Progress      float64 `json:"progress"`
-       TotalReal     int     `json:"totalReal"`
+       TotalEstimate float64 `json:"totalEstimate" 
mapstructure:"totalEstimate"`
+       TotalConsumed float64 `json:"totalConsumed" 
mapstructure:"totalConsumed"`
+       TotalLeft     float64 `json:"totalLeft" mapstructure:"totalLeft"`
+       Progress      float64 `json:"progress" mapstructure:"progress"`
+       TotalReal     int     `json:"totalReal" mapstructure:"totalReal"`
 }
 type PM struct {
-       PmId       int64  `json:"id"`
-       PmAccount  string `json:"account"`
-       PmAvatar   string `json:"avatar"`
-       PmRealname string `json:"realname"`
+       PmId       int64  `json:"id" mapstructure:"id"`
+       PmAccount  string `json:"account" mapstructure:"account"`
+       PmAvatar   string `json:"avatar" mapstructure:"avatar"`
+       PmRealname string `json:"realname" mapstructure:"realname"`
 }
 type Whitelist []struct {
-       WhitelistID       int64  `json:"id"`
-       WhitelistAccount  string `json:"account"`
-       WhitelistAvatar   string `json:"avatar"`
-       WhitelistRealname string `json:"realname"`
+       WhitelistID       int64  `json:"id" mapstructure:"id"`
+       WhitelistAccount  string `json:"account" mapstructure:"account"`
+       WhitelistAvatar   string `json:"avatar" mapstructure:"avatar"`
+       WhitelistRealname string `json:"realname" mapstructure:"realname"`
 }
 type Hours struct {
-       HoursTotalEstimate float64 `json:"totalEstimate"`
-       HoursTotalConsumed float64 `json:"totalConsumed"`
-       HoursTotalLeft     float64 `json:"totalLeft"`
-       HoursProgress      float64 `json:"progress"`
-       HoursTotalReal     float64 `json:"totalReal"`
+       HoursTotalEstimate float64 `json:"totalEstimate" 
mapstructure:"totalEstimate"`
+       HoursTotalConsumed float64 `json:"totalConsumed" 
mapstructure:"totalConsumed"`
+       HoursTotalLeft     float64 `json:"totalLeft" mapstructure:"totalLeft"`
+       HoursProgress      float64 `json:"progress" mapstructure:"progress"`
+       HoursTotalReal     float64 `json:"totalReal" mapstructure:"totalReal"`
 }
 
 func (ZentaoProject) TableName() string {
@@ -123,5 +125,9 @@ func (p ZentaoProject) ScopeName() string {
 }
 
 func (p ZentaoProject) ConvertApiScope() plugin.ToolLayerScope {
+       if p.ProjectType == "" {
+               p.ProjectType = p.Type
+               p.Type = "project"
+       }
        return p
 }
diff --git a/backend/plugins/zentao/tasks/bug_collector.go 
b/backend/plugins/zentao/tasks/bug_collector.go
index 91758442b..16ffda670 100644
--- a/backend/plugins/zentao/tasks/bug_collector.go
+++ b/backend/plugins/zentao/tasks/bug_collector.go
@@ -20,11 +20,12 @@ package tasks
 import (
        "encoding/json"
        "fmt"
+       "net/http"
+       "net/url"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
-       "net/http"
-       "net/url"
 )
 
 const RAW_BUG_TABLE = "zentao_api_bugs"
@@ -33,9 +34,12 @@ var _ plugin.SubTaskEntryPoint = CollectBug
 
 func CollectBug(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this collect only work for product
        if data.Options.ProductId == 0 {
                return nil
        }
+
        collector, err := api.NewApiCollector(api.ApiCollectorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
diff --git a/backend/plugins/zentao/tasks/bug_extractor.go 
b/backend/plugins/zentao/tasks/bug_extractor.go
index 9855d843e..eff39b734 100644
--- a/backend/plugins/zentao/tasks/bug_extractor.go
+++ b/backend/plugins/zentao/tasks/bug_extractor.go
@@ -19,6 +19,7 @@ package tasks
 
 import (
        "encoding/json"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -37,6 +38,12 @@ var ExtractBugMeta = plugin.SubTaskMeta{
 
 func ExtractBug(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this Extract only work for product
+       if data.Options.ProductId == 0 {
+               return nil
+       }
+
        extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
diff --git a/backend/plugins/zentao/tasks/execution_collector.go 
b/backend/plugins/zentao/tasks/execution_collector.go
index 1218f7fb3..be083083e 100644
--- a/backend/plugins/zentao/tasks/execution_collector.go
+++ b/backend/plugins/zentao/tasks/execution_collector.go
@@ -20,22 +20,26 @@ package tasks
 import (
        "encoding/json"
        "fmt"
+       "net/http"
+       "net/url"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
-       "net/http"
-       "net/url"
 )
 
 const RAW_EXECUTION_TABLE = "zentao_api_executions"
 
-var _ plugin.SubTaskEntryPoint = CollectExecution
+var _ plugin.SubTaskEntryPoint = CollectExecutions
 
-func CollectExecution(taskCtx plugin.SubTaskContext) errors.Error {
+func CollectExecutions(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this collect only work for project
        if data.Options.ProjectId == 0 {
                return nil
        }
+
        collector, err := api.NewApiCollector(api.ApiCollectorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
@@ -73,8 +77,8 @@ func CollectExecution(taskCtx plugin.SubTaskContext) 
errors.Error {
 }
 
 var CollectExecutionMeta = plugin.SubTaskMeta{
-       Name:             "CollectExecution",
-       EntryPoint:       CollectExecution,
+       Name:             "collectExecutions",
+       EntryPoint:       CollectExecutions,
        EnabledByDefault: true,
        Description:      "Collect Execution data from Zentao api",
        DomainTypes:      []string{plugin.DOMAIN_TYPE_TICKET},
diff --git a/backend/plugins/zentao/tasks/execution_extractor.go 
b/backend/plugins/zentao/tasks/execution_extractor.go
index f8efa2699..a891866d7 100644
--- a/backend/plugins/zentao/tasks/execution_extractor.go
+++ b/backend/plugins/zentao/tasks/execution_extractor.go
@@ -19,6 +19,7 @@ package tasks
 
 import (
        "encoding/json"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -37,6 +38,12 @@ var ExtractExecutionMeta = plugin.SubTaskMeta{
 
 func ExtractExecutions(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this Extract only work for project
+       if data.Options.ProjectId == 0 {
+               return nil
+       }
+
        extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
diff --git a/backend/plugins/zentao/tasks/product_convertor.go 
b/backend/plugins/zentao/tasks/product_convertor.go
index 31f64032c..3ddfe4bd7 100644
--- a/backend/plugins/zentao/tasks/product_convertor.go
+++ b/backend/plugins/zentao/tasks/product_convertor.go
@@ -18,6 +18,8 @@ limitations under the License.
 package tasks
 
 import (
+       "reflect"
+
        "github.com/apache/incubator-devlake/core/dal"
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/models/domainlayer"
@@ -26,7 +28,6 @@ import (
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
        "github.com/apache/incubator-devlake/plugins/zentao/models"
-       "reflect"
 )
 
 const RAW_PRODUCT_TABLE = "zentao_api_products"
@@ -75,7 +76,7 @@ func ConvertProducts(taskCtx plugin.SubTaskContext) 
errors.Error {
                                Name:        toolProduct.Name,
                                Description: toolProduct.Description,
                                CreatedDate: 
toolProduct.CreatedDate.ToNullableTime(),
-                               Type:        toolProduct.Type,
+                               Type:        toolProduct.Type + "/" + 
toolProduct.ProductType,
                        }
                        results := make([]interface{}, 0)
                        results = append(results, domainBoard)
diff --git a/backend/plugins/zentao/tasks/project_convertor.go 
b/backend/plugins/zentao/tasks/project_convertor.go
index 3c2d146ee..8bb555372 100644
--- a/backend/plugins/zentao/tasks/project_convertor.go
+++ b/backend/plugins/zentao/tasks/project_convertor.go
@@ -18,6 +18,8 @@ limitations under the License.
 package tasks
 
 import (
+       "reflect"
+
        "github.com/apache/incubator-devlake/core/dal"
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/models/domainlayer"
@@ -26,7 +28,6 @@ import (
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
        "github.com/apache/incubator-devlake/plugins/zentao/models"
-       "reflect"
 )
 
 const RAW_PROJECT_TABLE = "zentao_api_projects"
@@ -75,7 +76,7 @@ func ConvertProjects(taskCtx plugin.SubTaskContext) 
errors.Error {
                                Name:        toolProject.Name,
                                Description: toolProject.Description,
                                CreatedDate: 
toolProject.OpenedDate.ToNullableTime(),
-                               Type:        toolProject.Type,
+                               Type:        toolProject.Type + "/" + 
toolProject.ProjectType,
                        }
                        results := make([]interface{}, 0)
                        results = append(results, domainBoard)
diff --git a/backend/plugins/zentao/tasks/story_collector.go 
b/backend/plugins/zentao/tasks/story_collector.go
index 2d9d16617..9da194064 100644
--- a/backend/plugins/zentao/tasks/story_collector.go
+++ b/backend/plugins/zentao/tasks/story_collector.go
@@ -20,11 +20,12 @@ package tasks
 import (
        "encoding/json"
        "fmt"
+       "net/http"
+       "net/url"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
-       "net/http"
-       "net/url"
 )
 
 const RAW_STORY_TABLE = "zentao_api_stories"
@@ -33,9 +34,12 @@ var _ plugin.SubTaskEntryPoint = CollectStory
 
 func CollectStory(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this collect only work for product
        if data.Options.ProductId == 0 {
                return nil
        }
+
        collector, err := api.NewApiCollector(api.ApiCollectorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
diff --git a/backend/plugins/zentao/tasks/story_extractor.go 
b/backend/plugins/zentao/tasks/story_extractor.go
index e014701d2..e4e633fb5 100644
--- a/backend/plugins/zentao/tasks/story_extractor.go
+++ b/backend/plugins/zentao/tasks/story_extractor.go
@@ -19,6 +19,7 @@ package tasks
 
 import (
        "encoding/json"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -37,6 +38,12 @@ var ExtractStoryMeta = plugin.SubTaskMeta{
 
 func ExtractStory(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this collect only work for product
+       if data.Options.ProductId == 0 {
+               return nil
+       }
+
        extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,
diff --git a/backend/plugins/zentao/tasks/task_collector.go 
b/backend/plugins/zentao/tasks/task_collector.go
index 0547b8a9b..427569c11 100644
--- a/backend/plugins/zentao/tasks/task_collector.go
+++ b/backend/plugins/zentao/tasks/task_collector.go
@@ -20,14 +20,15 @@ package tasks
 import (
        "encoding/json"
        "fmt"
+       "net/http"
+       "net/url"
+       "reflect"
+
        "github.com/apache/incubator-devlake/core/dal"
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
        "github.com/apache/incubator-devlake/plugins/zentao/models"
-       "net/http"
-       "net/url"
-       "reflect"
 )
 
 const RAW_TASK_TABLE = "zentao_api_tasks"
@@ -40,9 +41,12 @@ var _ plugin.SubTaskEntryPoint = CollectTask
 
 func CollectTask(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this collect only work for project
        if data.Options.ProjectId == 0 {
                return nil
        }
+
        cursor, err := taskCtx.GetDal().Cursor(
                dal.Select(`id`),
                dal.From(&models.ZentaoExecution{}),
diff --git a/backend/plugins/zentao/tasks/task_extractor.go 
b/backend/plugins/zentao/tasks/task_extractor.go
index 46988d769..7d6efc18a 100644
--- a/backend/plugins/zentao/tasks/task_extractor.go
+++ b/backend/plugins/zentao/tasks/task_extractor.go
@@ -19,6 +19,7 @@ package tasks
 
 import (
        "encoding/json"
+
        "github.com/apache/incubator-devlake/core/errors"
        "github.com/apache/incubator-devlake/core/plugin"
        "github.com/apache/incubator-devlake/helpers/pluginhelper/api"
@@ -37,6 +38,12 @@ var ExtractTaskMeta = plugin.SubTaskMeta{
 
 func ExtractTask(taskCtx plugin.SubTaskContext) errors.Error {
        data := taskCtx.GetData().(*ZentaoTaskData)
+
+       // this collect only work for project
+       if data.Options.ProjectId == 0 {
+               return nil
+       }
+
        extractor, err := api.NewApiExtractor(api.ApiExtractorArgs{
                RawDataSubTaskArgs: api.RawDataSubTaskArgs{
                        Ctx: taskCtx,

Reply via email to