printavo-ruby 0.6.0 → 0.7.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: 3563777c538165a00ca4888be9d489c6a0e9b14542dac6d02a18b60894826f7d
4
- data.tar.gz: ceb47bf69ff0dc7f48888d4fee3f601aa621015f8028e6dd0af31e2037b36749
3
+ metadata.gz: 4f1b8022189ac0b62b87b7d9770c08b3f2320c6804705c41afd6e2b03c7239ca
4
+ data.tar.gz: 94761c4186f08d33b841eb9d364350f142c5b7b007d0f1fce2c08e7e237156d8
5
5
  SHA512:
6
- metadata.gz: b266887065b5f727b6f9660557ce37d7ab64b53f23033f5c64c678cae919f00cd21e169fee17177bce7e873fdcc9d978307a3254e20de0224aab4b8e9c462d97
7
- data.tar.gz: 4d1c944ca7283bab4e45dfe3cde0ddc6acf3ea35a167ee7b49574b6f7e367fff77a833253976605e2f8219aea932d5056b04004fcb55553cd4975bdfe853b3fe
6
+ metadata.gz: 5c22e476b535a7eebe9fba9a51ed5a36016a6da07c3f8f4e5cce478d609ee358316097f06bab770ebcdb3ec2cd43b0b5939bdc109394237691b0a4f8370cd6b4
7
+ data.tar.gz: 266b1fd4d0e738ca3928225681367371f6e3dc7ac26a1771e8758ff2ea6cac6adc40130e57bf7553d043a99fb2a464c1c0d609489c6f6ae83fde1568821ba716
data/docs/CHANGELOG.md CHANGED
@@ -6,6 +6,27 @@ All notable changes to this project will be documented in this file.
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
8
 
9
+ ## [0.7.0] - 2026-03-30
10
+
11
+ ### Added
12
+ - `Printavo::Transaction` model (`id`, `amount`, `kind`, `created_at`)
13
+ - `Transactions` resource: `all(order_id:)`, `find(id)` — scoped to an order, same pattern as Jobs
14
+ - `Printavo::TransactionPayment` model (`id`, `amount`, `payment_method`, `paid_at`, `note`)
15
+ - `TransactionPayments` resource: `create(**input)`, `update(id, **input)`, `delete(id)` —
16
+ mutation-only; `transactionPaymentCreate/Update/Delete`
17
+ - `Printavo::Task` model (`id`, `body`, `due_at`, `completed_at`, `completed?`, `assignee`)
18
+ - `Tasks` resource: `all`, `find(id)`, `create(**input)`, `update(id, **input)`,
19
+ `complete(id)` (sets `completedAt` to now via `taskUpdate`), `delete(id)`
20
+ - `Printavo::Thread` model (`id`, `subject`, `created_at`, `updated_at`)
21
+ - `Threads` resource: `all(order_id:)`, `find(id)`, `update(id, **input)`,
22
+ `email_message_create(**input)` — `threadUpdate` + `emailMessageCreate` mutations;
23
+ returns raw hash (no `EmailMessage` model yet)
24
+ - `client.tasks`, `client.threads`, `client.transactions`, `client.transaction_payments`
25
+ entry points on `Printavo::Client`
26
+ - 14 new `.graphql` files under `lib/printavo/graphql/`
27
+ - `Client#login` / `Client#logout` raise `NotImplementedError` with a message directing
28
+ consumers to the `email` + `token` initializer; gem uses stateless header-based auth
29
+
9
30
  ## [0.6.0] - 2026-03-30
10
31
 
11
32
  ### Added
data/docs/TODO.md CHANGED
@@ -21,6 +21,7 @@ Full task list for `printavo-ruby` across all versions. Checked items are shippe
21
21
  - [x] GitHub Actions CI: Ruby 3.3 + Ruby 4.0 matrix
22
22
  - [x] Automated RubyGems publish on `v*` tag via trusted publishing (`release.yml`)
23
23
  - [x] Git pre-push hook: guards `Gemfile.lock` version sync and `x86_64-linux` platform
24
+ - [x] `Client#login` / `Client#logout` — raise `NotImplementedError`; gem uses header-based auth, not session mutations
24
25
 
25
26
  ---
26
27
 
@@ -51,6 +52,13 @@ Full task list for `printavo-ruby` across all versions. Checked items are shippe
51
52
  - [x] `Inquiries#update(id, **input)` — `inquiryUpdate`
52
53
  - [x] `camelize_keys` — snake_case → camelCase input conversion
53
54
  - [x] `build_customer` / `build_order` — mutation response normalization helpers
55
+ - [ ] `Contacts#delete(id)` — `contactDelete`
56
+ - [ ] `Customers#delete(id)` — `customerDelete`
57
+ - [ ] `Inquiries#delete(id)` — `inquiryDelete`
58
+ - [ ] `Invoices#delete(id)` — `invoiceDelete`
59
+ - [ ] `Invoices#duplicate(id)` — `invoiceDuplicate`
60
+ - [ ] `Orders#delete(id)` — `quoteDelete`
61
+ - [ ] `Orders#duplicate(id)` — `quoteDuplicate`
54
62
 
