Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
178 changes: 178 additions & 0 deletions company_assisted.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// Non-generated wrapper for /employer/company endpoint to handle 202 responses from assisted connections.
// This file will not be overwritten by codegen.

package finchgo

import (
"context"
"net/http"
"reflect"
"slices"

"github.com/Finch-API/finch-api-go/internal/apijson"
"github.com/Finch-API/finch-api-go/internal/requestconfig"
"github.com/Finch-API/finch-api-go/option"
"github.com/tidwall/gjson"
)

// GetWithAssistedSupport reads basic company data with support for 202 responses
// from assisted connections. Returns a union type that can be either:
// - Company (200 OK with Company data)
// - CompanyDataSyncInProgress (202 Accepted with sync status)
func (r *HRISCompanyService) GetWithAssistedSupport(ctx context.Context, opts ...option.RequestOption) (res *CompanyResponse, err error) {
opts = slices.Concat(r.Options, opts)
path := "employer/company"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}

// CompanyResponse is the union wrapper for response variants
type CompanyResponse struct {
Code float64 `json:"code"`
FinchCode string `json:"finch_code"`
Message string `json:"message"`
Name string `json:"name"`
JSON companyResponseJSON `json:"-"`
union CompanyResponseUnion
}

// companyResponseJSON contains the JSON metadata for the struct [CompanyResponse]
type companyResponseJSON struct {
Code apijson.Field
FinchCode apijson.Field
Message apijson.Field
Name apijson.Field
raw string
ExtraFields map[string]apijson.Field
}

func (r companyResponseJSON) RawJSON() string {
return r.raw
}

func (r *CompanyResponse) UnmarshalJSON(data []byte) (err error) {
*r = CompanyResponse{}
err = apijson.UnmarshalRoot(data, &r.union)
if err != nil {
return err
}
return apijson.Port(r.union, &r)
}

// AsUnion returns a [CompanyResponseUnion] interface which you can cast
// to the specific types for more type safety.
//
// Possible runtime types of the union are [Company],
// [CompanyDataSyncInProgress].
func (r CompanyResponse) AsUnion() CompanyResponseUnion {
return r.union
}

// Union satisfied by [Company] or [CompanyDataSyncInProgress].
type CompanyResponseUnion interface {
implementsCompanyResponse()
}

func init() {
apijson.RegisterUnion(
reflect.TypeOf((*CompanyResponseUnion)(nil)).Elem(),
"code",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(Company{}),
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(CompanyDataSyncInProgress{}),
},
)
}

// Make Company satisfy the union interface
func (r Company) implementsCompanyResponse() {}

// CompanyDataSyncInProgress represents a 202 response when data sync is in progress
type CompanyDataSyncInProgress struct {
Code CompanyDataSyncInProgressCode `json:"code,required"`
FinchCode CompanyDataSyncInProgressFinchCode `json:"finch_code,required"`
Message CompanyDataSyncInProgressMessage `json:"message,required"`
Name CompanyDataSyncInProgressName `json:"name,required"`
JSON companyDataSyncInProgressJSON `json:"-"`
}

// companyDataSyncInProgressJSON contains the JSON metadata for the struct
// [CompanyDataSyncInProgress]
type companyDataSyncInProgressJSON struct {
Code apijson.Field
FinchCode apijson.Field
Message apijson.Field
Name apijson.Field
raw string
ExtraFields map[string]apijson.Field
}

func (r *CompanyDataSyncInProgress) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}

func (r companyDataSyncInProgressJSON) RawJSON() string {
return r.raw
}

func (r CompanyDataSyncInProgress) implementsCompanyResponse() {}

type CompanyDataSyncInProgressCode float64

const (
CompanyDataSyncInProgressCode202 CompanyDataSyncInProgressCode = 202
)

func (r CompanyDataSyncInProgressCode) IsKnown() bool {
switch r {
case CompanyDataSyncInProgressCode202:
return true
}
return false
}

type CompanyDataSyncInProgressFinchCode string

const (
CompanyDataSyncInProgressFinchCodeDataSyncInProgress CompanyDataSyncInProgressFinchCode = "data_sync_in_progress"
)

func (r CompanyDataSyncInProgressFinchCode) IsKnown() bool {
switch r {
case CompanyDataSyncInProgressFinchCodeDataSyncInProgress:
return true
}
return false
}

type CompanyDataSyncInProgressMessage string

const (
CompanyDataSyncInProgressMessageTheCompanyDataIsBeingFetchedPleaseCheckBackLater CompanyDataSyncInProgressMessage = "The company data is being fetched. Please check back later."
)

func (r CompanyDataSyncInProgressMessage) IsKnown() bool {
switch r {
case CompanyDataSyncInProgressMessageTheCompanyDataIsBeingFetchedPleaseCheckBackLater:
return true
}
return false
}

type CompanyDataSyncInProgressName string

const (
CompanyDataSyncInProgressNameAccepted CompanyDataSyncInProgressName = "accepted"
)

