Skip to content

Commit

Permalink
Merge pull request #24 from Hsn723/master
Browse files Browse the repository at this point in the history
Initial support for process management
  • Loading branch information
phongnhat19 authored Aug 5, 2019
2 parents c0cded9 + e8843d8 commit 6c41b97
Show file tree
Hide file tree
Showing 4 changed files with 264 additions and 2 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ to access [kintone][] with its official REST API ([en][APIen], [ja][APIja]).

## Version

0.1.1
0.1.2

## License

Expand Down
78 changes: 77 additions & 1 deletion app.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (

const (
NAME = "kintone-go-SDK"
VERSION = "0.1.1"
VERSION = "0.1.2"
DEFAULT_TIMEOUT = time.Second * 600 // Default value for App.Timeout
)

Expand Down Expand Up @@ -390,6 +390,52 @@ func (app *App) GetAllRecords(fields []string) ([]*Record, error) {
}
}

func isAllowedLang(allowedLangs []string, lang string) bool {
for _, allowedLang := range allowedLangs {
if lang == allowedLang {
return true
}
}
return false
}

// GetProcess retrieves the process management settings
// This method can only be used when App is initialized with password authentication
// lang must be one of default, en, zh, ja, user
func (app *App) GetProcess(lang string) (process *Process, err error) {
type request_body struct {
App uint64 `json:"app,string"`
lang string `json:"lang,string"`
}
if app.User == "" || app.Password == "" {
err = errors.New("This API only supports password authentication")
return
}
allowedLangs := []string{"default", "en", "zh", "ja", "user"}
if !isAllowedLang(allowedLangs, lang) {
err = errors.New("Illegal language provided")
return
}
data, _ := json.Marshal(request_body{app.AppId, lang})
req, err := app.newRequest("GET", "app/status", bytes.NewReader(data))
if err != nil {
return
}
resp, err := app.do(req)
if err != nil {
return
}
body, err := parseResponse(resp)
if err != nil {
return
}
process, err = DecodeProcess(body)
if err != nil {
err = ErrInvalidResponse
}
return
}