55
63
  ---
56
64
 
@@ -100,7 +108,9 @@ return values — they are exposed via model field accessors, not separate resou
100
108
  - `EmailMessage`, `TextMessage` — message subtypes under `Thread`
101
109
  - `Feature`, `FeatureRestriction` — embedded in `Account.features`
102
110
  - `LineItemEnabledColumns`, `LineItemGroupSize`, `LineItemPriceReceipt`, `LineItemSizeCount` — embedded in `LineItemGroup` / `LineItem`
103
- - `LoggedIn` — auth response type
111
+ - `LoggedIn` — auth response type for `login` / `logout` mutations; not wrapped — gem uses
112
+ header-based auth. Both methods raise `NotImplementedError` on `Printavo::Client` with a
113
+ message directing consumers to the `email` + `token` initializer pattern.
104
114
  - `MerchOrderDelivery`, `MerchStoreSummary` — embedded in `MerchOrder` / `MerchStore`
105
115
  - `MessageAttachment` — embedded in `Thread` messages
106
116
  - `ObjectTimestamps` — `createdAt` / `updatedAt` on all objects
@@ -135,12 +145,16 @@ return values — they are exposed via model field accessors, not separate resou
135
145
  - [x] `Invoices` resource: `all`, `find(id)`, `update`
136
146
  - [x] `client.invoices` entry point on `Printavo::Client`
137
147
 
148
+ ---
149
+
138
150
  ### Approvals
139
151
 
140
- - [ ] `Printavo::Approval` model (`id`, `status`, `approvedAt`, `contact`)
141
- - [ ] `Printavo::ApprovalRequest` model (`id`, `sentAt`, `expiresAt`, `approval`)
142
- - [ ] `Approvals` resource: `all(order_id:)`, `find(id)`
143
- - [ ] `approvalCreate`, `approvalUpdate` mutations
152
+ - [ ] `Printavo::ApprovalRequest` model (`id`, `status`, `sentAt`, `expiresAt`, `contact`)
153
+ - [ ] `ApprovalRequests` resource: `all(order_id:)`, `find(id)`
154
+ - [ ] `approvalRequestCreate` mutation
155
+ - [ ] `approvalRequestApprove(id:)` mutation
156
+ - [ ] `approvalRequestRevoke(id:)` mutation
157
+ - [ ] `approvalRequestUnapprove(id:)` mutation
144
158
 
145
159
  ### Categories
146
160
 
@@ -152,18 +166,19 @@ return values — they are exposed via model field accessors, not separate resou
152
166
  - [ ] `Printavo::ContractorProfile` model (`id`, `name`, `email`)
153
167
  - [ ] `ContractorProfiles` resource: `all`, `find(id)` — contractors assignable to invoices
154
168
 
155
- ### Delivery Methods
169
+ ### Custom Addresses
156
170
 
157
- - [ ] `Printavo::DeliveryMethod` model (`id`, `name`)
158
- - [ ] `DeliveryMethods` resource: `all` reference data (pickup, ship, etc.)
171
+ - [ ] `Printavo::CustomAddress` model (`id`, `name`, `address`, `city`, `state`, `zip`)
172
+ - [ ] `CustomAddresses` resource: `all(order_id:)`, `find(id)`, `create`, `update`, `delete`
173
+ - [ ] `customAddressCreate` / `customAddressCreates` (bulk) mutations
174
+ - [ ] `customAddressUpdate` / `customAddressUpdates` (bulk) mutations
175
+ - [ ] `customAddressDelete` / `customAddressDeletes` (bulk) mutations
159
176
 
160
- ### Delete Mutations
177
+ ### Delivery Methods
161
178
 
162
- - [ ] `contactDelete(id:)`
163
- - [ ] `customerDelete(id:)`
164
- - [ ] `quoteDelete(id:)` / `invoiceDelete(id:)`
165
- - [ ] `lineItemDelete(id:)`
166
- - [ ] `taskDelete(id:)`
179
+ - [ ] `Printavo::DeliveryMethod` model (`id`, `name`)
180
+ - [ ] `DeliveryMethods` resource: `all`, `find(id)`, `create`, `update`, `archive`
181
+ - [ ] `deliveryMethodCreate`, `deliveryMethodUpdate`, `deliveryMethodArchive` mutations
167
182
 
168
183
  ### Email Templates
169
184
 
@@ -179,20 +194,36 @@ return values — they are exposed via model field accessors, not separate resou
179
194
  ### Fees
180
195
 
181
196
  - [ ] `Printavo::Fee` model (`id`, `name`, `amount`, `taxable`)