func (r CompanyDataSyncInProgressName) IsKnown() bool {
switch r {
case CompanyDataSyncInProgressNameAccepted:
return true
}
return false
}
113 changes: 113 additions & 0 deletions company_assisted_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package finchgo_test

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"

finchgo "github.com/Finch-API/finch-api-go"
"github.com/Finch-API/finch-api-go/option"
)

func TestCompanyGetWithAssistedSupport_200Response(t *testing.T) {
// Mock server that returns 200 with Company data
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/employer/company" {
t.Errorf("Expected path /employer/company, got %s", r.URL.Path)
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
resp := map[string]interface{}{
"id": "12345678-1234-1234-1234-123456789012",
"legal_name": "Test Company LLC",
"ein": "12-3456789",
"primary_email": "test@example.com",
"primary_phone_number": "+11234567890",
"entity": map[string]interface{}{
"type": "llc",
"subtype": nil,
},
"locations": []interface{}{},
"accounts": []interface{}{},
"departments": []interface{}{},
}
json.NewEncoder(w).Encode(resp)
}))
defer server.Close()

client := finchgo.NewClient(
option.WithAccessToken("test-token"),
option.WithBaseURL(server.URL),
)

resp, err := client.HRIS.Company.GetWithAssistedSupport(context.Background())
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

// Check that we got a Company response
switch u := resp.AsUnion().(type) {
case finchgo.Company:
if u.ID != "12345678-1234-1234-1234-123456789012" {
t.Errorf("Expected ID 12345678-1234-1234-1234-123456789012, got %s", u.ID)
}
if u.LegalName != "Test Company LLC" {
t.Errorf("Expected LegalName 'Test Company LLC', got %s", u.LegalName)
}
case finchgo.CompanyDataSyncInProgress:
t.Fatalf("Expected Company, got CompanyDataSyncInProgress")
default:
t.Fatalf("Unexpected union type: %T", u)
}
}

func TestCompanyGetWithAssistedSupport_202Response(t *testing.T) {
// Mock server that returns 202 with sync status
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/employer/company" {
t.Errorf("Expected path /employer/company, got %s", r.URL.Path)
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) // SDK doesn't check HTTP status, relies on body
resp := map[string]interface{}{
"code": 202,
"finch_code": "data_sync_in_progress",
"message": "The company data is being fetched. Please check back later.",
"name": "accepted",
}
json.NewEncoder(w).Encode(resp)
}))
defer server.Close()

client := finchgo.NewClient(
option.WithAccessToken("test-token"),
option.WithBaseURL(server.URL),
)

resp, err := client.HRIS.Company.GetWithAssistedSupport(context.Background())
if err != nil {
t.Fatalf("Expected no error, got %v", err)
}

// Check that we got a CompanyDataSyncInProgress response
switch u := resp.AsUnion().(type) {
case finchgo.Company:
t.Fatalf("Expected CompanyDataSyncInProgress, got Company")
case finchgo.CompanyDataSyncInProgress:
if u.Code != finchgo.CompanyDataSyncInProgressCode202 {
t.Errorf("Expected Code 202, got %v", u.Code)
}
if u.FinchCode != finchgo.CompanyDataSyncInProgressFinchCodeDataSyncInProgress {
t.Errorf("Expected FinchCode 'data_sync_in_progress', got %s", u.FinchCode)
}
if u.Name != finchgo.CompanyDataSyncInProgressNameAccepted {
t.Errorf("Expected Name 'accepted', got %s", u.Name)
}
default:
t.Fatalf("Unexpected union type: %T", u)
}
}
43 changes: 43 additions & 0 deletions examples/company_assisted/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"context"
"fmt"
"os"

finchgo "github.com/Finch-API/finch-api-go"
"github.com/Finch-API/finch-api-go/option"
)

func main() {
client := finchgo.NewClient(
option.WithAccessToken(os.Getenv("FINCH_ACCESS_TOKEN")),
)

resp, err := client.HRIS.Company.GetWithAssistedSupport(context.Background())
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}

// Handle the union response
switch u := resp.AsUnion().(type) {
case finchgo.Company:
// 200 OK - Company data is ready
fmt.Printf("Company ID: %s\n", u.ID)
fmt.Printf("Legal Name: %s\n", u.LegalName)
fmt.Printf("EIN: %s\n", u.Ein)
fmt.Printf("Primary Email: %s\n", u.PrimaryEmail)

case finchgo.CompanyDataSyncInProgress:
// 202 Accepted - Data sync in progress
fmt.Printf("Status: %s (code %v)\n", u.Name, u.Code)
fmt.Printf("Message: %s\n", u.Message)
fmt.Printf("Finch Code: %s\n", u.FinchCode)
fmt.Println("\nPlease retry this request later. Data is still syncing from the provider.")

default:
fmt.Fprintf(os.Stderr, "Unexpected response type: %T\n", u)
os.Exit(1)
}
}