first commit
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
APP_PORT=0
|
||||
|
||||
DB_HOST=
|
||||
DB_USER=
|
||||
DB_PASSWORD=
|
||||
DB_NAME=
|
||||
DB_PORT=
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
# ignore visual studio code
|
||||
/.vs/
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
@@ -0,0 +1,36 @@
|
||||
# INVESA-NODE
|
||||
|
||||
Aplikasi INVESA Service
|
||||
|
||||
## Deskripsi
|
||||
|
||||
Aplikasi basis NodeJS untuk Web Aplikasi INVESA, pengontrol supervisi dan lalu lintas data monitor pada display depan kasir.
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ git clone https://git.trifonia.cloud/CMASA-MEMPAWAH/invesa-node.git
|
||||
$ cd invesa-node
|
||||
$ npm install
|
||||
```
|
||||
|
||||
## Penggunaan
|
||||
|
||||
Jalankan service dengan perintah :
|
||||
|
||||
```$ npm start```
|
||||
|
||||
## Authors
|
||||
|
||||
Developer dan programmer
|
||||
|
||||
[@siaupheng](mailto:[email protected])
|
||||
|
||||
## Version History
|
||||
|
||||
* 1.0
|
||||
* Initial Release
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed.
|
||||
@@ -0,0 +1,124 @@
|
||||
const express = require('express');
|
||||
const { createServer } = require('node:http');
|
||||
const { join } = require('node:path');
|
||||
const { Server } = require('socket.io');
|
||||
const mysql = require('mysql2/promise');
|
||||
const dotenv = require('@dotenvx/dotenvx');
|
||||
const { PoolConnection } = require('mysql2');
|
||||
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
const io = new Server(server, { 'path': '/io' });
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const db = mysql.createPool({
|
||||
host: process.env.DB_HOST || '127.0.0.1',
|
||||
user: process.env.DB_USER || 'mariadb',
|
||||
password: process.env.DB_PASSWORD || '',
|
||||
database: process.env.DB_NAME || '',
|
||||
port: process.env.DB_PORT || 3306,
|
||||
});
|
||||
|
||||
const app_port = process.env.APP_PORT || 3000;
|
||||
|
||||
io.on('connection', (socket) => {
|
||||
let pollPPOB = null;
|
||||
let pollSuper = null;
|
||||
let pollMonitor = null;
|
||||
// get ip address
|
||||
const forwardedIp = socket.handshake.headers["x-forwarded-for"];
|
||||
//const cloudflareIp = socket.handshake.headers["cf-connecting-ip"];
|
||||
const clientIp = forwardedIp ? forwardedIp.split(',')[0] : socket.handshake.address;
|
||||
//console.log("Real Client IP:", clientIp);
|
||||
|
||||
// PPOB
|
||||
socket.on('ppob-check', (ajson) => {
|
||||
if (!ajson || typeof ajson !== 'object') return socket.emit('ppob-error', { 'message': 'Invalid payload format' });
|
||||
const { CabID, UserID } = ajson;
|
||||
if (!CabID || !UserID) return socket.emit('ppob-error', { 'message': 'Missing required CabID and UserID' });
|
||||
|
||||
if (pollPPOB) clearInterval(pollPPOB);
|
||||
pollPPOB = setInterval(async () => {
|
||||
try {
|
||||
const [rows, fields] = await db.query("SELECT No_TX,Status FROM ppob_tx WHERE No_TX IN (SELECT No_TX FROM ppob_pend WHERE CabID=? AND UserID=?)", [ CabID, UserID ]);
|
||||
socket.emit('ppob-data', { 'prabayar': rows });
|
||||
} catch (error) {
|
||||
console.error("db query failed :", error);
|
||||
}
|
||||
}, 1500);
|
||||
});
|
||||
socket.on('ppob-update', (ajson) => {
|
||||
if (!ajson || typeof ajson !== 'object') return socket.emit('ppob-error', { 'message': 'Invalid payload format' });
|
||||
const { CabID, UserID } = ajson;
|
||||
if (!CabID || !UserID) return socket.emit('ppob-error', { 'message': 'Missing required CabID and UserID' });
|
||||
try {
|
||||
db.execute("DELETE FROM ppob_pend WHERE Status=4 AND CabID=? AND UserID=?", [ CabID, UserID ]);
|
||||
} catch (error) {
|
||||
console.error("db execute failed :", error);
|
||||
}
|
||||
});
|
||||
socket.on('ppob-done', () => {
|
||||
if (pollPPOB) clearInterval(pollPPOB);
|
||||
pollPPOB = null;
|
||||
});
|
||||
|
||||
// SUPERVISI
|
||||
socket.on('super-check', (ajson) => {
|
||||
if (pollSuper) return;
|
||||
pollSuper = setInterval(async () => {
|
||||
try {
|
||||
const [rows, fields] = await db.query({sql: "SELECT A.AuthID,O.Nama Nama_User,A.Tanggal,M.Judul,A.Catatan,A.REQ,'<a class=\"table-icon unlock2\" title=\"Proses\"><i class=\"bi-unlock2\"></i></a>' Aksi FROM (SELECT AuthID,UserID,Kode,DATE_FORMAT(Tanggal,'%d-%m-%Y %H:%i:%s') Tanggal,REQ,Catatan FROM app_auth WHERE Auth=0) A LEFT JOIN app_operator O ON (A.UserID=O.UserID) LEFT JOIN app_menu M ON (A.Kode=M.Kode)", rowsAsArray: true});
|
||||
socket.emit('super-data', { 'data': rows });
|
||||
} catch (error) {
|
||||
console.error("db query failed :", error);
|
||||
}
|
||||
}, 1500);
|
||||
});
|
||||
socket.on('super-done', () => {
|
||||
if (pollSuper) clearInterval(pollSuper);
|
||||
pollSuper = null;
|
||||
});
|
||||
|
||||
// MONITOR
|
||||
socket.on('monitor-check', (ajson) => {
|
||||
if (!ajson || typeof ajson !== 'object') return socket.emit('monitor-error', { 'message': 'Invalid payload format' });
|
||||
const { CabID, UserID } = ajson;
|
||||
if (pollMonitor) return;
|
||||
pollMonitor = setInterval(async () => {
|
||||
try {
|
||||
const adata = { 'total': 0, 'thank': 0 };
|
||||
const [row_pos, fields_pos] = await db.query("SELECT * FROM disp_login WHERE CabID=? AND IP=? ORDER BY Date DESC", [ CabID, clientIp ]);
|
||||
if (row_pos.length) {
|
||||
const [row_total, fields_total] = await db.query("SELECT SUM(-Qty*(Harga_Jual-Disk_Rupiah)) Total FROM tmp_inv_detail WHERE No_Ref=? AND Unix=?", [ row_pos[0].No_Pos, row_pos[0].Unix ]);
|
||||
const [row_thank, fields_thank] = await db.query("SELECT IF(No_Cetak='',0,1) Ada FROM disp_login WHERE CabID=? AND UserID=? AND Unix=?", [ CabID, row_pos[0].UserID, row_pos[0].Unix ]);
|
||||
if (row_total.length) adata.total = row_total[0].Total || 0;
|
||||
if (row_thank.length) adata.thank = row_thank[0].Ada || 0;
|
||||
}
|
||||
socket.emit('monitor-data', { 'data': adata });
|
||||
} catch (error) {
|
||||
console.error("db query failed :", error);
|
||||
}
|
||||
}, 1500);
|
||||
});
|
||||
socket.on('monitor-done', () => {
|
||||
if (pollMonitor) clearInterval(pollMonitor);
|
||||
pollMonitor = null;
|
||||
});
|
||||
|
||||
// DISCONNECT
|
||||
socket.on('disconnect', () => {
|
||||
if (pollPPOB) clearInterval(pollPPOB);
|
||||
if (pollSuper) clearInterval(pollSuper);
|
||||
if (pollMonitor) clearInterval(pollMonitor);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.sendFile(join(__dirname, 'public', 'index.html'));
|
||||
});
|
||||
app.use(express.static('public'));
|
||||
|
||||
server.listen(app_port, () => {
|
||||
console.log('Server running at http://localhost:' + app_port);
|
||||
});
|
||||
Generated
+1866
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "invesa-node",
|
||||
"version": "0.0.1",
|
||||
"description": "service apps for invesa",
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.69.1",
|
||||
"express": "^4.22.2",
|
||||
"mysql2": "^3.22.4",
|
||||
"socket.io": "^4.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.14"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Socket.IO for INVESA</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="author" content="Siau Pheng <siaupheng[at]3fonia.com>">
|
||||
<meta name="description" content="Socket.IO for Invesa v1.0.0, 3fonia Software">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<style>
|
||||
body {
|
||||
margin: 200px 0 0 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
font-size: 13pt;
|
||||
}
|
||||
h1 {
|
||||
color: #719e40;
|
||||
letter-spacing: -4px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
font-size: 50pt;
|
||||
font-weight: 300;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="/images/logo300.png">
|
||||
<h1>INVESA Socket.IO</h1>
|
||||
<div>power by 3fonia Software, a web-base software house</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user