cin7_core_api 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c48f34c3de3d21ac9674e0bb133a3b9a16158ae0eb5087fcaafdf8e8543f794
4
- data.tar.gz: e452799a7aa9ebf7b988d7146df5f01cc0f23c8be9c8213cda495dff6549653d
3
+ metadata.gz: bebb9103f8de0eff128f3225cb97eeacca8137b6501f09051858053e79443cf6
4
+ data.tar.gz: 27a765beb403a6279b6d74d25952688b304252e3308b22b47ada21f46c920401
5
5
  SHA512:
6
- metadata.gz: 0acaa3e83cfd47241d741a4fee553505f558ef091ae971e1f1a8753de40e510b89b03ea17bfc1d2aba60932261d1eddbfbbb20f8deb3d962b566261844bfca99
7
- data.tar.gz: fbd694cb6d780b6c718540e02ab0ee6f923f2c33b93ffc65243ff6293453c438dc15b20903e3f8027fa1a3aaa4770931fa9995481ae7b623ef9ff22c9b7d8093
6
+ metadata.gz: d007332b45d5a02e5810eabd256b24c77156e34fd737c3d68cf671608a9a149978380b21c9398be56d72430fa0ad3beaf28d56015c404b564a3bb838d98f1cb1
7
+ data.tar.gz: 3be8c44fc59d964e1fea08eede44326e6a38eff0885f7426c11986f23a383901c6215181b1fcca04f17306c667e2ce300336661e24e72e4d3a55d3f93529d5aa
data/CHANGELOG.md CHANGED
@@ -1,8 +1,17 @@
1
1
  # Changelog
2
2
 
3
- ## [Unreleased]
3
+ ## [0.3.0] - 2026-10-02
4
4
 
5
- ### 0.2.0 (release preparation)
5
+ - Add explicit credit-note creation/undo and Advanced Sale fulfilment, pick, pack and shipment resources with readback and distinct POST/PUT semantics.
6
+ - Add sale-header creation plus product, stock availability and carrier reads so sandbox preparation uses resource methods throughout.
7
+ - Preserve caller-supplied task IDs, monetary values, restock and shipment collections; do not select eligibility, append lines or restore inventory implicitly.
8
+
9
+ ## [0.2.1] - 2026-10-02
10
+
11
+ - Keep decompression failures and malformed UTF-8 responses, including invalid decoded JSON strings, inside the sanitized error contract, preserving uncertain-write recovery without retries.
12
+ - Preserve callback identity when another webhook subscription has credentials matching this subscription's URL components; continue filtering secrets throughout free text.
13
+
14
+ ## [0.2.0] - 2026-09-29
6
15
 
7
16
  - Add explicit sale update/undo, order, invoice, payment, sale manual-journal, standalone journal, tax-rule and webhook operations while preserving existing read methods.
8
17
  - Send JSON payloads without rounding amounts or FX rates; distinguish parent sale IDs, document task IDs, payment IDs and webhook IDs.
data/README.md CHANGED
@@ -9,7 +9,7 @@ Version `0.2.0` adds explicit payment, order, invoice, journal, and webhook oper
9
9
  Add the gem to your Gemfile:
10
10
 
11
11
  ```ruby
12
- gem "cin7_core_api", github: "PostCo/cin7_core_api", ref: "<reviewed-full-commit-sha>"
12
+ gem "cin7_core_api", "0.3.0"
13
13
  ```
14
14
 
15
15
  Then run:
@@ -20,7 +20,39 @@ bundle install
20
20
 
21
21
  Ruby 3.3 or newer is required.
22
22
 
