제품관리리
This commit is contained in:
parent
d47da1827e
commit
996616fc23
113
plm-api/src/controllers/app/common/product.controller.js
Normal file
113
plm-api/src/controllers/app/common/product.controller.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// src/controllers/admin/users/users.controller.js
|
||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
const productService = require("../../../services/product.service");
|
||||||
|
const authMiddleware = require("../../../middleware/auth.middleware");
|
||||||
|
const roleCheck = require("../../../middleware/roleCheck.middleware");
|
||||||
|
const { body, param } = require("express-validator");
|
||||||
|
const validate = require("../../../middleware/validator.middleware");
|
||||||
|
|
||||||
|
router.use(authMiddleware);
|
||||||
|
router.use(roleCheck(["super_admin", "company_admin"]));
|
||||||
|
|
||||||
|
// 제품군 목록 조회
|
||||||
|
router.get("/productList", async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const page = parseInt(req.query.page) || 1;
|
||||||
|
const limit = parseInt(req.query.limit) || 10;
|
||||||
|
|
||||||
|
const result = await productService.findAll(req.user, page, limit);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create product
|
||||||
|
router.post(
|
||||||
|
"/productCreate",
|
||||||
|
[
|
||||||
|
body("product_name").notEmpty().withMessage("유효한 ID가 필요합니다"),
|
||||||
|
body("companyId").isUUID().withMessage("유효한 회사 ID가 필요합니다"),
|
||||||
|
validate,
|
||||||
|
],
|
||||||
|
async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const product = await productService.createProduct(req.body, req.user);
|
||||||
|
res.status(201).json(product);
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update productUp
|
||||||
|
router.put(
|
||||||
|
"/productUpdate/:id",
|
||||||
|
[
|
||||||
|
param("id").isUUID().withMessage("유효한 ID가 필요합니다"),
|
||||||
|
body("product_code").optional().notEmpty().withMessage("제품 코드가 필요합니다."),
|
||||||
|
body("product_name").optional().notEmpty().withMessage("제품 이름이 필요합니다."),
|
||||||
|
body("companyId").optional().isUUID().withMessage("유효한 회사 ID가 필요합니다"),
|
||||||
|
validate,
|
||||||
|
],
|
||||||
|
async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const product = await productService.findById(req.params.id);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
return res.status(404).json({ message: "고객사를 찾을 수 없습니다" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// company_admin은 자신의 회사 고객사만 수정 가능
|
||||||
|
if (
|
||||||
|
req.user.role === "company_admin" &&
|
||||||
|
product.companyId !== req.user.companyId
|
||||||
|
) {
|
||||||
|
return res.status(403).json({
|
||||||
|
message: "다른 회사의 제품군을 수정할 수 없습니다",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedProduct = await productService.updateProduct(req.params.id, req.body, req.user);
|
||||||
|
res.json(updatedProduct);
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete productUp
|
||||||
|
router.delete(
|
||||||
|
"/productDelete/:id",
|
||||||
|
[
|
||||||
|
param("id").isUUID().withMessage("유효한 ID가 필요합니다"),
|
||||||
|
validate,
|
||||||
|
],
|
||||||
|
async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const product = await productService.findById(req.params.id);
|
||||||
|
|
||||||
|
if (!product) {
|
||||||
|
return res.status(404).json({ message: "제품군을 찾을 수 없습니다" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// company_admin은 자신의 회사 고객사만 삭제 가능
|
||||||
|
if (
|
||||||
|
req.user.role === "company_admin" &&
|
||||||
|
product.companyId !== req.user.companyId
|
||||||
|
) {
|
||||||
|
return res.status(403).json({
|
||||||
|
message: "다른 회사의 제품군을 삭제할 수 없습니다",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await productService.deleteProduct(req.params.id, req.user);
|
||||||
|
res.status(204).end();
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -19,6 +19,7 @@ const deviceController = require("../controllers/app/device/device.controller");
|
|||||||
const commonController = require("../controllers/app/common/common.controller");
|
const commonController = require("../controllers/app/common/common.controller");
|
||||||
const oemMngController = require("../controllers/app/common/oemmng.controller");
|
const oemMngController = require("../controllers/app/common/oemmng.controller");
|
||||||
const productgroupController = require("../controllers/app/common/productgroup.controller");
|
const productgroupController = require("../controllers/app/common/productgroup.controller");
|
||||||
|
const productController = require("../controllers/app/common/product.controller");
|
||||||
|
|
||||||
router.use("/health", healthController);
|
router.use("/health", healthController);
|
||||||
router.use("/auth", authController);
|
router.use("/auth", authController);
|
||||||
@ -37,5 +38,6 @@ router.use("/devices", deviceController);
|
|||||||
router.use("/common", commonController);
|
router.use("/common", commonController);
|
||||||
router.use("/oemmng", oemMngController);
|
router.use("/oemmng", oemMngController);
|
||||||
router.use("/productgroup", productgroupController);
|
router.use("/productgroup", productgroupController);
|
||||||
|
router.use("/product", productController);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
163
plm-api/src/services/product.service.js
Normal file
163
plm-api/src/services/product.service.js
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
const {
|
||||||
|
Product,
|
||||||
|
Company,
|
||||||
|
Role,
|
||||||
|
} = require("../models");
|
||||||
|
//const { Op } = require("sequelize");
|
||||||
|
const alertService = require("./alert.service");
|
||||||
|
|
||||||
|
class productService {
|
||||||
|
async findAll(currentUser, page = 1, limit = 10) {
|
||||||
|
try {
|
||||||
|
// Initialize the where clause
|
||||||
|
let where = {};
|
||||||
|
|
||||||
|
// company_admin은 자신의 회사 유저만 조회 가능
|
||||||
|
if (currentUser.role === "company_admin") {
|
||||||
|
where.companyId = currentUser.companyId;
|
||||||
|
}
|
||||||
|
// isActive 필터 추가
|
||||||
|
//where.isActive = { [Op.eq]: true };
|
||||||
|
|
||||||
|
const offset = (page - 1) * limit;
|
||||||
|
|
||||||
|
// 전체 개수 조회
|
||||||
|
const count = await Product.count({ where });
|
||||||
|
|
||||||
|
const products = await Product.findAll({
|
||||||
|
where,
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Company,
|
||||||
|
attributes: ["id", "name"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
order: [["createdAt", "DESC"]],
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
distinct: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 인덱스 추가
|
||||||
|
const productsWithIndex = products.map((product, index) => {
|
||||||
|
const productJson = product.toJSON();
|
||||||
|
productJson.index = offset + index + 1;
|
||||||
|
return productJson;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: count,
|
||||||
|
totalPages: Math.ceil(count / limit),
|
||||||
|
currentPage: page,
|
||||||
|
products: productsWithIndex,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in findAll:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async findById(id) {
|
||||||
|
return await Product.findByPk(id, {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: Company,
|
||||||
|
attributes: ["id", "name"],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async createProduct(productData, currentUser) {
|
||||||
|
const { roleId, ...productFields } = productData;
|
||||||
|
|
||||||
|
// 등록자 정보 추가
|
||||||
|
productFields.writer = currentUser.name;
|
||||||
|
productFields.regdate = new Date();
|
||||||
|
|
||||||
|
const product = await Product.create(productFields);
|
||||||
|
|
||||||
|
if (roleId) {
|
||||||
|
const role = await Role.findOne({
|
||||||
|
where: {
|
||||||
|
id: roleId,
|
||||||
|
companyId: product.companyId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!role) {
|
||||||
|
throw new Error("Role not found or does not belong to the company");
|
||||||
|
}
|
||||||
|
|
||||||
|
await product.addRole(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
await alertService.createAlert({
|
||||||
|
type: "info",
|
||||||
|
message: `제품군 ${product.name}이(가) ${currentUser.name}에 의해 생성되었습니다.`,
|
||||||
|
companyId: product.companyId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateProduct(id, updateData, currentUser) {
|
||||||
|
const { roleId, ...productFields } = updateData;
|
||||||
|
|
||||||
|
const product = await Product.findByPk(id);
|
||||||
|
if (!product) throw new Error("Product not found");
|
||||||
|
|
||||||
|
// company_admin은 특정 필드를 수정할 수 없음 (예: role을 super_admin으로 변경 불가)
|
||||||
|
if (currentUser.role === "company_admin") {
|
||||||
|
if (updateData.role && updateData.role === "super_admin") {
|
||||||
|
throw new Error("super_admin 역할을 부여할 수 없습니다");
|
||||||
|
}
|
||||||
|
updateData.companyId = currentUser.companyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedProduct = await product.update(productFields);
|
||||||
|
|
||||||
|
if (roleId) {
|
||||||
|
const role = await Role.findOne({
|
||||||
|
where: {
|
||||||
|
id: roleId,
|
||||||
|
companyId: product.companyId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!role) {
|
||||||
|
throw new Error("Role not found or does not belong to the company");
|
||||||
|
}
|
||||||
|
|
||||||
|
await product.addRole(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
await alertService.createAlert({
|
||||||
|
type: "info",
|
||||||
|
message: `제품군 ${product.name}이(가) ${currentUser.name}에 의해 수정되었습니다.`,
|
||||||
|
companyId: product.companyId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return updatedProduct;
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteProduct(id, currentUser) {
|
||||||
|
const product = await Product.findByPk(id);
|
||||||
|
if (!product) throw new Error("Product not found");
|
||||||
|
|
||||||
|
const productName = product.product_name;
|
||||||
|
const companyId = product.companyId;
|
||||||
|
|
||||||
|
await product.destroy();
|
||||||
|
|
||||||
|
await alertService.createAlert({
|
||||||
|
type: "info",
|
||||||
|
message: `제품군 ${productName}이(가) ${currentUser.name}에 의해 삭제되었습니다.`,
|
||||||
|
companyId: companyId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new productService();
|
Loading…
Reference in New Issue
Block a user