Compare commits
1 Commits
wisdom
...
251f7148b6
| Author | SHA1 | Date | |
|---|---|---|---|
| 251f7148b6 |
41
.env.example
41
.env.example
@@ -1,18 +1,18 @@
|
|||||||
# SQL DB Connection Colo
|
# # SQL DB Connection Colo
|
||||||
SQL_HOST=117.102.231.130
|
# SQL_HOST=117.102.231.130
|
||||||
SQL_DATABASE=cod_piu
|
|
||||||
SQL_USERNAME=sa
|
|
||||||
SQL_PASSWORD=@R3M4niA.
|
|
||||||
SQL_PORT=1433
|
|
||||||
|
|
||||||
# SQL_HOST=203.153.114.226
|
|
||||||
# SQL_PORT=1112
|
|
||||||
# SQL_DATABASE=piu
|
# SQL_DATABASE=piu
|
||||||
# SQL_USERNAME=sa
|
# SQL_USERNAME=sa
|
||||||
# SQL_PASSWORD=piu123
|
# SQL_PASSWORD=@R3M4niA.
|
||||||
|
# SQL_PORT=1433
|
||||||
|
|
||||||
|
SQL_HOST=203.153.114.226
|
||||||
|
SQL_PORT=1112
|
||||||
|
SQL_DATABASE=piu
|
||||||
|
SQL_USERNAME=sa
|
||||||
|
SQL_PASSWORD=piu123
|
||||||
|
|
||||||
# Application Port - express server listens on this port (default 9000).
|
# Application Port - express server listens on this port (default 9000).
|
||||||
PORT=9530
|
PORT=9528
|
||||||
ENDPOINT_WA=http://203.153.114.226:9529/send
|
ENDPOINT_WA=http://203.153.114.226:9529/send
|
||||||
# ENDPOINT_WA=http://localhost:9529/send
|
# ENDPOINT_WA=http://localhost:9529/send
|
||||||
ENDPOINT_FE=http://203.153.114.226:9527
|
ENDPOINT_FE=http://203.153.114.226:9527
|
||||||
@@ -23,11 +23,6 @@ SECRET=secret
|
|||||||
# JWT refresh secret
|
# JWT refresh secret
|
||||||
REFRESH_SECRET=refreshsecret
|
REFRESH_SECRET=refreshsecret
|
||||||
|
|
||||||
# IMAGEKIT
|
|
||||||
IMAGEKIT_URL_ENDPOINT=https://ik.imagekit.io/j0hxk7x3p
|
|
||||||
IMAGEKIT_PUBLIC_KEY=public_iMPQFBnXmdQy73TTB9w4SMQO4Jk=
|
|
||||||
IMAGEKIT_PRIVATE_KEY=private_vhO/jXHnEoaVYptOHIuZDPMbxIA=
|
|
||||||
|
|
||||||
# mail server settings
|
# mail server settings
|
||||||
# SMTP_FROM=youremail
|
# SMTP_FROM=youremail
|
||||||
# SMTP_USER=youremail
|
# SMTP_USER=youremail
|
||||||
@@ -45,18 +40,4 @@ IMAGEKIT_PRIVATE_KEY=private_vhO/jXHnEoaVYptOHIuZDPMbxIA=
|
|||||||
# CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
|
# CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
# REFRESH_TOKEN=1//XXXXXXXX
|
# REFRESH_TOKEN=1//XXXXXXXX
|
||||||
|
|
||||||
ENDPOINT_WHATSAPP=https://117.102.231.130:9531/send
|
|
||||||
# ENDPOINT_WHATSAPP=http://localhost:9529/send
|
|
||||||
|
|
||||||
# ENDPOINT_FE=http://localhost:8592
|
|
||||||
# ENDPOINT_FE=http://203.153.114.226:8466
|
|
||||||
ENDPOINT_FE=https://117.102.231.130:9529
|
|
||||||
|
|
||||||
|
|
||||||
# MQTT Connection
|
|
||||||
MQTT_HOST=ws://117.102.231.130:7001
|
|
||||||
MQTT_USERNAME=morekmorekmorek
|
|
||||||
MQTT_PASSWORD=morek888
|
|
||||||
TOPIC_COD=PIU_COD/ERROR_CODE
|
|
||||||
|
|
||||||
VITE_KEY_SESSION=PetekRombonganPetekMorekMorakMarek
|
VITE_KEY_SESSION=PetekRombonganPetekMorekMorakMarek
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,4 +3,3 @@ node_modules
|
|||||||
.vscode
|
.vscode
|
||||||
request.http
|
request.http
|
||||||
*.rest
|
*.rest
|
||||||
package-lock.json
|
|
||||||
27
app.js
27
app.js
@@ -8,8 +8,6 @@ const helmet = require("helmet");
|
|||||||
const compression = require("compression");
|
const compression = require("compression");
|
||||||
const unknownEndpoint = require("./middleware/unKnownEndpoint");
|
const unknownEndpoint = require("./middleware/unKnownEndpoint");
|
||||||
const { handleError } = require("./helpers/error");
|
const { handleError } = require("./helpers/error");
|
||||||
const { checkConnection, mqttClient } = require("./config");
|
|
||||||
const { onNotification } = require("./services/notifikasi-wa.service");
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
@@ -26,32 +24,7 @@ app.use("/api", routes);
|
|||||||
app.get("/", (req, res) =>
|
app.get("/", (req, res) =>
|
||||||
res.send("<h1 style='text-align: center'>HAHALO</h1>")
|
res.send("<h1 style='text-align: center'>HAHALO</h1>")
|
||||||
);
|
);
|
||||||
|
|
||||||
app.get("/check-db", async (req, res) => {
|
|
||||||
try {
|
|
||||||
const isConnected = await checkConnection();
|
|
||||||
res.json({
|
|
||||||
success: isConnected,
|
|
||||||
message: isConnected
|
|
||||||
? "Koneksi database OK"
|
|
||||||
: "Koneksi database gagal",
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
res.status(500).json({
|
|
||||||
success: false,
|
|
||||||
message: "Terjadi kesalahan saat cek koneksi database",
|
|
||||||
error: error.message,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(unknownEndpoint);
|
app.use(unknownEndpoint);
|
||||||
app.use(handleError);
|
app.use(handleError);
|
||||||
|
|
||||||
// Saat pesan diterima
|
|
||||||
mqttClient.on('message', (topic, message) => {
|
|
||||||
console.log(`Received message on topic "${topic}":`, message.toString());
|
|
||||||
onNotification(topic, message);
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|||||||
145
config/index.js
145
config/index.js
@@ -1,11 +1,8 @@
|
|||||||
require("dotenv").config();
|
require("dotenv").config();
|
||||||
const { default: mqtt } = require("mqtt");
|
|
||||||
const sql = require("mssql");
|
const sql = require("mssql");
|
||||||
|
|
||||||
const isProduction = process.env.NODE_ENV === "production";
|
const isProduction = process.env.NODE_ENV === "production";
|
||||||
|
|
||||||
const endPointWhatsapp = process.env.ENDPOINT_WHATSAPP;
|
|
||||||
|
|
||||||
// Config SQL Server
|
// Config SQL Server
|
||||||
const config = {
|
const config = {
|
||||||
user: process.env.SQL_USERNAME,
|
user: process.env.SQL_USERNAME,
|
||||||
@@ -31,18 +28,6 @@ const poolPromise = new sql.ConnectionPool(config)
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function checkConnection() {
|
|
||||||
try {
|
|
||||||
const pool = await poolPromise;
|
|
||||||
await pool.request().query("SELECT 1 AS isConnected");
|
|
||||||
console.log("🔍 SQL Server terkoneksi dengan baik");
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("⚠️ Gagal cek koneksi SQL Server:", error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper query (auto konversi $1 → @p1)
|
* Wrapper query (auto konversi $1 → @p1)
|
||||||
*/
|
*/
|
||||||
@@ -62,15 +47,7 @@ async function query(text, params = []) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validasi tanggal
|
* Build filter query
|
||||||
*/
|
|
||||||
function isValidDate(dateStr) {
|
|
||||||
const d = new Date(dateStr);
|
|
||||||
return !isNaN(d.getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build filter query (AND)
|
|
||||||
*/
|
*/
|
||||||
function buildFilterQuery(filterQuery = [], fixedParams = []) {
|
function buildFilterQuery(filterQuery = [], fixedParams = []) {
|
||||||
let whereConditions = [];
|
let whereConditions = [];
|
||||||
@@ -82,9 +59,7 @@ function buildFilterQuery(filterQuery = [], fixedParams = []) {
|
|||||||
switch (f.type) {
|
switch (f.type) {
|
||||||
case "string":
|
case "string":
|
||||||
queryParams.push(`%${f.param}%`);
|
queryParams.push(`%${f.param}%`);
|
||||||
whereConditions.push(
|
whereConditions.push(`${f.column} LIKE $${queryParams.length} COLLATE SQL_Latin1_General_CP1_CI_AS`);
|
||||||
`${f.column} LIKE $${queryParams.length} COLLATE SQL_Latin1_General_CP1_CI_AS`
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "number":
|
case "number":
|
||||||
@@ -96,30 +71,17 @@ function buildFilterQuery(filterQuery = [], fixedParams = []) {
|
|||||||
queryParams.push(f.param ? 1 : 0);
|
queryParams.push(f.param ? 1 : 0);
|
||||||
whereConditions.push(`${f.column} = $${queryParams.length}`);
|
whereConditions.push(`${f.column} = $${queryParams.length}`);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "between":
|
|
||||||
if (Array.isArray(f.param) && f.param.length === 2) {
|
|
||||||
const [from, to] = f.param;
|
|
||||||
if (isValidDate(from) && isValidDate(to)) {
|
|
||||||
queryParams.push(from);
|
|
||||||
queryParams.push(to);
|
|
||||||
whereConditions.push(
|
|
||||||
`CAST(${f.column} AS DATE) BETWEEN $${queryParams.length - 1} AND $${queryParams.length}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { whereConditions, whereParamAnd: queryParams };
|
return { whereConditions, queryParams };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build OR ILIKE (SQL Server pakai LIKE + COLLATE)
|
* Build OR ILIKE (SQL Server pakai LIKE + COLLATE)
|
||||||
*/
|
*/
|
||||||
function buildStringOrIlike(columnParam, criteria, fixedParams = []) {
|
function buildStringOrIlike(columnParam, criteria, fixedParams = []) {
|
||||||
if (!criteria) return { whereOrConditions: "", whereParamOr: fixedParams };
|
if (!criteria) return { whereClause: "", whereParam: fixedParams };
|
||||||
|
|
||||||
let orStringConditions = [];
|
let orStringConditions = [];
|
||||||
let queryParams = [...fixedParams];
|
let queryParams = [...fixedParams];
|
||||||
@@ -127,73 +89,20 @@ function buildStringOrIlike(columnParam, criteria, fixedParams = []) {
|
|||||||
columnParam.forEach((column) => {
|
columnParam.forEach((column) => {
|
||||||
if (!column) return;
|
if (!column) return;
|
||||||
queryParams.push(`%${criteria}%`);
|
queryParams.push(`%${criteria}%`);
|
||||||
orStringConditions.push(
|
orStringConditions.push(`${column} LIKE $${queryParams.length} COLLATE SQL_Latin1_General_CP1_CI_AS`);
|
||||||
`${column} LIKE $${queryParams.length} COLLATE SQL_Latin1_General_CP1_CI_AS`
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const whereClause = orStringConditions.length
|
const whereClause = orStringConditions.length
|
||||||
? `AND (${orStringConditions.join(" OR ")})`
|
? `AND (${orStringConditions.join(" OR ")})`
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
return { whereOrConditions: whereClause, whereParamOr: queryParams };
|
return { whereOrConditions: whereClause, whereParam: queryParams };
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build Date Filter (harian / mingguan / bulanan)
|
|
||||||
*/
|
|
||||||
function buildDateFilter(column, type, dateValue, fixedParams = []) {
|
|
||||||
let whereCondition = "";
|
|
||||||
let queryParams = [...fixedParams];
|
|
||||||
|
|
||||||
if (!dateValue && type !== "monthly") {
|
|
||||||
return { whereDateCondition: "", whereDateParams: queryParams };
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case "daily": {
|
|
||||||
queryParams.push(dateValue);
|
|
||||||
whereCondition = `CAST(${column} AS DATE) = $${queryParams.length}`;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "weekly": {
|
|
||||||
const startDate = new Date(dateValue);
|
|
||||||
if (!isNaN(startDate.getTime())) {
|
|
||||||
const endDate = new Date(startDate);
|
|
||||||
endDate.setDate(startDate.getDate() + 6);
|
|
||||||
|
|
||||||
queryParams.push(startDate.toISOString().split("T")[0]);
|
|
||||||
queryParams.push(endDate.toISOString().split("T")[0]);
|
|
||||||
|
|
||||||
whereCondition = `CAST(${column} AS DATE) BETWEEN $${queryParams.length - 1} AND $${queryParams.length}`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "monthly": {
|
|
||||||
const [year, month] = dateValue.split("-");
|
|
||||||
if (year && month) {
|
|
||||||
queryParams.push(parseInt(year), parseInt(month));
|
|
||||||
whereCondition = `YEAR(${column}) = $${queryParams.length - 1} AND MONTH(${column}) = $${queryParams.length}`;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
whereCondition = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
return { whereDateCondition: whereCondition, whereDateParams: queryParams };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build dynamic UPDATE
|
* Build dynamic UPDATE
|
||||||
*/
|
*/
|
||||||
function buildDynamicUpdate(table, data, where) {
|
function buildDynamicUpdate(table, data, where) {
|
||||||
data.updated_by = data.userId;
|
|
||||||
delete data.userId;
|
|
||||||
|
|
||||||
const setParts = [];
|
const setParts = [];
|
||||||
const values = [];
|
const values = [];
|
||||||
let index = 1;
|
let index = 1;
|
||||||
@@ -209,7 +118,8 @@ function buildDynamicUpdate(table, data, where) {
|
|||||||
throw new Error("Tidak ada kolom untuk diupdate");
|
throw new Error("Tidak ada kolom untuk diupdate");
|
||||||
}
|
}
|
||||||
|
|
||||||
setParts.push(`updated_at = CURRENT_TIMESTAMP`);
|
// updated_at otomatis pakai GETDATE()
|
||||||
|
setParts.push(`updated_at = GETDATE()`);
|
||||||
|
|
||||||
const whereParts = [];
|
const whereParts = [];
|
||||||
for (const [key, value] of Object.entries(where)) {
|
for (const [key, value] of Object.entries(where)) {
|
||||||
@@ -230,10 +140,6 @@ function buildDynamicUpdate(table, data, where) {
|
|||||||
* Build dynamic INSERT
|
* Build dynamic INSERT
|
||||||
*/
|
*/
|
||||||
function buildDynamicInsert(table, data) {
|
function buildDynamicInsert(table, data) {
|
||||||
data.created_by = data.userId;
|
|
||||||
data.updated_by = data.userId;
|
|
||||||
delete data.userId;
|
|
||||||
|
|
||||||
const columns = [];
|
const columns = [];
|
||||||
const placeholders = [];
|
const placeholders = [];
|
||||||
const values = [];
|
const values = [];
|
||||||
@@ -251,8 +157,9 @@ function buildDynamicInsert(table, data) {
|
|||||||
throw new Error("Tidak ada kolom untuk diinsert");
|
throw new Error("Tidak ada kolom untuk diinsert");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// created_at & updated_at otomatis
|
||||||
columns.push("created_at", "updated_at");
|
columns.push("created_at", "updated_at");
|
||||||
placeholders.push("CURRENT_TIMESTAMP", "CURRENT_TIMESTAMP");
|
placeholders.push("GETDATE()", "GETDATE()");
|
||||||
|
|
||||||
const query = `
|
const query = `
|
||||||
INSERT INTO ${table} (${columns.join(", ")})
|
INSERT INTO ${table} (${columns.join(", ")})
|
||||||
@@ -287,43 +194,11 @@ async function generateKode(prefix, tableName, columnName) {
|
|||||||
return prefix + String(nextNumber).padStart(3, "0");
|
return prefix + String(nextNumber).padStart(3, "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Koneksi ke broker MQTT
|
|
||||||
const mqttOptions = {
|
|
||||||
clientId: 'express_mqtt_client_' + Math.random().toString(16).substr(2, 8),
|
|
||||||
clean: true,
|
|
||||||
connectTimeout: 4000,
|
|
||||||
username: process.env.MQTT_USERNAME ?? 'morekmorekmorek', // jika ada
|
|
||||||
password: process.env.MQTT_PASSWORD ?? 'morek888', // jika ada
|
|
||||||
};
|
|
||||||
|
|
||||||
const mqttUrl = process.env.MQTT_HOST; // Ganti dengan broker kamu
|
|
||||||
const topic = process.env.TOPIC_COD ?? 'morek';
|
|
||||||
|
|
||||||
const mqttClient = mqtt.connect(mqttUrl, mqttOptions);
|
|
||||||
|
|
||||||
// Saat terkoneksi
|
|
||||||
mqttClient.on('connect', () => {
|
|
||||||
console.log('MQTT connected');
|
|
||||||
|
|
||||||
// Subscribe ke topik tertentu
|
|
||||||
mqttClient.subscribe(topic, (err) => {
|
|
||||||
if (!err) {
|
|
||||||
console.log(`Subscribed to topic "${topic}"`);
|
|
||||||
} else {
|
|
||||||
console.error('Subscribe error:', err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
checkConnection,
|
|
||||||
query,
|
query,
|
||||||
buildFilterQuery,
|
buildFilterQuery,
|
||||||
buildDateFilter,
|
|
||||||
buildStringOrIlike,
|
buildStringOrIlike,
|
||||||
buildDynamicInsert,
|
buildDynamicInsert,
|
||||||
buildDynamicUpdate,
|
buildDynamicUpdate,
|
||||||
generateKode,
|
generateKode,
|
||||||
endPointWhatsapp,
|
|
||||||
mqttClient
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,140 +1,26 @@
|
|||||||
const AuthService = require('../services/auth.service');
|
const authService = require("../services/auth.service");
|
||||||
const { setResponse, checkValidate } = require('../helpers/utils');
|
|
||||||
const { registerSchema, loginSchema } = require('../validate/auth.schema');
|
|
||||||
const { createCaptcha } = require('../utils/captcha');
|
|
||||||
const JWTService = require('../utils/jwt');
|
|
||||||
|
|
||||||
const CryptoJS = require('crypto-js');
|
const loginUser = async (req, res) => {
|
||||||
|
const { username, password, role, tenant } = req.body;
|
||||||
class AuthController {
|
const { token, refreshToken, user } = await authService.login(
|
||||||
// Register
|
username,
|
||||||
static async register(req, res) {
|
password,
|
||||||
const { error, value } = await checkValidate(registerSchema, req);
|
tenant
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format nomor HP Indonesia
|
|
||||||
if (value.user_phone && value.user_phone.startsWith('0')) {
|
|
||||||
value.user_phone = '+62' + value.user_phone.slice(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await AuthService.register(value);
|
|
||||||
|
|
||||||
const response = await setResponse(
|
|
||||||
{
|
|
||||||
user: { ...results.user, approved: false },
|
|
||||||
},
|
|
||||||
'User registered successfully. Waiting for admin approval.'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
res.header("auth-token", token);
|
||||||
}
|
res.cookie("refreshToken", refreshToken, {
|
||||||
|
|
||||||
// Login
|
|
||||||
static async login(req, res) {
|
|
||||||
const { error, value } = await checkValidate(loginSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await AuthService.login(value);
|
|
||||||
|
|
||||||
// Simpan refresh token di cookie
|
|
||||||
res.cookie('refreshToken', results.tokens.refreshToken, {
|
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
secure: false,
|
sameSite: process.env.NODE_ENV === "development" ? true : "none",
|
||||||
sameSite: 'lax',
|
secure: process.env.NODE_ENV === "development" ? false : true,
|
||||||
maxAge: 7 * 24 * 60 * 60 * 1000
|
|
||||||
});
|
});
|
||||||
|
res.status(200).json({
|
||||||
const response = await setResponse(
|
token,
|
||||||
{
|
refreshToken,
|
||||||
user: { ...results.user, approved: true },
|
user,
|
||||||
accessToken: results.tokens.accessToken
|
|
||||||
},
|
|
||||||
'Login successful'
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh Token
|
|
||||||
static async refreshToken(req, res) {
|
|
||||||
const refreshToken = req.cookies?.refreshToken;
|
|
||||||
|
|
||||||
if (!refreshToken) {
|
|
||||||
return res.status(401).json(setResponse(null, 'Refresh token is required', 401));
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await AuthService.refreshToken(refreshToken);
|
|
||||||
const response = await setResponse(results, 'Token refreshed successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logout
|
|
||||||
static async logout(req, res) {
|
|
||||||
res.clearCookie('refreshToken', {
|
|
||||||
httpOnly: true,
|
|
||||||
sameSite: 'none',
|
|
||||||
secure: true
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const response = await setResponse(null, 'Logged out successfully');
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Captcha
|
|
||||||
static async generateCaptcha(req, res) {
|
|
||||||
const { svg, text } = createCaptcha();
|
|
||||||
|
|
||||||
// Tampilkan captcha di header untuk dev
|
|
||||||
res.setHeader('X-Captcha-Text', text);
|
|
||||||
|
|
||||||
const response = await setResponse({ svg, text }, 'Captcha generated');
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async verifyTokenRedirect(req, res) {
|
|
||||||
const { tokenRedirect } = req.body;
|
|
||||||
|
|
||||||
const bytes = CryptoJS.AES.decrypt(tokenRedirect, process.env.VITE_KEY_SESSION);
|
|
||||||
const decrypted = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
|
|
||||||
|
|
||||||
console.log("decrypted: ", decrypted);
|
|
||||||
|
|
||||||
const userPhone = decrypted?.user_phone
|
|
||||||
const userName = decrypted?.user_name
|
|
||||||
const idData = decrypted?.id
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
user_id: userPhone,
|
|
||||||
user_fullname: userName,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const tokens = JWTService.generateTokenPair(payload);
|
module.exports = {
|
||||||
|
loginUser,
|
||||||
// Simpan refresh token di cookie
|
};
|
||||||
res.cookie('refreshToken', tokens.refreshToken, {
|
|
||||||
httpOnly: true,
|
|
||||||
secure: false,
|
|
||||||
sameSite: 'lax',
|
|
||||||
maxAge: 7 * 24 * 60 * 60 * 1000
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await setResponse(
|
|
||||||
{
|
|
||||||
accessToken: tokens.accessToken,
|
|
||||||
idData
|
|
||||||
},
|
|
||||||
'Verify successful'
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = AuthController;
|
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
const BrandService = require('../services/brand.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const {
|
|
||||||
insertBrandSchema,
|
|
||||||
updateBrandSchema,
|
|
||||||
} = require('../validate/brand.schema');
|
|
||||||
|
|
||||||
class BrandController {
|
|
||||||
// Get all brands
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await BrandService.getAllBrands(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Brand found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get brand by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await BrandService.getBrandById(id);
|
|
||||||
|
|
||||||
// console.log('Brand response structure:', JSON.stringify(results, null, 2));
|
|
||||||
|
|
||||||
const response = await setResponse(results, 'Brand found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create brand
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertBrandSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.created_by = req.user?.user_id || null;
|
|
||||||
|
|
||||||
const results = await BrandService.createBrand(value);
|
|
||||||
const response = await setResponse(results, 'Brand created successfully');
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update brand
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = await checkValidate(updateBrandSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.updated_by = req.user?.user_id || null;
|
|
||||||
|
|
||||||
const results = await BrandService.updateBrand(id, value);
|
|
||||||
const response = await setResponse(results, 'Brand updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete brand by ID
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await BrandService.deleteBrand(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Brand deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = BrandController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const ContactService = require('../services/contact.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertContactSchema, updateContactSchema } = require('../validate/contact.schema');
|
|
||||||
|
|
||||||
class ContactController {
|
|
||||||
// Get all contact
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await ContactService.getAllContact(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Contact found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get contact by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await ContactService.getContactById(id);
|
|
||||||
const response = await setResponse(results, 'Contact found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create contact
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertContactSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await ContactService.createContact(value);
|
|
||||||
const response = await setResponse(results, 'Contact created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update contact
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateContactSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await ContactService.updateContact(id, value);
|
|
||||||
const response = await setResponse(results, 'Contact updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete contact
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await ContactService.deleteContact(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Contact deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ContactController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const DeviceService = require('../services/device.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertDeviceSchema, updateDeviceSchema } = require('../validate/device.schema');
|
|
||||||
|
|
||||||
class DeviceController {
|
|
||||||
// Get all devices
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await DeviceService.getAllDevices(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Device found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get device by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await DeviceService.getDeviceById(id);
|
|
||||||
const response = await setResponse(results, 'Device found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create device
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertDeviceSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await DeviceService.createDevice(value);
|
|
||||||
const response = await setResponse(results, 'Device created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update device
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateDeviceSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await DeviceService.updateDevice(id, value);
|
|
||||||
const response = await setResponse(results, 'Device updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete device
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await DeviceService.deleteDevice(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Device deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = DeviceController;
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
const ErrorCodeService = require('../services/error_code.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const {
|
|
||||||
insertErrorCodeSchema,
|
|
||||||
updateErrorCodeSchema,
|
|
||||||
} = require('../validate/error_code.schema');
|
|
||||||
|
|
||||||
class ErrorCodeController {
|
|
||||||
static async getByBrandId(req, res) {
|
|
||||||
const { brandId } = req.params;
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await ErrorCodeService.getErrorCodesByBrandId(brandId, queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Error codes found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get error code by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const result = await ErrorCodeService.getErrorCodeById(id);
|
|
||||||
const response = setResponse(result, 'Error code found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create error code with solutions and spareparts
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertErrorCodeSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const { brandId } = req.params;
|
|
||||||
value.created_by = req.user?.user_id || null;
|
|
||||||
|
|
||||||
const result = await ErrorCodeService.createErrorCodeWithFullData(brandId, value);
|
|
||||||
const response = setResponse(result, 'Error code created successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update error code with solutions and spareparts
|
|
||||||
static async update(req, res) {
|
|
||||||
const { error, value } = await checkValidate(updateErrorCodeSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const { brandId, errorCodeId } = req.params;
|
|
||||||
value.updated_by = req.user?.user_id || null;
|
|
||||||
|
|
||||||
const result = await ErrorCodeService.updateErrorCodeWithFullData(brandId, errorCodeId, value);
|
|
||||||
const response = setResponse(result, 'Error code updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete error code
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { brandId, errorCodeId } = req.params;
|
|
||||||
const deletedBy = req.user?.user_id || null;
|
|
||||||
|
|
||||||
const result = await ErrorCodeService.deleteErrorCode(brandId, errorCodeId, deletedBy);
|
|
||||||
const response = setResponse(result, 'Error code deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ErrorCodeController;
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
const fs = require("fs");
|
|
||||||
const { setResponse } = require("../helpers/utils");
|
|
||||||
const {
|
|
||||||
createFileUploadDb,
|
|
||||||
deleteFileUploadByPathDb,
|
|
||||||
} = require("../db/file_uploads.db");
|
|
||||||
|
|
||||||
const uploadFile = async (req, res) => {
|
|
||||||
try {
|
|
||||||
if (!req.file) {
|
|
||||||
const response = await setResponse([], "Tidak ada file yang diunggah", 400);
|
|
||||||
return res.status(400).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
const file = req.file;
|
|
||||||
const ext = path.extname(file.originalname).toLowerCase();
|
|
||||||
const typeDoc = ext === ".pdf" ? "PDF" : "IMAGE";
|
|
||||||
const folder = typeDoc === "PDF" ? "pdf" : "images";
|
|
||||||
|
|
||||||
const pathDocument = `${folder}/${file.filename}`;
|
|
||||||
|
|
||||||
const fileData = {
|
|
||||||
file_upload_name: file.originalname,
|
|
||||||
path_document: pathDocument,
|
|
||||||
type_document: typeDoc,
|
|
||||||
createdBy: req.user?.user_id || null,
|
|
||||||
};
|
|
||||||
|
|
||||||
await createFileUploadDb(fileData);
|
|
||||||
|
|
||||||
const response = await setResponse(
|
|
||||||
{
|
|
||||||
file_upload_name: file.originalname,
|
|
||||||
path_document: pathDocument
|
|
||||||
},
|
|
||||||
"File berhasil diunggah"
|
|
||||||
);
|
|
||||||
res.status(200).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const response = await setResponse([], error.message, 500);
|
|
||||||
res.status(500).json(response);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const getFileByPath = async (req, res) => {
|
|
||||||
try {
|
|
||||||
const { folder, filename } = req.params;
|
|
||||||
|
|
||||||
// Decode filename from URL encoding
|
|
||||||
const decodedFilename = decodeURIComponent(filename);
|
|
||||||
const filePath = path.join(__dirname, "../uploads", folder, decodedFilename);
|
|
||||||
|
|
||||||
console.log('getFileByPath Debug:', {
|
|
||||||
folder,
|
|
||||||
originalFilename: filename,
|
|
||||||
decodedFilename,
|
|
||||||
filePath
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!fs.existsSync(filePath)) {
|
|
||||||
console.log('File not found at path:', filePath);
|
|
||||||
|
|
||||||
// try {
|
|
||||||
// const folderPath = path.join(__dirname, "../uploads", folder);
|
|
||||||
// const availableFiles = fs.readdirSync(folderPath);
|
|
||||||
// console.log('Available files in', folderPath, ':', availableFiles);
|
|
||||||
// } catch (listError) {
|
|
||||||
// console.log('Could not list files in folder:', listError.message);
|
|
||||||
// }
|
|
||||||
|
|
||||||
const response = await setResponse([], "File tidak ditemukan", 404);
|
|
||||||
return res.status(404).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.sendFile(filePath);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('getFileByPath Error:', error);
|
|
||||||
const response = await setResponse([], error.message, 500);
|
|
||||||
res.status(500).json(response);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteFileByPath = async (req, res) => {
|
|
||||||
try {
|
|
||||||
const { folder, filename } = req.params;
|
|
||||||
|
|
||||||
// Decode filename from URL encoding
|
|
||||||
const decodedFilename = decodeURIComponent(filename);
|
|
||||||
const filePath = path.join(__dirname, "../uploads", folder, decodedFilename);
|
|
||||||
|
|
||||||
if (!fs.existsSync(filePath)) {
|
|
||||||
const response = await setResponse([], "File tidak ditemukan", 404);
|
|
||||||
return res.status(404).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete physical file
|
|
||||||
fs.unlinkSync(filePath);
|
|
||||||
|
|
||||||
const pathDocument = `${folder}/${decodedFilename}`;
|
|
||||||
const deletedBy = req.user?.user_id || null;
|
|
||||||
await deleteFileUploadByPathDb(pathDocument, deletedBy);
|
|
||||||
|
|
||||||
const response = await setResponse([], "File berhasil dihapus");
|
|
||||||
res.status(200).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const response = await setResponse([], error.message, 500);
|
|
||||||
res.status(500).json(response);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
uploadFile,
|
|
||||||
getFileByPath,
|
|
||||||
deleteFileByPath,
|
|
||||||
};
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
const HistoryValue = require('../services/history_value.service');
|
|
||||||
const { setResponsePaging } = require('../helpers/utils');
|
|
||||||
|
|
||||||
class HistoryValueController {
|
|
||||||
|
|
||||||
static async getAllHistoryAlarm(req, res) {
|
|
||||||
try {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await HistoryValue.getAllHistoryAlarm(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Data found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const statusCode = error.statusCode || 500;
|
|
||||||
res.status(statusCode).json({
|
|
||||||
success: false,
|
|
||||||
statusCode,
|
|
||||||
message: error.message || 'Internal server error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getAllHistoryEvent(req, res) {
|
|
||||||
try {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await HistoryValue.getAllHistoryEvent(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Data found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const statusCode = error.statusCode || 500;
|
|
||||||
res.status(statusCode).json({
|
|
||||||
success: false,
|
|
||||||
statusCode,
|
|
||||||
message: error.message || 'Internal server error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getHistoryValueReport(req, res) {
|
|
||||||
try {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await HistoryValue.getHistoryValueReport(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Data found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const statusCode = error.statusCode || 500;
|
|
||||||
res.status(statusCode).json({
|
|
||||||
success: false,
|
|
||||||
statusCode,
|
|
||||||
message: error.message || 'Internal server error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getHistoryValueReportPivot(req, res) {
|
|
||||||
try {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await HistoryValue.getHistoryValueReportPivot(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Data found');
|
|
||||||
|
|
||||||
if (results.column) {
|
|
||||||
response.columns = results.column;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const statusCode = error.statusCode || 500;
|
|
||||||
res.status(statusCode).json({
|
|
||||||
success: false,
|
|
||||||
statusCode,
|
|
||||||
message: error.message || 'Internal server error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getHistoryValueTrendingPivot(req, res) {
|
|
||||||
try {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await HistoryValue.getHistoryValueTrendingPivot(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Data found');
|
|
||||||
|
|
||||||
if (results.column) {
|
|
||||||
response.columns = results.column;
|
|
||||||
}
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const statusCode = error.statusCode || 500;
|
|
||||||
res.status(statusCode).json({
|
|
||||||
success: false,
|
|
||||||
statusCode,
|
|
||||||
message: error.message || 'Internal server error'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = HistoryValueController;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const NotificationErrorService = require("../services/notification_error.service");
|
|
||||||
const {
|
|
||||||
setResponse,
|
|
||||||
setResponsePaging,
|
|
||||||
checkValidate,
|
|
||||||
} = require("../helpers/utils");
|
|
||||||
const {
|
|
||||||
insertNotificationSchema,
|
|
||||||
updateNotificationSchema,
|
|
||||||
} = require("../validate/notification.schema");
|
|
||||||
|
|
||||||
class NotificationErrorController {
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await NotificationErrorService.getAllNotification(
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
const response = await setResponsePaging(
|
|
||||||
queryParams,
|
|
||||||
results,
|
|
||||||
"Notification found"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await NotificationErrorService.getNotificationById(id);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification retrieved successfully"
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertNotificationSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, "Validation failed", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await NotificationErrorService.createNotificationError(
|
|
||||||
value
|
|
||||||
);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification created successfully"
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await NotificationErrorService.updateNotificationError(
|
|
||||||
id,
|
|
||||||
userId
|
|
||||||
);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error updated successfully"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async resend(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const results = await NotificationErrorService.resendNotification(id);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error resend successfully"
|
|
||||||
);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorController;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
const NotificationErrorLogService = require('../services/notification_error_log.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertNotificationErrorLogSchema } = require('../validate/notification_error_log.schema');
|
|
||||||
|
|
||||||
class NotificationErrorLogController {
|
|
||||||
// Get all notification error logs
|
|
||||||
static async getAll(req, res) {
|
|
||||||
try {
|
|
||||||
const results = await NotificationErrorLogService.getAllNotificationErrorLog();
|
|
||||||
const response = await setResponse(results, 'Notification Error Logs found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const response = await setResponse(error, error.message, error.statusCode || 500);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get notification error log by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
try {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await NotificationErrorLogService.getNotificationErrorLogById(id);
|
|
||||||
const response = await setResponse(results, 'Notification Error Log found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const response = await setResponse(error, error.message, error.statusCode || 500);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get notification error logs by notification_error_id
|
|
||||||
static async getByNotificationErrorId(req, res) {
|
|
||||||
try {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await NotificationErrorLogService.getNotificationErrorLogByNotificationErrorId(id);
|
|
||||||
const response = await setResponse(results, 'Notification Error Logs found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const response = await setResponse(error, error.message, error.statusCode || 500);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create notification error log
|
|
||||||
static async create(req, res) {
|
|
||||||
try {
|
|
||||||
const { error, value } = await checkValidate(insertNotificationErrorLogSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await NotificationErrorLogService.createNotificationErrorLog(value, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Notification Error Log created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
} catch (error) {
|
|
||||||
const response = await setResponse(error, error.message, error.statusCode || 500);
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorLogController;
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
const NotificationErrorSparepart = require('../services/notification_error_sparepart.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { updateNotificationErrorSparepartSchema, insertNotificationErrorSparepartSchema } = require('../validate/notification_error_sparepart.schema');
|
|
||||||
|
|
||||||
class NotificationErrorSparepartController {
|
|
||||||
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const { contact_id } = req.body;
|
|
||||||
const queryParams = req.query;
|
|
||||||
const results = await NotificationErrorSparepart.getAll(queryParams, contact_id);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Notification Error Sparepart found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const results = await NotificationErrorSparepart.getById(id);
|
|
||||||
const response = await setResponse(results, 'Notification Error Sparepart found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertNotificationErrorSparepartSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await NotificationErrorSparepart.create(value);
|
|
||||||
const response = await setResponse(results, 'Notification Error Sparepart created successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const { error, value } = await checkValidate(updateNotificationErrorSparepartSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await NotificationErrorSparepart.update(id, value);
|
|
||||||
const response = await setResponse(results, 'Notification Error Sparepart updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const { contact_id } = req.body;
|
|
||||||
|
|
||||||
const results = await NotificationErrorSparepart.delete(id, contact_id);
|
|
||||||
const response = await setResponse(results, 'Notification Error Sparepart deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorSparepartController;
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
const NotificationErrorUserService = require("../services/notification_error_user.service");
|
|
||||||
const {
|
|
||||||
setResponse,
|
|
||||||
setResponsePaging,
|
|
||||||
checkValidate,
|
|
||||||
} = require("../helpers/utils");
|
|
||||||
const {
|
|
||||||
insertNotificationErrorUserSchema,
|
|
||||||
updateNotificationErrorUserSchema,
|
|
||||||
} = require("../validate/notification_error_user.schema");
|
|
||||||
|
|
||||||
class NotificationErrorUserController {
|
|
||||||
// Get all NotificationErrorUser
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results =
|
|
||||||
await NotificationErrorUserService.getAllNotificationErrorUser(
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
const response = await setResponsePaging(
|
|
||||||
queryParams,
|
|
||||||
results,
|
|
||||||
"Notification Error User found"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get NotificationErrorUser by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results =
|
|
||||||
await NotificationErrorUserService.getNotificationErrorUserById(id);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error User found"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create NotificationErrorUser
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(
|
|
||||||
insertNotificationErrorUserSchema,
|
|
||||||
req
|
|
||||||
);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, "Validation failed", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results =
|
|
||||||
await NotificationErrorUserService.createNotificationErrorUser(value);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error User created successfully"
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update NotificationErrorUser
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(
|
|
||||||
updateNotificationErrorUserSchema,
|
|
||||||
req
|
|
||||||
);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, "Validation failed", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results =
|
|
||||||
await NotificationErrorUserService.updateNotificationErrorUser(id, value);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error User updated successfully"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Notification Error User
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results =
|
|
||||||
await NotificationErrorUserService.deleteNotificationErrorUser(
|
|
||||||
id,
|
|
||||||
req.user.user_id
|
|
||||||
);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error User deleted successfully"
|
|
||||||
);
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async resendByUser(req, res) {
|
|
||||||
const { id, contact_phone } = req.params;
|
|
||||||
const results = await NotificationErrorUserService.resendNotificationByUser(
|
|
||||||
id,
|
|
||||||
contact_phone
|
|
||||||
);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Notification Error By User resend successfully"
|
|
||||||
);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorUserController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const SubSectionService = require('../services/plant_sub_section.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertSubSectionSchema, updateSubSectionSchema } = require('../validate/plant_sub_section.schema');
|
|
||||||
|
|
||||||
class SubSectionController {
|
|
||||||
// Get all sub sections
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await SubSectionService.getAll(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Sub section found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get sub section by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await SubSectionService.getById(id);
|
|
||||||
const response = await setResponse(results, 'Sub section found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create sub section
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertSubSectionSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await SubSectionService.create(value);
|
|
||||||
const response = await setResponse(results, 'Sub section created successfully');
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sub section
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateSubSectionSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await SubSectionService.update(id, value);
|
|
||||||
const response = await setResponse(results, 'Sub section updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete sub section
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await SubSectionService.delete(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Sub section deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SubSectionController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const RolesService = require('../services/roles.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { updateRolesSchema, insertRolesSchema } = require('../validate/roles.schema');
|
|
||||||
|
|
||||||
class RolesController {
|
|
||||||
// Get all Roles
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await RolesService.getAllRoles(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Roles found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Roles by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await RolesService.getRolesById(id);
|
|
||||||
const response = await setResponse(results, 'Roles found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Roles
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertRolesSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await RolesService.createRoles(value);
|
|
||||||
const response = await setResponse(results, 'Roles created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Roles
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateRolesSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await RolesService.updateRoles(id, value);
|
|
||||||
const response = await setResponse(results, 'Roles updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Roles
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await RolesService.deleteRoles(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Roles deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = RolesController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const ScheduleService = require('../services/schedule.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { updateScheduleSchema, insertScheduleSchema } = require('../validate/schedule.schema');
|
|
||||||
|
|
||||||
class ScheduleController {
|
|
||||||
// Get all Schedule
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await ScheduleService.getAllSchedule(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Schedule found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Schedule by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await ScheduleService.getScheduleById(id);
|
|
||||||
const response = await setResponse(results, 'Schedule found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Schedule
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertScheduleSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await ScheduleService.insertScheduleDb(value);
|
|
||||||
const response = await setResponse(results, 'Schedule created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Schedule
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateScheduleSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await ScheduleService.updateSchedule(id, value);
|
|
||||||
const response = await setResponse(results, 'Schedule updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Schedule
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await ScheduleService.deleteSchedule(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Schedule deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ScheduleController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const ShiftService = require('../services/shift.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { updateShiftSchema, insertShiftSchema } = require('../validate/shift.schema');
|
|
||||||
|
|
||||||
class ShiftController {
|
|
||||||
// Get all Shift
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await ShiftService.getAllShift(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Shift found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Shift by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await ShiftService.getShiftById(id);
|
|
||||||
const response = await setResponse(results, 'Shift found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Shift
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertShiftSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await ShiftService.createShift(value);
|
|
||||||
const response = await setResponse(results, 'Shift created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Shift
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateShiftSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await ShiftService.updateShift(id, value);
|
|
||||||
const response = await setResponse(results, 'Shift updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Shift
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await ShiftService.deleteShift(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Shift deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ShiftController;
|
|
||||||
@@ -1,327 +0,0 @@
|
|||||||
const ExcelJS = require("exceljs");
|
|
||||||
const path = require("path");
|
|
||||||
|
|
||||||
const ImageKit = require("imagekit");
|
|
||||||
const imagekit = new ImageKit({
|
|
||||||
publicKey: process.env.IMAGEKIT_PUBLIC_KEY,
|
|
||||||
privateKey: process.env.IMAGEKIT_PRIVATE_KEY,
|
|
||||||
urlEndpoint: process.env.IMAGEKIT_URL_ENDPOINT,
|
|
||||||
});
|
|
||||||
|
|
||||||
const SparepartService = require("../services/sparepart.service");
|
|
||||||
|
|
||||||
const {
|
|
||||||
setResponse,
|
|
||||||
setResponsePaging,
|
|
||||||
checkValidate,
|
|
||||||
} = require("../helpers/utils");
|
|
||||||
|
|
||||||
const {
|
|
||||||
insertSparepartSchema,
|
|
||||||
updateSparepartSchema,
|
|
||||||
} = require("../validate/sparepart.schema");
|
|
||||||
|
|
||||||
class SparepartController {
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
const results = await SparepartService.getAllSparepart(queryParams);
|
|
||||||
const response = await setResponsePaging(
|
|
||||||
queryParams,
|
|
||||||
results,
|
|
||||||
"Sparepart found"
|
|
||||||
);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const results = await SparepartService.getSparepartById(id);
|
|
||||||
const response = await setResponse(results, "Sparepart found");
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertSparepartSchema, req);
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, "Validation failed", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (req.file) {
|
|
||||||
const upload = await imagekit.upload({
|
|
||||||
file: req.file.buffer,
|
|
||||||
fileName: req.file.originalname,
|
|
||||||
folder: "/sparepart",
|
|
||||||
});
|
|
||||||
|
|
||||||
value.sparepart_foto = upload.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await SparepartService.createSparepart(value);
|
|
||||||
return res
|
|
||||||
.status(201)
|
|
||||||
.json(setResponse(results, "Sparepart created successfully"));
|
|
||||||
} catch (err) {
|
|
||||||
return res
|
|
||||||
.status(err.statusCode || 500)
|
|
||||||
.json(setResponse([], err.message, err.statusCode || 500));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const { error, value } = await checkValidate(updateSparepartSchema, req);
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, "Validation failed", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (req.file) {
|
|
||||||
const upload = await imagekit.upload({
|
|
||||||
file: req.file.buffer,
|
|
||||||
fileName: req.file.originalname,
|
|
||||||
folder: "/sparepart",
|
|
||||||
});
|
|
||||||
|
|
||||||
value.sparepart_foto = upload.url;
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await SparepartService.updateSparepart(id, value);
|
|
||||||
return res
|
|
||||||
.status(200)
|
|
||||||
.json(setResponse(results, "Sparepart updated successfully"));
|
|
||||||
} catch (err) {
|
|
||||||
return res
|
|
||||||
.status(err.statusCode || 500)
|
|
||||||
.json(setResponse([], err.message, err.statusCode || 500));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async exportExcel(req, res) {
|
|
||||||
try {
|
|
||||||
const queryParams = req.query || {};
|
|
||||||
queryParams.limit = null;
|
|
||||||
|
|
||||||
const results = await SparepartService.getAllSparepart(queryParams);
|
|
||||||
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
const worksheet = workbook.addWorksheet("Sparepart Data");
|
|
||||||
|
|
||||||
worksheet.columns = [
|
|
||||||
{ header: "Name Sparepart", key: "sparepart_name", width: 30 },
|
|
||||||
{ header: "Code Sparepart", key: "sparepart_code", width: 20 },
|
|
||||||
{ header: "QTY Sparepart", key: "sparepart_qty", width: 15 },
|
|
||||||
{ header: "Merk", key: "sparepart_merk", width: 20 },
|
|
||||||
{ header: "Model", key: "sparepart_model", width: 20 },
|
|
||||||
{ header: "Unit", key: "sparepart_unit", width: 10 },
|
|
||||||
{ header: "Stock", key: "sparepart_stok", width: 10 },
|
|
||||||
{ header: "Foto", key: "sparepart_foto", width: 25 },
|
|
||||||
{ header: "Item Type", key: "sparepart_item_type", width: 25 },
|
|
||||||
{ header: "Dibuat Pada", key: "created_at", width: 20 },
|
|
||||||
];
|
|
||||||
|
|
||||||
worksheet.addRows(
|
|
||||||
results.data.map((item) => ({
|
|
||||||
...item,
|
|
||||||
sparepart_foto: "",
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let i = 0; i < results.data.length; i++) {
|
|
||||||
const item = results.data[i];
|
|
||||||
const rowNumber = i + 2;
|
|
||||||
|
|
||||||
if (!item.sparepart_foto) continue;
|
|
||||||
|
|
||||||
let imageUrl = item.sparepart_foto;
|
|
||||||
|
|
||||||
if (!imageUrl.startsWith("https")) continue;
|
|
||||||
|
|
||||||
let ext = path.extname(imageUrl).toLowerCase().replace(".", "");
|
|
||||||
|
|
||||||
if (!ext) ext = "jpg";
|
|
||||||
|
|
||||||
const supported = ["jpg", "jpeg", "png"];
|
|
||||||
if (!supported.includes(ext)) {
|
|
||||||
ext = "png";
|
|
||||||
}
|
|
||||||
|
|
||||||
let buffer;
|
|
||||||
try {
|
|
||||||
const resp = await fetch(imageUrl);
|
|
||||||
buffer = Buffer.from(await resp.arrayBuffer());
|
|
||||||
} catch (e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const imageId = workbook.addImage({
|
|
||||||
buffer,
|
|
||||||
extension: ext === "jpg" ? "jpeg" : ext,
|
|
||||||
});
|
|
||||||
|
|
||||||
worksheet.addImage(imageId, {
|
|
||||||
tl: { col: 7, row: rowNumber - 1 },
|
|
||||||
ext: { width: 80, height: 80 },
|
|
||||||
});
|
|
||||||
|
|
||||||
worksheet.getRow(rowNumber).height = 70;
|
|
||||||
}
|
|
||||||
|
|
||||||
worksheet.getRow(1).eachCell((cell) => {
|
|
||||||
cell.font = { bold: true };
|
|
||||||
cell.alignment = { horizontal: "center" };
|
|
||||||
});
|
|
||||||
|
|
||||||
const buffer = await workbook.xlsx.writeBuffer();
|
|
||||||
|
|
||||||
res.setHeader(
|
|
||||||
"Content-Type",
|
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
||||||
);
|
|
||||||
res.setHeader(
|
|
||||||
"Content-Disposition",
|
|
||||||
"attachment; filename=sparepart_data.xlsx"
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.send(buffer);
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(500).json({ message: error.message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async importExcel(req, res) {
|
|
||||||
try {
|
|
||||||
|
|
||||||
const workbook = new ExcelJS.Workbook();
|
|
||||||
await workbook.xlsx.load(req.file.buffer);
|
|
||||||
|
|
||||||
const worksheet = workbook.getWorksheet(1);
|
|
||||||
|
|
||||||
const images = worksheet.getImages();
|
|
||||||
const imageMap = {};
|
|
||||||
images.forEach((imgObj) => {
|
|
||||||
const imageId = imgObj.imageId;
|
|
||||||
const range = imgObj.range;
|
|
||||||
const row = range.tl.nativeRow + 1;
|
|
||||||
const image = workbook.getImage(imageId);
|
|
||||||
imageMap[row] = image;
|
|
||||||
});
|
|
||||||
|
|
||||||
const spareparts = [];
|
|
||||||
|
|
||||||
worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
|
|
||||||
if (rowNumber === 1) return;
|
|
||||||
|
|
||||||
const [
|
|
||||||
sparepart_name,
|
|
||||||
sparepart_code,
|
|
||||||
sparepart_description,
|
|
||||||
sparepart_qty_excel,
|
|
||||||
sparepart_merk,
|
|
||||||
sparepart_model,
|
|
||||||
sparepart_unit,
|
|
||||||
sparepart_stok_excel,
|
|
||||||
sparepart_foto_excel,
|
|
||||||
sparepart_item_type,
|
|
||||||
] = row.values.slice(1);
|
|
||||||
|
|
||||||
if (!sparepart_name) return;
|
|
||||||
|
|
||||||
if (!sparepart_code) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spareparts.push({
|
|
||||||
sparepart_name: sparepart_name || "",
|
|
||||||
sparepart_code: sparepart_code || "",
|
|
||||||
sparepart_description: sparepart_description || "",
|
|
||||||
sparepart_qty: Number(sparepart_qty_excel) || 0,
|
|
||||||
sparepart_merk: sparepart_merk || "",
|
|
||||||
sparepart_model: sparepart_model || "",
|
|
||||||
sparepart_unit: sparepart_unit || "",
|
|
||||||
sparepart_stok: sparepart_stok_excel || "",
|
|
||||||
sparepart_foto: sparepart_foto_excel || "",
|
|
||||||
sparepart_item_type: sparepart_item_type || "",
|
|
||||||
rowNumber,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if (spareparts.length === 0) {
|
|
||||||
return res
|
|
||||||
.status(400)
|
|
||||||
.json(setResponse([], "Tidak ada data valid untuk diimport", 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
for (const data of spareparts) {
|
|
||||||
let uploadedUrl = "";
|
|
||||||
|
|
||||||
try {
|
|
||||||
const image = imageMap[data.rowNumber];
|
|
||||||
if (image) {
|
|
||||||
const fileName = `sparepart_${Date.now()}_${
|
|
||||||
data.sparepart_code
|
|
||||||
}.jpg`;
|
|
||||||
const uploadResult = await imagekit.upload({
|
|
||||||
file: image.buffer,
|
|
||||||
fileName: fileName,
|
|
||||||
folder: "/sparepart",
|
|
||||||
});
|
|
||||||
|
|
||||||
uploadedUrl = uploadResult.url;
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
err;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.sparepart_foto = uploadedUrl || "";
|
|
||||||
|
|
||||||
const { rowNumber, ...dbData } = data;
|
|
||||||
|
|
||||||
const created = await SparepartService.createSparepart(dbData);
|
|
||||||
|
|
||||||
if (created && created[0]) {
|
|
||||||
results.push({
|
|
||||||
sparepart_id: created[0].sparepart_id,
|
|
||||||
sparepart_name: created[0].sparepart_name,
|
|
||||||
sparepart_code: created[0].sparepart_code,
|
|
||||||
sparepart_description: created[0].sparepart_description,
|
|
||||||
sparepart_qty: created[0].sparepart_qty,
|
|
||||||
sparepart_merk: created[0].sparepart_merk,
|
|
||||||
sparepart_model: created[0].sparepart_model,
|
|
||||||
sparepart_unit: created[0].sparepart_unit,
|
|
||||||
sparepart_stok: created[0].sparepart_stok,
|
|
||||||
sparepart_foto: created[0].sparepart_foto,
|
|
||||||
sparepart_item_type: created[0].sparepart_item_type,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.json(
|
|
||||||
setResponse(results, `${results.length} Sparepart berhasil diimport`)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
return res.status(500).json({ message: error.message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const results = await SparepartService.deleteSparepart(
|
|
||||||
id,
|
|
||||||
req.user.user_id
|
|
||||||
);
|
|
||||||
const response = await setResponse(
|
|
||||||
results,
|
|
||||||
"Sparepart deleted successfully"
|
|
||||||
);
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SparepartController;
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
const StatusService = require('../services/status.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertStatusSchema, updateStatusSchema } = require('../validate/status.schema');
|
|
||||||
|
|
||||||
class StatusController {
|
|
||||||
// Get all status
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await StatusService.getAllStatus(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Status found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get status by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await StatusService.getStatusById(id);
|
|
||||||
const response = await setResponse(results, 'Status found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create status
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertStatusSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await StatusService.createStatus(value);
|
|
||||||
const response = await setResponse(results, 'Status created successfully');
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
console.log("REQ BODY:", req.body);
|
|
||||||
|
|
||||||
const { error, value } = await checkValidate(updateStatusSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await StatusService.updateStatus(id, value);
|
|
||||||
const response = await setResponse(results, 'Status updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete status
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await StatusService.deleteStatus(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Status deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = StatusController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const TagsService = require('../services/tags.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertTagsSchema, updateTagsSchema } = require('../validate/tags.schema');
|
|
||||||
|
|
||||||
class TagsController {
|
|
||||||
// Get all devices
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await TagsService.getAllTags(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Tags found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get device by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await TagsService.getTagByID(id);
|
|
||||||
const response = await setResponse(results, 'Tags found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create device
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertTagsSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await TagsService.createTags(value);
|
|
||||||
const response = await setResponse(results, 'Tags created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update device
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateTagsSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await TagsService.updateTags(id, value);
|
|
||||||
const response = await setResponse(results, 'Tags updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete device
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await TagsService.deleteTags(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Tags deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = TagsController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const UnitService = require('../services/unit.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertUnitSchema, updateUnitSchema } = require('../validate/unit.schema');
|
|
||||||
|
|
||||||
class UnitController {
|
|
||||||
// Get all units
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await UnitService.getAllUnits(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'Unit found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get unit by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await UnitService.getUnitById(id);
|
|
||||||
const response = await setResponse(results, 'Unit found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create unit
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertUnitSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.created_by = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await UnitService.createUnit(value);
|
|
||||||
const response = await setResponse(results, 'Unit created successfully');
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update unit
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateUnitSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.updated_by = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await UnitService.updateUnit(id, value);
|
|
||||||
const response = await setResponse(results, 'Unit updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete unit
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await UnitService.deleteUnit(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'Unit deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = UnitController;
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
const UserScheduleService = require('../services/user_schedule.service');
|
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require('../helpers/utils');
|
|
||||||
const { insertUserScheduleSchema, updateUserScheduleSchema } = require('../validate/user_schedule.schema');
|
|
||||||
|
|
||||||
class UserScheduleController {
|
|
||||||
// Get all User Schedule
|
|
||||||
static async getAll(req, res) {
|
|
||||||
const queryParams = req.query;
|
|
||||||
|
|
||||||
const results = await UserScheduleService.getAllUserScheduleDb(queryParams);
|
|
||||||
const response = await setResponsePaging(queryParams, results, 'User Schedule found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get User Schedule by ID
|
|
||||||
static async getById(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await UserScheduleService.getUserScheduleByID(id);
|
|
||||||
const response = await setResponse(results, 'User Schedule found')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create User Schedule
|
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(insertUserScheduleSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await UserScheduleService.createUserSchedules(value);
|
|
||||||
const response = await setResponse(results, 'User Schedule created successfully')
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update User Schedule
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = checkValidate(updateUserScheduleSchema, req)
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id
|
|
||||||
|
|
||||||
const results = await UserScheduleService.updateUserSchedules(id, value);
|
|
||||||
const response = await setResponse(results, 'User Schedule updated successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete User Schedule
|
|
||||||
static async delete(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await UserScheduleService.deleteUserSchedules(id, req.user.user_id);
|
|
||||||
const response = await setResponse(results, 'User Schedule deleted successfully')
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = UserScheduleController;
|
|
||||||
@@ -1,108 +1,172 @@
|
|||||||
const UserService = require("../services/user.service");
|
const userService = require("../services/user.service");
|
||||||
const { setResponse, setResponsePaging, checkValidate } = require("../helpers/utils");
|
const { ErrorHandler } = require("../helpers/error");
|
||||||
const { userSchema, updateUserSchema, newPasswordSchema } = require("../validate/user.schema");
|
const { hashPassword } = require("../helpers/hashPassword");
|
||||||
|
const { setResponse, setPaging, setResponsePaging } = require("../helpers/utils");
|
||||||
|
const Joi = require("joi");
|
||||||
|
|
||||||
class UserController {
|
// Definisikan skema validasi
|
||||||
// Get all users
|
const validateTerm = Joi.object({
|
||||||
static async getAll(req, res) {
|
user_fullname: Joi.string().max(255).required(),
|
||||||
const queryParams = req.query;
|
user_name: Joi.string().max(255).required(),
|
||||||
|
user_email: Joi.string().max(255).email().allow(null),
|
||||||
|
user_password: Joi.string().max(255).required(),
|
||||||
|
role_id: Joi.number().integer().allow(null),
|
||||||
|
is_active: Joi.boolean().required()
|
||||||
|
});
|
||||||
|
|
||||||
const results = await UserService.getAllUsers(queryParams);
|
const getAllUsers = async (req, res) => {
|
||||||
const response = await setResponsePaging(queryParams, results, 'Users found');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
const {
|
||||||
|
page = 1,
|
||||||
|
limit = 10,
|
||||||
|
fullname: userFullname,
|
||||||
|
username: userName,
|
||||||
|
is_active: isActive,
|
||||||
|
criteria,
|
||||||
|
tenantID,
|
||||||
|
} = req.query
|
||||||
|
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
|
const filterQuery = {
|
||||||
|
fixed: {
|
||||||
|
limit, offset, tenantID
|
||||||
|
},
|
||||||
|
filterQuery: [
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
column: 'user_fullname',
|
||||||
|
param: userFullname
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'string',
|
||||||
|
column: 'user_name',
|
||||||
|
param: userName
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'number',
|
||||||
|
column: 'is_active',
|
||||||
|
param: isActive
|
||||||
|
}
|
||||||
|
],
|
||||||
|
filterCriteria:
|
||||||
|
{
|
||||||
|
criteria,
|
||||||
|
column: [
|
||||||
|
'user_fullname', 'user_name'
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get user by ID
|
const results = await userService.getAllUsers(filterQuery)
|
||||||
static async getById(req, res) {
|
const response = await setResponsePaging(results.data, results.total, parseInt(limit), parseInt(page))
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const results = await UserService.getUserById(id);
|
res.status(response.statusCode).json(response)
|
||||||
const response = await setResponse(results, 'User found');
|
};
|
||||||
|
|
||||||
|
const getAllStatusUsers = async (req, res) => {
|
||||||
|
|
||||||
|
const results = await userService.getAllStatusUsers();
|
||||||
|
const response = await setResponse(results)
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
res.status(response.statusCode).json(response);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Create user
|
const createUser = async (req, res) => {
|
||||||
static async create(req, res) {
|
|
||||||
const { error, value } = await checkValidate(userSchema, req);
|
|
||||||
|
|
||||||
|
// Lakukan validasi
|
||||||
|
const { error } = validateTerm.validate(req.body, { stripUnknown: true });
|
||||||
if (error) {
|
if (error) {
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
const response = await setResponse([], error.details[0].message, 400)
|
||||||
}
|
|
||||||
|
|
||||||
value.approved_by = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await UserService.createUser(value);
|
|
||||||
const response = await setResponse(results, 'User created successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update user
|
|
||||||
static async update(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
|
|
||||||
const { error, value } = await checkValidate(updateUserSchema, req);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
|
||||||
}
|
|
||||||
|
|
||||||
value.userId = req.user.user_id;
|
|
||||||
|
|
||||||
const results = await UserService.updateUser(id, value);
|
|
||||||
const response = await setResponse(results, 'User updated successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Approve user
|
|
||||||
static async approve(req, res) {
|
|
||||||
const { id } = req.params;
|
|
||||||
const approverId = req.user.user_id;
|
|
||||||
|
|
||||||
const updatedUser = await UserService.approveUser(id, approverId);
|
|
||||||
const response = await setResponse(updatedUser, 'User approved successfully');
|
|
||||||
|
|
||||||
return res.status(response.statusCode).json(response);
|
return res.status(response.statusCode).json(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reject user
|
const results = await userService.createUser({
|
||||||
static async reject(req, res) {
|
userFullname: req.body.user_fullname,
|
||||||
|
userName: req.body.user_name,
|
||||||
|
userEmail: req.body.user_email,
|
||||||
|
userPassword: req.body.user_password,
|
||||||
|
roleId: req.body.role_id,
|
||||||
|
isActive: req.body.is_active, // default 1 jika tidak dikirim
|
||||||
|
userID: req.body.userID,
|
||||||
|
tenantID: req.body.tenantID
|
||||||
|
});
|
||||||
|
|
||||||
|
const response = await setResponse(results);
|
||||||
|
|
||||||
|
res.status(response.statusCode).json(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserById = async (req, res) => {
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const approverId = req.user.user_id;
|
|
||||||
|
|
||||||
const updatedUser = await UserService.rejectUser(id, approverId);
|
const results = await userService.getUserById(id);
|
||||||
const response = await setResponse(updatedUser, 'User rejected successfully');
|
const response = await setResponse(results)
|
||||||
|
|
||||||
|
res.status(response.statusCode).json(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserProfile = async (req, res) => {
|
||||||
|
const { id } = req.user;
|
||||||
|
|
||||||
|
const results = await userService.getUserById(id);
|
||||||
|
const response = await setResponse(results)
|
||||||
|
|
||||||
|
res.status(response.statusCode).json(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateUser = async (req, res) => {
|
||||||
|
|
||||||
|
const { id } = req.params;
|
||||||
|
|
||||||
|
// Lakukan validasi
|
||||||
|
const { error } = validateTerm.validate(req.body, { stripUnknown: true });
|
||||||
|
if (error) {
|
||||||
|
const response = await setResponse([], error.details[0].message, 400)
|
||||||
return res.status(response.statusCode).json(response);
|
return res.status(response.statusCode).json(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Soft delete user
|
const results = await userService.updateUser({
|
||||||
static async delete(req, res) {
|
userFullname: req.body.user_fullname,
|
||||||
const { id } = req.params;
|
userName: req.body.user_name,
|
||||||
|
userEmail: req.body.user_email,
|
||||||
|
userPassword: req.body.user_password,
|
||||||
|
roleId: req.body.role_id,
|
||||||
|
isActive: req.body.is_active, // default 1 jika tidak dikirim
|
||||||
|
userID: req.body.userID,
|
||||||
|
tenantID: req.body.tenantID,
|
||||||
|
id
|
||||||
|
});
|
||||||
|
|
||||||
const results = await UserService.deleteUser(id, req.user.user_id);
|
const response = await setResponse(results);
|
||||||
const response = await setResponse(results, 'User deleted successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
res.status(response.statusCode).json(response);
|
||||||
}
|
};
|
||||||
|
|
||||||
// Change password
|
const deleteUser = async (req, res) => {
|
||||||
static async changePassword(req, res) {
|
|
||||||
const { id } = req.params;
|
const { id } = req.params;
|
||||||
const { error, value } = await checkValidate(newPasswordSchema, req);
|
const userID = req.userID
|
||||||
|
|
||||||
if (error) {
|
const results = await userService.deleteUser(id, userID);
|
||||||
return res.status(400).json(setResponse(error, 'Validation failed', 400));
|
const response = await setResponse(results)
|
||||||
}
|
|
||||||
|
|
||||||
const results = await UserService.changeUserPassword(id, value.new_password);
|
|
||||||
const response = await setResponse(results, 'Password changed successfully');
|
|
||||||
|
|
||||||
res.status(response.statusCode).json(response);
|
res.status(response.statusCode).json(response);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = UserController;
|
const getAllRoles = async (req, res) => {
|
||||||
|
const results = await userService.getAllRoles(req.body.tenantID);
|
||||||
|
const response = await setResponse(results)
|
||||||
|
|
||||||
|
res.status(response.statusCode).json(response);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getAllUsers,
|
||||||
|
createUser,
|
||||||
|
getUserById,
|
||||||
|
updateUser,
|
||||||
|
deleteUser,
|
||||||
|
getUserProfile,
|
||||||
|
getAllRoles,
|
||||||
|
getAllStatusUsers
|
||||||
|
};
|
||||||
|
|||||||
143
db/brand.db.js
143
db/brand.db.js
@@ -1,143 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all brands
|
|
||||||
const getAllBrandsDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.brand_name", "a.brand_type", "a.brand_manufacture", "a.brand_model", "a.brand_code"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.brand_type", param: searchParams.type, type: "string" },
|
|
||||||
{ column: "a.brand_manufacture", param: searchParams.manufacture, type: "string" },
|
|
||||||
{ column: "a.brand_model", param: searchParams.model, type: "string" },
|
|
||||||
{ column: "a.is_active", param: searchParams.status, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM m_brands a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? `AND ${whereConditions.join(' AND ')}` : ''}
|
|
||||||
${whereOrConditions ? whereOrConditions : ''}
|
|
||||||
ORDER BY a.brand_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
const total =
|
|
||||||
result?.recordset.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get brand by name (path-based)
|
|
||||||
const getBrandByNameDb = async (brandName) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM m_brands a
|
|
||||||
WHERE a.brand_name = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [brandName]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get brand by ID (for internal use)
|
|
||||||
const getBrandByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM m_brands a
|
|
||||||
WHERE a.brand_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create brand
|
|
||||||
const createBrandDb = async (data) => {
|
|
||||||
const newCode = await pool.generateKode("BRD", "m_brands", "brand_code");
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
brand_code: newCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_brands", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId ? await getBrandByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update brand by name
|
|
||||||
const updateBrandDb = async (brandName, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { brand_name: brandName };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate("m_brands", store, whereData);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getBrandByNameDb(brandName);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete brand
|
|
||||||
const deleteBrandDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_brands
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE brand_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if brand name exists (for validation)
|
|
||||||
const checkBrandNameExistsDb = async (brandName, excludeId = null) => {
|
|
||||||
let queryText = `
|
|
||||||
SELECT brand_id
|
|
||||||
FROM m_brands
|
|
||||||
WHERE brand_name = $1 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
let values = [brandName];
|
|
||||||
|
|
||||||
if (excludeId) {
|
|
||||||
queryText += ` AND brand_id != $2`;
|
|
||||||
values.push(excludeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
return result.recordset.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllBrandsDb,
|
|
||||||
getBrandByNameDb,
|
|
||||||
getBrandByIdDb,
|
|
||||||
createBrandDb,
|
|
||||||
updateBrandDb,
|
|
||||||
deleteBrandDb,
|
|
||||||
checkBrandNameExistsDb,
|
|
||||||
};
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get error codes by brand ID
|
|
||||||
const getErrorCodesByBrandIdDb = async (brandId, searchParams = {}) => {
|
|
||||||
let queryParams = [brandId];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [brandId, Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search across multiple columns
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.error_code", "a.error_code_name", "a.error_code_description"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter conditions
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.is_active", param: searchParams.status, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM brand_code a
|
|
||||||
WHERE a.brand_id = $1 AND a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? `AND ${whereConditions.join(' AND ')}` : ''}
|
|
||||||
${whereOrConditions ? whereOrConditions : ''}
|
|
||||||
ORDER BY a.error_code_id DESC
|
|
||||||
${searchParams.limit ? `OFFSET $3 * $2 ROWS FETCH NEXT $2 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
// Return paginated format if limit is provided
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const total = result?.recordset.length > 0 ? parseInt(result.recordset[0].total_data, 10) : 0;
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return simple array for backward compatibility
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createErrorCodeDb = async (brandId, data) => {
|
|
||||||
const store = {
|
|
||||||
brand_id: brandId,
|
|
||||||
error_code: data.error_code,
|
|
||||||
error_code_name: data.error_code_name,
|
|
||||||
error_code_description: data.error_code_description,
|
|
||||||
error_code_color: data.error_code_color,
|
|
||||||
path_icon: data.path_icon,
|
|
||||||
is_active: data.is_active,
|
|
||||||
created_by: data.created_by
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("brand_code", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateErrorCodeDb = async (brandId, errorCode, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = {
|
|
||||||
brand_id: brandId,
|
|
||||||
error_code: errorCode
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate("brand_code", store, whereData);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteErrorCodeDb = async (brandId, errorCode, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE brand_code
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE brand_id = $2 AND error_code = $3 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, brandId, errorCode]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getErrorCodeByIdDb = async (error_code_id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM brand_code a
|
|
||||||
WHERE a.error_code_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [error_code_id]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
const getErrorCodeByBrandAndCodeDb = async (brandId, errorCode) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM brand_code a
|
|
||||||
WHERE a.brand_id = $1 AND a.error_code = $2 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [brandId, errorCode]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get all error codes with pagination and search
|
|
||||||
const getAllErrorCodesDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search across multiple columns
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.error_code", "a.error_code_name", "a.error_code_description"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter conditions
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.is_active", param: searchParams.status, type: "string" },
|
|
||||||
{ column: "a.brand_id", param: searchParams.brand_id, type: "number" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM brand_code a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? `AND ${whereConditions.join(' AND ')}` : ''}
|
|
||||||
${whereOrConditions ? whereOrConditions : ''}
|
|
||||||
ORDER BY a.error_code_id DESC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
const total = result?.recordset.length > 0 ? parseInt(result.recordset[0].total_data, 10) : 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getErrorCodesByBrandIdDb,
|
|
||||||
getErrorCodeByIdDb,
|
|
||||||
getErrorCodeByBrandAndCodeDb,
|
|
||||||
createErrorCodeDb,
|
|
||||||
updateErrorCodeDb,
|
|
||||||
deleteErrorCodeDb,
|
|
||||||
getAllErrorCodesDb,
|
|
||||||
};
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get solutions by error code ID
|
|
||||||
const getSolutionsByErrorCodeIdDb = async (errorCodeId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM brand_code_solution a
|
|
||||||
WHERE a.error_code_id = $1 AND a.deleted_at IS NULL
|
|
||||||
ORDER BY a.brand_code_solution_id
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [errorCodeId]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create solution for error code
|
|
||||||
const createSolutionDb = async (errorCodeId, data) => {
|
|
||||||
const store = {
|
|
||||||
error_code_id: errorCodeId,
|
|
||||||
solution_name: data.solution_name,
|
|
||||||
type_solution: data.type_solution,
|
|
||||||
text_solution: data.text_solution,
|
|
||||||
path_solution: data.path_solution,
|
|
||||||
is_active: data.is_active,
|
|
||||||
created_by: data.created_by
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("brand_code_solution", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update solution
|
|
||||||
const updateSolutionDb = async (solutionId, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { brand_code_solution_id: solutionId };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate("brand_code_solution", store, whereData);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete solution
|
|
||||||
const deleteSolutionDb = async (solutionId, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE brand_code_solution
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE brand_code_solution_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, solutionId]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getSolutionsByErrorCodeIdDb,
|
|
||||||
createSolutionDb,
|
|
||||||
updateSolutionDb,
|
|
||||||
deleteSolutionDb,
|
|
||||||
};
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get spareparts by error_code_id
|
|
||||||
const getSparepartsByErrorCodeIdDb = async (errorCodeId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
s.sparepart_id,
|
|
||||||
s.sparepart_name,
|
|
||||||
s.sparepart_code,
|
|
||||||
s.sparepart_description,
|
|
||||||
s.sparepart_model,
|
|
||||||
s.sparepart_foto,
|
|
||||||
s.sparepart_item_type,
|
|
||||||
s.sparepart_qty,
|
|
||||||
s.sparepart_unit,
|
|
||||||
s.sparepart_merk,
|
|
||||||
s.sparepart_stok,
|
|
||||||
bs.created_at,
|
|
||||||
bs.created_by
|
|
||||||
FROM brand_sparepart bs
|
|
||||||
JOIN m_sparepart s ON bs.sparepart_id = s.sparepart_id
|
|
||||||
WHERE bs.error_code_id = $1
|
|
||||||
AND s.deleted_at IS NULL
|
|
||||||
ORDER BY s.sparepart_name
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [errorCodeId]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get error codes by sparepart_id
|
|
||||||
const getErrorCodesBySparepartIdDb = async (sparepartId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
ec.error_code_id,
|
|
||||||
ec.error_code,
|
|
||||||
ec.error_code_name,
|
|
||||||
ec.error_code_description,
|
|
||||||
ec.error_code_color,
|
|
||||||
ec.path_icon,
|
|
||||||
ec.is_active,
|
|
||||||
ec.created_at,
|
|
||||||
ec.updated_at
|
|
||||||
FROM brand_sparepart bs
|
|
||||||
JOIN m_error_codes ec ON bs.error_code_id = ec.error_code_id
|
|
||||||
WHERE bs.sparepart_id = $1
|
|
||||||
AND ec.deleted_at IS NULL
|
|
||||||
ORDER BY ec.error_code
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [sparepartId]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Insert error_code-spareparts relationship
|
|
||||||
const insertErrorCodeSparepartDb = async (errorCodeId, sparepartId, createdBy) => {
|
|
||||||
const queryText = `
|
|
||||||
INSERT INTO brand_sparepart (error_code_id, sparepart_id, created_by, created_at)
|
|
||||||
VALUES ($1, $2, $3, CURRENT_TIMESTAMP)
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [errorCodeId, sparepartId, createdBy]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Insert multiple error_code-spareparts relationships
|
|
||||||
const insertMultipleErrorCodeSparepartsDb = async (errorCodeId, sparepartIds, createdBy) => {
|
|
||||||
if (!sparepartIds || sparepartIds.length === 0) return [];
|
|
||||||
|
|
||||||
const values = sparepartIds.map((_, index) => `($1, $${index + 2}, $${sparepartIds.length + 2}, CURRENT_TIMESTAMP)`).join(', ');
|
|
||||||
const queryText = `
|
|
||||||
INSERT INTO brand_sparepart (error_code_id, sparepart_id, created_by, created_at)
|
|
||||||
VALUES ${values}
|
|
||||||
`;
|
|
||||||
const params = [errorCodeId, ...sparepartIds, createdBy];
|
|
||||||
const result = await pool.query(queryText, params);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Delete specific error_code-sparepart relationship
|
|
||||||
const deleteErrorCodeSparepartDb = async (errorCodeId, sparepartId) => {
|
|
||||||
const queryText = `
|
|
||||||
DELETE FROM brand_sparepart
|
|
||||||
WHERE error_code_id = $1 AND sparepart_id = $2
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [errorCodeId, sparepartId]);
|
|
||||||
return result.rowsAffected > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Delete all spareparts for an error_code
|
|
||||||
const deleteAllErrorCodeSparepartsDb = async (errorCodeId) => {
|
|
||||||
const queryText = `
|
|
||||||
DELETE FROM brand_sparepart
|
|
||||||
WHERE error_code_id = $1
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [errorCodeId]);
|
|
||||||
return result.rowsAffected > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update error_code-spareparts (replace all)
|
|
||||||
const updateErrorCodeSparepartsDb = async (errorCodeId, sparepartIds, updatedBy) => {
|
|
||||||
// Delete existing relationships
|
|
||||||
await deleteAllErrorCodeSparepartsDb(errorCodeId);
|
|
||||||
|
|
||||||
// Insert new relationships
|
|
||||||
if (sparepartIds && sparepartIds.length > 0) {
|
|
||||||
return await insertMultipleErrorCodeSparepartsDb(errorCodeId, sparepartIds, updatedBy);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkErrorCodeSparepartExistsDb = async (errorCodeId, sparepartId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT 1
|
|
||||||
FROM brand_spareparts
|
|
||||||
WHERE error_code_id = $1 AND sparepart_id = $2
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [errorCodeId, sparepartId]);
|
|
||||||
return result.recordset.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSparepartsByBrandIdDb = async (brandId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT DISTINCT
|
|
||||||
s.sparepart_id,
|
|
||||||
s.sparepart_name,
|
|
||||||
s.sparepart_code,
|
|
||||||
s.sparepart_description,
|
|
||||||
s.sparepart_model,
|
|
||||||
s.sparepart_foto,
|
|
||||||
s.sparepart_item_type,
|
|
||||||
s.sparepart_qty,
|
|
||||||
s.sparepart_unit,
|
|
||||||
s.sparepart_merk,
|
|
||||||
s.sparepart_stok,
|
|
||||||
s.created_at,
|
|
||||||
s.updated_at
|
|
||||||
FROM brand_sparepart bs
|
|
||||||
JOIN m_sparepart s ON bs.sparepart_id = s.sparepart_id
|
|
||||||
JOIN m_error_codes ec ON bs.error_code_id = ec.error_code_id
|
|
||||||
WHERE ec.brand_id = $1
|
|
||||||
AND s.deleted_at IS NULL
|
|
||||||
AND ec.deleted_at IS NULL
|
|
||||||
ORDER BY s.sparepart_name
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [brandId]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get brands by sparepart_id (now using error_code_id mapping)
|
|
||||||
const getBrandsBySparepartIdDb = async (sparepartId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT DISTINCT
|
|
||||||
b.brand_id,
|
|
||||||
b.brand_name,
|
|
||||||
b.brand_type,
|
|
||||||
b.brand_manufacture,
|
|
||||||
b.brand_model,
|
|
||||||
b.brand_code,
|
|
||||||
b.is_active,
|
|
||||||
b.created_at,
|
|
||||||
b.updated_at
|
|
||||||
FROM brand_sparepart bs
|
|
||||||
JOIN m_sparepart s ON bs.sparepart_id = s.sparepart_id
|
|
||||||
JOIN m_error_codes ec ON bs.error_code_id = ec.error_code_id
|
|
||||||
JOIN m_brands b ON ec.brand_id = b.brand_id
|
|
||||||
WHERE bs.sparepart_id = $1
|
|
||||||
AND s.deleted_at IS NULL
|
|
||||||
AND ec.deleted_at IS NULL
|
|
||||||
AND b.deleted_at IS NULL
|
|
||||||
ORDER BY b.brand_name
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [sparepartId]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Deprecated functions removed - table structure changed to use error_code_id instead of brand_id
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
// New functions using error_code_id
|
|
||||||
getSparepartsByErrorCodeIdDb,
|
|
||||||
getErrorCodesBySparepartIdDb,
|
|
||||||
insertErrorCodeSparepartDb,
|
|
||||||
insertMultipleErrorCodeSparepartsDb,
|
|
||||||
deleteErrorCodeSparepartDb,
|
|
||||||
deleteAllErrorCodeSparepartsDb,
|
|
||||||
updateErrorCodeSparepartsDb,
|
|
||||||
checkErrorCodeSparepartExistsDb,
|
|
||||||
};
|
|
||||||
106
db/contact.db.js
106
db/contact.db.js
@@ -1,106 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all Contact
|
|
||||||
const getAllContactDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"a.contact_name",
|
|
||||||
"a.contact_type",
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.contact_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "a.contact_type", param: searchParams.code, type: "string" },
|
|
||||||
{ column: "a.is_active", param: searchParams.active, type: "boolean" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM contact a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.contact_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getContactByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM contact a
|
|
||||||
WHERE a.contact_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createContactDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("contact", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getContactByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateContactDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { contact_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"contact",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getContactByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete tag
|
|
||||||
const deleteContactDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE contact
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE contact_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllContactDb,
|
|
||||||
getContactByIdDb,
|
|
||||||
createContactDb,
|
|
||||||
updateContactDb,
|
|
||||||
deleteContactDb,
|
|
||||||
};
|
|
||||||
133
db/device.db.js
133
db/device.db.js
@@ -1,133 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all devices
|
|
||||||
const getAllDevicesDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"a.device_name",
|
|
||||||
"a.device_code",
|
|
||||||
"a.device_location",
|
|
||||||
"a.ip_address",
|
|
||||||
"b.brand_name",
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.device_code", param: searchParams.code, type: "string" },
|
|
||||||
{ column: "a.device_location", param: searchParams.location, type: "string" },
|
|
||||||
{ column: "b.brand_name", param: searchParams.brand, type: "string" },
|
|
||||||
{ column: "a.is_active", param: searchParams.status, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
b.brand_name,
|
|
||||||
COALESCE(a.device_code, '') + ' - ' + COALESCE(a.device_name, '') AS device_code_name
|
|
||||||
FROM m_device a
|
|
||||||
LEFT JOIN m_brands b ON a.brand_id = b.brand_id
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? `AND ${whereConditions.join(' AND ')}` : ''}
|
|
||||||
${whereOrConditions ? whereOrConditions : ''}
|
|
||||||
ORDER BY a.device_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const getDeviceByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.brand_name,
|
|
||||||
COALESCE(a.device_code, '') + ' - ' + COALESCE(a.device_name, '') AS device_code_name
|
|
||||||
FROM m_device a
|
|
||||||
LEFT JOIN m_brands b ON a.brand_id = b.brand_id
|
|
||||||
WHERE a.device_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createDeviceDb = async (data) => {
|
|
||||||
const newCode = await pool.generateKode("DVC", "m_device", "device_code");
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
device_code: newCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert(
|
|
||||||
"m_device",
|
|
||||||
store
|
|
||||||
);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId ? await getDeviceByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateDeviceDb = async (id, data) => {
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Kondisi WHERE
|
|
||||||
const whereData = {
|
|
||||||
device_id: id,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_device",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getDeviceByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteDeviceDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_device
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE device_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllDevicesDb,
|
|
||||||
getDeviceByIdDb,
|
|
||||||
createDeviceDb,
|
|
||||||
updateDeviceDb,
|
|
||||||
deleteDeviceDb,
|
|
||||||
};
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get file upload by path
|
|
||||||
const getFileUploadByPathDb = async (path) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
file_upload_id,
|
|
||||||
file_upload_name,
|
|
||||||
type_document,
|
|
||||||
path_document,
|
|
||||||
created_by,
|
|
||||||
updated_by,
|
|
||||||
deleted_by,
|
|
||||||
created_at,
|
|
||||||
updated_at,
|
|
||||||
deleted_at
|
|
||||||
FROM file_upload
|
|
||||||
WHERE path_document = $1 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [path]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create file upload
|
|
||||||
const createFileUploadDb = async (data) => {
|
|
||||||
const store = {
|
|
||||||
file_upload_name: data.file_upload_name,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add path_document if exists
|
|
||||||
if (data.path_document) {
|
|
||||||
store.path_document = data.path_document;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add type_document if exists
|
|
||||||
if (data.type_document) {
|
|
||||||
store.type_document = data.type_document;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.createdBy) {
|
|
||||||
store.created_by = data.createdBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Data to insert:', store);
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
INSERT INTO file_upload (file_upload_name, path_document, type_document, created_by, created_at, updated_at)
|
|
||||||
VALUES ($1, $2, $3, $4, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
|
|
||||||
SELECT SCOPE_IDENTITY() as inserted_id;
|
|
||||||
`;
|
|
||||||
const values = [
|
|
||||||
store.file_upload_name,
|
|
||||||
store.path_document,
|
|
||||||
store.type_document,
|
|
||||||
store.created_by || null
|
|
||||||
];
|
|
||||||
|
|
||||||
// console.log('Manual Query:', queryText);
|
|
||||||
// console.log('Manual Values:', values);
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete file upload by path
|
|
||||||
const deleteFileUploadByPathDb = async (path, deletedBy = null) => {
|
|
||||||
const store = {
|
|
||||||
deleted_at: new Date(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (deletedBy) {
|
|
||||||
store.deleted_by = deletedBy;
|
|
||||||
}
|
|
||||||
|
|
||||||
const whereData = {
|
|
||||||
path_document: path,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"file_upload",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getFileUploadByPathDb,
|
|
||||||
createFileUploadDb,
|
|
||||||
deleteFileUploadByPathDb,
|
|
||||||
};
|
|
||||||
@@ -1,568 +0,0 @@
|
|||||||
const { columns } = require("mssql");
|
|
||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const getHistoryAlarmDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"b.tag_name",
|
|
||||||
"a.tagnum"
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "b.tag_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "b.tag_number", param: searchParams.name, type: "number" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
b.tag_name,
|
|
||||||
b.tag_number,
|
|
||||||
b.lim_low_crash,
|
|
||||||
b.lim_low,
|
|
||||||
b.lim_high,
|
|
||||||
b.lim_high_crash,
|
|
||||||
c.status_color
|
|
||||||
FROM alarm_history a
|
|
||||||
LEFT JOIN m_tags b ON a.tagnum = b.tag_number AND b.deleted_at IS NULL
|
|
||||||
LEFT JOIN m_status c ON a.status = c.status_number AND c.deleted_at IS NULL
|
|
||||||
WHERE a.datetime IS NOT NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.datetime DESC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHistoryEventDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"b.tag_name",
|
|
||||||
"a.tagnum"
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "b.tag_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "b.tag_number", param: searchParams.name, type: "number" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
c.status_color
|
|
||||||
FROM event_alarm a
|
|
||||||
LEFT JOIN m_status c ON a.status = c.status_number AND c.deleted_at IS NULL
|
|
||||||
WHERE a.datetime IS NOT NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.datetime DESC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkTableNamedDb = async (tableName) => {
|
|
||||||
try {
|
|
||||||
if (!tableName || !/^[a-zA-Z0-9_]+$/.test(tableName)) {
|
|
||||||
throw new Error('Invalid table name format');
|
|
||||||
}
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT TABLE_NAME, TABLE_SCHEMA, TABLE_TYPE
|
|
||||||
FROM INFORMATION_SCHEMA.TABLES
|
|
||||||
WHERE TABLE_NAME = $1
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, [tableName]);
|
|
||||||
return result.recordset;
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error in checkTableNamedDb:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHistoryValueReportDb = async (tableName, searchParams = {}) => {
|
|
||||||
try {
|
|
||||||
if (!tableName || !/^[a-zA-Z0-9_]+$/.test(tableName)) {
|
|
||||||
throw new Error('Invalid table name format');
|
|
||||||
}
|
|
||||||
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["b.tag_name", "CAST(a.tagnum AS VARCHAR)"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "b.tag_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "b.tag_number", param: searchParams.name, type: "number" },
|
|
||||||
{ column: "a.datetime", param: [searchParams.from, searchParams.to], type: "between" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
b.tag_name,
|
|
||||||
b.tag_number,
|
|
||||||
b.lim_low_crash,
|
|
||||||
b.lim_low,
|
|
||||||
b.lim_high,
|
|
||||||
b.lim_high_crash,
|
|
||||||
c.status_color
|
|
||||||
FROM ${tableName} a
|
|
||||||
LEFT JOIN m_tags b ON a.tagnum = b.tag_number AND b.deleted_at IS NULL
|
|
||||||
LEFT JOIN m_status c ON a.status = c.status_number AND c.deleted_at IS NULL
|
|
||||||
WHERE a.datetime IS NOT NULL AND b.is_report = 1
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.datetime DESC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total = result.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error in getHistoryValueReportDb:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHistoryValueReportPivotDb = async (tableName, searchParams = {}) => {
|
|
||||||
try {
|
|
||||||
if (!tableName || !/^[a-zA-Z0-9_]+$/.test(tableName)) {
|
|
||||||
throw new Error('Invalid table name format');
|
|
||||||
}
|
|
||||||
|
|
||||||
let from = searchParams.from || '';
|
|
||||||
let to = searchParams.to || '';
|
|
||||||
const interval = Math.max(1, Math.min(1440, Number(searchParams.interval ?? 10)));
|
|
||||||
|
|
||||||
if (from.length === 10 && /^\d{4}-\d{2}-\d{2}$/.test(from)) {
|
|
||||||
from += ' 00:00:00';
|
|
||||||
}
|
|
||||||
if (to.length === 10 && /^\d{4}-\d{2}-\d{2}$/.test(to)) {
|
|
||||||
to += ' 23:59:59';
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Table:', tableName);
|
|
||||||
console.log('From:', from, '| To:', to, '| Interval:', interval);
|
|
||||||
console.log('Filters:', searchParams);
|
|
||||||
|
|
||||||
const dateRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
|
||||||
if (!dateRegex.test(from) || !dateRegex.test(to)) {
|
|
||||||
throw new Error('Invalid date format. Expected: YYYY-MM-DD or YYYY-MM-DD HH:MM:SS');
|
|
||||||
}
|
|
||||||
|
|
||||||
const fromDate = new Date(from);
|
|
||||||
const toDate = new Date(to);
|
|
||||||
const daysDiff = (toDate - fromDate) / (1000 * 60 * 60 * 24);
|
|
||||||
|
|
||||||
if (daysDiff > 365) {
|
|
||||||
throw new Error('Date range cannot exceed 1 year');
|
|
||||||
}
|
|
||||||
if (daysDiff < 0) {
|
|
||||||
throw new Error('From date must be before to date');
|
|
||||||
}
|
|
||||||
|
|
||||||
let tagQueryParams = [];
|
|
||||||
let tagWhereConditions = [];
|
|
||||||
|
|
||||||
if (searchParams.plant_sub_section_id) {
|
|
||||||
tagWhereConditions.push(`plant_sub_section_id = $${tagQueryParams.length + 1}`);
|
|
||||||
tagQueryParams.push(searchParams.plant_sub_section_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchParams.plant_section_id) {
|
|
||||||
tagWhereConditions.push(`plant_section_id = $${tagQueryParams.length + 1}`);
|
|
||||||
tagQueryParams.push(searchParams.plant_section_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchParams.name) {
|
|
||||||
const nameFilter = `(tag_name LIKE $${tagQueryParams.length + 1} OR CAST(tag_number AS VARCHAR) LIKE $${tagQueryParams.length + 2})`;
|
|
||||||
tagWhereConditions.push(nameFilter);
|
|
||||||
tagQueryParams.push(`%${searchParams.name}%`, `%${searchParams.name}%`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchParams.criteria) {
|
|
||||||
const criteriaFilter = `(tag_name LIKE $${tagQueryParams.length + 1} OR CAST(tag_number AS VARCHAR) LIKE $${tagQueryParams.length + 2})`;
|
|
||||||
tagWhereConditions.push(criteriaFilter);
|
|
||||||
tagQueryParams.push(`%${searchParams.criteria}%`, `%${searchParams.criteria}%`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagWhereClause = tagWhereConditions.length > 0
|
|
||||||
? ` AND ${tagWhereConditions.join(" AND ")}`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const tagsQuery = `
|
|
||||||
SELECT tag_name, tag_number
|
|
||||||
FROM m_tags
|
|
||||||
WHERE is_report = 1 AND deleted_at IS NULL
|
|
||||||
${tagWhereClause}
|
|
||||||
ORDER BY tag_name
|
|
||||||
`;
|
|
||||||
|
|
||||||
console.log('Tags Query:', tagsQuery);
|
|
||||||
console.log('Tags Query Params:', tagQueryParams);
|
|
||||||
|
|
||||||
const tagsResult = await pool.query(tagsQuery, tagQueryParams);
|
|
||||||
|
|
||||||
console.log('Tags found:', tagsResult.recordset.length);
|
|
||||||
|
|
||||||
if (tagsResult.recordset.length === 0) {
|
|
||||||
return { data: [], column: '' };
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagNames = tagsResult.recordset.map(r => `[${r.tag_name}]`).join(', ');
|
|
||||||
const tagNamesColumn = tagsResult.recordset.map(r => r.tag_name).join(', ');
|
|
||||||
const tagNumbers = tagsResult.recordset.map(r => r.tag_number);
|
|
||||||
|
|
||||||
console.log('Filtered tag numbers:', tagNumbers);
|
|
||||||
console.log('Filtered tag names:', tagNamesColumn);
|
|
||||||
|
|
||||||
const tagNumbersFilter = tagNumbers.length > 0
|
|
||||||
? ` AND a.tagnum IN (${tagNumbers.join(',')})`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
DECLARE
|
|
||||||
@fromParam DATETIME = $1,
|
|
||||||
@toParam DATETIME = $2,
|
|
||||||
@intervalParam INT = $3;
|
|
||||||
|
|
||||||
SELECT TOP 10
|
|
||||||
'DEBUG_AVERAGING' as info,
|
|
||||||
b.tag_name,
|
|
||||||
DATEADD(MINUTE,
|
|
||||||
(DATEDIFF(MINUTE, @fromParam, CAST(a.datetime AS DATETIME)) / @intervalParam) * @intervalParam,
|
|
||||||
@fromParam
|
|
||||||
) AS waktu_group,
|
|
||||||
COUNT(*) as data_points,
|
|
||||||
AVG(CAST(a.val AS FLOAT)) as avg_val,
|
|
||||||
MIN(CAST(a.val AS FLOAT)) as min_val,
|
|
||||||
MAX(CAST(a.val AS FLOAT)) as max_val
|
|
||||||
FROM ${tableName} a
|
|
||||||
INNER JOIN m_tags b ON a.tagnum = b.tag_number
|
|
||||||
AND b.deleted_at IS NULL
|
|
||||||
AND b.is_report = 1
|
|
||||||
WHERE CAST(a.datetime AS DATETIME) BETWEEN @fromParam AND @toParam
|
|
||||||
AND a.val IS NOT NULL
|
|
||||||
${tagNumbersFilter}
|
|
||||||
GROUP BY
|
|
||||||
b.tag_name,
|
|
||||||
DATEADD(MINUTE,
|
|
||||||
(DATEDIFF(MINUTE, @fromParam, CAST(a.datetime AS DATETIME)) / @intervalParam) * @intervalParam,
|
|
||||||
@fromParam
|
|
||||||
)
|
|
||||||
ORDER BY b.tag_name, waktu_group;
|
|
||||||
|
|
||||||
;WITH TimeSeries AS (
|
|
||||||
SELECT @fromParam AS waktu
|
|
||||||
UNION ALL
|
|
||||||
SELECT DATEADD(MINUTE, @intervalParam, waktu)
|
|
||||||
FROM TimeSeries
|
|
||||||
WHERE DATEADD(MINUTE, @intervalParam, waktu) <= @toParam
|
|
||||||
),
|
|
||||||
CleanData AS (
|
|
||||||
SELECT
|
|
||||||
CAST(a.datetime AS DATETIME) as datetime_clean,
|
|
||||||
a.tagnum,
|
|
||||||
CAST(a.val AS FLOAT) as val,
|
|
||||||
b.tag_name
|
|
||||||
FROM ${tableName} a
|
|
||||||
INNER JOIN m_tags b ON a.tagnum = b.tag_number
|
|
||||||
AND b.deleted_at IS NULL
|
|
||||||
AND b.is_report = 1
|
|
||||||
WHERE ISDATE(a.datetime) = 1
|
|
||||||
AND a.val IS NOT NULL
|
|
||||||
AND CAST(a.datetime AS DATETIME) BETWEEN @fromParam AND @toParam
|
|
||||||
${tagNumbersFilter}
|
|
||||||
),
|
|
||||||
Averaged AS (
|
|
||||||
SELECT
|
|
||||||
DATEADD(MINUTE,
|
|
||||||
(DATEDIFF(MINUTE, @fromParam, datetime_clean) / @intervalParam) * @intervalParam,
|
|
||||||
@fromParam
|
|
||||||
) AS waktu_group,
|
|
||||||
tag_name,
|
|
||||||
AVG(val) AS avg_val
|
|
||||||
FROM CleanData
|
|
||||||
GROUP BY
|
|
||||||
DATEADD(MINUTE,
|
|
||||||
(DATEDIFF(MINUTE, @fromParam, datetime_clean) / @intervalParam) * @intervalParam,
|
|
||||||
@fromParam
|
|
||||||
),
|
|
||||||
tag_name
|
|
||||||
),
|
|
||||||
Pivoted AS (
|
|
||||||
SELECT
|
|
||||||
waktu_group,
|
|
||||||
${tagNames}
|
|
||||||
FROM Averaged
|
|
||||||
PIVOT (
|
|
||||||
MAX(avg_val)
|
|
||||||
FOR tag_name IN (${tagNames})
|
|
||||||
) AS p
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
CONVERT(VARCHAR(19), ts.waktu, 120) AS waktu,
|
|
||||||
${tagNames}
|
|
||||||
FROM TimeSeries ts
|
|
||||||
LEFT JOIN Pivoted p ON ts.waktu = p.waktu_group
|
|
||||||
ORDER BY ts.waktu
|
|
||||||
OPTION (MAXRECURSION 0);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, [from, to, interval]);
|
|
||||||
|
|
||||||
if (result.recordsets && result.recordsets.length >= 2) {
|
|
||||||
console.log('Sample averaging data:');
|
|
||||||
result.recordsets[0].slice(0, 10).forEach(row => {
|
|
||||||
console.log(`${row.tag_name} @ ${row.waktu_group}: avg=${row.avg_val}, min=${row.min_val}, max=${row.max_val}, points=${row.data_points}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log('\nPivot result sample:');
|
|
||||||
if (result.recordsets[1] && result.recordsets[1].length > 0) {
|
|
||||||
result.recordsets[1].slice(0, 5).forEach(row => {
|
|
||||||
console.log(JSON.stringify(row, null, 2));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const rows = result.recordsets?.[1] || result.recordset;
|
|
||||||
|
|
||||||
if (!rows || rows.length === 0) {
|
|
||||||
console.log('No pivot data');
|
|
||||||
return { data: [], column: tagNamesColumn };
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeKey = 'waktu';
|
|
||||||
const tagList = Object.keys(rows[0]).filter(k => k !== timeKey);
|
|
||||||
|
|
||||||
const nivoData = tagList.map(tag => ({
|
|
||||||
id: tag,
|
|
||||||
data: rows.map(row => ({
|
|
||||||
x: row[timeKey],
|
|
||||||
y: row[tag] !== null && row[tag] !== undefined ? Number(row[tag]) : null
|
|
||||||
}))
|
|
||||||
}));
|
|
||||||
|
|
||||||
nivoData.forEach(series => {
|
|
||||||
const nonNull = series.data.filter(d => d.y !== null && d.y !== 0);
|
|
||||||
const sampleVals = nonNull.slice(0, 3).map(d => d.y);
|
|
||||||
console.log(`${series.id}: ${nonNull.length} non-zero values, sample: [${sampleVals.join(', ')}]`);
|
|
||||||
});
|
|
||||||
|
|
||||||
return { data: nivoData, column: tagNamesColumn };
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error in getHistoryValueReportPivotDb:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getHistoryValueTrendingPivotDb = async (tableName, searchParams = {}) => {
|
|
||||||
let from = searchParams.from;
|
|
||||||
let to = searchParams.to;
|
|
||||||
|
|
||||||
// pastikan interval berupa number dan ada nilai default
|
|
||||||
const interval = Number(searchParams.interval) > 0 ? Number(searchParams.interval) : 10;
|
|
||||||
|
|
||||||
// --- Normalisasi tanggal (kalau cuma tanggal tanpa jam)
|
|
||||||
if (from.length === 10) from += ' 00:00:00';
|
|
||||||
if (to.length === 10) to += ' 23:59:59';
|
|
||||||
|
|
||||||
let tagQueryParams = [];
|
|
||||||
let tagWhereConditions = [];
|
|
||||||
|
|
||||||
if (searchParams.plant_sub_section_id) {
|
|
||||||
tagWhereConditions.push(`plant_sub_section_id = $${tagQueryParams.length + 1}`);
|
|
||||||
tagQueryParams.push(searchParams.plant_sub_section_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchParams.plant_section_id) {
|
|
||||||
tagWhereConditions.push(`plant_section_id = $${tagQueryParams.length + 1}`);
|
|
||||||
tagQueryParams.push(searchParams.plant_section_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchParams.name) {
|
|
||||||
const nameFilter = `(tag_name LIKE $${tagQueryParams.length + 1} OR CAST(tag_number AS VARCHAR) LIKE $${tagQueryParams.length + 2})`;
|
|
||||||
tagWhereConditions.push(nameFilter);
|
|
||||||
tagQueryParams.push(`%${searchParams.name}%`, `%${searchParams.name}%`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchParams.criteria) {
|
|
||||||
const criteriaFilter = `(tag_name LIKE $${tagQueryParams.length + 1} OR CAST(tag_number AS VARCHAR) LIKE $${tagQueryParams.length + 2})`;
|
|
||||||
tagWhereConditions.push(criteriaFilter);
|
|
||||||
tagQueryParams.push(`%${searchParams.criteria}%`, `%${searchParams.criteria}%`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagWhereClause = tagWhereConditions.length > 0
|
|
||||||
? ` AND ${tagWhereConditions.join(" AND ")}`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const tagsQuery = `
|
|
||||||
SELECT tag_name, tag_number
|
|
||||||
FROM m_tags
|
|
||||||
WHERE is_report = 1 AND deleted_at IS NULL
|
|
||||||
${tagWhereClause}
|
|
||||||
ORDER BY tag_name
|
|
||||||
`;
|
|
||||||
|
|
||||||
const tags = await pool.query(tagsQuery, tagQueryParams);
|
|
||||||
|
|
||||||
if (tags.recordset.length === 0) {
|
|
||||||
return { data: [] };
|
|
||||||
}
|
|
||||||
|
|
||||||
const tagNames = tags.recordset.map(r => `[${r.tag_name}]`).join(', ');
|
|
||||||
const tagNumbers = tags.recordset.map(r => r.tag_number);
|
|
||||||
|
|
||||||
const tagNumbersFilter = tagNumbers.length > 0
|
|
||||||
? ` AND a.tagnum IN (${tagNumbers.join(',')})`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
DECLARE
|
|
||||||
@fromParam DATETIME = '${from}',
|
|
||||||
@toParam DATETIME = '${to}',
|
|
||||||
@intervalParam INT = ${interval};
|
|
||||||
|
|
||||||
;WITH TimeSeries AS (
|
|
||||||
SELECT @fromParam AS waktu
|
|
||||||
UNION ALL
|
|
||||||
SELECT DATEADD(MINUTE, @intervalParam, waktu)
|
|
||||||
FROM TimeSeries
|
|
||||||
WHERE DATEADD(MINUTE, @intervalParam, waktu) <= @toParam
|
|
||||||
),
|
|
||||||
Averaged AS (
|
|
||||||
SELECT
|
|
||||||
DATEADD(MINUTE, DATEDIFF(MINUTE, 0, CAST(a.datetime AS DATETIME)) / @intervalParam * @intervalParam, 0) AS waktu_group,
|
|
||||||
b.tag_name,
|
|
||||||
ROUND(AVG(a.val), 4) AS avg_val
|
|
||||||
FROM ${tableName} a
|
|
||||||
LEFT JOIN m_tags b ON a.tagnum = b.tag_number AND b.deleted_at IS NULL
|
|
||||||
WHERE a.datetime BETWEEN @fromParam AND @toParam
|
|
||||||
${tagNumbersFilter}
|
|
||||||
GROUP BY
|
|
||||||
DATEADD(MINUTE, DATEDIFF(MINUTE, 0, CAST(a.datetime AS DATETIME)) / @intervalParam * @intervalParam, 0),
|
|
||||||
b.tag_name
|
|
||||||
),
|
|
||||||
Pivoted AS (
|
|
||||||
SELECT
|
|
||||||
waktu_group,
|
|
||||||
${tagNames}
|
|
||||||
FROM Averaged
|
|
||||||
PIVOT (
|
|
||||||
MAX(avg_val)
|
|
||||||
FOR tag_name IN (${tagNames})
|
|
||||||
) AS p
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
CONVERT(VARCHAR(16), ts.waktu, 120) AS waktu,
|
|
||||||
${tagNames}
|
|
||||||
FROM TimeSeries ts
|
|
||||||
LEFT JOIN Pivoted p ON ts.waktu = p.waktu_group
|
|
||||||
ORDER BY ts.waktu
|
|
||||||
OPTION (MAXRECURSION 0);
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText);
|
|
||||||
const rows = result.recordset;
|
|
||||||
|
|
||||||
if (!rows || rows.length === 0) return { data: [] };
|
|
||||||
|
|
||||||
// --- Bentuk data untuk Nivo Chart
|
|
||||||
const timeKey = 'waktu';
|
|
||||||
const tagList = Object.keys(rows[0]).filter(k => k !== timeKey);
|
|
||||||
|
|
||||||
const nivoData = tagList.map(tag => ({
|
|
||||||
id: tag,
|
|
||||||
data: rows.map(row => ({
|
|
||||||
x: row[timeKey],
|
|
||||||
y: row[tag] !== null ? Number(row[tag]) : null
|
|
||||||
}))
|
|
||||||
}));
|
|
||||||
|
|
||||||
return { data: nivoData };
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getHistoryAlarmDb,
|
|
||||||
getHistoryEventDb,
|
|
||||||
checkTableNamedDb,
|
|
||||||
getHistoryValueReportDb,
|
|
||||||
getHistoryValueReportPivotDb,
|
|
||||||
getHistoryValueTrendingPivotDb
|
|
||||||
};
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const InsertNotificationErrorDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert(
|
|
||||||
"notification_error",
|
|
||||||
store
|
|
||||||
);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getNotificationByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotificationByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.plant_sub_section_id,
|
|
||||||
c.plant_sub_section_name,
|
|
||||||
d.device_code,
|
|
||||||
d.device_name,
|
|
||||||
d.device_location,
|
|
||||||
d.listen_channel,
|
|
||||||
e.brand_name
|
|
||||||
|
|
||||||
FROM notification_error a
|
|
||||||
|
|
||||||
LEFT JOIN m_tags b
|
|
||||||
ON a.error_chanel = b.tag_number
|
|
||||||
|
|
||||||
LEFT JOIN m_plant_sub_section c
|
|
||||||
ON b.plant_sub_section_id = c.plant_sub_section_id
|
|
||||||
|
|
||||||
LEFT JOIN m_device d
|
|
||||||
ON a.error_chanel = d.listen_channel AND d.deleted_at IS NULL
|
|
||||||
|
|
||||||
LEFT JOIN m_brands e
|
|
||||||
ON d.brand_id = e.brand_id AND d.deleted_at IS NULL
|
|
||||||
|
|
||||||
WHERE a.notification_error_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDeviceNotificationByIdDb = async (chanel_id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
brand_id,
|
|
||||||
device_code,
|
|
||||||
device_name,
|
|
||||||
device_location,
|
|
||||||
listen_channel
|
|
||||||
|
|
||||||
FROM m_device
|
|
||||||
WHERE listen_channel = $1
|
|
||||||
AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [chanel_id]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const getAllNotificationDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"a.message_error_issue",
|
|
||||||
"a.is_send",
|
|
||||||
"a.is_delivered",
|
|
||||||
"a.is_read",
|
|
||||||
"a.is_active",
|
|
||||||
"b.error_code",
|
|
||||||
"b.error_code_name",
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.message_error_issue", param: searchParams.message_error_issue, type: "string" },
|
|
||||||
{ column: "a.is_send", param: searchParams.is_send, type: "number" },
|
|
||||||
{ column: "a.is_delivered", param: searchParams.is_delivered, type: "number" },
|
|
||||||
{ column: "a.is_read", param: searchParams.is_read, type: "number" },
|
|
||||||
{ column: "a.is_active", param: searchParams.is_active, type: "number" },
|
|
||||||
{ column: "b.error_code", param: searchParams.error_code, type: "string" },
|
|
||||||
{ column: "b.error_code_name", param: searchParams.error_code_name, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
|
|
||||||
a.notification_error_id,
|
|
||||||
a.error_code_id,
|
|
||||||
a.message_error_issue,
|
|
||||||
a.is_send,
|
|
||||||
a.is_delivered,
|
|
||||||
a.is_read,
|
|
||||||
a.is_active,
|
|
||||||
a.created_at,
|
|
||||||
|
|
||||||
b.error_code,
|
|
||||||
b.error_code_name,
|
|
||||||
b.error_code_color,
|
|
||||||
b.path_icon,
|
|
||||||
|
|
||||||
c.solution_name,
|
|
||||||
c.type_solution,
|
|
||||||
c.path_solution,
|
|
||||||
|
|
||||||
d.device_code,
|
|
||||||
d.device_name,
|
|
||||||
d.device_location,
|
|
||||||
d.listen_channel,
|
|
||||||
e.brand_name,
|
|
||||||
|
|
||||||
COALESCE(d.device_name, '') + ' - ' + COALESCE(b.error_code_name, '') AS device_name_error
|
|
||||||
|
|
||||||
FROM notification_error a
|
|
||||||
|
|
||||||
LEFT JOIN m_device d
|
|
||||||
ON a.error_chanel = d.listen_channel AND d.deleted_at IS NULL
|
|
||||||
|
|
||||||
LEFT JOIN brand_code b
|
|
||||||
ON a.error_code_id = b.error_code AND b.deleted_at IS NULL AND d.brand_id = b.brand_id
|
|
||||||
|
|
||||||
LEFT JOIN brand_code_solution c
|
|
||||||
ON b.error_code_id = c.error_code_id AND c.deleted_at IS NULL
|
|
||||||
|
|
||||||
LEFT JOIN m_brands e
|
|
||||||
ON d.brand_id = e.brand_id AND e.deleted_at IS NULL
|
|
||||||
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
|
|
||||||
ORDER BY a.notification_error_id DESC
|
|
||||||
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ""}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateNotificationErrorDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { notification_error_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"notification_error",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getNotificationByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getUsersNotificationErrorDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
b.notification_error_id,
|
|
||||||
a.notification_error_user_id,
|
|
||||||
a.contact_phone,
|
|
||||||
a.contact_name,
|
|
||||||
a.is_send,
|
|
||||||
a.updated_at,
|
|
||||||
c.is_active
|
|
||||||
|
|
||||||
FROM notification_error_user a
|
|
||||||
|
|
||||||
LEFT JOIN notification_error b ON a.notification_error_id = b.notification_error_id
|
|
||||||
|
|
||||||
LEFT JOIN contact c ON a.contact_phone = c.contact_phone
|
|
||||||
|
|
||||||
WHERE a.notification_error_id = $1
|
|
||||||
AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getNotificationByIdDb,
|
|
||||||
getDeviceNotificationByIdDb,
|
|
||||||
getAllNotificationDb,
|
|
||||||
InsertNotificationErrorDb,
|
|
||||||
updateNotificationErrorDb,
|
|
||||||
getUsersNotificationErrorDb
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const getAllNotificationErrorLogDb = async () => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.contact_name,
|
|
||||||
b.contact_type
|
|
||||||
FROM notification_error_log a
|
|
||||||
LEFT JOIN contact b ON a.contact_phone = b.contact_phone
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
ORDER BY a.notification_error_log_id DESC
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotificationErrorLogByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.contact_name,
|
|
||||||
b.contact_type
|
|
||||||
FROM notification_error_log a
|
|
||||||
LEFT JOIN contact b ON a.contact_phone = b.contact_phone
|
|
||||||
WHERE a.notification_error_log_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotificationErrorLogByNotificationErrorIdDb = async (notificationErrorId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.notification_error_log_description,
|
|
||||||
a.created_at,
|
|
||||||
b.contact_type,
|
|
||||||
c.user_fullname as created_by_name,
|
|
||||||
case when a.created_by is not null then c.user_fullname else b.contact_name end as contact_name,
|
|
||||||
case when a.created_by is not null then c.user_phone else a.contact_phone end as contact_phone
|
|
||||||
FROM notification_error_log a
|
|
||||||
LEFT JOIN contact b ON a.contact_phone = b.contact_phone
|
|
||||||
LEFT JOIN m_users c ON a.created_by = c.user_id
|
|
||||||
WHERE a.notification_error_id = $1 AND a.deleted_at IS NULL
|
|
||||||
ORDER BY a.created_at DESC
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [notificationErrorId]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createNotificationErrorLogDb = async (store) => {
|
|
||||||
const queryText = `
|
|
||||||
INSERT INTO notification_error_log (
|
|
||||||
notification_error_id,
|
|
||||||
contact_phone,
|
|
||||||
notification_error_log_description,
|
|
||||||
created_by,
|
|
||||||
updated_by,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
)
|
|
||||||
VALUES ($1, $2, $3, $4, $4, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
|
|
||||||
SELECT SCOPE_IDENTITY() as inserted_id;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const values = [
|
|
||||||
store.notification_error_id,
|
|
||||||
store.contact_phone,
|
|
||||||
store.notification_error_log_description,
|
|
||||||
store.created_by
|
|
||||||
];
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId ? await getNotificationErrorLogByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteNotificationErrorLogDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE notification_error_log
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE notification_error_log_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllNotificationErrorLogDb,
|
|
||||||
getNotificationErrorLogByIdDb,
|
|
||||||
getNotificationErrorLogByNotificationErrorIdDb,
|
|
||||||
createNotificationErrorLogDb,
|
|
||||||
deleteNotificationErrorLogDb,
|
|
||||||
};
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const insertNotificationErrorSparepartDb = async () => {
|
|
||||||
const insertQuery = `
|
|
||||||
INSERT INTO notification_error_sparepart (
|
|
||||||
notification_error_id,
|
|
||||||
brand_sparepart_id
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
ne.notification_error_id,
|
|
||||||
bs.brand_sparepart_id
|
|
||||||
|
|
||||||
FROM notification_error ne
|
|
||||||
|
|
||||||
INNER JOIN brand_sparepart bs
|
|
||||||
ON ne.error_code_id = bs.error_code_id
|
|
||||||
|
|
||||||
LEFT JOIN notification_error_sparepart nes
|
|
||||||
ON nes.notification_error_id = ne.notification_error_id
|
|
||||||
AND nes.brand_sparepart_id = bs.brand_sparepart_id
|
|
||||||
AND nes.deleted_at IS NULL
|
|
||||||
|
|
||||||
WHERE ne.deleted_at IS NULL
|
|
||||||
AND nes.notification_error_sparepart_id IS NULL;
|
|
||||||
`;
|
|
||||||
|
|
||||||
await pool.query(insertQuery);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAllNotificationErrorSparepartDb = async (searchParams = {}) => {
|
|
||||||
await insertNotificationErrorSparepartDb();
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"a.brand_sparepart_id",
|
|
||||||
"a.device_id",
|
|
||||||
"a.sparepart_id",
|
|
||||||
"b.sparepart_name",
|
|
||||||
"d.device_name",
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.brand_sparepart_id", param: searchParams.name, type: "int" },
|
|
||||||
{ column: "a.device_id", param: searchParams.code, type: "int" },
|
|
||||||
{ column: "a.unit", param: searchParams.unit, type: "string" },
|
|
||||||
{ column: "b.sparepart_name", param: searchParams.device, type: "string" },
|
|
||||||
{ column: "d.device_name", param: searchParams.device, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
b.sparepart_name,
|
|
||||||
b.sparepart_foto,
|
|
||||||
b.sparepart_stok,
|
|
||||||
b.sparepart_qty,
|
|
||||||
b.sparepart_description,
|
|
||||||
b.sparepart_model,
|
|
||||||
b.sparepart_merk,
|
|
||||||
b.sparepart_unit,
|
|
||||||
b.sparepart_item_type,
|
|
||||||
d.device_name
|
|
||||||
|
|
||||||
FROM notification_error_sparepart a
|
|
||||||
|
|
||||||
LEFT JOIN brand_sparepart c ON a.brand_sparepart_id = c.brand_sparepart_id
|
|
||||||
|
|
||||||
LEFT JOIN m_sparepart b ON c.sparepart_id = b.sparepart_id
|
|
||||||
|
|
||||||
LEFT JOIN m_device d on c.device_id = d.device_id
|
|
||||||
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.notification_error_sparepart_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotificationErrorSparepartByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.sparepart_name,
|
|
||||||
b.sparepart_foto,
|
|
||||||
b.sparepart_stok,
|
|
||||||
b.sparepart_qty,
|
|
||||||
b.sparepart_description,
|
|
||||||
b.sparepart_model,
|
|
||||||
b.sparepart_merk,
|
|
||||||
b.sparepart_unit,
|
|
||||||
b.sparepart_item_type,
|
|
||||||
d.device_name
|
|
||||||
|
|
||||||
FROM notification_error_sparepart a
|
|
||||||
|
|
||||||
LEFT JOIN brand_sparepart c ON a.brand_sparepart_id = c.brand_sparepart_id
|
|
||||||
|
|
||||||
LEFT JOIN m_sparepart b ON c.sparepart_id = b.sparepart_id
|
|
||||||
|
|
||||||
LEFT JOIN m_device d on c.device_id = d.device_id
|
|
||||||
|
|
||||||
WHERE a.notification_error_sparepart_id = $1
|
|
||||||
AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset?.[0] || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const createNotificationErrorSparepartDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("notification_error_sparepart", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getNotificationErrorSparepartByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateNotificationErrorSparepartDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { notification_error_sparepart_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"notification_error_sparepart",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getNotificationErrorSparepartByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete tag
|
|
||||||
const deleteNotificationErrorSparepartDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE notification_error_sparepart
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE notification_error_sparepart_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllNotificationErrorSparepartDb,
|
|
||||||
getNotificationErrorSparepartByIdDb,
|
|
||||||
createNotificationErrorSparepartDb,
|
|
||||||
updateNotificationErrorSparepartDb,
|
|
||||||
deleteNotificationErrorSparepartDb,
|
|
||||||
};
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all Notification
|
|
||||||
const getAllNotificationErrorUserDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.notification_error_id", "a.contact_id"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
column: "a.notification_error_id",
|
|
||||||
param: searchParams.name,
|
|
||||||
type: "int",
|
|
||||||
},
|
|
||||||
{ column: "a.contact_id", param: searchParams.code, type: "int" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM notification_error_user a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${
|
|
||||||
whereConditions.length > 0
|
|
||||||
? ` AND ${whereConditions.join(" AND ")}`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.notification_error_user_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ""}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotificationErrorUserByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
|
|
||||||
b. is_active as contact_is_active,
|
|
||||||
|
|
||||||
d.error_code,
|
|
||||||
d.error_code_name,
|
|
||||||
|
|
||||||
e.device_name
|
|
||||||
|
|
||||||
FROM notification_error_user a
|
|
||||||
|
|
||||||
LEFT JOIN contact b ON a.contact_phone = b.contact_phone
|
|
||||||
|
|
||||||
LEFT JOIN notification_error c ON a.notification_error_id = c.notification_error_id
|
|
||||||
|
|
||||||
LEFT JOIN brand_code d ON d.error_code_id = c.error_code_id
|
|
||||||
|
|
||||||
LEFT JOIN m_device e ON c.error_chanel = e.listen_channel
|
|
||||||
|
|
||||||
WHERE a.notification_error_user_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getNotificationErrorByIdDb = async (notification_error_id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.is_active as contact_is_active,
|
|
||||||
c.is_read
|
|
||||||
|
|
||||||
FROM notification_error_user a
|
|
||||||
LEFT JOIN contact b ON a.contact_phone = b.contact_phone
|
|
||||||
LEFT JOIN notification_error c ON a.notification_error_id = c.notification_error_id
|
|
||||||
WHERE a.notification_error_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [notification_error_id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createNotificationErrorUserDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert(
|
|
||||||
"notification_error_user",
|
|
||||||
store
|
|
||||||
);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getNotificationErrorUserByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateNotificationErrorUserDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { notification_error_user_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"notification_error_user",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getNotificationErrorUserByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete tag
|
|
||||||
const deleteNotificationErrorUserDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE notification_error_user
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE notification_error_user_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllNotificationErrorUserDb,
|
|
||||||
getNotificationErrorUserByIdDb,
|
|
||||||
getNotificationErrorByIdDb,
|
|
||||||
createNotificationErrorUserDb,
|
|
||||||
updateNotificationErrorUserDb,
|
|
||||||
deleteNotificationErrorUserDb,
|
|
||||||
};
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
// db/notification_wa.db.js
|
|
||||||
const { default: axios } = require('axios');
|
|
||||||
const CryptoJS = require('crypto-js');
|
|
||||||
const https = require('https');
|
|
||||||
|
|
||||||
const httpsAgent = new https.Agent({
|
|
||||||
rejectUnauthorized: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const generateTokenRedirect = async (userPhone, userName, id) => {
|
|
||||||
|
|
||||||
const plain = {
|
|
||||||
user_phone: userPhone,
|
|
||||||
user_name: userName,
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokenCrypt = CryptoJS.AES.encrypt(JSON.stringify(plain), process.env.VITE_KEY_SESSION).toString();
|
|
||||||
return tokenCrypt
|
|
||||||
}
|
|
||||||
|
|
||||||
const shortUrltiny = async (encodedToken) => {
|
|
||||||
const url = `${process.env.ENDPOINT_FE}/redirect?token=${encodedToken}`
|
|
||||||
|
|
||||||
const encodedUrl = encodeURIComponent(url); // ⬅️ Encode dulu!
|
|
||||||
|
|
||||||
const response = await axios.get(`https://tinyurl.com/api-create.php?url=${encodedUrl}`, { httpsAgent });
|
|
||||||
|
|
||||||
let shortUrl = response.data;
|
|
||||||
if (!shortUrl.startsWith('http')) {
|
|
||||||
shortUrl = 'https://' + shortUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return shortUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
const sendNotifikasi = async (phone, message) => {
|
|
||||||
const payload = {
|
|
||||||
phone: phone,
|
|
||||||
message: message
|
|
||||||
};
|
|
||||||
|
|
||||||
// console.log('payload', payload);
|
|
||||||
|
|
||||||
const endPointWhatsapp = process.env.ENDPOINT_WHATSAPP;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios.post(endPointWhatsapp, payload, { httpsAgent });
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
statusCode: response.status, // 200, 201, dll
|
|
||||||
data: response.data
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
statusCode: error.response?.status || null,
|
|
||||||
errorCode: error.code || null, // ECONNABORTED, dll
|
|
||||||
message: error.response?.data || error.message
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
generateTokenRedirect,
|
|
||||||
shortUrltiny,
|
|
||||||
sendNotifikasi,
|
|
||||||
};
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all sub sections
|
|
||||||
const getAllSubSectionsDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// OR condition (pencarian bebas)
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.plant_sub_section_code", "a.plant_sub_section_name"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ?? queryParams;
|
|
||||||
|
|
||||||
// AND condition (filter spesifik)
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.plant_sub_section_code", param: searchParams.code, type: "string" },
|
|
||||||
{ column: "a.plant_sub_section_name", param: searchParams.name, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ?? queryParams;
|
|
||||||
|
|
||||||
// Query utama
|
|
||||||
const queryText = `
|
|
||||||
SELECT COUNT(*) OVER() AS total_data, a.*
|
|
||||||
FROM m_plant_sub_section a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? whereOrConditions : ""}
|
|
||||||
ORDER BY a.plant_sub_section_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
const total =
|
|
||||||
result?.recordset.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get sub section by ID
|
|
||||||
const getSubSectionByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT a.*
|
|
||||||
FROM m_plant_sub_section a
|
|
||||||
WHERE a.plant_sub_section_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create new sub section
|
|
||||||
const createSubSectionDb = async (data) => {
|
|
||||||
// Generate kode otomatis
|
|
||||||
const newCode = await pool.generateKode("SUB", "m_plant_sub_section", "plant_sub_section_code");
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
plant_sub_section_code: newCode
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_plant_sub_section", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getSubSectionByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update sub section
|
|
||||||
const updateSubSectionDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { plant_sub_section_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate("m_plant_sub_section", store, whereData);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
|
|
||||||
return getSubSectionByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete sub section
|
|
||||||
const deleteSubSectionDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_plant_sub_section
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE plant_sub_section_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllSubSectionsDb,
|
|
||||||
getSubSectionByIdDb,
|
|
||||||
createSubSectionDb,
|
|
||||||
updateSubSectionDb,
|
|
||||||
deleteSubSectionDb,
|
|
||||||
};
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const getAllRolesDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Handle pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.role_name", "a.role_level", "a.role_description"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.role_name", param: searchParams.role_name, type: "string" },
|
|
||||||
{ column: "a.role_level", param: searchParams.start_time, type: "string" },
|
|
||||||
{ column: "a.role_description", param: searchParams.role_description, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM m_roles a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.role_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getRolesByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM m_roles a
|
|
||||||
WHERE a.role_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset?.[0] || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const insertRolesDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_roles", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getRolesByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateRolesDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { role_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_roles",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getRolesByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteRolesDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_roles
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE role_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllRolesDb,
|
|
||||||
getRolesByIdDb,
|
|
||||||
insertRolesDb,
|
|
||||||
updateRolesDb,
|
|
||||||
deleteRolesDb,
|
|
||||||
};
|
|
||||||
@@ -1,168 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
const { formattedDate } = require("../utils/date");
|
|
||||||
|
|
||||||
const normalizeClause = (clause) => {
|
|
||||||
if (!clause) return "";
|
|
||||||
return clause.replace(/^\s*(?:AND|WHERE)\s*/i, "").trim();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAllScheduleDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.schedule_date"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
column: "a.schedule_date",
|
|
||||||
param: searchParams.name,
|
|
||||||
type: "date",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const { whereDateCondition, whereDateParams } = pool.buildDateFilter(
|
|
||||||
"a.schedule_date",
|
|
||||||
searchParams.dateType,
|
|
||||||
searchParams.dateValue,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereDateParams) queryParams = whereDateParams;
|
|
||||||
|
|
||||||
const whereParts = [];
|
|
||||||
|
|
||||||
whereParts.push("a.deleted_at IS NULL");
|
|
||||||
|
|
||||||
if (Array.isArray(whereConditions) && whereConditions.length > 0) {
|
|
||||||
const joined = whereConditions.join(" AND ");
|
|
||||||
const norm = normalizeClause(joined);
|
|
||||||
if (norm) whereParts.push(norm);
|
|
||||||
} else if (typeof whereConditions === "string" && whereConditions.trim()) {
|
|
||||||
const norm = normalizeClause(whereConditions);
|
|
||||||
if (norm) whereParts.push(norm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whereOrConditions && String(whereOrConditions).trim()) {
|
|
||||||
const norm = normalizeClause(whereOrConditions);
|
|
||||||
if (norm) whereParts.push(norm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (whereDateCondition && String(whereDateCondition).trim()) {
|
|
||||||
const norm = normalizeClause(whereDateCondition);
|
|
||||||
if (norm) whereParts.push(norm);
|
|
||||||
}
|
|
||||||
|
|
||||||
const whereClause =
|
|
||||||
whereParts.length > 0 ? `WHERE ${whereParts.join(" AND ")}` : "";
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
b.shift_name,
|
|
||||||
b.start_time,
|
|
||||||
b.end_time
|
|
||||||
FROM schedule a
|
|
||||||
LEFT JOIN m_shift b ON a.shift_id = b.shift_id
|
|
||||||
${whereClause}
|
|
||||||
ORDER BY a.schedule_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ""}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get by ID
|
|
||||||
const getScheduleByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.shift_name,
|
|
||||||
b.start_time,
|
|
||||||
b.end_time
|
|
||||||
FROM schedule a
|
|
||||||
LEFT JOIN m_shift b ON a.shift_id = b.shift_id
|
|
||||||
WHERE a.schedule_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset?.[0] || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Insert (bisa multi hari)
|
|
||||||
const insertScheduleDb = async (store) => {
|
|
||||||
const nextDays = Number(store.next_day ?? 0);
|
|
||||||
const insertedRecords = [];
|
|
||||||
|
|
||||||
for (let i = 0; i <= nextDays; i++) {
|
|
||||||
const nextDate = new Date(store.schedule_date);
|
|
||||||
nextDate.setDate(nextDate.getDate() + i);
|
|
||||||
|
|
||||||
const formatted = formattedDate(nextDate);
|
|
||||||
const newStore = { ...store, schedule_date: formatted };
|
|
||||||
delete newStore.next_day;
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("schedule", newStore);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
if (insertedId) {
|
|
||||||
const record = await getScheduleByIdDb(insertedId);
|
|
||||||
insertedRecords.push(record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return insertedRecords;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update
|
|
||||||
const updateScheduleDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { schedule_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"schedule",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getScheduleByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete
|
|
||||||
const deleteScheduleDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE schedule
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE schedule_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllScheduleDb,
|
|
||||||
getScheduleByIdDb,
|
|
||||||
insertScheduleDb,
|
|
||||||
updateScheduleDb,
|
|
||||||
deleteScheduleDb,
|
|
||||||
};
|
|
||||||
100
db/shift.db.js
100
db/shift.db.js
@@ -1,100 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const getAllShiftDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Handle pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.shift_name", "a.start_time", "a.end_time"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.shift_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "a.start_time", param: searchParams.start_time, type: "time" },
|
|
||||||
{ column: "a.end_time", param: searchParams.end_time, type: "time" },
|
|
||||||
{ column: "a.is_active", param: searchParams.status, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM m_shift a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.shift_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getShiftByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*
|
|
||||||
FROM m_shift a
|
|
||||||
WHERE a.shift_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset?.[0] || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const insertShiftDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_shift", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getShiftByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateShiftDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { shift_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_shift",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getShiftByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteShiftDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_shift
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE shift_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllShiftDb,
|
|
||||||
getShiftByIdDb,
|
|
||||||
insertShiftDb,
|
|
||||||
updateShiftDb,
|
|
||||||
deleteShiftDb,
|
|
||||||
};
|
|
||||||
@@ -1,187 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all devices
|
|
||||||
const getAllSparepartDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"a.sparepart_name",
|
|
||||||
"a.sparepart_code",
|
|
||||||
"a.sparepart_model",
|
|
||||||
"a.updated_at",
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.sparepart_name", param: searchParams.code, type: "string" },
|
|
||||||
{
|
|
||||||
column: "a.sparepart_code",
|
|
||||||
param: searchParams.location,
|
|
||||||
type: "string",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
column: "b.sparepart_model",
|
|
||||||
param: searchParams.brand,
|
|
||||||
type: "string",
|
|
||||||
},
|
|
||||||
{ column: "a.updated_at", param: searchParams.status, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
COALESCE(a.sparepart_code, '') + ' - ' + COALESCE(a.sparepart_name, '') AS sparepart_code_name
|
|
||||||
FROM m_sparepart a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${
|
|
||||||
whereConditions.length > 0 ? `AND ${whereConditions.join(" AND ")}` : ""
|
|
||||||
}
|
|
||||||
${whereOrConditions ? whereOrConditions : ""}
|
|
||||||
ORDER BY a.sparepart_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ""}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSparepartByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
COALESCE(a.sparepart_code, '') + ' - ' + COALESCE(a.sparepart_name, '') AS sparepart_code_name
|
|
||||||
FROM m_sparepart a
|
|
||||||
WHERE a.sparepart_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkSparepartNameExistsDb = async (sparePartName, excludeId = null) => {
|
|
||||||
let queryText = `
|
|
||||||
SELECT sparepart_id
|
|
||||||
FROM m_sparepart
|
|
||||||
WHERE sparepart_name = $1 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
let values = [sparePartName];
|
|
||||||
if (excludeId) {
|
|
||||||
queryText += ` AND sparepart_id != $2`;
|
|
||||||
values.push(excludeId);
|
|
||||||
}
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
return result.recordset.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createSparepartDb = async (data) => {
|
|
||||||
const newCode = await pool.generateKode(
|
|
||||||
"SPAREPART",
|
|
||||||
"m_sparepart",
|
|
||||||
"sparepart_code"
|
|
||||||
);
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
sparepart_code: newCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert(
|
|
||||||
"m_sparepart",
|
|
||||||
store
|
|
||||||
);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId ? await getSparepartByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateSparepartDb = async (id, data) => {
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Kondisi WHERE
|
|
||||||
const whereData = {
|
|
||||||
sparepart_id: id,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_sparepart",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getSparepartByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteSparepartDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_sparepart
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE sparepart_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get multiple spareparts by IDs
|
|
||||||
const getSparepartsByIdsDb = async (sparepartIds) => {
|
|
||||||
if (!sparepartIds || sparepartIds.length === 0) return [];
|
|
||||||
|
|
||||||
const placeholders = sparepartIds.map((_, index) => `$${index + 1}`).join(', ');
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
sparepart_id,
|
|
||||||
sparepart_name,
|
|
||||||
sparepart_code,
|
|
||||||
sparepart_description,
|
|
||||||
sparepart_model,
|
|
||||||
sparepart_foto,
|
|
||||||
sparepart_item_type,
|
|
||||||
sparepart_qty,
|
|
||||||
sparepart_unit,
|
|
||||||
sparepart_merk,
|
|
||||||
sparepart_stok,
|
|
||||||
created_at,
|
|
||||||
updated_at
|
|
||||||
FROM m_sparepart
|
|
||||||
WHERE sparepart_id IN (${placeholders})
|
|
||||||
AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, sparepartIds);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllSparepartDb,
|
|
||||||
getSparepartByIdDb,
|
|
||||||
getSparepartsByIdsDb,
|
|
||||||
checkSparepartNameExistsDb,
|
|
||||||
createSparepartDb,
|
|
||||||
updateSparepartDb,
|
|
||||||
deleteSparepartDb,
|
|
||||||
};
|
|
||||||
117
db/status.db.js
117
db/status.db.js
@@ -1,117 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all status
|
|
||||||
const getAllStatusDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.status_name", "a.status_description"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.status_number", param: searchParams.number, type: "number" },
|
|
||||||
{ column: "a.is_active", param: searchParams.is_active, type: "boolean" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*
|
|
||||||
FROM m_status a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? `AND ${whereConditions.join(' AND ')}` : ''}
|
|
||||||
${whereOrConditions ? whereOrConditions : ''}
|
|
||||||
ORDER BY a.status_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getStatusByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT *
|
|
||||||
FROM m_status a
|
|
||||||
WHERE a.status_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if status_number already exists
|
|
||||||
const checkStatusNumberExistsDb = async (status_number) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT 1
|
|
||||||
FROM m_status
|
|
||||||
WHERE status_number = $1 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [status_number]);
|
|
||||||
return result.recordset.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const createStatusDb = async (data) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert(
|
|
||||||
"m_status",
|
|
||||||
data
|
|
||||||
);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId ? await getStatusByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateStatusDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { status_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_status",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getStatusByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteStatusDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_status
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE status_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllStatusDb,
|
|
||||||
getStatusByIdDb,
|
|
||||||
createStatusDb,
|
|
||||||
updateStatusDb,
|
|
||||||
deleteStatusDb,
|
|
||||||
checkStatusNumberExistsDb,
|
|
||||||
};
|
|
||||||
140
db/tags.db.js
140
db/tags.db.js
@@ -1,140 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all tags
|
|
||||||
const getAllTagsDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"a.tag_name",
|
|
||||||
"a.tag_code",
|
|
||||||
"a.tag_number",
|
|
||||||
"a.data_type",
|
|
||||||
"a.unit",
|
|
||||||
"b.device_name",
|
|
||||||
"c.plant_sub_section_name",
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.tag_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "a.tag_code", param: searchParams.code, type: "string" },
|
|
||||||
{ column: "a.data_type", param: searchParams.data, type: "string" },
|
|
||||||
{ column: "a.unit", param: searchParams.unit, type: "string" },
|
|
||||||
{ column: "b.device_name", param: searchParams.device, type: "string" },
|
|
||||||
{
|
|
||||||
column: "b.device_code",
|
|
||||||
param: searchParams.device,
|
|
||||||
type: "string",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
column: "c.plant_sub_section_name",
|
|
||||||
param: searchParams.subsection,
|
|
||||||
type: "string",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
b.device_name,
|
|
||||||
b.device_code,
|
|
||||||
c.plant_sub_section_name
|
|
||||||
FROM m_tags a
|
|
||||||
LEFT JOIN m_device b ON a.device_id = b.device_id
|
|
||||||
LEFT JOIN m_plant_sub_section c ON a.plant_sub_section_id = c.plant_sub_section_id
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY a.tag_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset?.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getTagsByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.device_name,
|
|
||||||
b.device_code,
|
|
||||||
c.plant_sub_section_name
|
|
||||||
FROM m_tags a
|
|
||||||
LEFT JOIN m_device b ON a.device_id = b.device_id
|
|
||||||
LEFT JOIN m_plant_sub_section c ON a.plant_sub_section_id = c.plant_sub_section_id
|
|
||||||
WHERE a.tag_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createTagsDb = async (data) => {
|
|
||||||
const newCode = await pool.generateKode("TAG", "m_tags", "tag_code");
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
tag_code: newCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_tags", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getTagsByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateTagsDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { tag_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_tags",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getTagsByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete tag
|
|
||||||
const deleteTagsDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_tags
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE tag_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllTagsDb,
|
|
||||||
getTagsByIdDb,
|
|
||||||
createTagsDb,
|
|
||||||
updateTagsDb,
|
|
||||||
deleteTagsDb,
|
|
||||||
};
|
|
||||||
119
db/unit.db.js
119
db/unit.db.js
@@ -1,119 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
// Get all units
|
|
||||||
const getAllUnitsDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.unit_code", "a.unit_name"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
|
||||||
|
|
||||||
// Filter
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.unit_code", param: searchParams.code, type: "string" },
|
|
||||||
{ column: "a.unit_name", param: searchParams.name, type: "string" },
|
|
||||||
{ column: "a.tag_id", param: searchParams.tag, type: "number" },
|
|
||||||
{ column: "a.is_active", param: searchParams.status, type: "string" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
COALESCE(a.unit_code, '') + ' - ' + COALESCE(a.unit_name, '') AS unit_code_name
|
|
||||||
FROM m_unit a
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? `AND ${whereConditions.join(" AND ")}` : ""}
|
|
||||||
${whereOrConditions ? whereOrConditions : ""}
|
|
||||||
ORDER BY a.unit_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
|
|
||||||
const total =
|
|
||||||
result?.recordset.length > 0
|
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return { data: result.recordset, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get unit by ID
|
|
||||||
const getUnitByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
COALESCE(a.unit_code, '') + ' - ' + COALESCE(a.unit_name, '') AS unit_code_name
|
|
||||||
FROM m_unit a
|
|
||||||
WHERE a.unit_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Create unit
|
|
||||||
const createUnitDb = async (data) => {
|
|
||||||
const newCode = await pool.generateKode("UNT", "m_unit", "unit_code");
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
...data,
|
|
||||||
unit_code: newCode,
|
|
||||||
};
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_unit", store);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
|
||||||
return insertedId ? await getUnitByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update unit
|
|
||||||
const updateUnitDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { unit_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"m_unit",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getUnitByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Soft delete unit
|
|
||||||
const deleteUnitDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_unit
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE unit_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Export
|
|
||||||
module.exports = {
|
|
||||||
getAllUnitsDb,
|
|
||||||
getUnitByIdDb,
|
|
||||||
createUnitDb,
|
|
||||||
updateUnitDb,
|
|
||||||
deleteUnitDb,
|
|
||||||
};
|
|
||||||
262
db/user.db.js
262
db/user.db.js
@@ -1,204 +1,142 @@
|
|||||||
const pool = require("../config");
|
const pool = require("../config");
|
||||||
|
|
||||||
// Get all users
|
const getAllUsersDb = async (param) => {
|
||||||
const getAllUsersDb = async (searchParams = {}) => {
|
// limit & offset masuk fixed param
|
||||||
let queryParams = [];
|
let fixedParams = [param.fixed.limit, param.fixed.offset, param.fixed.tenantID];
|
||||||
|
|
||||||
// Pagination
|
const { whereOrConditions, whereParam } = pool.buildStringOrIlike(
|
||||||
if (searchParams.limit) {
|
param.filterCriteria.column,
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
param.filterCriteria.criteria,
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
fixedParams
|
||||||
}
|
|
||||||
|
|
||||||
// Search
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
[
|
|
||||||
"u.user_fullname",
|
|
||||||
"u.user_name",
|
|
||||||
"u.user_email",
|
|
||||||
"r.role_name"
|
|
||||||
],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
);
|
||||||
|
const { whereConditions, queryParams } = pool.buildFilterQuery(param.filterQuery, whereParam);npm
|
||||||
|
|
||||||
queryParams = whereParamOr ? whereParamOr : queryParams;
|
const query = `
|
||||||
|
SELECT mut.*, mr.role_name, COUNT(*) OVER() AS total
|
||||||
// Filter
|
FROM m_users mut
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
LEFT JOIN system.role_tenant mr ON mr.role_id = mut.role_id
|
||||||
[
|
WHERE mut.deleted_at IS NULL AND mut.is_sa != 1 AND mut.tenant_id = $3
|
||||||
{ column: "u.user_fullname", param: searchParams.fullname, type: "string" },
|
${whereConditions.length > 0 ? ` AND ${whereConditions.join(" AND ")}` : ""}
|
||||||
{ column: "u.user_name", param: searchParams.username, type: "string" },
|
${whereOrConditions ? whereOrConditions : ""}
|
||||||
{ column: "u.user_email", param: searchParams.email, type: "string" },
|
ORDER BY mut.user_id
|
||||||
{ column: "r.role_name", param: searchParams.role, type: "string" },
|
OFFSET $2 ROWS FETCH NEXT $1 ROWS ONLY
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
|
|
||||||
queryParams = whereParamAnd ? whereParamAnd : queryParams;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
u.user_id, u.user_fullname, u.user_name, u.user_email, u.user_phone,
|
|
||||||
u.is_active, u.is_sa, u.is_approve, u.approved_by,
|
|
||||||
approver.user_fullname AS approved_by_name,
|
|
||||||
u.approved_at, u.created_at, u.updated_at, u.deleted_at,
|
|
||||||
u.updated_by, u.deleted_by,
|
|
||||||
r.role_id, r.role_name, r.role_description, r.role_level
|
|
||||||
FROM m_users u
|
|
||||||
LEFT JOIN m_roles r ON u.role_id = r.role_id
|
|
||||||
LEFT JOIN m_users approver ON u.approved_by = approver.user_id
|
|
||||||
WHERE u.deleted_at IS NULL
|
|
||||||
${whereConditions.length > 0 ? ` AND ${whereConditions.join(' AND ')}` : ''}
|
|
||||||
${whereOrConditions ? whereOrConditions : ''}
|
|
||||||
ORDER BY u.user_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ''}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
const result = await pool.query(query, queryParams);
|
||||||
|
const rows = result.recordset;
|
||||||
|
|
||||||
const total =
|
const total = rows.length > 0 ? parseInt(rows[0].total, 10) : 0;
|
||||||
result?.recordset.length > 0
|
return { data: rows, total };
|
||||||
? parseInt(result.recordset[0].total_data, 10)
|
};
|
||||||
: 0;
|
|
||||||
|
const createUserDb = async (param) => {
|
||||||
return { data: result.recordset, total };
|
const insertData = {
|
||||||
|
tenant_id: param.tenantID,
|
||||||
|
user_fullname: param.userFullname,
|
||||||
|
user_name: param.userName,
|
||||||
|
user_email: param.userEmail ?? null,
|
||||||
|
user_password: param.userPassword,
|
||||||
|
role_id: param.roleId ?? null,
|
||||||
|
is_active: param.isActive ? 1 : 0,
|
||||||
|
created_by: param.userID,
|
||||||
|
updated_by: param.userID,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { query, values } = pool.buildDynamicInsert("m_users", insertData);
|
||||||
|
|
||||||
|
const result = await pool.query(query, values);
|
||||||
|
return result.recordset[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get user by ID
|
|
||||||
const getUserByIdDb = async (id) => {
|
const getUserByIdDb = async (id) => {
|
||||||
const queryText = `
|
const query = `
|
||||||
SELECT
|
SELECT mut.*
|
||||||
u.user_id, u.user_fullname, u.user_name, u.user_email, u.user_phone,
|
FROM m_users mut
|
||||||
u.is_active, u.is_sa, u.is_approve, u.approved_by,
|
WHERE mut.user_id = $1
|
||||||
approver.user_fullname AS approved_by_name,
|
|
||||||
u.approved_at, u.created_at, u.updated_at, u.deleted_at,
|
|
||||||
u.updated_by, u.deleted_by,
|
|
||||||
r.role_id, r.role_name, r.role_description, r.role_level
|
|
||||||
FROM m_users u
|
|
||||||
LEFT JOIN m_roles r ON u.role_id = r.role_id
|
|
||||||
LEFT JOIN m_users approver ON u.approved_by = approver.user_id
|
|
||||||
WHERE u.user_id = $1 AND u.deleted_at IS NULL
|
|
||||||
`;
|
`;
|
||||||
const result = await pool.query(queryText, [id]);
|
const result = await pool.query(query, [id]);
|
||||||
return result.recordset[0];
|
return result.recordset[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get user by email
|
|
||||||
const getUserByUserEmailDb = async (email) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
u.user_id, u.user_fullname, u.user_name, u.user_email, u.user_phone,
|
|
||||||
u.user_password, u.is_active, u.is_sa, u.is_approve, u.role_id,
|
|
||||||
r.role_name, r.role_description, r.role_level
|
|
||||||
FROM m_users u
|
|
||||||
LEFT JOIN m_roles r ON u.role_id = r.role_id
|
|
||||||
WHERE u.user_email = $1 AND u.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [email]);
|
|
||||||
return result.recordset[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get user by username
|
|
||||||
const getUserByUsernameDb = async (username) => {
|
const getUserByUsernameDb = async (username) => {
|
||||||
const queryText = `
|
const query = `
|
||||||
SELECT
|
SELECT mut.*
|
||||||
u.user_id, u.user_fullname, u.user_name, u.user_email, u.user_phone,
|
FROM m_users mut
|
||||||
u.user_password, u.is_active, u.is_sa, u.is_approve, u.role_id,
|
WHERE LOWER(mut.username) = LOWER($1)
|
||||||
r.role_name, r.role_description, r.role_level
|
|
||||||
FROM m_users u
|
|
||||||
LEFT JOIN m_roles r ON u.role_id = r.role_id
|
|
||||||
WHERE u.user_name = $1 AND u.deleted_at IS NULL
|
|
||||||
`;
|
`;
|
||||||
const result = await pool.query(queryText, [username]);
|
const result = await pool.query(query, [username]);
|
||||||
return result.recordset[0];
|
return result.recordset[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create user
|
const getUserByUserEmailDb = async (userEmail) => {
|
||||||
const createUserDb = async (data) => {
|
const query = `
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert("m_users", data);
|
SELECT mut.*
|
||||||
const result = await pool.query(queryText, values);
|
FROM m_users mut
|
||||||
const insertedId = result.recordset[0]?.inserted_id;
|
WHERE LOWER(mut.user_email) = LOWER($1)
|
||||||
return insertedId ? await getUserByIdDb(insertedId) : null;
|
`;
|
||||||
|
const result = await pool.query(query, [userEmail]);
|
||||||
|
return result.recordset[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update user
|
const updateUserDb = async (param) => {
|
||||||
const updateUserDb = async (userId, data) => {
|
const updateData = {
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate("m_users", data, {
|
tenant_id: param.tenantID,
|
||||||
user_id: userId,
|
user_fullname: param.userFullname,
|
||||||
});
|
user_name: param.userName,
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
user_email: param.userEmail ?? null,
|
||||||
return getUserByIdDb(userId);
|
user_password: param.userPassword,
|
||||||
|
role_id: param.roleId ?? null,
|
||||||
|
is_active: param.isActive ? 1 : 0,
|
||||||
|
updated_by: param.userID,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Approve user
|
const whereData = { user_id: param.id };
|
||||||
const approveUserDb = async (userId, approverId) => {
|
|
||||||
const queryText = `
|
const { query, values } = pool.buildDynamicUpdate("m_users", updateData, whereData);
|
||||||
UPDATE m_users
|
|
||||||
SET
|
const result = await pool.query(query, values);
|
||||||
is_approve = 2,
|
return result.recordset[0];
|
||||||
approved_by = $1,
|
|
||||||
approved_at = CURRENT_TIMESTAMP,
|
|
||||||
updated_by = $1,
|
|
||||||
updated_at = CURRENT_TIMESTAMP
|
|
||||||
WHERE user_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [approverId, userId]);
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reject user
|
const deleteUserDb = async (id, userID) => {
|
||||||
const rejectUserDb = async (userId, approverId) => {
|
const query = `
|
||||||
const queryText = `
|
|
||||||
UPDATE m_users
|
UPDATE m_users
|
||||||
SET
|
SET deleted_at = GETDATE(), deleted_by = $1
|
||||||
is_approve = 0,
|
WHERE user_id = $2;
|
||||||
approved_by = $1,
|
|
||||||
approved_at = CURRENT_TIMESTAMP,
|
|
||||||
updated_by = $1,
|
|
||||||
updated_at = CURRENT_TIMESTAMP
|
|
||||||
WHERE user_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [approverId, userId]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change user password
|
SELECT * FROM m_users WHERE user_id = $2
|
||||||
const changeUserPasswordDb = async (userId, newPassword) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE m_users
|
|
||||||
SET user_password = $1, updated_at = CURRENT_TIMESTAMP
|
|
||||||
WHERE user_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
`;
|
||||||
await pool.query(queryText, [newPassword, userId]);
|
const result = await pool.query(query, [userID, id]);
|
||||||
return true;
|
return result.recordset[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Soft delete user
|
const changeUserPasswordDb = async (hashedPassword, userEmail, tenantId) => {
|
||||||
const deleteUserDb = async (userId, deletedBy) => {
|
const query = `
|
||||||
const queryText = `
|
|
||||||
UPDATE m_users
|
UPDATE m_users
|
||||||
SET
|
SET user_password = $1
|
||||||
deleted_at = CURRENT_TIMESTAMP,
|
WHERE user_email = $2 AND tenant_id = $3
|
||||||
deleted_by = $1,
|
|
||||||
is_active = 0
|
|
||||||
WHERE user_id = $2
|
|
||||||
AND deleted_at IS NULL
|
|
||||||
`;
|
`;
|
||||||
await pool.query(queryText, [deletedBy, userId]);
|
return pool.query(query, [hashedPassword, userEmail, tenantId]);
|
||||||
return true;
|
};
|
||||||
|
|
||||||
|
const getAllRoleDb = async (tenantId) => {
|
||||||
|
const query = `
|
||||||
|
SELECT *
|
||||||
|
FROM system.role_tenant
|
||||||
|
WHERE deleted_at IS NULL AND tenant_id = $1
|
||||||
|
`;
|
||||||
|
const result = await pool.query(query, [tenantId]);
|
||||||
|
return result.recordset;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getAllUsersDb,
|
getAllUsersDb,
|
||||||
getUserByIdDb,
|
getUserByIdDb,
|
||||||
getUserByUserEmailDb,
|
getUserByUserEmailDb,
|
||||||
getUserByUsernameDb,
|
|
||||||
createUserDb,
|
|
||||||
updateUserDb,
|
updateUserDb,
|
||||||
approveUserDb,
|
createUserDb,
|
||||||
rejectUserDb,
|
|
||||||
changeUserPasswordDb,
|
|
||||||
deleteUserDb,
|
deleteUserDb,
|
||||||
|
getUserByUsernameDb,
|
||||||
|
changeUserPasswordDb,
|
||||||
|
getAllRoleDb,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,170 +0,0 @@
|
|||||||
const pool = require("../config");
|
|
||||||
|
|
||||||
const getAllUserScheduleDb = async (searchParams = {}) => {
|
|
||||||
let queryParams = [];
|
|
||||||
|
|
||||||
// Handle pagination
|
|
||||||
if (searchParams.limit) {
|
|
||||||
const page = Number(searchParams.page ?? 1) - 1;
|
|
||||||
queryParams = [Number(searchParams.limit ?? 10), page];
|
|
||||||
}
|
|
||||||
|
|
||||||
const { whereOrConditions, whereParamOr } = pool.buildStringOrIlike(
|
|
||||||
["a.user_id", "a.user_schedule_id", "a.schedule_id", "a.user_schedule_id", "a.shift_id"],
|
|
||||||
searchParams.criteria,
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamOr) queryParams = whereParamOr;
|
|
||||||
|
|
||||||
const { whereConditions, whereParamAnd } = pool.buildFilterQuery(
|
|
||||||
[
|
|
||||||
{ column: "a.user_id", param: searchParams.user_id, type: "int" },
|
|
||||||
{
|
|
||||||
column: "a.user_schedule_id",
|
|
||||||
param: searchParams.user_schedule_id,
|
|
||||||
type: "int",
|
|
||||||
},
|
|
||||||
{ column: "a.schedule_id", param: searchParams.schedule_id, type: "int" },
|
|
||||||
{ column: "a.shift_id", param: searchParams.shift_id, type: "int" },
|
|
||||||
],
|
|
||||||
queryParams
|
|
||||||
);
|
|
||||||
if (whereParamAnd) queryParams = whereParamAnd;
|
|
||||||
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
COUNT(*) OVER() AS total_data,
|
|
||||||
a.*,
|
|
||||||
c.shift_name,
|
|
||||||
c.start_time,
|
|
||||||
c.end_time,
|
|
||||||
d.user_fullname,
|
|
||||||
d.user_name,
|
|
||||||
d.user_phone
|
|
||||||
FROM user_schedule a
|
|
||||||
LEFT JOIN schedule b ON a.schedule_id = b.schedule_id
|
|
||||||
LEFT JOIN m_shift c ON a.shift_id = c.shift_id
|
|
||||||
LEFT JOIN m_users d ON a.user_id = d.user_id
|
|
||||||
WHERE a.deleted_at IS NULL
|
|
||||||
${
|
|
||||||
whereConditions.length > 0
|
|
||||||
? ` AND ${whereConditions.join(" AND ")}`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
${whereOrConditions ? ` ${whereOrConditions}` : ""}
|
|
||||||
ORDER BY c.shift_id ASC
|
|
||||||
${searchParams.limit ? `OFFSET $2 * $1 ROWS FETCH NEXT $1 ROWS ONLY` : ""}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const result = await pool.query(queryText, queryParams);
|
|
||||||
const records = result.recordset || [];
|
|
||||||
|
|
||||||
const total = records.length > 0 ? parseInt(records[0].total_data, 10) : 0;
|
|
||||||
|
|
||||||
const groupedShift = {};
|
|
||||||
records.forEach((row) => {
|
|
||||||
if (!groupedShift[row.shift_id]) {
|
|
||||||
groupedShift[row.shift_id] = {
|
|
||||||
shift: {
|
|
||||||
shift_id: row.shift_id,
|
|
||||||
shift_name: row.shift_name,
|
|
||||||
start_time: row.start_time,
|
|
||||||
end_time: row.end_time,
|
|
||||||
users: [],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
groupedShift[row.shift_id].shift.users.push({
|
|
||||||
user_schedule_id: row.user_schedule_id,
|
|
||||||
user_id: row.user_id,
|
|
||||||
user_fullname: row.user_fullname,
|
|
||||||
user_name: row.user_name,
|
|
||||||
user_phone: row.user_phone,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = Object.values(groupedShift);
|
|
||||||
|
|
||||||
return { data, total };
|
|
||||||
};
|
|
||||||
|
|
||||||
const getUserScheduleById = async (userId, shiftId) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.user_schedule_id,
|
|
||||||
a.user_id,
|
|
||||||
a.shift_id
|
|
||||||
FROM user_schedule a
|
|
||||||
WHERE a.user_id = $1
|
|
||||||
AND a.shift_id = $2
|
|
||||||
AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [userId, shiftId]);
|
|
||||||
return result.recordset || [];
|
|
||||||
};
|
|
||||||
|
|
||||||
const getUserScheduleByIdDb = async (id) => {
|
|
||||||
const queryText = `
|
|
||||||
SELECT
|
|
||||||
a.*,
|
|
||||||
b.schedule_date,
|
|
||||||
c.shift_name,
|
|
||||||
c.start_time,
|
|
||||||
c.end_time,
|
|
||||||
d.user_fullname,
|
|
||||||
d.user_name,
|
|
||||||
d.user_phone
|
|
||||||
FROM user_schedule a
|
|
||||||
LEFT JOIN schedule b ON a.schedule_id = b.schedule_id
|
|
||||||
LEFT JOIN m_shift c ON a.shift_id = c.shift_id
|
|
||||||
LEFT JOIN m_users d ON a.user_id = d.user_id
|
|
||||||
WHERE a.user_schedule_id = $1 AND a.deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
const result = await pool.query(queryText, [id]);
|
|
||||||
return result.recordset?.[0] || null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const insertUserScheduleDb = async (store) => {
|
|
||||||
const { query: queryText, values } = pool.buildDynamicInsert(
|
|
||||||
"user_schedule",
|
|
||||||
store
|
|
||||||
);
|
|
||||||
const result = await pool.query(queryText, values);
|
|
||||||
const insertedId = result.recordset?.[0]?.inserted_id;
|
|
||||||
|
|
||||||
return insertedId ? await getUserScheduleByIdDb(insertedId) : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateUserScheduleDb = async (id, data) => {
|
|
||||||
const store = { ...data };
|
|
||||||
const whereData = { user_schedule_id: id };
|
|
||||||
|
|
||||||
const { query: queryText, values } = pool.buildDynamicUpdate(
|
|
||||||
"user_schedule",
|
|
||||||
store,
|
|
||||||
whereData
|
|
||||||
);
|
|
||||||
|
|
||||||
await pool.query(`${queryText} AND deleted_at IS NULL`, values);
|
|
||||||
return getUserScheduleByIdDb(id);
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteUserScheduleDb = async (id, deletedBy) => {
|
|
||||||
const queryText = `
|
|
||||||
UPDATE user_schedule
|
|
||||||
SET deleted_at = CURRENT_TIMESTAMP, deleted_by = $1
|
|
||||||
WHERE user_schedule_id = $2 AND deleted_at IS NULL
|
|
||||||
`;
|
|
||||||
await pool.query(queryText, [deletedBy, id]);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getAllUserScheduleDb,
|
|
||||||
getUserScheduleByIdDb,
|
|
||||||
insertUserScheduleDb,
|
|
||||||
updateUserScheduleDb,
|
|
||||||
deleteUserScheduleDb,
|
|
||||||
getUserScheduleById,
|
|
||||||
};
|
|
||||||
@@ -1,29 +1,43 @@
|
|||||||
const setResponse = (data = null, message = "success", statusCode = 200) => {
|
const setResponse = async (data = [], message = "success", statusCode = 200) => {
|
||||||
const total = Array.isArray(data) ? data.length : null;
|
const response = {
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
statusCode,
|
|
||||||
rows: total,
|
|
||||||
data,
|
data,
|
||||||
};
|
total: data.length,
|
||||||
|
message,
|
||||||
|
statusCode
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
};
|
};
|
||||||
|
|
||||||
const setResponsePaging = async (queryParam, data = [], message = "success", statusCode = 200) => {
|
const setResponsePaging = async (data = [], total, limit, page, message = "success", statusCode = 200) => {
|
||||||
|
|
||||||
const totalPages = Math.ceil(data?.total / Number(queryParam.limit ?? 0));
|
const totalPages = Math.ceil(total / limit);
|
||||||
|
|
||||||
const response = {
|
const response = {
|
||||||
message,
|
message,
|
||||||
statusCode,
|
statusCode,
|
||||||
rows: data?.data?.length,
|
data,
|
||||||
|
total: data.length,
|
||||||
paging: {
|
paging: {
|
||||||
current_limit: Number(queryParam.limit ?? 0),
|
total,
|
||||||
current_page: Number(queryParam.page ?? 0),
|
limit,
|
||||||
total_limit: data?.total,
|
page,
|
||||||
total_page: totalPages
|
page_total: totalPages
|
||||||
},
|
}
|
||||||
data: data?.data ?? []
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
|
};
|
||||||
|
|
||||||
|
const setPaging = async (total, limit, page) => {
|
||||||
|
|
||||||
|
const totalPages = Math.ceil(total / limit);
|
||||||
|
|
||||||
|
const response = {
|
||||||
|
total,
|
||||||
|
limit,
|
||||||
|
page,
|
||||||
|
page_total: totalPages
|
||||||
}
|
}
|
||||||
|
|
||||||
return response
|
return response
|
||||||
@@ -72,19 +86,4 @@ function orderByClauseQuery(orderParams) {
|
|||||||
return orderByClause
|
return orderByClause
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkValidate = (validateSchema, req) => {
|
module.exports = { setResponse, setResponsePaging, setPaging, convertId, formatToYYYYMMDD, orderByClauseQuery };
|
||||||
const { error, value } = validateSchema.validate(req.body || {}, { abortEarly: false });
|
|
||||||
if (error) {
|
|
||||||
const errors = error.details.reduce((acc, cur) => {
|
|
||||||
const field = Array.isArray(cur.path) ? cur.path.join('.') : String(cur.path);
|
|
||||||
if (!acc[field]) acc[field] = [];
|
|
||||||
acc[field].push(cur.message);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
return { error: errors, value }
|
|
||||||
}
|
|
||||||
|
|
||||||
return { error, value }
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { setResponse, setResponsePaging, convertId, formatToYYYYMMDD, orderByClauseQuery, checkValidate };
|
|
||||||
|
|||||||
9
helpers/validateUser.js
Normal file
9
helpers/validateUser.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
const validateUser = (email, password) => {
|
||||||
|
const validEmail = typeof email === "string" && email.trim() !== "";
|
||||||
|
const validPassword =
|
||||||
|
typeof password === "string" && password.trim().length >= 6;
|
||||||
|
|
||||||
|
return validEmail && validPassword;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = validateUser;
|
||||||
2
index.js
2
index.js
@@ -5,6 +5,6 @@ const { logger } = require("./utils/logger");
|
|||||||
|
|
||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
|
|
||||||
const PORT = process.env.PORT || 9533;
|
const PORT = process.env.PORT || 9524;
|
||||||
|
|
||||||
server.listen(PORT, () => logger.info(`Magic happening on port: ${PORT}`));
|
server.listen(PORT, () => logger.info(`Magic happening on port: ${PORT}`));
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
const Imagekit = require("imagekit");
|
|
||||||
const { IMAGEKIT_URL_ENDPOINT, IMAGEKIT_PUBLIC_KEY, IMAGEKIT_PRIVATE_KEY } = process.env;
|
|
||||||
|
|
||||||
module.exports = new Imagekit({
|
|
||||||
publicKey: IMAGEKIT_PUBLIC_KEY,
|
|
||||||
privateKey: IMAGEKIT_PRIVATE_KEY,
|
|
||||||
urlEndpoint: IMAGEKIT_URL_ENDPOINT,
|
|
||||||
});
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
const multer = require("multer");
|
|
||||||
|
|
||||||
const storage = multer.memoryStorage();
|
|
||||||
|
|
||||||
module.exports = multer({ storage });
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
const multer = require("multer");
|
|
||||||
const path = require("path");
|
|
||||||
const { randomUUID } = require("crypto");
|
|
||||||
const fs = require("fs");
|
|
||||||
|
|
||||||
// Fungsi untuk tentuin folder berdasarkan file type
|
|
||||||
function getFolderByType(mimetype) {
|
|
||||||
if (mimetype === "application/pdf") {
|
|
||||||
return "pdf";
|
|
||||||
} else if (mimetype.startsWith("image/")) {
|
|
||||||
return "images";
|
|
||||||
}
|
|
||||||
return "file";
|
|
||||||
}
|
|
||||||
|
|
||||||
const storage = multer.diskStorage({
|
|
||||||
destination: (req, file, cb) => {
|
|
||||||
const folderName = getFolderByType(file.mimetype);
|
|
||||||
const folderPath = path.join(__dirname, "../uploads", folderName);
|
|
||||||
|
|
||||||
fs.mkdirSync(folderPath, { recursive: true });
|
|
||||||
|
|
||||||
cb(null, folderPath);
|
|
||||||
},
|
|
||||||
filename: (req, file, cb) => {
|
|
||||||
const ext = path.extname(file.originalname);
|
|
||||||
const timestamp = Date.now();
|
|
||||||
|
|
||||||
const date = new Date(timestamp);
|
|
||||||
const year = date.getFullYear();
|
|
||||||
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
||||||
const day = String(date.getDate()).padStart(2, "0");
|
|
||||||
const hours = String(date.getHours()).padStart(2, "0");
|
|
||||||
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
||||||
const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
||||||
|
|
||||||
const formattedDate = `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
|
|
||||||
|
|
||||||
// Prefix berdasarkan tipe file
|
|
||||||
const prefix = file.mimetype === "application/pdf" ? "pdf" : "img";
|
|
||||||
const uniqueId = randomUUID().slice(0, 8);
|
|
||||||
|
|
||||||
cb(null, `${prefix}-${uniqueId}-${formattedDate}${ext}`);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const upload = multer({
|
|
||||||
storage,
|
|
||||||
fileFilter: (req, file, cb) => {
|
|
||||||
const allowedTypes = /jpeg|jpg|png|pdf/;
|
|
||||||
const allowedMimeTypes = /image\/(jpeg|jpg|png)|application\/pdf/;
|
|
||||||
|
|
||||||
const extname = allowedTypes.test(
|
|
||||||
path.extname(file.originalname).toLowerCase()
|
|
||||||
);
|
|
||||||
const mimetype = allowedMimeTypes.test(file.mimetype);
|
|
||||||
|
|
||||||
if (extname && mimetype) {
|
|
||||||
return cb(null, true);
|
|
||||||
} else {
|
|
||||||
cb(new Error("File type not allowed. Only PDF and Images (JPEG, JPG, PNG) are accepted."));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
limits: {
|
|
||||||
fileSize: 10 * 1024 * 1024, // 10MB max file size
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = upload;
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
const { getUserByIdDb } = require("../db/user.db");
|
|
||||||
|
|
||||||
function isPhoneNumberID(phone) {
|
|
||||||
return /^(?:\+62|62|0)8[1-9][0-9]{6,10}$/.test(phone);
|
|
||||||
}
|
|
||||||
|
|
||||||
const verifyAccess = (minLevel = 1, allowUnapprovedReadOnly = false) => {
|
|
||||||
return async (req, res, next) => {
|
|
||||||
try {
|
|
||||||
const user = req.user;
|
|
||||||
|
|
||||||
if (!user) throw new ErrorHandler(401, "Unauthorized: User not found");
|
|
||||||
|
|
||||||
// Super Admin bypass semua
|
|
||||||
if (user.is_sa) return next();
|
|
||||||
|
|
||||||
|
|
||||||
if (!isPhoneNumberID(user.user_id) && user.user_id) {
|
|
||||||
const fullUser = await getUserByIdDb(user.user_id);
|
|
||||||
if (!fullUser) throw new ErrorHandler(403, "Forbidden: User not found");
|
|
||||||
|
|
||||||
if (!fullUser.is_approve) {
|
|
||||||
if (req.method !== "GET") {
|
|
||||||
throw new ErrorHandler(403, "Account not approved — read-only access");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allowUnapprovedReadOnly) return next();
|
|
||||||
|
|
||||||
throw new ErrorHandler(403, "Account not approved");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fullUser.role_level || fullUser.role_level < minLevel) {
|
|
||||||
throw new ErrorHandler(403, "Forbidden: Insufficient role level");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (req.method !== 'GET' && req.baseUrl !== '/api/notification-log') {
|
|
||||||
if (req.baseUrl !== '/api/notification') {
|
|
||||||
throw new ErrorHandler(403, "Forbidden: Insufficient Access");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
next();
|
|
||||||
} catch (err) {
|
|
||||||
next(err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = verifyAccess;
|
|
||||||
14
middleware/verifyAdmin.js
Normal file
14
middleware/verifyAdmin.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
const { ErrorHandler } = require("../helpers/error");
|
||||||
|
|
||||||
|
module.exports = (req, res, next) => {
|
||||||
|
const { roles } = req.user;
|
||||||
|
if (roles && roles.includes("admin")) {
|
||||||
|
req.user = {
|
||||||
|
...req.user,
|
||||||
|
roles,
|
||||||
|
};
|
||||||
|
return next();
|
||||||
|
} else {
|
||||||
|
throw new ErrorHandler(401, "require admin role");
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,53 +1,47 @@
|
|||||||
const JWTService = require('../utils/jwt');
|
const jwt = require("jsonwebtoken");
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
const { ErrorHandler } = require("../helpers/error");
|
||||||
|
|
||||||
function setUser(req, decoded) {
|
const verifyToken = (req, res, next) => {
|
||||||
req.user = {
|
const authHeader = req.header("Authorization");
|
||||||
userId: decoded.user_id,
|
// console.log("authHeader", authHeader)
|
||||||
fullname: decoded.user_fullname,
|
|
||||||
username: decoded.user_name,
|
// Pastikan header Authorization ada dan berisi token
|
||||||
email: decoded.user_email,
|
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
||||||
roleId: decoded.role_id,
|
throw new ErrorHandler(401, "Token missing or invalid");
|
||||||
roleName: decoded.role_name,
|
|
||||||
is_sa: decoded.is_sa
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function verifyAccessToken(req, res, next) {
|
// Ambil token dari header Authorization
|
||||||
|
const token = authHeader.split(" ")[1];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let token = req.cookies?.accessToken;
|
// const decoded = jwt.decode(token, { complete: true });
|
||||||
|
// console.log("decoded", decoded)
|
||||||
|
// console.log("==============================")
|
||||||
|
// console.log("token", token)
|
||||||
|
// console.log("process.env.SECRET", process.env.SECRET)
|
||||||
|
// // console.log("==============================> ", jwt.verify(token, process.env.SECRET))
|
||||||
|
// jwt.verify(token, process.env.SECRET, (err, decoded) => {
|
||||||
|
// if (err) {
|
||||||
|
// console.error('Error verifying token: ==============================>', err.message);
|
||||||
|
// } else {
|
||||||
|
// console.log('Decoded payload: ==============================>', decoded);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
if (!token) {
|
const verified = jwt.verify(token, process.env.SECRET);
|
||||||
const authHeader = req.headers.authorization;
|
req.tokenExtract = verified;
|
||||||
if (authHeader && authHeader.startsWith('Bearer')) {
|
// console.log(req.tokenExtract);
|
||||||
token = authHeader.split(' ')[1];
|
|
||||||
} else {
|
|
||||||
token = req.query.token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!token) {
|
|
||||||
throw new ErrorHandler(401, 'Access Token is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const decoded = JWTService.verifyToken(token);
|
|
||||||
|
|
||||||
req.user = decoded;
|
|
||||||
|
|
||||||
|
req.userID = req.tokenExtract.user_id
|
||||||
|
req.tenantID = req.tokenExtract.tenant_id
|
||||||
|
req.roleID = req.tokenExtract.role_id
|
||||||
|
req.body.userID = req.tokenExtract.user_id
|
||||||
|
req.body.tenantID = req.tokenExtract.tenant_id
|
||||||
|
req.query.tenantID = req.tokenExtract.tenant_id
|
||||||
next();
|
next();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.name === 'TokenExpiredError') {
|
throw new ErrorHandler(401, error.message || "Invalid Token");
|
||||||
return next(new ErrorHandler(401, 'Access token expired'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error.name === 'JsonWebTokenError') {
|
|
||||||
return next(new ErrorHandler(401, 'Invalid access token'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(new ErrorHandler(500, 'Internal authentication error'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
verifyAccessToken
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = verifyToken;
|
||||||
|
|||||||
@@ -30,13 +30,11 @@
|
|||||||
"crypto": "^1.0.1",
|
"crypto": "^1.0.1",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"exceljs": "^4.4.0",
|
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"google-auth-library": "^8.7.0",
|
"google-auth-library": "^8.7.0",
|
||||||
"googleapis": "^112.0.0",
|
"googleapis": "^112.0.0",
|
||||||
"helmet": "^4.4.1",
|
"helmet": "^4.4.1",
|
||||||
"imagekit": "^6.0.0",
|
|
||||||
"joi": "^17.13.3",
|
"joi": "^17.13.3",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
|
|||||||
8
routes/auth.js
Normal file
8
routes/auth.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
const router = require("express").Router();
|
||||||
|
const {
|
||||||
|
loginUser,
|
||||||
|
} = require("../controllers/auth.controller");
|
||||||
|
|
||||||
|
router.post("/login", loginUser);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const AuthController = require("../controllers/auth.controller");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.post('/login', AuthController.login);
|
|
||||||
router.post('/register', AuthController.register);
|
|
||||||
router.get('/generate-captcha', AuthController.generateCaptcha);
|
|
||||||
router.post('/refresh-token', AuthController.refreshToken);
|
|
||||||
router.post('/verify-redirect', AuthController.verifyTokenRedirect);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const BrandController = require('../controllers/brand.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route('/')
|
|
||||||
.get(verifyToken.verifyAccessToken, BrandController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), BrandController.create);
|
|
||||||
|
|
||||||
router.route('/:id')
|
|
||||||
.get(verifyToken.verifyAccessToken, BrandController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), BrandController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), BrandController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const ContactController = require('../controllers/contact.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, ContactController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), ContactController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, ContactController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), ContactController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), ContactController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const DeviceController = require('../controllers/device.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, DeviceController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), DeviceController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, DeviceController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), DeviceController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), DeviceController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const ErrorCodeController = require('../controllers/error_code.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route('/brand/:brandId')
|
|
||||||
.get(verifyToken.verifyAccessToken, ErrorCodeController.getByBrandId)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), ErrorCodeController.create);
|
|
||||||
|
|
||||||
router.route('/brand/:brandId/:errorCodeId')
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), ErrorCodeController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), ErrorCodeController.delete);
|
|
||||||
|
|
||||||
router.route('/:id')
|
|
||||||
.get(verifyToken.verifyAccessToken, ErrorCodeController.getById);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const router = require("express").Router();
|
|
||||||
const upload = require("../middleware/uploads");
|
|
||||||
const verifyToken = require("../middleware/verifyToken");
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess");
|
|
||||||
const {
|
|
||||||
uploadFile,
|
|
||||||
getFileByPath,
|
|
||||||
deleteFileByPath,
|
|
||||||
} = require("../controllers/file_uploads.controller");
|
|
||||||
|
|
||||||
router.post("/", verifyToken.verifyAccessToken, verifyAccess(), upload.single("file"), uploadFile);
|
|
||||||
|
|
||||||
router.route("/:folder/:filename")
|
|
||||||
.get(verifyToken.verifyAccessToken, getFileByPath)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), deleteFileByPath);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const HistoryValueController = require('../controllers/history_value.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route('/alarm')
|
|
||||||
.get(verifyToken.verifyAccessToken, HistoryValueController.getAllHistoryAlarm)
|
|
||||||
router.route('/event')
|
|
||||||
.get(verifyToken.verifyAccessToken, HistoryValueController.getAllHistoryEvent)
|
|
||||||
router.route('/value-report')
|
|
||||||
.get(verifyToken.verifyAccessToken, HistoryValueController.getHistoryValueReport)
|
|
||||||
router.route('/value-report-pivot')
|
|
||||||
.get(verifyToken.verifyAccessToken, HistoryValueController.getHistoryValueReportPivot)
|
|
||||||
router.route('/value-trending')
|
|
||||||
.get(verifyToken.verifyAccessToken, HistoryValueController.getHistoryValueTrendingPivot)
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,46 +1,8 @@
|
|||||||
const router = require("express").Router();
|
const router = require("express").Router();
|
||||||
const auth = require("./auth.route");
|
const auth = require("./auth");
|
||||||
const users = require("./users.route");
|
const users = require("./users");
|
||||||
const device = require('./device.route');
|
|
||||||
const roles = require('./roles.route');
|
|
||||||
const tags = require("./tags.route");
|
|
||||||
const brand = require("./brand.route");
|
|
||||||
const subSection = require("./plant_sub_section.route");
|
|
||||||
const fileUploads = require("./file_uploads.route");
|
|
||||||
const shift = require("./shift.route");
|
|
||||||
const schedule = require("./schedule.route");
|
|
||||||
const status = require("./status.route");
|
|
||||||
const unit = require("./unit.route")
|
|
||||||
const UserSchedule = require("./user_schedule.route")
|
|
||||||
const historyValue = require("./history_value.route")
|
|
||||||
const contact = require("./contact.route")
|
|
||||||
const notificationError = require("./notification_error.route")
|
|
||||||
const notificationErrorSparepart = require("./notification_error_sparepart.route")
|
|
||||||
const sparepart = require("./sparepart.route")
|
|
||||||
const notificationErrorLog = require("./notification_error_log.route")
|
|
||||||
const notificationErrorUser = require("./notification_error_user.route")
|
|
||||||
const errorCode = require("./error_code.route")
|
|
||||||
|
|
||||||
router.use("/auth", auth);
|
router.use("/auth", auth);
|
||||||
router.use("/user", users);
|
router.use("/users", users);
|
||||||
router.use("/device", device);
|
|
||||||
router.use("/roles", roles);
|
|
||||||
router.use("/tags", tags);
|
|
||||||
router.use("/brand", brand);
|
|
||||||
router.use("/plant-sub-section", subSection);
|
|
||||||
router.use("/file-uploads", fileUploads);
|
|
||||||
router.use("/shift", shift);
|
|
||||||
router.use("/schedule", schedule);
|
|
||||||
router.use("/status", status);
|
|
||||||
router.use("/unit", unit);
|
|
||||||
router.use("/user-schedule", UserSchedule)
|
|
||||||
router.use("/history", historyValue)
|
|
||||||
router.use("/contact", contact)
|
|
||||||
router.use("/notification", notificationError)
|
|
||||||
router.use("/notification-sparepart", notificationErrorSparepart)
|
|
||||||
router.use("/sparepart", sparepart)
|
|
||||||
router.use("/notification-log", notificationErrorLog)
|
|
||||||
router.use("/notification-user", notificationErrorUser)
|
|
||||||
router.use("/error-code", errorCode)
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const NotificationErrorController = require("../controllers/notification_error.controller");
|
|
||||||
const verifyToken = require("../middleware/verifyToken");
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/")
|
|
||||||
.get(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorController.getAll
|
|
||||||
);
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/")
|
|
||||||
.post(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorController.create
|
|
||||||
);
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorController.getById)
|
|
||||||
.put(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorController.update
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
"/resend/:id",
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorController.resend
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const NotificationErrorLogController = require('../controllers/notification_error_log.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorLogController.getAll)
|
|
||||||
.post(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorLogController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorLogController.getById);
|
|
||||||
|
|
||||||
router.route("/notification_error/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorLogController.getByNotificationErrorId);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const NotificationErrorSparepartController = require('../controllers/notification_error_sparepart.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
// ===========================
|
|
||||||
// Notification Erro rSparepart Routes
|
|
||||||
// ===========================
|
|
||||||
|
|
||||||
router
|
|
||||||
.route('/')
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorSparepartController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), NotificationErrorSparepartController.create);
|
|
||||||
|
|
||||||
router
|
|
||||||
.route('/:id')
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorSparepartController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), NotificationErrorSparepartController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), NotificationErrorSparepartController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const NotificationErrorUserController = require("../controllers/notification_error_user.controller");
|
|
||||||
const verifyToken = require("../middleware/verifyToken");
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorUserController.getAll)
|
|
||||||
.post(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorUserController.create
|
|
||||||
);
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, NotificationErrorUserController.getById)
|
|
||||||
.put(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorUserController.update
|
|
||||||
)
|
|
||||||
.delete(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorUserController.delete
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
"/resend/:id/:contact_phone",
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
NotificationErrorUserController.resendByUser
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const PlantSubSectionController = require('../controllers/plant_sub_section.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route('/')
|
|
||||||
.get(verifyToken.verifyAccessToken, PlantSubSectionController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), PlantSubSectionController.create);
|
|
||||||
|
|
||||||
router.route('/:id')
|
|
||||||
.get(verifyToken.verifyAccessToken, PlantSubSectionController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), PlantSubSectionController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), PlantSubSectionController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const RolesController = require('../controllers/roles.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, RolesController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), RolesController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, RolesController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), RolesController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), RolesController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const ScheduleController = require('../controllers/schedule.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, ScheduleController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), ScheduleController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, ScheduleController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), ScheduleController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), ScheduleController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const ShiftController = require('../controllers/shift.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, ShiftController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), ShiftController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, ShiftController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), ShiftController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), ShiftController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
const express = require("express");
|
|
||||||
const SparepartController = require("../controllers/sparepart.controller");
|
|
||||||
const verifyToken = require("../middleware/verifyToken");
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess");
|
|
||||||
const upload = require("../middleware/upload");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
"/export",
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
SparepartController.exportExcel
|
|
||||||
);
|
|
||||||
|
|
||||||
router.post(
|
|
||||||
"/import",
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
upload.single("file"),
|
|
||||||
SparepartController.importExcel
|
|
||||||
);
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, SparepartController.getAll)
|
|
||||||
.post(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
upload.single("sparepart_foto"),
|
|
||||||
SparepartController.create
|
|
||||||
);
|
|
||||||
|
|
||||||
router
|
|
||||||
.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, SparepartController.getById)
|
|
||||||
.put(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
upload.single("sparepart_foto"),
|
|
||||||
SparepartController.update
|
|
||||||
)
|
|
||||||
.delete(
|
|
||||||
verifyToken.verifyAccessToken,
|
|
||||||
verifyAccess(),
|
|
||||||
SparepartController.delete
|
|
||||||
);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const StatusController = require('../controllers/status.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken");
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess");
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, StatusController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), StatusController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, StatusController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), StatusController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), StatusController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const TagsController = require('../controllers/tags.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, TagsController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), TagsController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, TagsController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), TagsController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), TagsController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const UnitController = require('../controllers/unit.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route('/')
|
|
||||||
.get(verifyToken.verifyAccessToken, UnitController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), UnitController.create);
|
|
||||||
|
|
||||||
router.route('/:id')
|
|
||||||
.get(verifyToken.verifyAccessToken, UnitController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), UnitController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), UnitController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const UserSchedulesController = require('../controllers/user_schedule.controller');
|
|
||||||
const verifyToken = require("../middleware/verifyToken")
|
|
||||||
const verifyAccess = require("../middleware/verifyAccess")
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route("/")
|
|
||||||
.get(verifyToken.verifyAccessToken, UserSchedulesController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), UserSchedulesController.create);
|
|
||||||
|
|
||||||
router.route("/:id")
|
|
||||||
.get(verifyToken.verifyAccessToken, UserSchedulesController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), UserSchedulesController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), UserSchedulesController.delete);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
33
routes/users.js
Normal file
33
routes/users.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
const {
|
||||||
|
getAllUsers,
|
||||||
|
createUser,
|
||||||
|
deleteUser,
|
||||||
|
getUserById,
|
||||||
|
updateUser,
|
||||||
|
getUserProfile,
|
||||||
|
getAllRoles,
|
||||||
|
getAllStatusUsers
|
||||||
|
} = require("../controllers/users.controller");
|
||||||
|
const router = require("express").Router();
|
||||||
|
const verifyAdmin = require("../middleware/verifyAdmin");
|
||||||
|
const verifyToken = require("../middleware/verifyToken");
|
||||||
|
|
||||||
|
router.get("/roles", getAllRoles);
|
||||||
|
|
||||||
|
router.route("/profile")
|
||||||
|
.get(getUserProfile);
|
||||||
|
|
||||||
|
router.route("/")
|
||||||
|
.get(verifyToken, getAllUsers)
|
||||||
|
.post(verifyToken, createUser);
|
||||||
|
|
||||||
|
router
|
||||||
|
.route("/status")
|
||||||
|
.get(verifyToken, getAllStatusUsers);
|
||||||
|
|
||||||
|
router.route("/:id")
|
||||||
|
.get(verifyToken, getUserById)
|
||||||
|
.put(verifyToken, updateUser)
|
||||||
|
.delete(verifyToken, deleteUser);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const UserController = require('../controllers/users.controller');
|
|
||||||
const verifyToken = require('../middleware/verifyToken');
|
|
||||||
const verifyAccess = require('../middleware/verifyAccess');
|
|
||||||
|
|
||||||
const router = express.Router();
|
|
||||||
|
|
||||||
router.route('/')
|
|
||||||
.get(verifyToken.verifyAccessToken, UserController.getAll)
|
|
||||||
.post(verifyToken.verifyAccessToken, verifyAccess(), UserController.create);
|
|
||||||
|
|
||||||
router.route('/:id')
|
|
||||||
.get(verifyToken.verifyAccessToken, UserController.getById)
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), UserController.update)
|
|
||||||
.delete(verifyToken.verifyAccessToken, verifyAccess(), UserController.delete);
|
|
||||||
|
|
||||||
router.route('/change-password/:id')
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), UserController.changePassword);
|
|
||||||
|
|
||||||
router.route('/:id/approve')
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), UserController.approve);
|
|
||||||
|
|
||||||
router.route('/:id/reject')
|
|
||||||
.put(verifyToken.verifyAccessToken, verifyAccess(), UserController.reject);
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
@@ -1,130 +1,77 @@
|
|||||||
|
const bcrypt = require("bcrypt");
|
||||||
|
const jwt = require("jsonwebtoken");
|
||||||
|
const validateUser = require("../helpers/validateUser");
|
||||||
|
const { ErrorHandler } = require("../helpers/error");
|
||||||
const {
|
const {
|
||||||
getUserByUserEmailDb,
|
|
||||||
createUserDb,
|
|
||||||
getUserByUsernameDb
|
getUserByUsernameDb
|
||||||
} = require('../db/user.db');
|
} = require("../db/user.db");
|
||||||
const { hashPassword, comparePassword } = require('../helpers/hashPassword');
|
const { logger } = require("../utils/logger");
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
const JWTService = require('../utils/jwt');
|
|
||||||
|
|
||||||
class AuthService {
|
class AuthService {
|
||||||
// Register
|
|
||||||
static async register(data) {
|
async login(username, password, tenantId) {
|
||||||
try {
|
try {
|
||||||
const existingEmail = await getUserByUserEmailDb(data.user_email);
|
// if (!validateUser(username, password)) {
|
||||||
const existingUsername = await getUserByUsernameDb(data.user_name);
|
// throw new ErrorHandler(403, "Invalid login");
|
||||||
|
// }
|
||||||
|
|
||||||
if (existingUsername) {
|
const user = await getUserByUsernameDb(username, tenantId);
|
||||||
throw new ErrorHandler(400, 'Username is already taken');
|
console.log(user);
|
||||||
}
|
|
||||||
if (existingEmail) {
|
if (!user) {
|
||||||
throw new ErrorHandler(400, 'Email is already taken');
|
throw new ErrorHandler(403, "Username not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const hashedPassword = await hashPassword(data.user_password);
|
const isCorrectPassword = password === user.password
|
||||||
|
if (!isCorrectPassword) {
|
||||||
const userId = await createUserDb({
|
throw new ErrorHandler(403, "Username or password incorrect.");
|
||||||
user_fullname: data.user_fullname,
|
|
||||||
user_name: data.user_name,
|
|
||||||
user_email: data.user_email,
|
|
||||||
user_phone: data.user_phone,
|
|
||||||
user_password: hashedPassword,
|
|
||||||
is_sa: 0,
|
|
||||||
is_active: 1,
|
|
||||||
is_approve: 1,
|
|
||||||
});
|
|
||||||
|
|
||||||
const newUser = {
|
|
||||||
user_id: userId,
|
|
||||||
user_fullname: data.user_fullname,
|
|
||||||
user_name: data.user_name,
|
|
||||||
user_email: data.user_email,
|
|
||||||
user_phone: data.user_phone
|
|
||||||
};
|
|
||||||
|
|
||||||
return { user: newUser };
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login
|
const dataToken = {
|
||||||
static async login(data) {
|
tenant_id: tenantId,
|
||||||
try {
|
|
||||||
const { identifier, password, captcha, captchaText } = data;
|
|
||||||
|
|
||||||
if (!captcha || captcha.toLowerCase() !== captchaText.toLowerCase()) {
|
|
||||||
throw new ErrorHandler(400, 'Invalid captcha');
|
|
||||||
}
|
|
||||||
|
|
||||||
let user;
|
|
||||||
if (identifier.includes('@')) {
|
|
||||||
user = await getUserByUserEmailDb(identifier);
|
|
||||||
} else {
|
|
||||||
user = await getUserByUsernameDb(identifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user) throw new ErrorHandler(401, 'Invalid credentials');
|
|
||||||
|
|
||||||
const passwordMatch = await comparePassword(password, user.user_password);
|
|
||||||
if (!passwordMatch) throw new ErrorHandler(401, 'Invalid credentials');
|
|
||||||
|
|
||||||
if (!user.is_active) throw new ErrorHandler(403, 'User is inactive');
|
|
||||||
if (!user.is_approve) throw new ErrorHandler(403, 'Your account has not been approved by admin yet.');
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
user_id: user.user_id,
|
user_id: user.user_id,
|
||||||
user_fullname: user.user_fullname,
|
username,
|
||||||
user_name: user.user_name,
|
fullname: user.full_name,
|
||||||
user_email: user.user_email,
|
role_id: user.role_id
|
||||||
user_phone: user.user_phone,
|
|
||||||
role_id: user.role_id,
|
|
||||||
role_name: user.role_name,
|
|
||||||
is_sa: user.is_sa
|
|
||||||
};
|
|
||||||
|
|
||||||
const tokens = JWTService.generateTokenPair(payload);
|
|
||||||
return { user: payload, tokens };
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh Token
|
const token = await this.signToken(dataToken);
|
||||||
static async refreshToken(refreshToken) {
|
const refreshToken = await this.signRefreshToken(dataToken);
|
||||||
try {
|
|
||||||
let decoded;
|
|
||||||
try {
|
|
||||||
decoded = JWTService.verifyRefreshToken(refreshToken);
|
|
||||||
} catch (err) {
|
|
||||||
if (err.message.includes('expired')) {
|
|
||||||
throw new ErrorHandler(401, 'Refresh token expired');
|
|
||||||
}
|
|
||||||
throw new ErrorHandler(401, 'Invalid refresh token');
|
|
||||||
}
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
user_id: decoded.user_id,
|
|
||||||
user_fullname: decoded.user_fullname,
|
|
||||||
user_name: decoded.user_name,
|
|
||||||
user_email: decoded.user_email,
|
|
||||||
user_phone: decoded.user_phone,
|
|
||||||
role_id: decoded.role_id,
|
|
||||||
role_name: decoded.role_name,
|
|
||||||
is_sa: decoded.is_sa
|
|
||||||
};
|
|
||||||
|
|
||||||
const accessToken = JWTService.generateAccessToken(payload);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
accessToken,
|
token,
|
||||||
tokenType: 'Bearer',
|
refreshToken,
|
||||||
expiresIn: 900
|
role_id: dataToken.role_id,
|
||||||
|
tenant_id: tenantId,
|
||||||
|
user: {
|
||||||
|
user_id: dataToken.user_id,
|
||||||
|
fullname: dataToken.fullname,
|
||||||
|
username: dataToken.username,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
throw new ErrorHandler(error.statusCode, error.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async signToken(data) {
|
||||||
|
try {
|
||||||
|
// console.log("signToken process.env.SECRET", process.env.SECRET)
|
||||||
|
return jwt.sign(data, process.env.SECRET, { expiresIn: "23h" });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
throw new ErrorHandler(500, "An error occurred");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AuthService;
|
async signRefreshToken(data) {
|
||||||
|
try {
|
||||||
|
return jwt.sign(data, process.env.REFRESH_SECRET, { expiresIn: "23h" });
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
throw new ErrorHandler(500, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new AuthService();
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
// Brand operations
|
|
||||||
const {
|
|
||||||
getAllBrandsDb,
|
|
||||||
getBrandByIdDb,
|
|
||||||
createBrandDb,
|
|
||||||
updateBrandDb,
|
|
||||||
deleteBrandDb,
|
|
||||||
checkBrandNameExistsDb,
|
|
||||||
} = require("../db/brand.db");
|
|
||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
|
|
||||||
class BrandService {
|
|
||||||
// Get all brands
|
|
||||||
static async getAllBrands(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllBrandsDb(param);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...results,
|
|
||||||
data: results.data
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get brand by ID (without error codes)
|
|
||||||
static async getBrandById(id) {
|
|
||||||
try {
|
|
||||||
const brand = await getBrandByIdDb(id);
|
|
||||||
if (!brand) throw new ErrorHandler(404, "Brand not found");
|
|
||||||
|
|
||||||
return brand;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Create brand
|
|
||||||
static async createBrand(data) {
|
|
||||||
try {
|
|
||||||
if (data.brand_name) {
|
|
||||||
const brandExists = await checkBrandNameExistsDb(data.brand_name);
|
|
||||||
if (brandExists) {
|
|
||||||
throw new ErrorHandler(400, "Brand name already exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const brandData = {
|
|
||||||
brand_name: data.brand_name,
|
|
||||||
brand_type: data.brand_type,
|
|
||||||
brand_manufacture: data.brand_manufacture,
|
|
||||||
brand_model: data.brand_model,
|
|
||||||
is_active: data.is_active !== undefined ? data.is_active : true,
|
|
||||||
created_by: data.created_by,
|
|
||||||
};
|
|
||||||
|
|
||||||
const createdBrand = await createBrandDb(brandData);
|
|
||||||
if (!createdBrand) {
|
|
||||||
throw new ErrorHandler(500, "Failed to create brand");
|
|
||||||
}
|
|
||||||
|
|
||||||
return createdBrand;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete brand by ID
|
|
||||||
static async deleteBrand(id, userId) {
|
|
||||||
try {
|
|
||||||
const brandExist = await getBrandByIdDb(id);
|
|
||||||
|
|
||||||
if (!brandExist) {
|
|
||||||
throw new ErrorHandler(404, "Brand not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteBrandDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Update brand
|
|
||||||
static async updateBrand(id, data) {
|
|
||||||
try {
|
|
||||||
const existingBrand = await getBrandByIdDb(id);
|
|
||||||
if (!existingBrand) throw new ErrorHandler(404, "Brand not found");
|
|
||||||
|
|
||||||
if (data.brand_name && data.brand_name !== existingBrand.brand_name) {
|
|
||||||
const brandExists = await checkBrandNameExistsDb(data.brand_name, id);
|
|
||||||
if (brandExists) {
|
|
||||||
throw new ErrorHandler(400, "Brand name already exists");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const brandData = {
|
|
||||||
brand_name: data.brand_name || existingBrand.brand_name,
|
|
||||||
brand_type: data.brand_type !== undefined ? data.brand_type : existingBrand.brand_type,
|
|
||||||
brand_manufacture: data.brand_manufacture !== undefined ? data.brand_manufacture : existingBrand.brand_manufacture,
|
|
||||||
brand_model: data.brand_model !== undefined ? data.brand_model : existingBrand.brand_model,
|
|
||||||
is_active: data.is_active !== undefined ? data.is_active : existingBrand.is_active,
|
|
||||||
updated_by: data.updated_by,
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatedBrand = await updateBrandDb(existingBrand.brand_name, brandData);
|
|
||||||
if (!updatedBrand) {
|
|
||||||
throw new ErrorHandler(500, "Failed to update brand");
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatedBrand;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = BrandService;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllContactDb,
|
|
||||||
getContactByIdDb,
|
|
||||||
createContactDb,
|
|
||||||
updateContactDb,
|
|
||||||
deleteContactDb
|
|
||||||
} = require('../db/contact.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class ContactService {
|
|
||||||
// Get all Contact
|
|
||||||
static async getAllContact(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllContactDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Contact by ID
|
|
||||||
static async getContactById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getContactByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Contact not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Contact
|
|
||||||
static async createContact(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await createContactDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Contact
|
|
||||||
static async updateContact(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getContactByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Contact not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateContactDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Contact
|
|
||||||
static async deleteContact(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getContactByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Contact not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteContactDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ContactService;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllDevicesDb,
|
|
||||||
getDeviceByIdDb,
|
|
||||||
createDeviceDb,
|
|
||||||
updateDeviceDb,
|
|
||||||
deleteDeviceDb
|
|
||||||
} = require('../db/device.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class DeviceService {
|
|
||||||
// Get all devices
|
|
||||||
static async getAllDevices(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllDevicesDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get device by ID
|
|
||||||
static async getDeviceById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getDeviceByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Device not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create device
|
|
||||||
static async createDevice(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await createDeviceDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update device
|
|
||||||
static async updateDevice(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getDeviceByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Device not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateDeviceDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete device
|
|
||||||
static async deleteDevice(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getDeviceByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Device not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteDeviceDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = DeviceService;
|
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
const {
|
|
||||||
getErrorCodesByBrandIdDb,
|
|
||||||
getErrorCodeByIdDb,
|
|
||||||
getErrorCodeByBrandAndCodeDb,
|
|
||||||
createErrorCodeDb,
|
|
||||||
updateErrorCodeDb,
|
|
||||||
deleteErrorCodeDb,
|
|
||||||
getAllErrorCodesDb,
|
|
||||||
} = require("../db/brand_code.db");
|
|
||||||
|
|
||||||
const {
|
|
||||||
getSolutionsByErrorCodeIdDb,
|
|
||||||
createSolutionDb,
|
|
||||||
updateSolutionDb,
|
|
||||||
deleteSolutionDb,
|
|
||||||
} = require("../db/brand_code_solution.db");
|
|
||||||
|
|
||||||
const {
|
|
||||||
getSparepartsByErrorCodeIdDb,
|
|
||||||
insertMultipleErrorCodeSparepartsDb,
|
|
||||||
updateErrorCodeSparepartsDb,
|
|
||||||
} = require("../db/brand_sparepart.db");
|
|
||||||
|
|
||||||
const { getFileUploadByPathDb } = require("../db/file_uploads.db");
|
|
||||||
|
|
||||||
class ErrorCodeService {
|
|
||||||
static async getAllErrorCodes(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllErrorCodesDb(param);
|
|
||||||
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get error code by ID with complete data
|
|
||||||
static async getErrorCodeById(id) {
|
|
||||||
try {
|
|
||||||
const errorCode = await getErrorCodeByIdDb(id);
|
|
||||||
if (!errorCode) throw new ErrorHandler(404, "Error code not found");
|
|
||||||
|
|
||||||
const solutions = await getSolutionsByErrorCodeIdDb(errorCode.error_code_id);
|
|
||||||
const spareparts = await getSparepartsByErrorCodeIdDb(errorCode.error_code_id);
|
|
||||||
|
|
||||||
const solutionsWithFiles = await Promise.all(
|
|
||||||
solutions.map(async (solution) => {
|
|
||||||
let fileData = null;
|
|
||||||
|
|
||||||
if (solution.path_solution && solution.type_solution !== "text") {
|
|
||||||
fileData = await getFileUploadByPathDb(solution.path_solution);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...solution,
|
|
||||||
file_upload_name: fileData?.file_upload_name || null,
|
|
||||||
path_document: fileData?.path_document || null,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...errorCode,
|
|
||||||
solution: solutionsWithFiles,
|
|
||||||
spareparts: spareparts,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get error codes by brand ID
|
|
||||||
static async getErrorCodesByBrandId(brandId, queryParams = {}) {
|
|
||||||
try {
|
|
||||||
const results = await getErrorCodesByBrandIdDb(brandId, queryParams);
|
|
||||||
|
|
||||||
if (results.data && results.total !== undefined) {
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorCodesWithDetails = await Promise.all(
|
|
||||||
results.map(async (errorCode) => {
|
|
||||||
const solutions = await getSolutionsByErrorCodeIdDb(errorCode.error_code_id);
|
|
||||||
const spareparts = await getSparepartsByErrorCodeIdDb(errorCode.error_code_id);
|
|
||||||
|
|
||||||
const solutionsWithFiles = await Promise.all(
|
|
||||||
solutions.map(async (solution) => {
|
|
||||||
let fileData = null;
|
|
||||||
|
|
||||||
if (solution.path_solution && solution.type_solution !== "text") {
|
|
||||||
fileData = await getFileUploadByPathDb(solution.path_solution);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...solution,
|
|
||||||
file_upload_name: fileData?.file_upload_name || null,
|
|
||||||
path_document: fileData?.path_document || null,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...errorCode,
|
|
||||||
solution: solutionsWithFiles,
|
|
||||||
spareparts: spareparts,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
return errorCodesWithDetails;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create error code with solutions and spareparts
|
|
||||||
static async createErrorCodeWithFullData(brandId, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== "object") data = {};
|
|
||||||
|
|
||||||
const errorId = await createErrorCodeDb(brandId, {
|
|
||||||
error_code: data.error_code,
|
|
||||||
error_code_name: data.error_code_name,
|
|
||||||
error_code_description: data.error_code_description,
|
|
||||||
error_code_color: data.error_code_color,
|
|
||||||
path_icon: data.path_icon,
|
|
||||||
is_active: data.is_active,
|
|
||||||
created_by: data.created_by,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!errorId) {
|
|
||||||
throw new Error("Failed to create error code");
|
|
||||||
}
|
|
||||||
if (data.spareparts && Array.isArray(data.spareparts)) {
|
|
||||||
await insertMultipleErrorCodeSparepartsDb(errorId, data.spareparts, data.created_by);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.solution && Array.isArray(data.solution)) {
|
|
||||||
for (const solutionData of data.solution) {
|
|
||||||
await createSolutionDb(errorId, {
|
|
||||||
solution_name: solutionData.solution_name,
|
|
||||||
type_solution: solutionData.type_solution,
|
|
||||||
text_solution: solutionData.text_solution || null,
|
|
||||||
path_solution: solutionData.path_solution || null,
|
|
||||||
is_active: solutionData.is_active,
|
|
||||||
created_by: data.created_by,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const createdErrorCode = await this.getErrorCodeById(errorId);
|
|
||||||
return createdErrorCode;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(500, `Create error code failed: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update error code with solutions and spareparts
|
|
||||||
static async updateErrorCodeWithFullData(brandId, errorCodeId, data) {
|
|
||||||
try {
|
|
||||||
const existingErrorCode = await getErrorCodeByIdDb(errorCodeId);
|
|
||||||
if (!existingErrorCode) throw new ErrorHandler(404, "Error code not found");
|
|
||||||
|
|
||||||
// Verify the error code belongs to the specified brand
|
|
||||||
if (existingErrorCode.brand_id !== parseInt(brandId)) {
|
|
||||||
throw new ErrorHandler(403, "Error code does not belong to specified brand");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are any error code fields to update
|
|
||||||
const hasMainFieldUpdate =
|
|
||||||
data.error_code !== undefined ||
|
|
||||||
data.error_code_name !== undefined ||
|
|
||||||
data.error_code_description !== undefined ||
|
|
||||||
data.error_code_color !== undefined ||
|
|
||||||
data.path_icon !== undefined ||
|
|
||||||
data.is_active !== undefined;
|
|
||||||
|
|
||||||
if (hasMainFieldUpdate) {
|
|
||||||
await updateErrorCodeDb(brandId, existingErrorCode.error_code, {
|
|
||||||
error_code: data.error_code,
|
|
||||||
error_code_name: data.error_code_name,
|
|
||||||
error_code_description: data.error_code_description,
|
|
||||||
error_code_color: data.error_code_color,
|
|
||||||
path_icon: data.path_icon,
|
|
||||||
is_active: data.is_active,
|
|
||||||
updated_by: data.updated_by,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.spareparts && Array.isArray(data.spareparts)) {
|
|
||||||
await updateErrorCodeSparepartsDb(existingErrorCode.error_code_id, data.spareparts, data.updated_by);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.solution && Array.isArray(data.solution)) {
|
|
||||||
const existingSolutions = await getSolutionsByErrorCodeIdDb(existingErrorCode.error_code_id);
|
|
||||||
const incomingSolutionNames = data.solution.map((s) => s.solution_name);
|
|
||||||
|
|
||||||
for (const solutionData of data.solution) {
|
|
||||||
const existingSolution = existingSolutions.find(
|
|
||||||
(s) => s.solution_name === solutionData.solution_name
|
|
||||||
);
|
|
||||||
|
|
||||||
if (existingSolution) {
|
|
||||||
await updateSolutionDb(
|
|
||||||
existingSolution.brand_code_solution_id,
|
|
||||||
{
|
|
||||||
solution_name: solutionData.solution_name,
|
|
||||||
type_solution: solutionData.type_solution,
|
|
||||||
text_solution: solutionData.text_solution || null,
|
|
||||||
path_solution: solutionData.path_solution || null,
|
|
||||||
is_active: solutionData.is_active,
|
|
||||||
updated_by: data.updated_by,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
await createSolutionDb(existingErrorCode.error_code_id, {
|
|
||||||
solution_name: solutionData.solution_name,
|
|
||||||
type_solution: solutionData.type_solution,
|
|
||||||
text_solution: solutionData.text_solution || null,
|
|
||||||
path_solution: solutionData.path_solution || null,
|
|
||||||
is_active: solutionData.is_active,
|
|
||||||
created_by: data.updated_by,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const existingSolution of existingSolutions) {
|
|
||||||
if (!incomingSolutionNames.includes(existingSolution.solution_name)) {
|
|
||||||
await deleteSolutionDb(existingSolution.brand_code_solution_id, data.updated_by);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const updatedErrorCode = await this.getErrorCodeById(existingErrorCode.error_code_id);
|
|
||||||
return updatedErrorCode;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(500, `Update error code failed: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete error code
|
|
||||||
static async deleteErrorCode(brandId, errorCodeId, deletedBy) {
|
|
||||||
try {
|
|
||||||
const errorCodeExist = await getErrorCodeByIdDb(errorCodeId);
|
|
||||||
|
|
||||||
if (!errorCodeExist) {
|
|
||||||
throw new ErrorHandler(404, "Error code not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify the error code belongs to the specified brand
|
|
||||||
if (errorCodeExist.brand_id !== parseInt(brandId)) {
|
|
||||||
throw new ErrorHandler(403, "Error code does not belong to specified brand");
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteErrorCodeDb(brandId, errorCodeExist.error_code, deletedBy);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ErrorCodeService;
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
const {
|
|
||||||
getHistoryAlarmDb,
|
|
||||||
getHistoryEventDb,
|
|
||||||
checkTableNamedDb,
|
|
||||||
getHistoryValueReportDb,
|
|
||||||
getHistoryValueReportPivotDb,
|
|
||||||
getHistoryValueTrendingPivotDb
|
|
||||||
} = require('../db/history_value.db');
|
|
||||||
const { getSubSectionByIdDb } = require('../db/plant_sub_section.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class HistoryValue {
|
|
||||||
|
|
||||||
static async getAllHistoryAlarm(param) {
|
|
||||||
try {
|
|
||||||
const results = await getHistoryAlarmDb(param);
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message || 'Error fetching alarm history');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getAllHistoryEvent(param) {
|
|
||||||
try {
|
|
||||||
const results = await getHistoryEventDb(param);
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message || 'Error fetching event history');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getHistoryValueReport(param) {
|
|
||||||
try {
|
|
||||||
if (!param.plant_sub_section_id) {
|
|
||||||
throw new ErrorHandler(400, 'plant_sub_section_id is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const plantSubSection = await getSubSectionByIdDb(param.plant_sub_section_id);
|
|
||||||
|
|
||||||
if (!plantSubSection || plantSubSection.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Plant sub section not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableNameValue = plantSubSection[0]?.table_name_value;
|
|
||||||
|
|
||||||
if (!tableNameValue) {
|
|
||||||
throw new ErrorHandler(404, 'Table name not configured for this sub section');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableExist = await checkTableNamedDb(tableNameValue);
|
|
||||||
|
|
||||||
if (!tableExist || tableExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, `Value table '${tableNameValue}' not found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await getHistoryValueReportDb(tableExist[0].TABLE_NAME, param);
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(
|
|
||||||
error.statusCode || 500,
|
|
||||||
error.message || 'Error fetching history value report'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getHistoryValueReportPivot(param) {
|
|
||||||
try {
|
|
||||||
if (!param.plant_sub_section_id) {
|
|
||||||
throw new ErrorHandler(400, 'plant_sub_section_id is required');
|
|
||||||
}
|
|
||||||
if (!param.from || !param.to) {
|
|
||||||
throw new ErrorHandler(400, 'from and to date parameters are required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const plantSubSection = await getSubSectionByIdDb(param.plant_sub_section_id);
|
|
||||||
|
|
||||||
if (!plantSubSection || plantSubSection.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Plant sub section not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableNameValue = plantSubSection[0]?.table_name_value;
|
|
||||||
|
|
||||||
if (!tableNameValue) {
|
|
||||||
throw new ErrorHandler(404, 'Table name not configured for this sub section');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableExist = await checkTableNamedDb(tableNameValue);
|
|
||||||
|
|
||||||
if (!tableExist || tableExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, `Value table '${tableNameValue}' not found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await getHistoryValueReportPivotDb(tableExist[0].TABLE_NAME, param);
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(
|
|
||||||
error.statusCode || 500,
|
|
||||||
error.message || 'Error fetching history value report pivot'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getHistoryValueTrendingPivot(param) {
|
|
||||||
try {
|
|
||||||
if (!param.plant_sub_section_id) {
|
|
||||||
throw new ErrorHandler(400, 'plant_sub_section_id is required');
|
|
||||||
}
|
|
||||||
if (!param.from || !param.to) {
|
|
||||||
throw new ErrorHandler(400, 'from and to date parameters are required');
|
|
||||||
}
|
|
||||||
|
|
||||||
const plantSubSection = await getSubSectionByIdDb(param.plant_sub_section_id);
|
|
||||||
|
|
||||||
if (!plantSubSection || plantSubSection.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Plant sub section not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableNameValue = plantSubSection[0]?.table_name_value;
|
|
||||||
|
|
||||||
if (!tableNameValue) {
|
|
||||||
throw new ErrorHandler(404, 'Table name not configured for this sub section');
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableExist = await checkTableNamedDb(tableNameValue);
|
|
||||||
|
|
||||||
if (!tableExist || tableExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, `Value table '${tableNameValue}' not found`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const results = await getHistoryValueTrendingPivotDb(tableExist[0].TABLE_NAME, param);
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(
|
|
||||||
error.statusCode || 500,
|
|
||||||
error.message || 'Error fetching history value trending pivot'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = HistoryValue;
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
// services/notification_error.service.js
|
|
||||||
const {
|
|
||||||
getAllNotificationDb,
|
|
||||||
getNotificationByIdDb,
|
|
||||||
InsertNotificationErrorDb,
|
|
||||||
getUsersNotificationErrorDb,
|
|
||||||
updateNotificationErrorDb,
|
|
||||||
} = require("../db/notification_error.db");
|
|
||||||
|
|
||||||
const { getErrorCodeByIdDb } = require("../db/brand_code.db");
|
|
||||||
|
|
||||||
const { getSolutionsByErrorCodeIdDb } = require("../db/brand_code_solution.db");
|
|
||||||
|
|
||||||
const {
|
|
||||||
getAllNotificationErrorLogDb,
|
|
||||||
getNotificationErrorLogByNotificationErrorIdDb,
|
|
||||||
} = require("../db/notification_error_log.db");
|
|
||||||
|
|
||||||
const { getSparepartsByErrorCodeIdDb } = require("../db/brand_sparepart.db");
|
|
||||||
|
|
||||||
const {
|
|
||||||
getNotificationErrorByIdDb,
|
|
||||||
} = require("../db/notification_error_user.db");
|
|
||||||
|
|
||||||
const { getFileUploadByPathDb } = require("../db/file_uploads.db");
|
|
||||||
|
|
||||||
const {
|
|
||||||
generateTokenRedirect,
|
|
||||||
shortUrltiny,
|
|
||||||
sendNotifikasi,
|
|
||||||
} = require("../db/notification_wa.db");
|
|
||||||
|
|
||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
|
|
||||||
class NotificationService {
|
|
||||||
static async getAllNotification(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllNotificationDb(param);
|
|
||||||
|
|
||||||
if (results && Array.isArray(results.data)) {
|
|
||||||
results.data = await Promise.all(
|
|
||||||
results.data.map(async (notification) => {
|
|
||||||
const usersNotification =
|
|
||||||
(await getUsersNotificationErrorDb(
|
|
||||||
notification.notification_error_id
|
|
||||||
)) || [];
|
|
||||||
return {
|
|
||||||
...notification,
|
|
||||||
users: usersNotification,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async createNotificationError(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== "object") data = {};
|
|
||||||
|
|
||||||
const result = await InsertNotificationErrorDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getNotificationById(id) {
|
|
||||||
try {
|
|
||||||
const notification = await getNotificationByIdDb(id);
|
|
||||||
|
|
||||||
if (
|
|
||||||
!notification ||
|
|
||||||
(Array.isArray(notification) && notification.length < 1)
|
|
||||||
) {
|
|
||||||
throw new ErrorHandler(404, "Notification not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const usersNotification = (await getUsersNotificationErrorDb(id)) || [];
|
|
||||||
|
|
||||||
// Get error code details if error_code_id exists
|
|
||||||
if (notification.error_code_id) {
|
|
||||||
const errorCode = await getErrorCodeByIdDb(notification.error_code_id);
|
|
||||||
|
|
||||||
if (errorCode) {
|
|
||||||
// Get solutions for this error code
|
|
||||||
const solutions =
|
|
||||||
(await getSolutionsByErrorCodeIdDb(errorCode.error_code_id)) || [];
|
|
||||||
|
|
||||||
const spareparts =
|
|
||||||
(await getSparepartsByErrorCodeIdDb(errorCode.error_code_id)) || [];
|
|
||||||
|
|
||||||
const solutionsWithDetails = await Promise.all(
|
|
||||||
solutions.map(async (solution) => {
|
|
||||||
let fileData = null;
|
|
||||||
if (
|
|
||||||
solution.path_solution &&
|
|
||||||
solution.type_solution &&
|
|
||||||
solution.type_solution !== "text"
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
fileData = await getFileUploadByPathDb(
|
|
||||||
solution.path_solution
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
fileData = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...solution,
|
|
||||||
file_upload_name: fileData?.file_upload_name || null,
|
|
||||||
path_document: fileData?.path_document || null,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
notification.error_code = {
|
|
||||||
...errorCode,
|
|
||||||
solution: solutionsWithDetails,
|
|
||||||
spareparts: spareparts,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get activity logs for this notification
|
|
||||||
const notificationLogs =
|
|
||||||
(await getNotificationErrorLogByNotificationErrorIdDb(id)) || [];
|
|
||||||
|
|
||||||
notification.users = usersNotification;
|
|
||||||
|
|
||||||
notification.activity_logs = notificationLogs;
|
|
||||||
|
|
||||||
return notification;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async updateNotificationError(notification_error_id, data) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getNotificationErrorByIdDb(notification_error_id);
|
|
||||||
|
|
||||||
if (!dataExist || (Array.isArray(dataExist) && dataExist.length < 1)) {
|
|
||||||
throw new ErrorHandler(404, "Notification Error User not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const notification = Array.isArray(dataExist) ? dataExist[0] : dataExist;
|
|
||||||
|
|
||||||
if (notification.is_read === true) {
|
|
||||||
return { success: true, message: "Notification has already been read" };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!notification.is_read) {
|
|
||||||
const updateStatus = await updateNotificationErrorDb(
|
|
||||||
notification_error_id,
|
|
||||||
{ is_read: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!updateStatus) {
|
|
||||||
throw new ErrorHandler(500, "Failed to update notification");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { success: true, message: "Notification marked as read" };
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async resendNotification(id) {
|
|
||||||
const deviceNotification = await getNotificationByIdDb(id);
|
|
||||||
if (!deviceNotification) throw new ErrorHandler(404, "Data not found");
|
|
||||||
|
|
||||||
const errorCode = await getErrorCodeByIdDb(
|
|
||||||
deviceNotification.error_code_id
|
|
||||||
);
|
|
||||||
const dataExist = await getUsersNotificationErrorDb(id);
|
|
||||||
|
|
||||||
const activeUsers =
|
|
||||||
dataExist?.filter((user) => user.is_active === true) || [];
|
|
||||||
|
|
||||||
if (activeUsers.length < 1)
|
|
||||||
throw new ErrorHandler(404, "No active contacts");
|
|
||||||
|
|
||||||
this._executeResendWa(
|
|
||||||
id,
|
|
||||||
activeUsers,
|
|
||||||
deviceNotification,
|
|
||||||
errorCode
|
|
||||||
).catch((err) => console.error("Background Process Error:", err));
|
|
||||||
|
|
||||||
return {
|
|
||||||
count: activeUsers.length,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static async _executeResendWa(
|
|
||||||
id,
|
|
||||||
activeUsers,
|
|
||||||
deviceNotification,
|
|
||||||
errorCode
|
|
||||||
) {
|
|
||||||
console.log(`user active: `, id, activeUsers);
|
|
||||||
|
|
||||||
const sendPromises = activeUsers.map(async (user) => {
|
|
||||||
try {
|
|
||||||
console.log(`user: ${user.contact_name} (${user.contact_phone})`);
|
|
||||||
const tokenRedirect = await generateTokenRedirect(
|
|
||||||
user.contact_phone,
|
|
||||||
user.contact_name,
|
|
||||||
id
|
|
||||||
);
|
|
||||||
|
|
||||||
const encodedToken = encodeURIComponent(tokenRedirect);
|
|
||||||
console.log("token: ", tokenRedirect);
|
|
||||||
const shortUrl = await shortUrltiny(encodedToken);
|
|
||||||
console.log("URL:", shortUrl);
|
|
||||||
|
|
||||||
const bodyWithUrl =
|
|
||||||
`Hai ${user.contact_name || "-"}\n` +
|
|
||||||
`Terjadi peringatan dengan kode ${errorCode?.error_code || "-"} - ${
|
|
||||||
errorCode?.error_code_name
|
|
||||||
} pada device ${deviceNotification.device_name || "-"}.\n` +
|
|
||||||
`Silahkan cek detail pada link berikut:\n ${shortUrl}`;
|
|
||||||
|
|
||||||
const resultSend = await sendNotifikasi(
|
|
||||||
user.contact_phone,
|
|
||||||
bodyWithUrl
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log("notifikasi wa:", resultSend)
|
|
||||||
|
|
||||||
const isSuccess = resultSend.success;
|
|
||||||
|
|
||||||
await updateNotificationErrorDb(user.notification_error_id, {
|
|
||||||
is_send: isSuccess,
|
|
||||||
is_delivered: isSuccess,
|
|
||||||
});
|
|
||||||
|
|
||||||
return { phone: user.contact_phone, status: "success" };
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`Gagal mengirim ke ${user.contact_phone}:`, err.message);
|
|
||||||
return {
|
|
||||||
phone: user.contact_phone,
|
|
||||||
status: "failed",
|
|
||||||
error: err.message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = await Promise.all(sendPromises);
|
|
||||||
console.log("result akhir: ", results)
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Resend chat: ${
|
|
||||||
results.filter((r) => r.status === "success").length
|
|
||||||
}, Gagal: ${results.filter((r) => r.status === "failed").length}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationService;
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllNotificationErrorLogDb,
|
|
||||||
getNotificationErrorLogByIdDb,
|
|
||||||
getNotificationErrorLogByNotificationErrorIdDb,
|
|
||||||
createNotificationErrorLogDb,
|
|
||||||
updateNotificationErrorLogDb,
|
|
||||||
deleteNotificationErrorLogDb
|
|
||||||
} = require('../db/notification_error_log.db');
|
|
||||||
|
|
||||||
const { getUserByIdDb } = require('../db/user.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class NotificationErrorLogService {
|
|
||||||
// Get all Notification Error Logs
|
|
||||||
static async getAllNotificationErrorLog() {
|
|
||||||
try {
|
|
||||||
const results = await getAllNotificationErrorLogDb();
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Notification Error Log by ID
|
|
||||||
static async getNotificationErrorLogById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getNotificationErrorLogByIdDb(id);
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
throw new ErrorHandler(404, 'Notification Error Log not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Notification Error Log
|
|
||||||
static async createNotificationErrorLog(data, userId) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
let createdBy = null;
|
|
||||||
let contactPhone = data.contact_phone || null;
|
|
||||||
|
|
||||||
if (userId) {
|
|
||||||
try {
|
|
||||||
const user = await getUserByIdDb(userId);
|
|
||||||
|
|
||||||
if (user && user.user_id) {
|
|
||||||
createdBy = Number(user.user_id);
|
|
||||||
} else {
|
|
||||||
createdBy = null;
|
|
||||||
contactPhone = userId;
|
|
||||||
}
|
|
||||||
} catch (dbError) {
|
|
||||||
createdBy = null;
|
|
||||||
contactPhone = userId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = {
|
|
||||||
notification_error_id: data.notification_error_id,
|
|
||||||
contact_phone: contactPhone,
|
|
||||||
notification_error_log_description: data.notification_error_log_description,
|
|
||||||
created_by: createdBy
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await createNotificationErrorLogDb(store);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Notification Error Log by notification_error_id
|
|
||||||
static async getNotificationErrorLogByNotificationErrorId(notificationErrorId) {
|
|
||||||
try {
|
|
||||||
const results = await getNotificationErrorLogByNotificationErrorIdDb(notificationErrorId);
|
|
||||||
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Notification Error Log
|
|
||||||
static async deleteNotificationErrorLog(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getNotificationErrorLogByIdDb(id);
|
|
||||||
|
|
||||||
if (!dataExist) {
|
|
||||||
throw new ErrorHandler(404, 'Notification Error Log not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteNotificationErrorLogDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorLogService;
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllNotificationErrorSparepartDb,
|
|
||||||
getNotificationErrorSparepartByIdDb,
|
|
||||||
createNotificationErrorSparepartDb,
|
|
||||||
updateNotificationErrorSparepartDb,
|
|
||||||
deleteNotificationErrorSparepartDb,
|
|
||||||
} = require("../db/notification_error_sparepart.db");
|
|
||||||
|
|
||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
|
|
||||||
class NotificationErrorSparepartService {
|
|
||||||
|
|
||||||
static async getAll(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllNotificationErrorSparepartDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getById(id) {
|
|
||||||
const result = await getNotificationErrorSparepartByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1)
|
|
||||||
throw new ErrorHandler(404, "Notification Error Sparepart not found");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async create(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await createNotificationErrorSparepartDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async update(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getNotificationErrorSparepartByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Notification Error Sparepart not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateNotificationErrorSparepartDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async delete(id) {
|
|
||||||
|
|
||||||
const exist = await getNotificationErrorSparepartByIdDb(id);
|
|
||||||
|
|
||||||
if (exist.length < 1)
|
|
||||||
throw new ErrorHandler(404, "Notification Error Sparepart not found");
|
|
||||||
|
|
||||||
return await deleteNotificationErrorSparepartDb(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorSparepartService;
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllNotificationErrorUserDb,
|
|
||||||
getNotificationErrorUserByIdDb,
|
|
||||||
createNotificationErrorUserDb,
|
|
||||||
updateNotificationErrorUserDb,
|
|
||||||
deleteNotificationErrorUserDb,
|
|
||||||
} = require("../db/notification_error_user.db");
|
|
||||||
|
|
||||||
const {
|
|
||||||
generateTokenRedirect,
|
|
||||||
shortUrltiny,
|
|
||||||
sendNotifikasi,
|
|
||||||
} = require("../db/notification_wa.db");
|
|
||||||
|
|
||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
|
|
||||||
class NotificationErrorUserService {
|
|
||||||
// Get all Contact
|
|
||||||
static async getAllNotificationErrorUser(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllNotificationErrorUserDb(param);
|
|
||||||
|
|
||||||
results.data.map((element) => {});
|
|
||||||
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get NotificationErrorUser by ID
|
|
||||||
static async getNotificationErrorUserById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getNotificationErrorUserByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1)
|
|
||||||
throw new ErrorHandler(404, "Notification Error User not found");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create NotificationErrorUser
|
|
||||||
static async createNotificationErrorUser(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== "object") data = {};
|
|
||||||
|
|
||||||
const result = await createNotificationErrorUserDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update NotificationErrorUser
|
|
||||||
static async updateNotificationErrorUser(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== "object") data = {};
|
|
||||||
|
|
||||||
const dataExist = await getNotificationErrorUserByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, "Notification Error User not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateNotificationErrorUserDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete NotificationErrorUser
|
|
||||||
static async deleteNotificationErrorUser(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getNotificationErrorUserByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, "Notification Error User not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteNotificationErrorUserDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async resendNotificationByUser(id, contact_phone) {
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
const idUser = Array.isArray(id) ? id : [id];
|
|
||||||
|
|
||||||
for (const id of idUser) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getNotificationErrorUserByIdDb(id);
|
|
||||||
|
|
||||||
if (!dataExist || dataExist.length < 1) {
|
|
||||||
results.push({
|
|
||||||
id,
|
|
||||||
status: "failed",
|
|
||||||
message: "Data Notification Error User not found",
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = dataExist[0];
|
|
||||||
|
|
||||||
if (data.contact_phone !== contact_phone) {
|
|
||||||
results.push({
|
|
||||||
id,
|
|
||||||
status: "failed",
|
|
||||||
message: `Phone ${contact_phone} not found.`,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.contact_is_active === false) {
|
|
||||||
results.push({
|
|
||||||
id,
|
|
||||||
status: "failed",
|
|
||||||
message: `Contact ${data.contact_phone} not active.`,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokenRedirect = await generateTokenRedirect(
|
|
||||||
data.contact_phone,
|
|
||||||
data.contact_name,
|
|
||||||
data.notification_error_id
|
|
||||||
);
|
|
||||||
|
|
||||||
const encodedToken = encodeURIComponent(tokenRedirect);
|
|
||||||
const shortUrl = await shortUrltiny(encodedToken);
|
|
||||||
|
|
||||||
const bodyWithUrl =
|
|
||||||
`Hai ${data.contact_name || "-"}\n` +
|
|
||||||
`Terjadi peringatan dengan kode error ${data.error_code || "-"} - ${
|
|
||||||
data.error_code_name || "-"
|
|
||||||
} ` +
|
|
||||||
`pada device ${
|
|
||||||
data.device_name || "-"
|
|
||||||
}, silahkan cek detail pada link berikut:\n` +
|
|
||||||
`${shortUrl}`;
|
|
||||||
|
|
||||||
const resultSend = await sendNotifikasi(
|
|
||||||
data.contact_phone,
|
|
||||||
bodyWithUrl
|
|
||||||
);
|
|
||||||
const isSuccess = resultSend.success;
|
|
||||||
|
|
||||||
const updateData = {
|
|
||||||
is_send: isSuccess,
|
|
||||||
message_error_issue: bodyWithUrl,
|
|
||||||
};
|
|
||||||
|
|
||||||
await updateNotificationErrorUserDb(id, updateData);
|
|
||||||
|
|
||||||
if (!isSuccess) {
|
|
||||||
results.push({
|
|
||||||
id,
|
|
||||||
status: "failed",
|
|
||||||
message: `WhatsApp API Gagal: ${
|
|
||||||
resultSend?.message || "Unknown Error"
|
|
||||||
}`,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
results.push({
|
|
||||||
status: 200,
|
|
||||||
notification_error_user_id: id,
|
|
||||||
notification_error_id: data.notification_error_id,
|
|
||||||
device_name: data.device_name,
|
|
||||||
error_code: data?.error_code,
|
|
||||||
error_code_name: data?.error_code_name,
|
|
||||||
users: {
|
|
||||||
contact_name: data.contact_name,
|
|
||||||
contact_phone: data.contact_phone,
|
|
||||||
is_send: isSuccess,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
results.push({ id, status: "error", message: err.message });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = NotificationErrorUserService;
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
const { getAllContactDb } = require("../db/contact.db");
|
|
||||||
const { InsertNotificationErrorDb, updateNotificationErrorDb } = require("../db/notification_error.db");
|
|
||||||
const {
|
|
||||||
createNotificationErrorUserDb,
|
|
||||||
updateNotificationErrorUserDb,
|
|
||||||
} = require("../db/notification_error_user.db");
|
|
||||||
const {
|
|
||||||
generateTokenRedirect,
|
|
||||||
shortUrltiny,
|
|
||||||
sendNotifikasi,
|
|
||||||
} = require("../db/notification_wa.db");
|
|
||||||
const { getErrorCodeByBrandAndCodeDb } = require("../db/brand_code.db");
|
|
||||||
const { getDeviceNotificationByIdDb } = require("../db/notification_error.db");
|
|
||||||
|
|
||||||
class NotifikasiWaService {
|
|
||||||
async onNotification(topic, message) {
|
|
||||||
try {
|
|
||||||
const paramDb = {
|
|
||||||
limit: 100,
|
|
||||||
page: 1,
|
|
||||||
criteria: "",
|
|
||||||
active: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
// const chanel = {
|
|
||||||
// "time": "2025-12-11 11:10:58",
|
|
||||||
// "c_4501": 4,
|
|
||||||
// "c_5501": 3,
|
|
||||||
// "c_6501": 0
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (topic === process.env.TOPIC_COD ?? "morek") {
|
|
||||||
const dataMqtt = JSON.parse(message);
|
|
||||||
|
|
||||||
const resultChanel = [];
|
|
||||||
|
|
||||||
Object.entries(dataMqtt).forEach(([key, value]) => {
|
|
||||||
if (key.startsWith("c_")) {
|
|
||||||
resultChanel.push({
|
|
||||||
chanel_id: Number(key.slice(2)),
|
|
||||||
value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = await getAllContactDb(paramDb);
|
|
||||||
|
|
||||||
const dataUsers = results.data;
|
|
||||||
|
|
||||||
for (const chanel of resultChanel) {
|
|
||||||
const deviceNotification = await getDeviceNotificationByIdDb(
|
|
||||||
Number(chanel.chanel_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
const errorCode = await getErrorCodeByBrandAndCodeDb(deviceNotification?.brand_id ?? 0, chanel.value);
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
error_code_id: chanel.value,
|
|
||||||
error_chanel: chanel.chanel_id,
|
|
||||||
is_send: false,
|
|
||||||
is_delivered: false,
|
|
||||||
is_read: false,
|
|
||||||
is_active: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const resultNotificationError = await InsertNotificationErrorDb(data);
|
|
||||||
|
|
||||||
let isSendNotification = false
|
|
||||||
|
|
||||||
for (const dataUser of dataUsers) {
|
|
||||||
if (dataUser.is_active) {
|
|
||||||
const tokenRedirect = await generateTokenRedirect(
|
|
||||||
dataUser.contact_phone,
|
|
||||||
dataUser.contact_name,
|
|
||||||
resultNotificationError.notification_error_id
|
|
||||||
);
|
|
||||||
|
|
||||||
const encodedToken = encodeURIComponent(tokenRedirect);
|
|
||||||
|
|
||||||
const shortUrl = await shortUrltiny(encodedToken);
|
|
||||||
|
|
||||||
const bodyMessage =
|
|
||||||
`Hai ${dataUser.contact_name || "-"}\n` +
|
|
||||||
`Terjadi kode error ${chanel?.value ?? "-"} ${errorCode?.error_code_name ?? ""}Chanel ${chanel?.chanel_id ?? "-"} ` +
|
|
||||||
`pada device ${deviceNotification?.device_name ?? "berikut"
|
|
||||||
}, Silahkan cek detail pada link berikut:\n` +
|
|
||||||
`${shortUrl}`;
|
|
||||||
|
|
||||||
const param = {
|
|
||||||
idData: resultNotificationError.notification_error_id,
|
|
||||||
userPhone: dataUser.contact_phone,
|
|
||||||
userName: dataUser.contact_name,
|
|
||||||
bodyMessage: bodyMessage,
|
|
||||||
};
|
|
||||||
|
|
||||||
const resultNotificationErrorUser =
|
|
||||||
await createNotificationErrorUserDb({
|
|
||||||
notification_error_id: param.idData,
|
|
||||||
contact_phone: param.userPhone,
|
|
||||||
contact_name: param.userName,
|
|
||||||
message_error_issue: param.bodyMessage,
|
|
||||||
is_send: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const resultSend = await sendNotifikasi(
|
|
||||||
param.userPhone,
|
|
||||||
param.bodyMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await updateNotificationErrorUserDb(
|
|
||||||
resultNotificationErrorUser[0].notification_error_user_id,
|
|
||||||
{
|
|
||||||
is_send: resultSend.success,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (resultSend.success) {
|
|
||||||
isSendNotification = resultSend.success
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await updateNotificationErrorDb(
|
|
||||||
resultNotificationError.notification_error_id,
|
|
||||||
{
|
|
||||||
is_send: isSendNotification,
|
|
||||||
is_delivered: isSendNotification,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = new NotifikasiWaService();
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllSubSectionsDb,
|
|
||||||
getSubSectionByIdDb,
|
|
||||||
createSubSectionDb,
|
|
||||||
updateSubSectionDb,
|
|
||||||
deleteSubSectionDb
|
|
||||||
} = require('../db/plant_sub_section.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class SubSectionService {
|
|
||||||
// Get all sub sections
|
|
||||||
static async getAll(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllSubSectionsDb(param);
|
|
||||||
|
|
||||||
results.data.map(el => {});
|
|
||||||
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get sub section by ID
|
|
||||||
static async getById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getSubSectionByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Sub section not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create sub section
|
|
||||||
static async create(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await createSubSectionDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sub section
|
|
||||||
static async update(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getSubSectionByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Sub section not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateSubSectionDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete sub section
|
|
||||||
static async delete(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getSubSectionByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Sub section not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteSubSectionDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = SubSectionService;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllRolesDb,
|
|
||||||
getRolesByIdDb,
|
|
||||||
insertRolesDb,
|
|
||||||
updateRolesDb,
|
|
||||||
deleteRolesDb
|
|
||||||
} = require('../db/roles.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class RolesService {
|
|
||||||
// Get all Roles
|
|
||||||
static async getAllRoles(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllRolesDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Roles by ID
|
|
||||||
static async getRolesById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getRolesByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Roles not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Roles
|
|
||||||
static async createRoles(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await insertRolesDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Roles
|
|
||||||
static async updateRoles(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getRolesByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Roles not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateRolesDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Roles
|
|
||||||
static async deleteRoles(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getRolesByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Roles not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteRolesDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = RolesService;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllScheduleDb,
|
|
||||||
getScheduleByIdDb,
|
|
||||||
insertScheduleDb,
|
|
||||||
updateScheduleDb,
|
|
||||||
deleteScheduleDb
|
|
||||||
} = require('../db/schedule.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class ScheduleService {
|
|
||||||
// Get all Schedule
|
|
||||||
static async getAllSchedule(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllScheduleDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Schedule by ID
|
|
||||||
static async getScheduleById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getScheduleByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Schedule not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Schedule
|
|
||||||
static async insertScheduleDb(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await insertScheduleDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Schedule
|
|
||||||
static async updateSchedule(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getScheduleByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Schedule not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateScheduleDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Schedule
|
|
||||||
static async deleteSchedule(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getScheduleByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Schedule not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteScheduleDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ScheduleService;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllShiftDb,
|
|
||||||
getShiftByIdDb,
|
|
||||||
insertShiftDb,
|
|
||||||
updateShiftDb,
|
|
||||||
deleteShiftDb
|
|
||||||
} = require('../db/shift.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class ShiftService {
|
|
||||||
// Get all Shift
|
|
||||||
static async getAllShift(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllShiftDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Shift by ID
|
|
||||||
static async getShiftById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getShiftByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Shift not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create Shift
|
|
||||||
static async createShift(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await insertShiftDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Shift
|
|
||||||
static async updateShift(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getShiftByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Shift not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateShiftDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete Shift
|
|
||||||
static async deleteShift(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getShiftByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Shift not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteShiftDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = ShiftService;
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllSparepartDb,
|
|
||||||
getSparepartByIdDb,
|
|
||||||
createSparepartDb,
|
|
||||||
updateSparepartDb,
|
|
||||||
deleteSparepartDb,
|
|
||||||
checkSparepartNameExistsDb,
|
|
||||||
} = require("../db/sparepart.db");
|
|
||||||
|
|
||||||
const { ErrorHandler } = require("../helpers/error");
|
|
||||||
|
|
||||||
class SparepartService {
|
|
||||||
static async getAllSparepart(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllSparepartDb(param);
|
|
||||||
results.data.map((item) => {});
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getSparepartById(id) {
|
|
||||||
try {
|
|
||||||
const sparepart = await getSparepartByIdDb(id);
|
|
||||||
|
|
||||||
if (!sparepart || sparepart.length === 0) {
|
|
||||||
throw new ErrorHandler(404, "Sparepart not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
return sparepart[0];
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async createSparepart(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== "object") data = {};
|
|
||||||
if (data.sparepart_name) {
|
|
||||||
const exists = await checkSparepartNameExistsDb(data.sparepart_name);
|
|
||||||
if (exists)
|
|
||||||
throw new ErrorHandler(400, "Sparepart name already exists");
|
|
||||||
}
|
|
||||||
const created = await createSparepartDb(data);
|
|
||||||
if (!created) throw new ErrorHandler(500, "Failed to create Sparepart");
|
|
||||||
return created;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async updateSparepart(id, data) {
|
|
||||||
try {
|
|
||||||
const existing = await getSparepartByIdDb(id);
|
|
||||||
if (!existing) throw new ErrorHandler(404, "Sparepart not found");
|
|
||||||
if (
|
|
||||||
data.sparepart_name &&
|
|
||||||
data.sparepart_name !== existing.sparepart_name
|
|
||||||
) {
|
|
||||||
const exists = await checkSparepartNameExistsDb(
|
|
||||||
data.sparepart_name,
|
|
||||||
id
|
|
||||||
);
|
|
||||||
if (exists)
|
|
||||||
throw new ErrorHandler(400, "Sparepart name already exists");
|
|
||||||
}
|
|
||||||
const updated = await updateSparepartDb(id, data);
|
|
||||||
if (!updated) throw new ErrorHandler(500, "Failed to update Sparepart");
|
|
||||||
return await this.getSparepartById(id);
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async deleteSparepart(id, userId) {
|
|
||||||
try {
|
|
||||||
const existing = await getSparepartByIdDb(id);
|
|
||||||
if (!existing) throw new ErrorHandler(404, "Sparepart not found");
|
|
||||||
const deleted = await deleteSparepartDb(id, userId);
|
|
||||||
if (!deleted) throw new ErrorHandler(500, "Failed to delete Sparepart");
|
|
||||||
return deleted;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
module.exports = SparepartService;
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllStatusDb,
|
|
||||||
getStatusByIdDb,
|
|
||||||
createStatusDb,
|
|
||||||
updateStatusDb,
|
|
||||||
deleteStatusDb,
|
|
||||||
checkStatusNumberExistsDb
|
|
||||||
} = require('../db/status.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class StatusService {
|
|
||||||
// Get all status
|
|
||||||
static async getAllStatus(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllStatusDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get status by ID
|
|
||||||
static async getStatusById(id) {
|
|
||||||
try {
|
|
||||||
const result = await getStatusByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Status not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async createStatus(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
if (data.status_number) {
|
|
||||||
const exists = await checkStatusNumberExistsDb(data.status_number);
|
|
||||||
if (exists) throw new ErrorHandler(400, 'Status number already exists');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await createStatusDb(data);
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode || 500, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status
|
|
||||||
static async updateStatus(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getStatusByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Status not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateStatusDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete status
|
|
||||||
static async deleteStatus(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getStatusByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Status not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteStatusDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = StatusService;
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
const {
|
|
||||||
getAllTagsDb,
|
|
||||||
getTagsByIdDb,
|
|
||||||
createTagsDb,
|
|
||||||
updateTagsDb,
|
|
||||||
deleteTagsDb
|
|
||||||
} = require('../db/tags.db');
|
|
||||||
const { ErrorHandler } = require('../helpers/error');
|
|
||||||
|
|
||||||
class TagsService {
|
|
||||||
// Get all devices
|
|
||||||
static async getAllTags(param) {
|
|
||||||
try {
|
|
||||||
const results = await getAllTagsDb(param);
|
|
||||||
|
|
||||||
results.data.map(element => {
|
|
||||||
});
|
|
||||||
|
|
||||||
return results
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get device by ID
|
|
||||||
static async getTagByID(id) {
|
|
||||||
try {
|
|
||||||
const result = await getTagsByIdDb(id);
|
|
||||||
|
|
||||||
if (result.length < 1) throw new ErrorHandler(404, 'Tags not found');
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create device
|
|
||||||
static async createTags(data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const result = await createTagsDb(data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update device
|
|
||||||
static async updateTags(id, data) {
|
|
||||||
try {
|
|
||||||
if (!data || typeof data !== 'object') data = {};
|
|
||||||
|
|
||||||
const dataExist = await getTagsByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Tags not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await updateTagsDb(id, data);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Soft delete device
|
|
||||||
static async deleteTags(id, userId) {
|
|
||||||
try {
|
|
||||||
const dataExist = await getTagsByIdDb(id);
|
|
||||||
|
|
||||||
if (dataExist.length < 1) {
|
|
||||||
throw new ErrorHandler(404, 'Tags not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await deleteTagsDb(id, userId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
} catch (error) {
|
|
||||||
throw new ErrorHandler(error.statusCode, error.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = TagsService;
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user