182
- - [ ] `Fees` resource: `all(order_id:)`, `find(id)`, `create`, `update`
183
- - [ ] `feeCreate`, `feeUpdate` mutations
197
+ - [ ] `Fees` resource: `all(order_id:)`, `find(id)`, `create`, `update`, `delete`
198
+ - [ ] `feeCreate` / `feeCreates` (bulk) mutations
199
+ - [ ] `feeUpdate` / `feeUpdates` (bulk) mutations
200
+ - [ ] `feeDelete` / `feeDeletes` (bulk) mutations
184
201
 
185
202
  ### Imprints
186
203
 
187
204
  - [ ] `Printavo::Imprint` model (`id`, `name`, `position`, `colors`, `personalization`)
188
- - [ ] `Imprints` resource: `all(line_item_group_id:)`, `find(id)`, `create`, `update`
189
- - [ ] `imprintCreate`, `imprintUpdate` mutations
205
+ - [ ] `Imprints` resource: `all(line_item_group_id:)`, `find(id)`, `create`, `update`, `delete`
206
+ - [ ] `imprintCreate` / `imprintCreates` (bulk) mutations
207
+ - [ ] `imprintUpdate` / `imprintUpdates` (bulk) mutations
208
+ - [ ] `imprintDelete` / `imprintDeletes` (bulk) mutations
209
+ - [ ] `imprintMockupCreate` / `imprintMockupCreates` (bulk) — attach mockup to imprint
210
+
211
+ ### Line Items
212
+
213
+ - [ ] `Printavo::LineItem` model (`id`, `name`, `quantity`, `price`, `taxable`)
214
+ - [ ] `LineItems` resource: `all(line_item_group_id:)`, `find(id)`, `create`, `update`, `delete`
215
+ - [ ] `lineItemCreate` / `lineItemCreates` (bulk) mutations
216
+ - [ ] `lineItemUpdate` / `lineItemUpdates` (bulk) mutations
217
+ - [ ] `lineItemDelete` / `lineItemDeletes` (bulk) mutations
218
+ - [ ] `lineItemMockupCreate` / `lineItemMockupCreates` (bulk) — attach mockup to line item
190
219
 
191
220
  ### Line Item Groups
192
221
 
193
222
  - [ ] `Printavo::LineItemGroup` model (`id`, `name`, `description`, `sizes`, `enabled_columns`)
194
- - [ ] `LineItemGroups` resource: `all(order_id:)`, `find(id)`, `create`, `update`
195
- - [ ] `lineItemGroupCreate`, `lineItemGroupUpdate` mutations
223
+ - [ ] `LineItemGroups` resource: `all(order_id:)`, `find(id)`, `create`, `update`, `delete`
224
+ - [ ] `lineItemGroupCreate` / `lineItemGroupCreates` (bulk) mutations
225
+ - [ ] `lineItemGroupUpdate` / `lineItemGroupUpdates` (bulk) mutations
226
+ - [ ] `lineItemGroupDelete` / `lineItemGroupDeletes` (bulk) mutations
196
227
 
197
228
  ### Merch
198
229
 
@@ -206,26 +237,32 @@ return values — they are exposed via model field accessors, not separate resou
206
237
 
207
238
  - [ ] `Printavo::Mockup` model (`id`, `url`, `position`, `createdAt`)
208
239
  - [ ] `Printavo::ProductionFile` model (`id`, `url`, `filename`, `createdAt`)
209
- - [ ] `Mockups` resource: `all(order_id:)`, `find(id)`, `create`
210
- - [ ] `ProductionFiles` resource: `all(order_id:)`, `find(id)`, `create`
240
+ - [ ] `Mockups` resource: `all(order_id:)`, `find(id)`, `delete`
241
+ - [ ] `mockupDelete` / `mockupDeletes` (bulk) mutations
242
+ - [ ] `ProductionFiles` resource: `all(order_id:)`, `find(id)`, `create`, `delete`
243
+ - [ ] `productionFileCreate` / `productionFileCreates` (bulk) mutations
244
+ - [ ] `productionFileDelete` / `productionFileDeletes` (bulk) mutations
211
245
 
212
246
  ### Payments
213
247
 
214
248
  - [ ] `Printavo::Payment` model (`id`, `amount`, `method`, `paidAt`)
215
- - [ ] `Printavo::PaymentDispute` model (`id`, `amount`, `reason`, `status`)
216
249
  - [ ] `Printavo::PaymentRequest` model (`id`, `amount`, `sentAt`, `paidAt`, `details`)
217
- - [ ] `Printavo::PaymentTerm` model (`id`, `name`, `netDays`) — reference data
250
+ - [ ] `Printavo::PaymentTerm` model (`id`, `name`, `netDays`)
218
251
  - [ ] `Payments` resource: `all(order_id:)`, `find(id)`
