xero-kiwi 0.5.1 → 0.6.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 +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +36 -0
- data/Rakefile +22 -63
- data/docs/accounting/credit-note.md +1 -1
- data/docs/accounting/overpayment.md +1 -1
- data/docs/accounting/prepayment.md +1 -1
- data/docs/client.md +48 -4
- data/lib/xero_kiwi/accounting/allocation.rb +19 -5
- data/lib/xero_kiwi/accounting/resource.rb +12 -0
- data/lib/xero_kiwi/version.rb +1 -1
- data/llms-full.txt +725 -645
- data/llms.txt +25 -11
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c3c9271654c527275c19a5738effb1f5d334844a14898eaf467fc6671fbc308a
|
|
4
|
+
data.tar.gz: 0645a88a9ccd58130524e24d9981f3999b74ddf8ee98af9600a73f45cda4d29e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 74bbf0e97f3207d0aaaa16c85a82fe5c1f8572ef10c3c5d802ed2b051538ad002c9aae5df62da3f9ffd7aa76e64d4446a33cfcb98ac5d9eec3edc2f6a143d1bb
|
|
7
|
+
data.tar.gz: 32141ab2ffa3f40865a432711e1e6147c99006325e30f633f035790ab1ffefd085021eda40d5f2e22621eda084fb34174691fe6c65c405497ab7452106c9aa69
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.6.0] - 2026-09-27
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **`Accounting::Allocation#amount` always returned nil.** It was mapped to Xero's `"Amount"`, which is the key for the allocation *request* body. Every response — and allocations only ever reach this gem embedded in a CreditNote, Prepayment or Overpayment response — carries `"AppliedAmount"`. The allocated value is now modelled as **`applied_amount`**, and `#amount` is an alias of it so callers who reached for the obvious name get the value they meant. Nothing that depended on a real value is affected, because there was never one to depend on.
|
|
8
|
+
|
|
9
|
+
This mattered more than a missing field usually would: `allocations.map(&:amount)` returned an array of nils rather than raising, so an importer would have written zeroes into every allocated amount with nothing failing anywhere. Reported by a consumer who checked stored payloads before trusting the typed path.
|
|
10
|
+
|
|
11
|
+
Four spec files had fabricated `"Amount"` payloads and so agreed with the bug instead of catching it; all now use the real response shape.
|
|
12
|
+
|
|
13
|
+
### Breaking
|
|
14
|
+
|
|
15
|
+
- `Allocation#to_h` now carries `:applied_amount` instead of `:amount`, and `:amount` is no longer a declared attribute (it is a plain reader, so one value maps to one key). Anyone reading `to_h[:amount]` was reading nil.
|
|
16
|
+
|
|
17
|
+
### Documentation
|
|
18
|
+
|
|
19
|
+
- The README now documents the release process. It covered running specs but said nothing about cutting a release, so the sequencing lived only in one person's head. It leads with the rule and the reason — `rake release` tags whatever is checked out, so a version bump riding along in a pull request gets orphaned the moment that PR is squash-merged, which is what happened to v0.5.2 — and records the thing that is not guessable from the repo: `docs/` ships inside the gem, so a documentation-only fix still needs a patch release to reach anyone.
|
|
20
|
+
|
|
21
|
+
## [0.5.2] - 2026-09-27
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
- Documented that `Resource#raw` returns nil on nested objects (line items, addresses, contact persons, payment terms) even with `retain_raw: true`, and that the enclosing resource's hash is the access path — `org.raw["Addresses"]` rather than `org.addresses.map(&:raw)`. The behaviour was deliberate and explained in a comment on `from_response`, but the `#raw` docstring never mentioned it and the failure is a silent nil, so a consumer mapped over a nested collection and was one step from storing `[null]`.
|
|
26
|
+
- Added a written contract for `raw` in `docs/client.md`: it is the parsed JSON with only top-level keys stringified, kiwi never normalises it (absent keys stay absent rather than becoming `[]`), unmodelled keys are preserved, and the freeze is shallow — the hash is frozen, the structures inside it are not. Specs pin all four, plus the nested-nil behaviour. The previous "is frozen" example overstated the guarantee and has been replaced.
|
|
27
|
+
- `llms.txt` is now generated alongside `llms-full.txt` from a single manifest in `tasks/llms.rb`, rather than hand-maintained. It had not been touched since the initial commit and was missing four releases of material — no `querying.md`, no `throttling.md`, no `tracking-category.md`, and no mention of `Page`, `RateLimit`, the throttle limiters or the tracking classes. `rake llms:check` now also fails when a doc exists under `docs/` that the manifest does not list, which is the half that was missing: the freshness check could not notice a doc that was never indexed in the first place.
|
|
28
|
+
|
|
3
29
|
## [0.5.1] - 2026-09-26
|
|
4
30
|
|
|
5
31
|
### Documentation
|
data/README.md
CHANGED
|
@@ -113,6 +113,42 @@ default `redis://127.0.0.1:6379/15`.
|
|
|
113
113
|
docker compose down # when you're done
|
|
114
114
|
```
|
|
115
115
|
|
|
116
|
+
### Releasing
|
|
117
|
+
|
|
118
|
+
**Merge first, then bump.** `rake release` tags whatever is checked out, so a
|
|
119
|
+
version bump that rides along inside a pull request gets orphaned the moment
|
|
120
|
+
that PR is squash-merged — the squash creates a new commit and the tag is left
|
|
121
|
+
pointing at the pre-merge branch commit, unreachable from `main`. Bumping after
|
|
122
|
+
the merge makes that impossible regardless of merge strategy.
|
|
123
|
+
|
|
124
|
+
So: land the work through a PR as normal, then
|
|
125
|
+
|
|
126
|
+
```sh
|
|
127
|
+
git checkout main && git pull
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
1. Bump `VERSION` in [lib/xero_kiwi/version.rb](lib/xero_kiwi/version.rb).
|
|
131
|
+
2. Move the `[Unreleased]` entries in [CHANGELOG.md](CHANGELOG.md) under a
|
|
132
|
+
dated version heading.
|
|
133
|
+
3. `bundle install` to refresh the lockfile's `xero-kiwi (x.y.z)`.
|
|
134
|
+
4. `bundle exec rake` — specs, RuboCop, and the `llms:check` freshness guard.
|
|
135
|
+
5. Commit to `main`. A commit-msg hook requires the `crimesjohnson:` prefix
|
|
136
|
+
there, so: `crimesjohnson: release x.y.z with <the headline>`.
|
|
137
|
+
|
|
138
|
+
```sh
|
|
139
|
+
bundle exec rake release # builds, tags, pushes the tag, publishes
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The gemspec sets `rubygems_mfa_required`, so this prompts for an OTP and can't
|
|
143
|
+
run unattended. Finally, cut the GitHub release from the changelog section:
|
|
144
|
+
|
|
145
|
+
```sh
|
|
146
|
+
gh release create vx.y.z --title "vx.y.z — <headline>" --notes-file <(…) --verify-tag --latest
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Note that `docs/` ships inside the gem, so a documentation-only fix still needs
|
|
150
|
+
a patch release to reach anyone — it won't arrive through GitHub alone.
|
|
151
|
+
|
|
116
152
|
## Contributing
|
|
117
153
|
|
|
118
154
|
Bug reports and pull requests are welcome on GitHub at
|
data/Rakefile
CHANGED
|
@@ -9,76 +9,35 @@ require "rubocop/rake_task"
|
|
|
9
9
|
|
|
10
10
|
RuboCop::RakeTask.new
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
# the docs in the same order the README's table of contents lists them.
|
|
14
|
-
LLMS_SOURCE_FILES = %w[
|
|
15
|
-
README.md
|
|
16
|
-
docs/getting-started.md
|
|
17
|
-
docs/client.md
|
|
18
|
-
docs/oauth.md
|
|
19
|
-
docs/tokens.md
|
|
20
|
-
docs/connections.md
|
|
21
|
-
docs/accounting/contact.md
|
|
22
|
-
docs/accounting/contact-group.md
|
|
23
|
-
docs/accounting/organisation.md
|
|
24
|
-
docs/accounting/user.md
|
|
25
|
-
docs/accounting/credit-note.md
|
|
26
|
-
docs/accounting/invoice.md
|
|
27
|
-
docs/accounting/payment.md
|
|
28
|
-
docs/accounting/overpayment.md
|
|
29
|
-
docs/accounting/prepayment.md
|
|
30
|
-
docs/accounting/branding-theme.md
|
|
31
|
-
docs/accounting/tracking-category.md
|
|
32
|
-
docs/accounting/address.md
|
|
33
|
-
docs/accounting/phone.md
|
|
34
|
-
docs/accounting/external-link.md
|
|
35
|
-
docs/accounting/payment-terms.md
|
|
36
|
-
docs/errors.md
|
|
37
|
-
docs/retries-and-rate-limits.md
|
|
38
|
-
docs/throttling.md
|
|
39
|
-
docs/querying.md
|
|
40
|
-
].freeze
|
|
41
|
-
|
|
42
|
-
LLMS_FULL_PATH = "llms-full.txt"
|
|
43
|
-
|
|
44
|
-
# Builds the llms-full.txt content from LLMS_SOURCE_FILES. Pure function:
|
|
45
|
-
# returns a String, doesn't touch the filesystem. Both `llms:build` and
|
|
46
|
-
# `llms:check` use this so the two tasks can never disagree about the
|
|
47
|
-
# expected output.
|
|
48
|
-
def build_llms_full
|
|
49
|
-
out = String.new(encoding: "UTF-8")
|
|
50
|
-
out << "# Xero Kiwi — full documentation\n\n"
|
|
51
|
-
out << "This file is the complete documentation for the Xero Kiwi gem (a Ruby wrapper for the Xero Accounting API), assembled into a single document for LLM consumption. It contains the README and every doc in the docs/ folder, in reading order.\n\n"
|
|
52
|
-
out << "For the curated index version, see llms.txt in the same directory.\n\n"
|
|
53
|
-
out << "Source: https://github.com/douglasgreyling/xero-kiwi\n\n"
|
|
54
|
-
LLMS_SOURCE_FILES.each { |path| append_file_block(out, path) }
|
|
55
|
-
out
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def append_file_block(out, path)
|
|
59
|
-
separator = "=" * 80
|
|
60
|
-
out << "\n" << separator << "\n"
|
|
61
|
-
out << "FILE: #{path}\n"
|
|
62
|
-
out << separator << "\n\n"
|
|
63
|
-
out << File.read(path, encoding: "UTF-8") << "\n"
|
|
64
|
-
end
|
|
12
|
+
require_relative "tasks/llms"
|
|
65
13
|
|
|
66
14
|
namespace :llms do
|
|
67
|
-
desc "Regenerate llms-full.txt from README and docs/"
|
|
15
|
+
desc "Regenerate llms.txt and llms-full.txt from README and docs/"
|
|
68
16
|
task :build do
|
|
69
|
-
|
|
70
|
-
|
|
17
|
+
Llms.outputs.each do |path, content|
|
|
18
|
+
File.write(path, content)
|
|
19
|
+
puts "Wrote #{path} (#{File.size(path)} bytes)"
|
|
20
|
+
end
|
|
71
21
|
end
|
|
72
22
|
|
|
73
|
-
desc "Verify llms-full.txt
|
|
23
|
+
desc "Verify llms.txt and llms-full.txt are up to date, and that every doc is indexed"
|
|
74
24
|
task :check do
|
|
75
|
-
|
|
76
|
-
|
|
25
|
+
missing = Llms.unindexed_docs
|
|
26
|
+
unless missing.empty?
|
|
27
|
+
warn "✗ These docs are not listed in Llms::DOCS, so they are missing from llms.txt and llms-full.txt:"
|
|
28
|
+
missing.each { |path| warn " #{path}" }
|
|
29
|
+
warn " Add them to tasks/llms.rb and run `bundle exec rake llms:build`."
|
|
30
|
+
exit 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
stale = Llms.outputs.reject do |path, expected|
|
|
34
|
+
File.exist?(path) && File.read(path, encoding: "UTF-8") == expected
|
|
35
|
+
end
|
|
77
36
|
|
|
78
|
-
if
|
|
79
|
-
puts "✓
|
|
37
|
+
if stale.empty?
|
|
38
|
+
puts "✓ llms.txt and llms-full.txt are up to date"
|
|
80
39
|
else
|
|
81
|
-
warn "✗
|
|
40
|
+
warn "✗ Out of date with README/docs: #{stale.keys.join(", ")}"
|
|
82
41
|
warn " Run `bundle exec rake llms:build` and commit the result."
|
|
83
42
|
exit 1
|
|
84
43
|
end
|
|
@@ -86,7 +45,7 @@ namespace :llms do
|
|
|
86
45
|
end
|
|
87
46
|
|
|
88
47
|
# Top-level convenience alias.
|
|
89
|
-
desc "Regenerate
|
|
48
|
+
desc "Regenerate the LLM docs bundles (alias for llms:build)"
|
|
90
49
|
task llms: "llms:build"
|
|
91
50
|
|
|
92
51
|
task default: %i[spec rubocop llms:check]
|
|
@@ -61,7 +61,7 @@ fields Xero returns:
|
|
|
61
61
|
| `reference` | `String` | Additional reference number (ACCRECCREDIT only). |
|
|
62
62
|
| `sent_to_contact` | `Boolean` | Whether the credit note has been sent to the contact. |
|
|
63
63
|
| `remaining_credit` | `Numeric` | The remaining credit balance. |
|
|
64
|
-
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each
|
|
64
|
+
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each has `allocation_id`, `applied_amount`, `date`, `is_deleted`, and an `invoice` reference. |
|
|
65
65
|
| `branding_theme_id` | `String` | The branding theme ID applied to the credit note. |
|
|
66
66
|
| `has_attachments` | `Boolean` | Whether the credit note has attachments. |
|
|
67
67
|
|
|
@@ -57,7 +57,7 @@ fields Xero returns:
|
|
|
57
57
|
| `currency_code` | `String` | The currency code (e.g. `"NZD"`). |
|
|
58
58
|
| `currency_rate` | `String` | The currency rate (1.0 for base currency). |
|
|
59
59
|
| `remaining_credit` | `String` | The remaining credit balance. |
|
|
60
|
-
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each
|
|
60
|
+
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each has `allocation_id`, `applied_amount`, `date`, `is_deleted`, and an `invoice` reference. |
|
|
61
61
|
| `payments` | `Array<XeroKiwi::Accounting::Payment>` | Payment records (references). See [Payments](payment.md). |
|
|
62
62
|
| `has_attachments` | `Boolean` | Whether the overpayment has attachments. |
|
|
63
63
|
| `reference` | `String` | Reference for the overpayment. |
|
|
@@ -58,7 +58,7 @@ fields Xero returns:
|
|
|
58
58
|
| `currency_rate` | `String` | The currency rate (1.0 for base currency). |
|
|
59
59
|
| `invoice_number` | `String` | The invoice number (for receive prepayments only). |
|
|
60
60
|
| `remaining_credit` | `String` | The remaining credit balance. |
|
|
61
|
-
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each
|
|
61
|
+
| `allocations` | `Array<XeroKiwi::Accounting::Allocation>` | Allocations to invoices. Each has `allocation_id`, `applied_amount`, `date`, `is_deleted`, and an `invoice` reference. |
|
|
62
62
|
| `payments` | `Array<XeroKiwi::Accounting::Payment>` | Payment records (references). See [Payments](payment.md). |
|
|
63
63
|
| `has_attachments` | `Boolean` | Whether the prepayment has attachments. |
|
|
64
64
|
| `fully_paid_on_date` | `Time` | When the prepayment was fully allocated, parsed as UTC. |
|
data/docs/client.md
CHANGED
|
@@ -68,6 +68,18 @@ Five things to know:
|
|
|
68
68
|
the envelope before building a resource, so there's nothing left of it by
|
|
69
69
|
the time `raw` is populated. If you need the envelope back, you're
|
|
70
70
|
rebuilding it yourself.
|
|
71
|
+
- **Nested objects return `nil`, even with `retain_raw: true`.** Line
|
|
72
|
+
items, addresses, contact persons and payment terms do not carry their
|
|
73
|
+
own payload. Reach them through the enclosing resource's hash:
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
org.addresses.map(&:raw) # => [nil] ← not what you want
|
|
77
|
+
org.raw["Addresses"] # => [{"AddressType" => "POBOX", …}]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
This is deliberate — see [why nested objects don't carry
|
|
81
|
+
raw](#why-nested-objects-dont-carry-raw) — but it fails quietly, so it's
|
|
82
|
+
worth knowing before you map over a collection and store the result.
|
|
71
83
|
- **It's the JSON representation.** Kiwi sends
|
|
72
84
|
`Accept: application/json`. Xero also serves XML, which nests
|
|
73
85
|
differently — XML has no arrays, so a single child parses to a Hash and
|
|
@@ -78,14 +90,46 @@ Five things to know:
|
|
|
78
90
|
the modelled attributes — different keys, different nesting. If you store
|
|
79
91
|
`to_h` where you meant to store the payload, readers fail by returning
|
|
80
92
|
nil rather than raising.
|
|
81
|
-
- **It's per resource, not per nested object.** Line items, addresses and
|
|
82
|
-
contact persons have no `#raw` of their own. They don't need one: the
|
|
83
|
-
resource's hash already holds every nested payload, so
|
|
84
|
-
`contact.raw["ContactPersons"]` gets there.
|
|
85
93
|
- **It costs memory.** Every resource holds its source hash alongside the
|
|
86
94
|
hydrated attributes, which roughly doubles the footprint of a large page.
|
|
87
95
|
That's why it's off by default.
|
|
88
96
|
|
|
97
|
+
### What `raw` guarantees
|
|
98
|
+
|
|
99
|
+
Depend on these; they won't change without a major version.
|
|
100
|
+
|
|
101
|
+
- It is the parsed JSON for that resource, with **only the top-level keys
|
|
102
|
+
stringified**. Everything nested is exactly what `JSON.parse` produced.
|
|
103
|
+
- **Kiwi does not normalise it.** No key renaming, no defaulting, no
|
|
104
|
+
filling in of absent keys. If Xero omits `Addresses`, `raw` has no
|
|
105
|
+
`"Addresses"` key — it does not become `[]`. If Xero sends `[]`, you get
|
|
106
|
+
`[]`. `raw.fetch("Addresses", [])` and `raw["Addresses"] || []` are both
|
|
107
|
+
safe and mean the same thing here.
|
|
108
|
+
- Keys the gem doesn't model are preserved. That's the point of it.
|
|
109
|
+
- The top-level hash is **frozen; nested structures are not**. `raw` itself
|
|
110
|
+
can't be mutated, but `raw["Addresses"]` is an ordinary mutable Array.
|
|
111
|
+
Dup before mutating if that matters to you.
|
|
112
|
+
|
|
113
|
+
The one thing deliberately *not* guaranteed is the presence of `raw` on
|
|
114
|
+
nested objects, per the bullet above.
|
|
115
|
+
|
|
116
|
+
### Why nested objects don't carry raw
|
|
117
|
+
|
|
118
|
+
Two reasons, both worth knowing if you're tempted to ask for it.
|
|
119
|
+
|
|
120
|
+
It would cost real memory on the workload `retain_raw` exists for. A page
|
|
121
|
+
of 1,000 invoices with five line items each retains about 3.4 MB with
|
|
122
|
+
top-level raw; giving every nested object its own hash adds about 1.6 MB
|
|
123
|
+
on top, roughly half again, and that's on a flag that has already doubled
|
|
124
|
+
your footprint.
|
|
125
|
+
|
|
126
|
+
More importantly it couldn't be done consistently. Several attributes —
|
|
127
|
+
`payment_terms` on Contact and Organisation, `invoice_addresses` on
|
|
128
|
+
Invoice — hydrate through custom lambdas that construct their objects
|
|
129
|
+
directly, so they'd stay `nil` while their siblings worked. "Nested
|
|
130
|
+
objects never carry raw" is a rule you can hold in your head. "Nested
|
|
131
|
+
objects carry raw except these four" is not.
|
|
132
|
+
|
|
89
133
|
### Migrating from an XML-based client
|
|
90
134
|
|
|
91
135
|
If you're replacing a Xero client that sent `Accept: text/xml` — HTTParty
|
|
@@ -5,17 +5,31 @@ module XeroKiwi
|
|
|
5
5
|
# Represents an allocation of a credit note, prepayment, or overpayment
|
|
6
6
|
# against an invoice.
|
|
7
7
|
#
|
|
8
|
+
# Xero names the allocated value differently depending on direction: the
|
|
9
|
+
# allocation *request* body takes "Amount", while every *response* — and
|
|
10
|
+
# allocations only ever reach this gem embedded in a CreditNote,
|
|
11
|
+
# Prepayment or Overpayment response — carries "AppliedAmount". This
|
|
12
|
+
# class was originally modelled off the request shape, so `amount`
|
|
13
|
+
# silently returned nil for every allocation the gem could actually
|
|
14
|
+
# produce. `#amount` is now an alias of `#applied_amount` so callers who
|
|
15
|
+
# reached for the obvious name get the value they meant.
|
|
16
|
+
#
|
|
8
17
|
# See: https://developer.xero.com/documentation/api/accounting/overpayments
|
|
9
18
|
class Allocation
|
|
10
19
|
include Resource
|
|
11
20
|
|
|
12
21
|
identity :allocation_id
|
|
13
22
|
|
|
14
|
-
attribute :allocation_id,
|
|
15
|
-
attribute :
|
|
16
|
-
attribute :date,
|
|
17
|
-
attribute :invoice,
|
|
18
|
-
attribute :is_deleted,
|
|
23
|
+
attribute :allocation_id, xero: "AllocationID", type: :guid
|
|
24
|
+
attribute :applied_amount, xero: "AppliedAmount", type: :decimal
|
|
25
|
+
attribute :date, xero: "Date", type: :date
|
|
26
|
+
attribute :invoice, xero: "Invoice", type: :object, of: Invoice, reference: true
|
|
27
|
+
attribute :is_deleted, xero: "IsDeleted", type: :bool
|
|
28
|
+
|
|
29
|
+
# Kept for callers written against the pre-0.6.0 attribute name. It
|
|
30
|
+
# could only ever have returned nil, so nothing that relied on a real
|
|
31
|
+
# value is affected.
|
|
32
|
+
def amount = applied_amount
|
|
19
33
|
end
|
|
20
34
|
end
|
|
21
35
|
end
|
|
@@ -139,11 +139,23 @@ module XeroKiwi
|
|
|
139
139
|
# arrived, or nil unless the client was built with `retain_raw: true`.
|
|
140
140
|
# Use it to reach fields the gem doesn't model.
|
|
141
141
|
#
|
|
142
|
+
# Returns nil on NESTED objects even when retain_raw is on — line
|
|
143
|
+
# items, addresses, contact persons, payment terms. Reach those
|
|
144
|
+
# through the enclosing resource instead:
|
|
145
|
+
#
|
|
146
|
+
# org.addresses.map(&:raw) # => [nil]
|
|
147
|
+
# org.raw["Addresses"] # => [{"AddressType" => "POBOX", ...}]
|
|
148
|
+
#
|
|
142
149
|
# Scope is the item, NOT the enclosing envelope: `contact.raw` has no
|
|
143
150
|
# "Contacts" key, and `organisation.raw` no "Organisations" key. Kiwi
|
|
144
151
|
# unwraps the envelope before a resource is built, so there is nothing
|
|
145
152
|
# left of it by the time this is populated.
|
|
146
153
|
#
|
|
154
|
+
# Kiwi never normalises what it stores here: absent keys stay absent
|
|
155
|
+
# rather than becoming [] or nil entries, and keys the gem doesn't
|
|
156
|
+
# model are preserved. The hash itself is frozen; the structures
|
|
157
|
+
# nested inside it are not.
|
|
158
|
+
#
|
|
147
159
|
# It is also the JSON representation specifically. Kiwi sends
|
|
148
160
|
# `Accept: application/json`; Xero's XML representation nests
|
|
149
161
|
# differently — no arrays, so one child is a Hash and several are an
|
data/lib/xero_kiwi/version.rb
CHANGED