printavo-ruby 0.6.0 → 0.8.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: b15234d01d31d249e662a33ee862660d1ce0f6ae20894c5ebb5f0ed28b048413
4
+ data.tar.gz: d00bbeb852bc3ababce742381586ff0dfa0577e936c1ee7ec608de63e2cc0cd1
5
5
  SHA512:
6
- metadata.gz: b266887065b5f727b6f9660557ce37d7ab64b53f23033f5c64c678cae919f00cd21e169fee17177bce7e873fdcc9d978307a3254e20de0224aab4b8e9c462d97
7
- data.tar.gz: 4d1c944ca7283bab4e45dfe3cde0ddc6acf3ea35a167ee7b49574b6f7e367fff77a833253976605e2f8219aea932d5056b04004fcb55553cd4975bdfe853b3fe
6
+ metadata.gz: fda95aafcc1ac46908d13a46bac277d39798dcef3999c49286d29ee334ff47c425477baf13be3a6a9bd2a5d70b30ad2f714ec4819938f46b8e54da2489de4df2
7
+ data.tar.gz: 211f5bddd9598a3254496c2bc82282634ac3208db5784d3e35f2408344864585aebeffd746e2be5f443012b0431e9bd64e7da0fbdf8941397138d55fdaf166e4
data/docs/CHANGELOG.md CHANGED
@@ -6,6 +6,49 @@ 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.8.0] - 2026-03-31
10
+
11
+ ### Added
12
+ - `Printavo::LineItem` model (`id`, `name`, `quantity`, `price`, `taxable`, `taxable?`)
13
+ - `LineItems` resource: `all(line_item_group_id:)`, `find`, `create`/`creates`, `update`/`updates`,
14
+ `delete`/`deletes`, `mockup_create`/`mockup_creates`
15
+ - `Printavo::LineItemGroup` model (`id`, `name`, `description`)
16
+ - `LineItemGroups` resource: `all(order_id:)`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`
17
+ - `Printavo::Imprint` model (`id`, `name`, `position`, `colors`)
18
+ - `Imprints` resource: `all(line_item_group_id:)`, `find`, `create`/`creates`, `update`/`updates`,
19
+ `delete`/`deletes`, `mockup_create`/`mockup_creates`
20
+ - `Printavo::Fee` model (`id`, `name`, `amount`, `taxable`, `taxable?`)
21
+ - `Fees` resource: `all(order_id:)`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`
22
+ - `Printavo::Expense` model (`id`, `name`, `amount`, `category`)
23
+ - `Expenses` resource: `all(order_id:)`, `find`, `create`, `update`
24
+ - `client.line_items`, `client.line_item_groups`, `client.imprints`, `client.fees`, `client.expenses`
25
+ entry points on `Printavo::Client`
26
+ - 40 new `.graphql` files under `lib/printavo/graphql/`
27
+
28
+ ### Changed
29
+ - `camelize_keys` moved from individual resource classes to `Resources::Base` — eliminates 7 duplicate definitions
30
+
31
+ ## [0.7.0] - 2026-03-30
32
+
33
+ ### Added
34
+ - `Printavo::Transaction` model (`id`, `amount`, `kind`, `created_at`)
35
+ - `Transactions` resource: `all(order_id:)`, `find(id)` — scoped to an order, same pattern as Jobs
36
+ - `Printavo::TransactionPayment` model (`id`, `amount`, `payment_method`, `paid_at`, `note`)
37
+ - `TransactionPayments` resource: `create(**input)`, `update(id, **input)`, `delete(id)` —
38
+ mutation-only; `transactionPaymentCreate/Update/Delete`
39
+ - `Printavo::Task` model (`id`, `body`, `due_at`, `completed_at`, `completed?`, `assignee`)
40
+ - `Tasks` resource: `all`, `find(id)`, `create(**input)`, `update(id, **input)`,
41
+ `complete(id)` (sets `completedAt` to now via `taskUpdate`), `delete(id)`
42
+ - `Printavo::Thread` model (`id`, `subject`, `created_at`, `updated_at`)
43
+ - `Threads` resource: `all(order_id:)`, `find(id)`, `update(id, **input)`,
44
+ `email_message_create(**input)` — `threadUpdate` + `emailMessageCreate` mutations;
45
+ returns raw hash (no `EmailMessage` model yet)
46
+ - `client.tasks`, `client.threads`, `client.transactions`, `client.transaction_payments`
47
+ entry points on `Printavo::Client`
48
+ - 14 new `.graphql` files under `lib/printavo/graphql/`
49
+ - `Client#login` / `Client#logout` raise `NotImplementedError` with a message directing
50
+ consumers to the `email` + `token` initializer; gem uses stateless header-based auth
51
+
9
52
  ## [0.6.0] - 2026-03-30
10
53
 
