This commit is contained in:
JunBarroga 2024-10-22 11:32:48 +08:00
parent 57ba9ee775
commit 0d6bd655de
3 changed files with 458 additions and 78 deletions

515
index.js
View File

@ -2,6 +2,8 @@ import express from "express";
import bodyParser from "body-parser"; import bodyParser from "body-parser";
import mongoose from "mongoose"; import mongoose from "mongoose";
import cors from "cors"; import cors from "cors";
import atob from "atob";
import dotenv from "dotenv"; import dotenv from "dotenv";
import multer from "multer"; import multer from "multer";
import helmet from "helmet"; import helmet from "helmet";
@ -120,10 +122,10 @@ function sendEmail(req, res, next) {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
Authorization: `Basic ${apiKey}`, Authorization: `Basic ${apiKey}`,
}, },
}; };
axios axios
.post(apiUrl, requestData, config) .post(apiUrl, requestData, config)
.then((response) => { .then((response) => {
// const status = response.data.Messages[0].Status; // const status = response.data.Messages[0].Status;
@ -143,20 +145,41 @@ function sendEmail(req, res, next) {
} }
app.post("/api/send-email/", sendEmail); app.post("/api/send-email/", sendEmail);
const odooClient = new Odoo({ // const odooClient = new Odoo({
url: "https://gis.pivi.com.ph", // url: "http://192.168.50.15:8070",
db: "gis.pivi.com.ph", // db: "gis.pivi.com.ph",
username: "egalang@obanana.com", // username: "egalang@obanana.com",
// password: "P@$$w0rd!",
// });
const odooClient2 = new Odoo({
url: "http://192.168.50.15:8071",
db: "pos.obanana.com",
username: "mahipe@obanana.com",
password: "P@$$w0rd!", password: "P@$$w0rd!",
}); });
const odooClient2 = new Odoo({ app.get("/get-assets", async (req, res) => {
url: "http://localhost:8069/",
db: "Paymongo",
username: "mahipe@obanana.com",
password: "abcd123",
});
app.get("/get-assets", async (req, res) => {
try { try {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
return res.status(400).json({ error: 'Authorization header is missing or invalid.' });
}
const base64Credentials = authHeader.split(' ')[1];
const decodedCredentials = atob(base64Credentials);
const [email, password] = decodedCredentials.split(':');
if (!email || !password) {
return res.status(400).json({ error: 'Invalid credentials format.' });
}
// console.log(email,password)
const odooClient = new Odoo({
url: "http://192.168.50.15:8070",
db: "gis.pivi.com.ph",
username: email,
password: password
});
odooClient.connect(async function (err) { odooClient.connect(async function (err) {
if (err) { if (err) {
console.log(err); console.log(err);
@ -166,7 +189,7 @@ app.get("/get-assets", async (req, res) => {
} }
console.log("Connected to Odoo server."); console.log("Connected to Odoo server.");
// Fetch asset IDs // Fetch asset IDs
const inParams = []; const inParams = [];
inParams.push([["name", "!=", false]]); inParams.push([["name", "!=", false]]);
inParams.push(parseInt(req.query.offset) || 0); //offset inParams.push(parseInt(req.query.offset) || 0); //offset
@ -346,53 +369,117 @@ app.get("/get-assets", async (req, res) => {
}); });
} else { } else {
images = image; images = image;
const inParams = [];
const asset = recordsArray.map( inParams.push([["related_asset", "!=", false]]);
(item) => { inParams.push(parseInt(req.query.offset) || 0); //offset
// Find matching attributes based on the numeric part of attr.assets inParams.push(parseInt(req.query.limit) || 0); //Limit
const matchedAttr = const params1 = [inParams];
attributes.filter( odooClient.execute_kw(
(attribute) => "pivi_assets.related",
item.attributes.some( "search",
(attrId) => params1,
attrId === async function (err, ids) {
attribute.id if (err) {
) // Compare to the first element of attr.assets console.log(err);
); return res.status(500).json({
error:
// Find matching bounds based on the numeric part of bounds.assets "Search Error: " + err.message,
const matchedBounds = });
bounds.filter( }
(bound) =>
item.bounds.some( if (ids.length === 0) {
(boundId) => return res.json([]); // No assets found
boundId === bound.id }
) // Compare to the first element of bounds.assets
); // Fetch asset records
const inParamsRead = [];
// Find matching images based on data.id == images.res_id inParamsRead.push(ids); // IDs
const matchedImages = inParamsRead.push([
images.filter( "id",
(image) => "related_asset",
image.res_id === item.id "asset",
); ]);
const paramsRead = [inParamsRead];
// Construct the asset object for this item
return { odooClient.execute_kw(
attr: matchedAttr, "pivi_assets.related",
bounds: matchedBounds, "read",
data: item, paramsRead,
images: matchedImages, async function (err2, related) {
}; if (err2) {
console.log(err2);
return res.status(500).json({
error:
"Read Error: " + err2.message,
});
} else {
let relateds
relateds = related;
const asset = recordsArray.map(
(item) => {
// Find matching attributes based on the numeric part of attr.assets
const matchedAttr =
attributes.filter(
(attribute) =>
item.attributes.some(
(attrId) =>
attrId ===
attribute.id
) // Compare to the first element of attr.assets
);
// Find matching bounds based on the numeric part of bounds.assets
const matchedBounds =
bounds.filter(
(bound) =>
item.bounds.some(
(boundId) =>
boundId === bound.id
) // Compare to the first element of bounds.assets
);
// Find matching bounds based on the numeric part of bounds.assets
const matchedRelated =
relateds.filter(
(related) =>
item.related.some(
(relatedId) =>
relatedId === related.id
)
);
// Find matching images based on data.id == images.res_id
const matchedImages =
images.filter(
(image) =>
image.res_id === item.id
);
// Construct the asset object for this item
return {
attr: matchedAttr,
bounds: matchedBounds,
data: item,
images: matchedImages,
related: matchedRelated
};
}
);
// res.json({
// data: recordsArray,
// attr: attributes,
// bounds: bounds,
// images: images,
// });
res.json(asset);
}
let pendingRequests =
records.length;
}
);
} }
); );
// res.json({
// data: recordsArray,
// attr: attributes,
// bounds: bounds,
// images: images,
// });
res.json(asset);
} }
let pendingRequests = let pendingRequests =
@ -719,10 +806,9 @@ app.get("/get-stages", async (req, res) => {
res.status(500).json({ error: "Data Fetch Error: " + error.message }); res.status(500).json({ error: "Data Fetch Error: " + error.message });
} }
}); });
app.post('/update-order-state', async (req, res) => { app.post('/update-order-state', async (req, res) => {
const { id, state } = req.body; // Order ID and new state passed in the request body const { id, state } = req.body;
if (!id || !state) { if (!id || !state) {
return res.status(400).json({ error: 'Order ID and state are required.' }); return res.status(400).json({ error: 'Order ID and state are required.' });
} }
@ -735,9 +821,8 @@ app.post('/update-order-state', async (req, res) => {
} }
console.log('Connected to Odoo server.'); console.log('Connected to Odoo server.');
// Search for the order by ID
const inParams = []; const inParams = [];
inParams.push([['id', '=', id]]); // Find the order by its ID inParams.push([['id', '=', id]]);
const params = [inParams]; const params = [inParams];
odooClient2.execute_kw('pos.order', 'search', params, function (err, orderIds) { odooClient2.execute_kw('pos.order', 'search', params, function (err, orderIds) {
@ -750,10 +835,9 @@ app.post('/update-order-state', async (req, res) => {
return res.status(404).json({ error: 'Order not found.' }); return res.status(404).json({ error: 'Order not found.' });
} }
// Update the state of the order
const inParamsUpdate = []; const inParamsUpdate = [];
inParamsUpdate.push(orderIds); // Order IDs to update inParamsUpdate.push(orderIds);
inParamsUpdate.push({ state: state }); // Fields to update inParamsUpdate.push({ state: state });
const paramsUpdate = [inParamsUpdate]; const paramsUpdate = [inParamsUpdate];
odooClient2.execute_kw('pos.order', 'write', paramsUpdate, function (err2, result) { odooClient2.execute_kw('pos.order', 'write', paramsUpdate, function (err2, result) {
@ -775,16 +859,293 @@ app.post('/update-order-state', async (req, res) => {
return res.status(500).json({ error: 'Update Error: ' + error.message }); return res.status(500).json({ error: 'Update Error: ' + error.message });
} }
}); });
app.get("/get-tables", async (req, res) => {
try {
odooClient2.connect(async function (err) {
if (err) {
console.log(err);
return res
.status(500)
.json({ error: "Connection Error: " + err.message });
}
console.log("Connected to Odoo server.");
// Fetch asset IDs
const inParams = [];
inParams.push([["name", "!=", false]]);
inParams.push(parseInt(req.query.offset) || 0);
inParams.push(parseInt(req.query.limit) || 0);
const params = [inParams];
const assets = [];
let recordsArray = [];
function fetchOdooData(model, method, params) { let attributes = [];
return new Promise((resolve, reject) => { let bounds = [];
odooClient.execute_kw(model, method, params, (err, data) => { let images = [];
if (err) return reject(err);
resolve(data); odooClient2.execute_kw(
"restaurant.table",
"search",
params,
async function (err, ids) {
if (err) {
console.log(err);
return res
.status(500)
.json({ error: "Search Error: " + err.message });
}
if (ids.length === 0) {
return res.json([]); // No assets found
}
// Fetch asset records
const inParamsRead = [];
inParamsRead.push(ids); // IDs
// inParamsRead.push([
// "id",
// "name",
// ]);
const paramsRead = [inParamsRead];
odooClient2.execute_kw(
"restaurant.table",
"read",
paramsRead,
async function (err2, records) {
if (err2) {
console.log(err2);
return res
.status(500)
.json({ error: "Read Error: " + err2.message });
} else {
recordsArray = records;
res.json(recordsArray);
}
let pendingRequests = records.length;
}
);
}
);
}); });
}); } catch (error) {
} console.error("Error:", error);
res.status(500).json({ error: "Data Fetch Error: " + error.message });
}
});
app.post('/create-asset-bounds', async (req, res) => {
try {
const postData = req.body;
if (!postData || postData.length === 0) {
return res.status(200).json({ error: 'No data provided.' });
}
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
return res.status(400).json({ error: 'Authorization header is missing or invalid.' });
}
const base64Credentials = authHeader.split(' ')[1];
const decodedCredentials = Buffer.from(base64Credentials, 'base64').toString('ascii'); // safer than `atob`
const [email, password] = decodedCredentials.split(':');
if (!email || !password) {
return res.status(400).json({ error: 'Invalid credentials format.' });
}
const odooClient = new Odoo({
url: "http://192.168.50.15:8070",
db: "gis.pivi.com.ph",
username: email,
password: password
});
odooClient.connect(async function (err) {
if (err) {
console.log(err);
return res.status(500).json({ error: 'Connection Error: ' + err.message });
}
console.log('Connected to Odoo server.');
// Use Promise.all to wait for all async operations to finish
try {
const createdIds = await Promise.all(
postData.map(async (data, index) => {
const { asset, name, longitude, latitude } = data;
if (!asset || !name || !longitude || !latitude) {
throw new Error(`Missing required fields in entry ${index + 1}`);
}
const params = [
{
asset: asset,
name: name,
longitude: longitude,
latitude: latitude,
}
];
// Return a promise for each create operation
return new Promise((resolve, reject) => {
odooClient.execute_kw('pivi_assets.bounds', 'create', [params], function (err2, id) {
if (err2) {
console.log('Create Error:', err2);
return reject(new Error('Create Error: ' + err2.message));
}
resolve(id);
});
});
})
);
return res.json({ success: true, createdIds });
} catch (error) {
return res.status(500).json({ error: error.message });
}
});
} catch (error) {
console.error('Error:', error);
return res.status(500).json({ error: 'Server Error: ' + error.message });
}
});
app.post('/odoo-webhook', (req, res) => {
const newOrder = req.body;
console.log('New POS order received:', newOrder);
// Process the order data as needed
// For example, send it to a WebSocket, log it, or store it in a database
res.status(200).send('Webhook received');
});
app.delete('/delete-asset-bounds', async (req, res) => {
try {
const assetId = req.query.asset;
console.log(assetId)
if (!assetId) {
return res.status(400).json({ error: 'Asset ID is required.' });
}
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Basic ')) {
return res.status(400).json({ error: 'Authorization header is missing or invalid.' });
}
const base64Credentials = authHeader.split(' ')[1];
const decodedCredentials = atob(base64Credentials);
const [email, password] = decodedCredentials.split(':');
if (!email || !password) {
return res.status(400).json({ error: 'Invalid credentials format.' });
}
// console.log(email,password)
const odooClient = new Odoo({
url: "http://192.168.50.15:8070",
db: "gis.pivi.com.ph",
username: email,
password: password
});
odooClient.connect(function (err) {
if (err) {
console.log(err);
return res.status(500).json({ error: 'Connection Error: ' + err.message });
}
console.log('Connected to Odoo server.');
const inParams = [];
inParams.push([['id', '=', assetId]]);
const searchParamsAsset = [inParams];
// const searchParamsAsset = [
// [['id', '=', assetId]]
// ];
odooClient.execute_kw('pivi_assets.pivi_assets', 'search', searchParamsAsset, function (err2, assetIds) {
if (err2) {
console.log(assetIds+" id")
console.log('Search Error:', err2);
return res.status(500).json({ error: 'Search Asset Error: ' + err2.message });
}
if (assetIds.length === 0) {
return res.status(404).json({ error: 'Asset not found.' });
}
odooClient.execute_kw('pivi_assets.pivi_assets', 'read', [assetIds], function (err3, assets) {
if (err3) {
console.log('Read Error:', err3);
return res.status(500).json({ error: 'Read Error: ' + err3.message });
}
const assetName = assets[0].name;
// const searchParamsBounds = [
// [['asset', '=', assetName]]
// ];
const inParams = [];
inParams.push([['asset', '=', assetName]]);
const searchParamsBounds = [inParams];
odooClient.execute_kw('pivi_assets.bounds', 'search', searchParamsBounds, function (err4, boundIds) {
if (err4) {
console.log('Search Bounds Error:', err4);
return res.status(500).json({ error: 'Search Bounds Error: ' + err4.message });
}
if (boundIds.length === 0) {
return res.status(200).json({ error: 'No bounds found for this asset.' });
}
odooClient.execute_kw('pivi_assets.bounds', 'read', [[boundIds]], function (err5, bounds) {
if (err5) {
console.log('Read Bounds Error:', err5);
return res.status(500).json({ error: 'Read Bounds Error: ' + err5.message });
}
const deletedIds = [];
bounds.forEach((bound, index) => {
const boundId = bound.id;
odooClient.execute_kw('pivi_assets.bounds', 'unlink', [[boundId]], function (err6) {
if (err6) {
console.log('Unlink Error:', err6);
return res.status(500).json({ error: 'Unlink Error: ' + err6.message });
}
deletedIds.push(boundId);
if (deletedIds.length === bounds.length) {
return res.json({ success: true, deletedIds });
}
});
});
});
});
});
});
});
} catch (error) {
console.error('Error:', error);
return res.status(500).json({ error: 'Server Error: ' + error.message });
}
});
// function fetchOdooData(model, method, params) {
// return new Promise((resolve, reject) => {
// odooClient.execute_kw(model, method, params, (err, data) => {
// if (err) return reject(err);
// resolve(data);
// });
// });
// }
/* MONGOOSE SETUP */ /* MONGOOSE SETUP */
const PORT = process.env.PORT || 3002; const PORT = process.env.PORT || 3002;
@ -801,7 +1162,7 @@ const PORT = process.env.PORT || 3002;
// .catch((error) => console.log(`${error} did not connect`)); // .catch((error) => console.log(`${error} did not connect`));
mongoose mongoose
.connect(process.env.MONGO_URL) .connect(process.env.DATABASE_URL)
.then(() => { .then(() => {
app.listen(PORT, () => console.log(`Server Port: ${PORT}`)); app.listen(PORT, () => console.log(`Server Port: ${PORT}`));

18
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"atob": "^2.1.2",
"axios": "^1.7.4", "axios": "^1.7.4",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
@ -184,6 +185,18 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
}, },
"node_modules/atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"license": "(MIT OR Apache-2.0)",
"bin": {
"atob": "bin/atob.js"
},
"engines": {
"node": ">= 4.5.0"
}
},
"node_modules/axios": { "node_modules/axios": {
"version": "1.7.4", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
@ -2437,6 +2450,11 @@
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
}, },
"atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
},
"axios": { "axios": {
"version": "1.7.4", "version": "1.7.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",

View File

@ -6,11 +6,12 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon index.js" "start": "nodemon index.js"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"atob": "^2.1.2",
"axios": "^1.7.4", "axios": "^1.7.4",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",