Merge branch 'develop' into adiDev

This commit is contained in:
AdisakKanthawilang 2025-04-01 13:38:34 +07:00
commit 26ef28f5cf
12 changed files with 1658 additions and 81 deletions

View file

@ -14,12 +14,12 @@ import logMiddleware from "./middlewares/logs";
import { CommandController } from "./controllers/CommandController";
import { ProfileSalaryController } from "./controllers/ProfileSalaryController";
// import { initWebSocket } from "./services/webSocket";
import { initWebSocket } from "./services/webSocket";
async function main() {
await AppDataSource.initialize();
// initWebSocket();
initWebSocket();
const app = express();

View file

@ -3065,6 +3065,9 @@ export class CommandController extends Controller {
commandCode?: string | null;
commandName?: string | null;
remark: string | null;
positionTypeNew?: string | null;
positionLevelNew?: string | null;
positionNameNew?: string | null;
}[];
},
) {
@ -3145,6 +3148,9 @@ export class CommandController extends Controller {
profile.leaveRemark = _null;
profile.leaveDate = _null;
profile.leaveType = _null;
profile.position = item.positionNameNew ?? _null;
profile.posTypeId = item.positionTypeNew ?? _null;
profile.posLevelId = item.positionLevelNew ?? _null
}
let userKeycloakId;
const checkUser = await getUserByUsername(profile.citizenId);

View file

@ -5626,6 +5626,9 @@ export class OrganizationController extends Controller {
const data = await this.orgRootRepository.find({
where: { orgRevisionId: orgRevisionActive.id },
order: {
orgRootOrder: "ASC",
},
});
return new HttpSuccess(data.map((x) => x.id));
}
@ -5647,6 +5650,9 @@ export class OrganizationController extends Controller {
const data = await this.orgRootRepository.find({
where: { orgRevisionId: orgRevisionActive.id },
order: {
orgRootOrder: "ASC",
},
});
return new HttpSuccess(data);
}
@ -5686,6 +5692,7 @@ export class OrganizationController extends Controller {
"orgChild1s.orgChild2s.orgChild3s.orgChild4s",
],
order: {
orgRootOrder: "ASC",
orgChild1s: {
orgChild1Order: "ASC",
orgChild2s: {

View file

@ -198,4 +198,22 @@ export class ProfileAssistanceController extends Controller {
return new HttpSuccess();
}
@Post("status")
public async editStatusProfileAssistance(
@Body() body: { status: string; refId: string },
@Request() req: RequestWithUser,
) {
const record = await this.profileAssistanceRepo.findOneBy({ refId: body.refId });
if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล");
record.status = body.status.trim().toLocaleUpperCase();
record.lastUpdateUserId = req.user.sub;
record.lastUpdateFullName = req.user.name;
record.lastUpdatedAt = new Date();
this.profileAssistanceRepo.save(record);
return new HttpSuccess();
}
}

View file

@ -15,6 +15,13 @@ export class ProfileAssistance extends EntityBase {
})
profileId: string;
@Column({
comment: "สถานะ",
default: "PENDING",
length: 20,
})
status: string;
@Column({
nullable: true,
comment: "หน่วยงานที่ให้ช่วยราชการ",

View file

@ -464,10 +464,20 @@ export type LogSequence = {
};
export function setLogDataDiff(req: RequestWithUser, data: DataDiff) {
req.app.locals.logData.dataDiff = {
before: JSON.stringify(data.before),
after: JSON.stringify(data.after),
};
// Check if data.before and data.after are valid objects
if (
data.before &&
typeof data.before === "object" &&
data.after &&
typeof data.after === "object"
) {
req.app.locals.logData.dataDiff = {
before: JSON.stringify(data.before),
after: JSON.stringify(data.after),
};
} else {
console.error("Invalid data provided: both before and after must be valid objects.");
}
}
export function addLogSequence(req: RequestWithUser, data: LogSequence) {

File diff suppressed because one or more lines are too long

View file

@ -24,6 +24,7 @@ import { Position } from "../entities/Position";
import { In, Not } from "typeorm";
import { PosMasterAct } from "../entities/PosMasterAct";
import { PermissionOrg } from "../entities/PermissionOrg";
import { sendWebSocket } from "./webSocket";
export let sendToQueue: (payload: any) => void;
export let sendToQueueOrg: (payload: any) => void;
@ -122,6 +123,15 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
relations: ["commandType", "commandRecives"],
});
if (!command) return true;
sendWebSocket(
"send-command-notification",
{
success: true,
message: `ระบบทำการออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543}`,
payload: command,
},
{ userId: user.sub },
).catch(console.error);
const path = commandTypePath(command.commandType.code);
if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ");
return await new CallAPI()
@ -156,11 +166,30 @@ async function handler(msg: amqp.ConsumeMessage): Promise<boolean> {
console.log("[AMQ] Excecute Command Success");
Object.assign(command, { status, lastUpdateUserId, lastUpdateFullName, lastUpdatedAt });
const result = await repo.save(command).catch((e) => console.log(e));
if (result) return true;
return false;
sendWebSocket(
"send-command-notification",
{
success: true,
message: `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} เสร็จสิ้น`,
payload: command,
},
{ userId: user.sub },
).catch(console.error);
return !!result;
})
.catch((e) => {
console.error(e);
sendWebSocket(
"send-command-notification",
{
success: false,
message: `ระบบออกคำสั่งเลขที่ ${command.commandNo}/${command.commandYear + 543} ผิดพลาด`,
payload: command,
},
{ userId: user.sub },
).catch(console.error);
return false;
});
}

View file

@ -1,43 +1,72 @@
// import { WebSocketServer } from "ws";
import { Server } from "socket.io";
// let wss: WebSocketServer;
let io: Server;
// export function initWebSocket() {
// wss = new WebSocketServer({ port: 13002, path: "/api/v1/org-socket" });
export function initWebSocket() {
if (io) return;
// // การจัดการคำขออัปเกรดจาก HTTP เป็น WebSocket
// wss.on("upgrade", (request: any, socket: any, head: any) => {
// console.log("🔹 Handling upgrade request...");
// wss.handleUpgrade(request, socket, head, (ws: any) => {
// console.log("🔹 WebSocket connection established");
// wss.emit("connection", ws, request);
// });
// });
io = new Server({ cors: { origin: "*" }, path: "/api/v1/org-socket" });
// wss.on("connection", (ws: any) => {
// console.log("✅ Client connected to WebSocket");
io.use(async (socket, next) => {
const token = socket.handshake.auth.token;
// ws.on("close", () => {
// console.log("❌ Client disconnected");
// });
const res = await fetch(`${process.env.AUTH_REALM_URL}/protocol/openid-connect/userinfo`, {
headers: { authorization: `Bearer ${token}` },
}).catch((e) => console.error(e));
// ws.on("error", (error: any) => {
// console.error("WebSocket error:", error);
// });
// });
// }
if (res?.ok) {
socket.data.user = await res.json();
}
// export async function sendWebSocket(data: any) {
// if (!wss) initWebSocket();
// wss.clients.forEach((client: any) => {
// if (client.readyState === WebSocket.OPEN) {
// const message = JSON.stringify(data);
// console.log("📤 Sending data to client:", message);
// client.send(message, (err: any) => {
// if (err) {
// console.error("❌ Error sending message:", err);
// }
// });
// }
// });
// }
next();
});
io.on("connection", (ws) => {
console.log("✅ Client connected to WebSocket");
ws.on("close", () => {
console.log("❌ Client disconnected");
});
ws.on("error", (error: any) => {
console.error("WebSocket error:", error);
});
});
io.listen(13002);
}
export async function sendWebSocket(
event: string,
data: any,
opts?: {
roles?: string | string[];
userId?: string | string[];
},
) {
if (!io) initWebSocket();
for (let [id, session] of io.of("/").sockets) {
const user: {
sub: string;
name: string;
given_name: string;
family_name: string;
preferred_username: string;
email: string;
role: string[];
} = session.data.user;
if (!user) continue;
if (typeof opts?.roles === "string") opts.roles = [opts.roles];
if (typeof opts?.userId === "string") opts.userId = [opts.userId];
if (
user.role?.some((v) => opts?.roles?.includes(v)) ||
opts?.userId?.some((v) => user.sub === v)
) {
io.to(id).emit(event, JSON.stringify(data));
}
}
}