245 lines
6.7 KiB
Go
245 lines
6.7 KiB
Go
package biz
|
||
|
||
import (
|
||
"ai_scheduler/internal/data/mongo_model"
|
||
"ai_scheduler/internal/entitys"
|
||
"ai_scheduler/internal/pkg"
|
||
"errors"
|
||
"fmt"
|
||
"time"
|
||
|
||
"context"
|
||
|
||
"go.mongodb.org/mongo-driver/bson"
|
||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||
"go.mongodb.org/mongo-driver/mongo"
|
||
)
|
||
|
||
type AdviceClientBiz struct {
|
||
AdvicerClientMongo *mongo_model.AdvicerClientMongo
|
||
mongo *pkg.Mongo
|
||
}
|
||
|
||
func NewAdviceClientBiz(
|
||
advicerClientMongo *mongo_model.AdvicerClientMongo,
|
||
mongo *pkg.Mongo,
|
||
) *AdviceClientBiz {
|
||
return &AdviceClientBiz{
|
||
AdvicerClientMongo: advicerClientMongo,
|
||
mongo: mongo,
|
||
}
|
||
}
|
||
|
||
func (a *AdviceClientBiz) Add(ctx context.Context, param *entitys.AdvicerClientAddReq) (id interface{}, err error) {
|
||
// AI 参与开关:默认开启
|
||
aiEnabled := true
|
||
if param.AiEnabled != nil {
|
||
aiEnabled = *param.AiEnabled
|
||
}
|
||
|
||
res, err := a.mongo.Co(a.AdvicerClientMongo).InsertOne(ctx, &mongo_model.AdvicerClientMongo{
|
||
ProjectId: param.ProjectId,
|
||
AdvicerId: param.AdvicerId,
|
||
Wxid: param.Wxid,
|
||
AiEnabled: aiEnabled,
|
||
PersonalInfo: param.PersonalInfo,
|
||
PurchasePurpose: param.PurchasePurpose,
|
||
CoreDemands: param.CoreDemands,
|
||
Concerns: param.Concerns,
|
||
DecisionProfile: param.DecisionProfile,
|
||
LastUpdateTime: time.Now(),
|
||
})
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return res.InsertedID, err
|
||
}
|
||
|
||
func (a *AdviceClientBiz) Update(ctx context.Context, param *entitys.AdvicerrClientUpdateReq) (err error) {
|
||
filter := bson.M{}
|
||
if len(param.Id) == 0 {
|
||
return errors.New("ID不能为空")
|
||
}
|
||
objectID, err := primitive.ObjectIDFromHex(param.Id)
|
||
if err != nil {
|
||
return fmt.Errorf("ID转换失败: %w", err)
|
||
}
|
||
filter["_id"] = objectID
|
||
|
||
// 读取旧记录,保留回调/等级评估自动维护的字段,避免人工编辑资料时被覆盖
|
||
var old mongo_model.AdvicerClientMongo
|
||
if err = a.mongo.Co(a.AdvicerClientMongo).FindOne(ctx, filter).Decode(&old); err != nil {
|
||
return fmt.Errorf("客户不存在: %w", err)
|
||
}
|
||
// AI 参与开关:未传保持原值
|
||
aiEnabled := old.AiEnabled
|
||
if param.AiEnabled != nil {
|
||
aiEnabled = *param.AiEnabled
|
||
}
|
||
|
||
update := bson.M{
|
||
"$set": &mongo_model.AdvicerClientMongo{
|
||
ProjectId: param.ProjectId,
|
||
AdvicerId: param.AdvicerId,
|
||
Wxid: old.Wxid,
|
||
AppId: old.AppId,
|
||
ClientLevel: old.ClientLevel,
|
||
LevelReason: old.LevelReason,
|
||
LevelUpdateAt: old.LevelUpdateAt,
|
||
LastContactAt: old.LastContactAt,
|
||
LastClientMsgAt: old.LastClientMsgAt,
|
||
LastReplyAt: old.LastReplyAt,
|
||
MsgCount: old.MsgCount,
|
||
AiEnabled: aiEnabled,
|
||
LastIterateAt: old.LastIterateAt,
|
||
PersonalInfo: param.PersonalInfo,
|
||
PurchasePurpose: param.PurchasePurpose,
|
||
CoreDemands: param.CoreDemands,
|
||
Concerns: param.Concerns,
|
||
DecisionProfile: param.DecisionProfile,
|
||
LastUpdateTime: time.Now(),
|
||
},
|
||
}
|
||
res := a.mongo.Co(a.AdvicerClientMongo).FindOneAndUpdate(ctx, filter, update)
|
||
return res.Err()
|
||
}
|
||
|
||
func (a *AdviceClientBiz) List(ctx context.Context, param *entitys.AdvicerClientListReq) (list []mongo_model.AdvicerClientItem, err error) {
|
||
filter := bson.M{}
|
||
// 1. advicer_id 条件
|
||
if param.AdvicerId != 0 {
|
||
filter["advicerId"] = param.AdvicerId
|
||
}
|
||
|
||
if param.ProjectId != 0 {
|
||
filter["projectId"] = param.ProjectId
|
||
}
|
||
|
||
// 2. _id 条件
|
||
if len(param.Id) != 0 {
|
||
objectID, err := primitive.ObjectIDFromHex(param.Id)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("ID转换失败: %w", err)
|
||
}
|
||
filter["_id"] = objectID
|
||
}
|
||
|
||
cursor, err := a.mongo.Co(a.AdvicerClientMongo).Find(ctx, filter)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
// 遍历结果
|
||
for cursor.Next(ctx) {
|
||
var advicerVersion mongo_model.AdvicerClientItem
|
||
if err := cursor.Decode(&advicerVersion); err != nil {
|
||
return nil, err
|
||
}
|
||
list = append(list, advicerVersion)
|
||
}
|
||
|
||
if err := cursor.Err(); err != nil {
|
||
return nil, err
|
||
}
|
||
return list, err
|
||
}
|
||
|
||
func (a *AdviceClientBiz) Del(ctx context.Context, param *entitys.AdvicerClientDelReq) (err error) {
|
||
filter := bson.M{}
|
||
|
||
if len(param.Id) != 0 {
|
||
objectID, err := primitive.ObjectIDFromHex(param.Id)
|
||
if err != nil {
|
||
return fmt.Errorf("ID转换失败: %w", err)
|
||
}
|
||
filter["_id"] = objectID
|
||
}
|
||
|
||
_, err = a.mongo.Co(a.AdvicerClientMongo).DeleteOne(ctx, filter)
|
||
|
||
return err
|
||
}
|
||
|
||
func (a *AdviceClientBiz) Info(ctx context.Context, param *entitys.AdvicerClientInfoReq) (info mongo_model.AdvicerClientMongo, err error) {
|
||
filter := bson.M{}
|
||
|
||
if len(param.Id) != 0 {
|
||
objectID, err := primitive.ObjectIDFromHex(param.Id)
|
||
if err != nil {
|
||
return info, fmt.Errorf("ID转换失败: %w", err)
|
||
|
||
}
|
||
filter["_id"] = objectID
|
||
}
|
||
|
||
res := a.mongo.Co(a.AdvicerClientMongo).FindOne(ctx, filter)
|
||
if res.Err() != nil {
|
||
return info, res.Err()
|
||
}
|
||
|
||
if err = res.Decode(&info); err != nil {
|
||
return info, err
|
||
}
|
||
return
|
||
}
|
||
|
||
// Bind 客户绑定微信(wxid 用于回调消息关联到该客户)
|
||
func (a *AdviceClientBiz) Bind(ctx context.Context, param *entitys.AdvicerClientBindReq) (err error) {
|
||
if len(param.Id) == 0 {
|
||
return errors.New("ID不能为空")
|
||
}
|
||
if len(param.Wxid) == 0 {
|
||
return errors.New("wxid不能为空")
|
||
}
|
||
objectID, err := primitive.ObjectIDFromHex(param.Id)
|
||
if err != nil {
|
||
return fmt.Errorf("ID转换失败: %w", err)
|
||
}
|
||
set := bson.M{"wxid": param.Wxid, "lastUpdateTime": time.Now()}
|
||
if len(param.AppId) != 0 {
|
||
set["appId"] = param.AppId
|
||
}
|
||
_, err = a.mongo.Co(a.AdvicerClientMongo).UpdateOne(ctx, bson.M{"_id": objectID}, bson.M{"$set": set})
|
||
return err
|
||
}
|
||
|
||
// FindByWxid 按客户微信 wxid 查询客户(回调链按消息来源定位客户)
|
||
func (a *AdviceClientBiz) FindByWxid(ctx context.Context, wxid string) (info mongo_model.AdvicerClientItem, found bool, err error) {
|
||
if len(wxid) == 0 {
|
||
return info, false, errors.New("wxid不能为空")
|
||
}
|
||
res := a.mongo.Co(a.AdvicerClientMongo).FindOne(ctx, bson.M{"wxid": wxid})
|
||
if res.Err() != nil {
|
||
if errors.Is(res.Err(), mongo.ErrNoDocuments) {
|
||
return info, false, nil
|
||
}
|
||
return info, false, res.Err()
|
||
}
|
||
if err = res.Decode(&info); err != nil {
|
||
return info, false, err
|
||
}
|
||
return info, true, nil
|
||
}
|
||
|
||
// TouchInteraction 更新客户互动时间与消息数(回调链针对已绑定客户调用)
|
||
// direction: customer 客户发来(更新 lastClientMsgAt);self/ai 我方回复(更新 lastReplyAt)
|
||
func (a *AdviceClientBiz) TouchInteraction(ctx context.Context, wxid string, direction string) (err error) {
|
||
if len(wxid) == 0 {
|
||
return nil
|
||
}
|
||
now := time.Now()
|
||
set := bson.M{
|
||
"lastContactAt": now,
|
||
}
|
||
if direction == mongo_model.WxMsgDirectionCustomer {
|
||
set["lastClientMsgAt"] = now
|
||
} else {
|
||
set["lastReplyAt"] = now
|
||
}
|
||
update := bson.M{
|
||
"$set": set,
|
||
"$inc": bson.M{"msgCount": 1},
|
||
}
|
||
_, err = a.mongo.Co(a.AdvicerClientMongo).UpdateOne(ctx, bson.M{"wxid": wxid}, update)
|
||
return err
|
||
}
|