23
- The `0.2.0` source is prepared for review; this README does not assert that it has been published. Pin a reviewed source commit until a release is available.
23
+ Version `0.2.1` adds response-decoding safety and callback-identity fixes. Published `0.2.0` remains unchanged. Check RubyGems for publication availability; to evaluate a reviewed source before publication, pin its full commit SHA from this repository.
24
+
25
+ Version `0.3.0` adds the explicit native correction and sandbox preparation resources below. It includes the `0.2.1` safety fixes.
26
+
27
+ ## Native correction and sandbox preparation
28
+
29
+ These methods use the same sanitized errors and never retry. Payloads use Cin7 String field names. `sale_id:` identifies the parent sale; `task_id:` identifies the particular credit-note or fulfilment task.
30
+
31
+ | Resource method | HTTP contract |
32
+ | --- | --- |
33
+ | `sales.create(payload:)` | POST `sale`; create a header with caller-selected customer, sale type and options |
34
+ | `credit_notes.create(payload:)` | POST `sale/creditnote`; explicit `SaleID` and `TaskID` |
35
+ | `credit_notes.undo(task_id:)` | DELETE `sale/creditnote` with `TaskID` and `Void=false` |
36
+ | `fulfilments.for_sale(sale_id:, include_product_info: false)` | GET `sale/fulfilment`; preserve its `Fulfilments` response collection |
37
+ | `fulfilments.create(payload:)` | POST `sale/fulfilment`; explicit `SaleID` |
38
+ | `fulfilments.undo(task_id:)` | DELETE `sale/fulfilment` with `TaskID` and `Void=false` |
39
+ | `picks.for_task(task_id:, include_product_info: false)` | GET `sale/fulfilment/pick` |
40
+ | `packs.for_task(task_id:, include_product_info: false)` | GET `sale/fulfilment/pack` |
41
+ | `shipments.for_task(task_id:)` | GET `sale/fulfilment/ship` |
42
+ | `picks.create/update(payload:)` | POST/PUT `sale/fulfilment/pick`; explicit `TaskID` |
43
+ | `packs.create/update(payload:)` | POST/PUT `sale/fulfilment/pack`; explicit `TaskID` |
44
+ | `shipments.create/update(payload:)` | POST/PUT `sale/fulfilment/ship`; explicit `TaskID` |
45
+ | `products.list(**filters)` | GET `product`; supports documented product discovery filters |
46
+ | `product_availability.list(**filters)` | GET `ref/productavailability`; `page`, `limit`, `id`, `name`, `sku`, `location`, `batch`, `category` |
47
+ | `carriers.list(**filters)` | GET `ref/carrier`; `page`, `limit`, `carrier_id`, `description` |
48
+
49
+ Cin7 documents credit-note **POST**, not PUT. Use `create` for an explicit new task or a draft/not-available task; it does not overwrite an authorised note by itself. For a new note, the caller may supply the documented empty GUID `TaskID`; the gem never chooses or inserts it. Forward complete `Lines`, `AdditionalCharges` and `Restock` collections deliberately.
50
+
51
+ The provider's credit-note DELETE eligibility is unusually narrow and duplicated in its Blueprint: Advanced Sale with credit-note `TaskID = SaleID`. Its applicability to connector-created secondary notes is unproven. Exposing `undo` does not establish that a particular paid, taxed or restocked note can be rebuilt safely. The caller must inspect state, preserve payouts and inventory ownership, check the actual rejection/readback and recover uncertain outcomes before proceeding.
52
+
53
+ Fulfilment `create` can convert a Simple Sale to Advanced Sale. Pack and shipment **POST may append lines**, while **PUT replaces** eligible draft/not-available documents. Shipment PUT must include all required packed boxes. The caller must preserve quantities, locations, batches, boxes and shipment identity and verify inventory after any restoration. The gem does not authorise a previously fulfilled sale correction or run pick/pack/ship automatically.
54
+
55
+ The `products` filters are `id`, `page`, `limit`, `name`, `sku`, `modified_since`, `include_deprecated`, `include_bom`, `include_suppliers`, `include_movements`, `include_attachments`, `include_reorder_levels`, and `include_custom_prices`. Nil filters are omitted, boolean false is retained, and unsupported filters fail before dispatch.
24
56
 
25
57
  ## Authentication
26
58
 
