Logos & scanner changes
Run Tests on Branches / Backend Tests (push) Successful in 3m41s
Run Tests on Branches / Frontend Tests (push) Successful in 3m27s

This commit is contained in:
Antoni Nuñez Romeu
2026-07-04 14:46:42 +02:00
parent 3b725df118
commit df0b114058
15 changed files with 414 additions and 19 deletions
+53
View File
@@ -16,6 +16,8 @@ import rateLimit from 'express-rate-limit';
import webpush from 'web-push';
import pino from 'pino';
import pinoHttp from 'pino-http';
import multer from 'multer';
import { createWorker } from 'tesseract.js';
import { searchMedicines, getMedicineDetails } from './cima-service.js';
import { runFarmaciaWebhookImport, DEFAULT_FARMACIAS_WEBHOOK, importPharmaciesFromRows } from './farmacias-webhook-import.js';
import { fetchPharmaciesExternal } from '../API/index.js';
@@ -515,6 +517,57 @@ app.get('/api/tsi/:cip/prescriptions', async (req, res) => {
}
});
// ========== TSI OCR: extract CIP from uploaded photo ==========
const upload = multer({
storage: multer.memoryStorage(),
limits: { fileSize: 10 * 1024 * 1024 }, // 10 MB max
fileFilter: (_req, file, cb) => {
if (file.mimetype.startsWith('image/')) cb(null, true);
else cb(new Error('Only image files are accepted'));
},
});
// Extract CIP from OCR text — looks for a long alphanumeric token (16 chars typical for CIP)
function extractCip(text) {
const cleaned = text.replace(/\s+/g, '');
// Try exact 16-char alphanumeric match first
const exact = cleaned.match(/[A-Z0-9]{16}/i);
if (exact) return exact[0].toUpperCase();
// Fallback: 830 alphanumeric chars
const loose = cleaned.match(/[A-Z0-9]{8,30}/i);
if (loose) return loose[0].toUpperCase();
return null;
}
app.post('/api/tsi/ocr', upload.single('photo'), async (req, res) => {
try {
if (!req.file) {
return res.status(400).json({ error: 'No image file provided' });
}
const worker = await createWorker('spa+eng');
const { data } = await worker.recognize(req.file.buffer);
await worker.terminate();
console.log('[OCR] Raw text:', data.text);
const cip = extractCip(data.text);
console.log('[OCR] Extracted CIP:', cip);
if (!cip) {
return res.status(422).json({
error: 'No se pudo detectar un código CIP en la imagen',
ocrText: data.text.trim().slice(0, 500),
});
}
res.json({ cip });
} catch (error) {
console.error('TSI OCR error:', error);
res.status(500).json({ error: 'Error procesando la imagen' });
}
});
// ========== AUTHENTICATION ROUTES ==========
// Login endpoint