ソースを参照

feature(项目管理): 项目产品、项目联系人修改

ZZH-wl 3 年 前
コミット
3ecbb22e62

+ 54 - 1
doc/订单全流程管理平台.pdma.json

@@ -4,7 +4,7 @@
   "avatar": "",
   "version": "4.2.2",
   "createdTime": "2023-1-6 11:43:05",
-  "updatedTime": "2023-1-9 18:04:10",
+  "updatedTime": "2023-1-11 16:11:04",
   "dbConns": [],
   "profile": {
     "default": {
@@ -3985,6 +3985,24 @@
           "domain": "16120F75-6AA7-4483-868D-F07F511BB081",
           "id": "1FED89AE-896F-45C6-AE36-826C64AE2531"
         },
+        {
+          "defKey": "nbo_code",
+          "defName": "项目编号",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "5E66BDBA-BED9-4D9C-A364-3AE85B30D071",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "AB7B27CE-EBBF-48F6-9067-22009AC7FAB2"
+        },
         {
           "defKey": "nbo_name",
           "defName": "项目名称",
@@ -4002,6 +4020,23 @@
           "domain": "54611CCC-CA4B-42E1-9F32-4944C85B85A6",
           "id": "DCCF7384-3A0D-4D1C-A206-2289320CD6D9"
         },
+        {
+          "defKey": "nbo_status",
+          "defName": "项目状态",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": true,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "refDict": "",
+          "extProps": {},
+          "domain": "73FD2BAD-2358-4336-B96D-45DC897BD792",
+          "id": "C768E679-EA79-4CCD-B204-7DAFF9BDBD3B"
+        },
         {
           "defKey": "cust_id",
           "defName": "关联客户",
@@ -11754,6 +11789,24 @@
           "domain": "6BC8F04B-6CFA-4995-98D3-318F5CDD774E",
           "id": "3645772F-029B-4F2F-9B4B-821C98E34B0A"
         },
+        {
+          "defKey": "guid_price",
+          "defName": "建议成交价",
+          "comment": "",
+          "type": "",
+          "len": "",
+          "scale": "",
+          "primaryKey": false,
+          "notNull": false,
+          "autoIncrement": false,
+          "defaultValue": "",
+          "hideInGraph": false,
+          "domain": "C3B1681B-99F9-4818-9E80-DE1652A51D85",
+          "refDict": "",
+          "extProps": {},
+          "notes": {},
+          "id": "7A480F51-91F3-48E6-B89C-90DC4DA806FE"
+        },
         {
           "defKey": "prod_price",
           "defName": "产品单价",

+ 1 - 1
opms_libary/utils/convert.go

@@ -203,7 +203,7 @@ func ListToArray(list *list.List) []interface{} {
 	return arr
 }
 
-// Map key字符串转驼峰
+// Map key字符串转驼峰 snake:下划线;upperCamel:大驼峰;默认:小驼峰
 func MapKeySnakeCamelCase(oldMap g.Map, convType ...string) g.Map {
 	newMap := make(g.Map)
 	for k, v := range oldMap {

+ 3 - 0
opms_parent/app/dao/proj/internal/proj_business_product.go

@@ -34,6 +34,7 @@ type projBusinessProductColumns struct {
 	ProdClass   string // 产品分类
 	ProdUnit    string // 产品单位
 	ProdNum     string // 产品数量
+	GuidPrice   string // 建议成交价
 	ProdPrice   string // 产品单价
 	TotalPrice  string // 总价
 	Remark      string // 备注
@@ -61,6 +62,7 @@ var (
 			ProdClass:   "prod_class",
 			ProdUnit:    "prod_unit",
 			ProdNum:     "prod_num",
+			GuidPrice:   "guid_price",
 			ProdPrice:   "prod_price",
 			TotalPrice:  "total_price",
 			Remark:      "remark",
@@ -90,6 +92,7 @@ func NewProjBusinessProductDao(tenant string) ProjBusinessProductDao {
 			ProdClass:   "prod_class",
 			ProdUnit:    "prod_unit",
 			ProdNum:     "prod_num",
+			GuidPrice:   "guid_price",
 			ProdPrice:   "prod_price",
 			TotalPrice:  "total_price",
 			Remark:      "remark",

+ 3 - 2
opms_parent/app/handler/proj/business_contact.go

@@ -5,6 +5,7 @@ import (
 	"dashoo.cn/common_definition/comm_def"
 	"dashoo.cn/opms_libary/myerrors"
 	"github.com/gogf/gf/errors/gerror"
+	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/util/gvalid"
 
 	projModel "dashoo.cn/micro/app/model/proj"
@@ -21,12 +22,12 @@ func (p *BusinessContactHandler) GetList(ctx context.Context, req *projModel.Bus
 	if err != nil {
 		return err
 	}
-	list, err := contactService.GetList(req)
+	total, list, err := contactService.GetList(req)
 	_, err, rsp.Code, rsp.Msg = myerrors.CheckError(err)
 	if err != nil {
 		return err
 	}
-	rsp.Data = list
+	rsp.Data = g.Map{"list": list, "total": total}
 	return nil
 }
 

+ 2 - 1
opms_parent/app/model/proj/internal/proj_business_product.go

@@ -14,10 +14,11 @@ type ProjBusinessProduct struct {
 	BusId       int         `orm:"bus_id"       json:"busId"`       // 关联项目
 	ProdId      int         `orm:"prod_id"      json:"prodId"`      // 关联产品
 	ProdName    string      `orm:"prod_name"    json:"prodName"`    // 产品名称
-	ProdCode    float64     `orm:"prod_code"    json:"prodCode"`    // 产品编码
+	ProdCode    string      `orm:"prod_code"    json:"prodCode"`    // 产品编码
 	ProdClass   string      `orm:"prod_class"   json:"prodClass"`   // 产品分类
 	ProdUnit    string      `orm:"prod_unit"    json:"prodUnit"`    // 产品单位
 	ProdNum     int         `orm:"prod_num"     json:"prodNum"`     // 产品数量
+	GuidPrice   float64     `orm:"guid_price"   json:"guidPrice"`   // 建议成交价
 	ProdPrice   float64     `orm:"prod_price"   json:"prodPrice"`   // 产品单价
 	TotalPrice  float64     `orm:"total_price"  json:"totalPrice"`  // 总价
 	Remark      string      `orm:"remark"       json:"remark"`      // 备注

+ 27 - 16
opms_parent/app/model/proj/proj_business.go

@@ -24,21 +24,30 @@ type ProjBusinessSearchReq struct {
 }
 
 type AddProjBusinessReq struct {
-	NboName          string      `json:"nboName"        v:"required#项目名称不能为空"`                                   // 项目名称
-	CustId           int         `json:"custId"        v:"required#关联客户不能为空"`                                    // 关联客户
-	CustName         string      `json:"custName"        v:"required#关联客户不能为空"`                                  // 客户名称
-	ObtainTime       *gtime.Time `orm:"obtain_time"        json:"obtainTime"`                                    // 获取时间
-	NboSource        string      `json:"nboSource"        v:"required#项目来源不能为空"`                                 // 项目来源
-	ContactId        int         `json:"contactId"        v:"required#关联联系人不能为空"`                                // 关联联系人
-	ContactName      string      `json:"contactName"        v:"required#联系人姓名不能为空"`                              // 联系人姓名
-	ContactPostion   string      `json:"contactPostion"`                                                         // 联系人岗位
-	ContactTelephone string      `json:"contactTelephone"`                                                       // 联系人电话
-	SaleId           int         `json:"saleId"        v:"required#归属销售不能为空"`                                    // 归属销售
-	SaleName         string      `json:"saleName"        v:"required#销售姓名不能为空"`                                  // 销售姓名
-	SalesModel       string      `json:"salesModel"        v:"required|in:10,20,30#销售模式不能为空|销售模式不存在"`            // 销售模式(10直销20经销30代理)
-	DistributorId    int         `json:"distributorId"        v:"required-unless:salesModel,10#经销商/代理商不能为空"`     // 经销商/代理商ID
-	DistributorName  string      `json:"distributorName"        v:"required-unless:salesModel,10#经销商/代理商名称不能为空"` // 经销商/代理商名称
-	Remark           string      `json:"remark"`                                                                 // 备注
+	NboName          string `json:"nboName"        v:"required#项目名称不能为空"`                                   // 项目名称
+	CustId           int    `json:"custId"        v:"required#关联客户不能为空"`                                    // 关联客户
+	CustName         string `json:"custName"        v:"required#关联客户不能为空"`                                  // 客户名称
+	NboSource        string `json:"nboSource"        v:"required#项目来源不能为空"`                                 // 项目来源
+	ContactId        int    `json:"contactId"        v:"required#关联联系人不能为空"`                                // 关联联系人
+	ContactName      string `json:"contactName"        v:"required#联系人姓名不能为空"`                              // 联系人姓名
+	ContactPostion   string `json:"contactPostion"`                                                         // 联系人岗位
+	ContactTelephone string `json:"contactTelephone"`                                                       // 联系人电话
+	SaleId           int    `json:"saleId"        v:"required#归属销售不能为空"`                                    // 归属销售
+	SaleName         string `json:"saleName"        v:"required#销售姓名不能为空"`                                  // 销售姓名
+	SalesModel       string `json:"salesModel"        v:"required|in:10,20,30#销售模式不能为空|销售模式不存在"`            // 销售模式(10直销20经销30代理)
+	DistributorId    int    `json:"distributorId"        v:"required-unless:salesModel,10#经销商/代理商不能为空"`     // 经销商/代理商ID
+	DistributorName  string `json:"distributorName"        v:"required-unless:salesModel,10#经销商/代理商名称不能为空"` // 经销商/代理商名称
+
+	NboBudget        float64     `json:"nboBudget"`        // 项目预算
+	ObtainTime       *gtime.Time `json:"obtainTime"`       // 获取时间
+	PlanPurchaseTime *gtime.Time `json:"planPurchaseTime"` // 计划采购时间
+	EstTransTime     *gtime.Time `json:"estTransTime"`     // 预计成交时间
+	EstTransPrice    float64     `json:"estTransPrice"`    // 预计成交价格
+	RiskProfile      string      `json:"riskProfile"`      // 风险情况
+	Difficulty       string      `json:"difficulty"`       // 困难点
+	Competitor       string      `json:"competitor"`       // 竞争公司
+	Intervention     string      `json:"intervention"`     // 介入情况
+	Remark           string      `json:"remark"`           // 备注
 
 	// 跟进日程
 	FollowTime     *gtime.Time `json:"followTime"       v:"required#跟进时间不能为空"`    // 跟进时间
@@ -62,8 +71,9 @@ type BusinessProduct struct {
 	ProdName   string  `json:"prodName"       v:"required#产品名称不能为空"` // 产品名称
 	ProdCode   string  `json:"prodCode"       v:"required#产品编码不能为空"` // 产品编码
 	ProdClass  string  `json:"prodClass"      v:"required#产品类别不能为空"` // 产品类别
-	ProdPrice  float64 `json:"prodPrice"      v:"required#产品单价不能为空"` // 产品单价
 	ProdNum    int     `json:"prodNum"        v:"required#产品数量不能为空"` // 产品数量
+	ProdPrice  float64 `json:"prodPrice"      v:"required#产品售价不能为空"` // 产品售价
+	GuidPrice  float64 `json:"guidPrice"`                            // 建议成交价
 	ProdUnit   string  `json:"prodUnit"`                             // 产品单位
 	TotalPrice int     `json:"totalPrice"`                           // 总价
 	Remark     string  `json:"remark"`                               // 备注
@@ -96,6 +106,7 @@ type BusinessPrimacyContactReq struct {
 // BusinessReq 获取项目关联信息
 type BusinessReq struct {
 	BusId    int64  `json:"busId"        v:"required# 关联项目不能为空"` // 主键
+	CuctId   int    `json:"cuctId"`                              // 客户联系人
 	CuctName string `json:"cuctName"`                            // 客户联系人姓名
 	OpnType  string `json:"opnType"`                             // 操作类型
 	request.PageReq

+ 30 - 4
opms_parent/app/service/proj/business.go

@@ -130,6 +130,11 @@ func (p *businessService) Create(req *model.AddProjBusinessReq) (err error) {
 	if err = gconv.Struct(req, businessData); err != nil {
 		return
 	}
+	contact := g.Map{
+		projDao.ProjBusinessContact.Columns.ContactId: req.ContactId,
+	}
+	service.SetCreatedInfo(contact, p.GetCxtUserId(), p.GetCxtUserName())
+
 	products := make([]*model.ProjBusinessProduct, len(req.Products))
 	if err = gconv.Structs(req.Products, &products); err != nil {
 		return
@@ -152,6 +157,13 @@ func (p *businessService) Create(req *model.AddProjBusinessReq) (err error) {
 		if err != nil {
 			return err
 		}
+		// 创建了联系人
+		contact[projDao.ProjBusinessContact.Columns.BusId] = lastId
+		_, err = projDao.NewProjBusinessContactDao(p.Tenant).TX(tx).Insert(contact)
+		if err != nil {
+			return err
+		}
+
 		// 处理项目产品信息
 		for _, v := range products {
 			v.BusId = int(lastId)
@@ -180,10 +192,18 @@ func (p *businessService) UpdateById(req *model.UpdateProjBusinessReq) (err erro
 		err = gerror.New("该数据不存在")
 		return err
 	}
-	businessData := new(model.ProjBusiness)
-	if err = gconv.Struct(req, businessData); err != nil {
+	businessData := gconv.Map(req)
+	businessData = utils.MapKeySnakeCamelCase(businessData, "snake")
+	products := make([]*model.ProjBusinessProduct, len(req.Products))
+	if err = gconv.Structs(req.Products, &products); err != nil {
 		return
 	}
+	var totalPrice float64
+	for _, v := range products {
+		v.TotalPrice = v.ProdPrice * float64(v.ProdNum)
+		totalPrice += v.TotalPrice
+		service.SetCreatedInfo(v, p.GetCxtUserId(), p.GetCxtUserName())
+	}
 	service.SetUpdatedInfo(businessData, p.GetCxtUserId(), p.GetCxtUserName())
 
 	err = p.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
@@ -192,13 +212,19 @@ func (p *businessService) UpdateById(req *model.UpdateProjBusinessReq) (err erro
 		if err != nil {
 			return err
 		}
+		// 添加项目产品
+		_, err = projDao.NewProjBusinessProductDao(p.Tenant).TX(tx).Save(products)
+		if err != nil {
+			return err
+		}
+
 		// 添加项目动态
 		dynamics := model.ProjBusinessDynamics{
 			BusId:   req.Id,
 			OpnType: "20",
-			Remark:  businessData.Remark,
+			Remark:  req.Remark,
 		}
-		err = p.CreateProjBusinessDynamics(tx, dynamics, businessData)
+		err = p.CreateProjBusinessDynamics(tx, dynamics, req)
 		return err
 	})
 	return

+ 13 - 3
opms_parent/app/service/proj/business_contact.go

@@ -6,6 +6,7 @@ import (
 	projDao "dashoo.cn/micro/app/dao/proj"
 	projModel "dashoo.cn/micro/app/model/proj"
 	"dashoo.cn/micro/app/service"
+	"github.com/gogf/gf/frame/g"
 )
 
 type businessContactService struct {
@@ -22,13 +23,22 @@ func NewBusinessContactService(ctx context.Context) (svc *businessContactService
 	return svc, nil
 }
 
-func (p *businessContactService) GetList(req *projModel.BusinessReq) (contactList []*projModel.BusinessContact, err error) {
+func (p *businessContactService) GetList(req *projModel.BusinessReq) (total int, contactList []*projModel.BusinessContact, err error) {
 	db := p.Dao.As("bus").LeftJoin(custDao.CustCustomerContact.Table, "contact", "bus.contact_id=contact.id").
-		Where("bus."+p.Dao.Columns.BusId, req.BusId).Fields("bus.id AS id, bus.*, contact.*")
+		Where("bus."+p.Dao.Columns.BusId, req.BusId)
+	if req.CuctId != 0 {
+		db = db.Where("contact.cuct_id", req.CuctId)
+	}
 	if req.CuctName != "" {
 		db = db.Where("contact.cuct_name", req.BusId)
 	}
-	err = db.Scan(&contactList)
+	total, err = db.Count()
+	if err != nil {
+		g.Log().Error(err)
+		return
+	}
+
+	err = db.Fields("bus.id AS id, bus.*, contact.*").Page(req.GetPage()).Order("bus.id desc").Scan(&contactList)
 	return
 }