diff options
| author | Simen A. W. Olsen <hello@simenandre.no> | 2026-10-17 14:27:46 +0200 |
|---|---|---|
| committer | Simen A. W. Olsen <hello@simenandre.no> | 2026-10-17 14:27:46 +0200 |
| commit | 08b6286f1bfe3892d0d63726d79cd5f1d9acac01 (patch) | |
| tree | dc979b1836bfb57253c9837e321445a07d4413e8 | |
| parent | c0a01ac65bb492640b169274614e0d8022f5076d (diff) | |
| download | fiken-0.2.0.tar.gz fiken-0.2.0.zip | |
Add CreateContactv0.2.0
Needed to link an order to Fiken without leaving the terminal: the signed
order already carries the legal name, organisation number and address, so
the contact can be made from it.
| -rw-r--r-- | fiken/fiken.go | 38 | ||||
| -rw-r--r-- | fiken/fiken_test.go | 35 |
2 files changed, 73 insertions, 0 deletions
diff --git a/fiken/fiken.go b/fiken/fiken.go index 3179a62..9b46607 100644 --- a/fiken/fiken.go +++ b/fiken/fiken.go @@ -137,6 +137,44 @@ type Contact struct { Inactive bool `json:"inactive"` } +// NewContact is a contact to create. Fiken requires only the name. +type NewContact struct { + Name string `json:"name"` + Email string `json:"email,omitempty"` + OrganizationNumber string `json:"organizationNumber,omitempty"` + Customer bool `json:"customer"` + Supplier bool `json:"supplier"` + Address *Address `json:"address,omitempty"` +} + +// Address is a postal address. Fiken requires a country on one. +type Address struct { + StreetAddress string `json:"streetAddress,omitempty"` + PostCode string `json:"postCode,omitempty"` + City string `json:"city,omitempty"` + Country string `json:"country"` +} + +// CreateContact creates a contact and returns its id, which Fiken reports +// only in a Location header. +func (c *Client) CreateContact(ctx context.Context, companySlug string, contact NewContact) (int64, error) { + assert.True(companySlug != "", "company slug must not be empty") + assert.True(strings.TrimSpace(contact.Name) != "", "a contact needs a name") + + body, err := json.Marshal(contact) + if err != nil { + return 0, fmt.Errorf("encode contact: %w", err) + } + resp, err := c.do(ctx, http.MethodPost, "/companies/"+companySlug+"/contacts", nil, body) + if err != nil { + return 0, err + } + defer resp.Body.Close() + io.Copy(io.Discard, io.LimitReader(resp.Body, maxBodyBytes)) //nolint:errcheck + + return idFromLocation(resp.Header.Get("Location")) +} + // DraftLine is one line of an invoice draft. UnitPrice is in the invoice // currency's minor unit — øre, cents — and Quantity is normally 1, so the // amount is carried entirely by the price and no float ever enters the diff --git a/fiken/fiken_test.go b/fiken/fiken_test.go index 2962e4a..1f24b86 100644 --- a/fiken/fiken_test.go +++ b/fiken/fiken_test.go @@ -318,3 +318,38 @@ func TestCreditNoteWithoutNumberingIsRecognised(t *testing.T) { t.Errorf("counter = %v, want the number before the first", counter) } } + +func TestCreateContactReadsTheLocationHeader(t *testing.T) { + var body NewContact + var path string + c := newTestClient(t, func(w http.ResponseWriter, r *http.Request) { + path = r.URL.Path + if r.Method != http.MethodPost { + t.Errorf("method = %s, want POST", r.Method) + } + if err := json.NewDecoder(r.Body).Decode(&body); err != nil { + t.Errorf("decode body: %v", err) + } + w.Header().Set("Location", "https://api.fiken.no/api/v2/companies/sokkel-as/contacts/9474586519") + w.WriteHeader(http.StatusCreated) + }) + + id, err := c.CreateContact(context.Background(), "sokkel-as", NewContact{ + Name: "Upstacked AS", OrganizationNumber: "926030396", Customer: true, + Address: &Address{StreetAddress: "Drammensveien 151", PostCode: "0277", City: "Oslo", Country: "Norge"}, + }) + if err != nil { + t.Fatalf("CreateContact: %v", err) + } + if id != 9474586519 { + t.Errorf("contact id = %d, want 9474586519", id) + } + if !strings.HasSuffix(path, "/companies/sokkel-as/contacts") { + t.Errorf("posted to %s, want the company's contacts", path) + } + // Fiken distinguishes a customer from a supplier, and a contact created as + // neither cannot be invoiced. + if !body.Customer || body.Address == nil || body.Address.Country == "" { + t.Errorf("contact was sent as %+v, want a customer with a country on its address", body) + } +} |
