mintsoft 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.serena/memories/code_style_conventions.md +35 -0
- data/.serena/memories/codebase_structure.md +35 -0
- data/.serena/memories/development_environment.md +37 -0
- data/.serena/memories/project_overview.md +28 -0
- data/.serena/memories/suggested_commands.md +63 -0
- data/.serena/memories/task_completion_checklist.md +46 -0
- data/.serena/project.yml +68 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +165 -0
- data/Rakefile +10 -0
- data/claudedocs/AUTH_CLIENT_DESIGN.md +294 -0
- data/claudedocs/FINAL_SIMPLIFIED_DESIGN.md +553 -0
- data/claudedocs/IMPLEMENTATION_SUMMARY.md +140 -0
- data/claudedocs/INDEX.md +83 -0
- data/claudedocs/MINIMAL_IMPLEMENTATION_PLAN.md +316 -0
- data/claudedocs/TOKEN_ONLY_CLIENT_DESIGN.md +408 -0
- data/claudedocs/USAGE_EXAMPLES.md +482 -0
- data/examples/complete_workflow.rb +146 -0
- data/lib/mintsoft/auth_client.rb +104 -0
- data/lib/mintsoft/base.rb +44 -0
- data/lib/mintsoft/client.rb +37 -0
- data/lib/mintsoft/errors.rb +9 -0
- data/lib/mintsoft/objects/order.rb +16 -0
- data/lib/mintsoft/objects/return.rb +26 -0
- data/lib/mintsoft/objects/return_reason.rb +11 -0
- data/lib/mintsoft/resources/base_resource.rb +53 -0
- data/lib/mintsoft/resources/orders.rb +36 -0
- data/lib/mintsoft/resources/returns.rb +90 -0
- data/lib/mintsoft/version.rb +5 -0
- data/lib/mintsoft.rb +17 -0
- data/sig/mintsoft.rbs +4 -0
- metadata +161 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
# Mintsoft Gem Usage Examples
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document provides complete usage examples for the Mintsoft gem, showing how to use the AuthClient for token management and the main Client for API operations.
|
|
6
|
+
|
|
7
|
+
## Basic Usage
|
|
8
|
+
|
|
9
|
+
### Step 1: Authentication
|
|
10
|
+
```ruby
|
|
11
|
+
require 'mintsoft'
|
|
12
|
+
|
|
13
|
+
# Initialize auth client
|
|
14
|
+
auth_client = Mintsoft::AuthClient.new
|
|
15
|
+
|
|
16
|
+
# Get authentication token
|
|
17
|
+
auth_response = auth_client.auth.authenticate(
|
|
18
|
+
ENV['MINTSOFT_USERNAME'],
|
|
19
|
+
ENV['MINTSOFT_PASSWORD']
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
# Check token validity
|
|
23
|
+
puts "Token: #{auth_response.token}"
|
|
24
|
+
puts "Expires at: #{auth_response.expires_at}"
|
|
25
|
+
puts "Valid: #{auth_response.valid?}"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Step 2: API Operations
|
|
29
|
+
```ruby
|
|
30
|
+
# Initialize main client with token
|
|
31
|
+
client = Mintsoft::Client.new(token: auth_response.token)
|
|
32
|
+
|
|
33
|
+
# Search for orders
|
|
34
|
+
orders = client.orders.search("ORD-2024-001")
|
|
35
|
+
puts "Found #{orders.length} orders"
|
|
36
|
+
|
|
37
|
+
# Get return reasons
|
|
38
|
+
reasons = client.returns.reasons
|
|
39
|
+
puts "Available reasons: #{reasons.map(&:name).join(', ')}"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Complete Order-to-Return Workflow
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
require 'mintsoft'
|
|
46
|
+
|
|
47
|
+
def complete_return_workflow(order_number, items_to_return)
|
|
48
|
+
# Step 1: Authenticate and get token
|
|
49
|
+
auth_client = Mintsoft::AuthClient.new
|
|
50
|
+
|
|
51
|
+
begin
|
|
52
|
+
auth_response = auth_client.auth.authenticate(
|
|
53
|
+
ENV['MINTSOFT_USERNAME'],
|
|
54
|
+
ENV['MINTSOFT_PASSWORD']
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
unless auth_response.valid?
|
|
58
|
+
puts "Invalid authentication response"
|
|
59
|
+
return false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Step 2: Initialize API client
|
|
63
|
+
client = Mintsoft::Client.new(token: auth_response.token)
|
|
64
|
+
|
|
65
|
+
# Step 3: Search for order
|
|
66
|
+
puts "Searching for order: #{order_number}"
|
|
67
|
+
orders = client.orders.search(order_number)
|
|
68
|
+
|
|
69
|
+
if orders.empty?
|
|
70
|
+
puts "Order not found: #{order_number}"
|
|
71
|
+
return false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
order = orders.first
|
|
75
|
+
puts "Found order: #{order.order_number} (ID: #{order.id})"
|
|
76
|
+
|
|
77
|
+
# Step 4: Get return reasons
|
|
78
|
+
puts "Fetching return reasons..."
|
|
79
|
+
reasons = client.returns.reasons
|
|
80
|
+
|
|
81
|
+
if reasons.empty?
|
|
82
|
+
puts "No return reasons available"
|
|
83
|
+
return false
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Select first active reason (or find by name)
|
|
87
|
+
selected_reason = reasons.find(&:active?) || reasons.first
|
|
88
|
+
puts "Selected reason: #{selected_reason.name} (ID: #{selected_reason.id})"
|
|
89
|
+
|
|
90
|
+
# Step 5: Create return
|
|
91
|
+
puts "Creating return for order ID: #{order.id}"
|
|
92
|
+
return_obj = client.returns.create(order.id)
|
|
93
|
+
puts "Created return ID: #{return_obj.id}"
|
|
94
|
+
|
|
95
|
+
# Step 6: Add items to return
|
|
96
|
+
items_to_return.each_with_index do |item, index|
|
|
97
|
+
puts "Adding item #{index + 1}: Product ID #{item[:product_id]}, Quantity #{item[:quantity]}"
|
|
98
|
+
|
|
99
|
+
success = client.returns.add_item(return_obj.id, {
|
|
100
|
+
product_id: item[:product_id],
|
|
101
|
+
quantity: item[:quantity],
|
|
102
|
+
reason_id: selected_reason.id,
|
|
103
|
+
unit_value: item[:unit_value],
|
|
104
|
+
notes: item[:notes]
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if success
|
|
108
|
+
puts " ✓ Item added successfully"
|
|
109
|
+
else
|
|
110
|
+
puts " ✗ Failed to add item"
|
|
111
|
+
return false
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
puts "Return workflow completed successfully!"
|
|
116
|
+
puts "Return ID: #{return_obj.id}"
|
|
117
|
+
return true
|
|
118
|
+
|
|
119
|
+
rescue Mintsoft::AuthenticationError => e
|
|
120
|
+
puts "Authentication failed: #{e.message}"
|
|
121
|
+
return false
|
|
122
|
+
rescue Mintsoft::ValidationError => e
|
|
123
|
+
puts "Validation error: #{e.message}"
|
|
124
|
+
return false
|
|
125
|
+
rescue Mintsoft::NotFoundError => e
|
|
126
|
+
puts "Resource not found: #{e.message}"
|
|
127
|
+
return false
|
|
128
|
+
rescue Mintsoft::APIError => e
|
|
129
|
+
puts "API error: #{e.message}"
|
|
130
|
+
return false
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Usage
|
|
135
|
+
items = [
|
|
136
|
+
{
|
|
137
|
+
product_id: 123,
|
|
138
|
+
quantity: 2,
|
|
139
|
+
unit_value: 25.00,
|
|
140
|
+
notes: "Damaged during shipping"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
product_id: 456,
|
|
144
|
+
quantity: 1,
|
|
145
|
+
unit_value: 50.00,
|
|
146
|
+
notes: "Wrong item sent"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
success = complete_return_workflow("ORD-2024-001", items)
|
|
151
|
+
puts success ? "Workflow completed!" : "Workflow failed!"
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Token Management Patterns
|
|
155
|
+
|
|
156
|
+
### Pattern 1: Simple One-Time Use
|
|
157
|
+
```ruby
|
|
158
|
+
# For scripts or one-off operations
|
|
159
|
+
auth_client = Mintsoft::AuthClient.new
|
|
160
|
+
auth_response = auth_client.auth.authenticate("username", "password")
|
|
161
|
+
|
|
162
|
+
client = Mintsoft::Client.new(token: auth_response.token)
|
|
163
|
+
# Perform operations...
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Pattern 2: Cached Token Manager
|
|
167
|
+
```ruby
|
|
168
|
+
class MintsoftService
|
|
169
|
+
def initialize(username, password)
|
|
170
|
+
@username = username
|
|
171
|
+
@password = password
|
|
172
|
+
@auth_client = Mintsoft::AuthClient.new
|
|
173
|
+
@auth_response = nil
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def client
|
|
177
|
+
ensure_valid_token!
|
|
178
|
+
Mintsoft::Client.new(token: @auth_response.token)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def token_info
|
|
182
|
+
@auth_response&.to_h
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
private
|
|
186
|
+
|
|
187
|
+
def ensure_valid_token!
|
|
188
|
+
if @auth_response.nil? || @auth_response.expired?
|
|
189
|
+
refresh_token!
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def refresh_token!
|
|
194
|
+
puts "Refreshing authentication token..."
|
|
195
|
+
@auth_response = @auth_client.auth.authenticate(@username, @password)
|
|
196
|
+
puts "Token refreshed, expires at: #{@auth_response.expires_at}"
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
# Usage
|
|
201
|
+
service = MintsoftService.new(ENV['MINTSOFT_USERNAME'], ENV['MINTSOFT_PASSWORD'])
|
|
202
|
+
|
|
203
|
+
# Token is automatically managed
|
|
204
|
+
client = service.client
|
|
205
|
+
orders = client.orders.search("ORD-001")
|
|
206
|
+
|
|
207
|
+
# Check token status
|
|
208
|
+
puts service.token_info
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Pattern 3: Thread-Safe Token Manager
|
|
212
|
+
```ruby
|
|
213
|
+
require 'thread'
|
|
214
|
+
|
|
215
|
+
class ThreadSafeTokenManager
|
|
216
|
+
def initialize(username, password)
|
|
217
|
+
@username = username
|
|
218
|
+
@password = password
|
|
219
|
+
@auth_client = Mintsoft::AuthClient.new
|
|
220
|
+
@auth_response = nil
|
|
221
|
+
@mutex = Mutex.new
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def client
|
|
225
|
+
token = current_token
|
|
226
|
+
Mintsoft::Client.new(token: token)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
private
|
|
230
|
+
|
|
231
|
+
def current_token
|
|
232
|
+
@mutex.synchronize do
|
|
233
|
+
if @auth_response.nil? || @auth_response.expired?
|
|
234
|
+
@auth_response = @auth_client.auth.authenticate(@username, @password)
|
|
235
|
+
end
|
|
236
|
+
@auth_response.token
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# Usage in multi-threaded environment
|
|
242
|
+
token_manager = ThreadSafeTokenManager.new("username", "password")
|
|
243
|
+
|
|
244
|
+
# Safe to use across multiple threads
|
|
245
|
+
threads = 3.times.map do |i|
|
|
246
|
+
Thread.new do
|
|
247
|
+
client = token_manager.client
|
|
248
|
+
orders = client.orders.search("ORD-00#{i}")
|
|
249
|
+
puts "Thread #{i}: Found #{orders.length} orders"
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
threads.each(&:join)
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Pattern 4: Persistent Token Storage
|
|
257
|
+
```ruby
|
|
258
|
+
require 'json'
|
|
259
|
+
require 'fileutils'
|
|
260
|
+
|
|
261
|
+
class PersistentTokenManager
|
|
262
|
+
TOKEN_FILE = '.mintsoft_token'
|
|
263
|
+
|
|
264
|
+
def initialize(username, password)
|
|
265
|
+
@username = username
|
|
266
|
+
@password = password
|
|
267
|
+
@auth_client = Mintsoft::AuthClient.new
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def client
|
|
271
|
+
token = current_token
|
|
272
|
+
Mintsoft::Client.new(token: token)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def clear_stored_token
|
|
276
|
+
File.delete(TOKEN_FILE) if File.exist?(TOKEN_FILE)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
private
|
|
280
|
+
|
|
281
|
+
def current_token
|
|
282
|
+
stored_token = load_stored_token
|
|
283
|
+
|
|
284
|
+
if stored_token && !token_expired?(stored_token)
|
|
285
|
+
return stored_token['token']
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# Get fresh token and store it
|
|
289
|
+
auth_response = @auth_client.auth.authenticate(@username, @password)
|
|
290
|
+
store_token(auth_response)
|
|
291
|
+
auth_response.token
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def load_stored_token
|
|
295
|
+
return nil unless File.exist?(TOKEN_FILE)
|
|
296
|
+
|
|
297
|
+
begin
|
|
298
|
+
JSON.parse(File.read(TOKEN_FILE))
|
|
299
|
+
rescue JSON::ParserError
|
|
300
|
+
nil
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def store_token(auth_response)
|
|
305
|
+
token_data = {
|
|
306
|
+
'token' => auth_response.token,
|
|
307
|
+
'expires_at' => auth_response.expires_at.to_i,
|
|
308
|
+
'created_at' => Time.now.to_i
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
File.write(TOKEN_FILE, JSON.pretty_generate(token_data))
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def token_expired?(stored_token)
|
|
315
|
+
expires_at = Time.at(stored_token['expires_at'])
|
|
316
|
+
Time.now >= expires_at
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
# Usage
|
|
321
|
+
token_manager = PersistentTokenManager.new("username", "password")
|
|
322
|
+
|
|
323
|
+
# Token persists across script runs
|
|
324
|
+
client = token_manager.client
|
|
325
|
+
|
|
326
|
+
# Clear stored token if needed
|
|
327
|
+
# token_manager.clear_stored_token
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Error Handling Patterns
|
|
331
|
+
|
|
332
|
+
### Pattern 1: Basic Error Handling
|
|
333
|
+
```ruby
|
|
334
|
+
begin
|
|
335
|
+
auth_client = Mintsoft::AuthClient.new
|
|
336
|
+
auth_response = auth_client.auth.authenticate("username", "password")
|
|
337
|
+
|
|
338
|
+
client = Mintsoft::Client.new(token: auth_response.token)
|
|
339
|
+
orders = client.orders.search("ORD-001")
|
|
340
|
+
|
|
341
|
+
puts "Found #{orders.length} orders"
|
|
342
|
+
|
|
343
|
+
rescue Mintsoft::AuthenticationError => e
|
|
344
|
+
puts "Authentication failed: #{e.message}"
|
|
345
|
+
rescue Mintsoft::ValidationError => e
|
|
346
|
+
puts "Invalid input: #{e.message}"
|
|
347
|
+
rescue Mintsoft::NotFoundError => e
|
|
348
|
+
puts "Resource not found: #{e.message}"
|
|
349
|
+
rescue Mintsoft::APIError => e
|
|
350
|
+
puts "API error (#{e.status_code}): #{e.message}"
|
|
351
|
+
rescue Mintsoft::Error => e
|
|
352
|
+
puts "Mintsoft error: #{e.message}"
|
|
353
|
+
end
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Pattern 2: Retry Logic
|
|
357
|
+
```ruby
|
|
358
|
+
def with_retry(max_attempts: 3, delay: 1)
|
|
359
|
+
attempt = 1
|
|
360
|
+
|
|
361
|
+
begin
|
|
362
|
+
yield
|
|
363
|
+
rescue Mintsoft::APIError => e
|
|
364
|
+
if e.status_code == 500 && attempt < max_attempts
|
|
365
|
+
puts "Server error, retrying in #{delay} seconds... (attempt #{attempt}/#{max_attempts})"
|
|
366
|
+
sleep(delay)
|
|
367
|
+
attempt += 1
|
|
368
|
+
retry
|
|
369
|
+
else
|
|
370
|
+
raise e
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
# Usage
|
|
376
|
+
with_retry(max_attempts: 3, delay: 2) do
|
|
377
|
+
client = Mintsoft::Client.new(token: token)
|
|
378
|
+
orders = client.orders.search("ORD-001")
|
|
379
|
+
end
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Pattern 3: Token Expiration Handling
|
|
383
|
+
```ruby
|
|
384
|
+
def execute_with_token_retry(&block)
|
|
385
|
+
attempt = 1
|
|
386
|
+
max_attempts = 2
|
|
387
|
+
|
|
388
|
+
begin
|
|
389
|
+
block.call
|
|
390
|
+
rescue Mintsoft::AuthenticationError => e
|
|
391
|
+
if e.status_code == 401 && attempt < max_attempts
|
|
392
|
+
puts "Token expired, refreshing..."
|
|
393
|
+
# Get new token
|
|
394
|
+
auth_response = @auth_client.auth.authenticate(@username, @password)
|
|
395
|
+
@current_token = auth_response.token
|
|
396
|
+
|
|
397
|
+
attempt += 1
|
|
398
|
+
retry
|
|
399
|
+
else
|
|
400
|
+
raise e
|
|
401
|
+
end
|
|
402
|
+
end
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# Usage
|
|
406
|
+
execute_with_token_retry do
|
|
407
|
+
client = Mintsoft::Client.new(token: @current_token)
|
|
408
|
+
orders = client.orders.search("ORD-001")
|
|
409
|
+
end
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Testing Examples
|
|
413
|
+
|
|
414
|
+
### Test Setup with Mock Responses
|
|
415
|
+
```ruby
|
|
416
|
+
require 'rspec'
|
|
417
|
+
require 'webmock/rspec'
|
|
418
|
+
require 'mintsoft'
|
|
419
|
+
|
|
420
|
+
RSpec.describe 'Mintsoft Integration' do
|
|
421
|
+
before do
|
|
422
|
+
WebMock.disable_net_connect!
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
let(:auth_response_body) do
|
|
426
|
+
{
|
|
427
|
+
'token' => 'mock_api_token_12345',
|
|
428
|
+
'expires_in' => 86400,
|
|
429
|
+
'token_type' => 'Bearer'
|
|
430
|
+
}
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
let(:orders_response_body) do
|
|
434
|
+
[
|
|
435
|
+
{
|
|
436
|
+
'id' => 123,
|
|
437
|
+
'order_number' => 'ORD-2024-001',
|
|
438
|
+
'status' => 'pending',
|
|
439
|
+
'customer_id' => 456
|
|
440
|
+
}
|
|
441
|
+
]
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
describe 'authentication and order search' do
|
|
445
|
+
it 'authenticates and searches for orders' do
|
|
446
|
+
# Mock authentication endpoint
|
|
447
|
+
stub_request(:post, 'https://api.mintsoft.com/api/auth')
|
|
448
|
+
.with(body: { username: 'testuser', password: 'testpass' }.to_json)
|
|
449
|
+
.to_return(
|
|
450
|
+
status: 200,
|
|
451
|
+
body: auth_response_body.to_json,
|
|
452
|
+
headers: { 'Content-Type' => 'application/json' }
|
|
453
|
+
)
|
|
454
|
+
|
|
455
|
+
# Mock order search endpoint
|
|
456
|
+
stub_request(:get, 'https://api.mintsoft.com/api/Order/Search')
|
|
457
|
+
.with(query: { OrderNumber: 'ORD-2024-001' })
|
|
458
|
+
.to_return(
|
|
459
|
+
status: 200,
|
|
460
|
+
body: orders_response_body.to_json,
|
|
461
|
+
headers: { 'Content-Type' => 'application/json' }
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
# Test authentication
|
|
465
|
+
auth_client = Mintsoft::AuthClient.new
|
|
466
|
+
auth_response = auth_client.auth.authenticate('testuser', 'testpass')
|
|
467
|
+
|
|
468
|
+
expect(auth_response.token).to eq('mock_api_token_12345')
|
|
469
|
+
expect(auth_response.valid?).to be true
|
|
470
|
+
|
|
471
|
+
# Test order search
|
|
472
|
+
client = Mintsoft::Client.new(token: auth_response.token)
|
|
473
|
+
orders = client.orders.search('ORD-2024-001')
|
|
474
|
+
|
|
475
|
+
expect(orders.length).to eq(1)
|
|
476
|
+
expect(orders.first.order_number).to eq('ORD-2024-001')
|
|
477
|
+
end
|
|
478
|
+
end
|
|
479
|
+
end
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
This comprehensive set of examples demonstrates various usage patterns for the Mintsoft gem, from basic operations to advanced token management and error handling strategies.
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Complete workflow example for the Mintsoft gem
|
|
5
|
+
# This demonstrates all 5 endpoints working together
|
|
6
|
+
|
|
7
|
+
require "mintsoft"
|
|
8
|
+
|
|
9
|
+
# Step 1: Authentication using AuthClient
|
|
10
|
+
puts "=== Step 1: Authentication ==="
|
|
11
|
+
auth_client = Mintsoft::AuthClient.new
|
|
12
|
+
begin
|
|
13
|
+
auth_response = auth_client.auth.authenticate(
|
|
14
|
+
ENV.fetch("MINTSOFT_USERNAME"),
|
|
15
|
+
ENV.fetch("MINTSOFT_PASSWORD")
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
puts "✅ Authentication successful!"
|
|
19
|
+
puts "Token: #{auth_response.token[0...10]}..."
|
|
20
|
+
puts "Expires at: #{auth_response.expires_at}"
|
|
21
|
+
puts "Expired?: #{auth_response.expired?}"
|
|
22
|
+
rescue Mintsoft::AuthenticationError => e
|
|
23
|
+
puts "❌ Authentication failed: #{e.message}"
|
|
24
|
+
exit 1
|
|
25
|
+
rescue KeyError => e
|
|
26
|
+
puts "❌ Environment variable not set: #{e.message}"
|
|
27
|
+
puts "Please set MINTSOFT_USERNAME and MINTSOFT_PASSWORD environment variables"
|
|
28
|
+
exit 1
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Step 2: Initialize client with token
|
|
32
|
+
puts "\n=== Step 2: Initialize Client ==="
|
|
33
|
+
client = Mintsoft::Client.new(token: auth_response.token)
|
|
34
|
+
puts "✅ Client initialized with token"
|
|
35
|
+
|
|
36
|
+
# Step 3: Search for orders
|
|
37
|
+
puts "\n=== Step 3: Search Orders ==="
|
|
38
|
+
order_number = "ORD-2024-001" # Change this to a real order number in your system
|
|
39
|
+
begin
|
|
40
|
+
orders = client.orders.search(order_number)
|
|
41
|
+
|
|
42
|
+
if orders.empty?
|
|
43
|
+
puts "⚠️ No orders found with number: #{order_number}"
|
|
44
|
+
puts "Please try with a different order number"
|
|
45
|
+
exit 1
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
order = orders.first
|
|
49
|
+
puts "✅ Found #{orders.size} order(s)"
|
|
50
|
+
puts "Order ID: #{order.id}"
|
|
51
|
+
puts "Order Number: #{order.order_number}"
|
|
52
|
+
puts "Customer ID: #{order.customer_id}" if order.respond_to?(:customer_id)
|
|
53
|
+
puts "Status: #{order.status}" if order.respond_to?(:status)
|
|
54
|
+
|
|
55
|
+
rescue Mintsoft::ValidationError => e
|
|
56
|
+
puts "❌ Validation error: #{e.message}"
|
|
57
|
+
exit 1
|
|
58
|
+
rescue Mintsoft::AuthenticationError => e
|
|
59
|
+
puts "❌ Authentication error: #{e.message}"
|
|
60
|
+
puts "Token may have expired. Please re-authenticate."
|
|
61
|
+
exit 1
|
|
62
|
+
rescue Mintsoft::APIError => e
|
|
63
|
+
puts "❌ API error: #{e.message}"
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Step 4: Get return reasons
|
|
68
|
+
puts "\n=== Step 4: Get Return Reasons ==="
|
|
69
|
+
begin
|
|
70
|
+
reasons = client.returns.reasons
|
|
71
|
+
puts "✅ Found #{reasons.size} return reason(s)"
|
|
72
|
+
|
|
73
|
+
reasons.each do |reason|
|
|
74
|
+
status = reason.active? ? "✅" : "❌"
|
|
75
|
+
puts " #{status} #{reason.name} (ID: #{reason.id}): #{reason.description}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Select the first active reason for demo
|
|
79
|
+
selected_reason = reasons.find(&:active?)
|
|
80
|
+
if selected_reason.nil?
|
|
81
|
+
puts "❌ No active return reasons found"
|
|
82
|
+
exit 1
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
puts "\n🎯 Selected reason: #{selected_reason.name}"
|
|
86
|
+
|
|
87
|
+
rescue Mintsoft::APIError => e
|
|
88
|
+
puts "❌ API error: #{e.message}"
|
|
89
|
+
exit 1
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Step 5: Create return
|
|
93
|
+
puts "\n=== Step 5: Create Return ==="
|
|
94
|
+
begin
|
|
95
|
+
return_obj = client.returns.create(order.id)
|
|
96
|
+
puts "✅ Return created successfully!"
|
|
97
|
+
puts "Return ID: #{return_obj.id}"
|
|
98
|
+
puts "Order ID: #{return_obj.order_id}"
|
|
99
|
+
puts "Status: #{return_obj.status}"
|
|
100
|
+
|
|
101
|
+
rescue Mintsoft::ValidationError => e
|
|
102
|
+
puts "❌ Validation error: #{e.message}"
|
|
103
|
+
exit 1
|
|
104
|
+
rescue Mintsoft::APIError => e
|
|
105
|
+
puts "❌ API error: #{e.message}"
|
|
106
|
+
exit 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Step 6: Add item to return
|
|
110
|
+
puts "\n=== Step 6: Add Item to Return ==="
|
|
111
|
+
item_attributes = {
|
|
112
|
+
product_id: 123, # Replace with actual product ID
|
|
113
|
+
quantity: 2, # Quantity to return
|
|
114
|
+
reason_id: selected_reason.id, # Selected return reason
|
|
115
|
+
unit_value: 25.00, # Unit value
|
|
116
|
+
notes: "Damaged during shipping" # Optional notes
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
begin
|
|
120
|
+
success = client.returns.add_item(return_obj.id, item_attributes)
|
|
121
|
+
|
|
122
|
+
if success
|
|
123
|
+
puts "✅ Item added to return successfully!"
|
|
124
|
+
puts "Product ID: #{item_attributes[:product_id]}"
|
|
125
|
+
puts "Quantity: #{item_attributes[:quantity]}"
|
|
126
|
+
puts "Reason: #{selected_reason.name}"
|
|
127
|
+
puts "Unit Value: $#{item_attributes[:unit_value]}"
|
|
128
|
+
puts "Notes: #{item_attributes[:notes]}"
|
|
129
|
+
else
|
|
130
|
+
puts "❌ Failed to add item to return"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
rescue Mintsoft::ValidationError => e
|
|
134
|
+
puts "❌ Validation error: #{e.message}"
|
|
135
|
+
rescue Mintsoft::APIError => e
|
|
136
|
+
puts "❌ API error: #{e.message}"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
puts "\n=== Workflow Complete ==="
|
|
140
|
+
puts "🎉 Successfully completed the full Mintsoft API workflow!"
|
|
141
|
+
puts " 1. ✅ Authenticated and got token"
|
|
142
|
+
puts " 2. ✅ Initialized client"
|
|
143
|
+
puts " 3. ✅ Searched for orders"
|
|
144
|
+
puts " 4. ✅ Retrieved return reasons"
|
|
145
|
+
puts " 5. ✅ Created return"
|
|
146
|
+
puts " 6. ✅ Added item to return"
|