blob: 5621bbe48b8800713be1b1d30c0eea87999494aa [file] [log] [blame]
package v8models
import (
"encoding/json"
"github.com/merico-dev/lake/plugins/core"
"github.com/merico-dev/lake/plugins/jira/models"
)
type Issue struct {
Expand string `json:"expand"`
ID uint64 `json:"id,string"`
Self string `json:"self"`
Key string `json:"key"`
Fields struct {
AllFields map[string]interface{}
Issuetype struct {
Self string `json:"self"`
ID string `json:"id"`
Description string `json:"description"`
IconURL string `json:"iconUrl"`
Name string `json:"name"`
Subtask bool `json:"subtask"`
AvatarID int `json:"avatarId"`
} `json:"issuetype"`
Parent *struct {
ID uint64 `json:"id,string"`
Key string `json:"key"`
} `json:"parent"`
Timespent interface{} `json:"timespent"`
Sprint *Sprint `json:"sprint"`
ClosedSprints []Sprint `json:"closedSprints"`
Project struct {
Self string `json:"self"`
ID uint64 `json:"id,string"`
Key string `json:"key"`
Name string `json:"name"`
ProjectTypeKey string `json:"projectTypeKey"`
AvatarUrls struct {
Four8X48 string `json:"48x48"`
Two4X24 string `json:"24x24"`
One6X16 string `json:"16x16"`
Three2X32 string `json:"32x32"`
} `json:"avatarUrls"`
} `json:"project"`
FixVersions []interface{} `json:"fixVersions"`
Aggregatetimespent interface{} `json:"aggregatetimespent"`
Resolution interface{} `json:"resolution"`
Resolutiondate *core.Iso8601Time `json:"resolutiondate"`
Workratio int `json:"workratio"`
LastViewed string `json:"lastViewed"`
Watches struct {
Self string `json:"self"`
WatchCount int `json:"watchCount"`
IsWatching bool `json:"isWatching"`
} `json:"watches"`
Created core.Iso8601Time `json:"created"`
Epic *struct {
ID int `json:"id"`
Key string `json:"key"`
Self string `json:"self"`
Name string `json:"name"`
Summary string `json:"summary"`
Color struct {
Key string `json:"key"`
} `json:"color"`
Done bool `json:"done"`
} `json:"epic"`
Priority *struct {
Self string `json:"self"`
IconURL string `json:"iconUrl"`
Name string `json:"name"`
ID uint64 `json:"id,string"`
} `json:"priority"`
Labels []interface{} `json:"labels"`
Timeestimate interface{} `json:"timeestimate"`
Aggregatetimeoriginalestimate interface{} `json:"aggregatetimeoriginalestimate"`
Versions []interface{} `json:"versions"`
Issuelinks []interface{} `json:"issuelinks"`
Assignee *User `json:"assignee"`
Updated core.Iso8601Time `json:"updated"`
Status struct {
Self string `json:"self"`
Description string `json:"description"`
IconURL string `json:"iconUrl"`
Name string `json:"name"`
ID string `json:"id"`
StatusCategory struct {
Self string `json:"self"`
ID int `json:"id"`
Key string `json:"key"`
ColorName string `json:"colorName"`
Name string `json:"name"`
} `json:"statusCategory"`
} `json:"status"`
Timeoriginalestimate *int64 `json:"timeoriginalestimate"`
Description interface{} `json:"description"`
Timetracking *struct {
RemainingEstimate string `json:"remainingEstimate"`
TimeSpent string `json:"timeSpent"`
RemainingEstimateSeconds int64 `json:"remainingEstimateSeconds"`
TimeSpentSeconds int `json:"timeSpentSeconds"`
} `json:"timetracking"`
Archiveddate interface{} `json:"archiveddate"`
Aggregatetimeestimate *int64 `json:"aggregatetimeestimate"`
Summary string `json:"summary"`
Creator User `json:"creator"`
Subtasks []interface{} `json:"subtasks"`
Reporter struct {
Self string `json:"self"`
Name string `json:"name"`
Key string `json:"key"`
EmailAddress string `json:"emailAddress"`
AvatarUrls struct {
Four8X48 string `json:"48x48"`
Two4X24 string `json:"24x24"`
One6X16 string `json:"16x16"`
Three2X32 string `json:"32x32"`
} `json:"avatarUrls"`
DisplayName string `json:"displayName"`
Active bool `json:"active"`
TimeZone string `json:"timeZone"`
} `json:"reporter"`
Aggregateprogress struct {
Progress int `json:"progress"`
Total int `json:"total"`
} `json:"aggregateprogress"`
Environment interface{} `json:"environment"`
Duedate interface{} `json:"duedate"`
Progress struct {
Progress int `json:"progress"`
Total int `json:"total"`
} `json:"progress"`
Worklog *struct {
StartAt int `json:"startAt"`
MaxResults int `json:"maxResults"`
Total int `json:"total"`
Worklogs []Worklog `json:"worklogs"`
} `json:"worklog"`
} `json:"fields"`
Changelog *struct {
StartAt int `json:"startAt"`
MaxResults int `json:"maxResults"`
Total int `json:"total"`
Histories []Changelog `json:"histories"`
} `json:"changelog"`
}
func (i Issue) toToolLayer(sourceId uint64, storyPointField string) *models.JiraIssue {
var workload float64
if storyPointField != "" {
workload, _ = i.Fields.AllFields[storyPointField].(float64)
}
result := &models.JiraIssue{
SourceId: sourceId,
IssueId: i.ID,
ProjectId: i.Fields.Project.ID,
Self: i.Self,
Key: i.Key,
StoryPoint: workload,
Summary: i.Fields.Summary,
Type: i.Fields.Issuetype.Name,
StatusName: i.Fields.Status.Name,
StatusKey: i.Fields.Status.StatusCategory.Key,
ResolutionDate: i.Fields.Resolutiondate.ToNullableTime(),
CreatorAccountId: i.Fields.Creator.getAccountId(),
CreatorDisplayName: i.Fields.Creator.DisplayName,
Created: i.Fields.Created.ToTime(),
Updated: i.Fields.Updated.ToTime(),
}
if i.Fields.Epic != nil {
result.EpicKey = i.Fields.Epic.Key
}
if i.Fields.Assignee != nil {
result.AssigneeAccountId = i.Fields.Assignee.getAccountId()
result.AssigneeDisplayName = i.Fields.Assignee.DisplayName
}
if i.Fields.Priority != nil {
result.PriorityId = i.Fields.Priority.ID
result.PriorityName = i.Fields.Priority.Name
}
if i.Fields.Timeoriginalestimate != nil {
result.OriginalEstimateMinutes = *i.Fields.Timeoriginalestimate / 60
}
if i.Fields.Aggregatetimeestimate != nil {
result.AggregateEstimateMinutes = *i.Fields.Aggregatetimeestimate / 60
}
if i.Fields.Timetracking != nil {
result.RemainingEstimateMinutes = i.Fields.Timetracking.RemainingEstimateSeconds / 60
}
if i.Fields.Parent != nil {
result.ParentId = i.Fields.Parent.ID
result.ParentKey = i.Fields.Parent.Key
}
if i.Fields.Sprint != nil {
result.SprintId = i.Fields.Sprint.ID
result.SprintName = i.Fields.Sprint.Name
}
return result
}
func (Issue) Unmarshal(raw json.RawMessage) ([]Issue, error) {
var raws []json.RawMessage
err := json.Unmarshal(raw, &raws)
if err != nil {
return nil, err
}
var issues []Issue
for _, msg := range raws {
var issue Issue
err = json.Unmarshal(msg, &issue)
if err != nil {
return nil, err
}
var issue2 struct {
Expand string `json:"expand"`
ID uint64 `json:"id,string"`
Self string `json:"self"`
Key string `json:"key"`
Fields json.RawMessage `json:"fields"`
}
err = json.Unmarshal(msg, &issue2)
if err != nil {
return nil, err
}
err = json.Unmarshal(issue2.Fields, &issue.Fields.AllFields)
if err != nil {
return nil, err
}
issues = append(issues, issue)
}
return issues, nil
}
func (Issue) ExtractRawMessage(blob []byte) (json.RawMessage, error) {
var resp struct {
StartAt int `json:"startAt"`
MaxResults int `json:"maxResults"`
Total int `json:"total"`
Issues json.RawMessage `json:"issues"`
}
err := json.Unmarshal(blob, &resp)
if err != nil {
return nil, err
}
return resp.Issues, nil
}
func (i Issue) ExtractEntities(sourceId uint64, storyPointField string) ([]uint64, *models.JiraIssue, bool, []*models.JiraWorklog, []*models.JiraChangelog, []*models.JiraChangelogItem) {
issue := i.toToolLayer(sourceId, storyPointField)
var worklogs []*models.JiraWorklog
var changelogs []*models.JiraChangelog
var changelogItems []*models.JiraChangelogItem
var needCollectWorklog bool
var sprints []uint64
if i.Fields.Worklog != nil {
if i.Fields.Worklog.Total > len(i.Fields.Worklog.Worklogs) {
needCollectWorklog = true
} else {
for _, w := range i.Fields.Worklog.Worklogs {
worklogs = append(worklogs, w.toToolLayer(sourceId, i.ID))
}
}
}
if i.Changelog != nil {
for _, changelog := range i.Changelog.Histories {
changelogs = append(changelogs, changelog.toToolLayer(sourceId, i.ID))
for _, item := range changelog.Items {
changelogItems = append(changelogItems, item.toToolLayer(sourceId, i.ID))
}
}
}
if i.Fields.Sprint != nil {
sprints = append(sprints, i.Fields.Sprint.ID)
}
for _, sprint := range i.Fields.ClosedSprints {
sprints = append(sprints, sprint.ID)
}
return sprints, issue, needCollectWorklog, worklogs, changelogs, changelogItems
}