@@ -253,7 +285,23 @@ mise exec -- bundle exec standardrb --cache false $(git ls-files '*.rb' '*.gemsp
253
285
  mise exec -- bundle exec rake build
254
286
  ```
255
287
 
256
- Stage intended new source/spec files before using the tracked-file lint command. CI tests Ruby 3.3 and 3.4. Specs use Faraday's test adapter and do not verify live accounting behavior. Inspect the built gem's file list before release: the gemspec packages only `lib/**/*.rb`, README, changelog and license. Preserve untracked research files. Publication and push require a separate release decision; RubyGems MFA remains required.
288
+ Stage intended new source/spec files before using the tracked-file lint command. CI tests Ruby 3.3 and 3.4. Specs use Faraday's test adapter and do not verify live accounting behavior. Inspect the built gem's file list before release: the gemspec packages only `lib/**/*.rb`, README, changelog and license. Preserve untracked research files.
289
+
290
+ ## Releasing
291
+
292
+ Publishing a GitHub release triggers `.github/workflows/release.yml`. It requires the tagged commit to be part of `main`, verifies the tag matches `v<VERSION>`, runs tests and lint, builds the gem, and publishes that exact version to RubyGems. Draft releases and ordinary branch pushes do not publish gems.
293
+
294
+ One-time setup: in the `cin7_core_api` gem's RubyGems **Trusted publishers** settings, register repository owner `PostCo`, repository `cin7_core_api`, workflow filename `release.yml`, and environment `release`. Use the same `release` environment in GitHub. [RubyGems Trusted Publishing](https://guides.rubygems.org/trusted-publishing/) uses GitHub OIDC, so no long-lived API key or interactive MFA code is needed in CI. Signing in locally does not configure this trust relationship.
295
+
296
+ For each new version:
297
+
298
+ 1. Update `lib/cin7_core_api/version.rb` and `CHANGELOG.md`, review the PR, and merge it into `main`.
299
+ 2. Create and publish a GitHub release at that merged commit, with a tag such as `v0.2.1` matching the gem version.
300
+ 3. Check the **Publish gem** workflow and verify the version is available on RubyGems before updating application dependencies.
301
+
302
+ The manually published `0.2.0` already exists. Do not republish it; this workflow is for subsequent versions. A failed attempt to publish an existing version does not replace that version. If a workflow is rerun after a partial success, check RubyGems first.
303
+
304
+ The manual fallback is `bundle exec rake release` from a clean, merged checkout. Tests and Standard run before Bundler's tag/push/publish steps. The main-branch ancestry guard belongs to the GitHub workflow; the manual command does not enforce it. Manual publishing still uses your RubyGems credentials and applicable MFA.
257
305
 
258
306
  ## CIN7 references
259
307
 
@@ -89,6 +89,34 @@ module Cin7CoreAPI
89
89
  @webhooks ||= Resources::Webhooks.new(connection)
90
90
  end
91
91
 
92
+ def fulfilments
93
+ @fulfilments ||= Resources::Fulfilments.new(connection)
94
+ end
95
+
96
+ def picks
97
+ @picks ||= Resources::Picks.new(connection)
98
+ end
99
+
100
+ def packs
101
+ @packs ||= Resources::Packs.new(connection)
102
+ end
103
+
104
+ def shipments
105
+ @shipments ||= Resources::Shipments.new(connection)
106
+ end
107
+
108
+ def products
109
+ @products ||= Resources::Products.new(connection)
110
+ end
111
+
112
+ def product_availability
113
+ @product_availability ||= Resources::ProductAvailability.new(connection)
114
+ end
115
+
116
+ def carriers
117
+ @carriers ||= Resources::Carriers.new(connection)
118
+ end
119
+
92
120
  def inspect
93
121
  "#<#{self.class}>"
94
122
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "faraday"
4
4
  require "json"
5
+ require "zlib"
5
6
 
6
7
  module Cin7CoreAPI
7
8
  class Connection
@@ -61,12 +62,10 @@ module Cin7CoreAPI
61
62
  context = {request_method: method, request_path: redactor.filter(path.split("?").first)}
62
63
  write = method != :get
63
64
 
64
- raw_response = @http.run_request(method, path, body, nil) do |request|
65
- request.params.update(params)
66
- end
65
+ raw_response = dispatch(method, path, body, params, context, write: write)
67
66
  parsed_body, valid_json = parse_body(raw_response.body)
68
67
  values = {"headers" => normalized_headers(raw_response.headers), "body" => parsed_body}
69
- sanitized = redactor.with_sensitive_values(values).filter(values)
68
+ sanitized = redactor.with_sensitive_values(values).filter(values, callback_redactor: redactor)
70
69
  response = Response.new(status: raw_response.status, headers: sanitized.fetch("headers"), body: sanitized.fetch("body"))
71
70
 
72
71
  raise_for_status!(response, context, write: write)
@@ -75,7 +74,13 @@ module Cin7CoreAPI
75
74
  end
76
75
 
77
76
  response
78
- rescue Faraday::Error => error
77
+ end
78
+
79
+ def dispatch(method, path, body, params, context, write:)
80
+ @http.run_request(method, path, body, nil) do |request|
81
+ request.params.update(params)
82
+ end
83
+ rescue Faraday::Error, Zlib::Error => error
79
84
  # Faraday exceptions can retain the entire authenticated request in their cause.
80
85
  raise TransportError.new("CIN7 Core transport failed (#{error.class})", ambiguous: write, **context), cause: nil
81
86
  end
@@ -87,11 +92,32 @@ module Cin7CoreAPI
87
92
  def parse_body(body)
88
93
  return [nil, true] if body.nil? || body.empty?
89
94
 
90
- [JSON.parse(body), true]
95
+ # JSON is UTF-8 even when the adapter labels its bytes as binary. Reject
96
+ # malformed success bodies, but keep rejection details safe to redact.
97
+ body = body.dup.force_encoding(Encoding::UTF_8)
98
+ return [body.scrub, false] unless body.valid_encoding?
99
+
100
+ parsed = JSON.parse(body)
101
+ # Some JSON parsers accept lone low-surrogate escapes and produce invalid
102
+ # strings. Do not expose or regex-filter partially decoded credentials.
103
+ valid_utf8?(parsed) ? [parsed, true] : [Redactor::FILTERED, false]
91
104
  rescue JSON::ParserError
92
105
  [body, false]
93
106
  end
94
107
 
108
+ def valid_utf8?(value)
109
+ case value
110
+ when Hash
111
+ value.all? { |key, entry| valid_utf8?(key) && valid_utf8?(entry) }
112
+ when Array
113
+ value.all? { |entry| valid_utf8?(entry) }
114
+ when String
115
+ value.valid_encoding?
116
+ else
117
+ true
118
+ end
119
+ end
120
+
95
121
  def raise_for_status!(response, context, write:)
96
122
  return if response.success?
97
123
 
@@ -18,7 +18,7 @@ module Cin7CoreAPI
18
18
  self.class.new(@secrets + sensitive_values(value))
19
19
  end
20
20
 
21
- def filter(value)
21
+ def filter(value, callback_redactor: self)
22
22
  case value
23
23
  when Hash
24
24
  value.each_with_object({}) do |(key, entry), result|
@@ -26,16 +26,18 @@ module Cin7CoreAPI
26
26
  result[key.to_s] = if sensitive_key?(key) || external_headers?(key)
27
27
  FILTERED
28
28
  elsif callback_url?(key) && entry.is_a?(String)
29
- filter_url(entry)
29
+ # Another subscription's credentials may equal this callback's
30
+ # integration ID or host label. Scope URL filtering to this record.
31
+ callback_redactor.with_sensitive_values(value).filter_url(entry)
30
32
  elsif structured_identifier?(key, entry)
31
33
  # Short header values must not corrupt identifiers or schema enums.
32
34
  @secrets.include?(entry) ? FILTERED : entry.dup
33
35
  else
34
- filter(entry)
36
+ filter(entry, callback_redactor: callback_redactor)
35
37
  end
36
38
  end
37
39
  when Array
38
- value.map { |entry| filter(entry) }
40
+ value.map { |entry| filter(entry, callback_redactor: callback_redactor) }
39
41
  when String
40
42
  filter_string(value)
41
43
  else
@@ -126,6 +128,8 @@ module Cin7CoreAPI
126
128
  []
127
129
  end
128
130
 
131
+ protected
132
+
129
133
  def filter_url(value)
130
134
  return FILTERED if @secrets.include?(value)
131
135
 
@@ -145,6 +149,8 @@ module Cin7CoreAPI
145
149
  FILTERED
146
150
  end
147
151
 
152
+ private
153
+
148
154
  def filter_authority(authority, host)
149
155
  _, separator, host_port = authority.rpartition("@")
150
156
  filtered_host = filter_url_component(host)
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class Carriers < Base
6
+ PARAMETERS = {page: "Page", limit: "Limit", carrier_id: "CarrierID", description: "Description"}.freeze
7
+
8
+ def list(**filters)
9
+ get("ref/carrier", params: filters, parameter_map: PARAMETERS)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -29,6 +29,16 @@ module Cin7CoreAPI
29
29
  require_parameter!(:sale_id, sale_id)
30
30
  get("sale/creditnote", params: options.merge(sale_id: sale_id), parameter_map: FOR_SALE_PARAMETERS)
31
31
  end
32
+
33
+ def create(payload:)
34
+ validate_payload!(payload, "SaleID", "TaskID")
35
+ connection.post("sale/creditnote", payload: payload)
36
+ end
37
+
38
+ def undo(task_id:)
39
+ require_parameter!(:task_id, task_id)
40
+ connection.delete("sale/creditnote", params: {"TaskID" => task_id, "Void" => false})
41
+ end
32
42
  end
33
43
  end
34
44
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class Fulfilments < Base
6
+ PARAMETERS = {sale_id: "SaleID", include_product_info: "IncludeProductInfo"}.freeze
7
+
8
+ def for_sale(sale_id:, **options)
9
+ require_parameter!(:sale_id, sale_id)
10
+ get("sale/fulfilment", params: options.merge(sale_id: sale_id), parameter_map: PARAMETERS)
11
+ end
12
+
13
+ def create(payload:)
14
+ validate_payload!(payload, "SaleID")
15
+ connection.post("sale/fulfilment", payload: payload)
16
+ end
17
+
18
+ def undo(task_id:)
19
+ require_parameter!(:task_id, task_id)
20
+ connection.delete("sale/fulfilment", params: {"TaskID" => task_id, "Void" => false})
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class Packs < Base
6
+ PARAMETERS = {task_id: "TaskID", include_product_info: "IncludeProductInfo"}.freeze
7
+
8
+ def for_task(task_id:, **options)
9
+ require_parameter!(:task_id, task_id)
10
+ get("sale/fulfilment/pack", params: options.merge(task_id: task_id), parameter_map: PARAMETERS)
11
+ end
12
+
13
+ def create(payload:)
14
+ validate_payload!(payload, "TaskID")
15
+ connection.post("sale/fulfilment/pack", payload: payload)
16
+ end
17
+
18
+ def update(payload:)
19
+ validate_payload!(payload, "TaskID")
20
+ connection.put("sale/fulfilment/pack", payload: payload)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class Picks < Base
6
+ PARAMETERS = {task_id: "TaskID", include_product_info: "IncludeProductInfo"}.freeze
7
+
8
+ def for_task(task_id:, **options)
9
+ require_parameter!(:task_id, task_id)
10
+ get("sale/fulfilment/pick", params: options.merge(task_id: task_id), parameter_map: PARAMETERS)
11
+ end
12
+
13
+ def create(payload:)
14
+ validate_payload!(payload, "TaskID")
15
+ connection.post("sale/fulfilment/pick", payload: payload)
16
+ end
17
+
18
+ def update(payload:)
19
+ validate_payload!(payload, "TaskID")
20
+ connection.put("sale/fulfilment/pick", payload: payload)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class ProductAvailability < Base
6
+ PARAMETERS = {
7
+ page: "Page", limit: "Limit", id: "ID", name: "Name", sku: "Sku",
8
+ location: "Location", batch: "Batch", category: "Category"
9
+ }.freeze
10
+
11
+ def list(**filters)
12
+ get("ref/productavailability", params: filters, parameter_map: PARAMETERS)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class Products < Base
6
+ PARAMETERS = {
7
+ id: "ID", page: "Page", limit: "Limit", name: "Name", sku: "Sku", modified_since: "ModifiedSince",
8
+ include_deprecated: "IncludeDeprecated", include_bom: "IncludeBOM", include_suppliers: "IncludeSuppliers",
9
+ include_movements: "IncludeMovements", include_attachments: "IncludeAttachments",
10
+ include_reorder_levels: "IncludeReorderLevels", include_custom_prices: "IncludeCustomPrices"
11
+ }.freeze
12
+
13
+ def list(**filters)
14
+ get("product", params: filters, parameter_map: PARAMETERS)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -41,6 +41,11 @@ module Cin7CoreAPI
41
41
  get("sale", params: options.merge(id: id), parameter_map: RETRIEVE_PARAMETERS)
42
42
  end
43
43
 
44
+ def create(payload:)
45
+ validate_payload!(payload)
46
+ connection.post("sale", payload: payload)
47
+ end
48
+
44
49
  def update(payload:)
45
50
  validate_payload!(payload, "ID")
46
51
  connection.put("sale", payload: payload)
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cin7CoreAPI
4
+ module Resources
5
+ class Shipments < Base
6
+ def for_task(task_id:)
7
+ require_parameter!(:task_id, task_id)
8
+ get("sale/fulfilment/ship", params: {task_id: task_id}, parameter_map: {task_id: "TaskID"})
9
+ end
10
+
11
+ def create(payload:)
12
+ validate_payload!(payload, "TaskID")
13
+ connection.post("sale/fulfilment/ship", payload: payload)
14
+ end
15
+
16
+ def update(payload:)
17
+ validate_payload!(payload, "TaskID")
18
+ connection.put("sale/fulfilment/ship", payload: payload)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cin7CoreAPI
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/cin7_core_api.rb CHANGED
@@ -21,6 +21,13 @@ require_relative "cin7_core_api/resources/manual_journals"
21
21
  require_relative "cin7_core_api/resources/journals"
22
22
  require_relative "cin7_core_api/resources/tax_rules"
23
23
  require_relative "cin7_core_api/resources/webhooks"
24
+ require_relative "cin7_core_api/resources/fulfilments"
25
+ require_relative "cin7_core_api/resources/picks"
26
+ require_relative "cin7_core_api/resources/packs"
27
+ require_relative "cin7_core_api/resources/shipments"
28
+ require_relative "cin7_core_api/resources/products"
29
+ require_relative "cin7_core_api/resources/product_availability"
30
+ require_relative "cin7_core_api/resources/carriers"
24
31
  require_relative "cin7_core_api/client"
25
32
 
26
33
  module Cin7CoreAPI
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cin7_core_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - PostCo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-09-29 00:00:00.000000000 Z
11
+ date: 2026-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -123,17 +123,24 @@ files:
123
123
  - lib/cin7_core_api/resources/accounts.rb
124
124
  - lib/cin7_core_api/resources/bank_accounts.rb
125
125
  - lib/cin7_core_api/resources/base.rb
126
+ - lib/cin7_core_api/resources/carriers.rb
126
127
  - lib/cin7_core_api/resources/credit_notes.rb
127
128
  - lib/cin7_core_api/resources/customer_credits.rb
128
129
  - lib/cin7_core_api/resources/customers.rb
130
+ - lib/cin7_core_api/resources/fulfilments.rb
129
131
  - lib/cin7_core_api/resources/invoices.rb
130
132
  - lib/cin7_core_api/resources/journals.rb
131
133
  - lib/cin7_core_api/resources/locations.rb
132
134
  - lib/cin7_core_api/resources/manual_journals.rb
133
135
  - lib/cin7_core_api/resources/me.rb
134
136
  - lib/cin7_core_api/resources/orders.rb
137
+ - lib/cin7_core_api/resources/packs.rb
135
138
  - lib/cin7_core_api/resources/payments.rb
139
+ - lib/cin7_core_api/resources/picks.rb
140
+ - lib/cin7_core_api/resources/product_availability.rb
141
+ - lib/cin7_core_api/resources/products.rb
136
142
  - lib/cin7_core_api/resources/sales.rb
143
+ - lib/cin7_core_api/resources/shipments.rb
137
144
  - lib/cin7_core_api/resources/tax_rules.rb
138
145
  - lib/cin7_core_api/resources/webhooks.rb
139
146
  - lib/cin7_core_api/response.rb