Bläddra i källkod

feature:跟进记录增加协访渠道和人员信息,合同添加运维信息导出功能

sunxinyuan 1 år sedan
förälder
incheckning
7143da4c29

+ 2 - 2
opms_admin/config/config.toml

@@ -1,11 +1,11 @@
 # 应用系统设置
 [setting]
     logpath = "./log/admin"
-    bind-addr = "192.168.0.106:8888"
+    bind-addr = "192.168.0.60:8888"
     need-advertise-addr = false
     srv-name = "dashoo.opms.admin-0.0.1-sxy"
     env = "dev"
-    websocket-addr = "192.168.0.106:8899"
+    websocket-addr = "192.168.0.60:8899"
 
 [logger.websocket]
     path   = "./log/websocket"

+ 9 - 0
opms_parent/app/dao/plat/internal/plat_followup.go

@@ -46,6 +46,9 @@ type platFollowupColumns struct {
 	ContactsId    string // 关联联系人
 	ContactsName  string // 联系人姓名
 	Reminders     string // 提醒对象
+	DistId        string // 经销商id
+	DistName      string // 经销商名称
+	VisitorName   string // 协访人员
 	NextTime      string // 下次联系时间
 	Remark        string // 备注
 	CreatedBy     string // 创建者
@@ -80,6 +83,9 @@ var (
 			ContactsId:    "contacts_id",
 			ContactsName:  "contacts_name",
 			Reminders:     "reminders",
+			DistId:        "dist_id",
+			DistName:      "dist_name",
+			VisitorName:   "visitor_name",
 			NextTime:      "next_time",
 			Remark:        "remark",
 			CreatedBy:     "created_by",
@@ -116,6 +122,9 @@ func NewPlatFollowupDao(tenant string) PlatFollowupDao {
 			ContactsId:    "contacts_id",
 			ContactsName:  "contacts_name",
 			Reminders:     "reminders",
+			DistId:        "dist_id",
+			DistName:      "dist_name",
+			VisitorName:   "visitor_name",
 			NextTime:      "next_time",
 			Remark:        "remark",
 			CreatedBy:     "created_by",

+ 22 - 0
opms_parent/app/handler/contract/ctr_contract.go

@@ -244,3 +244,25 @@ func (c *CtrContract) GetContractShareList(ctx context.Context, req *model.GetCo
 
 	return nil
 }
+
+// Swagger:CtrContract 合同 合同项目运维信息导出
+func (c *CtrContract) CtrContractMaintenanceExport(ctx context.Context, req *model.CtrContractListReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.List request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	path, err := s.CtrContractMaintenanceExport(ctx, req)
+	if err != nil {
+		return err
+	}
+
+	//rsp.Code = code
+	//rsp.Msg = msg
+	//rsp.Data = map[string]interface{}{
+	//	"total": total,
+	//	"list":  ent,
+	//}
+	rsp.Data = path
+	return nil
+}

+ 19 - 0
opms_parent/app/model/contract/ctr_contract.go

@@ -49,6 +49,15 @@ type CtrContractListReq struct {
 	CustCityId            int    `json:"custCityId"`            // 所在市ID
 	ContractSignTimeStart string `json:"contractSignTimeStart"` //合同签订时间开始
 	ContractSignTimeEnd   string `json:"contractSignTimeEnd"`   //合同签订时间结束
+
+	SoftwareMaintenanceBeginTimeStart *gtime.Time `json:"softwareMaintenanceBeginTimeStart"` // 软件运维开始时间
+	SoftwareMaintenanceBeginTimeEnd   *gtime.Time `json:"softwareMaintenanceBeginTimeEnd"`   // 软件运维开始时间
+	SoftwareMaintenanceEndTimeStart   *gtime.Time `json:"softwareMaintenanceEndTimeStart"`   // 软件运维结束时间
+	SoftwareMaintenanceEndTimeEnd     *gtime.Time `json:"softwareMaintenanceEndTimeEnd"`     // 软件运维结束时间
+	HardwareMaintenanceBeginTimeStart *gtime.Time `json:"hardwareMaintenanceBeginTimeStart"` // 硬件运维开始时间
+	HardwareMaintenanceBeginTimeEnd   *gtime.Time `json:"hardwareMaintenanceBeginTimeEnd"`   // 硬件运维开始时间
+	HardwareMaintenanceEndTimeStart   *gtime.Time `json:"hardwareMaintenanceEndTimeStart"`   // 硬件运维结束时间
+	HardwareMaintenanceEndTimeEnd     *gtime.Time `json:"hardwareMaintenanceEndTimeEnd"`     // 硬件运维结束时间
 }
 
 type CtrAddProduct struct {
@@ -179,3 +188,13 @@ type CtrContractCommitWithFileUrlReq struct {
 type GetContractShareReq struct {
 	ContractId string `json:"contractId" v:"required#合同Id不能为空"`
 }
+type CtrContractMaintenanceExport struct {
+	NboName                      string      `json:"nboName"                                export:"项目名称"`     // 项目名称
+	SoftwareMaintenanceBeginTime *gtime.Time `json:"softwareMaintenanceBeginTime"           export:"软件运维开始时间"` // 软件运维开始时间
+	SoftwareMaintenanceEndTime   *gtime.Time `json:"softwareMaintenanceEndTime"             export:"软件运维结束时间"` // 软件运维结束时间
+	HardwareMaintenanceBeginTime *gtime.Time `json:"hardwareMaintenanceBeginTime"           export:"硬件运维开始时间"` // 硬件运维开始时间
+	HardwareMaintenanceEndTime   *gtime.Time `json:"hardwareMaintenanceEndTime"             export:"硬件运维结束时间"` // 硬件运维结束时间
+	//SoftwareMaintenanceLimit     int         `json:"softwareMaintenanceLimit"`     // 软件运维期限(年)
+	//HardwareMaintenanceLimit     int         `json:"hardwareMaintenanceLimit"`     // 硬件运维期限(年)
+
+}

+ 3 - 0
opms_parent/app/model/plat/internal/plat_followup.go

@@ -26,6 +26,9 @@ type PlatFollowup struct {
 	ContactsId    int         `orm:"contacts_id"    json:"contactsId"`    // 关联联系人
 	ContactsName  string      `orm:"contacts_name"  json:"contactsName"`  // 联系人姓名
 	Reminders     string      `orm:"reminders"      json:"reminders"`     // 提醒对象
+	DistId        int         `orm:"dist_id"        json:"distId"`        // 经销商id
+	DistName      string      `orm:"dist_name"      json:"distName"`      // 经销商名称
+	VisitorName   string      `orm:"visitor_name"   json:"visitorName"`   // 协访人员
 	NextTime      *gtime.Time `orm:"next_time"      json:"nextTime"`      // 下次联系时间
 	Remark        string      `orm:"remark"         json:"remark"`        // 备注
 	CreatedBy     int         `orm:"created_by"     json:"createdBy"`     // 创建者

+ 21 - 17
opms_parent/app/model/plat/plat_followup.go

@@ -30,29 +30,33 @@ type SearchPlatFollowupReq struct {
 	DaysBeforeToday int    `json:"daysBeforeToday"`
 	IsMyself        string `json:"isMyself"`    // IsMyself为1时,查询本人的数据
 	CreatedName     string `json:"createdName"` // 跟进对象
+	DistId          string `json:"distId"`      // 经销商id
 	request.PageReq
 }
 
 // 添加数据
 type AddPlatFollowupReq struct {
-	FollowType    string                    `orm:"follow_type"    json:"followType"    v:"required#跟进类型不能为空"`                            // 跟进类型(10电话20邮件30拜访)
-	FollowDate    *gtime.Time               `orm:"follow_date"    json:"followDate"    v:"required#跟进时间不能为空"`                            // 跟进时间
-	FollowContent string                    `orm:"follow_content" json:"followContent" v:"required#跟进内容不能为空"`                            // 跟进内容
-	FurtherPlan   string                    `orm:"further_plan"   json:"furtherPlan" v:"required#下一步跟进计划和目标不能为空"`                  // 下一步跟进计划和目标
-	Effect        string                    `orm:"effect"         json:"effect" v:"required#达成效果不能为空"`                                   // 达成效果
-	Issue         string                    `orm:"issue"          json:"issue" v:"required#问题或困难不能为空"`                                  // 问题或困难
+	FollowType    string                    `orm:"follow_type"    json:"followType"    v:"required#跟进类型不能为空"`                    // 跟进类型(10电话20邮件30拜访)
+	FollowDate    *gtime.Time               `orm:"follow_date"    json:"followDate"    v:"required#跟进时间不能为空"`                    // 跟进时间
+	FollowContent string                    `orm:"follow_content" json:"followContent" v:"required#跟进内容不能为空"`                    // 跟进内容
+	FurtherPlan   string                    `orm:"further_plan"   json:"furtherPlan" v:"required#下一步跟进计划和目标不能为空"`                // 下一步跟进计划和目标
+	Effect        string                    `orm:"effect"         json:"effect" v:"required#达成效果不能为空"`                           // 达成效果
+	Issue         string                    `orm:"issue"          json:"issue" v:"required#问题或困难不能为空"`                           // 问题或困难
 	TargetId      int                       `orm:"target_id"      json:"targetId"      v:"required|min:1#跟进对象ID不能为空|跟进对象ID不能为空"` // 跟进对象ID
-	TargetType    string                    `orm:"target_type"    json:"targetType"    v:"required#跟进对象类型不能为空"`                        // 跟进对象类型(10客户,20项目,30合同,40回款)
-	TargetName    string                    `orm:"target_name"    json:"targetName"    v:"required#跟进对象不能为空"`                            // 跟进对象
-	CustId        int                       `orm:"cust_id"        json:"custId"`                                                                 // 关联客户
-	CustName      string                    `orm:"cust_name"      json:"custName"`                                                               // 客户名称
-	ContactType   string                    `orm:"contact_type"   json:"contactType"`                                                            // 联系人类型(10客户 20 渠道)
-	ContactsId    int                       `orm:"contacts_id"    json:"contactsId"`                                                             // 关联联系人
-	ContactsName  string                    `orm:"contacts_name"  json:"contactsName"`                                                           // 联系人姓名
-	Reminders     string                    `orm:"reminders"      json:"reminders"`                                                              // 提醒对象
-	NextTime      *gtime.Time               `orm:"next_time"      json:"nextTime"`                                                               // 下次联系时间
-	Remark        string                    `orm:"remark"         json:"remark"`                                                                 // 备注
-	Files         []*AddPlatFollowupFileReq `json:"files"`                                                                                       // 附件
+	TargetType    string                    `orm:"target_type"    json:"targetType"    v:"required#跟进对象类型不能为空"`                  // 跟进对象类型(10客户,20项目,30合同,40回款)
+	TargetName    string                    `orm:"target_name"    json:"targetName"    v:"required#跟进对象不能为空"`                    // 跟进对象
+	CustId        int                       `orm:"cust_id"        json:"custId"`                                                 // 关联客户
+	CustName      string                    `orm:"cust_name"      json:"custName"`                                               // 客户名称
+	ContactType   string                    `orm:"contact_type"   json:"contactType"`                                            // 联系人类型(10客户 20 渠道)
+	ContactsId    int                       `orm:"contacts_id"    json:"contactsId"`                                             // 关联联系人
+	ContactsName  string                    `orm:"contacts_name"  json:"contactsName"`                                           // 联系人姓名
+	Reminders     string                    `orm:"reminders"      json:"reminders"`                                              // 提醒对象
+	NextTime      *gtime.Time               `orm:"next_time"      json:"nextTime"`                                               // 下次联系时间
+	Remark        string                    `orm:"remark"         json:"remark"`                                                 // 备注
+	DistId        int                       `orm:"dist_id"        json:"distId"`                                                 // 经销商id
+	DistName      string                    `orm:"dist_name"      json:"distName"`                                               // 经销商名称
+	VisitorName   string                    `orm:"visitor_name"   json:"visitorName"`                                            // 协访人员
+	Files         []*AddPlatFollowupFileReq `json:"files"`                                                                       // 附件
 	//FollowContentType string      `orm:"follow_content_type" json:"followContentType" v:"required#跟进内容类型不能为空"`               // 跟进内容类型
 	//SupportName       string      `orm:"support_name"   json:"supportName"`                                                            // 总部支持人员
 }

+ 57 - 0
opms_parent/app/service/base.go

@@ -5,8 +5,10 @@ import (
 	"dashoo.cn/opms_libary/multipart"
 	"fmt"
 	"github.com/gogf/gf/encoding/gurl"
+	"github.com/gogf/gf/os/gfile"
 	"github.com/gogf/gf/text/gstr"
 	"github.com/gogf/gf/util/guid"
+	"github.com/xuri/excelize/v2"
 	"io/ioutil"
 	"log"
 	"net/http"
@@ -488,3 +490,58 @@ func DownloadTempFile(url string) (*multipart.FileHeader, error) {
 	fileData.File = file
 	return fileData, nil
 }
+
+// getExcelHeader  获取Excel表头
+func getExcelHeader(exportStruct interface{}, tag string) ([]string, g.MapStrStr) {
+	var headerList []string
+	headerMap := g.MapStrStr{}
+	reqType := reflect.TypeOf(exportStruct)
+	if reqType.Kind() == reflect.Ptr {
+		reqType = reqType.Elem()
+	}
+	for i := 0; i < reqType.NumField(); i++ {
+		fieldName, ok := reqType.Field(i).Tag.Lookup("json")
+		if !ok {
+			fieldName = reqType.Field(i).Name
+		}
+		if tag, ok := reqType.Field(i).Tag.Lookup(tag); ok {
+			headerList = append(headerList, tag)
+			headerMap[tag] = fieldName
+		}
+	}
+
+	return headerList, headerMap
+}
+
+// CommonExportExcel 公共单表导出excel
+func CommonExportExcel(ctx context.Context, fileName string, exportStruct interface{}, dataList []map[string]interface{}, handleFunc ...func(map[string]interface{}, string) interface{}) (path string, err error) {
+	headerList, headerMap := getExcelHeader(exportStruct, "export")
+	// 转换数据
+	xlsxFile := excelize.NewFile()
+	defer xlsxFile.Close()
+	// 插入表头
+	if fileName == "" {
+		fileName = "Sheet1"
+	}
+	xlsxFile.SetSheetName("Sheet1", fileName)
+	xlsxFile.SetSheetRow(fileName, "A1", &headerList)
+	for k, item := range dataList {
+		var row []interface{}
+		for _, h := range headerList {
+			val := item[headerMap[h]]
+			if len(handleFunc) > 0 {
+				val = handleFunc[0](item, headerMap[h])
+			}
+			row = append(row, val)
+		}
+		xlsxFile.SetSheetRow(fileName, fmt.Sprintf("A%d", k+2), &row)
+	}
+	dir := g.Config().GetString("setting.export-path")
+	gfile.Mkdir(dir)
+	path = dir + "/" + fileName + gtime.Now().Format("Y-m-d_H-i-s") + ".xlsx"
+	// 根据指定路径保存文件
+	if err := xlsxFile.SaveAs(path); err != nil {
+		g.Log().Error(ctx, err)
+	}
+	return path, err
+}

+ 58 - 0
opms_parent/app/service/contract/ctr_contract.go

@@ -261,7 +261,31 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	if req.ProductLine != "" {
 		dao = dao.Where("a.product_line = ?", req.ProductLine)
 	}
+	if req.SoftwareMaintenanceBeginTimeStart != nil {
+		dao = dao.Where("a.software_maintenance_begin_time >= ?", req.SoftwareMaintenanceBeginTimeStart)
+	}
+	if req.SoftwareMaintenanceBeginTimeEnd != nil {
+		dao = dao.Where("a.software_maintenance_begin_time <= ?", req.SoftwareMaintenanceBeginTimeEnd)
+	}
+	if req.SoftwareMaintenanceEndTimeStart != nil {
+		dao = dao.Where("a.software_maintenance_end_time >= ?", req.SoftwareMaintenanceEndTimeStart)
+	}
+	if req.SoftwareMaintenanceEndTimeEnd != nil {
+		dao = dao.Where("a.software_maintenance_end_time <= ?", req.SoftwareMaintenanceEndTimeEnd)
+	}
 
+	if req.HardwareMaintenanceBeginTimeStart != nil {
+		dao = dao.Where("a.hardware_maintenance_begin_time >= ?", req.HardwareMaintenanceBeginTimeStart)
+	}
+	if req.HardwareMaintenanceBeginTimeEnd != nil {
+		dao = dao.Where("a.hardware_maintenance_begin_time <= ?", req.HardwareMaintenanceBeginTimeEnd)
+	}
+	if req.HardwareMaintenanceEndTimeStart != nil {
+		dao = dao.Where("a.hardware_maintenance_end_time >= ?", req.HardwareMaintenanceEndTimeStart)
+	}
+	if req.HardwareMaintenanceEndTimeEnd != nil {
+		dao = dao.Where("a.hardware_maintenance_end_time <= ?", req.HardwareMaintenanceEndTimeEnd)
+	}
 	total, err := dao.Count()
 	if err != nil {
 		return 0, nil, err
@@ -1356,3 +1380,37 @@ func init() {
 	// job()
 
 }
+
+func (s CtrContractService) CtrContractMaintenanceExport(ctx context.Context, req *model.CtrContractListReq) (path string, err error) {
+
+	req.PageNum = 0
+	_, list, err := s.List(ctx, req)
+	if err != nil {
+		return path, err
+	}
+	exportsData := make([]*model.CtrContractMaintenanceExport, 0)
+	if err = gconv.Struct(&list, &exportsData); err != nil {
+		return
+	}
+	path, err = service.CommonExportExcel(ctx, "项目运维信息", model.CtrContractMaintenanceExport{}, gconv.Maps(exportsData), func(item map[string]interface{}, header string) interface{} {
+		if header == "softwareMaintenanceBeginTime" {
+			return gconv.GTime(item[header]).Format("Y-m-d")
+		}
+		if header == "softwareMaintenanceEndTime" {
+			return gconv.GTime(item[header]).Format("Y-m-d")
+		}
+		if header == "hardwareMaintenanceBeginTime" {
+			return gconv.GTime(item[header]).Format("Y-m-d")
+		}
+		if header == "hardwareMaintenanceEndTime" {
+			return gconv.GTime(item[header]).Format("Y-m-d")
+		}
+
+		return item[header]
+	})
+	if err != nil {
+		return path, err
+	}
+	return path, nil
+
+}

+ 3 - 0
opms_parent/app/service/plat/plat_followup.go

@@ -190,6 +190,9 @@ func (s *followupService) GetListByDay(req *model.SearchPlatFollowupReq) (total
 	if req.CustId != "" {
 		followupModel = followupModel.Where("cust_id", req.CustId)
 	}
+	if req.DistId != "" {
+		followupModel = followupModel.Where("dist_id", req.DistId)
+	}
 	if req.CustName != "" {
 		followupModel = followupModel.WhereLike("cust_name", "%"+req.CustName+"%")
 	}