You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

320 lines
9.7 KiB

10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
  1. const prisma = require("../utils/prisma");
  2. /**
  3. * @typedef {Object} Dept
  4. * @property {number} deptId
  5. * @property {number} parentId
  6. * @property {string} ancestors
  7. * @property {string} deptName
  8. * @property {number} orderNum
  9. * @property {number} status
  10. * @property {number} delFlag
  11. * @property {Date} createdAt
  12. * @property {Date} lastUpdatedAt
  13. */
  14. const Dept = {
  15. writable: [
  16. 'parentId', 'ancestors', 'deptName', 'orderNum', 'status', 'delFlag'
  17. ],
  18. validations: {
  19. deptName: (newValue = '') => {
  20. if (typeof newValue !== 'string' || newValue.length > 255) {
  21. throw new Error('Dept name must be a string and cannot be longer than 255 characters');
  22. }
  23. return newValue;
  24. },
  25. orderNum: (newValue = 0) => {
  26. const num = Number(newValue);
  27. if (isNaN(num)) {
  28. throw new Error('Order num must be a number');
  29. }
  30. return num;
  31. },
  32. status: (newValue = 0) => {
  33. const status = Number(newValue);
  34. if (isNaN(status) || status < 0 || status > 1) {
  35. throw new Error('Status must be a number between 0 and 1');
  36. }
  37. return status;
  38. },
  39. delFlag: (newValue = 0) => {
  40. const flag = Number(newValue);
  41. if (isNaN(flag) || flag < 0 || flag > 1) {
  42. throw new Error('Del flag must be a number between 0 and 1');
  43. }
  44. return flag;
  45. }
  46. },
  47. castColumnValue: function (key, value) {
  48. switch (key) {
  49. case 'status':
  50. case 'delFlag':
  51. return Number(value);
  52. default:
  53. return value;
  54. }
  55. },
  56. create: async function ({ parentId, ancestors, deptName, orderNum, status = 0, delFlag = 0 }) {
  57. try {
  58. const validatedDeptName = this.validations.deptName(deptName);
  59. const validatedOrderNum = this.validations.orderNum(orderNum);
  60. const validatedStatus = this.validations.status(status);
  61. const validatedDelFlag = this.validations.delFlag(delFlag);
  62. const dept = await prisma.dept.create({
  63. data: {
  64. parentId,
  65. ancestors,
  66. deptName: validatedDeptName,
  67. orderNum: validatedOrderNum,
  68. status: validatedStatus,
  69. delFlag: validatedDelFlag,
  70. createdAt: new Date(),
  71. lastUpdatedAt: new Date()
  72. }
  73. });
  74. return { dept, error: null };
  75. } catch (error) {
  76. console.error('FAILED TO CREATE DEPT.', error.message);
  77. return { dept: null, error: error.message };
  78. }
  79. },
  80. // 插入组织机构数据
  81. insertDept: async function (dept) {
  82. try {
  83. const insertedDept = await prisma.dept.create({
  84. data: {
  85. deptName: dept.deptName,
  86. parentId: dept.parentId || null,
  87. ancestors: dept.ancestors || null,
  88. orderNum: dept.orderNum || 0,
  89. status: dept.status || 0,
  90. delFlag: dept.delFlag || 0,
  91. createdAt: new Date(),
  92. lastUpdatedAt: new Date(),
  93. },
  94. });
  95. return insertedDept;
  96. } catch (error) {
  97. console.error("插入组织机构数据失败:", error);
  98. throw error;
  99. }
  100. },
  101. update: async function (deptId, updates = {}) {
  102. console.log("更新组织机构数据:", updates);
  103. try {
  104. // 检查 deptId 是否存在
  105. if (!deptId) throw new Error('没有提供用于查询的deptId');
  106. // 检查 updates 是否为空
  107. if (Object.keys(updates).length === 0) throw new Error('没有提供更新字段');
  108. // 查询当前组织机构
  109. const currentDept = await prisma.dept.findUnique({ where: { deptId } });
  110. if (!currentDept) throw new Error('不存在该组织机构');
  111. // 更新 lastUpdatedAt 字段
  112. updates.lastUpdatedAt = new Date();
  113. // 如果 parentId 发生变化,更新 ancestors 字段
  114. if (updates.parentId !== undefined && updates.parentId !== currentDept.parentId) {
  115. const parentId = updates.parentId;
  116. const parentDept = await prisma.dept.findUnique({ where: { deptId: parentId } });
  117. updates.ancestors = parentDept ? `${parentDept.ancestors},${parentId}` : `${parentId}`;
  118. }
  119. console.log("更新前组织机构数据:", updates);
  120. // 执行更新操作
  121. const updatedDept = await prisma.dept.update({
  122. where: { deptId }, // 使用 deptId 作为查询条件
  123. data: updates, // 更新的字段
  124. });
  125. console.log("更新后组织机构数据:", updatedDept);
  126. // 返回成功结果
  127. return { success: true, error: null, dept: updatedDept };
  128. } catch (error) {
  129. console.error(error.message);
  130. return { success: false, error: error.message, dept: null };
  131. }
  132. },
  133. get: async function (clause = {}) {
  134. try {
  135. const dept = await prisma.dept.findFirst({ where: clause, select: {
  136. deptId: true, parentId: true, ancestors: true, deptName: true, orderNum: true, status: true, delFlag: true, createdAt: true, lastUpdatedAt: true
  137. } });
  138. return dept ? { dept } : null;
  139. } catch (error) {
  140. console.error(error.message);
  141. return null;
  142. }
  143. },
  144. delete: async function (clause = {}) {
  145. try {
  146. const affectedRows = await prisma.dept.deleteMany({ where: clause });
  147. return affectedRows > 0;
  148. } catch (error) {
  149. console.error(error.message);
  150. return false;
  151. }
  152. },
  153. softDelete: async function (deptId) {
  154. try {
  155. // 检查 deptId 是否存在
  156. if (!deptId) throw new Error('没有提供用于查询的deptId');
  157. // 查询当前组织机构
  158. const currentDept = await prisma.dept.findUnique({ where: { deptId } });
  159. if (!currentDept) throw new Error('不存在该组织机构');
  160. // 执行逻辑删除操作
  161. const updatedDept = await prisma.dept.update({
  162. where: { deptId }, // 使用 deptId 作为查询条件
  163. data: {
  164. delFlag: 1, // 标记为已删除
  165. lastUpdatedAt: new Date(), // 更新最后修改时间
  166. },
  167. });
  168. console.log("逻辑删除后的组织机构数据:", updatedDept);
  169. // 返回成功结果
  170. return { success: true, error: null, dept: updatedDept };
  171. } catch (error) {
  172. console.error(error.message);
  173. return { success: false, error: error.message, dept: null };
  174. }
  175. },
  176. where: async function (clause = {}, limit = null) {
  177. try {
  178. const depts = await prisma.dept.findMany({
  179. where: clause,
  180. take: limit !== null ? limit : undefined,
  181. select: {
  182. deptId: true, parentId: true, ancestors: true, deptName: true, orderNum: true, status: true, delFlag: true, createdAt: true, lastUpdatedAt: true
  183. }
  184. });
  185. return depts;
  186. } catch (error) {
  187. console.error(error.message);
  188. return [];
  189. }
  190. },
  191. checkDeptNameUnique: async function (dept){
  192. try {
  193. const existingDept = await prisma.dept.findFirst({
  194. where: {
  195. deptName: dept.deptName, // 根据组织机构名称查询
  196. parentId: dept.parentId, // 排除父id
  197. },
  198. });
  199. // 如果查询到记录,说明组织机构名称已存在
  200. console.log("existingDept:", existingDept);
  201. return !existingDept;
  202. } catch (error) {
  203. console.error('检查组织机构名称唯一性失败:', error);
  204. throw error;
  205. }
  206. },
  207. // 检查组织机构是否包含未停用的子组织机构
  208. selectNormalChildrenDeptById: async function (deptId) {
  209. try {
  210. // 查询所有祖先组织机构中包含当前组织机构的未停用组织机构
  211. const childrenDepts = await prisma.$queryRaw`
  212. SELECT COUNT(*) as count
  213. FROM sys_dept
  214. WHERE status = 0
  215. AND del_flag = '0'
  216. AND FIND_IN_SET(${deptId}, ancestors)
  217. `;
  218. // 返回未停用的子组织机构数量
  219. return childrenDepts[0].count;
  220. } catch (error) {
  221. console.error("查询子组织机构失败:", error);
  222. throw error;
  223. }
  224. },
  225. // 检查组织机构是否有子组织机构
  226. hasChildByDeptId: async function (deptId) {
  227. try {
  228. const children = await prisma.dept.findMany({
  229. where: {
  230. parentId: deptId, // 查询当前组织机构的子组织机构
  231. delFlag: 0,
  232. },
  233. });
  234. // 如果有子组织机构,返回 true
  235. return children.length > 0;
  236. } catch (error) {
  237. console.error("检查子组织机构失败:", error);
  238. throw error;
  239. }
  240. },
  241. // 检查组织机构是否存在用户
  242. checkDeptExistUser: async function (deptId) {
  243. try {
  244. const deptUsers = await prisma.dept_users.findMany({
  245. where: {
  246. deptId: deptId, // 查询当前组织机构的用户
  247. },
  248. });
  249. // 如果存在用户,返回 true
  250. return deptUsers.length > 0;
  251. } catch (error) {
  252. console.error("检查组织机构用户失败:", error);
  253. throw error;
  254. }
  255. },
  256. /**
  257. * 获取组织机构树状结构
  258. * @returns {Promise<Array>}
  259. */
  260. getDeptTree:async function () {
  261. try {
  262. // 查询所有组织机构
  263. const allDepts = await prisma.dept.findMany();
  264. // 构建树状结构
  265. const buildTree = (parentId = null) => {
  266. return allDepts
  267. .filter((dept) => dept.parentId === parentId)
  268. .map((dept) => ({
  269. ...dept,
  270. children: buildTree(dept.deptId), // 递归获取子组织机构
  271. }));
  272. };
  273. return buildTree();
  274. } catch (error) {
  275. console.error("获取组织机构树状结构失败:", error);
  276. throw error;
  277. }
  278. },
  279. /**
  280. * 根据父组织机构 ID 获取子组织机构列表
  281. * @param {number} parentId - 父组织机构 ID
  282. * @returns {Promise<Array>}
  283. */
  284. getChildrenByParentId:async function (parentId = null) {
  285. try {
  286. const children = await prisma.dept.findMany({
  287. where: { parentId },
  288. });
  289. return children;
  290. } catch (error) {
  291. console.error("获取子组织机构列表失败:", error);
  292. throw error;
  293. }
  294. },
  295. };
  296. module.exports = { Dept };