219
- - [ ] `PaymentRequests` resource: `all(order_id:)`, `find(id)`, `create`
220
- - [ ] `PaymentTerms` resource: `all` — reference data
221
- - [ ] `paymentRequestCreate` mutation
252
+ - [ ] `PaymentRequests` resource: `all(order_id:)`, `find(id)`, `create`, `delete`
253
+ - [ ] `paymentRequestCreate`, `paymentRequestDelete` mutations
254
+ - [ ] `PaymentTerms` resource: `all`, `find(id)`, `create`, `update`, `archive`
255
+ - [ ] `paymentTermCreate`, `paymentTermUpdate`, `paymentTermArchive` mutations
222
256
 
223
257
  ### Preset Tasks
224
258
 
225
259
  - [ ] `Printavo::PresetTask` model (`id`, `body`, `dueOffsetDays`, `assignee`)
226
260
  - [ ] `Printavo::PresetTaskGroup` model (`id`, `name`, `tasks`)
227
- - [ ] `PresetTaskGroups` resource: `all`, `find(id)`, `create`, `update`
228
- - [ ] `presetTaskGroupCreate`, `presetTaskGroupUpdate` mutations
261
+ - [ ] `PresetTasks` resource: `find(id)`, `create`, `update`, `delete`
262
+ - [ ] `presetTaskCreate`, `presetTaskUpdate`, `presetTaskDelete` mutations
263
+ - [ ] `PresetTaskGroups` resource: `all`, `find(id)`, `create`, `update`, `delete`, `apply`
264
+ - [ ] `presetTaskGroupCreate`, `presetTaskGroupUpdate`, `presetTaskGroupDelete` mutations
265
+ - [ ] `presetTaskGroupApply(id:, order_id:)` mutation — applies a group to an order
229
266
 
230
267
  ### Product Catalog & Pricing
231
268
 
@@ -234,36 +271,26 @@ return values — they are exposed via model field accessors, not separate resou
234
271
  - [ ] `Products` resource: `all`, `find(id)`
235
272
  - [ ] `PricingMatrices` resource: `all`, `find(id)`
236
273
 
237
- ### Purchase Orders
238
-
239
- - [ ] `Printavo::PurchaseOrder` model (`id`, `vendorName`, `total`, `sentAt`)
240
- - [ ] `Printavo::PoLineItem` model (`id`, `name`, `quantity`, `price`)
241
- - [ ] `PurchaseOrders` resource: `all`, `find(id)`, `create`, `update`
242
- - [ ] `purchaseOrderCreate`, `purchaseOrderUpdate` mutations
243
-
244
- ### Refunds & Returns
245
-
246
- - [ ] `Printavo::Refund` model (`id`, `amount`, `reason`, `createdAt`)
247
- - [ ] `Printavo::Return` model (`id`, `quantity`, `reason`, `createdAt`)
248
- - [ ] `Refunds` resource: `all(order_id:)`, `find(id)`, `create`
249
- - [ ] `refundCreate` mutation
274
+ ### Tasks
250
275
 
251
- ### Tasks
276
+ - [x] `Printavo::Task` model (`id`, `body`, `dueAt`, `completedAt`, `assignee`)
277
+ - [x] `Tasks` resource: `all`, `find(id)`, `create`, `update`, `complete`, `delete`
278
+ - [x] `taskCreate`, `taskUpdate`, `taskDelete` mutations
252
279
 
253
- - [ ] `Printavo::Task` model (`id`, `body`, `dueAt`, `completedAt`, `assignee`)
254
- - [ ] `Tasks` resource: `all`, `find(id)`, `create`, `update`, `complete`
255
- - [ ] `taskCreate`, `taskUpdate` mutations
280
+ ### Threads (Messages)
256
281
 
257
- ### Threads (Messages)
282
+ - [x] `Printavo::Thread` model (`id`, `subject`, `createdAt`, `updatedAt`)
283
+ - [x] `Threads` resource: `all(order_id:)`, `find(id)`, `update`
284
+ - [x] `threadUpdate` mutation
285
+ - [x] `emailMessageCreate` mutation — send an email message on a thread
258
286
 
259
- - [ ] `Printavo::Thread` model (`id`, `body`, `author`, `createdAt`, `attachments`)
260
- - [ ] `Threads` resource: `all(order_id:)`, `find(id)`, `create`
261
- - [ ] `threadCreate` mutation
287
+ ### Transactions
262
288
 
263
- ### Transactions
264
-
265
- - [ ] `Printavo::Transaction` model (`id`, `amount`, `kind`, `createdAt`, `details`)
266
- - [ ] `Transactions` resource: `all(order_id:)`, `find(id)`
289
+ - [x] `Printavo::Transaction` model (`id`, `amount`, `kind`, `createdAt`)
290
+ - [x] `Transactions` resource: `all(order_id:)`, `find(id)`
291
+ - [x] `Printavo::TransactionPayment` model (`id`, `amount`, `paymentMethod`, `paidAt`, `note`)
292
+ - [x] `TransactionPayments` resource: `create`, `update`, `delete`
293
+ - [x] `transactionPaymentCreate`, `transactionPaymentUpdate`, `transactionPaymentDelete` mutations
267
294
 
