فهرست منبع

feature: 工单优化

liuyaqi 2 سال پیش
والد
کامیت
cb531d08fb

+ 19 - 1
opms_parent/app/dao/work/internal/work_order.go

@@ -35,16 +35,22 @@ type workOrderColumns struct {
 	NboId          string // 关联项目
 	NboCode        string // 项目编码
 	NboName        string // 项目名称
+	ProductLine    string // 产品线
 	CustId         string // 关联客户
 	CustName       string // 客户名称
 	OrderTypeId    string // 工单类型
 	OrderTypeName  string // 工单类型名称
-	OrderStatus    string // 工单状态(10发起20审批中30审批通过40审批拒绝50关闭)
+	OrderStatus    string // 工单状态(10发起20审批中30审批通过40审批拒绝50关闭60已完成)
+	EndTime        string // 结束时间
 	FormData       string // 表单数据
 	AssignUserId   string // 分派人员ID
 	AssignUserName string // 分派人员姓名
 	Feedback       string // 反馈信息
 	File           string // 相关文件
+	FinishRemark   string // 完成信息
+	FinishTime     string // 完成信息
+	FinishBy       string // 完成操作人
+	FinishByName   string // 完成操作人
 	Remark         string // 备注
 	CreatedBy      string // 创建者
 	CreatedName    string // 创建人
@@ -67,16 +73,22 @@ var (
 			NboId:          "nbo_id",
 			NboCode:        "nbo_code",
 			NboName:        "nbo_name",
+			ProductLine:    "product_line",
 			CustId:         "cust_id",
 			CustName:       "cust_name",
 			OrderTypeId:    "order_type_id",
 			OrderTypeName:  "order_type_name",
 			OrderStatus:    "order_status",
+			EndTime:        "end_time",
 			FormData:       "form_data",
 			AssignUserId:   "assign_user_id",
 			AssignUserName: "assign_user_name",
 			Feedback:       "feedback",
 			File:           "file",
+			FinishRemark:   "finish_remark",
+			FinishTime:     "finish_time",
+			FinishBy:       "finish_by",
+			FinishByName:   "finish_by_name",
 			Remark:         "remark",
 			CreatedBy:      "created_by",
 			CreatedName:    "created_name",
@@ -101,16 +113,22 @@ func NewWorkOrderDao(tenant string) WorkOrderDao {
 			NboId:          "nbo_id",
 			NboCode:        "nbo_code",
 			NboName:        "nbo_name",
+			ProductLine:    "product_line",
 			CustId:         "cust_id",
 			CustName:       "cust_name",
 			OrderTypeId:    "order_type_id",
 			OrderTypeName:  "order_type_name",
 			OrderStatus:    "order_status",
+			EndTime:        "end_time",
 			FormData:       "form_data",
 			AssignUserId:   "assign_user_id",
 			AssignUserName: "assign_user_name",
 			Feedback:       "feedback",
 			File:           "file",
+			FinishRemark:   "finish_remark",
+			FinishTime:     "finish_time",
+			FinishBy:       "finish_by",
+			FinishByName:   "finish_by_name",
 			Remark:         "remark",
 			CreatedBy:      "created_by",
 			CreatedName:    "created_name",

+ 1 - 1
opms_parent/app/handler/base/product.go

@@ -14,7 +14,7 @@ import (
 
 type ProductHandler struct{}
 
-// GetList 获取列表
+// Swagger:Product 产品 产品列表
 func (b *ProductHandler) GetList(ctx context.Context, req *model.ProductSearchReq, rsp *comm_def.CommonMsg) error {
 	s, err := server.NewProductService(ctx)
 	if err != nil {

+ 20 - 0
opms_parent/app/handler/dingtalk/ding_event.go

@@ -9,6 +9,7 @@ import (
 	"dashoo.cn/micro/app/service/dingtalk_log"
 	platServer "dashoo.cn/micro/app/service/plat"
 	projService "dashoo.cn/micro/app/service/proj"
+	workService "dashoo.cn/micro/app/service/work"
 	workflowServer "dashoo.cn/micro/app/service/workflow"
 	"dashoo.cn/opms_libary/plugin/dingtalk"
 	dingContext "dashoo.cn/opms_libary/plugin/dingtalk/context"
@@ -240,6 +241,25 @@ func (h *DingHandler) handleBpmsInstanceChange(msg *message.MixMessage, ctx *din
 			return err.Error()
 		}
 		return "success"
+	case model.WorkOrderCreate:
+		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
+			srv, err := workService.NewOrderService(ctx.SubsMessage.Ctx)
+			if err != nil {
+				glog.Error(err)
+				return err.Error()
+			}
+			err = srv.WorkOrderNotify(instance, msg)
+			if err != nil {
+				glog.Error(err)
+				return err.Error()
+			}
+		}
+		err = s.Update(instance, msg)
+		if err != nil {
+			glog.Error(err)
+			return err.Error()
+		}
+		return "success"
 	case model.ProjectCreate:
 		if msg.ProcessType == "finish" || msg.ProcessType == "terminate" {
 			srv, err := projService.NewBusinessService(ctx.SubsMessage.Ctx)

+ 63 - 1
opms_parent/app/handler/work/work_order.go

@@ -76,7 +76,7 @@ func (w *WorkOrderHandler) UpdateById(ctx context.Context, req *model.UpdateWork
 	return nil
 }
 
-// 创建工单
+// Swagger:WorkOrder 工单 创建工单
 func (w *WorkOrderHandler) CreateWorkOrder(ctx context.Context, req *model.WorkOrderReq, rsp *comm_def.CommonMsg) error {
 	orderService, err := workSrv.NewOrderService(ctx)
 	if err != nil {
@@ -172,3 +172,65 @@ func (w *WorkOrderHandler) GetWorkOrderFeedbackByDay(ctx context.Context, req *m
 	rsp.Data = g.Map{"list": list}
 	return nil
 }
+
+// Swagger:WorkOrder 工单 完成工单
+func (w *WorkOrderHandler) Finish(ctx context.Context, req *model.WorkOrderFinishReq, rsp *comm_def.CommonMsg) error {
+	orderService, err := workSrv.NewOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	err = orderService.Finish(ctx, req)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// Swagger:WorkOrder 工单 关闭工单
+func (w *WorkOrderHandler) Close(ctx context.Context, req *model.WorkOrderCloseReq, rsp *comm_def.CommonMsg) error {
+	orderService, err := workSrv.NewOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	err = orderService.Close(ctx, req)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// Swagger:WorkOrder 工单 添加动态
+func (w *WorkOrderHandler) AddDynamics(ctx context.Context, req *model.WorkOrderAddDynamics, rsp *comm_def.CommonMsg) error {
+	orderService, err := workSrv.NewOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	if err := gvalid.CheckStruct(ctx, req, nil); err != nil {
+		return err
+	}
+	err = orderService.AddDynamics(ctx, req)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// Swagger:WorkOrder 工单,测试tag 工单动态
+func (w *WorkOrderHandler) DynamicsList(ctx context.Context, req *model.WorkOrderDynamicsListReq, rsp *comm_def.CommonMsg) error {
+	orderService, err := workSrv.NewOrderService(ctx)
+	if err != nil {
+		return err
+	}
+	total, list, err := orderService.DynamicsList(ctx, req)
+	if err != nil {
+		return err
+	}
+	rsp.Data = g.Map{"list": list, "total": total}
+	return nil
+}

+ 5 - 3
opms_parent/app/model/base/base_product.go

@@ -16,9 +16,11 @@ type BaseProduct internal.BaseProduct
 // Fill with you ideas below.
 
 type ProductSearchReq struct {
-	ProdCode  string `json:"prodCode"`
-	ProdName  string `json:"prodName"`
-	ProdClass string `json:"ProdClass"`
+	ProdCode     string `json:"prodCode"`
+	ProdName     string `json:"prodName"`
+	ProdClass    string `json:"ProdClass"`
+	OnlyHardware bool   `json:"onlyHardware"` // 只查询硬件产品
+	OnlySoftware bool   `json:"onlySoftware"` // 只查询软件产品
 	request.PageReq
 }
 

+ 7 - 1
opms_parent/app/model/work/internal/work_order.go

@@ -15,16 +15,22 @@ type WorkOrder struct {
 	NboId          int         `orm:"nbo_id"           json:"nboId"`          // 关联项目
 	NboCode        string      `orm:"nbo_code"         json:"nboCode"`        // 项目编码
 	NboName        string      `orm:"nbo_name"         json:"nboName"`        // 项目名称
+	ProductLine    string      `orm:"product_line"     json:"productLine"`    // 产品线
 	CustId         int         `orm:"cust_id"          json:"custId"`         // 关联客户
 	CustName       string      `orm:"cust_name"        json:"custName"`       // 客户名称
 	OrderTypeId    int         `orm:"order_type_id"    json:"orderTypeId"`    // 工单类型
 	OrderTypeName  string      `orm:"order_type_name"  json:"orderTypeName"`  // 工单类型名称
-	OrderStatus    string      `orm:"order_status"     json:"orderStatus"`    // 工单状态(10发起20审批中30审批通过40审批拒绝50关闭)
+	OrderStatus    string      `orm:"order_status"     json:"orderStatus"`    // 工单状态(10发起20审批中30审批通过40审批拒绝50关闭60已完成)
+	EndTime        *gtime.Time `orm:"end_time"         json:"endTime"`        // 结束时间
 	FormData       string      `orm:"form_data"        json:"formData"`       // 表单数据
 	AssignUserId   int         `orm:"assign_user_id"   json:"assignUserId"`   // 分派人员ID
 	AssignUserName string      `orm:"assign_user_name" json:"assignUserName"` // 分派人员姓名
 	Feedback       string      `orm:"feedback"         json:"feedback"`       // 反馈信息
 	File           string      `orm:"file"             json:"file"`           // 相关文件
+	FinishRemark   string      `orm:"finish_remark"    json:"finishRemark"`   // 完成信息
+	FinishTime     *gtime.Time `orm:"finish_time"      json:"finishTime"`     // 完成信息
+	FinishBy       int         `orm:"finish_by"        json:"finishBy"`       // 完成操作人
+	FinishByName   string      `orm:"finish_by_name"   json:"finishByName"`   // 完成操作人
 	Remark         string      `orm:"remark"           json:"remark"`         // 备注
 	CreatedBy      int         `orm:"created_by"       json:"createdBy"`      // 创建者
 	CreatedName    string      `orm:"created_name"     json:"createdName"`    // 创建人

+ 25 - 0
opms_parent/app/model/work/work_order.go

@@ -7,6 +7,7 @@ package work
 import (
 	"dashoo.cn/micro/app/model/work/internal"
 	"dashoo.cn/opms_libary/request"
+	"github.com/gogf/gf/os/gtime"
 )
 
 // WorkOrder is the golang structure for table work_order.
@@ -40,6 +41,7 @@ type WorkOrderReq struct {
 	FormData       []DingTalkFormItemData `json:"formData"         v:"required#表单数据不能为空"`   // 表单数据
 	AssignUserId   int                    `json:"assignUserId"     v:"min:1#分派人员不能为空"`      // 分派人员ID
 	AssignUserName string                 `json:"assignUserName"   v:"required#分派人员姓名不能为空"` // 分派人员姓名
+	EndTime        *gtime.Time            `json:"endTime"`                                  // 结束时间
 	File           string                 `json:"file"`                                     // 相关文件
 	Remark         string                 `json:"remark"`                                   // 备注
 }
@@ -71,6 +73,20 @@ type WorkOrderFeedbackSearchReq struct {
 	request.PageReq
 }
 
+type WorkOrderFinishReq struct {
+	OrderId      int    `json:"orderId"     v:"min:1#工单不能为空"` //
+	FinishRemark string `json:"finishRemark"`                 // 完成信息
+}
+
+type WorkOrderCloseReq struct {
+	OrderId int `json:"orderId"     v:"min:1#工单不能为空"` // 主健
+}
+
+type WorkOrderAddDynamics struct {
+	OrderId int    `json:"orderId"     v:"min:1#工单不能为空"`  // 主健
+	Content string `json:"content" v:"required#动态信息不能为空"` // 动态信息
+}
+
 // 反馈记录详情展示,按日期返回前端结果
 type WorkOrderFeedbackRes struct {
 	FeeDate               string               `json:"feeDate"` // 日期
@@ -87,3 +103,12 @@ type WorkOrderExport struct {
 type WorkByteExport struct {
 	Content []byte `json:"content"` // 导出数据流
 }
+
+type WorkOrderDynamicsListReq struct {
+	request.PageReq
+	SearchText  string `json:"searchText"`  // 操作人,操作内容
+	OrderId     int    `json:"orderId"`     // 工单ID
+	OpnPeopleId int    `json:"opnPeopleId"` // 操作人ID
+	OpnPeople   string `json:"opnPeople"`   // 操作人
+	OpnType     string `json:"opnType"`     // 操作类型
+}

+ 1 - 0
opms_parent/app/model/workflow/plat_workflow.go

@@ -27,6 +27,7 @@ const (
 	DistToProxy      = "52" // 经销商转代理商
 	DistProxyRenew   = "53" // 代理商续签
 	DistToDist       = "54" // 代理商转经销商
+	WorkOrderCreate  = "61" // 工单创建
 )
 
 // PlatWorkflow is the golang structure for table plat_workflow.

+ 10 - 1
opms_parent/app/service/base/base_product.go

@@ -40,6 +40,12 @@ func (s *productService) GetList(req *model.ProductSearchReq) (total int, produc
 	if req.ProdClass != "" {
 		Dao = Dao.Where("prod_class = ?", req.ProdClass)
 	}
+	if req.OnlyHardware {
+		Dao = Dao.Where("prod_class in (40,60)", req.ProdClass)
+	}
+	if req.OnlySoftware {
+		Dao = Dao.Where("prod_class in (10,20,30)", req.ProdClass)
+	}
 
 	total, err = Dao.Count()
 	if err != nil {
@@ -48,7 +54,10 @@ func (s *productService) GetList(req *model.ProductSearchReq) (total int, produc
 		return
 	}
 
-	err = Dao.Page(req.GetPage()).Order("id asc").Scan(&productList)
+	if req.PageNum != 0 && req.PageSize != 0 {
+		Dao = Dao.Page(req.GetPage())
+	}
+	err = Dao.Order("id asc").Scan(&productList)
 	return
 }
 

+ 180 - 7
opms_parent/app/service/work/work_order.go

@@ -3,6 +3,13 @@ package work
 import (
 	"bytes"
 	"context"
+	"database/sql"
+	"encoding/json"
+	"fmt"
+	"strconv"
+	"strings"
+
+	proj "dashoo.cn/micro/app/dao/proj"
 	contractModel "dashoo.cn/micro/app/model/contract"
 	workflowModel "dashoo.cn/micro/app/model/workflow"
 	workflowService "dashoo.cn/micro/app/service/workflow"
@@ -10,14 +17,10 @@ import (
 	"dashoo.cn/opms_libary/plugin/dingtalk"
 	"dashoo.cn/opms_libary/plugin/dingtalk/message"
 	"dashoo.cn/opms_libary/plugin/dingtalk/workflow"
-	"database/sql"
-	"fmt"
 	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/os/gtime"
 	"github.com/gogf/gf/util/gconv"
-	"strconv"
-	"strings"
 
 	"dashoo.cn/common_definition/comm_def"
 	"dashoo.cn/opms_libary/myerrors"
@@ -30,8 +33,10 @@ import (
 
 type OrderService struct {
 	*service.ContextService
-	Dao         *work.WorkOrderDao
-	FeedbackDao *work.WorkOrderFeedbackDao
+	Dao             *work.WorkOrderDao
+	FeedbackDao     *work.WorkOrderFeedbackDao
+	ProjBusinessDao *proj.ProjBusinessDao
+	DynamicsDao     *work.WorkOrderDynamicsDao
 }
 
 // 工单状态
@@ -45,6 +50,8 @@ func NewOrderService(ctx context.Context) (svc *OrderService, err error) {
 	}
 	svc.Dao = work.NewWorkOrderDao(svc.Tenant)
 	svc.FeedbackDao = work.NewWorkOrderFeedbackDao(svc.Tenant)
+	svc.ProjBusinessDao = proj.NewProjBusinessDao(svc.Tenant)
+	svc.DynamicsDao = work.NewWorkOrderDynamicsDao(svc.Tenant)
 	return svc, nil
 }
 
@@ -165,6 +172,16 @@ func (s *OrderService) CreateWorkOrder(req *model.WorkOrderReq, args *multipart.
 	if err = gconv.Struct(req, data); err != nil {
 		return
 	}
+
+	p, err := s.ProjBusinessDao.Where("id = ?", req.NboId).One()
+	if err != nil {
+		return err
+	}
+	if p == nil {
+		return myerrors.TipsError("项目不存在")
+	}
+	data.ProductLine = p.ProductLine
+
 	data.OrderStatus = "20"
 	service.SetCreatedInfo(data, s.GetCxtUserId(), s.GetCxtUserName())
 
@@ -188,6 +205,16 @@ func (s *OrderService) CreateWorkOrder(req *model.WorkOrderReq, args *multipart.
 	}
 
 	err = s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+		if g.Config().GetBool("dingtalk.disable-for-dev") {
+			g.Log().Warning("disable-for-dev true 未创建钉钉审批!!!!!!!!!!!!")
+			data.OrderStatus = "30"
+			lastId, err := s.Dao.TX(tx).Data(data).InsertAndGetId()
+			if err != nil {
+				return err
+			}
+			return s.AddDynamicsByCurrentUser(tx, int(lastId), "创建工单", map[string]interface{}{})
+		}
+
 		// 更新项目调级
 		lastId, err := s.Dao.TX(tx).Data(data).InsertAndGetId()
 		if err != nil {
@@ -198,7 +225,7 @@ func (s *OrderService) CreateWorkOrder(req *model.WorkOrderReq, args *multipart.
 		workflowSrv, _ := workflowService.NewFlowService(s.Ctx)
 		bizCode := gconv.String(lastId) + ":" + req.OrderTypeCode
 
-		workflowId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.ProjectToReserve, "", &workflow.StartProcessInstanceRequest{
+		workflowId, err := workflowSrv.StartProcessInstance(bizCode, workflowModel.WorkOrderCreate, "", &workflow.StartProcessInstanceRequest{
 			ProcessCode:         &req.OrderTypeCode,
 			FormComponentValues: formComponentValues,
 		})
@@ -207,6 +234,7 @@ func (s *OrderService) CreateWorkOrder(req *model.WorkOrderReq, args *multipart.
 			g.Log().Error(err)
 			return err
 		}
+		err = s.AddDynamicsByCurrentUser(tx, int(lastId), "创建工单", map[string]interface{}{})
 		return err
 	})
 	return
@@ -334,3 +362,148 @@ func (s *OrderService) GetWorkOrderFeedbackByDay(req *model.WorkOrderFeedbackSea
 	}
 	return
 }
+
+func (s *OrderService) Finish(ctx context.Context, req *model.WorkOrderFinishReq) error {
+	ent, err := s.Dao.Where("id = ?", req.OrderId).One()
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		return myerrors.TipsError("工单不存在")
+	}
+	if ent.OrderStatus != "30" {
+		return myerrors.TipsError("当前工单不可完成")
+	}
+
+	return s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		_, err = tx.Update("work_order", map[string]interface{}{
+			"order_status":   "60",
+			"finish_remark":  req.FinishRemark,
+			"finish_time":    gtime.Now(),
+			"finish_by":      s.CxtUser.Id,
+			"finish_by_name": s.CxtUser.NickName,
+			"updated_by":     s.CxtUser.Id,
+			"updated_name":   s.CxtUser.NickName,
+			"updated_time":   gtime.Now(),
+		}, "id = ?", req.OrderId)
+		if err != nil {
+			return err
+		}
+		err = s.AddDynamicsByCurrentUser(tx, int(req.OrderId), "完成工单", map[string]interface{}{})
+		return err
+	})
+}
+
+func (s *OrderService) Close(ctx context.Context, req *model.WorkOrderCloseReq) error {
+	ent, err := s.Dao.Where("id = ?", req.OrderId).One()
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		return myerrors.TipsError("工单不存在")
+	}
+	if !(ent.OrderStatus == "30" || ent.OrderStatus == "10") {
+		return myerrors.TipsError("当前工单不可关闭")
+	}
+	return s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		_, err = tx.Update("work_order", map[string]interface{}{
+			"order_status": "50",
+			"updated_by":   s.CxtUser.Id,
+			"updated_name": s.CxtUser.NickName,
+			"updated_time": gtime.Now(),
+		}, "id = ?", req.OrderId)
+		if err != nil {
+			return err
+		}
+		err = s.AddDynamicsByCurrentUser(tx, int(req.OrderId), "关闭工单", map[string]interface{}{})
+		return err
+	})
+}
+
+func (s *OrderService) AddDynamics(ctx context.Context, req *model.WorkOrderAddDynamics) error {
+	return s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		return s.AddDynamicsByCurrentUser(tx, req.OrderId, "添加动态", map[string]interface{}{
+			"content": req.Content,
+		})
+	})
+}
+
+func (s OrderService) AddDynamicsByCurrentUser(tx *gdb.TX, orderId int, opnType string, content map[string]interface{}) error {
+	contentByte, err := json.Marshal(content)
+	if err != nil {
+		return err
+	}
+	_, err = tx.InsertAndGetId("work_order_dynamics", model.WorkOrderDynamics{
+		OrderId:     orderId,
+		OpnPeopleId: s.CxtUser.Id,
+		OpnPeople:   s.CxtUser.NickName,
+		OpnDate:     gtime.Now(),
+		OpnType:     opnType,
+		OpnContent:  string(contentByte),
+		Remark:      "",
+		CreatedBy:   s.CxtUser.Id,
+		CreatedName: s.CxtUser.NickName,
+		CreatedTime: gtime.Now(),
+		UpdatedBy:   s.CxtUser.Id,
+		UpdatedName: s.CxtUser.NickName,
+		UpdatedTime: gtime.Now(),
+	})
+	return err
+}
+
+func (s *OrderService) DynamicsList(ctx context.Context, req *model.WorkOrderDynamicsListReq) (int, interface{}, error) {
+	dao := &s.DynamicsDao.WorkOrderDynamicsDao
+	if req.SearchText != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.SearchText)
+		dao = dao.Where("(opn_people LIKE ? || opn_content LIKE ?)", likestr, likestr)
+	}
+	if req.OrderId != 0 {
+		dao = dao.Where("order_id = ?", req.OrderId)
+	}
+	if req.OpnPeopleId != 0 {
+		dao = dao.Where("opn_people_id = ?", req.OpnPeopleId)
+	}
+	if req.OpnPeople != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.OpnPeople)
+		dao = dao.Where("opn_people like ?", likestr)
+	}
+	if req.OpnType != "" {
+		dao = dao.Where("opn_type = ?", req.OpnType)
+	}
+	// if req.OpnContent != "" {
+	// 	likestr := fmt.Sprintf("%%%s%%", req.OpnContent)
+	// 	dao = dao.Where("opn_content like ?", likestr)
+	// }
+	if req.BeginTime != "" {
+		dao = dao.Where("created_time > ?", req.BeginTime)
+	}
+	if req.EndTime != "" {
+		dao = dao.Where("created_time < ?", req.EndTime)
+	}
+
+	total, err := dao.Count()
+	if err != nil {
+		return 0, nil, err
+	}
+	if req.PageNum != 0 {
+		dao = dao.Page(req.GetPage())
+	}
+	orderby := "created_time desc"
+	if req.OrderBy != "" {
+		orderby = req.OrderBy
+	}
+	dao = dao.Order(orderby)
+
+	ents := []*model.WorkOrderDynamics{}
+	err = dao.Structs(&ents)
+	if err != nil && err != sql.ErrNoRows {
+		return 0, nil, err
+	}
+
+	ret := map[string][]*model.WorkOrderDynamics{}
+	for _, ent := range ents {
+		date := ent.OpnDate.Format("Y-m-d")
+		ret[date] = append(ret[date], ent)
+	}
+	return total, ret, err
+}

+ 11 - 0
opms_parent/schema/tmp.sql

@@ -132,3 +132,14 @@ alter table base_distributor add `appro_status` varchar(4) COMMENT '审核状态
 alter table plat_followup add `further_plan` text COMMENT '下一步跟进计划和目标' after follow_content;
 alter table plat_followup add `effect` text COMMENT '达成效果' after further_plan;
 alter table plat_followup add `issue` text COMMENT '问题或困难' after effect;
+
+-- 2023-06-20
+alter table work_order add `product_line` varchar(4) NOT NULL COMMENT '产品线' after nbo_name;
+alter table work_order add `end_time` datetime DEFAULT NULL COMMENT '结束时间' after order_status;
+alter table work_order add `finish_remark` text DEFAULT NULL COMMENT '完成信息' after `file`;
+alter table work_order add `finish_time` datetime DEFAULT NULL COMMENT '完成信息' after `finish_remark`;
+alter table work_order add `finish_by` int(11) DEFAULT NULL COMMENT '完成操作人' after `finish_time`;
+alter table work_order add `finish_by_name`  varchar(90) DEFAULT NULL COMMENT '完成操作人' after `finish_by`;
+alter table work_order modify `order_status` varchar(4) NOT NULL COMMENT '工单状态(10发起20审批中30审批通过40审批拒绝50关闭60已完成)';
+-- 添加工单状态字典 60已完成
+

+ 36 - 0
opms_parent/schema/work_order.sql

@@ -0,0 +1,36 @@
+work_order CREATE TABLE `work_order` (
+    `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+    `name` varchar(90) NOT NULL COMMENT '工单名称',
+    `nbo_id` int(11) DEFAULT NULL COMMENT '关联项目',
+    `nbo_code` varchar(32) DEFAULT NULL COMMENT '项目编码',
+    `nbo_name` varchar(90) DEFAULT NULL COMMENT '项目名称',
+    `cust_id` int(11) DEFAULT NULL COMMENT '关联客户',
+    `cust_name` varchar(90) DEFAULT NULL COMMENT '客户名称',
+    `order_type_id` int(11) NOT NULL COMMENT '工单类型',
+    `order_type_name` varchar(90) NOT NULL COMMENT '工单类型名称',
+    `order_status` varchar(4) NOT NULL COMMENT '工单状态(10发起20审批中30审批通过40审批拒绝50关闭)',
+    `form_data` text NOT NULL COMMENT '表单数据',
+    `assign_user_id` int(11) DEFAULT NULL COMMENT '分派人员ID',
+    `assign_user_name` varchar(90) DEFAULT NULL COMMENT '分派人员姓名',
+    `feedback` varchar(255) DEFAULT NULL COMMENT '反馈信息',
+    `file` text DEFAULT NULL COMMENT '相关文件',
+    `remark` text DEFAULT NULL COMMENT '备注',
+    `created_by` int(11) NOT NULL COMMENT '创建者',
+    `created_name` varchar(90) NOT NULL COMMENT '创建人',
+    `created_time` datetime NOT NULL COMMENT '创建时间',
+    `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+    `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+    `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+    `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+    PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 9 DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '工单信息' 
+
+-- 工单列表显示字段:工单编号、工单标题、工单类型、工单状态、关联客户、关联项目、产品线、负责人、是否超期、申请人
+alter table work_order add `product_line` varchar(4) NOT NULL COMMENT '产品线' after nbo_name;
+alter table work_order add `end_time` datetime DEFAULT NULL COMMENT '结束时间' after order_status;
+alter table work_order add `finish_remark` text DEFAULT NULL COMMENT '完成信息' after `file`;
+alter table work_order add `finish_time` datetime DEFAULT NULL COMMENT '完成信息' after `finish_remark`;
+alter table work_order add `finish_by` int(11) DEFAULT NULL COMMENT '完成操作人' after `finish_time`;
+alter table work_order add `finish_by_name`  varchar(90) DEFAULT NULL COMMENT '完成操作人' after `finish_by`;
+alter table work_order modify `order_status` varchar(4) NOT NULL COMMENT '工单状态(10发起20审批中30审批通过40审批拒绝50关闭60已完成)';
+