@chanaka_nakandala/integration-agent 1.0.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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/dist/cache/file-cache.d.ts +10 -0
  4. package/dist/cache/file-cache.d.ts.map +1 -0
  5. package/dist/cache/file-cache.js +79 -0
  6. package/dist/cache/file-cache.js.map +1 -0
  7. package/dist/cli/init-command.d.ts +2 -0
  8. package/dist/cli/init-command.d.ts.map +1 -0
  9. package/dist/cli/init-command.js +115 -0
  10. package/dist/cli/init-command.js.map +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +493 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/scrapers/docs-scraper.d.ts +28 -0
  16. package/dist/scrapers/docs-scraper.d.ts.map +1 -0
  17. package/dist/scrapers/docs-scraper.js +200 -0
  18. package/dist/scrapers/docs-scraper.js.map +1 -0
  19. package/dist/search/keyword-search.d.ts +39 -0
  20. package/dist/search/keyword-search.d.ts.map +1 -0
  21. package/dist/search/keyword-search.js +127 -0
  22. package/dist/search/keyword-search.js.map +1 -0
  23. package/dist/tools/code-generation-tool.d.ts +33 -0
  24. package/dist/tools/code-generation-tool.d.ts.map +1 -0
  25. package/dist/tools/code-generation-tool.js +62 -0
  26. package/dist/tools/code-generation-tool.js.map +1 -0
  27. package/dist/tools/search-result-formatter.d.ts +27 -0
  28. package/dist/tools/search-result-formatter.d.ts.map +1 -0
  29. package/dist/tools/search-result-formatter.js +89 -0
  30. package/dist/tools/search-result-formatter.js.map +1 -0
  31. package/dist/tools/search-tool.d.ts +9 -0
  32. package/dist/tools/search-tool.d.ts.map +1 -0
  33. package/dist/tools/search-tool.js +32 -0
  34. package/dist/tools/search-tool.js.map +1 -0
  35. package/dist/tools/template-loader.d.ts +54 -0
  36. package/dist/tools/template-loader.d.ts.map +1 -0
  37. package/dist/tools/template-loader.js +148 -0
  38. package/dist/tools/template-loader.js.map +1 -0
  39. package/dist/types/search.d.ts +21 -0
  40. package/dist/types/search.d.ts.map +1 -0
  41. package/dist/types/search.js +2 -0
  42. package/dist/types/search.js.map +1 -0
  43. package/package.json +63 -0
  44. package/templates/README.md +98 -0
  45. package/templates/authenticate/curl.template +97 -0
  46. package/templates/authenticate/java.template +155 -0
  47. package/templates/authenticate/python.template +111 -0
  48. package/templates/authenticate/typescript.template +98 -0
  49. package/templates/create_menu/curl.template +145 -0
  50. package/templates/create_menu/java.template +285 -0
  51. package/templates/create_menu/python.template +159 -0
  52. package/templates/create_menu/typescript.template +184 -0
  53. package/templates/receive_order/curl.template +138 -0
  54. package/templates/receive_order/java.template +263 -0
  55. package/templates/receive_order/python.template +157 -0
  56. package/templates/receive_order/typescript.template +194 -0
  57. package/templates/update_item_availability/curl.template +143 -0
  58. package/templates/update_item_availability/java.template +279 -0
  59. package/templates/update_item_availability/python.template +203 -0
  60. package/templates/update_item_availability/typescript.template +194 -0
  61. package/templates/update_order_status/curl.template +138 -0
  62. package/templates/update_order_status/java.template +202 -0
  63. package/templates/update_order_status/python.template +142 -0
  64. package/templates/update_order_status/typescript.template +139 -0
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Grubtech Order Receive Webhook - TypeScript (Express.js)
3
+ *
4
+ * This example demonstrates how to receive orders from Grubtech
5
+ * via webhook and process them in your system.
6
+ *
7
+ * Prerequisites:
8
+ * - Node.js 18+
9
+ * - Express.js (npm install express)
10
+ * - crypto module (built-in)
11
+ *
12
+ * Replace the following placeholders:
13
+ * - {{WEBHOOK_SECRET}}: Your webhook secret for signature verification
14
+ * - {{ORDER_PROCESSING_LOGIC}}: Your business logic to process the order
15
+ */
16
+
17
+ import express, { Request, Response } from 'express';
18
+ import crypto from 'crypto';
19
+
20
+ const app = express();
21
+ const PORT = 3000;
22
+ const WEBHOOK_SECRET = '{{WEBHOOK_SECRET}}';
23
+
24
+ // Middleware to parse JSON and preserve raw body for signature verification
25
+ app.use(
26
+ express.json({
27
+ verify: (req: any, res, buf) => {
28
+ req.rawBody = buf.toString('utf8');
29
+ },
30
+ })
31
+ );
32
+
33
+ interface OrderItem {
34
+ id: string;
35
+ name: string;
36
+ quantity: number;
37
+ price: number;
38
+ modifiers?: Array<{ id: string; name: string; price: number }>;
39
+ }
40
+
41
+ interface Order {
42
+ orderId: string;
43
+ partnerOrderId?: string;
44
+ status: string;
45
+ createdAt: string;
46
+ customer: {
47
+ name: string;
48
+ phone: string;
49
+ email?: string;
50
+ };
51
+ delivery: {
52
+ type: 'delivery' | 'pickup';
53
+ address?: string;
54
+ city?: string;
55
+ instructions?: string;
56
+ };
57
+ items: OrderItem[];
58
+ totals: {
59
+ subtotal: number;
60
+ tax: number;
61
+ deliveryFee: number;
62
+ total: number;
63
+ };
64
+ payment: {
65
+ method: string;
66
+ status: string;
67
+ };
68
+ }
69
+
70
+ interface WebhookResponse {
71
+ accepted: boolean;
72
+ orderId?: string;
73
+ partnerOrderId?: string;
74
+ message?: string;
75
+ estimatedReadyTime?: string;
76
+ }
77
+
78
+ /**
79
+ * Verify webhook signature
80
+ */
81
+ function verifySignature(req: any): boolean {
82
+ const signature = req.headers['x-grubtech-signature'];
83
+
84
+ if (!signature) {
85
+ console.error('❌ No signature provided');
86
+ return false;
87
+ }
88
+
89
+ // Calculate expected signature using HMAC-SHA256
90
+ const expectedSignature = crypto
91
+ .createHmac('sha256', WEBHOOK_SECRET)
92
+ .update(req.rawBody)
93
+ .digest('hex');
94
+
95
+ // Constant-time comparison to prevent timing attacks
96
+ const isValid = crypto.timingSafeEqual(
97
+ Buffer.from(signature),
98
+ Buffer.from(expectedSignature)
99
+ );
100
+
101
+ if (!isValid) {
102
+ console.error('❌ Invalid signature');
103
+ }
104
+
105
+ return isValid;
106
+ }
107
+
108
+ /**
109
+ * Process order (replace with your business logic)
110
+ */
111
+ async function processOrder(order: Order): Promise<WebhookResponse> {
112
+ try {
113
+ console.log(`📦 Processing order: ${order.orderId}`);
114
+ console.log(`Customer: ${order.customer.name}`);
115
+ console.log(`Items: ${order.items.length}`);
116
+ console.log(`Total: $${order.totals.total}`);
117
+
118
+ // {{ORDER_PROCESSING_LOGIC}}
119
+ // Example: Save to database, notify kitchen, etc.
120
+
121
+ // Simulate processing time
122
+ await new Promise((resolve) => setTimeout(resolve, 100));
123
+
124
+ // Calculate estimated ready time (example: 30 minutes from now)
125
+ const readyTime = new Date(Date.now() + 30 * 60 * 1000).toISOString();
126
+
127
+ return {
128
+ accepted: true,
129
+ orderId: order.orderId,
130
+ partnerOrderId: `POS-${Date.now()}`,
131
+ message: 'Order accepted successfully',
132
+ estimatedReadyTime: readyTime,
133
+ };
134
+ } catch (error) {
135
+ console.error('❌ Order processing error:', error);
136
+
137
+ return {
138
+ accepted: false,
139
+ orderId: order.orderId,
140
+ message: `Order rejected: ${error}`,
141
+ };
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Webhook endpoint to receive orders from Grubtech
147
+ */
148
+ app.post('/webhooks/grubtech/orders', async (req: Request, res: Response) => {
149
+ try {
150
+ // Verify signature
151
+ if (!verifySignature(req)) {
152
+ return res.status(401).json({
153
+ accepted: false,
154
+ message: 'Invalid signature',
155
+ });
156
+ }
157
+
158
+ const order: Order = req.body;
159
+
160
+ // Validate order data
161
+ if (!order.orderId || !order.items || order.items.length === 0) {
162
+ return res.status(400).json({
163
+ accepted: false,
164
+ message: 'Invalid order data',
165
+ });
166
+ }
167
+
168
+ // Process order
169
+ const response = await processOrder(order);
170
+
171
+ // Send response
172
+ const statusCode = response.accepted ? 200 : 400;
173
+ return res.status(statusCode).json(response);
174
+ } catch (error) {
175
+ console.error('❌ Webhook error:', error);
176
+ return res.status(500).json({
177
+ accepted: false,
178
+ message: 'Internal server error',
179
+ });
180
+ }
181
+ });
182
+
183
+ /**
184
+ * Health check endpoint
185
+ */
186
+ app.get('/health', (req: Request, res: Response) => {
187
+ res.json({ status: 'ok' });
188
+ });
189
+
190
+ // Start server
191
+ app.listen(PORT, () => {
192
+ console.log(`✅ Webhook server listening on port ${PORT}`);
193
+ console.log(`Webhook URL: http://localhost:${PORT}/webhooks/grubtech/orders`);
194
+ });
@@ -0,0 +1,143 @@
1
+ #!/bin/bash
2
+
3
+ # Grubtech Item Availability Update - cURL
4
+ #
5
+ # This example demonstrates how to update menu item availability in Grubtech.
6
+ #
7
+ # Prerequisites:
8
+ # - curl command-line tool
9
+ # - jq (for JSON parsing, optional)
10
+ # - Valid access token from authentication
11
+ #
12
+ # Replace the following placeholders:
13
+ # - {{AUTH_TOKEN}}: Access token from authentication step
14
+ # - {{ITEM_ID}}: The menu item ID to update
15
+ # - {{AVAILABLE_STATUS}}: Boolean availability status (true/false)
16
+
17
+ AUTH_TOKEN="{{AUTH_TOKEN}}"
18
+ ITEM_ID="{{ITEM_ID}}"
19
+ AVAILABLE_STATUS={{AVAILABLE_STATUS}} # true or false
20
+ BASE_URL="https://api.grubtech.io"
21
+
22
+ # Update single item availability
23
+ update_item_availability() {
24
+ local item_id=$1
25
+ local available=$2
26
+ local reason=$3
27
+
28
+ echo "Updating item ${item_id}: available=${available}"
29
+
30
+ # Construct payload
31
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
32
+ PAYLOAD=$(cat <<EOF
33
+ {
34
+ "itemId": "${item_id}",
35
+ "available": ${available},
36
+ "timestamp": "${TIMESTAMP}",
37
+ "reason": "${reason}"
38
+ }
39
+ EOF
40
+ )
41
+
42
+ # Make availability update request
43
+ RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT \
44
+ "${BASE_URL}/v1/items/${item_id}/availability" \
45
+ -H "Authorization: Bearer ${AUTH_TOKEN}" \
46
+ -H "Content-Type: application/json" \
47
+ -d "$PAYLOAD")
48
+
49
+ # Extract HTTP status code and body
50
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n 1)
51
+ BODY=$(echo "$RESPONSE" | sed '$d')
52
+
53
+ # Check for errors
54
+ if [ "$HTTP_CODE" -ne 200 ]; then
55
+ echo "❌ Availability update failed: HTTP $HTTP_CODE"
56
+ echo "Response: $BODY"
57
+ return 1
58
+ fi
59
+
60
+ echo "✅ Item availability updated successfully!"
61
+ echo "$BODY" | jq '.' 2>/dev/null || echo "$BODY"
62
+ }
63
+
64
+ # Update multiple items in bulk
65
+ update_bulk_availability() {
66
+ echo "Updating multiple items availability..."
67
+
68
+ # Construct bulk payload
69
+ TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
70
+ PAYLOAD=$(cat <<'EOF'
71
+ {
72
+ "updates": [
73
+ {
74
+ "itemId": "item-123",
75
+ "available": false,
76
+ "reason": "Out of stock"
77
+ },
78
+ {
79
+ "itemId": "item-456",
80
+ "available": true,
81
+ "reason": "Back in stock"
82
+ },
83
+ {
84
+ "itemId": "item-789",
85
+ "available": true,
86
+ "reason": "In stock"
87
+ }
88
+ ],
89
+ "timestamp": "TIMESTAMP_PLACEHOLDER"
90
+ }
91
+ EOF
92
+ )
93
+
94
+ # Replace timestamp placeholder
95
+ PAYLOAD=$(echo "$PAYLOAD" | sed "s/TIMESTAMP_PLACEHOLDER/$TIMESTAMP/")
96
+
97
+ # Make bulk availability update request
98
+ RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT \
99
+ "${BASE_URL}/v1/items/availability/bulk" \
100
+ -H "Authorization: Bearer ${AUTH_TOKEN}" \
101
+ -H "Content-Type: application/json" \
102
+ -d "$PAYLOAD")
103
+
104
+ # Extract HTTP status code and body
105
+ HTTP_CODE=$(echo "$RESPONSE" | tail -n 1)
106
+ BODY=$(echo "$RESPONSE" | sed '$d')
107
+
108
+ # Check for errors
109
+ if [ "$HTTP_CODE" -ne 200 ]; then
110
+ echo "❌ Bulk availability update failed: HTTP $HTTP_CODE"
111
+ echo "Response: $BODY"
112
+ return 1
113
+ fi
114
+
115
+ echo "✅ Bulk availability updated successfully!"
116
+ echo "$BODY" | jq '.' 2>/dev/null || echo "$BODY"
117
+ }
118
+
119
+ # Helper functions
120
+ mark_out_of_stock() {
121
+ update_item_availability "$1" false "Out of stock"
122
+ }
123
+
124
+ mark_in_stock() {
125
+ update_item_availability "$1" true "Back in stock"
126
+ }
127
+
128
+ # Main execution
129
+ main() {
130
+ # Example 1: Single item update
131
+ update_item_availability "$ITEM_ID" "$AVAILABLE_STATUS" "Inventory sync"
132
+
133
+ echo ""
134
+
135
+ # Example 2: Mark item out of stock
136
+ # mark_out_of_stock "item-123"
137
+
138
+ # Example 3: Bulk update
139
+ # update_bulk_availability
140
+ }
141
+
142
+ # Run main function
143
+ main
@@ -0,0 +1,279 @@
1
+ /**
2
+ * Grubtech Item Availability Update - Java (Spring Boot)
3
+ *
4
+ * This example demonstrates how to update menu item availability in Grubtech
5
+ * to keep items in sync with your inventory status.
6
+ *
7
+ * Prerequisites:
8
+ * - Java 17+
9
+ * - Spring Boot 3.x
10
+ * - Spring WebFlux (for WebClient)
11
+ *
12
+ * Replace the following placeholders:
13
+ * - {{AUTH_TOKEN}}: Access token from authentication step
14
+ * - {{ITEM_ID}}: The menu item ID to update
15
+ * - {{AVAILABLE_STATUS}}: Boolean availability status (true/false)
16
+ */
17
+
18
+ package com.example.grubtech;
19
+
20
+ import org.springframework.http.HttpHeaders;
21
+ import org.springframework.http.MediaType;
22
+ import org.springframework.stereotype.Service;
23
+ import org.springframework.web.reactive.function.client.WebClient;
24
+ import reactor.core.publisher.Mono;
25
+
26
+ import java.time.Instant;
27
+ import java.util.HashMap;
28
+ import java.util.List;
29
+ import java.util.Map;
30
+ import java.util.stream.Collectors;
31
+
32
+ @Service
33
+ public class GrubtechItemAvailabilityService {
34
+
35
+ private static final String AUTH_TOKEN = "{{AUTH_TOKEN}}";
36
+ private static final String BASE_URL = "https://api.grubtech.io";
37
+
38
+ private final WebClient webClient;
39
+
40
+ public GrubtechItemAvailabilityService() {
41
+ this.webClient = WebClient.builder()
42
+ .baseUrl(BASE_URL)
43
+ .build();
44
+ }
45
+
46
+ /**
47
+ * Update single item availability
48
+ *
49
+ * @param itemId The menu item ID
50
+ * @param available True if in stock, False if out of stock
51
+ * @param reason Optional reason for status change
52
+ * @return Availability update response
53
+ */
54
+ public AvailabilityResponse updateItemAvailability(
55
+ String itemId,
56
+ boolean available,
57
+ String reason
58
+ ) {
59
+ try {
60
+ // Construct payload
61
+ Map<String, Object> payload = new HashMap<>();
62
+ payload.put("itemId", itemId);
63
+ payload.put("available", available);
64
+ payload.put("timestamp", Instant.now().toString());
65
+
66
+ if (reason != null && !reason.isEmpty()) {
67
+ payload.put("reason", reason);
68
+ }
69
+
70
+ System.out.println("Updating item " + itemId + ": available=" + available);
71
+
72
+ // Make availability update request
73
+ AvailabilityResponse response = webClient.put()
74
+ .uri("/v1/items/" + itemId + "/availability")
75
+ .header(HttpHeaders.AUTHORIZATION, "Bearer " + AUTH_TOKEN)
76
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
77
+ .bodyValue(payload)
78
+ .retrieve()
79
+ .onStatus(
80
+ status -> !status.is2xxSuccessful(),
81
+ clientResponse -> clientResponse.bodyToMono(String.class)
82
+ .flatMap(errorBody -> Mono.error(
83
+ new RuntimeException(
84
+ "Availability update failed: " +
85
+ clientResponse.statusCode() +
86
+ " - " + errorBody
87
+ )
88
+ ))
89
+ )
90
+ .bodyToMono(AvailabilityResponse.class)
91
+ .block();
92
+
93
+ if (response == null) {
94
+ throw new RuntimeException("No response received");
95
+ }
96
+
97
+ System.out.println("✅ Item availability updated successfully!");
98
+ System.out.println("Item ID: " + response.getItemId());
99
+ System.out.println("Available: " + available);
100
+
101
+ return response;
102
+
103
+ } catch (Exception e) {
104
+ System.err.println("❌ Availability update error: " + e.getMessage());
105
+ throw e;
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Update multiple items availability in bulk
111
+ *
112
+ * @param updates List of item availability updates
113
+ * @return Bulk availability update response
114
+ */
115
+ public BulkAvailabilityResponse updateBulkAvailability(
116
+ List<ItemUpdate> updates
117
+ ) {
118
+ try {
119
+ // Construct bulk payload
120
+ Map<String, Object> payload = new HashMap<>();
121
+ payload.put("updates", updates);
122
+ payload.put("timestamp", Instant.now().toString());
123
+
124
+ System.out.println("Updating " + updates.size() + " items availability");
125
+
126
+ // Make bulk availability update request
127
+ BulkAvailabilityResponse response = webClient.put()
128
+ .uri("/v1/items/availability/bulk")
129
+ .header(HttpHeaders.AUTHORIZATION, "Bearer " + AUTH_TOKEN)
130
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
131
+ .bodyValue(payload)
132
+ .retrieve()
133
+ .onStatus(
134
+ status -> !status.is2xxSuccessful(),
135
+ clientResponse -> Mono.error(
136
+ new RuntimeException(
137
+ "Bulk availability update failed: " +
138
+ clientResponse.statusCode()
139
+ )
140
+ )
141
+ )
142
+ .bodyToMono(BulkAvailabilityResponse.class)
143
+ .block();
144
+
145
+ if (response == null) {
146
+ throw new RuntimeException("No response received");
147
+ }
148
+
149
+ System.out.println("✅ Bulk availability updated successfully!");
150
+ System.out.println("Updated: " + response.getUpdatedCount() + " items");
151
+
152
+ // Report any errors
153
+ if (response.getErrors() != null && !response.getErrors().isEmpty()) {
154
+ System.out.println("⚠️ " + response.getErrors().size() + " items had errors:");
155
+ response.getErrors().forEach(err ->
156
+ System.out.println(" - " + err.getItemId() + ": " + err.getError())
157
+ );
158
+ }
159
+
160
+ return response;
161
+
162
+ } catch (Exception e) {
163
+ System.err.println("❌ Bulk availability update error: " + e.getMessage());
164
+ throw e;
165
+ }
166
+ }
167
+
168
+ /**
169
+ * Mark item as out of stock
170
+ */
171
+ public AvailabilityResponse markOutOfStock(String itemId) {
172
+ return updateItemAvailability(itemId, false, "Out of stock");
173
+ }
174
+
175
+ /**
176
+ * Mark item as back in stock
177
+ */
178
+ public AvailabilityResponse markInStock(String itemId) {
179
+ return updateItemAvailability(itemId, true, "Back in stock");
180
+ }
181
+
182
+ /**
183
+ * Sync inventory with Grubtech
184
+ */
185
+ public BulkAvailabilityResponse syncInventory(Map<String, Boolean> inventory) {
186
+ List<ItemUpdate> updates = inventory.entrySet().stream()
187
+ .map(entry -> new ItemUpdate(
188
+ entry.getKey(),
189
+ entry.getValue(),
190
+ entry.getValue() ? "In stock" : "Out of stock"
191
+ ))
192
+ .collect(Collectors.toList());
193
+
194
+ return updateBulkAvailability(updates);
195
+ }
196
+
197
+ // Data models
198
+ public static class ItemUpdate {
199
+ private String itemId;
200
+ private boolean available;
201
+ private String reason;
202
+
203
+ public ItemUpdate(String itemId, boolean available, String reason) {
204
+ this.itemId = itemId;
205
+ this.available = available;
206
+ this.reason = reason;
207
+ }
208
+
209
+ // Getters
210
+ public String getItemId() { return itemId; }
211
+ public boolean isAvailable() { return available; }
212
+ public String getReason() { return reason; }
213
+ }
214
+
215
+ public static class AvailabilityResponse {
216
+ private boolean success;
217
+ private String itemId;
218
+ private String message;
219
+
220
+ // Getters and setters
221
+ public boolean isSuccess() { return success; }
222
+ public void setSuccess(boolean success) { this.success = success; }
223
+ public String getItemId() { return itemId; }
224
+ public void setItemId(String itemId) { this.itemId = itemId; }
225
+ public String getMessage() { return message; }
226
+ public void setMessage(String message) { this.message = message; }
227
+ }
228
+
229
+ public static class BulkAvailabilityResponse {
230
+ private boolean success;
231
+ private int updatedCount;
232
+ private List<ItemError> errors;
233
+
234
+ // Getters and setters
235
+ public boolean isSuccess() { return success; }
236
+ public void setSuccess(boolean success) { this.success = success; }
237
+ public int getUpdatedCount() { return updatedCount; }
238
+ public void setUpdatedCount(int updatedCount) { this.updatedCount = updatedCount; }
239
+ public List<ItemError> getErrors() { return errors; }
240
+ public void setErrors(List<ItemError> errors) { this.errors = errors; }
241
+ }
242
+
243
+ public static class ItemError {
244
+ private String itemId;
245
+ private String error;
246
+
247
+ // Getters and setters
248
+ public String getItemId() { return itemId; }
249
+ public void setItemId(String itemId) { this.itemId = itemId; }
250
+ public String getError() { return error; }
251
+ public void setError(String error) { this.error = error; }
252
+ }
253
+
254
+ // Main method for testing
255
+ public static void main(String[] args) {
256
+ try {
257
+ GrubtechItemAvailabilityService service = new GrubtechItemAvailabilityService();
258
+
259
+ String itemId = "{{ITEM_ID}}";
260
+ boolean available = {{AVAILABLE_STATUS}}; // true or false
261
+
262
+ // Example 1: Single item update
263
+ service.updateItemAvailability(itemId, available, "Inventory sync");
264
+
265
+ // Example 2: Mark item out of stock
266
+ // service.markOutOfStock("item-123");
267
+
268
+ // Example 3: Bulk update from inventory
269
+ // service.syncInventory(Map.of(
270
+ // "item-123", false, // Out of stock
271
+ // "item-456", true, // In stock
272
+ // "item-789", true // In stock
273
+ // ));
274
+
275
+ } catch (Exception e) {
276
+ System.exit(1);
277
+ }
278
+ }
279
+ }