268
295
  ### Types of Work
269
296
 
@@ -278,8 +305,7 @@ return values — they are exposed via model field accessors, not separate resou
278
305
  ### Vendors
279
306
 
280
307
  - [ ] `Printavo::Vendor` model (`id`, `name`, `email`, `phone`)
281
- - [ ] `Vendors` resource: `all`, `find(id)`, `create`, `update`
282
- - [ ] `vendorCreate`, `vendorUpdate` mutations
308
+ - [ ] `Vendors` resource: `all`, `find(id)` — read-only; no create/update/delete in V2 API
283
309
 
284
310
  ---
285
311
 
@@ -291,18 +317,18 @@ return values — they are exposed via model field accessors, not separate resou
291
317
  - [x] `Contacts` resource (`find`, `create`, `update`)
292
318
  - [x] `Account` resource (singleton `find`)
293
319
 
294
- ### v0.7.0 — Transactions, Tasks & Threads
320
+ ### v0.7.0 — Transactions, Tasks & Threads
295
321
 
296
- - [ ] `Transactions` resource (`all`, `find`)
297
- - [ ] `Tasks` resource (`all`, `find`, `create`, `update`, `complete`)
298
- - [ ] `Threads` resource (`all`, `find`, `create`)
299
- - [ ] Delete mutations: `contactDelete`, `customerDelete`, `quoteDelete`, `invoiceDelete`, `lineItemDelete`, `taskDelete`
322
+ - [x] `Transactions` resource (`all`, `find`) + `TransactionPayments` (`create`, `update`, `delete`)
323
+ - [x] `Tasks` resource (`all`, `find`, `create`, `update`, `complete`, `delete`)
324
+ - [x] `Threads` resource (`all`, `find`, `update`) + `emailMessageCreate`
300
325
 
301
- ### v0.8.0 — Order Structure: Line Item Groups, Imprints & Fees
326
+ ### v0.8.0 — Order Structure: Line Items, Line Item Groups, Imprints & Fees
302
327
 
303
- - [ ] `LineItemGroups` resource (`all`, `find`, `create`, `update`)
304
- - [ ] `Imprints` resource (`all`, `find`, `create`, `update`)
305
- - [ ] `Fees` resource (`all`, `find`, `create`, `update`)
328
+ - [ ] `LineItems` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
329
+ - [ ] `LineItemGroups` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
330
+ - [ ] `Imprints` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`, mockup attach)
331
+ - [ ] `Fees` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
306
332
  - [ ] `Expenses` resource (`all`, `find`, `create`, `update`)
307
333
 
308
334
  ### v0.9.0 — Merch, Products & Pricing
@@ -311,34 +337,44 @@ return values — they are exposed via model field accessors, not separate resou
311
337
  - [ ] `Products` resource + `PricingMatrices` resource
312
338
  - [ ] `Categories` resource (reference data)
313
339
 
314
- ### v0.10.0 — Financial: Payments, Purchase Orders & Refunds
340
+ ### v0.10.0 — Financial: Payments, Payment Terms & Requests
315
341
 
316
342
  - [ ] `Payments` resource (`all`, `find`)
317
- - [ ] `PaymentRequests` resource (`all`, `find`, `create`)
318
- - [ ] `PaymentTerms` resource (`all`) reference data
319
- - [ ] `PurchaseOrders` + `PoLineItems` resources
320
- - [ ] `Refunds` + `Returns` resources
343
+ - [ ] `PaymentRequests` resource (`all`, `find`, `create`, `delete`)
344
+ - [ ] `PaymentTerms` resource (`all`, `find`, `create`, `update`, `archive`)
321
345
 
322
346
  ### v0.11.0 — Workflow: Approvals & Preset Tasks
323
347
 
324
- - [ ] `Approvals` resource (`all`, `find`, `create`)
325
- - [ ] `PresetTaskGroups` resource (`all`, `find`, `create`, `update`)
348
+ - [ ] `ApprovalRequests` resource (`all`, `find`, `create`, `approve`, `revoke`, `unapprove`)
349
+ - [ ] `PresetTasks` resource (`find`, `create`, `update`, `delete`)
350
+ - [ ] `PresetTaskGroups` resource (`all`, `find`, `create`, `update`, `delete`, `apply`)
326
351
 
327
352
  ### v0.12.0 — Files, Media & Communication
328
353
 
329
- - [ ] `ProductionFiles` resource (`all`, `find`, `create`)
330
- - [ ] `Mockups` resource (`all`, `find`, `create`)
354
+ - [ ] `ProductionFiles` resource (`all`, `find`, `create`/`creates`, `delete`/`deletes`)
355
+ - [ ] `Mockups` resource (`all`, `find`, `delete`/`deletes`)
331
356
  - [ ] `EmailTemplates` resource (`all`, `find`)
357
+ - [ ] `CustomAddresses` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
332
358
 
333
359
  ### v0.13.0 — People, Orgs & Reference Data
334
360
 
335
361
  - [ ] `Users` resource (`all`, `find`)
336
- - [ ] `Vendors` resource (`all`, `find`, `create`, `update`)
362
+ - [ ] `Vendors` resource (`all`, `find`) — read-only
337
363
  - [ ] `ContractorProfiles` resource (`all`, `find`)
338
- - [ ] `DeliveryMethods` resource (`all`) reference data
339
- - [ ] `TypesOfWork` resource (`all`) — reference data
364
+ - [ ] `DeliveryMethods` resource (`all`, `find`, `create`, `update`, `archive`)
365
+ - [ ] `TypesOfWork` resource (`all`)
366
+
367
+ ### v0.14.0 — Delete & Duplicate Mutations for Shipped Resources
368
+
369
+ - [ ] `Contacts#delete` — `contactDelete`
370
+ - [ ] `Customers#delete` — `customerDelete`
371
+ - [ ] `Inquiries#delete` — `inquiryDelete`
372
+ - [ ] `Invoices#delete` — `invoiceDelete`
373
+ - [ ] `Invoices#duplicate` — `invoiceDuplicate`
374
+ - [ ] `Orders#delete` — `quoteDelete`
375
+ - [ ] `Orders#duplicate` — `quoteDuplicate`
340
376
 
