added new backend

This commit is contained in:
Sridhar260802 2025-05-17 00:11:16 +05:30
commit f6ff68a8be
15 changed files with 1979 additions and 0 deletions

5
.env Normal file
View File

@ -0,0 +1,5 @@
DB_HOST="122.166.69.162"
DB_USER="rootuser"
DB_PASSWORD="1234"
DB_NAME="vvvet"
PORT="5002"

7
.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
node_modules/
__pycache__/
*.pyc
*.pyo
*.pyd
venv/
*.egg-info/

1
README.md Normal file
View File

@ -0,0 +1 @@
# vvet_backend

369
app.js Normal file
View File

@ -0,0 +1,369 @@
// const express = require("express");
// const multer = require("multer");
// const axios = require("axios");
// const cors = require("cors");
// const mysql = require("mysql2/promise");
// const FormData = require("form-data");
// const app = express();
// const PORT = 5002;
// app.use(express.json());
// app.use(cors());
// // Use multer memory storage for file uploads
// const upload = multer({ storage: multer.memoryStorage() });
// // MySQL connection config — keys must be lowercase for mysql2
// const dbConfig = {
// host: "122.166.69.162",
// user: "rootuser",
// password: "1234",
// database: "vvvet",
// port: 5002, // default MySQL port; change if needed
// };
// let db;
// (async () => {
// try {
// db = await mysql.createPool(dbConfig);
// console.log("Connected to MySQL DB");
// } catch (err) {
// console.error("MySQL connection error:", err);
// }
// })();
// // PAN verification API
// app.post("/api/verify-pan", upload.single("panImage"), async (req, res) => {
// try {
// const { pan } = req.body;
// const panImage = req.file;
// if (!pan || !panImage) {
// return res.status(400).json({ verified: false, message: "PAN and image are required" });
// }
// // Validate PAN format
// const panFormatRegex = /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/;
// if (!panFormatRegex.test(pan)) {
// return res.status(200).json({ verified: false, message: "Invalid PAN format" });
// }
// // Prepare form data to send image buffer to Python OCR server
// const formData = new FormData();
// formData.append("image", panImage.buffer, panImage.originalname);
// // Send POST request to Python OCR server
// const ocrResponse = await axios.post(
// "http://localhost:6001/extract-text",
// formData,
// {
// headers: formData.getHeaders(),
// }
// );
// const extractedText = ocrResponse.data.text || "";
// console.log("Extracted Text from OCR:", extractedText);
// if (!extractedText.toUpperCase().includes(pan.toUpperCase())) {
// return res.status(200).json({ verified: false, message: "PAN not found in image" });
// }
// return res.status(200).json({ verified: true, message: "PAN verified successfully" });
// } catch (error) {
// console.error("Error in /api/verify-pan:", error);
// return res.status(500).json({ verified: false, message: "Internal server error" });
// }
// });
// // Fundraising submission API (example)
// app.post("/api/fundraising/submit", upload.fields([
// { name: "feeDoc", maxCount: 1 },
// { name: "medicalPhoto", maxCount: 1 },
// { name: "medicalDoc", maxCount: 1 },
// { name: "document", maxCount: 1 },
// ]), async (req, res) => {
// try {
// const formData = req.body;
// const files = req.files;
// console.log("Received form data:", formData);
// console.log("Received files:", files ? Object.keys(files) : "No files uploaded");
// if (!db) {
// return res.status(500).json({ message: "DB connection not available" });
// }
// const sql = `INSERT INTO fundraising
// (name, email, phone, category, feeDoc_name, medicalPhoto_name, medicalDoc_name, document_name)
// VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
// const values = [
// formData.name || null,
// formData.email || null,
// formData.phone || null,
// formData.category || null,
// files?.feeDoc?.[0]?.originalname || null,
// files?.medicalPhoto?.[0]?.originalname || null,
// files?.medicalDoc?.[0]?.originalname || null,
// files?.document?.[0]?.originalname || null,
// ];
// await db.query(sql, values);
// return res.status(200).json({ message: "Fundraising form submitted successfully" });
// } catch (error) {
// console.error("Error in /api/fundraising/submit:", error);
// return res.status(500).json({ message: "Internal server error" });
// }
// });
// // Start the server
// app.listen(PORT, () => {
// console.log(`Server running on http://localhost:${PORT}`);
// });
const express = require("express");
const multer = require("multer");
const axios = require("axios");
const cors = require("cors");
const mysql = require("mysql2/promise");
const FormData = require("form-data");
const extractDocumentRoute = require("./routes/extractDocument");
const app = express();
const PORT = 5002;
app.use(express.json());
app.use(cors());
app.use("/api", extractDocumentRoute);
// Use multer memory storage for file uploads
const upload = multer({ storage: multer.memoryStorage() });
// MySQL connection config — keys must be lowercase for mysql2
const dbConfig = {
host: "122.166.69.162",
user: "rootuser",
password: "1234",
database: "vvvet",
port: 3306, // Default MySQL port; change if needed
};
let db;
(async () => {
try {
db = await mysql.createPool(dbConfig);
console.log("Connected to MySQL DB");
} catch (err) {
console.error("MySQL connection error:", err);
}
})();
// PAN verification API
app.post("/api/verify-pan", upload.single("panImage"), async (req, res) => {
try {
const { pan } = req.body;
const panImage = req.file;
if (!pan || !panImage) {
return res.status(400).json({ verified: false, message: "PAN and image are required" });
}
// Validate PAN format
const panFormatRegex = /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/;
if (!panFormatRegex.test(pan)) {
return res.status(200).json({ verified: false, message: "Invalid PAN format" });
}
// Prepare form data to send image buffer to Python OCR server
const formData = new FormData();
formData.append("image", panImage.buffer, panImage.originalname);
// Send POST request to Python OCR server
const ocrResponse = await axios.post(
"http://localhost:6001/extract-text",
formData,
{
headers: formData.getHeaders(),
}
);
const extractedText = ocrResponse.data.text || "";
console.log("Extracted Text from OCR:", extractedText);
if (!extractedText.toUpperCase().includes(pan.toUpperCase())) {
return res.status(200).json({ verified: false, message: "PAN not found in image" });
}
return res.status(200).json({ verified: true, message: "PAN verified successfully" });
} catch (error) {
console.error("Error in /api/verify-pan:", error);
return res.status(500).json({ verified: false, message: "Internal server error" });
}
});
// Fundraising submission API
// app.post(
// "/api/fundraising/submit",
// upload.fields([
// { name: "feeDoc", maxCount: 1 },
// { name: "medicalPhoto", maxCount: 1 },
// { name: "medicalDoc", maxCount: 1 },
// { name: "document", maxCount: 1 },
// { name: "panImage", maxCount: 1 },
// ]),
// async (req, res) => {
// try {
// const formData = req.body;
// const files = req.files;
// console.log("Received form data:", formData);
// console.log("Received files:", files ? Object.keys(files) : "No files uploaded");
// if (!db) {
// return res.status(500).json({ message: "DB connection not available" });
// }
// const sql = `INSERT INTO fundraisings
// (name, email, phone, category, feeDoc_name, medicalPhoto_name, medicalDoc_name, document_name)
// VALUES (?, ?, ?, ?, ?, ?, ?, ?)`;
// const values = [
// formData.name || null,
// formData.email || null,
// formData.phone || null,
// formData.category || null,
// files?.fee_Doc?.[0]?.originalname || null,
// files?.medical_Photo?.[0]?.originalname || null,
// files?.medical_Doc?.[0]?.originalname || null,
// files?.document?.[0]?.originalname || null,
// files?.panImage?.[0]?.originalname || null,
// ];
// await db.query(sql, values);
// return res.status(200).json({ message: "Fundraising form submitted successfully" });
// } catch (error) {
// console.error("Error in /api/fundraising/submit:", error);
// return res.status(500).json({ message: "Internal server error" });
// }
// }
// );
app.post(
"/api/fundraising/submit",
upload.fields([
{ name: "feeDoc", maxCount: 1 },
{ name: "medicalPhoto", maxCount: 1 },
{ name: "medicalDoc", maxCount: 1 },
{ name: "document", maxCount: 1 },
{ name: "panImage", maxCount: 1 },
]),
async (req, res) => {
try {
const formData = req.body;
const files = req.files;
console.log("Received form data:", formData);
console.log("Received files:", files ? Object.keys(files) : "No files uploaded");
if (!db) {
return res.status(500).json({ message: "DB connection not available" });
}
const sql = `INSERT INTO fundraisings (
name, email, phone, age, dob, category, pan_number, pan_document,
fee_document,
medical_document,
other_document,
transaction_screenshot,
fundraising_amount, bank_account_holder_name, bank_name, bank_account_number, ifsc_code
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ? )`;
const values = [
formData.name || null,
formData.email || null,
formData.phone || null,
formData.age || null,
formData.dob || null,
formData.category || null,
formData.pan || null,
files?.panImage?.[0]?.originalname || null,
files?.feeDoc?.[0]?.originalname || null,
files?.medicalDoc?.[0]?.originalname || null,
files?.document?.[0]?.originalname || null,
files?.transactionScreenshot?.[0]?.originalname || null,
formData.fundAmount || null,
formData.bankHolderName || null,
formData.bankName || null,
formData.accountNumber || null,
formData.ifscCode || null
];
await db.query(sql, values);
return res.status(200).json({ message: "Fundraising form submitted successfully" });
} catch (error) {
console.error("Error in /api/fundraising/submit:", error);
return res.status(500).json({ message: "Internal server error" });
}
}
);
//donor submission API
// Donor submission API
app.post(
"/api/donor/submit",
upload.fields([
{ name: "panImage", maxCount: 1 },
{ name: "transactionScreenshot", maxCount: 1 },
]),
async (req, res) => {
try {
const formData = req.body;
const files = req.files;
if (!db) {
return res.status(500).json({ message: "DB connection not available" });
}
const sql = `INSERT INTO donors (
name, email, phone, age, dob, pan_number, pan_document,
bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
donation_amount, payment, transaction_screenshot
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
const values = [
formData.name || null,
formData.email || null,
formData.phone || null,
formData.age || null,
formData.dob || null,
formData.pan || null,
files?.panImage?.[0]?.originalname || null,
formData.bankHolderName || null,
formData.bankName || null,
formData.accountNumber || null,
formData.ifscCode || null,
formData.donation_Amount || null,
formData.payment|| null,
files?.transactionScreenshot?.[0]?.originalname || null,
];
await db.query(sql, values);
return res.status(200).json({ message: "Donor form submitted successfully" });
} catch (error) {
console.error("Error in /api/donor/submit:", error);
return res.status(500).json({ message: "Internal server error" });
}
}
);
// Start the server
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});

View File

@ -0,0 +1,25 @@
const Tesseract = require('tesseract.js');
const path = require('path');
exports.extractPanText = async (req, res) => {
try {
if (!req.files || !req.files.pan_document) {
return res.status(400).json({ error: 'PAN document is required' });
}
const panDocPath = req.files.pan_document[0].path;
const result = await Tesseract.recognize(
panDocPath,
'eng',
{ logger: m => console.log(m) }
);
const extractedText = result.data.text;
// TODO: You can add regex here to specifically extract PAN number if needed
res.json({ extractedText });
} catch (err) {
console.error('PAN Extraction Error:', err);
res.status(500).json({ error: 'Failed to extract PAN text' });
}
};

View File

@ -0,0 +1,105 @@
const { donorPool, fundraisingPool } = require('../db');
// Helper: get filename from uploaded file or null
const getFileName = (files, field) => files && files[field] && files[field][0] ? files[field][0].filename : null;
// Donor submission
exports.submitDonor = (req, res) => {
const files = req.files || {};
const {
name, email, age, dob, phone, pan_number,
bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
donation_amount, payment
} = req.body;
if (!name || !donation_amount || !payment) {
return res.status(400).json({ error: 'Missing required fields' });
}
const pan_document = getFileName(files, 'pan_document');
const transaction_screenshot = getFileName(files, 'transaction_screenshot');
const sql = `
INSERT INTO donors (
name, email, age, dob, phone, pan_number, pan_document,
bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
donation_amount, payment, transaction_screenshot
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
const values = [
name, email || null, age || null, dob || null, phone || null, pan_number || null, pan_document,
bank_account_holder_name || null, bank_name || null, bank_account_number || null, ifsc_code || null,
donation_amount, payment, transaction_screenshot
];
donorPool.query(sql, values, (err, results) => {
if (err) {
console.error('Donor Insert Error:', err);
return res.status(500).json({ error: 'Failed to insert donor data' });
}
res.json({ message: 'Donor data submitted', id: results.insertId });
});
};
// Fundraising submission
exports.submitFundraisings = (req, res) => {
const files = req.files || {};
const {
name, email, age, dob, phone, pan_number,
category, patient_name, cause, hospital_name, medical_location, attender_name, medical_phone,
medical_amount, student_name, standard, parent_name, parent_phone, education_amount,
disaster_name, disaster_place, disaster_phone, disaster_amount,
general_name, general_place, general_phone, general_amount,
other_reason, bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
fundraising_amount, payment_method
} = req.body;
if (!name || !category || !fundraising_amount) {
return res.status(400).json({ error: 'Missing required fields' });
}
// Files
const pan_document = getFileName(files, 'pan_document');
const fee_document = getFileName(files, 'fee_document');
const medical_certificate = getFileName(files, 'medical_certificate');
const medical_document = getFileName(files, 'medical_document');
const disaster_document = getFileName(files, 'disaster_document');
const general_document = getFileName(files, 'general_document');
const other_document = getFileName(files, 'other_document');
const transaction_screenshot = getFileName(files, 'transaction_screenshot');
const sql = `
INSERT INTO fundraisings (
name, email, age, dob, phone, pan_number, pan_document,
category, patient_name, cause, hospital_name, medical_location, attender_name, medical_phone,
medical_amount, medical_certificate, medical_document,
student_name, standard, parent_name, parent_phone, education_amount, fee_document,
disaster_name, disaster_place, disaster_phone, disaster_amount, disaster_document,
general_name, general_place, general_phone, general_amount, general_document,
other_reason, other_document,
bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
fundraising_amount, transaction_screenshot
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
const values = [
name, email || null, age || null, dob || null, phone || null, pan_number || null, pan_document,
category, patient_name || null, cause || null, hospital_name || null, medical_location || null, attender_name || null, medical_phone || null,
medical_amount || null, medical_certificate, medical_document,
student_name || null, standard || null, parent_name || null, parent_phone || null, education_amount || null, fee_document,
disaster_name || null, disaster_place || null, disaster_phone || null, disaster_amount || null, disaster_document,
general_name || null, general_place || null, general_phone || null, general_amount || null, general_document,
other_reason || null, other_document,
bank_account_holder_name || null, bank_name || null, bank_account_number || null, ifsc_code || null,
fundraising_amount, transaction_screenshot
];
fundraisingPool.query(sql, values, (err, results) => {
if (err) {
console.error('Fundraising Insert Error:', err);
return res.status(500).json({ error: 'Failed to insert fundraising data' });
}
res.json({ message: 'Fundraising data submitted', id: results.insertId });
});
};

25
db.js Normal file
View File

@ -0,0 +1,25 @@
const mysql = require('mysql2');
const dotenv = require('dotenv');
dotenv.config();
const donorPool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_DONORS,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
const fundraisingPool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME_FUNDRAISING,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
module.exports = { donorPool, fundraisingPool };

0
models/vvetModel.js Normal file
View File

View File

@ -0,0 +1,24 @@
from flask import Flask, request, jsonify
import pytesseract
from PIL import Image
import io
app = Flask(__name__)
@app.route('/extract-text', methods=['POST'])
def extract_text():
if 'image' not in request.files:
return jsonify({'error': 'No image file provided'}), 400
file = request.files['document']
file = request.files['image']
text = extract_text_from_image(file)
image = Image.open(io.BytesIO(file.read()))
# Replace with your Doctor OCR model if needed
text = pytesseract.image_to_string(image)
return jsonify({'text': text})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=6001)

1278
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
package.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "vvvet-backend",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^1.9.0",
"cors": "^2.8.5",
"express": "^5.1.0",
"form-data": "^4.0.2",
"multer": "^1.4.5-lts.2",
"mysql2": "^3.14.1",
"tesseract.js": "^6.0.1"
}
}

55
routes/donorRoutes.js Normal file
View File

@ -0,0 +1,55 @@
const express = require("express");
const router = express.Router();
const multer = require("multer");
const upload = multer({ dest: "uploads/" }); // or your existing multer config
const { donorPool } = require("../db");
// Helper: get filename from uploaded files
const getFileName = (files, field) => files && files[field] && files[field][0] ? files[field][0].filename : null;
// Donor submission controller function
const submitDonor = (req, res) => {
const files = req.files || {};
const {
name, email, age, dob, phone, pan_number,
bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
donation_amount, payment_method
} = req.body;
if (!name || !donation_amount || !payment) {
return res.status(400).json({ error: 'Missing required fields' });
} else {
const pan_document = getFileName(files, 'pan_document');
const transaction_screenshot = getFileName(files, 'transaction_screenshot');
const sql = `
INSERT INTO donors (
name, email, age, dob, phone, pan_number, pan_document,
bank_account_holder_name, bank_name, bank_account_number, ifsc_code,
donation_amount, payment, transaction_screenshot
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
const values = [
name, email || null, age || null, dob || null, phone || null, pan_number || null, pan_document,
bank_account_holder_name || null, bank_name || null, bank_account_number || null, ifsc_code || null,
donation_amount, payment, transaction_screenshot
];
donorPool.query(sql, values, (err, results) => {
if (err) {
console.error('Donor Insert Error:', err);
return res.status(500).json({ error: 'Failed to insert donor data' });
}
res.json({ message: 'Donor data submitted', id: results.insertId });
});
}
};
// Route definition
router.post("/donor/submit", upload.fields([
{ name: "pan_document", maxCount: 1 },
{ name: "transaction_screenshot", maxCount: 1 }
]), submitDonor);
module.exports = router;

45
routes/extractDocument.js Normal file
View File

@ -0,0 +1,45 @@
const express = require("express");
const router = express.Router();
const multer = require("multer");
const fs = require("fs");
const FormData = require("form-data");
const axios = require("axios");
const db = require("../db"); // MySQL connection
const upload = multer({ dest: "uploads/" });
router.post("/extract-document", upload.single("document"), async (req, res) => {
const { user_id, document_type } = req.body;
const file = req.file;
if (!file || !document_type || !user_id) {
return res.status(400).json({ message: "Missing required fields." });
}
try {
const formData = new FormData();
formData.append("document", fs.createReadStream(file.path));
const response = await axios.post("http://localhost:6001/extract-text", formData, {
headers: formData.getHeaders(),
});
const extractedText = response.data.text || "";
// Store in MySQL
await db.execute(
"INSERT INTO extracted_documents (user_id, document_type, original_filename, extracted_text) VALUES (?, ?, ?, ?)",
[user_id, document_type, file.originalname, extractedText]
);
// Cleanup uploaded file
fs.unlinkSync(file.path);
res.json({ message: "Text extracted and stored successfully.", extractedText });
} catch (err) {
console.error(err);
res.status(500).json({ message: "Document extraction failed." });
}
});
module.exports = router;

8
routes/panRoutes.js Normal file
View File

@ -0,0 +1,8 @@
const express = require('express');
const router = express.Router();
const panController = require('../controllers/panController');
// POST /api/pan/extract - extract PAN text from uploaded image
router.post('/extract', panController.extractPanText);
module.exports = router;

11
routes/vvetRoutes.js Normal file
View File

@ -0,0 +1,11 @@
const express = require('express');
const router = express.Router();
const vvetController = require('../controllers/vvetController');
// POST /api/vvet/donor - submit donor data
router.post('/donor', vvetController.submitDonor);
// POST /api/vvet/fundraising - submit fundraising data
router.post('/fundraising', vvetController.submitFundraising);
module.exports = router;