Add product and storage management routes and database functions

This commit is contained in:
2026-05-26 13:57:37 +02:00
parent 4c0c441e92
commit b3c3be5590
8 changed files with 233 additions and 18 deletions
@@ -10,3 +10,58 @@ const pool = mysql
database: process.env.DB_NAME, database: process.env.DB_NAME,
}) })
.promise(); .promise();
export const newProduct = async (
name,
description,
price,
amount,
storage_location,
expiry_date,
bottling_date,
) => {
const [result] = await pool.query(
"INSERT INTO products (name, description, price, amount, storage_location, expiry_date, bottling_date) VALUES (?, ?, ?, ?, UUID_TO_BIN(?), ?, ?)",
[
name,
description,
price,
amount,
storage_location,
expiry_date,
bottling_date,
],
);
if (result.affectedRows > 0) {
return { code: "sp001" }; // success
} else {
return { code: "ep001" }; // error
}
};
export const allProducts = async () => {
const [result] = await pool.query(`
SELECT
BIN_TO_UUID(p.uuid) AS uuid,
p.name,
p.description,
p.price,
p.amount,
BIN_TO_UUID(s.uuid) AS storage_location_uuid,
s.name AS storage_location_name,
p.expiry_date,
p.bottling_date,
p.picture,
p.created_at,
p.updated_at
FROM products p
JOIN storage_locations s ON p.storage_location = s.uuid
`);
if (result.length > 0) {
return { code: "sp002", data: result };
} else {
return { code: "ep002" };
}
};
@@ -0,0 +1,37 @@
import mysql from "mysql2";
import dotenv from "dotenv";
dotenv.config();
const pool = mysql
.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
})
.promise();
export const allStorages = async () => {
const [result] = await pool.query(
"SELECT BIN_TO_UUID(uuid) AS uuid, name, description, created_at, updated_at FROM storage_locations;",
);
if (result.length > 0) {
return { code: "ss001", data: result };
} else {
return { code: "es001" };
}
};
export const newStorage = async (name, description) => {
const [result] = await pool.query(
"INSERT INTO storage_locations (name, description) VALUES (?, ?)",
[name, description],
);
if (result.affectedRows > 0) {
return { code: "ss002" };
} else {
return { code: "es002" };
}
};
@@ -18,14 +18,14 @@ export const findUser = async (username, password) => {
); );
if (result.length <= 0) { if (result.length <= 0) {
return { code: "e001" }; // username or password is wrong return { code: "eu001" }; // username or password is wrong
} }
if (!result[0].is_active) { if (!result[0].is_active) {
return { code: "e002" }; // user is deactivated return { code: "eu002" }; // user is deactivated
} }
return { code: "s001", data: result[0] }; // user found return { code: "su001", data: result[0] }; // user found
}; };
export const loginUser = async (username) => { export const loginUser = async (username) => {
@@ -35,8 +35,8 @@ export const loginUser = async (username) => {
); );
if (result.affectedRows > 0) { if (result.affectedRows > 0) {
return { code: "s002" }; return { code: "su002" };
} else { } else {
return { code: "e003" }; return { code: "eu003" };
} }
}; };
+64
View File
@@ -1,6 +1,70 @@
import express from "express"; import express from "express";
import dotenv from "dotenv"; import dotenv from "dotenv";
import { authenticate } from "../../services/tokenService.js";
import { allProducts, newProduct } from "./database/products.database.js";
dotenv.config(); dotenv.config();
const router = express.Router(); const router = express.Router();
router.post("/new-product", authenticate, async (req, res) => {
const {
name,
description,
price,
amount,
storage_location,
expiry_date,
bottling_date,
} = req.body;
const result = await newProduct(
name,
description,
price,
amount,
storage_location,
expiry_date,
bottling_date,
);
if (result.code === "ep001") {
res.status(406).json({
success: false,
code: "ep001",
data: null,
message: "Error while creating product",
});
}
if (result.code === "sp001") {
res.status(201).json({
success: true,
code: "sp001",
data: null,
message: "",
});
}
});
router.get("/all-products", authenticate, async (req, res) => {
const result = await allProducts();
if (result.code === "ep002") {
res.status(406).json({
success: false,
code: "ep002",
data: null,
message: "Error while fetching products",
});
}
if (result.code === "sp002") {
res.status(200).json({
success: true,
code: "sp002",
data: result.data,
message: "",
});
}
});
export default router; export default router;
+54
View File
@@ -0,0 +1,54 @@
import express from "express";
import dotenv from "dotenv";
import { authenticate } from "../../services/tokenService.js";
import { allStorages, newStorage } from "./database/storage.database.js";
dotenv.config();
const router = express.Router();
router.get("/all-storages", authenticate, async (req, res) => {
const result = await allStorages();
if (result.code === "es001") {
res.status(500).json({
success: false,
code: "es001",
data: null,
message: "unexpected server error",
});
}
if (result.code === "ss001") {
res.status(200).json({
success: true,
code: "ss001",
data: result.data,
message: "",
});
}
});
router.post("/new-storage", authenticate, async (req, res) => {
const { name, description } = req.body;
const result = await newStorage(name, description);
if (result.code === "es002") {
res.status(500).json({
success: false,
code: "es002",
data: null,
message: "unexpected server error",
});
}
if (result.code === "ss002") {
res.status(201).json({
success: true,
code: "ss002",
data: null,
message: "",
});
}
});
export default router;
+7 -7
View File
@@ -11,32 +11,32 @@ router.post("/login", async (req, res) => {
const result = await findUser(username, password); const result = await findUser(username, password);
if (result.code === "e001") { if (result.code === "eu001") {
res.status(404).json({ res.status(404).json({
success: false, success: false,
code: "e001", code: "eu001",
data: null, data: null,
message: "username oder password is wrong", message: "username oder password is wrong",
}); });
} }
if (result.code === "e002") { if (result.code === "eu002") {
res.status(403).json({ res.status(403).json({
success: false, success: false,
code: "e002", code: "eu002",
data: null, data: null,
message: "user is deactivated", message: "user is deactivated",
}); });
} }
if (result.code === "s001") { if (result.code === "su001") {
const token = await generateToken(result.data); const token = await generateToken(result.data);
const login = await loginUser(result.data.username); const login = await loginUser(result.data.username);
if (login.code === "e003") { if (login.code === "e003") {
res.status(500).json({ res.status(500).json({
success: false, success: false,
code: "e003", code: "eu003",
data: null, data: null,
message: "Unexpected server error. Please contact system admin.", message: "Unexpected server error. Please contact system admin.",
}); });
@@ -44,7 +44,7 @@ router.post("/login", async (req, res) => {
res.status(202).json({ res.status(202).json({
success: true, success: true,
code: "s001", code: "su001",
data: { data: {
token, token,
}, },
+3
View File
@@ -18,6 +18,9 @@ app.use("/users", userRouter);
import productRouter from "./routes/app/products.route.js"; import productRouter from "./routes/app/products.route.js";
app.use("/products", productRouter); app.use("/products", productRouter);
import storageRouter from "./routes/app/storage.route.js";
app.use("/storage", storageRouter);
app.listen(PORT, () => { app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`); console.log(`Server is running on http://localhost:${PORT}`);
}); });
+7 -5
View File
@@ -1,11 +1,13 @@
import { defineConfig } from 'vite' import { defineConfig } from "vite";
import react, { reactCompilerPreset } from '@vitejs/plugin-react' import react, { reactCompilerPreset } from "@vitejs/plugin-react";
import babel from '@rolldown/plugin-babel' import babel from "@rolldown/plugin-babel";
import tailwindcss from "@tailwindcss/vite";
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [
react(), react(),
babel({ presets: [reactCompilerPreset()] }) tailwindcss(),
babel({ presets: [reactCompilerPreset()] }),
], ],
}) });