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.
@@ -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"