xero-kiwi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env.example +2 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +89 -0
- data/Rakefile +89 -0
- data/docs/accounting/address.md +54 -0
- data/docs/accounting/branding-theme.md +92 -0
- data/docs/accounting/contact-group.md +91 -0
- data/docs/accounting/contact.md +166 -0
- data/docs/accounting/credit-note.md +97 -0
- data/docs/accounting/external-link.md +33 -0
- data/docs/accounting/invoice.md +134 -0
- data/docs/accounting/organisation.md +119 -0
- data/docs/accounting/overpayment.md +94 -0
- data/docs/accounting/payment-terms.md +58 -0
- data/docs/accounting/payment.md +99 -0
- data/docs/accounting/phone.md +45 -0
- data/docs/accounting/prepayment.md +111 -0
- data/docs/accounting/user.md +109 -0
- data/docs/client.md +174 -0
- data/docs/connections.md +166 -0
- data/docs/errors.md +271 -0
- data/docs/getting-started.md +138 -0
- data/docs/oauth.md +508 -0
- data/docs/retries-and-rate-limits.md +224 -0
- data/docs/tokens.md +339 -0
- data/lib/xero_kiwi/accounting/address.rb +58 -0
- data/lib/xero_kiwi/accounting/allocation.rb +66 -0
- data/lib/xero_kiwi/accounting/branding_theme.rb +76 -0
- data/lib/xero_kiwi/accounting/contact.rb +153 -0
- data/lib/xero_kiwi/accounting/contact_group.rb +57 -0
- data/lib/xero_kiwi/accounting/contact_person.rb +45 -0
- data/lib/xero_kiwi/accounting/credit_note.rb +115 -0
- data/lib/xero_kiwi/accounting/external_link.rb +38 -0
- data/lib/xero_kiwi/accounting/invoice.rb +142 -0
- data/lib/xero_kiwi/accounting/line_item.rb +64 -0
- data/lib/xero_kiwi/accounting/organisation.rb +138 -0
- data/lib/xero_kiwi/accounting/overpayment.rb +107 -0
- data/lib/xero_kiwi/accounting/payment.rb +105 -0
- data/lib/xero_kiwi/accounting/payment_terms.rb +77 -0
- data/lib/xero_kiwi/accounting/phone.rb +46 -0
- data/lib/xero_kiwi/accounting/prepayment.rb +109 -0
- data/lib/xero_kiwi/accounting/tracking_category.rb +42 -0
- data/lib/xero_kiwi/accounting/user.rb +80 -0
- data/lib/xero_kiwi/client.rb +576 -0
- data/lib/xero_kiwi/connection.rb +78 -0
- data/lib/xero_kiwi/errors.rb +34 -0
- data/lib/xero_kiwi/identity.rb +40 -0
- data/lib/xero_kiwi/oauth/id_token.rb +102 -0
- data/lib/xero_kiwi/oauth/pkce.rb +51 -0
- data/lib/xero_kiwi/oauth.rb +232 -0
- data/lib/xero_kiwi/token.rb +99 -0
- data/lib/xero_kiwi/token_refresher.rb +53 -0
- data/lib/xero_kiwi/version.rb +5 -0
- data/lib/xero_kiwi.rb +33 -0
- data/llms-full.txt +3351 -0
- data/llms.txt +56 -0
- data/sig/xero_kiwi.rbs +4 -0
- metadata +164 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Credit Notes
|
|
2
|
+
|
|
3
|
+
A Xero **credit note** is a document that reduces the amount owed on an
|
|
4
|
+
invoice. Credit notes can be applied (allocated) to outstanding invoices. You
|
|
5
|
+
need a `tenant_id` from a [connection](../connections.md) before you can fetch
|
|
6
|
+
credit notes.
|
|
7
|
+
|
|
8
|
+
> See: [Xero docs — Credit Notes](https://developer.xero.com/documentation/api/accounting/creditnotes)
|
|
9
|
+
|
|
10
|
+
## Listing credit notes
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
client = XeroKiwi::Client.new(access_token: "ya29...")
|
|
14
|
+
|
|
15
|
+
# Pass a tenant ID string…
|
|
16
|
+
credit_notes = client.credit_notes("70784a63-d24b-46a9-a4db-0e70a274b056")
|
|
17
|
+
|
|
18
|
+
# …or a XeroKiwi::Connection (its tenant_id is used automatically).
|
|
19
|
+
connection = client.connections.first
|
|
20
|
+
credit_notes = client.credit_notes(connection)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`client.credit_notes` hits `GET /api.xro/2.0/CreditNotes` with the
|
|
24
|
+
`Xero-Tenant-Id` header set to the tenant you specify. It returns an
|
|
25
|
+
`Array<XeroKiwi::Accounting::CreditNote>`.
|
|
26
|
+
|
|
27
|
+
## Fetching a single credit note
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
cn = client.credit_note(tenant_id, "aea95d78-ea48-456b-9b08-6bc012600072")
|
|
31
|
+
cn.total # => 100.00
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`client.credit_note` hits `GET /api.xro/2.0/CreditNotes/{CreditNoteID}` and
|
|
35
|
+
returns a single `XeroKiwi::Accounting::CreditNote`, or `nil` if the response is
|
|
36
|
+
empty. The single-credit-note response includes full line item details.
|
|
37
|
+
|
|
38
|
+
## The CreditNote object
|
|
39
|
+
|
|
40
|
+
Each `XeroKiwi::Accounting::CreditNote` is an immutable value object exposing the
|
|
41
|
+
fields Xero returns:
|
|
42
|
+
|
|
43
|
+
| Attribute | Type | What it is |
|
|
44
|
+
|-----------|------|------------|
|
|
45
|
+
| `credit_note_id` | `String` | The unique Xero identifier. |
|
|
46
|
+
| `credit_note_number` | `String` | The credit note number (e.g. `"CN-0002"`). |
|
|
47
|
+
| `type` | `String` | `"ACCRECCREDIT"` (accounts receivable) or `"ACCPAYCREDIT"` (accounts payable). |
|
|
48
|
+
| `contact` | `XeroKiwi::Accounting::Contact` | The contact (reference — use `contact.reference?` to check). See [Contacts](contact.md). |
|
|
49
|
+
| `date` | `Time` | The date the credit note was issued, parsed as UTC. |
|
|
50
|
+
| `status` | `String` | e.g. `"DRAFT"`, `"SUBMITTED"`, `"AUTHORISED"`, `"PAID"`, `"VOIDED"`. |
|
|
51
|
+
| `line_amount_types` | `String` | `"Inclusive"`, `"Exclusive"`, or `"NoTax"`. |
|
|
52
|
+
| `line_items` | `Array<XeroKiwi::Accounting::LineItem>` | The line items. See [Prepayments — LineItem](prepayment.md#the-lineitem-object). |
|
|
53
|
+
| `sub_total` | `Numeric` | The subtotal excluding taxes. |
|
|
54
|
+
| `total_tax` | `Numeric` | The total tax amount. |
|
|
55
|
+
| `total` | `Numeric` | The total (subtotal + total tax). |
|
|
56
|
+
| `cis_deduction` | `Numeric` | CIS deduction (UK Construction Industry Scheme only). |
|
|
57
|
+
| `updated_date_utc` | `Time` | When the credit note was last modified, parsed as UTC. |
|
|
58
|
+
| `currency_code` | `String` | The currency code (e.g. `"NZD"`). |
|
|
59
|
+
| `currency_rate` | `Numeric` | The currency rate (1.0 for base currency). |
|
|
60
|
+
| `fully_paid_on_date` | `Time` | When the credit note was fully allocated, parsed as UTC. |
|
|
61
|
+
| `reference` | `String` | Additional reference number (ACCRECCREDIT only). |
|
|
62
|
+
| `sent_to_contact` | `Boolean` | Whether the credit note has been sent to the contact. |
|
|
63
|
+
| `remaining_credit` | `Numeric` | The remaining credit balance. |
|
|
64
|
+
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each allocation has an `invoice` reference. |
|
|
65
|
+
| `branding_theme_id` | `String` | The branding theme ID applied to the credit note. |
|
|
66
|
+
| `has_attachments` | `Boolean` | Whether the credit note has attachments. |
|
|
67
|
+
|
|
68
|
+
## Predicates
|
|
69
|
+
|
|
70
|
+
```ruby
|
|
71
|
+
cn.accounts_receivable? # type == "ACCRECCREDIT"
|
|
72
|
+
cn.accounts_payable? # type == "ACCPAYCREDIT"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Equality and hashing
|
|
76
|
+
|
|
77
|
+
Two credit notes are `==` if they share the same `credit_note_id`. `#hash` is
|
|
78
|
+
consistent with `==`, so credit notes work as hash keys and in sets.
|
|
79
|
+
|
|
80
|
+
## Error behaviour
|
|
81
|
+
|
|
82
|
+
| HTTP status | Exception | What it usually means |
|
|
83
|
+
|-------------|-----------|------------------------|
|
|
84
|
+
| 200 | (none — returns credit notes) | Success |
|
|
85
|
+
| 401 | `XeroKiwi::AuthenticationError` | Access token is invalid or expired |
|
|
86
|
+
| 403 | `XeroKiwi::ClientError` | The token doesn't have the required scope |
|
|
87
|
+
| 404 | `XeroKiwi::ClientError` | The credit note ID doesn't exist |
|
|
88
|
+
|
|
89
|
+
## Common patterns
|
|
90
|
+
|
|
91
|
+
### Listing credit notes with remaining credit
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
credit_notes = client.credit_notes(tenant_id)
|
|
95
|
+
with_credit = credit_notes.select { |cn| cn.remaining_credit.to_f > 0 }
|
|
96
|
+
with_credit.each { |cn| puts "#{cn.credit_note_number}: #{cn.remaining_credit} remaining" }
|
|
97
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# XeroKiwi::Accounting::ExternalLink
|
|
2
|
+
|
|
3
|
+
A Xero external link (social or web profile). Used by
|
|
4
|
+
[Organisation](organisation.md).
|
|
5
|
+
|
|
6
|
+
> See: [Xero docs — External link types](https://developer.xero.com/documentation/api/accounting/types#externallinks)
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
org.external_links.each do |link|
|
|
12
|
+
puts "#{link.link_type}: #{link.url}"
|
|
13
|
+
end
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Attributes
|
|
17
|
+
|
|
18
|
+
| Attribute | Type | Notes |
|
|
19
|
+
|-----------|------|-------|
|
|
20
|
+
| `link_type` | `String` | `"Facebook"`, `"GooglePlus"`, `"LinkedIn"`, `"Twitter"`, or `"Website"` |
|
|
21
|
+
| `url` | `String` | The URL for the service |
|
|
22
|
+
|
|
23
|
+
## Equality
|
|
24
|
+
|
|
25
|
+
Two external links are `==` if all their attributes match. `#hash` is
|
|
26
|
+
consistent with `==`.
|
|
27
|
+
|
|
28
|
+
## Serialisation
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
link.to_h
|
|
32
|
+
# => { link_type: "Facebook", url: "https://facebook.com/example" }
|
|
33
|
+
```
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Invoices
|
|
2
|
+
|
|
3
|
+
A Xero **invoice** is either a sales invoice (accounts receivable, `ACCREC`) or
|
|
4
|
+
a purchase bill (accounts payable, `ACCPAY`). Invoices carry line items,
|
|
5
|
+
payments, credit notes, and allocation details. You need a `tenant_id` from a
|
|
6
|
+
[connection](../connections.md) before you can fetch invoices.
|
|
7
|
+
|
|
8
|
+
> See: [Xero docs — Invoices](https://developer.xero.com/documentation/api/accounting/invoices)
|
|
9
|
+
|
|
10
|
+
## Listing invoices
|
|
11
|
+
|
|
12
|
+
```ruby
|
|
13
|
+
client = XeroKiwi::Client.new(access_token: "ya29...")
|
|
14
|
+
|
|
15
|
+
# Pass a tenant ID string…
|
|
16
|
+
invoices = client.invoices("70784a63-d24b-46a9-a4db-0e70a274b056")
|
|
17
|
+
|
|
18
|
+
# …or a XeroKiwi::Connection (its tenant_id is used automatically).
|
|
19
|
+
connection = client.connections.first
|
|
20
|
+
invoices = client.invoices(connection)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`client.invoices` hits `GET /api.xro/2.0/Invoices` with the `Xero-Tenant-Id`
|
|
24
|
+
header set to the tenant you specify. It returns an
|
|
25
|
+
`Array<XeroKiwi::Accounting::Invoice>`.
|
|
26
|
+
|
|
27
|
+
**Note:** The list response returns only a summary of each contact and no line
|
|
28
|
+
items. Fetch an individual invoice for full details including line items.
|
|
29
|
+
|
|
30
|
+
## Fetching a single invoice
|
|
31
|
+
|
|
32
|
+
```ruby
|
|
33
|
+
inv = client.invoice(tenant_id, "243216c5-369e-4056-ac67-05388f86dc81")
|
|
34
|
+
inv.total # => "2025.00"
|
|
35
|
+
inv.invoice_number # => "OIT00546"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`client.invoice` hits `GET /api.xro/2.0/Invoices/{InvoiceID}` and returns a
|
|
39
|
+
single `XeroKiwi::Accounting::Invoice`, or `nil` if the response is empty.
|
|
40
|
+
|
|
41
|
+
## The Invoice object
|
|
42
|
+
|
|
43
|
+
Each `XeroKiwi::Accounting::Invoice` is an immutable value object. The fields below
|
|
44
|
+
cover both the list and single-invoice responses:
|
|
45
|
+
|
|
46
|
+
| Attribute | Type | What it is |
|
|
47
|
+
|-----------|------|------------|
|
|
48
|
+
| `invoice_id` | `String` | The unique Xero identifier. |
|
|
49
|
+
| `invoice_number` | `String` | The invoice number (e.g. `"OIT00546"`). |
|
|
50
|
+
| `type` | `String` | `"ACCREC"` (sales) or `"ACCPAY"` (bills). |
|
|
51
|
+
| `contact` | `XeroKiwi::Accounting::Contact` | The contact (reference — use `contact.reference?` to check). See [Contacts](contact.md). |
|
|
52
|
+
| `date` | `Time` | The invoice date, parsed as UTC. |
|
|
53
|
+
| `due_date` | `Time` | The due date, parsed as UTC. |
|
|
54
|
+
| `status` | `String` | e.g. `"DRAFT"`, `"SUBMITTED"`, `"AUTHORISED"`, `"PAID"`, `"VOIDED"`, `"DELETED"`. |
|
|
55
|
+
| `line_amount_types` | `String` | `"Inclusive"`, `"Exclusive"`, or `"NoTax"`. |
|
|
56
|
+
| `line_items` | `Array<XeroKiwi::Accounting::LineItem>` | The line items (empty on list, populated on single). See [Prepayments — LineItem](prepayment.md#the-lineitem-object). |
|
|
57
|
+
| `sub_total` | `String/Numeric` | The subtotal excluding taxes. |
|
|
58
|
+
| `total_tax` | `String/Numeric` | The total tax amount. |
|
|
59
|
+
| `total` | `String/Numeric` | The total (subtotal + total tax). |
|
|
60
|
+
| `total_discount` | `String/Numeric` | Total discounts on line items. |
|
|
61
|
+
| `updated_date_utc` | `Time` | When the invoice was last modified, parsed as UTC. |
|
|
62
|
+
| `currency_code` | `String` | The currency code (e.g. `"NZD"`). |
|
|
63
|
+
| `currency_rate` | `Numeric` | The currency rate (1.0 for base currency). |
|
|
64
|
+
| `reference` | `String` | Additional reference number (ACCREC only). |
|
|
65
|
+
| `branding_theme_id` | `String` | The branding theme ID. |
|
|
66
|
+
| `url` | `String` | URL link to a source document. |
|
|
67
|
+
| `sent_to_contact` | `Boolean` | Whether the invoice displays as "sent" in Xero. |
|
|
68
|
+
| `expected_payment_date` | `Time` | Expected payment date (ACCREC only). |
|
|
69
|
+
| `planned_payment_date` | `Time` | Planned payment date (ACCPAY only). |
|
|
70
|
+
| `has_attachments` | `Boolean` | Whether the invoice has attachments. |
|
|
71
|
+
| `repeating_invoice_id` | `String` | The repeating invoice template ID, if applicable. |
|
|
72
|
+
| `payments` | `Array<XeroKiwi::Accounting::Payment>` | Payment records (references). See [Payments](payment.md). |
|
|
73
|
+
| `credit_notes` | `Array<Hash>` | Credit notes applied (raw hashes). |
|
|
74
|
+
| `prepayments` | `Array<Hash>` | Prepayments applied (raw hashes). |
|
|
75
|
+
| `overpayments` | `Array<Hash>` | Overpayments applied (raw hashes). |
|
|
76
|
+
| `amount_due` | `String/Numeric` | Amount remaining to be paid. |
|
|
77
|
+
| `amount_paid` | `String/Numeric` | Sum of payments received. |
|
|
78
|
+
| `amount_credited` | `String/Numeric` | Sum of credit notes, overpayments, and prepayments applied. |
|
|
79
|
+
| `cis_deduction` | `Numeric` | CIS deduction (UK Construction Industry Scheme only). |
|
|
80
|
+
| `fully_paid_on_date` | `Time` | When the invoice was fully paid, parsed as UTC. |
|
|
81
|
+
| `sales_tax_calculation_type_code` | `String` | US auto sales tax calculation type. |
|
|
82
|
+
| `invoice_addresses` | `Array<Hash>` | Invoice addresses (US auto sales tax only). |
|
|
83
|
+
|
|
84
|
+
## Predicates
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
inv.accounts_receivable? # type == "ACCREC"
|
|
88
|
+
inv.accounts_payable? # type == "ACCPAY"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Equality and hashing
|
|
92
|
+
|
|
93
|
+
Two invoices are `==` if they share the same `invoice_id`. `#hash` is consistent
|
|
94
|
+
with `==`, so invoices work as hash keys and in sets.
|
|
95
|
+
|
|
96
|
+
## Error behaviour
|
|
97
|
+
|
|
98
|
+
| HTTP status | Exception | What it usually means |
|
|
99
|
+
|-------------|-----------|------------------------|
|
|
100
|
+
| 200 | (none — returns invoices) | Success |
|
|
101
|
+
| 401 | `XeroKiwi::AuthenticationError` | Access token is invalid or expired |
|
|
102
|
+
| 403 | `XeroKiwi::ClientError` | The token doesn't have the required scope |
|
|
103
|
+
| 404 | `XeroKiwi::ClientError` | The invoice ID doesn't exist |
|
|
104
|
+
|
|
105
|
+
## Common patterns
|
|
106
|
+
|
|
107
|
+
### Retrieving the online invoice URL
|
|
108
|
+
|
|
109
|
+
For sales (ACCREC) invoices that are not in DRAFT status, you can retrieve the
|
|
110
|
+
online invoice URL that customers can use to view and pay:
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
url = client.online_invoice_url(tenant_id, "243216c5-369e-4056-ac67-05388f86dc81")
|
|
114
|
+
puts url # => "https://in.xero.com/iztKMjyAEJT7MVnmruxgCdIJUDStfRgmtdQSIW13"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Returns `nil` if no online invoice URL is available.
|
|
118
|
+
|
|
119
|
+
### Listing outstanding invoices
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
invoices = client.invoices(tenant_id)
|
|
123
|
+
outstanding = invoices.select { |inv| inv.amount_due.to_f > 0 }
|
|
124
|
+
outstanding.each { |inv| puts "#{inv.invoice_number}: #{inv.amount_due} due" }
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Fetching an invoice with full line items
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
inv = client.invoice(tenant_id, "243216c5-369e-4056-ac67-05388f86dc81")
|
|
131
|
+
inv.line_items.each do |li|
|
|
132
|
+
puts " #{li.description}: #{li.line_amount}"
|
|
133
|
+
end
|
|
134
|
+
```
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Organisation
|
|
2
|
+
|
|
3
|
+
A Xero **organisation** is the actual accounting entity — the company, sole
|
|
4
|
+
trader, trust, etc. that owns the books. You need a `tenant_id` from a
|
|
5
|
+
[connection](../connections.md) before you can fetch one.
|
|
6
|
+
|
|
7
|
+
> See: [Xero docs — Organisation](https://developer.xero.com/documentation/api/accounting/organisation)
|
|
8
|
+
|
|
9
|
+
## Fetching an organisation
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
client = XeroKiwi::Client.new(access_token: "ya29...")
|
|
13
|
+
|
|
14
|
+
# Pass a tenant ID string…
|
|
15
|
+
org = client.organisation("70784a63-d24b-46a9-a4db-0e70a274b056")
|
|
16
|
+
|
|
17
|
+
# …or a XeroKiwi::Connection (its tenant_id is used automatically).
|
|
18
|
+
connection = client.connections.first
|
|
19
|
+
org = client.organisation(connection)
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`client.organisation` hits `GET /api.xro/2.0/Organisation` with the
|
|
23
|
+
`Xero-Tenant-Id` header set to the tenant you specify. It returns a single
|
|
24
|
+
`XeroKiwi::Accounting::Organisation`.
|
|
25
|
+
|
|
26
|
+
## The Organisation object
|
|
27
|
+
|
|
28
|
+
Each `XeroKiwi::Accounting::Organisation` is an immutable value object exposing the fields
|
|
29
|
+
Xero returns:
|
|
30
|
+
|
|
31
|
+
| Attribute | Type | What it is |
|
|
32
|
+
|-----------|------|------------|
|
|
33
|
+
| `organisation_id` | `String` | The unique identifier for the organisation. |
|
|
34
|
+
| `api_key` | `String` | The API key (if set). |
|
|
35
|
+
| `name` | `String` | The display name (e.g. "Maple Florists Ltd"). |
|
|
36
|
+
| `legal_name` | `String` | The registered legal name. |
|
|
37
|
+
| `pays_tax` | `Boolean` | Whether the organisation is registered for tax. |
|
|
38
|
+
| `version` | `String` | The Xero edition version code (e.g. `"NZ"`, `"GLOBAL"`). |
|
|
39
|
+
| `organisation_type` | `String` | The type — `"COMPANY"`, `"SOLE_TRADER"`, `"TRUST"`, etc. |
|
|
40
|
+
| `base_currency` | `String` | The base currency code (e.g. `"NZD"`, `"ZAR"`). |
|
|
41
|
+
| `country_code` | `String` | The two-letter country code (e.g. `"NZ"`, `"ZA"`). |
|
|
42
|
+
| `is_demo_company` | `Boolean` | Whether this is a Xero demo company. |
|
|
43
|
+
| `organisation_status` | `String` | `"ACTIVE"` or otherwise. |
|
|
44
|
+
| `registration_number` | `String` | The company registration number. |
|
|
45
|
+
| `employer_identification_number` | `String` | The EIN (US organisations). |
|
|
46
|
+
| `tax_number` | `String` | The tax/VAT number. |
|
|
47
|
+
| `financial_year_end_day` | `Integer` | Day of month the financial year ends (1–31). |
|
|
48
|
+
| `financial_year_end_month` | `Integer` | Month the financial year ends (1–12). |
|
|
49
|
+
| `sales_tax_basis` | `String` | e.g. `"Payments"`, `"CASH"`, `"ACCRUALS"`. |
|
|
50
|
+
| `sales_tax_period` | `String` | e.g. `"TWOMONTHS"`, `"MONTHLY"`. |
|
|
51
|
+
| `default_sales_tax` | `String` | e.g. `"Tax Exclusive"`. |
|
|
52
|
+
| `default_purchases_tax` | `String` | e.g. `"Tax Exclusive"`. |
|
|
53
|
+
| `period_lock_date` | `Time` | The period lock date, parsed as UTC. |
|
|
54
|
+
| `end_of_year_lock_date` | `Time` | The end-of-year lock date, parsed as UTC. |
|
|
55
|
+
| `created_date_utc` | `Time` | When the organisation was created, parsed as UTC. |
|
|
56
|
+
| `timezone` | `String` | The organisation's timezone code (e.g. `"NEWZEALANDSTANDARDTIME"`). |
|
|
57
|
+
| `organisation_entity_type` | `String` | The entity type (e.g. `"COMPANY"`). |
|
|
58
|
+
| `short_code` | `String` | The Xero short code for this organisation. |
|
|
59
|
+
| `organisation_class` | `String` | The Xero subscription class (e.g. `"PREMIUM"`, `"STARTER"`). |
|
|
60
|
+
| `edition` | `String` | The Xero subscription edition (e.g. `"BUSINESS"`). |
|
|
61
|
+
| `line_of_business` | `String` | The industry / line of business. |
|
|
62
|
+
| `addresses` | `Array<XeroKiwi::Accounting::Address>` | The organisation's addresses. See [Address](address.md). |
|
|
63
|
+
| `phones` | `Array<XeroKiwi::Accounting::Phone>` | The organisation's phone numbers. See [Phone](phone.md). |
|
|
64
|
+
| `external_links` | `Array<XeroKiwi::Accounting::ExternalLink>` | Social/web profile links. See [ExternalLink](external-link.md). |
|
|
65
|
+
| `payment_terms` | `XeroKiwi::Accounting::PaymentTerms` | Default payment terms for bills and sales. See [PaymentTerms](payment-terms.md). |
|
|
66
|
+
|
|
67
|
+
## Predicates
|
|
68
|
+
|
|
69
|
+
```ruby
|
|
70
|
+
org.demo_company? # is_demo_company == true
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Equality and hashing
|
|
74
|
+
|
|
75
|
+
Two organisations are `==` if they share the same `organisation_id`. `#hash`
|
|
76
|
+
is consistent with `==`, so organisations work as hash keys and in sets.
|
|
77
|
+
|
|
78
|
+
## Date parsing
|
|
79
|
+
|
|
80
|
+
The Xero Accounting API serialises timestamps differently from the Connections
|
|
81
|
+
API. Connections use ISO 8601 strings (e.g. `"2019-07-09T23:40:30.1833130"`),
|
|
82
|
+
but the Accounting API (including Organisation) uses the legacy .NET JSON
|
|
83
|
+
format: `/Date(1574275974000)/`.
|
|
84
|
+
|
|
85
|
+
XeroKiwi handles both transparently — all `Time` attributes are parsed to UTC
|
|
86
|
+
`Time` objects regardless of which format Xero sends. You don't need to think
|
|
87
|
+
about this unless you're looking at raw cassette data or debugging timestamp
|
|
88
|
+
issues.
|
|
89
|
+
|
|
90
|
+
## Error behaviour
|
|
91
|
+
|
|
92
|
+
| HTTP status | Exception | What it usually means |
|
|
93
|
+
|-------------|-----------|------------------------|
|
|
94
|
+
| 200 | (none — returns the organisation) | Success |
|
|
95
|
+
| 401 | `XeroKiwi::AuthenticationError` | Access token is invalid or expired |
|
|
96
|
+
| 403 | `XeroKiwi::ClientError` | The token doesn't have the `accounting.settings.read` scope |
|
|
97
|
+
| 404 | `XeroKiwi::ClientError` | The tenant ID doesn't correspond to an organisation |
|
|
98
|
+
|
|
99
|
+
## Common patterns
|
|
100
|
+
|
|
101
|
+
### From connection to organisation
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
client = XeroKiwi::Client.new(access_token: "ya29...")
|
|
105
|
+
|
|
106
|
+
client.connections.each do |conn|
|
|
107
|
+
org = client.organisation(conn)
|
|
108
|
+
puts "#{org.name} (#{org.base_currency}) — #{org.country_code}"
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Checking if it's a demo company
|
|
113
|
+
|
|
114
|
+
```ruby
|
|
115
|
+
org = client.organisation(tenant_id)
|
|
116
|
+
if org.demo_company?
|
|
117
|
+
puts "This is a demo company — data isn't real"
|
|
118
|
+
end
|
|
119
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Overpayments
|
|
2
|
+
|
|
3
|
+
A Xero **overpayment** is an excess payment received or made beyond the amount
|
|
4
|
+
of an invoice. Overpayments are created via the BankTransactions endpoint and
|
|
5
|
+
refunded via the Payments endpoint. This resource lets you retrieve overpayments
|
|
6
|
+
and their allocations. You need a `tenant_id` from a
|
|
7
|
+
[connection](../connections.md) before you can fetch overpayments.
|
|
8
|
+
|
|
9
|
+
> See: [Xero docs — Overpayments](https://developer.xero.com/documentation/api/accounting/overpayments)
|
|
10
|
+
|
|
11
|
+
## Listing overpayments
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
client = XeroKiwi::Client.new(access_token: "ya29...")
|
|
15
|
+
|
|
16
|
+
# Pass a tenant ID string…
|
|
17
|
+
overpayments = client.overpayments("70784a63-d24b-46a9-a4db-0e70a274b056")
|
|
18
|
+
|
|
19
|
+
# …or a XeroKiwi::Connection (its tenant_id is used automatically).
|
|
20
|
+
connection = client.connections.first
|
|
21
|
+
overpayments = client.overpayments(connection)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`client.overpayments` hits `GET /api.xro/2.0/Overpayments` with the
|
|
25
|
+
`Xero-Tenant-Id` header set to the tenant you specify. It returns an
|
|
26
|
+
`Array<XeroKiwi::Accounting::Overpayment>`.
|
|
27
|
+
|
|
28
|
+
## Fetching a single overpayment
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
op = client.overpayment(tenant_id, "aea95d78-ea48-456b-9b08-6bc012600072")
|
|
32
|
+
op.total # => "100.00"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`client.overpayment` hits `GET /api.xro/2.0/Overpayments/{OverpaymentID}` and
|
|
36
|
+
returns a single `XeroKiwi::Accounting::Overpayment`, or `nil` if the response is
|
|
37
|
+
empty.
|
|
38
|
+
|
|
39
|
+
## The Overpayment object
|
|
40
|
+
|
|
41
|
+
Each `XeroKiwi::Accounting::Overpayment` is an immutable value object exposing the
|
|
42
|
+
fields Xero returns:
|
|
43
|
+
|
|
44
|
+
| Attribute | Type | What it is |
|
|
45
|
+
|-----------|------|------------|
|
|
46
|
+
| `overpayment_id` | `String` | The unique Xero identifier. |
|
|
47
|
+
| `type` | `String` | `"RECEIVE-OVERPAYMENT"` or `"SPEND-OVERPAYMENT"`. |
|
|
48
|
+
| `contact` | `XeroKiwi::Accounting::Contact` | The contact (reference — use `contact.reference?` to check). See [Contacts](contact.md). |
|
|
49
|
+
| `date` | `Time` | The date the overpayment was made, parsed as UTC. |
|
|
50
|
+
| `status` | `String` | e.g. `"AUTHORISED"`, `"PAID"`, `"VOIDED"`. |
|
|
51
|
+
| `line_amount_types` | `String` | `"Inclusive"`, `"Exclusive"`, or `"NoTax"`. |
|
|
52
|
+
| `line_items` | `Array<XeroKiwi::Accounting::LineItem>` | The line items. See [Prepayments — LineItem](prepayment.md#the-lineitem-object). |
|
|
53
|
+
| `sub_total` | `String` | The subtotal excluding taxes. |
|
|
54
|
+
| `total_tax` | `String` | The total tax amount. |
|
|
55
|
+
| `total` | `String` | The total (subtotal + total tax). |
|
|
56
|
+
| `updated_date_utc` | `Time` | When the overpayment was last modified, parsed as UTC. |
|
|
57
|
+
| `currency_code` | `String` | The currency code (e.g. `"NZD"`). |
|
|
58
|
+
| `currency_rate` | `String` | The currency rate (1.0 for base currency). |
|
|
59
|
+
| `remaining_credit` | `String` | The remaining credit balance. |
|
|
60
|
+
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each allocation has an `invoice` reference. |
|
|
61
|
+
| `payments` | `Array<XeroKiwi::Accounting::Payment>` | Payment records (references). See [Payments](payment.md). |
|
|
62
|
+
| `has_attachments` | `Boolean` | Whether the overpayment has attachments. |
|
|
63
|
+
| `reference` | `String` | Reference for the overpayment. |
|
|
64
|
+
|
|
65
|
+
## Predicates
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
op.receive? # type == "RECEIVE-OVERPAYMENT"
|
|
69
|
+
op.spend? # type == "SPEND-OVERPAYMENT"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Equality and hashing
|
|
73
|
+
|
|
74
|
+
Two overpayments are `==` if they share the same `overpayment_id`. `#hash` is
|
|
75
|
+
consistent with `==`, so overpayments work as hash keys and in sets.
|
|
76
|
+
|
|
77
|
+
## Error behaviour
|
|
78
|
+
|
|
79
|
+
| HTTP status | Exception | What it usually means |
|
|
80
|
+
|-------------|-----------|------------------------|
|
|
81
|
+
| 200 | (none — returns overpayments) | Success |
|
|
82
|
+
| 401 | `XeroKiwi::AuthenticationError` | Access token is invalid or expired |
|
|
83
|
+
| 403 | `XeroKiwi::ClientError` | The token doesn't have the required scope |
|
|
84
|
+
| 404 | `XeroKiwi::ClientError` | The overpayment ID doesn't exist |
|
|
85
|
+
|
|
86
|
+
## Common patterns
|
|
87
|
+
|
|
88
|
+
### Listing overpayments with remaining credit
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
overpayments = client.overpayments(tenant_id)
|
|
92
|
+
with_credit = overpayments.select { |op| op.remaining_credit.to_f > 0 }
|
|
93
|
+
with_credit.each { |op| puts "#{op.overpayment_id}: #{op.remaining_credit} remaining" }
|
|
94
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# XeroKiwi::Accounting::PaymentTerms
|
|
2
|
+
|
|
3
|
+
Default payment terms for an organisation or contact, containing separate
|
|
4
|
+
terms for bills (accounts payable) and sales invoices (accounts receivable).
|
|
5
|
+
|
|
6
|
+
> See: [Xero docs — Payment terms](https://developer.xero.com/documentation/api/accounting/types#paymentterms)
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
if org.payment_terms
|
|
12
|
+
bills = org.payment_terms.bills
|
|
13
|
+
sales = org.payment_terms.sales
|
|
14
|
+
|
|
15
|
+
puts "Bills due: day #{bills.day} (#{bills.type})" if bills
|
|
16
|
+
puts "Sales due: day #{sales.day} (#{sales.type})" if sales
|
|
17
|
+
end
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## PaymentTerms attributes
|
|
21
|
+
|
|
22
|
+
| Attribute | Type | Notes |
|
|
23
|
+
|-----------|------|-------|
|
|
24
|
+
| `bills` | `XeroKiwi::Accounting::PaymentTerm` | Default terms for accounts payable. `nil` if not configured. |
|
|
25
|
+
| `sales` | `XeroKiwi::Accounting::PaymentTerm` | Default terms for accounts receivable. `nil` if not configured. |
|
|
26
|
+
|
|
27
|
+
`PaymentTerms` itself is `nil` on the parent object when the organisation or
|
|
28
|
+
contact has no payment terms configured at all.
|
|
29
|
+
|
|
30
|
+
## PaymentTerm attributes
|
|
31
|
+
|
|
32
|
+
Each side (bills or sales) is a `XeroKiwi::Accounting::PaymentTerm`:
|
|
33
|
+
|
|
34
|
+
| Attribute | Type | Notes |
|
|
35
|
+
|-----------|------|-------|
|
|
36
|
+
| `day` | `Integer` | Day of month (0–31) |
|
|
37
|
+
| `type` | `String` | The payment term type (see below) |
|
|
38
|
+
|
|
39
|
+
### Payment term types
|
|
40
|
+
|
|
41
|
+
| Type | Meaning |
|
|
42
|
+
|------|---------|
|
|
43
|
+
| `DAYSAFTERBILLDATE` | Day(s) after bill date |
|
|
44
|
+
| `DAYSAFTERBILLMONTH` | Day(s) after bill month |
|
|
45
|
+
| `OFCURRENTMONTH` | Of the current month |
|
|
46
|
+
| `OFFOLLOWINGMONTH` | Of the following month |
|
|
47
|
+
|
|
48
|
+
## Equality
|
|
49
|
+
|
|
50
|
+
Two `PaymentTerms` are `==` if both their `bills` and `sales` are equal. Two
|
|
51
|
+
`PaymentTerm` objects are `==` if they share the same `day` and `type`.
|
|
52
|
+
|
|
53
|
+
## Serialisation
|
|
54
|
+
|
|
55
|
+
```ruby
|
|
56
|
+
org.payment_terms.to_h
|
|
57
|
+
# => { bills: { day: 15, type: "OFCURRENTMONTH" }, sales: { day: 20, type: "OFFOLLOWINGMONTH" } }
|
|
58
|
+
```
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Payments
|
|
2
|
+
|
|
3
|
+
A Xero **payment** records money received or paid against an invoice, credit
|
|
4
|
+
note, prepayment, or overpayment. Payments can be applied to approved AR and AP
|
|
5
|
+
invoices, and used to refund credit notes, prepayments, and overpayments. You
|
|
6
|
+
need a `tenant_id` from a [connection](../connections.md) before you can fetch
|
|
7
|
+
payments.
|
|
8
|
+
|
|
9
|
+
> See: [Xero docs — Payments](https://developer.xero.com/documentation/api/accounting/payments)
|
|
10
|
+
|
|
11
|
+
## Listing payments
|
|
12
|
+
|
|
13
|
+
```ruby
|
|
14
|
+
client = XeroKiwi::Client.new(access_token: "ya29...")
|
|
15
|
+
|
|
16
|
+
# Pass a tenant ID string…
|
|
17
|
+
payments = client.payments("70784a63-d24b-46a9-a4db-0e70a274b056")
|
|
18
|
+
|
|
19
|
+
# …or a XeroKiwi::Connection (its tenant_id is used automatically).
|
|
20
|
+
connection = client.connections.first
|
|
21
|
+
payments = client.payments(connection)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`client.payments` hits `GET /api.xro/2.0/Payments` with the `Xero-Tenant-Id`
|
|
25
|
+
header set to the tenant you specify. It returns an
|
|
26
|
+
`Array<XeroKiwi::Accounting::Payment>`.
|
|
27
|
+
|
|
28
|
+
## Fetching a single payment
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
payment = client.payment(tenant_id, "b26fd49a-cbae-470a-a8f8-bcbc119e0379")
|
|
32
|
+
payment.amount # => 500.00
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
`client.payment` hits `GET /api.xro/2.0/Payments/{PaymentID}` and returns a
|
|
36
|
+
single `XeroKiwi::Accounting::Payment`, or `nil` if the response is empty.
|
|
37
|
+
|
|
38
|
+
## The Payment object
|
|
39
|
+
|
|
40
|
+
Each `XeroKiwi::Accounting::Payment` is an immutable value object exposing the
|
|
41
|
+
fields Xero returns:
|
|
42
|
+
|
|
43
|
+
| Attribute | Type | What it is |
|
|
44
|
+
|-----------|------|------------|
|
|
45
|
+
| `payment_id` | `String` | The unique Xero identifier. |
|
|
46
|
+
| `date` | `Time` | The date the payment was made, parsed as UTC. |
|
|
47
|
+
| `currency_rate` | `Numeric` | Exchange rate (1.0 for base currency). |
|
|
48
|
+
| `amount` | `Numeric` | The payment amount in the invoice's currency. |
|
|
49
|
+
| `bank_amount` | `Numeric` | The payment amount in the account's currency. |
|
|
50
|
+
| `reference` | `String` | An optional description for the payment. |
|
|
51
|
+
| `is_reconciled` | `Boolean` | Whether the payment has been reconciled. |
|
|
52
|
+
| `status` | `String` | e.g. `"AUTHORISED"`, `"DELETED"`. |
|
|
53
|
+
| `payment_type` | `String` | e.g. `"ACCRECPAYMENT"`, `"ACCPAYPAYMENT"`. See Xero docs for all types. |
|
|
54
|
+
| `updated_date_utc` | `Time` | When the payment was last modified, parsed as UTC. |
|
|
55
|
+
| `batch_payment_id` | `String` | The batch payment ID, if created as part of a batch. |
|
|
56
|
+
| `batch_payment` | `Hash` | Batch payment details (raw hash). |
|
|
57
|
+
| `account` | `Hash` | The account the payment was made from (raw hash with `AccountID`, `Code`, `Name`). |
|
|
58
|
+
| `invoice` | `Hash` | The invoice the payment was made against (raw hash). |
|
|
59
|
+
| `credit_note` | `Hash` | The credit note being refunded (raw hash), if applicable. |
|
|
60
|
+
| `prepayment` | `Hash` | The prepayment being refunded (raw hash), if applicable. |
|
|
61
|
+
| `overpayment` | `Hash` | The overpayment being refunded (raw hash), if applicable. |
|
|
62
|
+
| `has_account` | `Boolean` | Whether the payment has an associated account. |
|
|
63
|
+
|
|
64
|
+
## Predicates
|
|
65
|
+
|
|
66
|
+
```ruby
|
|
67
|
+
payment.reconciled? # is_reconciled == true
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Equality and hashing
|
|
71
|
+
|
|
72
|
+
Two payments are `==` if they share the same `payment_id`. `#hash` is consistent
|
|
73
|
+
with `==`, so payments work as hash keys and in sets.
|
|
74
|
+
|
|
75
|
+
## Error behaviour
|
|
76
|
+
|
|
77
|
+
| HTTP status | Exception | What it usually means |
|
|
78
|
+
|-------------|-----------|------------------------|
|
|
79
|
+
| 200 | (none — returns payments) | Success |
|
|
80
|
+
| 401 | `XeroKiwi::AuthenticationError` | Access token is invalid or expired |
|
|
81
|
+
| 403 | `XeroKiwi::ClientError` | The token doesn't have the required scope |
|
|
82
|
+
| 404 | `XeroKiwi::ClientError` | The payment ID doesn't exist |
|
|
83
|
+
|
|
84
|
+
## Common patterns
|
|
85
|
+
|
|
86
|
+
### Listing reconciled payments
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
payments = client.payments(tenant_id)
|
|
90
|
+
reconciled = payments.select(&:reconciled?)
|
|
91
|
+
reconciled.each { |p| puts "#{p.reference}: #{p.amount}" }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Finding payments for a specific invoice
|
|
95
|
+
|
|
96
|
+
```ruby
|
|
97
|
+
payments = client.payments(tenant_id)
|
|
98
|
+
for_invoice = payments.select { |p| p.invoice&.dig("InvoiceNumber") == "INV-0001" }
|
|
99
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# XeroKiwi::Accounting::Phone
|
|
2
|
+
|
|
3
|
+
A Xero phone number. Used by [Organisation](organisation.md), and in future by
|
|
4
|
+
Contact and other resources.
|
|
5
|
+
|
|
6
|
+
> See: [Xero docs — Phone types](https://developer.xero.com/documentation/api/accounting/types#phones)
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
org.phones.each do |phone|
|
|
12
|
+
puts "#{phone.phone_type}: #{phone.phone_country_code} #{phone.phone_area_code} #{phone.phone_number}"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
mobile = org.phones.find(&:mobile?)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Attributes
|
|
19
|
+
|
|
20
|
+
| Attribute | Type | Notes |
|
|
21
|
+
|-----------|------|-------|
|
|
22
|
+
| `phone_type` | `String` | `"DEFAULT"`, `"DDI"`, `"MOBILE"`, or `"FAX"` |
|
|
23
|
+
| `phone_number` | `String` | Max 50 characters |
|
|
24
|
+
| `phone_area_code` | `String` | Max 10 characters |
|
|
25
|
+
| `phone_country_code` | `String` | Max 20 characters |
|
|
26
|
+
|
|
27
|
+
## Predicates
|
|
28
|
+
|
|
29
|
+
```ruby
|
|
30
|
+
phone.default? # phone_type == "DEFAULT"
|
|
31
|
+
phone.mobile? # phone_type == "MOBILE"
|
|
32
|
+
phone.fax? # phone_type == "FAX"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Equality
|
|
36
|
+
|
|
37
|
+
Two phones are `==` if all their attributes match. `#hash` is consistent
|
|
38
|
+
with `==`.
|
|
39
|
+
|
|
40
|
+
## Serialisation
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
phone.to_h
|
|
44
|
+
# => { phone_type: "DEFAULT", phone_number: "1234567", phone_area_code: "09", phone_country_code: "64" }
|
|
45
|
+
```
|