printavo-ruby 0.4.0 → 0.5.1
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/README.md +52 -1
- data/docs/CHANGELOG.md +16 -0
- data/lib/printavo/client.rb +2 -0
- data/lib/printavo/config.rb +3 -1
- data/lib/printavo/connection.rb +2 -0
- data/lib/printavo/errors.rb +2 -0
- data/lib/printavo/graphql_client.rb +2 -0
- data/lib/printavo/models/base.rb +2 -0
- data/lib/printavo/models/customer.rb +2 -0
- data/lib/printavo/models/inquiry.rb +2 -0
- data/lib/printavo/models/job.rb +2 -0
- data/lib/printavo/models/order.rb +2 -0
- data/lib/printavo/models/status.rb +2 -0
- data/lib/printavo/page.rb +2 -0
- data/lib/printavo/resources/base.rb +2 -0
- data/lib/printavo/resources/customers.rb +59 -31
- data/lib/printavo/resources/inquiries.rb +31 -49
- data/lib/printavo/resources/jobs.rb +4 -31
- data/lib/printavo/resources/orders.rb +69 -49
- data/lib/printavo/resources/statuses.rb +4 -25
- data/lib/printavo/version.rb +3 -1
- data/lib/printavo/webhooks.rb +2 -0
- data/lib/printavo.rb +2 -0
- 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: 34f4d971a1f4d0c685fb6780bc12d7737c915d533bc49c9d96fb5c73522eec58
|
|
4
|
+
data.tar.gz: 687c158df7fa205ac7aa5607bb2c6a7171ee7eac972005b0b5d102cee3b7dd0d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 402856b46761b8a924bd92a5e433d99faf0f5aa976b9e7e9e4a2e35ee814dda18e4caddafe40f890507832535e233596e6979a439a26895bf20a8caefe8979ad
|
|
7
|
+
data.tar.gz: dd48f4059d8d5d596e1a3e569cdecaa3842c79713ea2da48c112c86664c42f418c035988bbc9c11e48e337508e6af6aa8f6c9938bacf762eda79a5b2e6366e76
|
data/README.md
CHANGED
|
@@ -136,6 +136,57 @@ end
|
|
|
136
136
|
all_jobs = client.jobs.all_pages(order_id: "99")
|
|
137
137
|
```
|
|
138
138
|
|
|
139
|
+
### Mutations
|
|
140
|
+
|
|
141
|
+
#### Customers
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
# Create
|
|
145
|
+
customer = client.customers.create(
|
|
146
|
+
primary_contact: { firstName: "Jane", lastName: "Smith", email: "jane@example.com" },
|
|
147
|
+
company_name: "Acme Shirts"
|
|
148
|
+
)
|
|
149
|
+
puts customer.full_name # => "Jane Smith"
|
|
150
|
+
puts customer.company # => "Acme Shirts"
|
|
151
|
+
|
|
152
|
+
# Update
|
|
153
|
+
customer = client.customers.update("42", company_name: "New Name Inc")
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### Orders
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
# Create (Printavo creates orders as quotes first)
|
|
160
|
+
order = client.orders.create(
|
|
161
|
+
contact: { id: "456" },
|
|
162
|
+
due_at: "2026-06-01T09:00:00Z",
|
|
163
|
+
customer_due_at: "2026-06-01",
|
|
164
|
+
nickname: "Summer Rush"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Update
|
|
168
|
+
order = client.orders.update("99", nickname: "Rush Job", production_note: "Ships Friday")
|
|
169
|
+
|
|
170
|
+
# Move to a new status
|
|
171
|
+
registry = client.statuses.registry
|
|
172
|
+
order = client.orders.update_status("99", status_id: registry[:in_production].id)
|
|
173
|
+
puts order.status # => "In Production"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
#### Inquiries
|
|
177
|
+
|
|
178
|
+
```ruby
|
|
179
|
+
# Create
|
|
180
|
+
inquiry = client.inquiries.create(
|
|
181
|
+
name: "Bob Johnson",
|
|
182
|
+
email: "bob@example.com",
|
|
183
|
+
request: "100 hoodies, front + back print"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Update
|
|
187
|
+
inquiry = client.inquiries.update("55", nickname: "Hoodies Rush")
|
|
188
|
+
```
|
|
189
|
+
|
|
139
190
|
### Statuses
|
|
140
191
|
|
|
141
192
|
```ruby
|
|
@@ -294,7 +345,7 @@ end
|
|
|
294
345
|
| 0.2.0 | Status registry + Inquiries ✅ |
|
|
295
346
|
| 0.3.0 | Pagination helpers (`each_page`, `all_pages`) + `bin/lint` ✅ |
|
|
296
347
|
| 0.4.0 | Expanded GraphQL DSL (`mutate`, `paginate`) ✅ |
|
|
297
|
-
| 0.5.0 | Mutations (create/update) |
|
|
348
|
+
| 0.5.0 | Mutations (create/update) ✅ |
|
|
298
349
|
| 0.6.0 | Analytics / Reporting queries |
|
|
299
350
|
| 0.7.0 | Community burn-in / API stabilization |
|
|
300
351
|
| 0.8.0 | Retry/backoff + rate limit awareness |
|
data/docs/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.5.0] - 2026-03-30
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- `Customers#create(primary_contact:, **input)` — `customerCreate` mutation; normalizes `primaryContact` + `companyName` response fields to match the read-side `Customer` model
|
|
15
|
+
- `Customers#update(id, **input)` — `customerUpdate` mutation
|
|
16
|
+
- `Orders#create(**input)` — `quoteCreate` mutation; normalizes `total` → `totalPrice` in response
|
|
17
|
+
- `Orders#update(id, **input)` — `quoteUpdate` mutation
|
|
18
|
+
- `Orders#update_status(id, status_id:)` — `statusUpdate` mutation; handles `OrderUnion (Quote | Invoice)` via inline fragments
|
|
19
|
+
- `Inquiries#create(**input)` — `inquiryCreate` mutation
|
|
20
|
+
- `Inquiries#update(id, **input)` — `inquiryUpdate` mutation
|
|
21
|
+
- All mutation methods accept snake_case keyword args and camelize them for GraphQL input
|
|
22
|
+
- `CREATE_MUTATION` and `UPDATE_MUTATION` constants on `Customers`, `Orders`, `Inquiries`; `UPDATE_STATUS_MUTATION` on `Orders`
|
|
23
|
+
- Private `build_customer` and `build_order` normalizers centralize mutation response mapping
|
|
24
|
+
- Private `camelize_keys` on `Customers` and `Orders` converts `snake_case` → `camelCase` for input variables
|
|
25
|
+
- Factory helpers `fake_customer_mutation_response` and `fake_order_mutation_response` for testing
|
|
26
|
+
|
|
11
27
|
## [0.4.0] - 2026-03-30
|
|
12
28
|
|
|
13
29
|
### Added
|
data/lib/printavo/client.rb
CHANGED
data/lib/printavo/config.rb
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# lib/printavo/config.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
module Printavo
|
|
3
5
|
class Config
|
|
4
6
|
attr_accessor :email, :token, :base_url, :timeout
|
|
5
7
|
|
|
6
|
-
BASE_URL = 'https://www.printavo.com/api/v2'
|
|
8
|
+
BASE_URL = 'https://www.printavo.com/api/v2'
|
|
7
9
|
|
|
8
10
|
def initialize
|
|
9
11
|
@base_url = BASE_URL
|
data/lib/printavo/connection.rb
CHANGED
data/lib/printavo/errors.rb
CHANGED
data/lib/printavo/models/base.rb
CHANGED
data/lib/printavo/models/job.rb
CHANGED
data/lib/printavo/page.rb
CHANGED
|
@@ -1,38 +1,13 @@
|
|
|
1
1
|
# lib/printavo/resources/customers.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
module Printavo
|
|
3
5
|
module Resources
|
|
4
6
|
class Customers < Base
|
|
5
|
-
ALL_QUERY
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
id
|
|
10
|
-
firstName
|
|
11
|
-
lastName
|
|
12
|
-
email
|
|
13
|
-
phone
|
|
14
|
-
company
|
|
15
|
-
}
|
|
16
|
-
pageInfo {
|
|
17
|
-
hasNextPage
|
|
18
|
-
endCursor
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
GQL
|
|
23
|
-
|
|
24
|
-
FIND_QUERY = <<~GQL.freeze
|
|
25
|
-
query Customer($id: ID!) {
|
|
26
|
-
customer(id: $id) {
|
|
27
|
-
id
|
|
28
|
-
firstName
|
|
29
|
-
lastName
|
|
30
|
-
email
|
|
31
|
-
phone
|
|
32
|
-
company
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
GQL
|
|
7
|
+
ALL_QUERY = File.read(File.join(__dir__, '../graphql/customers/all.graphql')).freeze
|
|
8
|
+
FIND_QUERY = File.read(File.join(__dir__, '../graphql/customers/find.graphql')).freeze
|
|
9
|
+
CREATE_MUTATION = File.read(File.join(__dir__, '../graphql/customers/create.graphql')).freeze
|
|
10
|
+
UPDATE_MUTATION = File.read(File.join(__dir__, '../graphql/customers/update.graphql')).freeze
|
|
36
11
|
|
|
37
12
|
def all(first: 25, after: nil)
|
|
38
13
|
fetch_page(first: first, after: after).records
|
|
@@ -43,6 +18,36 @@ module Printavo
|
|
|
43
18
|
Printavo::Customer.new(data['customer'])
|
|
44
19
|
end
|
|
45
20
|
|
|
21
|
+
# Creates a new customer. Requires a +primary_contact+ hash with at least
|
|
22
|
+
# +firstName+ and +email+. Optional keyword arguments map to CustomerCreateInput.
|
|
23
|
+
#
|
|
24
|
+
# @param primary_contact [Hash] contact fields (firstName, lastName, email, phone)
|
|
25
|
+
# @return [Printavo::Customer]
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
# client.customers.create(
|
|
29
|
+
# primary_contact: { firstName: "Jane", lastName: "Smith", email: "jane@example.com" },
|
|
30
|
+
# company_name: "Acme Shirts"
|
|
31
|
+
# )
|
|
32
|
+
def create(primary_contact:, **input)
|
|
33
|
+
variables = { input: camelize_keys(input).merge(primaryContact: primary_contact) }
|
|
34
|
+
data = @graphql.mutate(CREATE_MUTATION, variables: variables)
|
|
35
|
+
build_customer(data['customerCreate'])
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Updates an existing customer by ID.
|
|
39
|
+
#
|
|
40
|
+
# @param id [String, Integer]
|
|
41
|
+
# @return [Printavo::Customer]
|
|
42
|
+
#
|
|
43
|
+
# @example
|
|
44
|
+
# client.customers.update("42", company_name: "New Name")
|
|
45
|
+
def update(id, **input)
|
|
46
|
+
data = @graphql.mutate(UPDATE_MUTATION,
|
|
47
|
+
variables: { id: id.to_s, input: camelize_keys(input) })
|
|
48
|
+
build_customer(data['customerUpdate'])
|
|
49
|
+
end
|
|
50
|
+
|
|
46
51
|
private
|
|
47
52
|
|
|
48
53
|
def fetch_page(first: 25, after: nil, **)
|
|
@@ -55,6 +60,29 @@ module Printavo
|
|
|
55
60
|
end_cursor: page_info['endCursor']
|
|
56
61
|
)
|
|
57
62
|
end
|
|
63
|
+
|
|
64
|
+
# Normalizes a mutation response into the shape Customer.new expects.
|
|
65
|
+
# The mutation returns companyName + nested primaryContact; our model
|
|
66
|
+
# reads company, firstName, lastName, email, phone from the top level.
|
|
67
|
+
def build_customer(attrs)
|
|
68
|
+
return nil unless attrs
|
|
69
|
+
|
|
70
|
+
normalized = attrs.dup
|
|
71
|
+
normalized['company'] ||= attrs['companyName']
|
|
72
|
+
if (contact = attrs['primaryContact'])
|
|
73
|
+
%w[firstName lastName email phone].each do |field|
|
|
74
|
+
normalized[field] ||= contact[field]
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
Printavo::Customer.new(normalized)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Converts snake_case Ruby keyword args to camelCase for GraphQL input.
|
|
81
|
+
def camelize_keys(hash)
|
|
82
|
+
hash.transform_keys do |key|
|
|
83
|
+
key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
|
|
84
|
+
end
|
|
85
|
+
end
|
|
58
86
|
end
|
|
59
87
|
end
|
|
60
88
|
end
|
|
@@ -1,56 +1,13 @@
|
|
|
1
1
|
# lib/printavo/resources/inquiries.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
module Printavo
|
|
3
5
|
module Resources
|
|
4
6
|
class Inquiries < Base
|
|
5
|
-
ALL_QUERY
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
id
|
|
10
|
-
nickname
|
|
11
|
-
totalPrice
|
|
12
|
-
status {
|
|
13
|
-
id
|
|
14
|
-
name
|
|
15
|
-
color
|
|
16
|
-
}
|
|
17
|
-
customer {
|
|
18
|
-
id
|
|
19
|
-
firstName
|
|
20
|
-
lastName
|
|
21
|
-
email
|
|
22
|
-
company
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
pageInfo {
|
|
26
|
-
hasNextPage
|
|
27
|
-
endCursor
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
GQL
|
|
32
|
-
|
|
33
|
-
FIND_QUERY = <<~GQL.freeze
|
|
34
|
-
query Inquiry($id: ID!) {
|
|
35
|
-
inquiry(id: $id) {
|
|
36
|
-
id
|
|
37
|
-
nickname
|
|
38
|
-
totalPrice
|
|
39
|
-
status {
|
|
40
|
-
id
|
|
41
|
-
name
|
|
42
|
-
color
|
|
43
|
-
}
|
|
44
|
-
customer {
|
|
45
|
-
id
|
|
46
|
-
firstName
|
|
47
|
-
lastName
|
|
48
|
-
email
|
|
49
|
-
company
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
GQL
|
|
7
|
+
ALL_QUERY = File.read(File.join(__dir__, '../graphql/inquiries/all.graphql')).freeze
|
|
8
|
+
FIND_QUERY = File.read(File.join(__dir__, '../graphql/inquiries/find.graphql')).freeze
|
|
9
|
+
CREATE_MUTATION = File.read(File.join(__dir__, '../graphql/inquiries/create.graphql')).freeze
|
|
10
|
+
UPDATE_MUTATION = File.read(File.join(__dir__, '../graphql/inquiries/update.graphql')).freeze
|
|
54
11
|
|
|
55
12
|
def all(first: 25, after: nil)
|
|
56
13
|
fetch_page(first: first, after: after).records
|
|
@@ -61,6 +18,31 @@ module Printavo
|
|
|
61
18
|
Printavo::Inquiry.new(data['inquiry'])
|
|
62
19
|
end
|
|
63
20
|
|
|
21
|
+
# Creates a new inquiry. Requires +name:+ at minimum.
|
|
22
|
+
#
|
|
23
|
+
# @return [Printavo::Inquiry]
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# client.inquiries.create(name: "Jane Smith", email: "jane@example.com",
|
|
27
|
+
# request: "100 hoodies, front + back print")
|
|
28
|
+
def create(**input)
|
|
29
|
+
data = @graphql.mutate(CREATE_MUTATION, variables: { input: input })
|
|
30
|
+
Printavo::Inquiry.new(data['inquiryCreate'])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Updates an existing inquiry by ID.
|
|
34
|
+
#
|
|
35
|
+
# @param id [String, Integer]
|
|
36
|
+
# @return [Printavo::Inquiry]
|
|
37
|
+
#
|
|
38
|
+
# @example
|
|
39
|
+
# client.inquiries.update("55", nickname: "Hoodies Rush")
|
|
40
|
+
def update(id, **input)
|
|
41
|
+
data = @graphql.mutate(UPDATE_MUTATION,
|
|
42
|
+
variables: { id: id.to_s, input: input })
|
|
43
|
+
Printavo::Inquiry.new(data['inquiryUpdate'])
|
|
44
|
+
end
|
|
45
|
+
|
|
64
46
|
private
|
|
65
47
|
|
|
66
48
|
def fetch_page(first: 25, after: nil, **)
|
|
@@ -1,38 +1,11 @@
|
|
|
1
1
|
# lib/printavo/resources/jobs.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
module Printavo
|
|
3
5
|
module Resources
|
|
4
6
|
class Jobs < Base
|
|
5
|
-
ALL_QUERY
|
|
6
|
-
|
|
7
|
-
order(id: $orderId) {
|
|
8
|
-
lineItems(first: $first, after: $after) {
|
|
9
|
-
nodes {
|
|
10
|
-
id
|
|
11
|
-
name
|
|
12
|
-
quantity
|
|
13
|
-
price
|
|
14
|
-
taxable
|
|
15
|
-
}
|
|
16
|
-
pageInfo {
|
|
17
|
-
hasNextPage
|
|
18
|
-
endCursor
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
GQL
|
|
24
|
-
|
|
25
|
-
FIND_QUERY = <<~GQL.freeze
|
|
26
|
-
query LineItem($id: ID!) {
|
|
27
|
-
lineItem(id: $id) {
|
|
28
|
-
id
|
|
29
|
-
name
|
|
30
|
-
quantity
|
|
31
|
-
price
|
|
32
|
-
taxable
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
GQL
|
|
7
|
+
ALL_QUERY = File.read(File.join(__dir__, '../graphql/jobs/all.graphql')).freeze
|
|
8
|
+
FIND_QUERY = File.read(File.join(__dir__, '../graphql/jobs/find.graphql')).freeze
|
|
36
9
|
|
|
37
10
|
def all(order_id:, first: 25, after: nil)
|
|
38
11
|
fetch_page(order_id: order_id, first: first, after: after).records
|
|
@@ -1,56 +1,16 @@
|
|
|
1
1
|
# lib/printavo/resources/orders.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
module Printavo
|
|
3
5
|
module Resources
|
|
4
6
|
class Orders < Base
|
|
5
|
-
ALL_QUERY
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
status {
|
|
13
|
-
id
|
|
14
|
-
name
|
|
15
|
-
color
|
|
16
|
-
}
|
|
17
|
-
customer {
|
|
18
|
-
id
|
|
19
|
-
firstName
|
|
20
|
-
lastName
|
|
21
|
-
email
|
|
22
|
-
company
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
pageInfo {
|
|
26
|
-
hasNextPage
|
|
27
|
-
endCursor
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
GQL
|
|
32
|
-
|
|
33
|
-
FIND_QUERY = <<~GQL.freeze
|
|
34
|
-
query Order($id: ID!) {
|
|
35
|
-
order(id: $id) {
|
|
36
|
-
id
|
|
37
|
-
nickname
|
|
38
|
-
totalPrice
|
|
39
|
-
status {
|
|
40
|
-
id
|
|
41
|
-
name
|
|
42
|
-
color
|
|
43
|
-
}
|
|
44
|
-
customer {
|
|
45
|
-
id
|
|
46
|
-
firstName
|
|
47
|
-
lastName
|
|
48
|
-
email
|
|
49
|
-
company
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
GQL
|
|
7
|
+
ALL_QUERY = File.read(File.join(__dir__, '../graphql/orders/all.graphql')).freeze
|
|
8
|
+
FIND_QUERY = File.read(File.join(__dir__, '../graphql/orders/find.graphql')).freeze
|
|
9
|
+
# Printavo creates orders as quotes first; the mutation is quoteCreate.
|
|
10
|
+
CREATE_MUTATION = File.read(File.join(__dir__, '../graphql/orders/create.graphql')).freeze
|
|
11
|
+
UPDATE_MUTATION = File.read(File.join(__dir__, '../graphql/orders/update.graphql')).freeze
|
|
12
|
+
# statusUpdate returns an OrderUnion (Quote | Invoice) — requires fragments.
|
|
13
|
+
UPDATE_STATUS_MUTATION = File.read(File.join(__dir__, '../graphql/orders/update_status.graphql')).freeze
|
|
54
14
|
|
|
55
15
|
def all(first: 25, after: nil)
|
|
56
16
|
fetch_page(first: first, after: after).records
|
|
@@ -61,6 +21,50 @@ module Printavo
|
|
|
61
21
|
Printavo::Order.new(data['order'])
|
|
62
22
|
end
|
|
63
23
|
|
|
24
|
+
# Creates a new order (quote) in Printavo.
|
|
25
|
+
# Requires at minimum +contact:+ (IDInput), +due_at:+, and +customer_due_at:+.
|
|
26
|
+
#
|
|
27
|
+
# @return [Printavo::Order]
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# client.orders.create(
|
|
31
|
+
# contact: { id: "456" },
|
|
32
|
+
# due_at: "2026-06-01T09:00:00Z",
|
|
33
|
+
# customer_due_at: "2026-06-01"
|
|
34
|
+
# )
|
|
35
|
+
def create(**input)
|
|
36
|
+
data = @graphql.mutate(CREATE_MUTATION, variables: { input: camelize_keys(input) })
|
|
37
|
+
build_order(data['quoteCreate'])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Updates an existing order (quote or invoice) by ID.
|
|
41
|
+
#
|
|
42
|
+
# @param id [String, Integer]
|
|
43
|
+
# @return [Printavo::Order]
|
|
44
|
+
#
|
|
45
|
+
# @example
|
|
46
|
+
# client.orders.update("99", nickname: "Rush Job", production_note: "Ships Friday")
|
|
47
|
+
def update(id, **input)
|
|
48
|
+
data = @graphql.mutate(UPDATE_MUTATION,
|
|
49
|
+
variables: { id: id.to_s, input: camelize_keys(input) })
|
|
50
|
+
build_order(data['quoteUpdate'])
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Moves an order to a new status.
|
|
54
|
+
#
|
|
55
|
+
# @param id [String, Integer] order (quote/invoice) ID
|
|
56
|
+
# @param status_id [String, Integer] target status ID
|
|
57
|
+
# @return [Printavo::Order]
|
|
58
|
+
#
|
|
59
|
+
# @example
|
|
60
|
+
# registry = client.statuses.registry
|
|
61
|
+
# client.orders.update_status("99", status_id: registry[:in_production].id)
|
|
62
|
+
def update_status(id, status_id:)
|
|
63
|
+
data = @graphql.mutate(UPDATE_STATUS_MUTATION,
|
|
64
|
+
variables: { parentId: id.to_s, statusId: status_id.to_s })
|
|
65
|
+
build_order(data['statusUpdate'])
|
|
66
|
+
end
|
|
67
|
+
|
|
64
68
|
private
|
|
65
69
|
|
|
66
70
|
def fetch_page(first: 25, after: nil, **)
|
|
@@ -73,6 +77,22 @@ module Printavo
|
|
|
73
77
|
end_cursor: page_info['endCursor']
|
|
74
78
|
)
|
|
75
79
|
end
|
|
80
|
+
|
|
81
|
+
# Normalizes mutation response: quoteCreate/quoteUpdate return `total`
|
|
82
|
+
# rather than `totalPrice`. Map it so Order model accessors work unchanged.
|
|
83
|
+
def build_order(attrs)
|
|
84
|
+
return nil unless attrs
|
|
85
|
+
|
|
86
|
+
normalized = attrs.dup
|
|
87
|
+
normalized['totalPrice'] ||= attrs['total']
|
|
88
|
+
Printavo::Order.new(normalized)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def camelize_keys(hash)
|
|
92
|
+
hash.transform_keys do |key|
|
|
93
|
+
key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
76
96
|
end
|
|
77
97
|
end
|
|
78
98
|
end
|
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
# lib/printavo/resources/statuses.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
module Printavo
|
|
3
5
|
module Resources
|
|
4
6
|
class Statuses < Base
|
|
5
|
-
ALL_QUERY
|
|
6
|
-
|
|
7
|
-
statuses(first: $first, after: $after) {
|
|
8
|
-
nodes {
|
|
9
|
-
id
|
|
10
|
-
name
|
|
11
|
-
color
|
|
12
|
-
}
|
|
13
|
-
pageInfo {
|
|
14
|
-
hasNextPage
|
|
15
|
-
endCursor
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
GQL
|
|
20
|
-
|
|
21
|
-
FIND_QUERY = <<~GQL.freeze
|
|
22
|
-
query Status($id: ID!) {
|
|
23
|
-
status(id: $id) {
|
|
24
|
-
id
|
|
25
|
-
name
|
|
26
|
-
color
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
GQL
|
|
7
|
+
ALL_QUERY = File.read(File.join(__dir__, '../graphql/statuses/all.graphql')).freeze
|
|
8
|
+
FIND_QUERY = File.read(File.join(__dir__, '../graphql/statuses/find.graphql')).freeze
|
|
30
9
|
|
|
31
10
|
def all(first: 100, after: nil)
|
|
32
11
|
fetch_page(first: first, after: after).records
|
data/lib/printavo/version.rb
CHANGED
data/lib/printavo/webhooks.rb
CHANGED
data/lib/printavo.rb
CHANGED