341
- ### v0.14.0 — Retry / Backoff & CLI
377
+ ### v0.15.0 — Retry / Backoff & CLI
342
378
 
343
379
  - [ ] Configurable `max_retries` on `Printavo::Client`
344
380
  - [ ] Exponential backoff with jitter on 429 responses
@@ -37,24 +37,52 @@ module Printavo
37
37
  Resources::Customers.new(@graphql)
38
38
  end
39
39
 
40
+ def inquiries
41
+ Resources::Inquiries.new(@graphql)
42
+ end
43
+
40
44
  def invoices
41
45
  Resources::Invoices.new(@graphql)
42
46
  end
43
47
 
44
- def statuses
45
- Resources::Statuses.new(@graphql)
48
+ def jobs
49
+ Resources::Jobs.new(@graphql)
50
+ end
51
+
52
+ def login(*)
53
+ raise NotImplementedError,
54
+ 'login is not supported — this gem authenticates via email + token headers. ' \
55
+ 'Pass credentials to Printavo::Client.new(email:, token:) instead.'
56
+ end
57
+
58
+ def logout(*)
59
+ raise NotImplementedError,
60
+ 'logout is not supported — this gem uses stateless header-based auth. ' \
61
+ 'Simply discard the client instance when done.'
46
62
  end
47
63
 
48
64
  def orders
49
65
  Resources::Orders.new(@graphql)
50
66
  end
51
67
 
52
- def jobs
53
- Resources::Jobs.new(@graphql)
68
+ def statuses
69
+ Resources::Statuses.new(@graphql)
54
70
  end
55
71
 
56
- def inquiries
57
- Resources::Inquiries.new(@graphql)
72
+ def tasks
73
+ Resources::Tasks.new(@graphql)
74
+ end
75
+
76
+ def threads
77
+ Resources::Threads.new(@graphql)
78
+ end
79
+
80
+ def transaction_payments
81
+ Resources::TransactionPayments.new(@graphql)
82
+ end
83
+
84
+ def transactions
85
+ Resources::Transactions.new(@graphql)
58
86
  end
59
87
  end
60
88
  end
