This repository has been archived by the owner on Jan 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
savings.go
247 lines (208 loc) · 8.66 KB
/
savings.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
package starling
import (
"context"
"fmt"
"net/http"
"strings"
"github.com/google/uuid"
)
// SavingsGoal is a goal defined by a customer to hold savings
type SavingsGoal struct {
UID string `json:"uid"` // Unique identifier of the savings goal
Name string `json:"name"` // Name of the savings goal
Target Amount `json:"target"`
TotalSaved Amount `json:"totalSaved"`
SavedPercentage int32 `json:"savedPercentage"` // Percentage of target currently deposited in the savings goal
}
// SavingsGoals is a list containing all savings goals for customer
type savingsGoals struct {
SavingsGoals []SavingsGoal `json:"savingsGoalList"`
}
// SavingsGoalRequest is a request to create a new savings goal
type SavingsGoalRequest struct {
Name string `json:"name"` // Name of the savings goal
Currency string `json:"currency"` // ISO-4217 3 character currency code of the savings goal
Target Amount `json:"target"`
Base64EncodedPhoto string `json:"base64EncodedPhoto"` // A text (base 64) encoded picture to associate with the savings goal
}
// SavingsGoalResponse represents a response after attempting to create a savings goal
type savingsGoalResponse struct {
UID string `json:"savingsGoalUid"`
Success bool `json:"success"`
Errors []ErrorDetail `json:"errors"`
}
// SavingsGoalTransferResponse represents the response received after attempting to make an immediate or recurring transfer
// into/out of a savings goal.
type savingsGoalTransferResponse struct {
UID string `json:"transferUid"` // Unique identifier for the transfer
Success bool `json:"success"` // True if the method completed successfully
Errors []ErrorDetail `json:"errors"` // List of errors if the method request failed
}
// WithdrawalRequest is a request to withdraw money from a savings goal
type withdrawalRequest struct {
Amount `json:"amount"`
}
// TopUpRequest represents request to make an immediate transfer into a savings goal
type topUpRequest struct {
Amount `json:"amount"`
}
// RecurringTransferRequest represents a request to create scheduled payment into a savings goal
type RecurringTransferRequest struct {
UID string `json:"transferUid,omitempty"`
RecurrenceRule RecurrenceRule `json:"recurrenceRule"`
Amount `json:"currencyAndAmount"`
}
// SavingsGoals returns the savings goals for the current user. It also returns the http response
// in case this is required for further processing. It is possible that the user has no savings goals
// in which case a nil value will be returned. An error will be returned if unable to retrieve goals
// from the API.
func (c *Client) SavingsGoals(ctx context.Context) ([]SavingsGoal, *http.Response, error) {
req, err := c.NewRequest("GET", "/api/v1/savings-goals", nil)
if err != nil {
return nil, nil, err
}
var goals savingsGoals
resp, err := c.Do(ctx, req, &goals)
if err != nil {
return goals.SavingsGoals, resp, err
}
return goals.SavingsGoals, resp, nil
}
// SavingsGoal returns an individual savings goal based on a UID. It also returns the http response
// in case this is required for further processing. An error will be returned if unable to retrieve
// goals from the API.
func (c *Client) SavingsGoal(ctx context.Context, uid string) (*SavingsGoal, *http.Response, error) {
req, err := c.NewRequest("GET", "/api/v1/savings-goals/"+uid, nil)
if err != nil {
return nil, nil, err
}
var goal *SavingsGoal
resp, err := c.Do(ctx, req, &goal)
if err != nil {
return goal, resp, err
}
return goal, resp, nil
}
// CreateSavingsGoal creates an individual savings goal based on a UID. It returns the http response
// in case this is required for further processing. An error will be returned if the API is unable
// to create the goal.
func (c *Client) CreateSavingsGoal(ctx context.Context, uid string, sgReq SavingsGoalRequest) (*http.Response, error) {
req, err := c.NewRequest("PUT", "/api/v1/savings-goals/"+uid, sgReq)
if err != nil {
return nil, err
}
var sgResp *savingsGoalResponse
resp, err := c.Do(ctx, req, &sgResp)
if err != nil {
return resp, err
}
ers := make([]string, len(sgResp.Errors))
for i, v := range sgResp.Errors {
ers[i] = v.Message
}
if sgResp.Success != true {
return resp, fmt.Errorf(strings.Join(ers, ", "))
}
return resp, nil
}
// TransferToSavingsGoal transfers money into a savings goal. It returns the http response in case this is required for further
// processing. An error will be returned if the API is unable to transfer the amount into the savings goal.
func (c *Client) TransferToSavingsGoal(ctx context.Context, goalUID string, a Amount) (string, *http.Response, error) {
txnUID, err := uuid.NewRandom()
if err != nil {
return "", nil, err
}
req, err := c.NewRequest("PUT", "/api/v1/savings-goals/"+goalUID+"/add-money/"+txnUID.String(), topUpRequest{Amount: a})
if err != nil {
return "", nil, err
}
tuResp := new(savingsGoalTransferResponse)
resp, err := c.Do(ctx, req, &tuResp)
if err != nil {
return "", resp, err
}
return tuResp.UID, resp, nil
}
// TransferFromSavingsGoal transfers money out of a savings goal. It returns the http response in case this is required for further
// processing. An error will be returned if the API is unable to transfer the amount out of the savings goal.
func (c *Client) TransferFromSavingsGoal(ctx context.Context, goalUID string, a Amount) (string, *http.Response, error) {
txnUID, err := uuid.NewRandom()
if err != nil {
return "", nil, err
}
req, err := c.NewRequest("PUT", "/api/v1/savings-goals/"+goalUID+"/withdraw-money/"+txnUID.String(), topUpRequest{Amount: a})
if err != nil {
return "", nil, err
}
var tuResp *savingsGoalTransferResponse
resp, err := c.Do(ctx, req, &tuResp)
if err != nil {
return "", resp, err
}
return tuResp.UID, resp, nil
}
// DeleteSavingsGoal deletes a savings goal for the current customer. It returns http.StatusNoContent
// on success. No payload is returned.
func (c *Client) DeleteSavingsGoal(ctx context.Context, uid string) (*http.Response, error) {
req, err := c.NewRequest("DELETE", "/api/v1/savings-goals/"+uid, nil)
if err != nil {
return nil, err
}
resp, err := c.Do(ctx, req, nil)
return resp, err
}
// SavingsGoalPhoto returns the photo for savings goal based on a UID. It also returns the http response
// in case this is required for further processing. An error will be returned if unable to retrieve
// the photo from the API.
func (c *Client) SavingsGoalPhoto(ctx context.Context, uid string) (*Photo, *http.Response, error) {
req, err := c.NewRequest("GET", "/api/v1/savings-goals/"+uid+"/photo", nil)
if err != nil {
return nil, nil, err
}
var photo *Photo
resp, err := c.Do(ctx, req, &photo)
if err != nil {
return photo, resp, err
}
return photo, resp, nil
}
// RecurringTransfer returns the recurring savings for savings goal based on a UID. It also returns
// the http response in case this is required for further processing. An error will be returned if
// unable to retrieve the recurring savings set-up from the API.
func (c *Client) RecurringTransfer(ctx context.Context, uid string) (*RecurringTransferRequest, *http.Response, error) {
req, err := c.NewRequest("GET", "/api/v1/savings-goals/"+uid+"/recurring-transfer", nil)
if err != nil {
return nil, nil, err
}
var rtr *RecurringTransferRequest
resp, err := c.Do(ctx, req, &rtr)
if err != nil {
return rtr, resp, err
}
return rtr, resp, nil
}
// CreateRecurringTransfer sets up the recurring transfer for a savings goal. It takes the UID of the savings goal, along with a RecurringTransferRequest
// and returns the UID of the recurring transfer. It also returns the http response in case this is required for further processing. An error is returned
// on failure.
func (c *Client) CreateRecurringTransfer(ctx context.Context, uid string, rtr RecurringTransferRequest) (string, *http.Response, error) {
req, err := c.NewRequest("PUT", "/api/v1/savings-goals/"+uid+"/recurring-transfer", rtr)
if err != nil {
return "", nil, err
}
var tuResp *savingsGoalTransferResponse
resp, err := c.Do(ctx, req, &tuResp)
if err != nil {
return "", resp, err
}
return "", resp, nil
}
// DeleteRecurringTransfer deletes the recurring transfer for a savings goal. It takes the UID of the savings goal and returns no content. It returns the
// http response in case this is required for further processing. An error is returned on failure.
func (c *Client) DeleteRecurringTransfer(ctx context.Context, uid string) (*http.Response, error) {
req, err := c.NewRequest("DELETE", "/api/v1/savings-goals/"+uid+"/recurring-transfer", nil)
if err != nil {
return nil, err
}
resp, err := c.Do(ctx, req, nil)
return resp, err
}