package opsdev import ( "context" contractmodel "dashoo.cn/opms_parent/app/model/contract" "errors" "fmt" "strconv" "strings" "dashoo.cn/common_definition/comm_def" eventdao "dashoo.cn/opms_parent/app/dao/opsdev" opsdevmodel "dashoo.cn/opms_parent/app/model/opsdev" "dashoo.cn/opms_parent/app/service" "github.com/gogf/gf/database/gdb" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/gtime" ) // DeliveryProjectService 交付项目服务 type DeliveryProjectService struct { *service.ContextService Dao *eventdao.OpsDeliveryProjectDao } // NewDeliveryProjectService 初始化服务 func NewDeliveryProjectService(ctx context.Context) (*DeliveryProjectService, error) { svc := &DeliveryProjectService{} var err error if svc.ContextService, err = svc.Init(ctx); err != nil { return nil, err } svc.Dao = eventdao.NewOpsDeliveryProjectDao(svc.Tenant) return svc, nil } // GetList 获取列表(带权限校验) func (s *DeliveryProjectService) GetList(req *opsdevmodel.OpsDeliveryProjectSearchReq) (int64, []*opsdevmodel.OpsDeliveryProject, error) { m := s.Dao.Ctx(s.Ctx) // 权限控制 where := s.buildPermissionWhere() if where != "" { m = m.Where(where) } // 项目状态筛选(支持多选,逗号分隔) if req.ProjectStatus != "" { statusList := strings.Split(req.ProjectStatus, ",") if len(statusList) > 0 { m = m.Where("project_status", statusList) } } // 项目名称模糊查询 if req.ProjectName != "" { m = m.Where("project_name like ?", "%"+req.ProjectName+"%") } // 销售负责人模糊查询 if req.SalesUserName != "" { m = m.Where("sales_user_name like ?", "%"+req.SalesUserName+"%") } // 交付负责人模糊查询 if req.DeliveryUserName != "" { m = m.Where("delivery_user_name like ?", "%"+req.DeliveryUserName+"%") } // 关键词搜索(项目名称、合同编号) if req.KeyWords != "" { m = m.Where("project_name like ? OR contract_no like ?", "%"+req.KeyWords+"%", "%"+req.KeyWords+"%") } // 其他查询条件 if req.Status != "" { m = m.Where("project_status", req.Status) } if req.ProductLine != "" { productLineList := strings.Split(req.ProductLine, ",") m = m.Where("product_line", productLineList) } if req.DeliveryUserId > 0 { m = m.Where("delivery_user_id", req.DeliveryUserId) } if req.SalesUserId > 0 { m = m.Where("sales_user_id", req.SalesUserId) } // 获取总数 total, err := m.Count() if err != nil { return 0, nil, err } // 分页查询 if req.PageNum <= 0 { req.PageNum = 1 } if req.PageSize <= 0 { req.PageSize = 20 } // 排序 orderBy := "created_time desc" if req.SortField != "" && req.SortOrder != "" { orderBy = req.SortField + " " + req.SortOrder } var list []*opsdevmodel.OpsDeliveryProject err = m.Page(req.PageNum, req.PageSize).Order(orderBy).Scan(&list) if err != nil { return 0, nil, err } return int64(total), list, nil } // GetListAll 获取所有项目列表(不带权限校验,仅用于下拉选择等场景) func (s *DeliveryProjectService) GetListAll(req *opsdevmodel.OpsDeliveryProjectSearchReq) (int64, []*opsdevmodel.OpsDeliveryProject, error) { m := s.Dao.Ctx(s.Ctx) // 项目状态筛选(支持多选,逗号分隔) if req.ProjectStatus != "" { statusList := strings.Split(req.ProjectStatus, ",") if len(statusList) > 0 { m = m.Where("project_status", statusList) } } // 项目名称模糊查询 if req.ProjectName != "" { m = m.Where("project_name like ?", "%"+req.ProjectName+"%") } // 销售负责人模糊查询 if req.SalesUserName != "" { m = m.Where("sales_user_name like ?", "%"+req.SalesUserName+"%") } // 交付负责人模糊查询 if req.DeliveryUserName != "" { m = m.Where("delivery_user_name like ?", "%"+req.DeliveryUserName+"%") } // 关键词搜索(项目名称、合同编号) if req.KeyWords != "" { m = m.Where("project_name like ? OR contract_no like ?", "%"+req.KeyWords+"%", "%"+req.KeyWords+"%") } // 其他查询条件 if req.Status != "" { m = m.Where("project_status", req.Status) } if req.ProductLine != "" { productLineList := strings.Split(req.ProductLine, ",") m = m.Where("product_line", productLineList) } if req.DeliveryUserId > 0 { m = m.Where("delivery_user_id", req.DeliveryUserId) } if req.SalesUserId > 0 { m = m.Where("sales_user_id", req.SalesUserId) } // 获取总数 total, err := m.Count() if err != nil { return 0, nil, err } // 分页查询 if req.PageNum <= 0 { req.PageNum = 1 } if req.PageSize <= 0 { req.PageSize = 20 } // 排序 orderBy := "created_time desc" if req.SortField != "" && req.SortOrder != "" { orderBy = req.SortField + " " + req.SortOrder } var list []*opsdevmodel.OpsDeliveryProject err = m.Page(req.PageNum, req.PageSize).Order(orderBy).Scan(&list) if err != nil { return 0, nil, err } return int64(total), list, nil } // buildPermissionWhere 构建权限条件 func (s *DeliveryProjectService) buildPermissionWhere() string { // 全部可见角色 allVisibleRoles := []string{ "GeneralManager", // 总经理 "SalesDirector", // 销售总监 "ResearchAndDevelopmentDirector", // 研发总监 "ResearchAndDevelopmentSupervisor", // 研发主管 "PersonnelDirector", // 人事总监 "SysAdmin", // 系统管理员 "GeneralManagerAssistant", // 总经理助理 } for _, role := range allVisibleRoles { if service.StringsContains(s.CxtUser.Roles, role) { return "" // 全部可见,无额外条件 } } // 构建权限条件 where := "(1=0" // 大区经理:查看授权区域内所有项目 if service.StringsContains(s.CxtUser.Roles, "RegionalManager") { where += fmt.Sprintf(" OR sales_region_id IN (SELECT sale_region_id FROM base_region_auth WHERE user_id = %d)", s.CxtUser.Id) } // 销售工程师:查看销售负责人是自己的项目 if service.StringsContains(s.CxtUser.Roles, "SalesEngineer") { where += fmt.Sprintf(" OR sales_user_id = %d", s.CxtUser.Id) } // 项目经理、项目交付经理:查看项目负责人是自己的项目 if service.StringsContains(s.CxtUser.Roles, "ProjectManager") || service.StringsContains(s.CxtUser.Roles, "ProjectDeliveryManager") { where += fmt.Sprintf(" OR delivery_user_id = %d", s.CxtUser.Id) } where += ")" return where } // GetEntityById 根据ID获取详情 func (s *DeliveryProjectService) GetEntityById(req *comm_def.IdReq) (*opsdevmodel.OpsDeliveryProject, error) { if req.Id <= 0 { return nil, errors.New("ID不能为空") } var entity *opsdevmodel.OpsDeliveryProject err := s.Dao.Where("id", req.Id).Scan(&entity) if err != nil { return nil, err } if entity == nil { return nil, errors.New("记录不存在") } return entity, nil } // Create 创建 func (s *DeliveryProjectService) Create(req *opsdevmodel.OpsDeliveryProjectReq) error { // 设置默认值 if req.ProjectStatus == "" { req.ProjectStatus = "10" // 默认待交付 } data := g.Map{ "project_name": req.ProjectName, "project_status": req.ProjectStatus, "contract_id": req.ContractId, "contract_no": req.ContractNo, "cust_id": req.CustId, "cust_name": req.CustName, "product_line": req.ProductLine, "delivery_user_id": req.DeliveryUserId, "delivery_user_name": req.DeliveryUserName, "sales_user_id": req.SalesUserId, "sales_user_name": req.SalesUserName, "sales_region_id": req.SalesRegionId, "delivery_node": req.DeliveryNode, "remark": req.Remark, "created_time": gtime.Now(), "updated_time": gtime.Now(), } // 处理计划交付时间 if req.PlanDeliveryTime != "" { data["plan_delivery_time"] = req.PlanDeliveryTime } // 处理计划验收时间 if req.PlanAcceptTime != "" { data["plan_accept_time"] = req.PlanAcceptTime } _, err := s.Dao.Data(data).Insert() return err } // CreateProjectByContract 合同审批通过后,按合同信息自动创建交付项目 func CreateProjectByContract(tx *gdb.TX, tenant string, contract *contractmodel.CtrContract) error { if contract == nil { return errors.New("合同信息不能为空") } projectDao := eventdao.NewOpsDeliveryProjectDao(tenant) // 审批回调可能重复触发,按合同ID幂等创建 count, err := projectDao.TX(tx).Where("contract_id = ? AND deleted_time IS NULL", contract.Id).Count() if err != nil { return err } if count > 0 { return nil } data := g.Map{ "project_name": contract.ContractName, "project_status": "10", "contract_id": contract.Id, "contract_no": contract.ContractCode, "cust_id": strconv.Itoa(contract.CustId), "cust_name": contract.CustName, "product_line": contract.ProductLine, "sales_user_id": contract.InchargeId, "sales_user_name": contract.InchargeName, "sales_region_id": contract.CustCityId, "delivery_node": "05", "created_time": gtime.Now(), "updated_time": gtime.Now(), } _, err = projectDao.TX(tx).Data(data).Insert() return err } // UpdateById 更新 func (s *DeliveryProjectService) UpdateById(req *opsdevmodel.OpsDeliveryProjectUpdateReq) error { if req.Id <= 0 { return errors.New("ID不能为空") } data := g.Map{ "project_name": req.ProjectName, "project_status": req.ProjectStatus, "contract_id": req.ContractId, "contract_no": req.ContractNo, "cust_id": req.CustId, "cust_name": req.CustName, "product_line": req.ProductLine, "delivery_user_id": req.DeliveryUserId, "delivery_user_name": req.DeliveryUserName, "sales_user_id": req.SalesUserId, "sales_user_name": req.SalesUserName, "sales_region_id": req.SalesRegionId, "delivery_node": req.DeliveryNode, "remark": req.Remark, "updated_time": gtime.Now(), } // 处理计划交付时间(允许清空) if req.PlanDeliveryTime != "" { data["plan_delivery_time"] = req.PlanDeliveryTime } else { data["plan_delivery_time"] = nil } // 处理计划验收时间(允许清空) if req.PlanAcceptTime != "" { data["plan_accept_time"] = req.PlanAcceptTime } else { data["plan_accept_time"] = nil } _, err := s.Dao.Where("id", req.Id).Data(data).Update() return err } // DeleteByIds 批量删除 func (s *DeliveryProjectService) DeleteByIds(req *comm_def.IdsReq) error { if len(req.Ids) == 0 { return errors.New("ID不能为空") } _, err := s.Dao.WhereIn("id", req.Ids).Delete() return err } // AssignDeliveryUser 指派/改派交付负责人 func (s *DeliveryProjectService) AssignDeliveryUser(req *opsdevmodel.AssignDeliveryUserReq) error { if req.ProjectId <= 0 { return errors.New("项目ID不能为空") } // 查询项目是否存在 project, err := s.Dao.Where("id", req.ProjectId).FindOne() if err != nil { return err } if project == nil { return errors.New("项目不存在") } // 构建更新数据 data := g.Map{ "delivery_user_id": req.DeliveryUserId, "delivery_user_name": req.DeliveryUserName, "updated_time": gtime.Now(), } // 首次指派时更新状态和节点 if !req.IsReassign { if req.ProjectStatus != "" { data["project_status"] = req.ProjectStatus } if req.DeliveryNode != "" { data["delivery_node"] = req.DeliveryNode } if req.AssignedTime != "" { data["assigned_time"] = req.AssignedTime } if req.PlanDeliveryTime != "" { data["plan_delivery_time"] = req.PlanDeliveryTime } if req.PlanAcceptTime != "" { data["plan_accept_time"] = req.PlanAcceptTime } } // 追加备注 if req.Remark != "" { oldRemark := project.Remark if oldRemark != "" { data["remark"] = oldRemark + "\n" + req.Remark } else { data["remark"] = req.Remark } } _, err = s.Dao.Where("id", req.ProjectId).Data(data).Update() return err }