Skip to content

Commit

Permalink
+ [stories] add stories api
Browse files Browse the repository at this point in the history
Signed-off-by: ysicing <[email protected]>
  • Loading branch information
ysicing committed Sep 19, 2024
1 parent 0a06b99 commit b96d97e
Show file tree
Hide file tree
Showing 4 changed files with 277 additions and 61 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,20 @@ Zentao API client enabling Go programs to interact with Zentao in a simple and u
- [x] 获取产品发布列表
- [x] 需求(Stories)
- [x] 获取项目需求列表
- [x] 变更需求
- [x] 获取产品需求列表
- [x] 创建需求
- [x] 获取执行需求列表
- [x] 变更需求
- [x] 创建需求
- [x] 获取需求详情
- [x] 删除需求
- [x] 修改需求其他字段
- [x] 激活需求
- [x] 关闭需求
- [x] 指派需求
- [ ] 预估工时
- [ ] 子需求
- [ ] 撤回评审
- [ ] 评审需求
- [x] 项目(Projects)
- [x] 创建项目
- [x] 获取项目列表
Expand Down
74 changes: 67 additions & 7 deletions example/stories/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"log"

"github.com/easysoft/go-zentao/v20/zentao"

"github.com/davecgh/go-spew/spew"
)

func main() {
Expand All @@ -32,16 +34,74 @@ func main() {
zentao.WithoutProxy(),
)
if err != nil {
log.Fatal(err)
panic(err)
}
p1, _, err := zt.Stories.ProductsList(1)
if err != nil {
panic(err)
}
log.Printf("product 1 stories count: %v", len(p1.Stories))
p2, _, err := zt.Stories.ProjectsList(2)
if err != nil {
panic(err)
}
log.Printf("product 1 stories count: %v", len(p2.Stories))
createMsg := zentao.StoriesCreateMeta{
Product: 1,
}
createMsg.Title = "test story"
createMsg.Pri = 1
createMsg.Category = zentao.CategoryFeature
createMsg.Spec = "test spec"
// 可选
createMsg.Verify = "test verify"
p3, _, err := zt.Stories.Create(createMsg)
if err != nil {
panic(err)
}
log.Printf("created story id: %v", p3.ID)
p4, _, err := zt.Stories.UpdateByID(p3.ID, zentao.StoriesMeta{
Title: "test story updated",
})
if err != nil {
panic(err)
}
log.Printf("updated story id: %v", p4.ID)
uptateMsg := zentao.StoriesUpdateFieldMeta{}
uptateMsg.Category = zentao.CategoryOther
uptateMsg.Reviewer = []string{"dev1"}
p5, _, err := zt.Stories.UpdateFieldByID(p4.ID, uptateMsg)
if err != nil {
panic(err)
}
log.Printf("updated story filed id: %v", p5.ID)
p6, _, err := zt.Stories.GetByID(p4.ID)
if err != nil {
panic(err)
}
spew.Dump(p6)
p7, _, err := zt.Stories.CloseByID(p6.ID, zentao.StoriesClose{
Closedreason: zentao.CloseReasonBydesign,
Comment: "test close",
})
if err != nil {
panic(err)
}
pds, _, err := zt.Products.List()
log.Printf("close story id: %v", p7.ID)
p8, _, err := zt.Stories.ActiveByID(p7.ID, zentao.StoriesActive{
Comment: "test active",
AssignedTo: "dev1",
})
if err != nil {
log.Fatal(err)
panic(err)
}
log.Printf("Products count: %v", len(pds.Products))
pgs, _, err := zt.Programs.List("")
log.Printf("active story id: %v", p8.ID)
p9, _, err := zt.Stories.AssignByID(p8.ID, zentao.StoriesActive{
Comment: "test assign",
AssignedTo: "dev2",
})
if err != nil {
log.Fatal(err)
panic(err)
}
log.Printf("Programs count: %v", len(pgs.Programs))
log.Printf("assign story id: %v", p9.ID)
}
197 changes: 145 additions & 52 deletions zentao/stories.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,50 +40,55 @@ type StoriesMeta struct {
}

type StoriesExtMeta struct {
Source string `json:"source,omitempty"`
SourceNote string `json:"sourceNote,omitempty"`
Pri int `json:"pri,omitempty"`
Category string `json:"category,omitempty"`
Estimate float64 `json:"estimate,omitempty"`
Keywords string `json:"keywords,omitempty"`
Source StoriesSource `json:"source,omitempty"`
SourceNote string `json:"sourceNote,omitempty"` // 来源备注
Pri int `json:"pri,omitempty"`
Category StoriesCategory `json:"category,omitempty"`
Estimate float64 `json:"estimate,omitempty"` // 预估工时
Keywords string `json:"keywords,omitempty"`
Parent any `json:"parent,omitempty"` // 可能是数组, 产品计划时是数组
Reviewer []string `json:"reviewer,omitempty"`
}

