first commit
This commit is contained in:
25
source/config/config.ts
Normal file
25
source/config/config.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { readFileSync } from "fs";
|
||||
|
||||
interface IConfig {
|
||||
base_url: string;
|
||||
schedule: string[];
|
||||
delay: number;
|
||||
row_per_batch: number;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
mcuID: string;
|
||||
}
|
||||
const j_config = JSON.parse(
|
||||
readFileSync("./config-point-member.json").toString()
|
||||
);
|
||||
|
||||
const config: IConfig = {
|
||||
base_url: j_config["base_url"],
|
||||
schedule: j_config["schedule"],
|
||||
delay: j_config["delay"],
|
||||
row_per_batch: j_config["row_per_batch"],
|
||||
startDate: j_config["startDate"],
|
||||
endDate: j_config["endDate"],
|
||||
mcuID: j_config["mcuID"],
|
||||
};
|
||||
export default config;
|
||||
48
source/config/logging.ts
Normal file
48
source/config/logging.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import moment from "moment";
|
||||
|
||||
const getTimeStamp = (): string => {
|
||||
const dt = moment().format("yyyy-MM-DD HH:mm:ss");
|
||||
return dt;
|
||||
};
|
||||
|
||||
const info = (namespace: string, message: string, object?: any) => {
|
||||
if (object) {
|
||||
console.log(
|
||||
`[${getTimeStamp()}] [INFO] [${namespace}] [${message}]`,
|
||||
object
|
||||
);
|
||||
} else {
|
||||
console.log(`[${getTimeStamp()}] [INFO] [${namespace}] [${message}]`);
|
||||
}
|
||||
};
|
||||
|
||||
const warning = (namespace: string, message: string, object?: any) => {
|
||||
if (object) {
|
||||
console.log(
|
||||
`[${getTimeStamp()}] [WARNING] [${namespace}] [${message}]`,
|
||||
object
|
||||
);
|
||||
} else {
|
||||
console.log(`[${getTimeStamp()}] [WARNING] [${namespace}] [${message}]`);
|
||||
}
|
||||
};
|
||||
|
||||
const error = (namespace: string, message: string, object?: any) => {
|
||||
if (object) {
|
||||
console.log(
|
||||
`[${getTimeStamp()}] [ERROR] [${namespace}] [${message}]`,
|
||||
object
|
||||
);
|
||||
} else {
|
||||
console.log(`[${getTimeStamp()}] [ERROR] [${namespace}] [${message}]`);
|
||||
}
|
||||
};
|
||||
|
||||
const delay = (time: number) => new Promise((res) => setTimeout(res, time));
|
||||
|
||||
export default {
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
delay,
|
||||
};
|
||||
1
source/interfaces.ts
Normal file
1
source/interfaces.ts
Normal file
@@ -0,0 +1 @@
|
||||
/* Tidak terpakai */
|
||||
131
source/lib-inject.ts
Normal file
131
source/lib-inject.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import axios from "axios";
|
||||
import config from "./config/config";
|
||||
import logging from "./config/logging";
|
||||
import { NAME_SPACE } from "./server";
|
||||
|
||||
export const getListOutbox = async (
|
||||
statusOutbox: string,
|
||||
startDate: string,
|
||||
endDate: string,
|
||||
setupID: string
|
||||
) => {
|
||||
const url = config.base_url + "mockup/sendwa/sendwa/listoutbox";
|
||||
logging.info(NAME_SPACE, "\t INFO : " + url);
|
||||
logging.info(NAME_SPACE, "\t INFO Status Outbox: " + statusOutbox);
|
||||
logging.info(NAME_SPACE, "\t INFO Start Date: " + startDate);
|
||||
logging.info(NAME_SPACE, "\t INFO End Date: " + endDate);
|
||||
logging.info(NAME_SPACE, "\t INFO Setup id: " + setupID);
|
||||
|
||||
try {
|
||||
const resp = await axios.post(
|
||||
url,
|
||||
{
|
||||
statusOutbox: statusOutbox,
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
setupID: setupID,
|
||||
},
|
||||
{
|
||||
headers: { "Content-Type": "application/json; charset=UTF-8" },
|
||||
responseType: "text",
|
||||
}
|
||||
);
|
||||
const jresp =
|
||||
typeof resp.data === "string" ? JSON.parse(resp.data) : resp.data;
|
||||
return jresp;
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
logging.error(NAME_SPACE, "Error di lib inject catch axios");
|
||||
logging.error(NAME_SPACE, e.response?.data.toString());
|
||||
} else if (e instanceof Error) {
|
||||
logging.error(NAME_SPACE, "Error di instance of error");
|
||||
logging.error(NAME_SPACE, e.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const sendToQontak = async (param: any) => {
|
||||
const url = config.base_url + "mockup/sendwa/sendwa/QontakSendMsg";
|
||||
logging.info(NAME_SPACE, "\t INFO : " + url);
|
||||
logging.info(NAME_SPACE, "\t INFO Payload: " + JSON.stringify(param));
|
||||
|
||||
try {
|
||||
const resp = await axios.post(url, param, {
|
||||
headers: { "Content-Type": "application/json; charset=UTF-8" },
|
||||
responseType: "text",
|
||||
});
|
||||
const statusResp = resp.data.status;
|
||||
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"\t INFO Resp Qontak: " + JSON.stringify(statusResp)
|
||||
);
|
||||
return statusResp;
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
logging.error(NAME_SPACE, "Error di lib inject catch axios");
|
||||
logging.error(NAME_SPACE, e.response?.data.toString());
|
||||
} else if (e instanceof Error) {
|
||||
logging.error(NAME_SPACE, "Error di instance of error");
|
||||
logging.error(NAME_SPACE, e.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const uploadFileCdn = async (param: any) => {
|
||||
const url = config.base_url + "mockup/sendwa/sendwa/uploadfile";
|
||||
logging.info(NAME_SPACE, "\t INFO : " + url);
|
||||
logging.info(NAME_SPACE, "\t INFO Payload: " + JSON.stringify(param));
|
||||
|
||||
try {
|
||||
const resp = await axios.post(url, param, {
|
||||
headers: { "Content-Type": "application/json; charset=UTF-8" },
|
||||
responseType: "text",
|
||||
});
|
||||
|
||||
const statusResp = resp.data.status;
|
||||
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"\t INFO Resp Upload: " + JSON.stringify(statusResp)
|
||||
);
|
||||
return statusResp;
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
logging.error(NAME_SPACE, "Error di lib inject catch axios");
|
||||
logging.error(NAME_SPACE, e.response?.data.toString());
|
||||
} else if (e instanceof Error) {
|
||||
logging.error(NAME_SPACE, "Error di instance of error");
|
||||
logging.error(NAME_SPACE, e.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const changeStatusOutbox = async (param: any) => {
|
||||
const url = config.base_url + "mockup/sendwa/sendwa/changeStatusOutbox";
|
||||
logging.info(NAME_SPACE, "\t INFO : " + url);
|
||||
logging.info(NAME_SPACE, "\t INFO Payload: " + JSON.stringify(param));
|
||||
|
||||
try {
|
||||
const resp = await axios.post(url, param, {
|
||||
headers: { "Content-Type": "application/json; charset=UTF-8" },
|
||||
responseType: "text",
|
||||
});
|
||||
|
||||
const statusResp = resp.data.status;
|
||||
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"\t INFO Resp Change Status: " + JSON.stringify(statusResp)
|
||||
);
|
||||
return statusResp;
|
||||
} catch (e) {
|
||||
if (axios.isAxiosError(e)) {
|
||||
logging.error(NAME_SPACE, "Error di lib inject catch axios");
|
||||
logging.error(NAME_SPACE, e.response?.data.toString());
|
||||
} else if (e instanceof Error) {
|
||||
logging.error(NAME_SPACE, "Error di instance of error");
|
||||
logging.error(NAME_SPACE, e.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
256
source/server.ts
Normal file
256
source/server.ts
Normal file
@@ -0,0 +1,256 @@
|
||||
import config from "./config/config";
|
||||
import logging from "./config/logging";
|
||||
import * as Xcron from "node-cron";
|
||||
|
||||
import {
|
||||
getListOutbox,
|
||||
sendToQontak,
|
||||
uploadFileCdn,
|
||||
changeStatusOutbox,
|
||||
} from "./lib-inject";
|
||||
|
||||
export const NAME_SPACE = "SENT RESULT VIA WA";
|
||||
const VERSION = "1.0";
|
||||
|
||||
let isRunning = false;
|
||||
|
||||
logging.info(NAME_SPACE, "Starting. Ver:", `${VERSION}`);
|
||||
|
||||
const on_init = async () => {
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"-------------------- ON INIT START --------------------"
|
||||
);
|
||||
|
||||
await main("N");
|
||||
await main("E");
|
||||
await main("R");
|
||||
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"-------------------- ON INIT END --------------------"
|
||||
);
|
||||
};
|
||||
|
||||
on_init();
|
||||
|
||||
async function main(status: string) {
|
||||
if (isRunning) {
|
||||
logging.info(NAME_SPACE, "Process is running. Skip this run.");
|
||||
return;
|
||||
}
|
||||
isRunning = true;
|
||||
|
||||
try {
|
||||
logging.info(NAME_SPACE, "Process is running. Start to get list outbox.");
|
||||
|
||||
let outboxs = await getLists(status);
|
||||
|
||||
/* Pesan minta diproses kirim */
|
||||
if (status == "N") {
|
||||
logging.info(NAME_SPACE, "GET Processed (N) Message");
|
||||
|
||||
for (let i = 0; i < outboxs.length; i++) {
|
||||
let outbox = outboxs[i];
|
||||
logging.info(NAME_SPACE, "\t Detail: ", outbox);
|
||||
let retry = outbox.XWaOutboxIsRetry;
|
||||
|
||||
/* Jika fileUrl masih 0, maka panggil upload file */
|
||||
if (outbox.fileUrl == null) {
|
||||
let resp = uploadFile(outbox);
|
||||
logging.info(NAME_SPACE, "\t Uploading File to CDN: ", resp);
|
||||
logging.info(NAME_SPACE, "\t wait 2s \t");
|
||||
await delay(2000);
|
||||
|
||||
if ((await resp) == "OK") {
|
||||
logging.info(NAME_SPACE, "\t File Uploaded");
|
||||
|
||||
let response = sentMsg(outbox, status, retry);
|
||||
|
||||
logging.info(NAME_SPACE, "\t wait 4s \t");
|
||||
await delay(4000);
|
||||
|
||||
logging.info(NAME_SPACE, "\t Resp Qontak: ", response);
|
||||
} else {
|
||||
// Change Status ke Error
|
||||
changeStatus(outbox, "E", retry);
|
||||
}
|
||||
} else {
|
||||
// Jika fileUrl sudah ada maka langsung kirim file
|
||||
let response = sentMsg(outbox, status, retry);
|
||||
|
||||
logging.info(NAME_SPACE, "\t wait 4s \t");
|
||||
await delay(4000);
|
||||
|
||||
logging.info(NAME_SPACE, "\t Resp Qontak: ", response);
|
||||
}
|
||||
}
|
||||
} else if (status == "E") {
|
||||
/* Pesan Eror < 5x retry */
|
||||
logging.info(NAME_SPACE, "GET Error (E) Message");
|
||||
for (let i = 0; i < outboxs.length; i++) {
|
||||
let outbox = outboxs[i];
|
||||
logging.info(NAME_SPACE, "\t Detail: ", outbox);
|
||||
let retry = outbox.XWaOutboxIsRetry;
|
||||
|
||||
if (retry >= 5) {
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"\t Retry count more than 5. Skip this message."
|
||||
);
|
||||
continue;
|
||||
} else {
|
||||
retry++;
|
||||
|
||||
if (outbox.fileUrl == null) {
|
||||
let resp = uploadFile(outbox);
|
||||
logging.info(NAME_SPACE, "\t Uploading File to CDN: ", resp);
|
||||
logging.info(NAME_SPACE, "\t wait 2s \t");
|
||||
await delay(2000);
|
||||
|
||||
if ((await resp) == "OK") {
|
||||
logging.info(NAME_SPACE, "\t File Uploaded");
|
||||
|
||||
let response = sentMsg(outbox, status, retry);
|
||||
|
||||
logging.info(NAME_SPACE, "\t wait 4s \t");
|
||||
await delay(4000);
|
||||
|
||||
logging.info(NAME_SPACE, "\t Resp Qontak: ", response);
|
||||
} else {
|
||||
changeStatus(outbox, "E", retry);
|
||||
}
|
||||
} else {
|
||||
let response = sentMsg(outbox, status, retry);
|
||||
logging.info(NAME_SPACE, "\t wait 4s \t");
|
||||
await delay(4000);
|
||||
logging.info(NAME_SPACE, "\t Resp Qontak: ", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (status == "R") {
|
||||
logging.info(NAME_SPACE, "GET Rejected (R) Message");
|
||||
|
||||
for (let i = 0; i < outboxs.length; i++) {
|
||||
let outbox = outboxs[i];
|
||||
logging.info(NAME_SPACE, "\t Detail: ", outbox);
|
||||
let retry = outbox.XWaOutboxIsRetry;
|
||||
|
||||
/* Jika fileUrl masih 0, maka panggil upload file */
|
||||
if (outbox.fileUrl == null) {
|
||||
let resp = uploadFile(outbox);
|
||||
logging.info(NAME_SPACE, "\t Uploading File to CDN: ", resp);
|
||||
logging.info(NAME_SPACE, "\t wait 2s \t");
|
||||
await delay(2000);
|
||||
|
||||
if ((await resp) == "OK") {
|
||||
logging.info(NAME_SPACE, "\t File Uploaded");
|
||||
|
||||
let response = sentMsg(outbox, status, retry);
|
||||
|
||||
logging.info(NAME_SPACE, "\t wait 4s \t");
|
||||
await delay(4000);
|
||||
|
||||
logging.info(NAME_SPACE, "\t Resp Qontak: ", response);
|
||||
} else {
|
||||
// Change Status ke Error
|
||||
changeStatus(outbox, "E", retry);
|
||||
}
|
||||
} else {
|
||||
// Jika fileUrl sudah ada maka langsung kirim file
|
||||
let response = sentMsg(outbox, status, retry);
|
||||
|
||||
logging.info(NAME_SPACE, "\t wait 4s \t");
|
||||
await delay(4000);
|
||||
|
||||
logging.info(NAME_SPACE, "\t Resp Qontak: ", response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logging.info(NAME_SPACE, "End Job Get Order");
|
||||
isRunning = false;
|
||||
} catch (e) {
|
||||
isRunning = false;
|
||||
if (e instanceof Error) {
|
||||
logging.error(NAME_SPACE, e.message);
|
||||
} else {
|
||||
logging.error(NAME_SPACE, "Unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getLists(status: string) {
|
||||
const statusOutbox = status;
|
||||
// const statusOutbox = config.statusOutbox;
|
||||
const startDate = config.startDate;
|
||||
const endDate = config.endDate;
|
||||
const setupID = config.mcuID;
|
||||
|
||||
var resp = await getListOutbox(statusOutbox, startDate, endDate, setupID);
|
||||
if (resp["status"] != "OK") {
|
||||
logging.error(NAME_SPACE, "\t Error get outbox data", resp);
|
||||
logging.error(NAME_SPACE, "\t Error: ", resp);
|
||||
} else {
|
||||
logging.info(
|
||||
NAME_SPACE,
|
||||
"\t Success get order data found ",
|
||||
resp.data.length
|
||||
);
|
||||
}
|
||||
const result =
|
||||
typeof resp.data === "string" ? JSON.parse(resp.data) : resp.data;
|
||||
return result;
|
||||
}
|
||||
|
||||
async function sentMsg(item: any, status: string, retry: number) {
|
||||
let payload = {
|
||||
orderID: item.orderID,
|
||||
orderDate: item.orderDate,
|
||||
patientDOB: item.patientDOB,
|
||||
patientName: item.patientName,
|
||||
patientHp: item.patientHp,
|
||||
corpName: item.CorporateName,
|
||||
fileName: item.fileName,
|
||||
statusOutbox: status,
|
||||
retryOutbox: retry,
|
||||
sendWaID: item.sendWaID,
|
||||
};
|
||||
// return payload;
|
||||
|
||||
/* Axios for POST to the WA API */
|
||||
var response = await sendToQontak(payload); // Response "OK"
|
||||
return response;
|
||||
}
|
||||
|
||||
async function uploadFile(item: any) {
|
||||
let payload = {
|
||||
fileName: item.fileName,
|
||||
rptUrl: item.localUrl,
|
||||
mime: "application/pdf",
|
||||
XWaOutboxID: item.sendWaID,
|
||||
};
|
||||
// return payload;
|
||||
|
||||
var response = await uploadFileCdn(payload); // Response "OK"
|
||||
return response;
|
||||
}
|
||||
|
||||
async function changeStatus(item: any, status: string, retry: number) {
|
||||
let payload = {
|
||||
toStatus: status,
|
||||
XWaOutboxID: item.sendWaID,
|
||||
retry: retry,
|
||||
};
|
||||
// return payload;
|
||||
|
||||
var response = await changeStatusOutbox(payload);
|
||||
return response;
|
||||
}
|
||||
|
||||
async function delay(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
function elseif(arg0: boolean) {
|
||||
throw new Error("Function not implemented.");
|
||||
}
|
||||
Reference in New Issue
Block a user