// FileData stores downloaded file data.
type FileData struct {
ContentType string // MIME type of the contents.
Expand Down Expand Up @@ -715,6 +761,36 @@ func (app *App) UpdateRecordsByKey(recs []*Record, ignoreRevision bool, keyField
return err
}

// UpdateRecordStatus updates the Status of a record
func (app *App) UpdateRecordStatus(rec *Record, action *ProcessAction, assignee *Entity, ignoreRevision bool) (err error) {
type request_body struct {
App uint64 `json:"app,string"`
Id uint64 `json:"id,string"`
Revision int64 `json:"revision,string"`
Action string `json:"action"`
Assignee string `json:"assignee,omitempty"`
}
rev := rec.Revision()
if ignoreRevision {
rev = -1
}
var code string
if assignee != nil {
code = assignee.Code
}
data, _ := json.Marshal(request_body{app.AppId, rec.id, rev, action.Name, code})
req, err := app.newRequest("PUT", "record/status", bytes.NewReader(data))
if err != nil {
return
}
resp, err := app.do(req)
if err != nil {
return
}
_, err = parseResponse(resp)
return
}

// DeleteRecords deletes multiple records.
//
// Up to 100 records can be deleted at once.
Expand Down
58 changes: 58 additions & 0 deletions process.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// (C) 2014 Cybozu. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.

package kintone

import (
"encoding/json"
)

// Process represents the process management settings for an application
type Process struct {
Enable bool `json:"enable"`
States map[string](*ProcessState) `json:"states"`
Actions []*ProcessAction `json:"actions"`
Revision string `json:"revision"`
}

// ProcessState represents a process management status
type ProcessState struct {
Name string `json:"name"`
Index string `json:"index"`
Assignee *ProcessAssignee `json:"assignee"`
}

// ProcessAction representes a process management action
type ProcessAction struct {
Name string `json:"name"`
From string `json:"from"`
To string `json:"to"`
FilterCond string `json:"filterCond"`
}

// ProcessAssignee represents a ProcessState assignee
type ProcessAssignee struct {
Type string `json:type`
Entities []*ProcessEntity `json:entities`
}

// ProcessEntity represents a process assignee entity
type ProcessEntity struct {
Entity *Entity `json:entity`
IncludeSubs bool `json:includeSubs`
}

// Entity is the concrete representation of a process entity
type Entity struct {
Type string `json:type`
Code string `json:code`
}

func DecodeProcess(b []byte) (p *Process, err error) {
err = json.Unmarshal(b, &p)
if err != nil {
return
}
return
}
128 changes: 128 additions & 0 deletions process_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// (C) 2014 Cybozu. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file.

package kintone

import (
"testing"
)

func TestDecodeProcess(t *testing.T) {
t.Parallel()
j := []byte(`
{
"enable": true,
"states": {
"Not started": {
"name": "Not started",
"index": "0",
"assignee": {
"type": "ONE",
"entities": [
]
}
},
"In progress": {
"name": "In progress",
"index": "1",
"assignee": {
"type": "ALL",
"entities": [
{
"entity": {
"type": "USER",
"code": "user1"
},
"includeSubs": false
},
{
"entity": {
"type": "FIELD_ENTITY",
"code": "creator"
},
"includeSubs": false
},
{
"entity": {
"type": "CUSTOM_FIELD",
"code": "Boss"
},
"includeSubs": false
}
]
}
},
"Completed": {
"name": "Completed",
"index": "2",
"assignee": {
"type": "ONE",
"entities": [
]
}
}
},
"actions": [
{
"name": "Start",
"from": "Not started",
"to": "In progress",
"filterCond": "Record_number = \"1\""
},
{
"name": "Complete",
"from": "In progress",
"to": "Completed",
"filterCond": ""
}
],
"revision": "3"
}`)
process, err := DecodeProcess(j)
if err != nil {
t.Fatal(err)
}
if !process.Enable {
t.Errorf("Expected enabled, got %v", process.Enable)
}
if len(process.States) != 3 {
t.Errorf("Expected 3 states, got %v", len(process.States))
}
if len(process.Actions) != 2 {
t.Errorf("Expected 2 actions, got %v", len(process.Actions))
}
if process.Revision != "3" {
t.Errorf("Expected revision to be 3, got %v", process.Revision)
}
notStartedProcess := process.States["Not started"]
if notStartedProcess.Name != "Not started" {
t.Errorf("Expected status name to be \"Not started\", got \"%v\"", notStartedProcess.Name)
}
if notStartedProcess.Index != "0" {
t.Errorf("Expected status index to be 0, got %v", notStartedProcess.Index)
}
if notStartedProcess.Assignee.Type != "ONE" {
t.Errorf("Expected assignee type to be \"ONE\", got \"%v\"", notStartedProcess.Assignee.Type)
}
inProgressProcess := process.States["In progress"]
if len(inProgressProcess.Assignee.Entities) != 3 {
t.Errorf("Expected 0 assignees, got %v", len(inProgressProcess.Assignee.Entities))
}
if inProgressProcess.Assignee.Entities[0].Entity.Code != "user1" {
t.Errorf("Expected entity to be named \"user1\", got \"%v\"", inProgressProcess.Assignee.Entities[0].Entity.Code)
}
if inProgressProcess.Assignee.Entities[0].IncludeSubs {
t.Errorf("Expected entity to not include subs, got %v", inProgressProcess.Assignee.Entities[0].IncludeSubs)
}
completeAction := process.Actions[1]
if completeAction.Name != "Complete" {
t.Errorf("Expected action name to be \"Complete\", got \"%v\"", completeAction.Name)
}
if completeAction.From != "In progress" {
t.Errorf("Expected previous status to be \"In progress\", got \"%v\"", completeAction.From)
}
if completeAction.To != "Completed" {
t.Errorf("Expected next status to be \"Completed\", got \"%v\"", completeAction.To)
}
}

0 comments on commit 6c41b97

Please sign in to comment.