05.1 ปรบปรง backend ทงหมด และ frontend/login
This commit is contained in:
@@ -1,124 +1,124 @@
|
||||
// FILE: src/routes/correspondences.js
|
||||
// 03.2 7) เพิ่ม routes/correspondences.js (ใหม่)
|
||||
// - ใช้ร่วมกับ requirePerm() และ buildScopeWhere()
|
||||
// - สำหรับจัดการ correspondences (ดู/เพิ่ม/แก้ไข/ลบ) ตามสิทธิ์ของผู้ใช้
|
||||
// Correspondences routes
|
||||
// - CRUD operations for correspondences
|
||||
// - Requires appropriate permissions via requirePerm middleware
|
||||
// - Uses org scope for all permissions
|
||||
// - correspondence:read, correspondence:create, correspondence:update, correspondence:delete
|
||||
// - Correspondence fields: id (PK), org_id, project_id, corr_no, subject, status, created_by
|
||||
// - Basic validation: org_id, corr_no, subject required for create
|
||||
|
||||
// FILE: backend/src/routes/correspondences.js
|
||||
import { Router } from "express";
|
||||
import sql from "../db/index.js";
|
||||
import { requirePerm } from "../middleware/requirePerm.js";
|
||||
import { buildScopeWhere, ownerResolvers } from "../utils/scope.js";
|
||||
import PERM from "../config/permissions.js";
|
||||
|
||||
const r = Router();
|
||||
const OWN = ownerResolvers(sql, "correspondences", "id");
|
||||
|
||||
// LIST
|
||||
r.get(
|
||||
"/",
|
||||
requirePerm(PERM.correspondence.read, { scope: "global" }),
|
||||
requirePerm("corr.view", { projectParam: "project_id" }),
|
||||
async (req, res) => {
|
||||
const { project_id, org_id, q, limit = 50, offset = 0 } = req.query;
|
||||
const base = buildScopeWhere(req.principal, {
|
||||
tableAlias: "c",
|
||||
orgColumn: "c.org_id",
|
||||
projectColumn: "c.project_id",
|
||||
permCode: PERM.correspondence.read,
|
||||
preferProject: true,
|
||||
});
|
||||
const extra = [];
|
||||
const params = {
|
||||
...base.params,
|
||||
limit: Number(limit),
|
||||
offset: Number(offset),
|
||||
};
|
||||
if (project_id) {
|
||||
extra.push("c.project_id = :project_id");
|
||||
params.project_id = Number(project_id);
|
||||
const p = req.principal;
|
||||
const params = [];
|
||||
const cond = [];
|
||||
|
||||
if (!p.is_superadmin) {
|
||||
if (project_id) {
|
||||
if (!p.inProject(Number(project_id)))
|
||||
return res.status(403).json({ error: "FORBIDDEN_PROJECT" });
|
||||
cond.push("c.project_id=?");
|
||||
params.push(Number(project_id));
|
||||
} else if (p.project_ids?.length) {
|
||||
cond.push(
|
||||
`c.project_id IN (${p.project_ids.map(() => "?").join(",")})`
|
||||
);
|
||||
params.push(...p.project_ids);
|
||||
}
|
||||
} else if (project_id) {
|
||||
cond.push("c.project_id=?");
|
||||
params.push(Number(project_id));
|
||||
}
|
||||
|
||||
if (org_id) {
|
||||
extra.push("c.org_id = :org_id");
|
||||
params.org_id = Number(org_id);
|
||||
cond.push("c.org_id=?");
|
||||
params.push(Number(org_id));
|
||||
}
|
||||
if (q) {
|
||||
extra.push("(c.corr_no LIKE :q OR c.subject LIKE :q)");
|
||||
params.q = `%${q}%`;
|
||||
cond.push("(c.corr_no LIKE ? OR c.subject LIKE ?)");
|
||||
params.push(`%${q}%`, `%${q}%`);
|
||||
}
|
||||
const where = [base.where, ...extra].join(" AND ");
|
||||
|
||||
const where = cond.length ? `WHERE ${cond.join(" AND ")}` : "";
|
||||
const [rows] = await sql.query(
|
||||
`SELECT c.* FROM correspondences c WHERE ${where} ORDER BY c.id DESC LIMIT :limit OFFSET :offset`,
|
||||
params
|
||||
`SELECT c.* FROM correspondences c ${where} ORDER BY c.id DESC LIMIT ? OFFSET ?`,
|
||||
[...params, Number(limit), Number(offset)]
|
||||
);
|
||||
res.json(rows);
|
||||
}
|
||||
);
|
||||
|
||||
r.get(
|
||||
"/:id",
|
||||
requirePerm(PERM.correspondence.read, {
|
||||
scope: "org",
|
||||
getOrgId: OWN.getOrgIdById,
|
||||
}),
|
||||
async (req, res) => {
|
||||
const id = Number(req.params.id);
|
||||
const [[row]] = await sql.query(
|
||||
"SELECT * FROM correspondences WHERE id=?",
|
||||
[id]
|
||||
);
|
||||
if (!row) return res.status(404).json({ error: "Not found" });
|
||||
res.json(row);
|
||||
}
|
||||
);
|
||||
// GET
|
||||
r.get("/:id", requirePerm("corr.view"), async (req, res) => {
|
||||
const id = Number(req.params.id);
|
||||
const [[row]] = await sql.query("SELECT * FROM correspondences WHERE id=?", [
|
||||
id,
|
||||
]);
|
||||
if (!row) return res.status(404).json({ error: "Not found" });
|
||||
const p = req.principal;
|
||||
if (!p.is_superadmin && !p.inProject(row.project_id))
|
||||
return res.status(403).json({ error: "FORBIDDEN_PROJECT" });
|
||||
res.json(row);
|
||||
});
|
||||
|
||||
// CREATE
|
||||
r.post(
|
||||
"/",
|
||||
requirePerm(PERM.correspondence.create, {
|
||||
scope: "org",
|
||||
getOrgId: async (req) => req.body?.org_id ?? null,
|
||||
}),
|
||||
requirePerm("corr.manage", { projectParam: "project_id" }),
|
||||
async (req, res) => {
|
||||
const { org_id, project_id, corr_no, subject, status } = req.body;
|
||||
const { org_id, project_id, corr_no, subject, status } = req.body || {};
|
||||
if (!project_id || !corr_no)
|
||||
return res.status(400).json({ error: "project_id and corr_no required" });
|
||||
const [rs] = await sql.query(
|
||||
`INSERT INTO correspondences (org_id, project_id, corr_no, subject, status, created_by) VALUES (?,?,?,?,?,?)`,
|
||||
[org_id, project_id, corr_no, subject, status, req.principal.userId]
|
||||
`INSERT INTO correspondences (org_id, project_id, corr_no, subject, status, created_by)
|
||||
VALUES (?,?,?,?,?,?)`,
|
||||
[
|
||||
org_id || null,
|
||||
project_id,
|
||||
corr_no,
|
||||
subject || null,
|
||||
status || null,
|
||||
req.principal.user_id,
|
||||
]
|
||||
);
|
||||
res.json({ id: rs.insertId });
|
||||
}
|
||||
);
|
||||
|
||||
r.put(
|
||||
"/:id",
|
||||
requirePerm(PERM.correspondence.update, {
|
||||
scope: "org",
|
||||
getOrgId: OWN.getOrgIdById,
|
||||
}),
|
||||
async (req, res) => {
|
||||
const id = Number(req.params.id);
|
||||
const { subject, status } = req.body;
|
||||
await sql.query(
|
||||
"UPDATE correspondences SET subject=?, status=? WHERE id=?",
|
||||
[subject, status, id]
|
||||
);
|
||||
res.json({ ok: 1 });
|
||||
}
|
||||
);
|
||||
// UPDATE
|
||||
r.put("/:id", requirePerm("corr.manage"), async (req, res) => {
|
||||
const id = Number(req.params.id);
|
||||
const [[row]] = await sql.query("SELECT * FROM correspondences WHERE id=?", [
|
||||
id,
|
||||
]);
|
||||
if (!row) return res.status(404).json({ error: "Not found" });
|
||||
const p = req.principal;
|
||||
if (!p.is_superadmin && !p.inProject(row.project_id))
|
||||
return res.status(403).json({ error: "FORBIDDEN_PROJECT" });
|
||||
|
||||
r.delete(
|
||||
"/:id",
|
||||
requirePerm(PERM.correspondence.delete, {
|
||||
scope: "org",
|
||||
getOrgId: OWN.getOrgIdById,
|
||||
}),
|
||||
async (req, res) => {
|
||||
const id = Number(req.params.id);
|
||||
await sql.query("DELETE FROM correspondences WHERE id=?", [id]);
|
||||
res.json({ ok: 1 });
|
||||
}
|
||||
);
|
||||
const { subject, status } = req.body || {};
|
||||
await sql.query("UPDATE correspondences SET subject=?, status=? WHERE id=?", [
|
||||
subject ?? row.subject,
|
||||
status ?? row.status,
|
||||
id,
|
||||
]);
|
||||
res.json({ ok: 1 });
|
||||
});
|
||||
|
||||
// DELETE
|
||||
r.delete("/:id", requirePerm("corr.manage"), async (req, res) => {
|
||||
const id = Number(req.params.id);
|
||||
const [[row]] = await sql.query("SELECT * FROM correspondences WHERE id=?", [
|
||||
id,
|
||||
]);
|
||||
if (!row) return res.status(404).json({ error: "Not found" });
|
||||
const p = req.principal;
|
||||
if (!p.is_superadmin && !p.inProject(row.project_id))
|
||||
return res.status(403).json({ error: "FORBIDDEN_PROJECT" });
|
||||
await sql.query("DELETE FROM correspondences WHERE id=?", [id]);
|
||||
res.json({ ok: 1 });
|
||||
});
|
||||
|
||||
export default r;
|
||||
|
||||
Reference in New Issue
Block a user