9 changed files with 547 additions and 44 deletions
-
1.gitignore
-
63.idea/inspectionProfiles/Project_Default.xml
-
160server/endpoints/dept.js
-
2server/index.js
-
238server/models/dept.js
-
12server/prisma/migrations/20250222043007_init/migration.sql
-
10server/prisma/migrations/20250224030233_init_test_table/migration.sql
-
98server/prisma/schema.prisma
-
5server/utils/files/index.js
@ -1,6 +1,69 @@ |
|||
<component name="InspectionProjectProfileManager"> |
|||
<profile version="1.0"> |
|||
<option name="myName" value="Project Default" /> |
|||
<inspection_tool class="AliAccessStaticViaInstance" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliArrayNamingShouldHaveBracket" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliControlFlowStatementWithoutBraces" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliDeprecation" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliEqualsAvoidNull" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliLongLiteralsEndingWithLowercaseL" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliMissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AliWrapperTypeEquality" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAbstractClassShouldStartWithAbstractNaming" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAbstractMethodOrInterfaceMethodMustUseJavadoc" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidApacheBeanUtilsCopy" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidCallStaticSimpleDateFormat" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidCommentBehindStatement" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidComplexCondition" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidConcurrentCompetitionRandom" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidDoubleOrFloatEqualCompare" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidManuallyCreateThread" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidMissUseOfMathRandom" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidNegationOperator" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidNewDateGetTime" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidPatternCompileInMethod" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidReturnInFinally" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidStartWithDollarAndUnderLineNaming" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaAvoidUseTimer" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaBigDecimalAvoidDoubleConstructor" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaBooleanPropertyShouldNotStartWithIs" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaClassCastExceptionWithSubListToArrayList" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaClassCastExceptionWithToArray" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaClassMustHaveAuthor" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaCollectionInitShouldAssignCapacity" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaCommentsMustBeJavadocFormat" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaConcurrentExceptionWithModifyOriginSubList" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaCountDownShouldInFinally" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaDontModifyInForeachCircle" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaExceptionClassShouldEndWithException" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaIbatisMethodQueryForList" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaLockShouldWithTryFinally" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaLowerCamelCaseVariableNaming" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaMethodReturnWrapperType" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaMethodTooLong" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaPackageNaming" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaPojoMustOverrideToString" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaPojoMustUsePrimitiveField" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaPojoNoDefaultValue" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaRemoveCommentedCode" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaServiceOrDaoClassShouldEndWithImpl" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaSneakyThrowsWithoutExceptionType" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaStringConcat" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaSwitchExpression" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaSwitchStatement" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaTestClassShouldEndWithTestNaming" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaThreadLocalShouldRemove" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaThreadPoolCreation" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaThreadShouldSetName" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaTransactionMustHaveRollback" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaUndefineMagicConstant" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaUnsupportedExceptionWithModifyAsList" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaUseQuietReferenceNotation" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="AlibabaUseRightCaseForDateFormat" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
<inspection_tool class="MapOrSetKeyShouldOverrideHashCodeEquals" enabled="true" level="WARNING" enabled_by_default="true" /> |
|||
</profile> |
|||
</component> |
|||
@ -0,0 +1,160 @@ |
|||
const { Dept } = require("../models/dept"); |
|||
const { validatedRequest } = require("../utils/middleware/validatedRequest"); |
|||
const { |
|||
strictMultiUserRoleValid, |
|||
ROLES |
|||
} = require("../utils/middleware/multiUserProtected"); |
|||
function deptEndpoints(app) { |
|||
if (!app) return; |
|||
|
|||
app.get( |
|||
"/dept/list", |
|||
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])], |
|||
async (_request, response) => { |
|||
try { |
|||
const depts = await Dept.where(); |
|||
response.status(200).json({ depts }); |
|||
} catch (e) { |
|||
console.error(e); |
|||
response.sendStatus(500).end(); |
|||
} |
|||
} |
|||
); |
|||
|
|||
app.post("/dept/add", |
|||
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])], |
|||
async (request, response) => { |
|||
try { |
|||
const dept = request.body; // 获取请求体中的部门数据
|
|||
// 检查部门名称是否唯一
|
|||
const isUnique = await Dept.checkDeptNameUnique(dept); |
|||
if (!isUnique) { |
|||
return response.status(400).json({ |
|||
success: false, |
|||
message: `新增部门 '${dept.deptName}' 失败,部门名称已存在`, |
|||
}); |
|||
}; |
|||
// 按照deptId查询父部门
|
|||
const parentDept = await Dept.get({ deptId: dept.parentId }); |
|||
dept.ancestors = parentDept.dept.ancestors + ',' + dept.parentId; |
|||
// 插入部门数据
|
|||
const insertedDept = await Dept.insertDept(dept); |
|||
// 返回成功响应
|
|||
response.status(200).json({ |
|||
success: true, |
|||
data: insertedDept, |
|||
}); |
|||
} catch (error) { |
|||
// 处理错误
|
|||
console.error("添加部门失败:", error); |
|||
response.status(500).json({ |
|||
success: false, |
|||
message: "添加部门失败,服务器内部错误", |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
app.post("/dept/edit", |
|||
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])], |
|||
async (request, response) => { |
|||
try { |
|||
const dept = request.body; // 获取请求体中的部门数据
|
|||
|
|||
// 检查部门名称是否唯一
|
|||
const isUnique = await Dept.checkDeptNameUnique(dept); |
|||
if (!isUnique) { |
|||
return response.status(400).json({ |
|||
success: false, |
|||
message: `修改部门 '${dept.deptName}' 失败,部门名称已存在`, |
|||
}); |
|||
} |
|||
|
|||
// 检查上级部门是否是自己
|
|||
if (dept.parentId === dept.deptId) { |
|||
return response.status(400).json({ |
|||
success: false, |
|||
message: `修改部门 '${dept.deptName}' 失败,上级部门不能是自己`, |
|||
}); |
|||
} |
|||
|
|||
// 检查部门是否包含未停用的子部门
|
|||
if (dept.status === 1) { |
|||
const normalChildrenCount = await Dept.selectNormalChildrenDeptById(dept.deptId); |
|||
if (normalChildrenCount > 0) { |
|||
return response.status(400).json({ |
|||
success: false, |
|||
message: "该部门包含未停用的子部门!", |
|||
}); |
|||
} |
|||
} |
|||
// 更新部门数据
|
|||
const updatedDept = await Dept.update(dept); |
|||
// 返回成功响应
|
|||
response.status(200).json({ |
|||
success: true, |
|||
data: updatedDept, |
|||
}); |
|||
} catch (error) { |
|||
// 处理错误
|
|||
console.error("修改部门失败:", error); |
|||
response.status(500).json({ |
|||
success: false, |
|||
message: "修改部门失败,服务器内部错误", |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
// 删除部门的接口
|
|||
app.delete("/dept/:deptId", |
|||
[validatedRequest, strictMultiUserRoleValid([ROLES.admin])], |
|||
async (request, response) => { |
|||
try { |
|||
const deptId = parseInt(request.params.deptId); // 获取部门 ID
|
|||
|
|||
// 检查部门是否有子部门
|
|||
const hasChild = await Dept.hasChildByDeptId(deptId); |
|||
if (hasChild) { |
|||
return response.status(400).json({ |
|||
success: false, |
|||
message: "存在下级部门,不允许删除", |
|||
}); |
|||
} |
|||
|
|||
// 检查部门是否存在用户
|
|||
const hasUser = await Dept.checkDeptExistUser(deptId); |
|||
if (hasUser) { |
|||
return response.status(400).json({ |
|||
success: false, |
|||
message: "部门存在用户,不允许删除", |
|||
}); |
|||
} |
|||
|
|||
// // 检查部门数据权限
|
|||
// const hasDataScope = await Dept.checkDeptDataScope(deptId);
|
|||
// if (!hasDataScope) {
|
|||
// return response.status(403).json({
|
|||
// success: false,
|
|||
// message: "无权限删除该部门",
|
|||
// });
|
|||
// }
|
|||
|
|||
// 删除部门
|
|||
const deletedDept = await Dept.deleteDeptById(deptId); |
|||
|
|||
// 返回成功响应
|
|||
response.status(200).json({ |
|||
success: true, |
|||
data: deletedDept, |
|||
}); |
|||
} catch (error) { |
|||
// 处理错误
|
|||
console.error("删除部门失败:", error); |
|||
response.status(500).json({ |
|||
success: false, |
|||
message: "删除部门失败,服务器内部错误", |
|||
}); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
module.exports = { deptEndpoints }; |
|||
@ -0,0 +1,238 @@ |
|||
const prisma = require("../utils/prisma"); |
|||
|
|||
/** |
|||
* @typedef {Object} Dept |
|||
* @property {number} deptId |
|||
* @property {number} parentId |
|||
* @property {string} ancestors |
|||
* @property {string} deptName |
|||
* @property {number} orderNum |
|||
* @property {number} status |
|||
* @property {number} delFlag |
|||
* @property {Date} createdAt |
|||
* @property {Date} lastUpdatedAt |
|||
*/ |
|||
|
|||
const Dept = { |
|||
writable: [ |
|||
'parentId', 'ancestors', 'deptName', 'orderNum', 'status', 'delFlag' |
|||
], |
|||
validations: { |
|||
deptName: (newValue = '') => { |
|||
if (typeof newValue !== 'string' || newValue.length > 255) { |
|||
throw new Error('Dept name must be a string and cannot be longer than 255 characters'); |
|||
} |
|||
return newValue; |
|||
}, |
|||
orderNum: (newValue = 0) => { |
|||
const num = Number(newValue); |
|||
if (isNaN(num)) { |
|||
throw new Error('Order num must be a number'); |
|||
} |
|||
return num; |
|||
}, |
|||
status: (newValue = 0) => { |
|||
const status = Number(newValue); |
|||
if (isNaN(status) || status < 0 || status > 1) { |
|||
throw new Error('Status must be a number between 0 and 1'); |
|||
} |
|||
return status; |
|||
}, |
|||
delFlag: (newValue = 0) => { |
|||
const flag = Number(newValue); |
|||
if (isNaN(flag) || flag < 0 || flag > 1) { |
|||
throw new Error('Del flag must be a number between 0 and 1'); |
|||
} |
|||
return flag; |
|||
} |
|||
}, |
|||
castColumnValue: function (key, value) { |
|||
switch (key) { |
|||
case 'status': |
|||
case 'delFlag': |
|||
return Number(value); |
|||
default: |
|||
return value; |
|||
} |
|||
}, |
|||
create: async function ({ parentId, ancestors, deptName, orderNum, status = 0, delFlag = 0 }) { |
|||
try { |
|||
const validatedDeptName = this.validations.deptName(deptName); |
|||
const validatedOrderNum = this.validations.orderNum(orderNum); |
|||
const validatedStatus = this.validations.status(status); |
|||
const validatedDelFlag = this.validations.delFlag(delFlag); |
|||
|
|||
const dept = await prisma.dept.create({ |
|||
data: { |
|||
parentId, |
|||
ancestors, |
|||
deptName: validatedDeptName, |
|||
orderNum: validatedOrderNum, |
|||
status: validatedStatus, |
|||
delFlag: validatedDelFlag, |
|||
createdAt: new Date(), |
|||
lastUpdatedAt: new Date() |
|||
} |
|||
}); |
|||
|
|||
return { dept, error: null }; |
|||
} catch (error) { |
|||
console.error('FAILED TO CREATE DEPT.', error.message); |
|||
return { dept: null, error: error.message }; |
|||
} |
|||
}, |
|||
// 插入部门数据
|
|||
insertDept: async function (dept) { |
|||
try { |
|||
const insertedDept = await prisma.dept.create({ |
|||
data: { |
|||
deptName: dept.deptName, |
|||
parentId: dept.parentId || null, |
|||
ancestors: dept.ancestors || null, |
|||
orderNum: dept.orderNum || 0, |
|||
status: dept.status || 0, |
|||
delFlag: dept.delFlag || 0, |
|||
createdAt: new Date(), |
|||
lastUpdatedAt: new Date(), |
|||
}, |
|||
}); |
|||
return insertedDept; |
|||
} catch (error) { |
|||
console.error("插入部门数据失败:", error); |
|||
throw error; |
|||
} |
|||
}, |
|||
update: async function (deptId, updates = {}) { |
|||
try { |
|||
if (!deptId) throw new Error('No dept id provided for update'); |
|||
|
|||
const currentDept = await prisma.dept.findUnique({ where: { deptId } }); |
|||
if (!currentDept) throw new Error('Dept not found'); |
|||
|
|||
Object.entries(updates).forEach(([key, value]) => { |
|||
if (this.writable.includes(key)) { |
|||
if (Object.prototype.hasOwnProperty.call(this.validations, key)) { |
|||
updates[key] = this.validations[key](this.castColumnValue(key, value)); |
|||
} else { |
|||
updates[key] = this.castColumnValue(key, value); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
updates.lastUpdatedAt = new Date(); |
|||
|
|||
const updatedDept = await prisma.dept.update({ where: { deptId }, data: updates }); |
|||
|
|||
return { success: true, error: null, dept: updatedDept }; |
|||
} catch (error) { |
|||
console.error(error.message); |
|||
return { success: false, error: error.message, dept: null }; |
|||
} |
|||
}, |
|||
get: async function (clause = {}) { |
|||
try { |
|||
const dept = await prisma.dept.findFirst({ where: clause, select: { |
|||
deptId: true, parentId: true, ancestors: true, deptName: true, orderNum: true, status: true, delFlag: true, createdAt: true, lastUpdatedAt: true |
|||
} }); |
|||
return dept ? { dept } : null; |
|||
} catch (error) { |
|||
console.error(error.message); |
|||
return null; |
|||
} |
|||
}, |
|||
delete: async function (clause = {}) { |
|||
try { |
|||
const affectedRows = await prisma.dept.deleteMany({ where: clause }); |
|||
return affectedRows > 0; |
|||
} catch (error) { |
|||
console.error(error.message); |
|||
return false; |
|||
} |
|||
}, |
|||
where: async function (clause = {}, limit = null) { |
|||
try { |
|||
const depts = await prisma.dept.findMany({ |
|||
where: clause, |
|||
take: limit !== null ? limit : undefined, |
|||
select: { |
|||
deptId: true, parentId: true, ancestors: true, deptName: true, orderNum: true, status: true, delFlag: true, createdAt: true, lastUpdatedAt: true |
|||
} |
|||
}); |
|||
return depts; |
|||
} catch (error) { |
|||
console.error(error.message); |
|||
return []; |
|||
} |
|||
}, |
|||
checkDeptNameUnique: async function (dept){ |
|||
try { |
|||
const existingDept = await prisma.dept.findFirst({ |
|||
where: { |
|||
deptName: dept.deptName, // 根据部门名称查询
|
|||
parentId: dept.parentId, // 排除父id
|
|||
}, |
|||
}); |
|||
|
|||
// 如果查询到记录,说明部门名称已存在
|
|||
return !existingDept; |
|||
} catch (error) { |
|||
console.error('检查部门名称唯一性失败:', error); |
|||
throw error; |
|||
} |
|||
}, |
|||
|
|||
// 检查部门是否包含未停用的子部门
|
|||
selectNormalChildrenDeptById: async function (deptId) { |
|||
try { |
|||
// 查询所有祖先部门中包含当前部门的未停用部门
|
|||
const childrenDepts = await prisma.$queryRaw`
|
|||
SELECT COUNT(*) as count |
|||
FROM sys_dept |
|||
WHERE status = 0 |
|||
AND del_flag = '0' |
|||
AND FIND_IN_SET(${deptId}, ancestors) |
|||
`;
|
|||
|
|||
// 返回未停用的子部门数量
|
|||
return childrenDepts[0].count; |
|||
} catch (error) { |
|||
console.error("查询子部门失败:", error); |
|||
throw error; |
|||
} |
|||
}, |
|||
// 检查部门是否有子部门
|
|||
hasChildByDeptId: async function (deptId) { |
|||
try { |
|||
const children = await prisma.dept.findMany({ |
|||
where: { |
|||
parentId: deptId, // 查询当前部门的子部门
|
|||
delFlag: 0, |
|||
}, |
|||
}); |
|||
|
|||
// 如果有子部门,返回 true
|
|||
return children.length > 0; |
|||
} catch (error) { |
|||
console.error("检查子部门失败:", error); |
|||
throw error; |
|||
} |
|||
}, |
|||
// 检查部门是否存在用户
|
|||
checkDeptExistUser: async function (deptId) { |
|||
try { |
|||
const users = await prisma.user.findMany({ |
|||
where: { |
|||
deptId: deptId, // 查询当前部门的用户
|
|||
}, |
|||
}); |
|||
|
|||
// 如果存在用户,返回 true
|
|||
return users.length > 0; |
|||
} catch (error) { |
|||
console.error("检查部门用户失败:", error); |
|||
throw error; |
|||
} |
|||
}, |
|||
}; |
|||
|
|||
module.exports = { Dept }; |
|||
@ -0,0 +1,12 @@ |
|||
-- CreateTable |
|||
CREATE TABLE "dept" ( |
|||
"deptId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, |
|||
"parentId" INTEGER, |
|||
"ancestors" TEXT, |
|||
"deptName" TEXT, |
|||
"orderNum" INTEGER, |
|||
"status" INTEGER NOT NULL DEFAULT 0, |
|||
"delFlag" INTEGER NOT NULL DEFAULT 0, |
|||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, |
|||
"lastUpdatedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP |
|||
); |
|||
@ -0,0 +1,10 @@ |
|||
-- CreateTable |
|||
CREATE TABLE "dept_users" ( |
|||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, |
|||
"deptId" INTEGER NOT NULL, |
|||
"userId" INTEGER NOT NULL, |
|||
"createdAt" DATETIME DEFAULT CURRENT_TIMESTAMP, |
|||
"updatedAt" DATETIME DEFAULT CURRENT_TIMESTAMP, |
|||
CONSTRAINT "dept_users_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, |
|||
CONSTRAINT "dept_users_deptId_fkey" FOREIGN KEY ("deptId") REFERENCES "dept" ("deptId") ON DELETE CASCADE ON UPDATE NO ACTION |
|||
); |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue