xero-kiwi 0.10.0 → 0.11.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 +11 -0
- data/docs/accounting/tracking-category.md +15 -5
- data/docs/querying.md +12 -3
- data/lib/xero_kiwi/client.rb +13 -8
- data/lib/xero_kiwi/version.rb +1 -1
- data/llms-full.txt +27 -8
- 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: e52bfcc3939a00a86a7bc26b931aa6e7553b2479fb3b2b36c3215daccad754de
|
|
4
|
+
data.tar.gz: 0c13e42901c11b857c0476dea1c898a46a12404de66231df0b82cb9c899d9a71
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d9b16a8564e87c0935dfd301ec480fa856c7374f70ca939eef877d4e108f8e54a9ef38a1454451d848de1d6c697addb561f3bf81e3405414dbb0567c9ff77d2
|
|
7
|
+
data.tar.gz: 169f97330de612d1c940bbd0ee0d671c5d5ae7cc4284f5cc42af9b5d59cd37c2e5a68a81113d7e56a66c6e03a5a649bac779783d9b055db143f04684cd6d954c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.11.0] - 2026-10-08
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`include_archived:`** on `tracking_categories` / `each_tracking_category` / `each_tracking_category_page`, matching the contacts methods. Maps to Xero's `includeArchived`. Without it, Xero leaves out archived categories *and* the archived options under active ones, so a sync that mirrors the list — deleting whatever Xero didn't return — deletes every archived option, and historical invoices tagged with one stop resolving. A consumer's legacy XML client sent the flag; on 0.10.0 passing it raised `ArgumentError: unknown keyword: :include_archived`.
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
- The tracking categories "lookup from option ID" example now passes `include_archived: true`. Without it, `options.fetch` raises `KeyError` on any line item tagged with an archived option.
|
|
12
|
+
- The "Ignoring archived categories" example filtered a list that could never contain one, since Xero leaves archived categories out by default. It now says so, and shows the filter on a list fetched with `include_archived: true`.
|
|
13
|
+
|
|
3
14
|
## [0.10.0] - 2026-09-29
|
|
4
15
|
|
|
5
16
|
### Breaking
|
|
@@ -52,8 +52,11 @@ categories.first.options.map(&:name) # => ["Eastside", "Westside"]
|
|
|
52
52
|
the `Xero-Tenant-Id` header set, and returns a `XeroKiwi::Page` of
|
|
53
53
|
`TrackingCategory` objects.
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
Archived categories, and archived options under active ones, are left out
|
|
56
|
+
unless you pass `include_archived: true`. See [Querying](../querying.md).
|
|
57
|
+
|
|
58
|
+
This endpoint isn't paged — Xero returns every category in one response, and
|
|
59
|
+
an organisation has at most two active ones. `each_tracking_category` exists so all ten list resources behave
|
|
57
60
|
consistently, but there's no reason to reach for it over the plain call.
|
|
58
61
|
|
|
59
62
|
## Fetching a single category
|
|
@@ -139,10 +142,12 @@ so it falls back to structural equality — every attribute must match.
|
|
|
139
142
|
### Building a lookup from option ID to names
|
|
140
143
|
|
|
141
144
|
Line items carry only IDs and denormalised names; if you need the canonical
|
|
142
|
-
option list, fetch the definitions once per sync and index them.
|
|
145
|
+
option list, fetch the definitions once per sync and index them. Include
|
|
146
|
+
archived ones, or a line item tagged with an archived option raises
|
|
147
|
+
`KeyError`.
|
|
143
148
|
|
|
144
149
|
```ruby
|
|
145
|
-
options = client.tracking_categories(tenant_id).flat_map do |category|
|
|
150
|
+
options = client.tracking_categories(tenant_id, include_archived: true).flat_map do |category|
|
|
146
151
|
category.options.map { |option| [option.tracking_option_id, [category.name, option.name]] }
|
|
147
152
|
end.to_h
|
|
148
153
|
|
|
@@ -156,6 +161,11 @@ end
|
|
|
156
161
|
|
|
157
162
|
### Ignoring archived categories
|
|
158
163
|
|
|
164
|
+
Xero leaves archived categories out unless you ask for them, so a plain
|
|
165
|
+
`client.tracking_categories(tenant_id)` already returns only active ones.
|
|
166
|
+
Filter when you fetched archived ones too, for a lookup like the one above:
|
|
167
|
+
|
|
159
168
|
```ruby
|
|
160
|
-
|
|
169
|
+
categories = client.tracking_categories(tenant_id, include_archived: true)
|
|
170
|
+
active = categories.select(&:active?)
|
|
161
171
|
```
|
data/docs/querying.md
CHANGED
|
@@ -233,14 +233,18 @@ exception, no special flag. An empty page after `modified_since:` is
|
|
|
233
233
|
indistinguishable from a filter that matched nothing (intentional — the
|
|
234
234
|
caller can treat them identically).
|
|
235
235
|
|
|
236
|
-
## `include_archived:` — archived contacts
|
|
236
|
+
## `include_archived:` — archived contacts and tracking categories
|
|
237
237
|
|
|
238
|
-
Contacts only. Maps to Xero's `includeArchived`
|
|
239
|
-
archived
|
|
238
|
+
Contacts and tracking categories only. Maps to Xero's `includeArchived`
|
|
239
|
+
query param, which returns archived records **alongside** active ones in
|
|
240
|
+
the same pass.
|
|
240
241
|
|
|
241
242
|
```ruby
|
|
242
243
|
client.contacts(tenant, include_archived: true)
|
|
243
244
|
client.each_contact(tenant, include_archived: true) { |contact| … }
|
|
245
|
+
|
|
246
|
+
client.tracking_categories(tenant, include_archived: true)
|
|
247
|
+
client.each_tracking_category(tenant, include_archived: true) { |category| … }
|
|
244
248
|
```
|
|
245
249
|
|
|
246
250
|
This is not the same as filtering on `contact_status`. A
|
|
@@ -252,6 +256,11 @@ It matters beyond contacts themselves: Xero keeps serving archived
|
|
|
252
256
|
contacts as members of contact groups, so without this you can't tell
|
|
253
257
|
which group members are archived locally.
|
|
254
258
|
|
|
259
|
+
For tracking categories it reaches the options too. Without it, Xero leaves
|
|
260
|
+
out archived categories *and* the archived options under active ones. Line
|
|
261
|
+
items keep pointing at an archived option, so a sync that mirrors the list
|
|
262
|
+
without this flag deletes options its invoices still refer to.
|
|
263
|
+
|
|
255
264
|
## Combining everything
|
|
256
265
|
|
|
257
266
|
Mix and match freely:
|
data/lib/xero_kiwi/client.rb
CHANGED
|
@@ -617,7 +617,11 @@ module XeroKiwi
|
|
|
617
617
|
# Fetches the Tracking Categories for the given tenant. Accepts a tenant-id
|
|
618
618
|
# string or a XeroKiwi::Connection (we use its tenant_id).
|
|
619
619
|
# See: https://developer.xero.com/documentation/api/accounting/trackingcategories
|
|
620
|
-
def tracking_categories(tenant_id, where: nil, order: nil, page_size: nil, page: nil, modified_since: nil)
|
|
620
|
+
def tracking_categories(tenant_id, where: nil, order: nil, page_size: nil, include_archived: nil, page: nil, modified_since: nil)
|
|
621
|
+
extra_params = {}
|
|
622
|
+
|
|
623
|
+
extra_params["includeArchived"] = include_archived unless include_archived.nil?
|
|
624
|
+
|
|
621
625
|
list_request(
|
|
622
626
|
path: "/api.xro/2.0/TrackingCategories",
|
|
623
627
|
tenant_id: tenant_id,
|
|
@@ -626,27 +630,28 @@ module XeroKiwi
|
|
|
626
630
|
order: order,
|
|
627
631
|
page: page,
|
|
628
632
|
page_size: page_size,
|
|
629
|
-
modified_since: modified_since
|
|
633
|
+
modified_since: modified_since,
|
|
634
|
+
extra_params: extra_params
|
|
630
635
|
)
|
|
631
636
|
end
|
|
632
637
|
|
|
633
638
|
# Yields every Tracking Category across all pages, driving `#tracking_categories` with
|
|
634
639
|
# `page:` until an empty or short page signals the end. Returns an
|
|
635
640
|
# Enumerator when no block is given.
|
|
636
|
-
def each_tracking_category(tenant_id, where: nil, order: nil, page_size: nil, start_page: 1, modified_since: nil, &block)
|
|
637
|
-
return to_enum(:each_tracking_category, tenant_id, where: where, order: order, page_size: page_size, start_page: start_page, modified_since: modified_since) unless block
|
|
641
|
+
def each_tracking_category(tenant_id, where: nil, order: nil, page_size: nil, include_archived: nil, start_page: 1, modified_since: nil, &block)
|
|
642
|
+
return to_enum(:each_tracking_category, tenant_id, where: where, order: order, page_size: page_size, include_archived: include_archived, start_page: start_page, modified_since: modified_since) unless block
|
|
638
643
|
|
|
639
|
-
each_tracking_category_page(tenant_id, where: where, order: order, page_size: page_size, start_page: start_page, modified_since: modified_since) { |pg| pg.each(&block) }
|
|
644
|
+
each_tracking_category_page(tenant_id, where: where, order: order, page_size: page_size, include_archived: include_archived, start_page: start_page, modified_since: modified_since) { |pg| pg.each(&block) }
|
|
640
645
|
end
|
|
641
646
|
|
|
642
647
|
# Same walk as `#each_tracking_category`, but yields each XeroKiwi::Page rather
|
|
643
648
|
# than its items. Pair `page.page` with `start_page:` to make a sync
|
|
644
649
|
# resumable: record the page number in the same transaction that stores
|
|
645
650
|
# the rows, and a crash can't leave a marker ahead of the data.
|
|
646
|
-
def each_tracking_category_page(tenant_id, where: nil, order: nil, page_size: nil, start_page: 1, modified_since: nil, &block)
|
|
647
|
-
return to_enum(:each_tracking_category_page, tenant_id, where: where, order: order, page_size: page_size, start_page: start_page, modified_since: modified_since) unless block
|
|
651
|
+
def each_tracking_category_page(tenant_id, where: nil, order: nil, page_size: nil, include_archived: nil, start_page: 1, modified_since: nil, &block)
|
|
652
|
+
return to_enum(:each_tracking_category_page, tenant_id, where: where, order: order, page_size: page_size, include_archived: include_archived, start_page: start_page, modified_since: modified_since) unless block
|
|
648
653
|
|
|
649
|
-
walk_pages(:tracking_categories, tenant_id, where: where, order: order, page_size: page_size, start_page: start_page, modified_since: modified_since, &block)
|
|
654
|
+
walk_pages(:tracking_categories, tenant_id, where: where, order: order, page_size: page_size, include_archived: include_archived, start_page: start_page, modified_since: modified_since, &block)
|
|
650
655
|
end
|
|
651
656
|
|
|
652
657
|
# Fetches a single Tracking Category by ID for the given tenant. Accepts a
|
data/lib/xero_kiwi/version.rb
CHANGED
data/llms-full.txt
CHANGED
|
@@ -2158,14 +2158,18 @@ exception, no special flag. An empty page after `modified_since:` is
|
|
|
2158
2158
|
indistinguishable from a filter that matched nothing (intentional — the
|
|
2159
2159
|
caller can treat them identically).
|
|
2160
2160
|
|
|
2161
|
-
## `include_archived:` — archived contacts
|
|
2161
|
+
## `include_archived:` — archived contacts and tracking categories
|
|
2162
2162
|
|
|
2163
|
-
Contacts only. Maps to Xero's `includeArchived`
|
|
2164
|
-
archived
|
|
2163
|
+
Contacts and tracking categories only. Maps to Xero's `includeArchived`
|
|
2164
|
+
query param, which returns archived records **alongside** active ones in
|
|
2165
|
+
the same pass.
|
|
2165
2166
|
|
|
2166
2167
|
```ruby
|
|
2167
2168
|
client.contacts(tenant, include_archived: true)
|
|
2168
2169
|
client.each_contact(tenant, include_archived: true) { |contact| … }
|
|
2170
|
+
|
|
2171
|
+
client.tracking_categories(tenant, include_archived: true)
|
|
2172
|
+
client.each_tracking_category(tenant, include_archived: true) { |category| … }
|
|
2169
2173
|
```
|
|
2170
2174
|
|
|
2171
2175
|
This is not the same as filtering on `contact_status`. A
|
|
@@ -2177,6 +2181,11 @@ It matters beyond contacts themselves: Xero keeps serving archived
|
|
|
2177
2181
|
contacts as members of contact groups, so without this you can't tell
|
|
2178
2182
|
which group members are archived locally.
|
|
2179
2183
|
|
|
2184
|
+
For tracking categories it reaches the options too. Without it, Xero leaves
|
|
2185
|
+
out archived categories *and* the archived options under active ones. Line
|
|
2186
|
+
items keep pointing at an archived option, so a sync that mirrors the list
|
|
2187
|
+
without this flag deletes options its invoices still refer to.
|
|
2188
|
+
|
|
2180
2189
|
## Combining everything
|
|
2181
2190
|
|
|
2182
2191
|
Mix and match freely:
|
|
@@ -3545,8 +3554,11 @@ categories.first.options.map(&:name) # => ["Eastside", "Westside"]
|
|
|
3545
3554
|
the `Xero-Tenant-Id` header set, and returns a `XeroKiwi::Page` of
|
|
3546
3555
|
`TrackingCategory` objects.
|
|
3547
3556
|
|
|
3548
|
-
|
|
3549
|
-
|
|
3557
|
+
Archived categories, and archived options under active ones, are left out
|
|
3558
|
+
unless you pass `include_archived: true`. See [Querying](../querying.md).
|
|
3559
|
+
|
|
3560
|
+
This endpoint isn't paged — Xero returns every category in one response, and
|
|
3561
|
+
an organisation has at most two active ones. `each_tracking_category` exists so all ten list resources behave
|
|
3550
3562
|
consistently, but there's no reason to reach for it over the plain call.
|
|
3551
3563
|
|
|
3552
3564
|
## Fetching a single category
|
|
@@ -3632,10 +3644,12 @@ so it falls back to structural equality — every attribute must match.
|
|
|
3632
3644
|
### Building a lookup from option ID to names
|
|
3633
3645
|
|
|
3634
3646
|
Line items carry only IDs and denormalised names; if you need the canonical
|
|
3635
|
-
option list, fetch the definitions once per sync and index them.
|
|
3647
|
+
option list, fetch the definitions once per sync and index them. Include
|
|
3648
|
+
archived ones, or a line item tagged with an archived option raises
|
|
3649
|
+
`KeyError`.
|
|
3636
3650
|
|
|
3637
3651
|
```ruby
|
|
3638
|
-
options = client.tracking_categories(tenant_id).flat_map do |category|
|
|
3652
|
+
options = client.tracking_categories(tenant_id, include_archived: true).flat_map do |category|
|
|
3639
3653
|
category.options.map { |option| [option.tracking_option_id, [category.name, option.name]] }
|
|
3640
3654
|
end.to_h
|
|
3641
3655
|
|
|
@@ -3649,8 +3663,13 @@ end
|
|
|
3649
3663
|
|
|
3650
3664
|
### Ignoring archived categories
|
|
3651
3665
|
|
|
3666
|
+
Xero leaves archived categories out unless you ask for them, so a plain
|
|
3667
|
+
`client.tracking_categories(tenant_id)` already returns only active ones.
|
|
3668
|
+
Filter when you fetched archived ones too, for a lookup like the one above:
|
|
3669
|
+
|
|
3652
3670
|
```ruby
|
|
3653
|
-
|
|
3671
|
+
categories = client.tracking_categories(tenant_id, include_archived: true)
|
|
3672
|
+
active = categories.select(&:active?)
|
|
3654
3673
|
```
|
|
3655
3674
|
|
|
3656
3675
|
|