This repository has been archived by the owner on Apr 20, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
/
linked_transaction.go
194 lines (152 loc) · 7.94 KB
/
linked_transaction.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
package accounting
import (
"encoding/json"
"encoding/xml"
"time"
"github.com/XeroAPI/xerogolang"
"github.com/XeroAPI/xerogolang/helpers"
"github.com/markbates/goth"
)
//LinkedTransaction can link transactions from an Accounts Payable invoice to an
//accounts recievable invoice - also known as a billable expense
type LinkedTransaction struct {
// Filter by the SourceTransactionID. Get all the linked transactions created from a particular ACCPAY invoice
SourceTransactionID string `json:"SourceTransactionID,omitempty" xml:"SourceTransactionID,omitempty"`
// The line item identifier from the source transaction.
SourceLineItemID string `json:"SourceLineItemID" xml:"SourceLineItemID"`
// Filter by the combination of ContactID and Status. Get all the linked transactions that have been assigned to a particular customer and have a particular status e.g. GET /LinkedTransactions?ContactID=4bb34b03-3378-4bb2-a0ed-6345abf3224e&Status=APPROVED.
ContactID string `json:"ContactID,omitempty" xml:"ContactID,omitempty"`
// Filter by the TargetTransactionID. Get all the linked transactions allocated to a particular ACCREC invoice
TargetTransactionID string `json:"TargetTransactionID,omitempty" xml:"TargetTransactionID,omitempty"`
// The line item identifier from the target transaction. It is possible to link multiple billable expenses to the same TargetLineItemID.
TargetLineItemID string `json:"TargetLineItemID,omitempty" xml:"TargetLineItemID,omitempty"`
// The Xero identifier for an Linked Transaction e.g. /LinkedTransactions/297c2dc5-cc47-4afd-8ec8-74990b8761e9
LinkedTransactionID string `json:"LinkedTransactionID,omitempty" xml:"LinkedTransactionID,omitempty"`
// Filter by the combination of ContactID and Status. Get all the linked transactions that have been assigned to a particular customer and have a particular status e.g. GET /LinkedTransactions?ContactID=4bb34b03-3378-4bb2-a0ed-6345abf3224e&Status=APPROVED.
Status string `json:"Status,omitempty" xml:"Status,omitempty"`
// This will always be BILLABLEEXPENSE. More types may be added in future.
Type string `json:"Type,omitempty" xml:"Type,omitempty"`
// The last modified date in UTC format
UpdatedDateUTC string `json:"UpdatedDateUTC,omitempty" xml:"-"`
// The Type of the source tranasction. This will be ACCPAY if the linked transaction was created from an invoice and SPEND if it was created from a bank transaction.
SourceTransactionTypeCode string `json:"SourceTransactionTypeCode,omitempty" xml:"SourceTransactionTypeCode,omitempty"`
}
//LinkedTransactions is a collection of LinkedTransactions
type LinkedTransactions struct {
LinkedTransactions []LinkedTransaction `json:"LinkedTransactions" xml:"LinkedTransaction"`
}
//The Xero API returns Dates based on the .Net JSON date format available at the time of development
//We need to convert these to a more usable format - RFC3339 for consistency with what the API expects to recieve
func (l *LinkedTransactions) convertDates() error {
var err error
for n := len(l.LinkedTransactions) - 1; n >= 0; n-- {
l.LinkedTransactions[n].UpdatedDateUTC, err = helpers.DotNetJSONTimeToRFC3339(l.LinkedTransactions[n].UpdatedDateUTC, true)
if err != nil {
return err
}
}
return nil
}
func unmarshalLinkedTransaction(linkedTransactionResponseBytes []byte) (*LinkedTransactions, error) {
var linkedTransactionResponse *LinkedTransactions
err := json.Unmarshal(linkedTransactionResponseBytes, &linkedTransactionResponse)
if err != nil {
return nil, err
}
err = linkedTransactionResponse.convertDates()
if err != nil {
return nil, err
}
return linkedTransactionResponse, err
}
//Create will create LinkedTransactions given an LinkedTransactions struct
func (l *LinkedTransactions) Create(provider *xerogolang.Provider, session goth.Session) (*LinkedTransactions, error) {
additionalHeaders := map[string]string{
"Accept": "application/json",
"Content-Type": "application/xml",
}
body, err := xml.MarshalIndent(l, " ", " ")
if err != nil {
return nil, err
}
linkedTransactionResponseBytes, err := provider.Create(session, "LinkedTransactions", additionalHeaders, body)
if err != nil {
return nil, err
}
return unmarshalLinkedTransaction(linkedTransactionResponseBytes)
}
//Update will update an LinkedTransaction given an LinkedTransactions struct
//This will only handle single LinkedTransaction - you cannot update multiple LinkedTransactions in a single call
//LinkedTransactions cannot be modified, only created and deleted.
func (l *LinkedTransactions) Update(provider *xerogolang.Provider, session goth.Session) (*LinkedTransactions, error) {
additionalHeaders := map[string]string{
"Accept": "application/json",
"Content-Type": "application/xml",
}
body, err := xml.MarshalIndent(l, " ", " ")
if err != nil {
return nil, err
}
LinkedTransactionResponseBytes, err := provider.Update(session, "LinkedTransactions/"+l.LinkedTransactions[0].LinkedTransactionID, additionalHeaders, body)
if err != nil {
return nil, err
}
return unmarshalLinkedTransaction(LinkedTransactionResponseBytes)
}
//FindLinkedTransactionsModifiedSince will get all LinkedTransactions modified after a specified date.
//additional querystringParameters such as page, SourceTransactionID, ContactID,
//Status, and TargetTransactionID can be added as a map
func FindLinkedTransactionsModifiedSince(provider *xerogolang.Provider, session goth.Session, modifiedSince time.Time, querystringParameters map[string]string) (*LinkedTransactions, error) {
additionalHeaders := map[string]string{
"Accept": "application/json",
}
if !modifiedSince.Equal(dayZero) {
additionalHeaders["If-Modified-Since"] = modifiedSince.Format(time.RFC3339)
}
linkedTransactionResponseBytes, err := provider.Find(session, "LinkedTransactions", additionalHeaders, querystringParameters)
if err != nil {
return nil, err
}
return unmarshalLinkedTransaction(linkedTransactionResponseBytes)
}
//FindLinkedTransactions will get all LinkedTransactions.
//additional querystringParameters such as page, SourceTransactionID, ContactID,
//Status, and TargetTransactionID can be added as a map
func FindLinkedTransactions(provider *xerogolang.Provider, session goth.Session, querystringParameters map[string]string) (*LinkedTransactions, error) {
return FindLinkedTransactionsModifiedSince(provider, session, dayZero, querystringParameters)
}
//FindLinkedTransaction will get a single LinkedTransaction - LinkedTransactionID must be a GUID for an LinkedTransaction
func FindLinkedTransaction(provider *xerogolang.Provider, session goth.Session, linkedTransactionID string) (*LinkedTransactions, error) {
additionalHeaders := map[string]string{
"Accept": "application/json",
}
linkedTransactionResponseBytes, err := provider.Find(session, "LinkedTransactions/"+linkedTransactionID, additionalHeaders, nil)
if err != nil {
return nil, err
}
return unmarshalLinkedTransaction(linkedTransactionResponseBytes)
}
//RemoveLinkedTransaction will get a single LinkedTransaction - LinkedTransactionID must be a GUID for an LinkedTransaction
func RemoveLinkedTransaction(provider *xerogolang.Provider, session goth.Session, linkedTransactionID string) (*LinkedTransactions, error) {
additionalHeaders := map[string]string{
"Accept": "application/json",
}
linkedTransactionResponseBytes, err := provider.Remove(session, "LinkedTransactions/"+linkedTransactionID, additionalHeaders)
if err != nil {
return nil, err
}
return unmarshalLinkedTransaction(linkedTransactionResponseBytes)
}
//GenerateExampleLinkedTransaction Creates an Example LinkedTransaction
func GenerateExampleLinkedTransaction(sourceTransactionID string, sourceLineItemID string, contactID string) *LinkedTransactions {
linkedTransaction := LinkedTransaction{
SourceTransactionID: sourceTransactionID,
SourceLineItemID: sourceLineItemID,
ContactID: contactID,
}
l := &LinkedTransactions{
LinkedTransactions: []LinkedTransaction{},
}
l.LinkedTransactions = append(l.LinkedTransactions, linkedTransaction)
return l
}