@@ -0,0 +1,13 @@
1
+ # lib/printavo/models/task.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class Task < Models::Base
6
+ def id = self['id']
7
+ def body = self['body']
8
+ def due_at = self['dueAt']
9
+ def completed_at = self['completedAt']
10
+ def completed? = !completed_at.nil?
11
+ def assignee = self['assignee']
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ # lib/printavo/models/thread.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class Thread < Models::Base
6
+ def id = self['id']
7
+ def subject = self['subject']
8
+ def created_at = self['createdAt']
9
+ def updated_at = self['updatedAt']
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ # lib/printavo/models/transaction.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class Transaction < Models::Base
6
+ def id = self['id']
7
+ def amount = self['amount']
8
+ def kind = self['kind']
9
+ def created_at = self['createdAt']
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # lib/printavo/models/transaction_payment.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class TransactionPayment < Models::Base
6
+ def id = self['id']
7
+ def amount = self['amount']
8
+ def payment_method = self['paymentMethod']
9
+ def paid_at = self['paidAt']
10
+ def note = self['note']
11
+ end
12
+ end
@@ -0,0 +1,65 @@
1
+ # lib/printavo/resources/tasks.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ module Resources
6
+ class Tasks < Base
7
+ ALL_QUERY = File.read(File.join(__dir__, '../graphql/tasks/all.graphql')).freeze
8
+ FIND_QUERY = File.read(File.join(__dir__, '../graphql/tasks/find.graphql')).freeze
9
+ CREATE_MUTATION = File.read(File.join(__dir__, '../graphql/tasks/create.graphql')).freeze
10
+ UPDATE_MUTATION = File.read(File.join(__dir__, '../graphql/tasks/update.graphql')).freeze
11
+ DELETE_MUTATION = File.read(File.join(__dir__, '../graphql/tasks/delete.graphql')).freeze
12
+
13
+ def all(first: 25, after: nil)
14
+ fetch_page(first: first, after: after).records
15
+ end
16
+
17
+ def find(id)
18
+ data = @graphql.query(FIND_QUERY, variables: { id: id.to_s })
19
+ Printavo::Task.new(data['task'])
20
+ end
21
+
22
+ def create(**input)
23
+ data = @graphql.mutate(CREATE_MUTATION, variables: { input: camelize_keys(input) })
24
+ Printavo::Task.new(data['taskCreate'])
25
+ end
26
+
27
+ def update(id, **input)
28
+ data = @graphql.mutate(UPDATE_MUTATION,
29
+ variables: { id: id.to_s, input: camelize_keys(input) })
30
+ Printavo::Task.new(data['taskUpdate'])
31
+ end
32
+
33
+ # Marks a task complete by setting completedAt to the current time.
34
+ def complete(id)
35
+ require 'time'
36
+ update(id, completed_at: Time.now.utc.iso8601)
37
+ end
38
+
39
+ # Deletes a task. Raises on failure; returns nil on success.
40
+ def delete(id)
41
+ @graphql.mutate(DELETE_MUTATION, variables: { id: id.to_s })
42
+ nil
43
+ end
44
+
45
+ private
46
+
47
+ def fetch_page(first: 25, after: nil, **)
48
+ data = @graphql.query(ALL_QUERY, variables: { first: first, after: after })
49
+ nodes = data['tasks']['nodes'].map { |attrs| Printavo::Task.new(attrs) }
50
+ page_info = data['tasks']['pageInfo']
51
+ Printavo::Page.new(
52
+ records: nodes,
53
+ has_next_page: page_info['hasNextPage'],
54
+ end_cursor: page_info['endCursor']
55
+ )
56
+ end
57
+
58
+ def camelize_keys(hash)
59
+ hash.transform_keys do |key|
60
+ key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,59 @@
1
+ # lib/printavo/resources/threads.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ module Resources
6
+ class Threads < Base
7
+ ALL_QUERY = File.read(File.join(__dir__, '../graphql/threads/all.graphql')).freeze
8
+ FIND_QUERY = File.read(File.join(__dir__, '../graphql/threads/find.graphql')).freeze
9
+ UPDATE_MUTATION = File.read(File.join(__dir__, '../graphql/threads/update.graphql')).freeze
10
+ EMAIL_MESSAGE_CREATE_MUTATION =
11
+ File.read(File.join(__dir__, '../graphql/threads/email_message_create.graphql')).freeze
12
+
13
+ def all(order_id:, first: 25, after: nil)
14
+ fetch_page(order_id: order_id, first: first, after: after).records
15
+ end
16
+
17
+ def find(id)
18
+ data = @graphql.query(FIND_QUERY, variables: { id: id.to_s })
19
+ Printavo::Thread.new(data['thread'])
20
+ end
21
+
22
+ def update(id, **input)
23
+ data = @graphql.mutate(UPDATE_MUTATION,
24
+ variables: { id: id.to_s, input: camelize_keys(input) })
25
+ Printavo::Thread.new(data['threadUpdate'])
26
+ end
27
+
28
+ # Sends an email message on a thread. Returns the raw message hash.
29
+ # A dedicated EmailMessage model is planned for a future version.
30
+ def email_message_create(**input)
31
+ data = @graphql.mutate(EMAIL_MESSAGE_CREATE_MUTATION,
32
+ variables: { input: camelize_keys(input) })
33
+ data['emailMessageCreate']
34
+ end
35
+
36
+ private
37
+
38
+ def fetch_page(order_id:, first: 25, after: nil, **)
39
+ data = @graphql.query(
40
+ ALL_QUERY,
41
+ variables: { orderId: order_id.to_s, first: first, after: after }
42
+ )
43
+ nodes = data['order']['threads']['nodes'].map { |attrs| Printavo::Thread.new(attrs) }
44
+ page_info = data['order']['threads']['pageInfo']
45
+ Printavo::Page.new(
46
+ records: nodes,
47
+ has_next_page: page_info['hasNextPage'],
48
+ end_cursor: page_info['endCursor']
49
+ )
50
+ end
51
+
52
+ def camelize_keys(hash)
53
+ hash.transform_keys do |key|
54
+ key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ # lib/printavo/resources/transaction_payments.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ module Resources
6
+ class TransactionPayments < Base
7
+ CREATE_MUTATION = File.read(File.join(__dir__, '../graphql/transaction_payments/create.graphql')).freeze
8
+ UPDATE_MUTATION = File.read(File.join(__dir__, '../graphql/transaction_payments/update.graphql')).freeze
9
+ DELETE_MUTATION = File.read(File.join(__dir__, '../graphql/transaction_payments/delete.graphql')).freeze
10
+
11
+ def create(**input)
12
+ data = @graphql.mutate(CREATE_MUTATION, variables: { input: camelize_keys(input) })
13
+ Printavo::TransactionPayment.new(data['transactionPaymentCreate'])
14
+ end
15
+
16
+ def update(id, **input)
17
+ data = @graphql.mutate(UPDATE_MUTATION,
18
+ variables: { id: id.to_s, input: camelize_keys(input) })
19
+ Printavo::TransactionPayment.new(data['transactionPaymentUpdate'])
20
+ end
21
+
22
+ # Deletes a transaction payment. Raises on failure; returns nil on success.
23
+ def delete(id)
24
+ @graphql.mutate(DELETE_MUTATION, variables: { id: id.to_s })
25
+ nil
26
+ end
27
+
28
+ private
29
+
30
+ def camelize_keys(hash)
31
+ hash.transform_keys do |key|
32
+ key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ # lib/printavo/resources/transactions.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ module Resources
6
+ class Transactions < Base
7
+ ALL_QUERY = File.read(File.join(__dir__, '../graphql/transactions/all.graphql')).freeze
8
+ FIND_QUERY = File.read(File.join(__dir__, '../graphql/transactions/find.graphql')).freeze
9
+
10
+ def all(order_id:, first: 25, after: nil)
11
+ fetch_page(order_id: order_id, first: first, after: after).records
12
+ end
13
+
14
+ def find(id)
15
+ data = @graphql.query(FIND_QUERY, variables: { id: id.to_s })
16
+ Printavo::Transaction.new(data['transaction'])
17
+ end
18
+
19
+ private
20
+
21
+ def fetch_page(order_id:, first: 25, after: nil, **)
22
+ data = @graphql.query(
23
+ ALL_QUERY,
24
+ variables: { orderId: order_id.to_s, first: first, after: after }
25
+ )
26
+ nodes = data['order']['transactions']['nodes'].map { |attrs| Printavo::Transaction.new(attrs) }
27
+ page_info = data['order']['transactions']['pageInfo']
28
+ Printavo::Page.new(
29
+ records: nodes,
30
+ has_next_page: page_info['hasNextPage'],
31
+ end_cursor: page_info['endCursor']
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Printavo
5
- VERSION = '0.6.0'
5
+ VERSION = '0.7.0'
6
6
  end
data/lib/printavo.rb CHANGED
@@ -20,6 +20,10 @@ require_relative 'printavo/models/status'
20
20
  require_relative 'printavo/models/order'
21
21
  require_relative 'printavo/models/job'
22
22
  require_relative 'printavo/models/inquiry'
23
+ require_relative 'printavo/models/task'
24
+ require_relative 'printavo/models/thread'
25
+ require_relative 'printavo/models/transaction'
26
+ require_relative 'printavo/models/transaction_payment'
23
27
  require_relative 'printavo/resources/base'
24
28
  require_relative 'printavo/resources/account'
25
29
  require_relative 'printavo/resources/contacts'
@@ -29,6 +33,10 @@ require_relative 'printavo/resources/statuses'
29
33
  require_relative 'printavo/resources/orders'
30
34
  require_relative 'printavo/resources/jobs'
31
35
  require_relative 'printavo/resources/inquiries'
36
+ require_relative 'printavo/resources/tasks'
37
+ require_relative 'printavo/resources/threads'
38
+ require_relative 'printavo/resources/transactions'
39
+ require_relative 'printavo/resources/transaction_payments'
32
40
  require_relative 'printavo/webhooks'
33
41
  require_relative 'printavo/client'
34
42
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: printavo-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stan Carver II
@@ -281,6 +281,10 @@ files:
281
281
  - lib/printavo/models/job.rb
282
282
  - lib/printavo/models/order.rb
283
283
  - lib/printavo/models/status.rb
284
+ - lib/printavo/models/task.rb
285
+ - lib/printavo/models/thread.rb
286
+ - lib/printavo/models/transaction.rb
287
+ - lib/printavo/models/transaction_payment.rb
284
288
  - lib/printavo/page.rb
285
289
  - lib/printavo/resources/account.rb
286
290
  - lib/printavo/resources/base.rb
@@ -291,6 +295,10 @@ files:
291
295
  - lib/printavo/resources/jobs.rb
292
296
  - lib/printavo/resources/orders.rb
293
297
  - lib/printavo/resources/statuses.rb
298
+ - lib/printavo/resources/tasks.rb
299
+ - lib/printavo/resources/threads.rb
300
+ - lib/printavo/resources/transaction_payments.rb
301
+ - lib/printavo/resources/transactions.rb
294
302
  - lib/printavo/version.rb
295
303
  - lib/printavo/webhooks.rb
296
304
  homepage: https://github.com/scarver2/printavo-ruby