Files
yunzerwebsiteallinone/go/controllers/backend_crm_pool.go
T

269 lines
7.3 KiB
Go

package controllers
import (
"encoding/json"
"fmt"
"io"
"strings"
"time"
"server/models"
"server/pkg/jwtutil"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
)
// BackendCrmPoolController 客户公海控制器
// 公海语义:in_pool=1 的客户处于公海中(租户共享,无个人负责人);
// 移入公海会置 in_pool=1 并释放负责人,领取/分配/移出会置 in_pool=0 并绑定负责人。
type BackendCrmPoolController struct {
beego.Controller
}
func (c *BackendCrmPoolController) poolClaims() (*jwtutil.Claims, error) {
auth := c.Ctx.Request.Header.Get("Authorization")
if auth == "" {
return nil, fmt.Errorf("未登录")
}
parts := strings.SplitN(auth, " ", 2)
if len(parts) != 2 || parts[0] != "Bearer" {
return nil, fmt.Errorf("认证信息格式错误")
}
claims, err := jwtutil.ParseToken(parts[1])
if err != nil {
return nil, fmt.Errorf("无效的token")
}
if claims.UserType != "backend" {
return nil, fmt.Errorf("无权访问")
}
return claims, nil
}
func (c *BackendCrmPoolController) poolJsonErr(httpStatus, bizCode int, msg string) {
c.Ctx.Output.SetStatus(httpStatus)
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
_ = c.ServeJSON()
}
func (c *BackendCrmPoolController) poolOk(data interface{}) {
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": data}
_ = c.ServeJSON()
}
// List GET /backend/crm/pool/list 公海列表(无负责人、租户内共享)
func (c *BackendCrmPoolController) List() {
claims, err := c.poolClaims()
if err != nil {
c.poolJsonErr(401, 401, err.Error())
return
}
page, _ := c.GetInt("page", 1)
pageSize, _ := c.GetInt("pageSize", 20)
keyword := strings.TrimSpace(c.GetString("keyword"))
customerType := strings.TrimSpace(c.GetString("customer_type"))
customerLevel := strings.TrimSpace(c.GetString("customer_level"))
startTime := strings.TrimSpace(c.GetString("start_time"))
endTime := strings.TrimSpace(c.GetString("end_time"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
cond := orm.NewCondition().
And("tenant_id", fmt.Sprintf("%d", claims.TenantId)).
And("delete_time__isnull", true).
And("in_pool", 1)
if keyword != "" {
kw := orm.NewCondition().
Or("customer_name__contains", keyword).
Or("contact_person__contains", keyword).
Or("contact_phone__contains", keyword)
cond = cond.AndCond(kw)
}
if customerType != "" {
cond = cond.And("customer_type", customerType)
}
if customerLevel != "" {
cond = cond.And("customer_level", customerLevel)
}
if startTime != "" {
cond = cond.And("pool_in_time__gte", startTime)
}
if endTime != "" {
cond = cond.And("pool_in_time__lte", endTime+" 23:59:59")
}
qs := models.Orm.QueryTable(new(models.TenantCrmCustomer)).SetCond(cond)
total, _ := qs.Count()
var list []models.TenantCrmCustomer
if total > 0 {
_, _ = qs.OrderBy("-pool_in_time").Offset((page - 1) * pageSize).Limit(pageSize).All(&list)
}
c.poolOk(map[string]interface{}{
"list": list,
"total": total,
"page": page,
"pageSize": pageSize,
})
}
// Move POST /backend/crm/pool/move 移入公海:释放负责人,记录原负责人与原因
func (c *BackendCrmPoolController) Move() {
claims, err := c.poolClaims()
if err != nil {
c.poolJsonErr(401, 401, err.Error())
return
}
var p struct {
IDs []uint64 `json:"ids"`
Reason string `json:"reason"`
}
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.poolJsonErr(400, 400, "参数错误")
return
}
if len(p.IDs) == 0 {
c.poolJsonErr(400, 400, "请选择要移入公海客户")
return
}
reason := strings.TrimSpace(p.Reason)
if reason == "" {
c.poolJsonErr(400, 400, "请填写移入原因")
return
}
now := time.Now()
updated := 0
for _, id := range p.IDs {
var cust models.TenantCrmCustomer
err := models.Orm.QueryTable(new(models.TenantCrmCustomer)).
Filter("id", id).
Filter("tenant_id", fmt.Sprintf("%d", claims.TenantId)).
Filter("delete_time__isnull", true).
One(&cust)
if err != nil {
continue
}
// 记录原负责人(移入公海前的负责人),再清空负责人并置入公海
cust.LastOwnerName = cust.OwnerUserName
cust.OwnerUserID = ""
cust.OwnerUserName = ""
cust.InPool = 1
cust.PoolReason = reason
cust.PoolInTime = &now
cust.UpdateTime = now
if _, err := models.Orm.Update(&cust,
"last_owner_name", "owner_user_id", "owner_user_name", "in_pool",
"pool_reason", "pool_in_time", "update_time"); err == nil {
updated++
}
}
c.poolOk(map[string]interface{}{"updated": updated})
}
// Claim POST /backend/crm/pool/claim 领取:将公海客户归属为当前登录用户
func (c *BackendCrmPoolController) Claim() {
claims, err := c.poolClaims()
if err != nil {
c.poolJsonErr(401, 401, err.Error())
return
}
var p struct {
IDs []uint64 `json:"ids"`
}
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.poolJsonErr(400, 400, "参数错误")
return
}
if len(p.IDs) == 0 {
c.poolJsonErr(400, 400, "请选择客户")
return
}
now := time.Now()
uid := fmt.Sprintf("%d", claims.UserID)
updated := 0
for _, id := range p.IDs {
var cust models.TenantCrmCustomer
err := models.Orm.QueryTable(new(models.TenantCrmCustomer)).
Filter("id", id).
Filter("tenant_id", fmt.Sprintf("%d", claims.TenantId)).
Filter("delete_time__isnull", true).
One(&cust)
if err != nil {
continue
}
cust.OwnerUserID = uid
cust.OwnerUserName = resolveUserName(claims)
cust.InPool = 0
cust.PoolInTime = nil
cust.PoolReason = ""
cust.UpdateTime = now
if _, err := models.Orm.Update(&cust,
"owner_user_id", "owner_user_name", "in_pool", "pool_in_time", "pool_reason", "update_time"); err == nil {
updated++
}
}
c.poolOk(map[string]interface{}{"updated": updated})
}
// Assign POST /backend/crm/pool/assign 分配:将公海客户分配给指定负责人
func (c *BackendCrmPoolController) Assign() {
claims, err := c.poolClaims()
if err != nil {
c.poolJsonErr(401, 401, err.Error())
return
}
var p struct {
IDs []uint64 `json:"ids"`
OwnerUserID interface{} `json:"owner_user_id"`
OwnerUserName string `json:"owner_user_name"`
}
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.poolJsonErr(400, 400, "参数错误")
return
}
if len(p.IDs) == 0 {
c.poolJsonErr(400, 400, "请选择客户")
return
}
ownerID := strings.TrimSpace(fmt.Sprintf("%v", p.OwnerUserID))
if ownerID == "" {
c.poolJsonErr(400, 400, "请指定负责人")
return
}
now := time.Now()
updated := 0
for _, id := range p.IDs {
var cust models.TenantCrmCustomer
err := models.Orm.QueryTable(new(models.TenantCrmCustomer)).
Filter("id", id).
Filter("tenant_id", fmt.Sprintf("%d", claims.TenantId)).
Filter("delete_time__isnull", true).
One(&cust)
if err != nil {
continue
}
cust.OwnerUserID = ownerID
cust.OwnerUserName = strings.TrimSpace(p.OwnerUserName)
cust.InPool = 0
cust.PoolInTime = nil
cust.PoolReason = ""
cust.UpdateTime = now
if _, err := models.Orm.Update(&cust,
"owner_user_id", "owner_user_name", "in_pool", "pool_in_time", "pool_reason", "update_time"); err == nil {
updated++
}
}
c.poolOk(map[string]interface{}{"updated": updated})
}