11
54
  ### 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,47 +166,64 @@ 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
 
170
185
  - [ ] `Printavo::EmailTemplate` model (`id`, `name`, `subject`, `body`)
171
186
  - [ ] `EmailTemplates` resource: `all`, `find(id)`
172
187
 
173
- ### Expenses
188
+ ### Expenses
189
+
190
+ - [x] `Printavo::Expense` model (`id`, `name`, `amount`, `category`)
191
+ - [x] `Expenses` resource: `all(order_id:)`, `find(id)`, `create`, `update`
192
+ - [x] `expenseCreate`, `expenseUpdate` mutations
174
193
 
175
- - [ ] `Printavo::Expense` model (`id`, `name`, `amount`, `category`)
176
- - [ ] `Expenses` resource: `all(order_id:)`, `find(id)`, `create`, `update`
177
- - [ ] `expenseCreate`, `expenseUpdate` mutations
194
+ ### Fees
178
195
 
179
- ### Fees
196
+ - [x] `Printavo::Fee` model (`id`, `name`, `amount`, `taxable`)
197
+ - [x] `Fees` resource: `all(order_id:)`, `find(id)`, `create`, `update`, `delete`
198
+ - [x] `feeCreate` / `feeCreates` (bulk) mutations
199
+ - [x] `feeUpdate` / `feeUpdates` (bulk) mutations
200
+ - [x] `feeDelete` / `feeDeletes` (bulk) mutations
180
201
 
181
- - [ ] `Printavo::Fee` model (`id`, `name`, `amount`, `taxable`)
182
- - [ ] `Fees` resource: `all(order_id:)`, `find(id)`, `create`, `update`
183
- - [ ] `feeCreate`, `feeUpdate` mutations
202
+ ### Imprints
184
203
 
185
- ### Imprints
204
+ - [x] `Printavo::Imprint` model (`id`, `name`, `position`, `colors`)
205
+ - [x] `Imprints` resource: `all(line_item_group_id:)`, `find(id)`, `create`, `update`, `delete`
206
+ - [x] `imprintCreate` / `imprintCreates` (bulk) mutations
207
+ - [x] `imprintUpdate` / `imprintUpdates` (bulk) mutations
208
+ - [x] `imprintDelete` / `imprintDeletes` (bulk) mutations
209
+ - [x] `imprintMockupCreate` / `imprintMockupCreates` (bulk) — attach mockup to imprint
186
210
 
187
- - [ ] `Printavo::Imprint` model (`id`, `name`, `position`, `colors`, `personalization`)
188
- - [ ] `Imprints` resource: `all(line_item_group_id:)`, `find(id)`, `create`, `update`
189
- - [ ] `imprintCreate`, `imprintUpdate` mutations
211
+ ### Line Items
190
212
 
191
- ### Line Item Groups
213
+ - [x] `Printavo::LineItem` model (`id`, `name`, `quantity`, `price`, `taxable`)
214
+ - [x] `LineItems` resource: `all(line_item_group_id:)`, `find(id)`, `create`, `update`, `delete`
215
+ - [x] `lineItemCreate` / `lineItemCreates` (bulk) mutations
216
+ - [x] `lineItemUpdate` / `lineItemUpdates` (bulk) mutations
217
+ - [x] `lineItemDelete` / `lineItemDeletes` (bulk) mutations
218
+ - [x] `lineItemMockupCreate` / `lineItemMockupCreates` (bulk) — attach mockup to line item
192
219
 
