From f1394d60aa251597968bd495bb706ddb468356ff Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Fri, 15 Nov 2024 10:20:36 +0000 Subject: [PATCH] Adding address line support methods --- CHANGELOG.md | 4 ++++ org/address.go | 48 +++++++++++++++++++++++++++++++++++++++++++++ org/address_test.go | 45 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ec2ec60..fd0ab145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p ## [Unreleased] +### Added + +- `org`: `Address` includes `LineOne()`, `LineTwo()`, `CompleteNumber()` methods to help with conversion to other formats with some regional formatting. + ## [v0.205.0] ### Added diff --git a/org/address.go b/org/address.go index 29663471..ec3b38c2 100644 --- a/org/address.go +++ b/org/address.go @@ -95,3 +95,51 @@ func (Address) JSONSchemaExtend(js *jsonschema.Schema) { }, } } + +// LineOne returns the first line of the address by automatically +// combining street, number, and other details into a single line. +// This is useful for compatibility with other formats that don't +// support the number fields directly. +func (a *Address) LineOne() string { + str := a.Street + num := a.CompleteNumber() + if num != "" { + if a.numberFirst() { + str = num + " " + str + } else { + str = str + " " + num + } + } + return str +} + +// LineTwo returns the second line of the address which for GOBL +// is the `StreetExtra` field. +func (a *Address) LineTwo() string { + return a.StreetExtra +} + +// CompleteNumber will combine all the number related details, such +// as number, block, floor, and door, into a single string separated +// by spaces. +func (a *Address) CompleteNumber() string { + strs := []string{a.Number, a.Block, a.Floor, a.Door} + // Remove empty strings. + var parts []string + for _, s := range strs { + if s != "" { + parts = append(parts, s) + } + } + return strings.Join(parts, " ") +} + +func (a *Address) numberFirst() bool { + // TODO: add more countries here! + switch a.Country.Code() { + case l10n.GB, l10n.US, l10n.CA, l10n.FR: + return true + default: + return false + } +} diff --git a/org/address_test.go b/org/address_test.go index 661aeb5c..bb9444df 100644 --- a/org/address_test.go +++ b/org/address_test.go @@ -73,3 +73,48 @@ func TestAddressValidation(t *testing.T) { assert.ErrorContains(t, a.Validate(), "uuid: invalid UUID length: 7") }) } + +func TestAddressLineOne(t *testing.T) { + t.Run("number first", func(t *testing.T) { + a := &org.Address{ + Number: "12", + Street: "Main St.", + Country: "GB", + } + assert.Equal(t, "12 Main St.", a.LineOne()) + }) + + t.Run("street first", func(t *testing.T) { + a := &org.Address{ + Number: "12", + Street: "Gran Vía", + Country: "ES", + } + assert.Equal(t, "Gran Vía 12", a.LineOne()) + }) + + t.Run("combine number details", func(t *testing.T) { + a := &org.Address{ + Number: "12", + Block: "esc. 1", + Floor: "10", + Door: "C", + Street: "Gran Vía", + Country: "ES", + } + assert.Equal(t, "Gran Vía 12 esc. 1 10 C", a.LineOne()) + }) +} + +func TestAddressLineTwo(t *testing.T) { + t.Run("number first", func(t *testing.T) { + a := &org.Address{ + Number: "12", + Street: "Main St.", + StreetExtra: "Apt. 3", + Country: "GB", + } + assert.Equal(t, "12 Main St.", a.LineOne()) + assert.Equal(t, "Apt. 3", a.LineTwo()) + }) +}