@arela/uploader 0.2.13 → 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.
- package/.env.template +66 -0
- package/README.md +263 -62
- package/docs/API_ENDPOINTS_FOR_DETECTION.md +647 -0
- package/docs/QUICK_REFERENCE_API_DETECTION.md +264 -0
- package/docs/REFACTORING_SUMMARY_DETECT_PEDIMENTOS.md +200 -0
- package/package.json +3 -2
- package/scripts/cleanup-ds-store.js +109 -0
- package/scripts/cleanup-system-files.js +69 -0
- package/scripts/tests/phase-7-features.test.js +415 -0
- package/scripts/tests/signal-handling.test.js +275 -0
- package/scripts/tests/smart-watch-integration.test.js +554 -0
- package/scripts/tests/watch-service-integration.test.js +584 -0
- package/src/commands/UploadCommand.js +31 -4
- package/src/commands/WatchCommand.js +1342 -0
- package/src/config/config.js +270 -2
- package/src/document-type-shared.js +2 -0
- package/src/document-types/support-document.js +200 -0
- package/src/file-detection.js +9 -1
- package/src/index.js +163 -4
- package/src/services/AdvancedFilterService.js +505 -0
- package/src/services/AutoProcessingService.js +749 -0
- package/src/services/BenchmarkingService.js +381 -0
- package/src/services/DatabaseService.js +1019 -539
- package/src/services/ErrorMonitor.js +275 -0
- package/src/services/LoggingService.js +419 -1
- package/src/services/MonitoringService.js +401 -0
- package/src/services/PerformanceOptimizer.js +511 -0
- package/src/services/ReportingService.js +511 -0
- package/src/services/SignalHandler.js +255 -0
- package/src/services/SmartWatchDatabaseService.js +527 -0
- package/src/services/WatchService.js +783 -0
- package/src/services/upload/ApiUploadService.js +447 -3
- package/src/services/upload/MultiApiUploadService.js +233 -0
- package/src/services/upload/SupabaseUploadService.js +12 -5
- package/src/services/upload/UploadServiceFactory.js +24 -0
- package/src/utils/CleanupManager.js +262 -0
- package/src/utils/FileOperations.js +44 -0
- package/src/utils/WatchEventHandler.js +522 -0
- package/supabase/migrations/001_create_initial_schema.sql +366 -0
- package/supabase/migrations/002_align_with_arela_api_schema.sql +145 -0
- package/.envbackup +0 -37
- package/SUPABASE_UPLOAD_FIX.md +0 -157
- package/commands.md +0 -14
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
# Backend API Endpoints for Pedimento Detection and Propagation
|
|
2
|
+
|
|
3
|
+
This document describes the required backend API endpoints needed to support the refactored detection and propagation functionality in the uploader client.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The uploader client has been refactored to use API endpoints instead of direct Supabase client queries for:
|
|
8
|
+
1. PDF pedimento detection process
|
|
9
|
+
2. Arela path propagation to related files
|
|
10
|
+
|
|
11
|
+
This provides better abstraction, security, and control over database operations.
|
|
12
|
+
|
|
13
|
+
## Required Endpoints
|
|
14
|
+
|
|
15
|
+
### 1. GET /api/uploader/pdf-records
|
|
16
|
+
|
|
17
|
+
Fetch PDF records that are ready for pedimento detection processing.
|
|
18
|
+
|
|
19
|
+
#### Authentication
|
|
20
|
+
- Requires `x-api-key` header
|
|
21
|
+
|
|
22
|
+
#### Query Parameters
|
|
23
|
+
|
|
24
|
+
| Parameter | Type | Required | Default | Description |
|
|
25
|
+
|-----------|------|----------|---------|-------------|
|
|
26
|
+
| `offset` | integer | No | 0 | Pagination offset for records |
|
|
27
|
+
| `limit` | integer | No | 100 | Maximum number of records to return |
|
|
28
|
+
| `status` | string | No | - | Filter by status field |
|
|
29
|
+
| `file_extension` | string | No | - | Filter by file extension |
|
|
30
|
+
| `is_like_simplificado` | boolean | No | - | Filter records likely to be simplificado |
|
|
31
|
+
|
|
32
|
+
#### Example Request
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
GET /api/uploader/pdf-records?offset=0&limit=100&status=fs-stats&file_extension=pdf&is_like_simplificado=true
|
|
36
|
+
Headers:
|
|
37
|
+
x-api-key: your-api-key-here
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### Response Format
|
|
41
|
+
|
|
42
|
+
**Success (200 OK)**
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
[
|
|
46
|
+
{
|
|
47
|
+
"id": "uuid-here",
|
|
48
|
+
"original_path": "/path/to/file.pdf",
|
|
49
|
+
"filename": "file.pdf",
|
|
50
|
+
"file_extension": "pdf",
|
|
51
|
+
"status": "fs-stats"
|
|
52
|
+
},
|
|
53
|
+
...
|
|
54
|
+
]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Error Response**
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"error": "Error message here",
|
|
62
|
+
"message": "Detailed error description"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
#### Implementation Notes
|
|
67
|
+
|
|
68
|
+
- Should query the `uploader` table in Supabase
|
|
69
|
+
- Apply filters based on query parameters
|
|
70
|
+
- Order results by `created_at` for consistent pagination
|
|
71
|
+
- Use efficient indexing on frequently filtered columns (`status`, `file_extension`, `is_like_simplificado`)
|
|
72
|
+
- Should support range queries for pagination: `range(offset, offset + limit - 1)`
|
|
73
|
+
|
|
74
|
+
#### SQL Query Example
|
|
75
|
+
|
|
76
|
+
```sql
|
|
77
|
+
SELECT id, original_path, filename, file_extension, status
|
|
78
|
+
FROM uploader
|
|
79
|
+
WHERE status = 'fs-stats'
|
|
80
|
+
AND file_extension = 'pdf'
|
|
81
|
+
AND is_like_simplificado = true
|
|
82
|
+
ORDER BY created_at
|
|
83
|
+
LIMIT 100 OFFSET 0;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### 2. PATCH /api/uploader/batch-update-detection
|
|
89
|
+
|
|
90
|
+
Batch update detection results for multiple records.
|
|
91
|
+
|
|
92
|
+
#### Authentication
|
|
93
|
+
- Requires `x-api-key` header
|
|
94
|
+
|
|
95
|
+
#### Request Body
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"updates": [
|
|
100
|
+
{
|
|
101
|
+
"id": "uuid-here",
|
|
102
|
+
"status": "detected",
|
|
103
|
+
"document_type": "pedimento-simplificado",
|
|
104
|
+
"num_pedimento": "23 12 3456 7890123",
|
|
105
|
+
"arela_path": "RFC123456789/2023/3456/",
|
|
106
|
+
"year": "2023",
|
|
107
|
+
"rfc": "RFC123456789",
|
|
108
|
+
"message": null
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "uuid-here-2",
|
|
112
|
+
"status": "file-not-found",
|
|
113
|
+
"message": "File no longer exists at original path"
|
|
114
|
+
},
|
|
115
|
+
...
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### Update Object Fields
|
|
121
|
+
|
|
122
|
+
| Field | Type | Required | Description |
|
|
123
|
+
|-------|------|----------|-------------|
|
|
124
|
+
| `id` | uuid | Yes | Record ID to update |
|
|
125
|
+
| `status` | string | Yes | New status: 'detected', 'not-detected', 'file-not-found', 'detection-error' |
|
|
126
|
+
| `document_type` | string | No | Detected document type (e.g., 'pedimento-simplificado') |
|
|
127
|
+
| `num_pedimento` | string | No | Detected pedimento number |
|
|
128
|
+
| `arela_path` | string | No | Generated Arela storage path |
|
|
129
|
+
| `year` | string | No | Extracted year from pedimento |
|
|
130
|
+
| `rfc` | string | No | Extracted RFC |
|
|
131
|
+
| `message` | string | No | Error message or additional notes |
|
|
132
|
+
|
|
133
|
+
#### Response Format
|
|
134
|
+
|
|
135
|
+
**Success (200 OK)**
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"success": true,
|
|
140
|
+
"updated": 25,
|
|
141
|
+
"errors": []
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Partial Success (200 OK)**
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"success": true,
|
|
150
|
+
"updated": 23,
|
|
151
|
+
"errors": [
|
|
152
|
+
{
|
|
153
|
+
"id": "uuid-that-failed",
|
|
154
|
+
"message": "Update failed: reason"
|
|
155
|
+
}
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Error Response (400/500)**
|
|
161
|
+
|
|
162
|
+
```json
|
|
163
|
+
{
|
|
164
|
+
"success": false,
|
|
165
|
+
"updated": 0,
|
|
166
|
+
"errors": [
|
|
167
|
+
{
|
|
168
|
+
"message": "Validation error or other error description"
|
|
169
|
+
}
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Implementation Notes
|
|
175
|
+
|
|
176
|
+
- Should perform batch updates efficiently (use bulk UPDATE or upsert operations)
|
|
177
|
+
- Validate that all required fields are present
|
|
178
|
+
- Handle partial failures gracefully - some updates may succeed while others fail
|
|
179
|
+
- Consider transaction handling for data consistency
|
|
180
|
+
- Log all updates for audit purposes
|
|
181
|
+
- Should handle updates in batches of reasonable size (e.g., 100-500 records)
|
|
182
|
+
|
|
183
|
+
#### SQL Query Example (PostgreSQL)
|
|
184
|
+
|
|
185
|
+
```sql
|
|
186
|
+
-- Using a CTE (Common Table Expression) for batch updates
|
|
187
|
+
WITH update_data(id, status, document_type, num_pedimento, arela_path, year, rfc, message) AS (
|
|
188
|
+
VALUES
|
|
189
|
+
('uuid-1'::uuid, 'detected', 'pedimento-simplificado', '23 12 3456 7890123', 'RFC/2023/3456/', '2023', 'RFC123456789', NULL),
|
|
190
|
+
('uuid-2'::uuid, 'file-not-found', NULL, NULL, NULL, NULL, NULL, 'File no longer exists')
|
|
191
|
+
)
|
|
192
|
+
UPDATE uploader AS u
|
|
193
|
+
SET
|
|
194
|
+
status = ud.status,
|
|
195
|
+
document_type = COALESCE(ud.document_type, u.document_type),
|
|
196
|
+
num_pedimento = COALESCE(ud.num_pedimento, u.num_pedimento),
|
|
197
|
+
arela_path = COALESCE(ud.arela_path, u.arela_path),
|
|
198
|
+
year = COALESCE(ud.year, u.year),
|
|
199
|
+
rfc = COALESCE(ud.rfc, u.rfc),
|
|
200
|
+
message = COALESCE(ud.message, u.message),
|
|
201
|
+
updated_at = NOW()
|
|
202
|
+
FROM update_data AS ud
|
|
203
|
+
WHERE u.id = ud.id;
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
### 3. POST /api/uploader/propagate-arela-path
|
|
209
|
+
|
|
210
|
+
Execute arela_path propagation process on the backend. This endpoint handles all the logic for finding pedimentos and propagating their arela_path to related files in the same directory.
|
|
211
|
+
|
|
212
|
+
#### Authentication
|
|
213
|
+
- Requires `x-api-key` header
|
|
214
|
+
|
|
215
|
+
#### Request Body
|
|
216
|
+
|
|
217
|
+
```json
|
|
218
|
+
{
|
|
219
|
+
"years": ["2023", "2024"]
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
| Field | Type | Required | Description |
|
|
224
|
+
|-------|------|----------|-------------|
|
|
225
|
+
| `years` | array of strings | No | Optional year filter (e.g., ["2023", "2024"]) |
|
|
226
|
+
|
|
227
|
+
#### Example Request
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
POST /api/uploader/propagate-arela-path
|
|
231
|
+
Headers:
|
|
232
|
+
x-api-key: your-api-key-here
|
|
233
|
+
Content-Type: application/json
|
|
234
|
+
Body:
|
|
235
|
+
{
|
|
236
|
+
"years": ["2023", "2024"]
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
#### Response Format
|
|
241
|
+
|
|
242
|
+
**Success (200 OK)**
|
|
243
|
+
|
|
244
|
+
```json
|
|
245
|
+
{
|
|
246
|
+
"success": true,
|
|
247
|
+
"processedCount": 150,
|
|
248
|
+
"updatedCount": 1250,
|
|
249
|
+
"errorCount": 2
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Error Response**
|
|
254
|
+
|
|
255
|
+
```json
|
|
256
|
+
{
|
|
257
|
+
"success": false,
|
|
258
|
+
"processedCount": 0,
|
|
259
|
+
"updatedCount": 0,
|
|
260
|
+
"errorCount": 1,
|
|
261
|
+
"error": "Error message here"
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
#### Implementation Notes
|
|
266
|
+
|
|
267
|
+
This endpoint should perform all propagation logic server-side:
|
|
268
|
+
|
|
269
|
+
1. **Find Pedimentos**: Query `pedimento_simplificado` records that have `arela_path` set
|
|
270
|
+
- Filter by `years` if provided
|
|
271
|
+
- Order by `created_at` for consistent processing
|
|
272
|
+
|
|
273
|
+
2. **For Each Pedimento**:
|
|
274
|
+
- Extract the base directory path from `original_path`
|
|
275
|
+
- Extract the folder part of `arela_path` (remove filename if present)
|
|
276
|
+
- Find all related files in the same directory where `arela_path IS NULL`
|
|
277
|
+
- Update those files with the pedimento's `arela_path` and `year`
|
|
278
|
+
|
|
279
|
+
3. **Pagination**: Process records in batches to handle large datasets
|
|
280
|
+
- Use cursor-based or offset pagination internally
|
|
281
|
+
- Handle pagination reset when updates change query results
|
|
282
|
+
|
|
283
|
+
4. **Error Handling**: Continue processing even if some records fail
|
|
284
|
+
- Track errors but don't stop the entire process
|
|
285
|
+
- Return counts of processed, updated, and errors
|
|
286
|
+
|
|
287
|
+
#### SQL Logic Example
|
|
288
|
+
|
|
289
|
+
```sql
|
|
290
|
+
-- Step 1: Find pedimentos with arela_path
|
|
291
|
+
WITH pedimentos AS (
|
|
292
|
+
SELECT id, original_path, arela_path, year
|
|
293
|
+
FROM uploader
|
|
294
|
+
WHERE document_type = 'pedimento_simplificado'
|
|
295
|
+
AND arela_path IS NOT NULL
|
|
296
|
+
AND ($1::text[] IS NULL OR year = ANY($1::text[]))
|
|
297
|
+
ORDER BY created_at
|
|
298
|
+
)
|
|
299
|
+
-- Step 2: For each pedimento, update related files
|
|
300
|
+
UPDATE uploader u
|
|
301
|
+
SET
|
|
302
|
+
arela_path = p.arela_path,
|
|
303
|
+
year = p.year,
|
|
304
|
+
updated_at = NOW()
|
|
305
|
+
FROM pedimentos p
|
|
306
|
+
WHERE u.arela_path IS NULL
|
|
307
|
+
AND u.original_path LIKE (SELECT regexp_replace(p.original_path, '/[^/]+$', '') || '%')
|
|
308
|
+
AND u.id != p.id;
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Note**: The actual implementation should process pedimentos iteratively with proper pagination and error handling, not in a single query.
|
|
312
|
+
|
|
313
|
+
#### Performance Considerations
|
|
314
|
+
|
|
315
|
+
- Process in batches of 50-100 pedimentos at a time
|
|
316
|
+
- Use batch updates (50-100 files per update query)
|
|
317
|
+
- Add appropriate database indexes on `original_path`, `arela_path`, `document_type`, `year`
|
|
318
|
+
- Consider using background jobs for large datasets
|
|
319
|
+
- Log progress for monitoring
|
|
320
|
+
- Handle transaction boundaries appropriately
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## RFC-Based Upload Endpoints
|
|
325
|
+
|
|
326
|
+
The following endpoints support RFC-based file upload operations.
|
|
327
|
+
|
|
328
|
+
### 4. GET /api/uploader/rfc-file-count
|
|
329
|
+
|
|
330
|
+
Get count of files for specified RFCs.
|
|
331
|
+
|
|
332
|
+
#### Authentication
|
|
333
|
+
- Requires `x-api-key` header
|
|
334
|
+
|
|
335
|
+
#### Query Parameters
|
|
336
|
+
|
|
337
|
+
| Parameter | Type | Required | Default | Description |
|
|
338
|
+
|-----------|------|----------|---------|-------------|
|
|
339
|
+
| `rfcs` | string | Yes | - | Comma-separated list of RFC values (e.g., "RFC123,RFC456") |
|
|
340
|
+
|
|
341
|
+
#### Example Request
|
|
342
|
+
|
|
343
|
+
```bash
|
|
344
|
+
GET /api/uploader/rfc-file-count?rfcs=RFC123456789,RFC987654321
|
|
345
|
+
Headers:
|
|
346
|
+
x-api-key: your-api-key-here
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
#### Response Format
|
|
350
|
+
|
|
351
|
+
**Success (200 OK)**
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"count": 1250
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### SQL Query Example
|
|
360
|
+
|
|
361
|
+
```sql
|
|
362
|
+
SELECT COUNT(*) as count
|
|
363
|
+
FROM uploader
|
|
364
|
+
WHERE rfc = ANY($1::text[])
|
|
365
|
+
AND arela_path IS NOT NULL;
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
### 5. GET /api/uploader/pedimentos-by-rfc
|
|
371
|
+
|
|
372
|
+
Fetch pedimento_simplificado records for specified RFCs.
|
|
373
|
+
|
|
374
|
+
#### Authentication
|
|
375
|
+
- Requires `x-api-key` header
|
|
376
|
+
|
|
377
|
+
#### Query Parameters
|
|
378
|
+
|
|
379
|
+
| Parameter | Type | Required | Default | Description |
|
|
380
|
+
|-----------|------|----------|---------|-------------|
|
|
381
|
+
| `rfcs` | string | Yes | - | Comma-separated list of RFC values |
|
|
382
|
+
| `years` | string | No | - | Optional comma-separated list of years to filter |
|
|
383
|
+
| `offset` | integer | No | 0 | Pagination offset |
|
|
384
|
+
| `limit` | integer | No | 500 | Maximum number of records to return |
|
|
385
|
+
|
|
386
|
+
#### Example Request
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
GET /api/uploader/pedimentos-by-rfc?rfcs=RFC123456789,RFC987654321&years=2023,2024&offset=0&limit=500
|
|
390
|
+
Headers:
|
|
391
|
+
x-api-key: your-api-key-here
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
#### Response Format
|
|
395
|
+
|
|
396
|
+
**Success (200 OK)**
|
|
397
|
+
|
|
398
|
+
```json
|
|
399
|
+
[
|
|
400
|
+
{
|
|
401
|
+
"arela_path": "RFC123456789/2023/3456/"
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"arela_path": "RFC123456789/2024/7890/"
|
|
405
|
+
}
|
|
406
|
+
]
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### SQL Query Example
|
|
410
|
+
|
|
411
|
+
```sql
|
|
412
|
+
SELECT arela_path
|
|
413
|
+
FROM uploader
|
|
414
|
+
WHERE document_type = 'pedimento_simplificado'
|
|
415
|
+
AND rfc = ANY($1::text[])
|
|
416
|
+
AND arela_path IS NOT NULL
|
|
417
|
+
AND ($2::text[] IS NULL OR year = ANY($2::text[]))
|
|
418
|
+
ORDER BY created_at
|
|
419
|
+
LIMIT $3 OFFSET $4;
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### 6. GET /api/uploader/files-for-upload
|
|
425
|
+
|
|
426
|
+
Fetch files ready for upload by arela_path.
|
|
427
|
+
|
|
428
|
+
#### Authentication
|
|
429
|
+
- Requires `x-api-key` header
|
|
430
|
+
|
|
431
|
+
#### Query Parameters
|
|
432
|
+
|
|
433
|
+
| Parameter | Type | Required | Default | Description |
|
|
434
|
+
|-----------|------|----------|---------|-------------|
|
|
435
|
+
| `arela_paths` | string | Yes | - | Pipe-separated list of arela_path values |
|
|
436
|
+
| `offset` | integer | No | 0 | Pagination offset |
|
|
437
|
+
| `limit` | integer | No | 1000 | Maximum number of records to return |
|
|
438
|
+
|
|
439
|
+
#### Example Request
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
GET /api/uploader/files-for-upload?arela_paths=RFC123/2023/3456/|RFC456/2024/7890/&offset=0&limit=1000
|
|
443
|
+
Headers:
|
|
444
|
+
x-api-key: your-api-key-here
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### Response Format
|
|
448
|
+
|
|
449
|
+
**Success (200 OK)**
|
|
450
|
+
|
|
451
|
+
```json
|
|
452
|
+
[
|
|
453
|
+
{
|
|
454
|
+
"id": "uuid-here",
|
|
455
|
+
"original_path": "/path/to/file.xml",
|
|
456
|
+
"arela_path": "RFC123456789/2023/3456/",
|
|
457
|
+
"filename": "file.xml",
|
|
458
|
+
"rfc": "RFC123456789",
|
|
459
|
+
"document_type": "support_document"
|
|
460
|
+
},
|
|
461
|
+
...
|
|
462
|
+
]
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
#### SQL Query Example
|
|
466
|
+
|
|
467
|
+
```sql
|
|
468
|
+
SELECT id, original_path, arela_path, filename, rfc, document_type
|
|
469
|
+
FROM uploader
|
|
470
|
+
WHERE arela_path = ANY($1::text[])
|
|
471
|
+
AND status != 'file-uploaded'
|
|
472
|
+
AND original_path IS NOT NULL
|
|
473
|
+
ORDER BY created_at
|
|
474
|
+
LIMIT $2 OFFSET $3;
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### 7. PATCH /api/uploader/batch-update-status
|
|
480
|
+
|
|
481
|
+
Batch update file status after upload operations.
|
|
482
|
+
|
|
483
|
+
#### Authentication
|
|
484
|
+
- Requires `x-api-key` header
|
|
485
|
+
|
|
486
|
+
#### Request Body
|
|
487
|
+
|
|
488
|
+
```json
|
|
489
|
+
{
|
|
490
|
+
"updates": [
|
|
491
|
+
{
|
|
492
|
+
"id": "uuid-here",
|
|
493
|
+
"status": "file-uploaded",
|
|
494
|
+
"message": "Successfully uploaded",
|
|
495
|
+
"processing_status": "UPLOADED"
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
"id": "uuid-here-2",
|
|
499
|
+
"status": "upload-error",
|
|
500
|
+
"message": "Upload failed: connection timeout"
|
|
501
|
+
}
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
#### Update Object Fields
|
|
507
|
+
|
|
508
|
+
| Field | Type | Required | Description |
|
|
509
|
+
|-------|------|----------|-------------|
|
|
510
|
+
| `id` | uuid | Yes | Record ID to update |
|
|
511
|
+
| `status` | string | Yes | New status value |
|
|
512
|
+
| `message` | string | No | Status message |
|
|
513
|
+
| `processing_status` | string | No | Processing queue status |
|
|
514
|
+
|
|
515
|
+
#### Response Format
|
|
516
|
+
|
|
517
|
+
**Success (200 OK)**
|
|
518
|
+
|
|
519
|
+
```json
|
|
520
|
+
{
|
|
521
|
+
"success": true,
|
|
522
|
+
"updated": 25,
|
|
523
|
+
"errors": []
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
**Partial Success (200 OK)**
|
|
528
|
+
|
|
529
|
+
```json
|
|
530
|
+
{
|
|
531
|
+
"success": true,
|
|
532
|
+
"updated": 23,
|
|
533
|
+
"errors": [
|
|
534
|
+
{
|
|
535
|
+
"id": "uuid-that-failed",
|
|
536
|
+
"message": "Update failed: reason"
|
|
537
|
+
}
|
|
538
|
+
]
|
|
539
|
+
}
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
#### SQL Query Example
|
|
543
|
+
|
|
544
|
+
```sql
|
|
545
|
+
WITH update_data(id, status, message, processing_status) AS (
|
|
546
|
+
VALUES
|
|
547
|
+
('uuid-1'::uuid, 'file-uploaded', 'Success', 'UPLOADED'),
|
|
548
|
+
('uuid-2'::uuid, 'upload-error', 'Failed', NULL)
|
|
549
|
+
)
|
|
550
|
+
UPDATE uploader AS u
|
|
551
|
+
SET
|
|
552
|
+
status = COALESCE(ud.status, u.status),
|
|
553
|
+
message = COALESCE(ud.message, u.message),
|
|
554
|
+
processing_status = COALESCE(ud.processing_status, u.processing_status),
|
|
555
|
+
updated_at = NOW()
|
|
556
|
+
FROM update_data AS ud
|
|
557
|
+
WHERE u.id = ud.id;
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
## Migration Path
|
|
563
|
+
|
|
564
|
+
### Phase 1: Implementation (Backend)
|
|
565
|
+
1. Implement all five endpoints in the backend API
|
|
566
|
+
2. Add proper authentication and authorization
|
|
567
|
+
3. Add rate limiting and request validation
|
|
568
|
+
4. Test endpoints with sample data
|
|
569
|
+
|
|
570
|
+
### Phase 2: Testing (Client)
|
|
571
|
+
1. Test the refactored client code with the new endpoints
|
|
572
|
+
2. Performance testing with large datasets
|
|
573
|
+
3. Verify pagination works correctly
|
|
574
|
+
|
|
575
|
+
### Phase 3: Deployment
|
|
576
|
+
1. Deploy backend API changes
|
|
577
|
+
2. Update client configuration to use API endpoints
|
|
578
|
+
3. Monitor logs for any issues
|
|
579
|
+
4. Phase out direct Supabase access completely
|
|
580
|
+
|
|
581
|
+
## Security Considerations
|
|
582
|
+
|
|
583
|
+
1. **Authentication**: All endpoints require valid `x-api-key` header
|
|
584
|
+
2. **Rate Limiting**: Implement rate limiting to prevent abuse
|
|
585
|
+
3. **Input Validation**: Validate all query parameters and request body data
|
|
586
|
+
4. **SQL Injection Prevention**: Use parameterized queries or ORM
|
|
587
|
+
5. **Authorization**: Ensure API keys have appropriate permissions
|
|
588
|
+
6. **Audit Logging**: Log all data access and modifications
|
|
589
|
+
7. **Path Traversal**: Validate `basePath` parameter to prevent directory traversal attacks
|
|
590
|
+
|
|
591
|
+
## Performance Considerations
|
|
592
|
+
|
|
593
|
+
1. **Indexing**: Add database indexes on commonly filtered columns:
|
|
594
|
+
- `status`
|
|
595
|
+
- `file_extension`
|
|
596
|
+
- `is_like_simplificado`
|
|
597
|
+
- `created_at`
|
|
598
|
+
- `document_type`
|
|
599
|
+
- `arela_path`
|
|
600
|
+
- `original_path` (consider using pg_trgm for LIKE queries)
|
|
601
|
+
- `year`
|
|
602
|
+
|
|
603
|
+
2. **Batch Size**: Optimize batch sizes for updates (50-100 records per batch for propagation)
|
|
604
|
+
|
|
605
|
+
3. **Connection Pooling**: Use database connection pooling to handle concurrent requests
|
|
606
|
+
|
|
607
|
+
4. **Caching**: Consider caching frequently accessed data
|
|
608
|
+
|
|
609
|
+
5. **Pagination**: Implement efficient pagination with cursors or offset/limit
|
|
610
|
+
|
|
611
|
+
6. **LIKE Query Optimization**: Use proper indexes or consider full-text search for path matching
|
|
612
|
+
|
|
613
|
+
## Error Handling
|
|
614
|
+
|
|
615
|
+
Both endpoints should return appropriate HTTP status codes:
|
|
616
|
+
|
|
617
|
+
- **200 OK**: Successful operation
|
|
618
|
+
- **400 Bad Request**: Invalid parameters or request body
|
|
619
|
+
- **401 Unauthorized**: Missing or invalid API key
|
|
620
|
+
- **429 Too Many Requests**: Rate limit exceeded
|
|
621
|
+
- **500 Internal Server Error**: Server-side error
|
|
622
|
+
|
|
623
|
+
## Testing Checklist
|
|
624
|
+
|
|
625
|
+
- [ ] GET /api/uploader/pdf-records returns correct records with filters
|
|
626
|
+
- [ ] GET /api/uploader/pdf-records handles pagination correctly
|
|
627
|
+
- [ ] GET /api/uploader/pdf-records returns empty array when no records found
|
|
628
|
+
- [ ] PATCH /api/uploader/batch-update-detection successfully updates records
|
|
629
|
+
- [ ] PATCH /api/uploader/batch-update-detection handles partial failures gracefully
|
|
630
|
+
- [ ] PATCH /api/uploader/batch-update-detection validates required fields
|
|
631
|
+
- [ ] GET /api/uploader/pedimentos-for-propagation returns correct pedimento records
|
|
632
|
+
- [ ] GET /api/uploader/pedimentos-for-propagation handles year filtering correctly
|
|
633
|
+
- [ ] GET /api/uploader/related-files finds files in same directory
|
|
634
|
+
- [ ] GET /api/uploader/related-files excludes pedimento record correctly
|
|
635
|
+
- [ ] PATCH /api/uploader/batch-update-arela-path successfully updates arela_path and year
|
|
636
|
+
- [ ] All endpoints require valid authentication
|
|
637
|
+
- [ ] All endpoints handle errors appropriately
|
|
638
|
+
- [ ] Performance testing with 10,000+ records
|
|
639
|
+
- [ ] Rate limiting works as expected
|
|
640
|
+
|
|
641
|
+
## Example Integration Code
|
|
642
|
+
|
|
643
|
+
The client code has been updated in:
|
|
644
|
+
- `/src/services/upload/ApiUploadService.js` - API methods for detection and propagation
|
|
645
|
+
- `/src/services/DatabaseService.js` - Detection and propagation logic using API
|
|
646
|
+
|
|
647
|
+
See the implementation for reference on how to integrate these endpoints.
|