ai_scheduler/internal/services/advice/customer_new.go

225 lines
6.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package advice
import (
"ai_scheduler/internal/biz"
"ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg"
"ai_scheduler/internal/pkg/wx"
"fmt"
"strconv"
"strings"
"github.com/gofiber/fiber/v2"
)
// CustomerService 微信好友数据服务
type CustomerService struct {
customerBiz *biz.AdviceCustomerBiz
labelBiz *biz.AdviceLabelBiz
projectBiz *biz.AdviceProjectBiz
advicerBiz *biz.AdviceAdvicerBiz
}
func NewCustomerService(customerBiz *biz.AdviceCustomerBiz, labelBiz *biz.AdviceLabelBiz, projectBiz *biz.AdviceProjectBiz, advicerBiz *biz.AdviceAdvicerBiz) *CustomerService {
return &CustomerService{customerBiz: customerBiz, labelBiz: labelBiz, projectBiz: projectBiz, advicerBiz: advicerBiz}
}
// Add 新增单条好友
func (s *CustomerService) Add(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerAddReq{}
if err := c.BodyParser(req); err != nil {
return err
}
err := s.customerBiz.Add(c.UserContext(), req)
return pkg.HandleResponse(c, nil, err)
}
// List 好友列表查询
func (s *CustomerService) List(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerListReq{}
if err := c.BodyParser(req); err != nil {
return err
}
list, err := s.customerBiz.List(c.UserContext(), req)
return pkg.HandleResponse(c, list, err)
}
// Del 删除好友
func (s *CustomerService) Del(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerDelReq{}
if err := c.BodyParser(req); err != nil {
return err
}
err := s.customerBiz.Del(c.UserContext(), req)
return pkg.HandleResponse(c, nil, err)
}
// Diff 好友差集查询(同时返回标签列表)
func (s *CustomerService) Diff(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerDiffReq{}
if err := c.BodyParser(req); err != nil {
return err
}
diff, err := s.customerBiz.Diff(c.UserContext(), req)
if err != nil {
return pkg.HandleResponse(c, nil, err)
}
// 顺便查询标签列表
if req.SelfWxid != "" {
labels, _ := s.labelBiz.List(c.UserContext(), &entitys.AdvicerLabelListReq{SelfWxid: req.SelfWxid})
if labels != nil {
diff.Labels = labels
}
}
return pkg.HandleResponse(c, diff, nil)
}
// BatchAdd 批量新增好友
func (s *CustomerService) BatchAdd(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerBatchAddReq{}
if err := c.BodyParser(req); err != nil {
return err
}
err := s.customerBiz.BatchAdd(c.UserContext(), req)
return pkg.HandleResponse(c, nil, err)
}
// BatchUpdate 批量更新已有好友信息
func (s *CustomerService) BatchUpdate(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerBatchAddReq{}
if err := c.BodyParser(req); err != nil {
return err
}
err := s.customerBiz.BatchUpdate(c.UserContext(), req)
return pkg.HandleResponse(c, nil, err)
}
// UpdateLabels 更新好友标签列表(wx API + DB 一次完成)
func (s *CustomerService) UpdateLabels(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerUpdateLabelsReq{}
if err := c.BodyParser(req); err != nil {
return err
}
// 1. 查询项目的 wx_token
project, err := s.projectBiz.BaseInfo(req.ProjectId)
if err != nil {
return pkg.HandleResponse(c, nil, err)
}
if project.WxToken == "" {
return pkg.HandleResponse(c, nil, fiber.NewError(fiber.StatusBadRequest, "项目未配置微信接入 Token"))
}
// 2. 调用微信 API 修改好友标签(全量替换)
var wxIds []string
if req.UserName != "" {
wxIds = strings.Split(req.UserName, ",")
}
wxReq := wx.ModifyMemberListReq{
AppId: req.AppId,
LabelIds: req.LabelList,
WxIds: wxIds,
}
var wxRes wx.ModifyMemberListResData
if err := wx.Request(c.UserContext(), project.WxToken, wx.ModifyMemberList, wxReq, &wxRes); err != nil {
return pkg.HandleResponse(c, nil, fmt.Errorf("微信标签修改失败: %w", err))
}
// 3. 更新 DB
if err := s.customerBiz.UpdateLabels(c.UserContext(), &entitys.AdvicerCustomerUpdateLabelsReq{
SelfWxid: req.SelfWxid,
UserName: req.UserName,
LabelList: req.LabelList,
}); err != nil {
return pkg.HandleResponse(c, nil, fmt.Errorf("数据库更新失败: %w", err))
}
return pkg.HandleResponse(c, nil, nil)
}
// HostedList 查询项目下所有托管客户(在托管标签分组内的客户)
func (s *CustomerService) HostedList(c *fiber.Ctx) error {
req := &entitys.AdvicerCustomerHostedListReq{}
if err := c.BodyParser(req); err != nil {
return err
}
ctx := c.UserContext()
// 1. 查项目下所有销售
advicers, err := s.advicerBiz.List(ctx, &entitys.AdvicerListReq{ProjectId: req.ProjectId})
if err != nil {
return pkg.HandleResponse(c, nil, err)
}
// 构建 selfWxid -> advicerName 映射,收集所有 selfWxid
// 关联逻辑:advicer.wx_id = ai_advice_customer.self_wxid
advicerMap := make(map[string]string)
var selfWxids []string
for _, adv := range advicers {
wxId, _ := adv["wx_id"].(string)
name, _ := adv["name"].(string)
if wxId != "" {
advicerMap[wxId] = name
selfWxids = append(selfWxids, wxId)
}
}
if len(selfWxids) == 0 {
return pkg.HandleResponse(c, []entitys.HostedCustomerItem{}, nil)
}
// 2. 获取每个销售的托管标签 ID,构建 selfWxid -> hostingLabelIds 和 labelId -> labelName 映射
hostingLabelsMap := make(map[string]map[int]bool)
labelNameMap := make(map[int]string)
for _, selfWxid := range selfWxids {
hostIds, _ := s.labelBiz.GetHostingLabelIds(ctx, selfWxid)
if len(hostIds) == 0 {
continue
}
hostingLabelsMap[selfWxid] = make(map[int]bool)
for _, id := range hostIds {
hostingLabelsMap[selfWxid][id] = true
}
labels, _ := s.labelBiz.List(ctx, &entitys.AdvicerLabelListReq{SelfWxid: selfWxid})
for _, l := range labels {
labelNameMap[int(l.LabelId)] = l.LabelName
}
}
if len(hostingLabelsMap) == 0 {
return pkg.HandleResponse(c, []entitys.HostedCustomerItem{}, nil)
}
// 3. 查询这些 selfWxid 下的所有客户,筛选出在托管标签下的
allCustomers, err := s.customerBiz.FindBySelfWxids(ctx, selfWxids)
if err != nil {
return pkg.HandleResponse(c, nil, err)
}
var result []entitys.HostedCustomerItem
for _, cust := range allCustomers {
hostLabels, ok := hostingLabelsMap[cust.SelfWxid]
if !ok {
continue
}
// 判断客户的 label_list 与托管标签是否有交集
var matchedNames []string
for _, ls := range strings.Split(cust.LabelList, ",") {
id, e := strconv.Atoi(strings.TrimSpace(ls))
if e == nil && hostLabels[id] {
if name, exists := labelNameMap[id]; exists {
matchedNames = append(matchedNames, name)
}
}
}
if len(matchedNames) == 0 {
continue
}
result = append(result, entitys.HostedCustomerItem{
AiAdviceCustomer: cust,
LabelNames: strings.Join(matchedNames, ","),
AdvicerName: advicerMap[cust.SelfWxid],
})
}
return pkg.HandleResponse(c, result, nil)
}