type StoriesBody struct {
StoriesExtMeta
ID int `json:"id"`
Parent any `json:"parent"` // 可能是数组, 产品计划时是数组
Product int `json:"product"`
Branch int `json:"branch"`
Module int `json:"module"`
Plan string `json:"plan"`
Frombug int `json:"fromBug"`
Title string `json:"title"`
Type string `json:"type"`
Status string `json:"status"`
Substatus string `json:"subStatus"`
Color string `json:"color"`
Stage string `json:"stage"`
Stagedby string `json:"stagedBy"`
Mailto string `json:"mailto"`
Openedby any `json:"openedBy"` // 产品计划是string, 其他可能是UserMeta
Openeddate string `json:"openedDate"`
Assignedto string `json:"assignedTo"`
Assigneddate any `json:"assignedDate"`
Lasteditedby string `json:"lastEditedBy"`
Lastediteddate string `json:"lastEditedDate"`
Reviewedby string `json:"reviewedBy"`
Revieweddate any `json:"reviewedDate"`
Closedby string `json:"closedBy"`
Closeddate any `json:"closedDate"`
Closedreason string `json:"closedReason"`
Tobug int `json:"toBug"`
Childstories string `json:"childStories"`
Linkstories string `json:"linkStories"`
Duplicatestory int `json:"duplicateStory"`
Version int `json:"version"`
Urchanged string `json:"URChanged"`
Deleted string `json:"deleted"`
Plantitle string `json:"planTitle,omitempty"`
ID int `json:"id"`
Product int `json:"product"`
Project int `json:"project,omitempty"`
Branch int `json:"branch"`
Module int `json:"module"`
Plan string `json:"plan"`
Frombug int `json:"fromBug"`
Title string `json:"title"`
Type string `json:"type"`
Status StoriesStatus `json:"status"`
Substatus string `json:"subStatus"`
Color string `json:"color"`
Stage StoriesStage `json:"stage"`
Stagedby any `json:"stagedBy"`
Mailto any `json:"mailto"` // 概率数组
Openedby any `json:"openedBy"` // 产品计划是string, 其他可能是UserMeta
Openeddate string `json:"openedDate"`
Assignedto any `json:"assignedTo"`
Assigneddate string `json:"assignedDate"`
Lasteditedby any `json:"lastEditedBy"`
Lastediteddate string `json:"lastEditedDate"`
Reviewedby any `json:"reviewedBy"`
Revieweddate string `json:"reviewedDate"`
Closedby any `json:"closedBy"`
Closeddate string `json:"closedDate"`
Closedreason string `json:"closedReason"`
Tobug int `json:"toBug"`
Childstories string `json:"childStories"`
Linkstories string `json:"linkStories"`
Duplicatestory int `json:"duplicateStory"`
Version int `json:"version"`
Urchanged string `json:"URChanged"`
Deleted any `json:"deleted"` // 需求返回时是bool, 产品计划是string
Plantitle string `json:"planTitle,omitempty"`
NotReview []string `json:"notReview,omitempty"`
NeedSummaryEstimate bool `json:"needSummaryEstimate,omitempty"`
ProductStatus string `json:"productStatus,omitempty"`
}

type StoriesCreateMeta struct {
Expand All @@ -104,7 +109,18 @@ type StoriesMsg struct {
Executions []interface{} `json:"executions"`
Tasks []interface{} `json:"tasks"`
Stages []interface{} `json:"stages"`
Children []interface{} `json:"children"`
Children []interface{} `json:"children,omitempty"`
}

type StoriesClose struct {
Closedreason StoriesCloseReason `json:"closedReason,omitempty"`
Duplicatestory int `json:"duplicateStory,omitempty"`
Comment string `json:"comment,omitempty"`
}

type StoriesActive struct {
AssignedTo string `json:"assignedTo,omitempty"`
Comment string `json:"comment,omitempty"`
}

// ProjectsList 获取项目需求列表
Expand Down Expand Up @@ -148,17 +164,6 @@ func (s *StoriesService) DeleteByID(id int) (*CustomResp, *req.Response, error)
return &u, resp, err
}

// UpdateByID 变更需求
func (s *StoriesService) UpdateByID(id int, story StoriesMeta) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/change", id)))
return &u, resp, err
}

// GetByID 获取需求详情
func (s *StoriesService) GetByID(id int) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
Expand Down Expand Up @@ -189,3 +194,91 @@ func (s *StoriesService) UpdateFieldByID(id int, uf StoriesUpdateFieldMeta) (*St
Put(s.client.RequestURL(fmt.Sprintf("/stories/%d", id)))
return &u, resp, err
}

// UpdateByID 变更需求
func (s *StoriesService) UpdateByID(id int, story StoriesMeta) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/change", id)))
return &u, resp, err
}

// CloseByID 关闭需求
func (s *StoriesService) CloseByID(id int, story StoriesClose) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/close", id)))
return &u, resp, err
}

// ActiveByID 激活需求
func (s *StoriesService) ActiveByID(id int, story StoriesActive) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/active", id)))
return &u, resp, err
}

// AssignByID 指派需求
func (s *StoriesService) AssignByID(id int, story StoriesActive) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/assign", id)))
return &u, resp, err
}

// EstimateByID 预估工时
func (s *StoriesService) EstimateByID(id int, story StoriesMeta) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/estimate", id)))
return &u, resp, err
}

// ChildByID 子需求
func (s *StoriesService) ChildByID(id int, story StoriesMeta) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/child", id)))
return &u, resp, err
}

// RecallByID 撤回评审
func (s *StoriesService) RecallByID(id int, story StoriesMeta) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/recall", id)))
return &u, resp, err
}

// ReviewByID 审核需求
func (s *StoriesService) ReviewByID(id int, story StoriesMeta) (*StoriesMsg, *req.Response, error) {
var u StoriesMsg
resp, err := s.client.client.R().
SetHeader("Token", s.client.token).
SetBody(&story).
SetSuccessResult(&u).
Post(s.client.RequestURL(fmt.Sprintf("/stories/%d/review", id)))
return &u, resp, err
}
Loading

0 comments on commit b96d97e

Please sign in to comment.