diff --git a/xm-core/src/main/java/com/xm/core/ctrl/XmProductController.java b/xm-core/src/main/java/com/xm/core/ctrl/XmProductController.java index 69066cff..cc7626d2 100644 --- a/xm-core/src/main/java/com/xm/core/ctrl/XmProductController.java +++ b/xm-core/src/main/java/com/xm/core/ctrl/XmProductController.java @@ -12,6 +12,8 @@ import com.xm.core.entity.XmProduct; import com.xm.core.entity.XmProductCopyVo; import com.xm.core.entity.XmProject; import com.xm.core.service.XmProductService; +import com.xm.core.service.XmProjectGroupService; +import com.xm.core.service.XmProjectService; import io.swagger.annotations.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -44,6 +46,8 @@ public class XmProductController { @Autowired private XmProductService xmProductService; + @Autowired + private XmProjectGroupService groupService; @Value("${mdp.platform-branch-id:platform-branch-001}") String platformBranchId="platform-branch-001"; @@ -266,7 +270,7 @@ public class XmProductController { return ResponseHelper.failed("pstatus-not-0-3","该产品不是初始、已关闭状态,不允许删除"); }else if(!user.getBranchId().equals(xmProductDb.getBranchId())){ return ResponseHelper.failed("branchId-not-right","该产品不属于您所在的机构,不允许删除"); - }else if(!user.getUserid().equals(xmProductDb.getPmUserid()) && !user.getUserid().equals(xmProductDb.getAssUserid())){ + }else if(!groupService.checkUserIsProductAdm(xmProductDb,user.getUserid())){ return ResponseHelper.failed("pmUserid-not-right","您不是该产品产品负责人,也不是产品助理,不允许删除"); } if(!"1".equals(xmProductDb.getIsTpl())){ @@ -301,6 +305,11 @@ public class XmProductController { Map m = new HashMap<>(); Tips tips=new Tips("成功更新一条数据"); try{ + XmProduct xmProductDb=xmProductService.getProductFromCache(xmProduct.getId()); + if(xmProductDb==null){ + return ResponseHelper.failed("product-0","产品已不存在"); + } + xmProductService.updateByPk(xmProduct); xmProductService.clearCache(xmProduct.getId()); m.put("data",xmProduct); @@ -347,7 +356,7 @@ public class XmProductController { otips.setFailureMsg("pstatus-not-0-3","产品【"+xmProductDb.getProductName()+"】不是初始、已关闭状态,不允许删除"); }else if(!user.getBranchId().equals(xmProductDb.getBranchId())){ otips.setFailureMsg("branchId-not-right","产品【"+xmProductDb.getProductName()+"】不属于您所在的机构,不允许删除"); - }else if(!user.getUserid().equals(xmProductDb.getPmUserid()) && !user.getUserid().equals(xmProductDb.getAssUserid())){ + }else if(!groupService.checkUserIsProductAdm(xmProductDb,user.getUserid())){ otips.setFailureMsg("pmUserid-not-right","您不是产品【"+xmProductDb.getProductName()+"】负责人,也不是产品助理,不允许删除"); }else{ if(!"1".equals(xmProductDb.getIsTpl())){ diff --git a/xm-core/src/main/java/com/xm/core/ctrl/XmProductPhaseController.java b/xm-core/src/main/java/com/xm/core/ctrl/XmProductPhaseController.java new file mode 100644 index 00000000..5123cb61 --- /dev/null +++ b/xm-core/src/main/java/com/xm/core/ctrl/XmProductPhaseController.java @@ -0,0 +1,716 @@ +package com.xm.core.ctrl; + +import com.alibaba.fastjson.JSON; +import com.mdp.core.entity.Tips; +import com.mdp.core.err.BizException; +import com.mdp.core.utils.NumberUtil; +import com.mdp.core.utils.RequestUtils; +import com.mdp.core.utils.ResponseHelper; +import com.mdp.mybatis.PageUtils; +import com.mdp.qx.HasQx; +import com.mdp.safe.client.entity.User; +import com.mdp.safe.client.utils.LoginUtils; +import com.xm.core.PubTool; +import com.xm.core.entity.XmProduct; +import com.xm.core.entity.XmProjectPhase; +import com.xm.core.service.*; +import com.xm.core.vo.XmProjectGroupVo; +import com.xm.core.vo.XmProjectPhaseVo; +import io.swagger.annotations.*; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.*; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +import static com.mdp.core.utils.BaseUtils.map; + +/** + * url编制采用rest风格,如对XM.xm_project_phase 产品计划模板的操作有增删改查,对应的url分别为:
+ * 新增: xm/xmProjectPhase/add
+ * 查询: xm/xmProjectPhase/list
+ * 模糊查询: xm/xmProjectPhase/listKey
+ * 修改: xm/xmProjectPhase/edit
+ * 删除: xm/xmProjectPhase/del
+ * 批量删除: xm/xmProjectPhase/batchDel
+ * 组织 com.qqkj 顶级模块 oa 大模块 xm 小模块
+ * 实体 XmProjectPhase 表 XM.xm_project_phase 当前主键(包括多主键): id; + ***/ +@RestController("xm.core.xmProductPhaseController") +@RequestMapping(value="/**/xm/core/xmProductPhase") +@Api(tags={"产品计划模板操作接口"}) +public class XmProductPhaseController { + + static Log logger=LogFactory.getLog(XmProductPhaseController.class); + + @Autowired + private XmProjectPhaseService xmProjectPhaseService; + + @Autowired + private XmProjectGroupService groupService; + + @Autowired + private XmProjectService xmProjectService; + + + @Autowired + private XmProductService xmProductService; + + @Autowired + XmRecordService xmRecordService; + + @ApiOperation( value = "查询产品计划模板信息列表",notes="listXmProjectPhase,条件之间是 and关系,模糊查询写法如 {studentName:'%才哥%'}") + @ApiImplicitParams({ + @ApiImplicitParam(name="id",value="计划主键,主键",required=false), + @ApiImplicitParam(name="phaseName",value="计划名称",required=false), + @ApiImplicitParam(name="remark",value="备注",required=false), + @ApiImplicitParam(name="parentPhaseId",value="上级计划编号",required=false), + @ApiImplicitParam(name="branchId",value="机构编号",required=false), + @ApiImplicitParam(name="productId",value="当前产品编号",required=false), + @ApiImplicitParam(name="beginDate",value="开始时间",required=false), + @ApiImplicitParam(name="endDate",value="结束时间",required=false), + @ApiImplicitParam(name="phaseBudgetHours",value="工时(不包括下一级)-应该大于或等于task中总工时",required=false), + @ApiImplicitParam(name="phaseBudgetStaffNu",value="投入人员数(不包括下一级)-应该大于或等于task中总人数",required=false), + @ApiImplicitParam(name="ctime",value="创建时间",required=false), + @ApiImplicitParam(name="phaseBudgetNouserAt",value="非人力成本总预算(不包括下一级)-应该大于或等于task中非人力总成本",required=false), + @ApiImplicitParam(name="phaseBudgetInnerUserAt",value="内部人力成本总预算(不包括下一级)-应该大于或等于task中内部人力总成本",required=false), + @ApiImplicitParam(name="phaseBudgetOutUserAt",value="外购人力成本总预算(不包括下一级)-应该大于或等于task中外购总成本",required=false), + @ApiImplicitParam(name="projectBaselineId",value="产品级基线",required=false), + @ApiImplicitParam(name="bizProcInstId",value="当前流程实例编号",required=false), + @ApiImplicitParam(name="bizFlowState",value="当前流程状态0初始1审批中2审批通过3审批不通过4流程取消或者删除",required=false), + @ApiImplicitParam(name="phaseBudgetWorkload",value="总工作量单位人时-应该大于或者等于task中的预算总工作量",required=false), + @ApiImplicitParam(name="phaseActWorkload",value="已完成工作量单位人时-从task中的实际工作量算出",required=false), + @ApiImplicitParam(name="phaseActInnerUserWorkload",value="实际内部人力工作量-来自任务表合计",required=false), + @ApiImplicitParam(name="phaseActOutUserWorkload",value="实际外购人力工作量-来自任务表合计",required=false), + @ApiImplicitParam(name="taskType",value="0售前方案1投标2需求3设计4开发5测试6验收7部署8运维--来自基础数据表taskType",required=false), + @ApiImplicitParam(name="planType",value="计划类型w1-周,w2-2周,w3-3周,m1-1月,m2-2月,q1-季,q2-半年,y1-年",required=false), + @ApiImplicitParam(name="seqNo",value="顺序号",required=false), + @ApiImplicitParam(name="phaseBudgetInnerUserWorkload",value="内部人力工作量总预算(不包括下一级)-应该大于或等于task中内部人力总成本",required=false), + @ApiImplicitParam(name="phaseBudgetOutUserWorkload",value="外购人力工作量总预算(不包括下一级)-应该大于或等于task中外购总成本",required=false), + @ApiImplicitParam(name="actNouserAt",value="实际非人力成本-来自任务表合计",required=false), + @ApiImplicitParam(name="actInnerUserAt",value="实际内部人力成本-来自任务表合计",required=false), + @ApiImplicitParam(name="phaseBudgetInnerUserPrice",value="内部人力成本单价元/人时",required=false), + @ApiImplicitParam(name="phaseBudgetOutUserPrice",value="外购人力成本单价元/人时",required=false), + @ApiImplicitParam(name="phaseBudgetOutUserCnt",value="外购人数",required=false), + @ApiImplicitParam(name="phaseBudgetInnerUserCnt",value="内部人数",required=false), + @ApiImplicitParam(name="actRate",value="实际进度0-100",required=false), + @ApiImplicitParam(name="phaseStatus",value="计划状态0初始1执行中2完工3关闭4删除中5已删除6暂停",required=false), + @ApiImplicitParam(name="actOutUserAt",value="实际外部人力成本",required=false), + @ApiImplicitParam(name="taskCnt",value="任务数",required=false), + @ApiImplicitParam(name="finishTaskCnt",value="完成的任务数",required=false), + @ApiImplicitParam(name="iterationCnt",value="迭代数",required=false), + @ApiImplicitParam(name="pageSize",value="每页记录数",required=false), + @ApiImplicitParam(name="currentPage",value="当前页码,从1开始",required=false), + @ApiImplicitParam(name="total",value="总记录数,服务器端收到0时,会自动计算总记录数,如果上传>0的不自动计算",required=false), + @ApiImplicitParam(name="orderFields",value="排序列 如性别、学生编号排序 ['sex','studentId']",required=false), + @ApiImplicitParam(name="orderDirs",value="排序方式,与orderFields对应,升序 asc,降序desc 如 性别 升序、学生编号降序 ['asc','desc']",required=false) + }) + @ApiResponses({ + @ApiResponse(code = 200,response= XmProjectPhase.class,message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'错误码'},pageInfo:{total:总记录数},data:[数据对象1,数据对象2,...]}") + }) + @RequestMapping(value="/list",method=RequestMethod.GET) + public Map listXmProjectPhase( @RequestParam Map xmProjectPhase){ + Map m = new HashMap<>(); + RequestUtils.transformArray(xmProjectPhase, "ids"); + PageUtils.startPage(xmProjectPhase); + List> xmProjectPhaseList = xmProjectPhaseService.selectListMapByWhere(xmProjectPhase); //列出XmProjectPhase列表 + PageUtils.responePage(m, xmProjectPhaseList); + if("1".equals(xmProjectPhase.get("withParents")) && !"1".equals(xmProjectPhase.get("isTop")) && xmProjectPhaseList.size()>0){ + Set pidPathsSet=new HashSet<>(); + Set idSet=new HashSet<>(); + for (Map map : xmProjectPhaseList) { + String id= (String) map.get("id"); + idSet.add(id); + String pidPaths= (String) map.get("pidPaths"); + pidPaths=PubTool.getPidPaths(pidPaths,id); + if(pidPaths.length()<=2){ + continue; + } + pidPathsSet.add(pidPaths); + } + if(pidPathsSet!=null && pidPathsSet.size()>0){ + List> parentList=xmProjectPhaseService.selectListMapByWhere(map("pidPathsList",pidPathsSet.stream().collect(Collectors.toList()))); + parentList=parentList.stream().filter(i->!idSet.contains(i.get("id"))).collect(Collectors.toList()); + if(parentList!=null && parentList.size()>0){ + xmProjectPhaseList.addAll(parentList); + m.put("total", NumberUtil.getInteger(m.get("total"),0)+parentList.size()); + } + } + } + m.put("data",xmProjectPhaseList); + Tips tips=new Tips("查询成功"); + m.put("tips", tips); + return m; + } + + + @HasQx(value = "xm_core_xmProductPhase_setPhaseMngUser",name = "设置计划负责人",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/setPhaseMngUser",method=RequestMethod.POST) + public Map setPhaseMngUser(@RequestBody XmProjectPhase xmProjectPhase) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功设置"); + try{ + if(StringUtils.isEmpty(xmProjectPhase.getId())) { + tips.setFailureMsg("计划编号不能为空"); + m.put("tips", tips); + return m; + }else{ + XmProjectPhase xmProjectPhaseQuery = new XmProjectPhase(xmProjectPhase.getId()); + XmProjectPhase xmProjectPhaseDb=this.xmProjectPhaseService.selectOneObject(xmProjectPhaseQuery); + if(xmProjectPhaseDb==null){ + tips.setFailureMsg("计划不存在"); + m.put("tips", tips); + return m; + } + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhaseDb.getProductId()); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhaseDb.getProductId()); + User user = LoginUtils.getCurrentUserInfo(); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许设置计划负责人"); + m.put("tips", tips); + return m; + } + boolean meIsHisTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,xmProjectPhase.getMngUserid(),user.getUserid()); + if( !meIsPm && !meIsHisTeamHead ){ + tips.setFailureMsg("您不是"+xmProjectPhase.getMngUsername()+"的组长,不允许设置其为计划负责人"); + m.put("tips", tips); + return m; + } + if(tips.isOk()){ + XmProjectPhase xmProjectPhaseToUpdate=new XmProjectPhase(); + xmProjectPhaseToUpdate.setId(xmProjectPhase.getId()); + xmProjectPhaseToUpdate.setMngUserid(xmProjectPhase.getMngUserid()); + xmProjectPhaseToUpdate.setMngUsername(xmProjectPhase.getMngUsername()); + this.xmProjectPhaseService.updateSomeFieldByPk(xmProjectPhaseToUpdate); + } + } + + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + + @ApiOperation( value = "新增一条xm_project_phase信息",notes="addXmProjectPhase,主键如果为空,后台自动生成") + @ApiResponses({ + @ApiResponse(code = 200,response=XmProjectPhase.class,message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'},data:数据对象}") + }) + @HasQx(value = "xm_core_xmProductPhase_add",name = "创建产品计划",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/add",method=RequestMethod.POST) + public Map addXmProjectPhase(@RequestBody XmProjectPhase xmProjectPhase) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功新增一条数据"); + try{ + if(StringUtils.isEmpty(xmProjectPhase.getId())) { + xmProjectPhase.setId(xmProjectPhaseService.createKey("id")); + }else{ + XmProjectPhase xmProjectPhaseQuery = new XmProjectPhase(xmProjectPhase.getId()); + if(xmProjectPhaseService.countByWhere(xmProjectPhaseQuery)>0){ + tips.setFailureMsg("编号重复,请修改编号再提交"); + m.put("tips", tips); + return m; + } + } + User user = LoginUtils.getCurrentUserInfo(); + if(!StringUtils.hasText(xmProjectPhase.getMngUserid())){ + xmProjectPhase.setMngUserid(user.getUserid()); + xmProjectPhase.setMngUsername(user.getUsername()); + } + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhase.getProductId()); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhase.getProductId()); + + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许设置计划负责人"); + m.put("tips", tips); + return m; + } + boolean meIsHisTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,xmProjectPhase.getMngUserid(),user.getUserid()); + if( !meIsPm && !meIsHisTeamHead ){ + tips.setFailureMsg("您不是"+xmProjectPhase.getMngUsername()+"的组长,不允许设置其为计划负责人"); + m.put("tips", tips); + return m; + } + BigDecimal phaseBudgetCost=BigDecimal.ZERO; + String productId=null; + BigDecimal zero=BigDecimal.ZERO; + productId=xmProjectPhase.getProductId(); + BigDecimal phaseBudgetInnerUserAt=NumberUtil.getBigDecimal(xmProjectPhase.getPhaseBudgetInnerUserAt(),zero); + BigDecimal phaseBudgetOutUserAt=NumberUtil.getBigDecimal(xmProjectPhase.getPhaseBudgetOutUserAt(),zero); + BigDecimal phaseBudgetNouserAt=NumberUtil.getBigDecimal(xmProjectPhase.getPhaseBudgetNouserAt(),zero); + phaseBudgetCost=phaseBudgetCost.add(phaseBudgetInnerUserAt).add(phaseBudgetOutUserAt).add(phaseBudgetNouserAt); + List excludePhaseIds=new ArrayList<>(); + excludePhaseIds.add(xmProjectPhase.getId()); + if(!StringUtils.hasText(xmProjectPhase.getParentPhaseId())){//如果为顶级计划,预算不能大于产品总预算 + Tips judgetTips=xmProjectPhaseService.judgetProductBudget(productId, phaseBudgetCost,phaseBudgetInnerUserAt,phaseBudgetOutUserAt,phaseBudgetNouserAt,excludePhaseIds); + }else{ + XmProjectPhase parentDb=xmProjectPhaseService.selectOneObject(new XmProjectPhase(xmProjectPhase.getParentPhaseId())); + if(parentDb==null){ + return ResponseHelper.failed("p-no-exists","上级计划不存在"); + } + if(!"1".equals(parentDb.getNtype())){ + return ResponseHelper.failed("p-ntype-no-1","上级【"+parentDb.getPhaseName()+"】不是计划集,不能在其之下建立子计划"); + } + } + xmProjectPhaseService.parentIdPathsCalcBeforeSave(xmProjectPhase); + xmProjectPhaseService.insert(xmProjectPhase); + xmRecordService.addProductPhaseRecord(productId, xmProjectPhase.getId(), "产品-计划-新增计划", "新增计划"+xmProjectPhase.getPhaseName(),JSON.toJSONString(xmProjectPhase),null); + m.put("data",xmProjectPhase); + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + /***/ + @ApiOperation( value = "删除一条xm_project_phase信息",notes="delXmProjectPhase,仅需要上传主键字段") + @ApiResponses({ + @ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}}") + }) + @HasQx(value = "xm_core_xmProductPhase_del",name = "删除产品计划",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/del",method=RequestMethod.POST) + public Map delXmProjectPhase(@RequestBody XmProjectPhase xmProjectPhase){ + Map m = new HashMap<>(); + Tips tips=new Tips("成功删除一条数据"); + try{ + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhase.getProductId()); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhase.getProductId()); + User user = LoginUtils.getCurrentUserInfo(); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许删除计划"); + m.put("tips", tips); + return m; + } + boolean meIsHisTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,xmProjectPhase.getMngUserid(),user.getUserid()); + if( !meIsPm && !meIsHisTeamHead ){ + tips.setFailureMsg("您不是"+xmProjectPhase.getMngUsername()+"的组长,不允许删除其负责的计划"); + m.put("tips", tips); + return m; + } + //检查是否由关联的任务,有则不允许删除 + Long exists=this.xmProjectPhaseService.checkExistsTask(xmProjectPhase.getId()); + if(exists>0) { + tips.setFailureMsg("存在"+exists+"条任务,不允许删除"); + }else { + XmProjectPhase xmProjectPhaseDb=this.xmProjectPhaseService.selectOneObject(xmProjectPhase); + if(xmProjectPhaseDb.getChildrenCnt()!=null && xmProjectPhaseDb.getChildrenCnt()>0){ + tips.setFailureMsg("存在"+xmProjectPhaseDb.getChildrenCnt()+"条子计划,不允许删除"); + } else { + xmProjectPhaseService.deleteByPk(xmProjectPhaseDb); + xmRecordService.addProductPhaseRecord(xmProjectPhaseDb.getProductId(), xmProjectPhaseDb.getId(), "产品-计划-删除计划", "删除计划"+xmProjectPhaseDb.getPhaseName(),JSON.toJSONString(xmProjectPhaseDb),null); + } + } + + + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + + + /***/ + @ApiOperation( value = "根据主键修改一条xm_project_phase信息",notes="editXmProjectPhase") + @ApiResponses({ + @ApiResponse(code = 200,response=XmProjectPhase.class, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'},data:数据对象}") + }) + @HasQx(value = "xm_core_xmProductPhase_edit",name = "修改产品计划基础信息",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/edit",method=RequestMethod.POST) + public Map editXmProjectPhase(@RequestBody XmProjectPhase xmProjectPhase) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功更新一条数据"); + try{ + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhase.getProductId()); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhase.getProductId()); + User user = LoginUtils.getCurrentUserInfo(); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许修改计划"); + m.put("tips", tips); + return m; + } + if(!StringUtils.hasText(xmProjectPhase.getMngUserid())){ + xmProjectPhase.setMngUserid(user.getUserid()); + xmProjectPhase.setMngUsername(user.getUsername()); + } + boolean meIsHisTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,xmProjectPhase.getMngUserid(),user.getUserid()); + if( !meIsPm && !meIsHisTeamHead ){ + tips.setFailureMsg("您不是"+xmProjectPhase.getMngUsername()+"的组长,不允许修改其负责的计划"); + m.put("tips", tips); + return m; + } + BigDecimal phaseBudgetCost=BigDecimal.ZERO; + String productId=null; + BigDecimal zero=BigDecimal.ZERO; + productId=xmProjectPhase.getProductId(); + BigDecimal phaseBudgetInnerUserAt=NumberUtil.getBigDecimal(xmProjectPhase.getPhaseBudgetInnerUserAt(),zero); + BigDecimal phaseBudgetOutUserAt=NumberUtil.getBigDecimal(xmProjectPhase.getPhaseBudgetOutUserAt(),zero); + BigDecimal phaseBudgetNouserAt=NumberUtil.getBigDecimal(xmProjectPhase.getPhaseBudgetNouserAt(),zero); + phaseBudgetCost=phaseBudgetCost.add(phaseBudgetInnerUserAt).add(phaseBudgetOutUserAt).add(phaseBudgetNouserAt); + List excludePhaseIds=new ArrayList<>(); + excludePhaseIds.add(xmProjectPhase.getId()); + Tips judgetTips=xmProjectPhaseService.judgetBudget(productId, phaseBudgetCost,phaseBudgetInnerUserAt,phaseBudgetOutUserAt,phaseBudgetNouserAt,excludePhaseIds); + if(judgetTips.isOk()) { + xmProjectPhase=xmProjectPhaseService.autoCalcWorkload(xmProjectPhase); + xmProjectPhaseService.editByPk(xmProjectPhase); + xmRecordService.addProductPhaseRecord(xmProjectPhase.getProductId(), xmProjectPhase.getId(), "产品-计划-修改计划", "修改计划"+xmProjectPhase.getPhaseName(),JSON.toJSONString(xmProjectPhase),null); + + }else { + tips=judgetTips; + } + m.put("data",xmProjectPhase); + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + + + + /***/ + @ApiOperation( value = "根据主键列表批量删除xm_project_phase信息",notes="batchDelXmProjectPhase,仅需要上传主键字段") + @ApiResponses({ + @ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}") + }) + @HasQx(value = "xm_core_xmProductPhase_batchDel",name = "批量删除产品计划",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/batchDel",method=RequestMethod.POST) + public Map batchDelXmProjectPhase(@RequestBody List xmProjectPhases) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功删除"+(xmProjectPhases==null?0:xmProjectPhases.size())+"条数据"); + try{ + if(xmProjectPhases==null || xmProjectPhases.size()==0){ + tips.setFailureMsg("计划不能为空"); + m.put("tips", tips); + return m; + } + XmProjectPhase xmProjectPhase=xmProjectPhases.get(0); + if(!StringUtils.hasText(xmProjectPhase.getProductId())){ + tips.setFailureMsg("产品编号不能为空"); + m.put("tips", tips); + return m; + } + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhase.getProductId()); + List existsTaskList=new ArrayList<>(); + List hasChildList=new ArrayList<>(); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhase.getProductId()); + User user = LoginUtils.getCurrentUserInfo(); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许删除计划"); + m.put("tips", tips); + return m; + } + List noQxUsernames=new ArrayList<>(); + List delPhases=new ArrayList<>(); + List xmProjectPhaseListDb=this.xmProjectPhaseService.selectListByIds(xmProjectPhases.stream().map(i->i.getId()).collect(Collectors.toList())); + for (XmProjectPhase phase : xmProjectPhaseListDb) { + boolean meIsHisTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,phase.getMngUserid(),user.getUserid()); + if( !meIsPm && !meIsHisTeamHead ){ + noQxUsernames.add(phase.getMngUsername()); + continue; + } + //检查是否由关联的任务,有则不允许删除 + Long exists=this.xmProjectPhaseService.checkExistsTask(phase.getId()); + if(exists>0) { + existsTaskList.add(phase.getPhaseName()); + }else { + delPhases.add(phase); + } + } + List canDelNodes=new ArrayList<>(); + for (XmProjectPhase phase : delPhases) { + + boolean canDelAllChild =xmProjectPhaseService.checkCanDelAllChild(phase,delPhases); + if(!canDelAllChild) { + hasChildList.add(phase.getPhaseName()); + }else { + canDelNodes.add(phase); + } + } + if(canDelNodes.size()>0){ + this.xmProjectPhaseService.doBatchDelete(canDelNodes); + } + List msgs=new ArrayList<>(); + msgs.add("成功删除"+canDelNodes.size()+"条数据。"); + if(noQxUsernames.size()>0){ + msgs.add("您无权删除以下人员所负责的计划【"+StringUtils.arrayToCommaDelimitedString(noQxUsernames.toArray())+"】"); + } + if(hasChildList.size()>0){ + msgs.add("以下计划存在子计划,不允许删除。【"+hasChildList.stream().collect(Collectors.joining(","))+"】"); + } + + if(existsTaskList.size()>0){ + msgs.add("以下计划存在关联的任务,不允许删除。【"+existsTaskList.stream().collect(Collectors.joining(","))+"】"); + } + if(canDelNodes.size()==0){ + tips.setFailureMsg(msgs.stream().collect(Collectors.joining(";\n"))); + }else{ + tips.setOkMsg(msgs.stream().collect(Collectors.joining(";\n"))); + } + + + + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + /***/ + @ApiOperation( value = "根据主键列表批量删除xm_project_phase信息",notes="batchDelXmProjectPhase,仅需要上传主键字段") + @ApiResponses({ + @ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}") + }) + @HasQx(value = "xm_core_xmProductPhase_batchImportFromTemplate",name = "从模板批量创建产品计划",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/batchImportFromTemplate",method=RequestMethod.POST) + public Map batchImportFromTemplate(@RequestBody List xmProjectPhases) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功导入"+xmProjectPhases.size()+"条数据"); + try{ + if(xmProjectPhases==null || xmProjectPhases.size()==0){ + tips.setFailureMsg("计划不能为空"); + m.put("tips", tips); + return m; + } + XmProjectPhase xmProjectPhase=xmProjectPhases.get(0); + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhase.getProductId()); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhase.getProductId()); + User user = LoginUtils.getCurrentUserInfo(); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许批量导入计划"); + m.put("tips", tips); + return m; + } + BigDecimal phaseBudgetCost=BigDecimal.ZERO; + BigDecimal phaseBudgetInnerUserAt=BigDecimal.ZERO; + BigDecimal phaseBudgetOutUserAt=BigDecimal.ZERO; + BigDecimal phaseBudgetNouserAt=BigDecimal.ZERO; + String productId=null; + BigDecimal zero=BigDecimal.ZERO; + for (XmProjectPhase g : xmProjectPhases) { + productId=g.getProductId(); + g.setMngUserid(user.getUserid()); + g.setMngUsername(user.getUsername()); + phaseBudgetInnerUserAt=phaseBudgetInnerUserAt.add(NumberUtil.getBigDecimal(g.getPhaseBudgetInnerUserAt(),zero)); + phaseBudgetOutUserAt=phaseBudgetOutUserAt.add(NumberUtil.getBigDecimal(g.getPhaseBudgetOutUserAt(),zero)); + phaseBudgetNouserAt=phaseBudgetNouserAt.add(NumberUtil.getBigDecimal(g.getPhaseBudgetNouserAt(),zero)); + phaseBudgetCost=phaseBudgetCost.add(phaseBudgetInnerUserAt).add(phaseBudgetOutUserAt).add(phaseBudgetNouserAt); + g=xmProjectPhaseService.autoCalcWorkload(g); + + } + + Tips judgetTips=xmProjectPhaseService.judgetBudget(productId, phaseBudgetCost,phaseBudgetInnerUserAt,phaseBudgetOutUserAt,phaseBudgetNouserAt,null); + if(judgetTips.isOk()) { + for (XmProjectPhase projectPhase : xmProjectPhases) { + projectPhase.setMngUsername(user.getUsername()); + projectPhase.setMngUserid(user.getUserid()); + projectPhase.setCtime(new Date()); + projectPhase.setLtime(new Date()); + } + xmProjectPhaseService.parentIdPathsCalcBeforeSave(xmProjectPhases); + xmProjectPhaseService.doBatchInsert(xmProjectPhases); + + for (XmProjectPhase phase : xmProjectPhases) { + xmRecordService.addProductPhaseRecord(phase.getProductId(), phase.getId(), "产品-计划-新增计划", "新增计划"+phase.getPhaseName(),JSON.toJSONString(phase),null); + + } + }else { + tips=judgetTips; + } + + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + /***/ + @ApiOperation( value = "批量修改预算",notes="batchSaveBudget,仅需要上传主键字段") + @ApiResponses({ + @ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}") + }) + @HasQx(value = "xm_core_xmProductPhase_batchSaveBudget",name = "批量修改产品计划的预算",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/batchSaveBudget",method=RequestMethod.POST) + public Map batchSaveBudget(@RequestBody List xmProjectPhases) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功修改"+xmProjectPhases.size()+"条数据"); + try{ + if(xmProjectPhases==null || xmProjectPhases.size()==0){ + tips.setFailureMsg("计划不能为空"); + m.put("tips", tips); + return m; + } + XmProjectPhase xmProjectPhase=xmProjectPhases.get(0); + XmProduct xmProduct=this.xmProductService.getProductFromCache(xmProjectPhase.getProductId()); + List groupVoList=groupService.getProductGroupVoList(xmProjectPhase.getProductId()); + User user = LoginUtils.getCurrentUserInfo(); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许修改计划预算"); + m.put("tips", tips); + return m; + } + BigDecimal phaseBudgetCost=BigDecimal.ZERO; + BigDecimal phaseBudgetInnerUserAt=BigDecimal.ZERO; + BigDecimal phaseBudgetOutUserAt=BigDecimal.ZERO; + BigDecimal phaseBudgetNouserAt=BigDecimal.ZERO; + String productId=null; + BigDecimal zero=BigDecimal.ZERO; + List excludePhaseIds=new ArrayList<>(); + for (XmProjectPhase g : xmProjectPhases) { + productId=g.getProductId(); + phaseBudgetInnerUserAt=phaseBudgetInnerUserAt.add(NumberUtil.getBigDecimal(g.getPhaseBudgetInnerUserAt(),zero)); + phaseBudgetOutUserAt=phaseBudgetOutUserAt.add(NumberUtil.getBigDecimal(g.getPhaseBudgetOutUserAt(),zero)); + phaseBudgetNouserAt=phaseBudgetNouserAt.add(NumberUtil.getBigDecimal(g.getPhaseBudgetNouserAt(),zero)); + g=xmProjectPhaseService.autoCalcWorkload(g); + + excludePhaseIds.add(g.getId()); + } + phaseBudgetCost=phaseBudgetCost.add(phaseBudgetInnerUserAt).add(phaseBudgetOutUserAt).add(phaseBudgetNouserAt); + + Tips judgetTips=xmProjectPhaseService.judgetBudget(productId, phaseBudgetCost,phaseBudgetInnerUserAt,phaseBudgetOutUserAt,phaseBudgetNouserAt,excludePhaseIds); + if(judgetTips.isOk()) { + + for (XmProjectPhaseVo projectPhase : xmProjectPhases) { + if(!"1".equals(projectPhase.getNtype()) && !"add".equals(projectPhase.getOpType())&& !"addSub".equals(projectPhase.getOpType())){ + if(xmProjectPhases.stream().filter(i->projectPhase.getId().equals(i.getParentPhaseId())).findAny().isPresent()){ + return ResponseHelper.failed("p-ntype-no-1",projectPhase.getPhaseName()+"不是计划集,不允许下挂子计划"); + } + } + if("add".equals(projectPhase.getOpType())||"addSub".equals(projectPhase.getOpType())){ + int childrenCnt=Integer.valueOf(xmProjectPhases.stream().filter(i->projectPhase.getId().equals(i.getParentPhaseId())).count()+""); + if(childrenCnt>0){ + projectPhase.setChildrenCnt(childrenCnt); + projectPhase.setNtype("1"); + } + } + } + xmProjectPhaseService.parentIdPathsCalcBeforeSave(xmProjectPhases.stream().map(i->(XmProjectPhase)i).collect(Collectors.toList())); + xmProjectPhaseService.batchInsertOrUpdate(xmProjectPhases); + for (XmProjectPhase phase : xmProjectPhases) { + xmRecordService.addProductPhaseRecord(phase.getProductId(), phase.getId(), "产品-计划-修改计划预算", "修改计划"+phase.getPhaseName(),JSON.toJSONString(phase),null); + + } + }else { + tips=judgetTips; + } + + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + @ApiOperation( value = "计算bug、task、测试案例、等数据",notes="loadTasksToXmProjectPhase") + @ApiResponses({ + @ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}") + }) + @HasQx(value = "xm_core_xmProductPhase_loadTasksToXmProductPhase",name = "计算各个计划对应的bug、task、测试案例等数据",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/loadTasksToXmProductPhase",method=RequestMethod.POST) + public Map loadTasksToXmProductPhase(@RequestBody Map params) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功修改数据"); + try{ + String productId=(String) params.get("productId"); + List groupVoList=groupService.getProductGroupVoList(productId); + User user = LoginUtils.getCurrentUserInfo(); + + XmProduct xmProduct=this.xmProductService.getProductFromCache(productId); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许发起计划统计任务"); + m.put("tips", tips); + return m; + } + int i= xmProjectPhaseService.loadTasksToXmProjectPhase((String) params.get("productId")); + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } + + @ApiOperation( value = "计算bug、task、测试案例、等数据",notes="loadTasksToXmProjectPhase") + @ApiResponses({ + @ApiResponse(code = 200, message = "{tips:{isOk:true/false,msg:'成功/失败原因',tipscode:'失败时错误码'}") + }) + @HasQx(value = "xm_core_xmProductPhase_loadTasksToXmProductPhase",name = "计算各个计划对应的bug、task、测试案例等数据",categoryId = "admin-xm",categoryName = "管理端-产品管理系统") + @RequestMapping(value="/calcKeyPaths",method=RequestMethod.POST) + public Map calcKeyPaths(@RequestBody Map params) { + Map m = new HashMap<>(); + Tips tips=new Tips("成功修改数据"); + try{ + String productId=(String) params.get("productId"); + List groupVoList=groupService.getProductGroupVoList(productId); + User user = LoginUtils.getCurrentUserInfo(); + + XmProduct xmProduct=this.xmProductService.getProductFromCache(productId); + boolean meIsPm=groupService.checkUserIsProductAdm(xmProduct,user.getUserid()); + boolean meIsTeamHead=groupService.checkUserIsOtherUserTeamHead(groupVoList,user.getUserid(),user.getUserid()); + if( !meIsPm && !meIsTeamHead ){ + tips.setFailureMsg("您不是组长、也不是产品管理者,不允许发起关键路径计算任务"); + m.put("tips", tips); + return m; + } + xmProjectPhaseService.calcKeyPaths((String) params.get("productId")); + }catch (BizException e) { + tips=e.getTips(); + logger.error("",e); + }catch (Exception e) { + tips.setFailureMsg(e.getMessage()); + logger.error("",e); + } + m.put("tips", tips); + return m; + } +} diff --git a/xm-core/src/main/java/com/xm/core/service/XmProjectPhaseService.java b/xm-core/src/main/java/com/xm/core/service/XmProjectPhaseService.java index 63466f37..12dd0b7a 100644 --- a/xm-core/src/main/java/com/xm/core/service/XmProjectPhaseService.java +++ b/xm-core/src/main/java/com/xm/core/service/XmProjectPhaseService.java @@ -458,5 +458,69 @@ public class XmProjectPhaseService extends BaseService { public List selectListByIds(List ids) { return super.selectList("selectListByIds",ids); } + + /** + * 判断新增预算是否超出产品总预算 + * @param productId + * @param addPhaseBudgetCost + * @param addPhaseBudgetInnerUserAt + * @param addPhaseBudgetOutUserAt + * @param addPhaseBudgetNouserAt + * @param excludePhaseIds + * @return + */ + public Tips judgetProductBudget(String productId,BigDecimal addPhaseBudgetCost,BigDecimal addPhaseBudgetInnerUserAt,BigDecimal addPhaseBudgetOutUserAt,BigDecimal addPhaseBudgetNouserAt,List excludePhaseIds){ + Tips tips=new Tips("检查预算成功"); + Map g=this.selectTotalProductAndPhaseBudgetCost(productId,excludePhaseIds); + BigDecimal phaseBudgetCost=BigDecimal.ZERO; + BigDecimal zero=BigDecimal.ZERO; + + if(addPhaseBudgetCost==null) { + addPhaseBudgetCost=BigDecimal.ZERO; + } + if(addPhaseBudgetInnerUserAt==null) { + addPhaseBudgetInnerUserAt=BigDecimal.ZERO; + } + if(addPhaseBudgetOutUserAt==null) { + addPhaseBudgetOutUserAt=BigDecimal.ZERO; + } + if(addPhaseBudgetNouserAt==null) { + addPhaseBudgetNouserAt=BigDecimal.ZERO; + } + BigDecimal phaseBudgetInnerUserAt=NumberUtil.getBigDecimal(g.get("phaseBudgetInnerUserAt"),zero); + BigDecimal phaseBudgetOutUserAt=NumberUtil.getBigDecimal(g.get("phaseBudgetOutUserAt"),zero); + BigDecimal phaseBudgetNouserAt=NumberUtil.getBigDecimal(g.get("phaseBudgetNouserAt"),zero); + + /** + * + p.pbudget_workload, + p.pbudget_amount, + p.pmenu_budget_workload, + p.pmenu_budget_amount + */ + BigDecimal pbudgetWorkload=NumberUtil.getBigDecimal(g.get("pbudgetWorkload"),zero); + BigDecimal planTotalCost=NumberUtil.getBigDecimal(g.get("pbudgetAmount"),zero); + + + BigDecimal phaseBudgetCostAt=phaseBudgetCost.add(phaseBudgetInnerUserAt).add(phaseBudgetOutUserAt).add(phaseBudgetNouserAt); + phaseBudgetCostAt=phaseBudgetCostAt.add(addPhaseBudgetCost); + if(phaseBudgetCostAt.compareTo(planTotalCost)>0) { + tips.setFailureMsg("计划总体预算超出产品总预算"+phaseBudgetCostAt.subtract(planTotalCost)+"元"); + return tips; + }else { + return tips; + } + + } + + /** + * 查询产品及计划总预算,用于判断是否超出预算 + */ + public Map selectTotalProductAndPhaseBudgetCost(String productId,List excludePhaseIds){ + Map p=new HashMap<>(); + p.put("productId", productId); + p.put("excludePhaseIds", excludePhaseIds); + return this.selectOne("selectTotalProductAndPhaseBudgetCost", p); + } } diff --git a/xm-core/src/main/resources/mybatis/mapper/xm/core/dao/XmProjectPhaseMapper.xml b/xm-core/src/main/resources/mybatis/mapper/xm/core/dao/XmProjectPhaseMapper.xml index 5481f86d..ec4cb952 100644 --- a/xm-core/src/main/resources/mybatis/mapper/xm/core/dao/XmProjectPhaseMapper.xml +++ b/xm-core/src/main/resources/mybatis/mapper/xm/core/dao/XmProjectPhaseMapper.xml @@ -29,10 +29,10 @@ + {call load_tasks_to_xm_project_phase(#{projectId,mode=IN})}