193
- - [ ] `Printavo::LineItemGroup` model (`id`, `name`, `description`, `sizes`, `enabled_columns`)
194
- - [ ] `LineItemGroups` resource: `all(order_id:)`, `find(id)`, `create`, `update`
195
- - [ ] `lineItemGroupCreate`, `lineItemGroupUpdate` mutations
220
+ ### Line Item Groups
221
+
222
+ - [x] `Printavo::LineItemGroup` model (`id`, `name`, `description`)
223
+ - [x] `LineItemGroups` resource: `all(order_id:)`, `find(id)`, `create`, `update`, `delete`
224
+ - [x] `lineItemGroupCreate` / `lineItemGroupCreates` (bulk) mutations
225
+ - [x] `lineItemGroupUpdate` / `lineItemGroupUpdates` (bulk) mutations
226
+ - [x] `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,19 +317,19 @@ 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`)
306
- - [ ] `Expenses` resource (`all`, `find`, `create`, `update`)
328
+ - [x] `LineItems` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
329
+ - [x] `LineItemGroups` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
330
+ - [x] `Imprints` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`, mockup attach)
331
+ - [x] `Fees` resource (`all`, `find`, `create`/`creates`, `update`/`updates`, `delete`/`deletes`)
332
+ - [x] `Expenses` resource (`all`, `find`, `create`, `update`)
307
333
 
308
334
  ### v0.9.0 — Merch, Products & Pricing
309
335
 
@@ -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,72 @@ module Printavo
37
37
  Resources::Customers.new(@graphql)
38
38
  end
39
39
 
40
+ def expenses
41
+ Resources::Expenses.new(@graphql)
42
+ end
43
+
44
+ def fees
45
+ Resources::Fees.new(@graphql)
46
+ end
47
+
48
+ def imprints
49
+ Resources::Imprints.new(@graphql)
50
+ end
51
+
52
+ def inquiries
53
+ Resources::Inquiries.new(@graphql)
54
+ end
55
+
40
56
  def invoices
41
57
  Resources::Invoices.new(@graphql)
42
58
  end
43
59
 
44
- def statuses
45
- Resources::Statuses.new(@graphql)
60
+ def jobs
61
+ Resources::Jobs.new(@graphql)
62
+ end
63
+
64
+ def line_item_groups
65
+ Resources::LineItemGroups.new(@graphql)
66
+ end
67
+
68
+ def line_items
69
+ Resources::LineItems.new(@graphql)
70
+ end
71
+
72
+ def login(*)
73
+ raise NotImplementedError,
74
+ 'login is not supported — this gem authenticates via email + token headers. ' \
75
+ 'Pass credentials to Printavo::Client.new(email:, token:) instead.'
76
+ end
77
+
78
+ def logout(*)
79
+ raise NotImplementedError,
80
+ 'logout is not supported — this gem uses stateless header-based auth. ' \
81
+ 'Simply discard the client instance when done.'
46
82
  end
47
83
 
48
84
  def orders
49
85
  Resources::Orders.new(@graphql)
50
86
  end
51
87
 
52
- def jobs
53
- Resources::Jobs.new(@graphql)
88
+ def statuses
89
+ Resources::Statuses.new(@graphql)
54
90
  end
55
91
 
56
- def inquiries
57
- Resources::Inquiries.new(@graphql)
92
+ def tasks
93
+ Resources::Tasks.new(@graphql)
94
+ end
95
+
96
+ def threads
97
+ Resources::Threads.new(@graphql)
98
+ end
99
+
100
+ def transaction_payments
101
+ Resources::TransactionPayments.new(@graphql)
102
+ end
103
+
104
+ def transactions
105
+ Resources::Transactions.new(@graphql)
58
106
  end
59
107
  end
60
108
  end
@@ -0,0 +1,11 @@
1
+ # lib/printavo/models/expense.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class Expense < Models::Base
6
+ def id = self['id']
7
+ def name = self['name']
8
+ def amount = self['amount']
9
+ def category = self['category']
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # lib/printavo/models/fee.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class Fee < Models::Base
6
+ def id = self['id']
7
+ def name = self['name']
8
+ def amount = self['amount']
9
+ def taxable = self['taxable']
10
+ def taxable? = !!self['taxable']
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ # lib/printavo/models/imprint.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class Imprint < Models::Base
6
+ def id = self['id']
7
+ def name = self['name']
8
+ def position = self['position']
9
+ def colors = self['colors']
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ # lib/printavo/models/line_item.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class LineItem < Models::Base
6
+ def id = self['id']
7
+ def name = self['name']
8
+ def quantity = self['quantity']
9
+ def price = self['price']
10
+ def taxable = self['taxable']
11
+ def taxable? = !!self['taxable']
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ # lib/printavo/models/line_item_group.rb
2
+ # frozen_string_literal: true
3
+
4
+ module Printavo
5
+ class LineItemGroup < Models::Base
6
+ def id = self['id']
7
+ def name = self['name']
8
+ def description = self['description']
9
+ end
10
+ 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
@@ -48,6 +48,14 @@ module Printavo
48
48
  def fetch_page(**)
49
49
  raise NotImplementedError, "#{self.class}#fetch_page is not implemented"
50
50
  end
51
+
52
+ # Converts snake_case Symbol/String keys to camelCase String keys.
53
+ # Used when building GraphQL mutation input objects.
54
+ def camelize_keys(hash)
55
+ hash.transform_keys do |key|
56
+ key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
57
+ end
58
+ end
51
59
  end
52
60
  end
53
61
  end
@@ -44,14 +44,6 @@ module Printavo
44
44
  variables: { id: id.to_s, input: camelize_keys(input) })
45
45
  Printavo::Contact.new(data['contactUpdate'])
46
46
  end
47
-
48
- private
49
-
50
- def camelize_keys(hash)
51
- hash.transform_keys do |key|
52
- key.to_s.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
53
- end
54
- end
55
47
  end
56
48
  end
57
49
  end
@@ -76,13 +76,6 @@ module Printavo
76
76
  end
77
77
  Printavo::Customer.new(normalized)
78
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
86
79
  end
87
80
  end
88
81
  end