Skip to content

Commit 047ca5e

Browse files
committed
Feature: Allow listing industries
To create a company there's an option to send the industry ID, but without being able to list the industries, the SDK user don't know what ID to provide. This changes now add the ability to list the industries and cover this gap.
1 parent 059ee45 commit 047ca5e

File tree

3 files changed

+195
-0
lines changed

3 files changed

+195
-0
lines changed

projects/industry.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package projects
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
9+
twapi "github.com/teamwork/twapi-go-sdk"
10+
)
11+
12+
var (
13+
_ twapi.HTTPRequester = (*IndustryListRequest)(nil)
14+
_ twapi.HTTPResponser = (*IndustryListResponse)(nil)
15+
)
16+
17+
// Industry refers to the business sector or market category that a company
18+
// belongs to, such as technology, healthcare, finance, or education. It helps
19+
// provide context about the nature of a company’s work and can be used to
20+
// better organize and filter data across the platform. By associating companies
21+
// and projects with specific industries, Teamwork.com allows teams to gain
22+
// clearer insights, tailor communication, and segment information in ways that
23+
// make it easier to manage relationships and understand the broader business
24+
// landscape in which their clients and partners operate.
25+
type Industry struct {
26+
// ID is the unique identifier of the industry.
27+
ID LegacyNumber `json:"id"`
28+
29+
// Name is the name of the industry.
30+
Name string `json:"name"`
31+
}
32+
33+
// IndustryListRequest represents the request body for loading multiple industries.
34+
//
35+
// Not documented.
36+
type IndustryListRequest struct{}
37+
38+
// NewIndustryListRequest creates a new IndustryListRequest with default values.
39+
func NewIndustryListRequest() IndustryListRequest {
40+
return IndustryListRequest{}
41+
}
42+
43+
// HTTPRequest creates an HTTP request for the IndustryListRequest.
44+
func (p IndustryListRequest) HTTPRequest(ctx context.Context, server string) (*http.Request, error) {
45+
uri := server + "/industries.json"
46+
47+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, nil)
48+
if err != nil {
49+
return nil, err
50+
}
51+
return req, nil
52+
}
53+
54+
// IndustryListResponse contains information by multiple industries matching the
55+
// request filters.
56+
//
57+
// Not documented.
58+
type IndustryListResponse struct {
59+
Industries []Industry `json:"industries"`
60+
}
61+
62+
// HandleHTTPResponse handles the HTTP response for the IndustryListResponse. If
63+
// some unexpected HTTP status code is returned by the API, a twapi.HTTPError is
64+
// returned.
65+
func (p *IndustryListResponse) HandleHTTPResponse(resp *http.Response) error {
66+
if resp.StatusCode != http.StatusOK {
67+
return twapi.NewHTTPError(resp, "failed to list industries")
68+
}
69+
70+
if err := json.NewDecoder(resp.Body).Decode(p); err != nil {
71+
return fmt.Errorf("failed to decode list industries response: %w", err)
72+
}
73+
return nil
74+
}
75+
76+
// IndustryList retrieves multiple industries using the provided request
77+
// and returns the response.
78+
func IndustryList(
79+
ctx context.Context,
80+
engine *twapi.Engine,
81+
req IndustryListRequest,
82+
) (*IndustryListResponse, error) {
83+
return twapi.Execute[IndustryListRequest, *IndustryListResponse](ctx, engine, req)
84+
}

projects/industry_example_test.go

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package projects_test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"net"
7+
"net/http"
8+
"strings"
9+
10+
twapi "github.com/teamwork/twapi-go-sdk"
11+
"github.com/teamwork/twapi-go-sdk/projects"
12+
"github.com/teamwork/twapi-go-sdk/session"
13+
)
14+
15+
func ExampleIndustryList() {
16+
address, stop, err := startIndustryServer() // mock server for demonstration purposes
17+
if err != nil {
18+
fmt.Printf("failed to start server: %s", err)
19+
return
20+
}
21+
defer stop()
22+
23+
ctx := context.Background()
24+
engine := twapi.NewEngine(session.NewBearerToken("your_token", fmt.Sprintf("http://%s", address)))
25+
26+
industryRequest := projects.NewIndustryListRequest()
27+
28+
industryResponse, err := projects.IndustryList(ctx, engine, industryRequest)
29+
if err != nil {
30+
fmt.Printf("failed to list industries: %s", err)
31+
} else {
32+
for _, industry := range industryResponse.Industries {
33+
fmt.Printf("retrieved industry with identifier %d\n", industry.ID)
34+
}
35+
}
36+
37+
// Output: retrieved industry with identifier 12345
38+
// retrieved industry with identifier 12346
39+
}
40+
41+
func startIndustryServer() (string, func(), error) {
42+
ln, err := net.Listen("tcp", "localhost:0")
43+
if err != nil {
44+
return "", nil, fmt.Errorf("failed to start server: %w", err)
45+
}
46+
47+
mux := http.NewServeMux()
48+
mux.HandleFunc("GET /industries", func(w http.ResponseWriter, _ *http.Request) {
49+
w.WriteHeader(http.StatusOK)
50+
w.Header().Set("Content-Type", "application/json")
51+
_, _ = fmt.Fprintln(w, `{"industries":[{"id":"12345"},{"id":"12346"}]}`)
52+
})
53+
54+
server := &http.Server{
55+
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
56+
if r.Header.Get("Authorization") != "Bearer your_token" {
57+
http.Error(w, "Unauthorized", http.StatusUnauthorized)
58+
return
59+
}
60+
r.URL.Path = strings.TrimSuffix(r.URL.Path, ".json")
61+
mux.ServeHTTP(w, r)
62+
}),
63+
}
64+
65+
stop := make(chan struct{})
66+
go func() {
67+
_ = server.Serve(ln)
68+
}()
69+
go func() {
70+
<-stop
71+
_ = server.Shutdown(context.Background())
72+
}()
73+
74+
return ln.Addr().String(), func() {
75+
close(stop)
76+
}, nil
77+
}

projects/industry_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package projects_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
"time"
7+
8+
"github.com/teamwork/twapi-go-sdk/projects"
9+
)
10+
11+
func TestIndustryList(t *testing.T) {
12+
if engine == nil {
13+
t.Skip("Skipping test because the engine is not initialized")
14+
}
15+
16+
tests := []struct {
17+
name string
18+
input projects.IndustryListRequest
19+
}{{
20+
name: "all industries",
21+
}}
22+
23+
for _, tt := range tests {
24+
t.Run(tt.name, func(t *testing.T) {
25+
ctx := t.Context()
26+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
27+
t.Cleanup(cancel)
28+
29+
if _, err := projects.IndustryList(ctx, engine, tt.input); err != nil {
30+
t.Errorf("unexpected error: %s", err)
31+
}
32+
})
33+
}
34+
}

0 commit comments

Comments
 (0)