| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618 |
- package cust
- import (
- "bytes"
- "context"
- "dashoo.cn/micro/app/model/base"
- "dashoo.cn/micro/app/model/contract"
- server "dashoo.cn/micro/app/service/base"
- "dashoo.cn/micro/app/service/partner"
- "dashoo.cn/opms_libary/myerrors"
- "dashoo.cn/opms_libary/plugin/dingtalk/message"
- "dashoo.cn/opms_libary/request"
- "encoding/base64"
- "encoding/json"
- "fmt"
- "github.com/360EntSecGroup-Skylar/excelize"
- "github.com/gogf/gf/container/garray"
- "github.com/gogf/gf/database/gdb"
- "github.com/gogf/gf/encoding/gjson"
- "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/os/gtime"
- "github.com/gogf/gf/text/gstr"
- "github.com/gogf/gf/util/gconv"
- "github.com/gogf/gf/util/gvalid"
- "github.com/mozillazg/go-pinyin"
- excelizev2 "github.com/xuri/excelize/v2"
- "math"
- "strconv"
- "strings"
- "time"
- "dashoo.cn/micro/app/dao/cust"
- platdao "dashoo.cn/micro/app/dao/plat"
- model "dashoo.cn/micro/app/model/cust"
- workflowModel "dashoo.cn/micro/app/model/workflow"
- "dashoo.cn/micro/app/service"
- )
- type CustomerService struct {
- *service.ContextService
- Dao *cust.CustCustomerDao
- BelongDao *cust.CustCustomerBelongDao
- DynamicsDao *cust.CustCustomerDynamicsDao
- ContactDao *cust.CustCustomerContactDao
- FollowDao *platdao.PlatFollowupDao
- BelongServer *CustomerbelongService
- ContanctServer *CustomercontactService
- }
- var isPublic, noPublic = "10", "20" // 公海,非公海
- var AllocaTion, OperaTion, Receive, Merge = "10", "20", "30", "40" // 10分配20转移30领取40合并
- type OpnType struct {
- OperaTion string
- }
- func NewCustomerService(ctx context.Context) (svc *CustomerService, err error) {
- svc = new(CustomerService)
- if svc.ContextService, err = svc.Init(ctx); err != nil {
- return nil, err
- }
- svc.Dao = cust.NewCustCustomerDao(svc.Tenant)
- svc.BelongDao = cust.NewCustCustomerBelongDao(svc.Tenant)
- svc.DynamicsDao = cust.NewCustCustomerDynamicsDao(svc.Tenant)
- svc.ContactDao = cust.NewCustCustomerContactDao(svc.Tenant)
- svc.FollowDao = platdao.NewPlatFollowupDao(svc.Tenant)
- svc.BelongServer, _ = NewCustomerBelongService(ctx)
- svc.ContanctServer, _ = NewCustomerContactService(ctx)
- return svc, nil
- }
- // GetList 客户列表列表
- func (s *CustomerService) GetList(req *model.CustCustomerSearchReq) (total int, customerList []*model.CustList, err error) {
- Model := s.Dao.FieldsEx(s.Dao.C.DeletedTime)
- if req.IsPublic {
- Model = Model.Where(s.Dao.C.IsPublic, isPublic)
- } else {
- Model = Model.Where(s.Dao.C.IsPublic, noPublic)
- if req.TargetType == "self" {
- Model = Model.Where(s.Dao.C.SalesId, s.CxtUser.Id)
- } else if req.TargetType == "other" {
- Model = Model.Where(s.Dao.C.SalesId, s.DataScope["userIds"]).WhereNot(s.Dao.C.SalesId, s.CxtUser.Id)
- } else {
- Model = Model.DataScope(s.Ctx, "sales_id").Where(s.Dao.C.IsPublic, noPublic)
- }
- }
- //客户名称
- if req.CustName != "" {
- Model = Model.Where(s.Dao.C.CustName+" like ?", "%"+req.CustName+"%")
- }
- //客户编码
- if req.CustCode != "" {
- Model = Model.Where(s.Dao.C.CustCode+" like ?", "%"+req.CustCode+"%")
- }
- //客户行业
- if req.CustIndustry != "" {
- Model = Model.Where(s.Dao.C.CustIndustry, req.CustIndustry)
- }
- //客户级别
- if req.CustLevel != "" {
- Model = Model.Where(s.Dao.C.CustLevel, req.CustLevel)
- }
- //
- //if req.FollowUpDate != "" {
- // Model = Model.Where(s.Dao.C.FollowUpDate+" like ? ", req.FollowUpDate+"%")
- //}
- //省份
- if req.CustProvince != "" {
- Model = Model.Where(s.Dao.C.CustProvince, req.CustProvince)
- }
- //市
- if req.CustCity != "" {
- Model = Model.Where(s.Dao.C.CustCity, req.CustCity)
- }
- //所属销售
- if req.SalesName != "" {
- Model = Model.Where(s.Dao.C.SalesName+" like ?", "%"+req.SalesName+"%")
- }
- // 获取日期区间范围内的记录
- if req.BeginTime != "" && req.EndTime != "" {
- begin := strings.Split(req.BeginTime, " ")[0] + " 00:00:00"
- end := strings.Split(req.EndTime, " ")[0] + " 23:59:59"
- Model = Model.WhereBetween(s.Dao.C.FollowUpDate, begin, end)
- }
- if req.IsRemovePage {
- Model = Model
- } else {
- Model = Model.Page(req.GetPage())
- }
- total, err = Model.Count()
- if err != nil {
- g.Log().Error(err)
- err = myerrors.DbError("获取总行数失败。")
- return
- }
- err = Model.Order("id desc").Scan(&customerList)
- if err != nil {
- g.Log().Error(err)
- return
- }
- return
- }
- func (s *CustomerService) customerCode(province, industry string) (string, error) {
- sequence, err := service.Sequence(s.Dao.DB, "customer_code")
- if err != nil {
- return "", err
- }
- return s.customerProvinceCode(province) + industry + sequence, nil
- }
- func (s *CustomerService) customerProvinceCode(province string) string {
- if province == "重庆市" {
- return "CQ"
- }
- province = strings.Trim(province, "市")
- province = strings.Trim(province, "省")
- province = strings.Trim(province, "特别行政区")
- province = strings.Trim(province, "自治区")
- province = strings.Trim(province, "壮族")
- province = strings.Trim(province, "回族")
- province = strings.Trim(province, "维吾尔")
- pinyinArg := pinyin.NewArgs()
- pinyinArg.Style = pinyin.FIRST_LETTER
- provincePinyin := pinyin.Pinyin(province, pinyinArg)
- provinceFirstletter := []string{}
- for _, i := range provincePinyin {
- provinceFirstletter = append(provinceFirstletter, i[0])
- }
- provinceCode := strings.Join(provinceFirstletter, "")
- provinceCode = strings.ToUpper(provinceCode)
- fmt.Println(provincePinyin, provinceFirstletter, provinceCode)
- return provinceCode
- }
- // Create 创建客户
- func (s *CustomerService) Create(req *model.CustomerAddSeq) (insertId int64, err error) {
- cusTomer := new(model.CustCustomer)
- count, err := s.Dao.Where(s.Dao.C.CustName, req.CustName).Count()
- if err != nil {
- g.Log().Error(err)
- return
- }
- if count > 0 {
- return 0, myerrors.TipsError("该客户信息已存在,不可重复添加")
- }
- if err = gconv.Struct(req, cusTomer); err != nil {
- return
- }
- service.SetCreatedInfo(cusTomer, s.GetCxtUserId(), s.CxtUser.NickName)
- custCode, err := s.customerCode(req.CustProvince, req.CustIndustry)
- if err != nil {
- return 0, err
- }
- cusTomer.CustCode = custCode
- cusTomer.CustStatus = "10"
- roles := s.GetCxtUserRoles()
- isSales := false
- for _, v := range roles {
- if v == "SalesEngineer" || v == "ProductLineManager" { // 销售角色
- isSales = true
- break
- }
- }
- if _, ok := s.DataScope["is_big"]; ok {
- isSales = true
- }
- // 销售角色
- if isSales {
- cusTomer.IsPublic = noPublic
- cusTomer.SalesId = s.GetCxtUserId()
- cusTomer.SalesName = s.CxtUser.NickName
- cusTomer.CustStatus = "30"
- insertId, err = s.Dao.InsertAndGetId(cusTomer)
- if err != nil {
- g.Log().Error(err)
- return 0, err
- }
- err = s.CreateBelong(gconv.Int(insertId))
- return insertId, err
- } else {
- cusTomer.IsPublic = isPublic
- insertId, err = s.Dao.InsertAndGetId(cusTomer)
- if err != nil {
- g.Log().Error(err)
- return 0, err
- }
- }
- return insertId, err
- }
- // CreateBelong 创建客户归属信息
- func (s *CustomerService) CreateBelong(custId int) (err error) {
- belong := new(model.CustomerBelongAddSeq)
- belong.CustId = custId
- belong.SaleName = s.CxtUser.NickName
- belong.OpnType = AllocaTion
- belong.OpnPeople = s.CxtUser.NickName
- err = s.BelongServer.Create(belong)
- if err != nil {
- g.Log().Error(err)
- return
- }
- return
- }
- // 删除客户
- func (s *CustomerService) DeleteByIds(Ids []int64) (err error) {
- customerCount, err := s.Dao.Where(" id in (?)", Ids).Count()
- if err != nil {
- g.Log().Error(err)
- return
- }
- if customerCount == 0 {
- err = myerrors.TipsError("客户信息不存在")
- return
- }
- //删除客户表
- s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
- //客户表
- _, err = s.Dao.TX(tx).Where("id in (?)", Ids).Delete()
- if err != nil {
- g.Log().Error(err)
- return err
- }
- //客户联系人表
- _, err = s.ContactDao.Where("cust_id in (?)", Ids).Delete()
- if err != nil {
- g.Log().Error(err)
- return err
- }
- //客户归属表
- _, err = s.BelongDao.Where("cust_id in (?)", Ids).Delete()
- if err != nil {
- g.Log().Error(err)
- return err
- }
- return nil
- })
- return
- }
- // UpdateById 修改客户
- func (s *CustomerService) UpdateById(req *model.UpdateCustomer) (err error) {
- //判断数据是否存在
- count, err := s.Dao.Where("id = ", req.Id).Count()
- if err != nil {
- g.Log().Error(err)
- return
- }
- if count == 0 {
- return
- }
- //新的客户名字是否存在
- num, err := s.Dao.Where(s.Dao.C.CustName, req.CustName).WhereNot(s.Dao.C.Id, req.Id).Count()
- if err != nil {
- g.Log().Error(err)
- return err
- }
- if num > 0 {
- return myerrors.TipsError(fmt.Sprintf("客户名称[%s]已存在", req.CustName))
- }
- CustomertData := new(model.CustomerAddSeq)
- if err = gconv.Struct(req, CustomertData); err != nil {
- return
- }
- service.SetUpdatedInfo(CustomertData, s.GetCxtUserId(), s.CxtUser.NickName)
- _, err = s.Dao.FieldsEx(s.Dao.C.CreatedTime, s.Dao.C.CreatedBy, s.Dao.C.CreatedName, s.Dao.C.Id, s.Dao.C.CustCode, s.Dao.C.SalesName, s.Dao.C.SalesId).
- WherePri(s.Dao.C.Id, req.Id).Update(CustomertData)
- if err != nil {
- g.Log().Error(err)
- return
- }
- return
- }
- var AssignCustomerRequestProcessCode = "PROC-FE42B2D1-6097-4DE8-8AC5-23541B7D5C8A" // BizCode: 11
- var MoveToPubicRequestProcessCode = "PROC-C030BD3D-74A3-4FE5-9EBA-DF3BA9F8AEF9" // BizCode: 12
- var TransCustomerRequestProcessCode = "PROC-03BE93D3-9A44-43A1-BA6D-D1BB75702542" // BizCode: 13
- // AssignCustomerRequest 领取客户申请
- func (s *CustomerService) AssignCustomerRequest(ctx context.Context, req *model.AssignCustomerReq) error {
- if req.ApplyRemark == "" {
- return myerrors.TipsError("请输入申请说明")
- }
- data, err := s.Dao.Where("id in (?)", req.Ids).LockShared().All()
- if err != nil {
- return err
- }
- if len(data) == 0 {
- return myerrors.TipsError("领取用户不能为空")
- }
- for _, v := range data {
- if v.CustStatus != "10" {
- return myerrors.TipsError(fmt.Sprintf("客户: %s 已被领取", v.CustName))
- }
- if v.CustProvince == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的所在省信息", v.CustName))
- }
- if v.CustCity == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的所在市信息", v.CustName))
- }
- if v.CustIndustry == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的客户类型信息", v.CustName))
- }
- }
- city := []string{}
- cityData := s.DataScope["cust_city_id"]
- if cityData != nil {
- for _, i := range cityData.([]interface{}) {
- city = append(city, i.(string))
- }
- }
- fmt.Println(city)
- cust := []*model.CustCustomer{}
- noNeedApprovalCust := []*model.CustCustomer{}
- noNeedApprovalCustId := []int64{}
- for _, v := range data {
- if service.StringSlicecontains(city, strconv.Itoa(v.CustCityId)) {
- noNeedApprovalCust = append(noNeedApprovalCust, v)
- noNeedApprovalCustId = append(noNeedApprovalCustId, int64(v.Id))
- } else {
- cust = append(cust, v)
- }
- }
- if len(noNeedApprovalCustId) != 0 {
- err = s.ChangeCustBelong(noNeedApprovalCustId, req.SalesId, req.SalesName)
- if err != nil {
- return err
- }
- req.Receive = AllocaTion
- err = s.BatchCreatebelong(data, req)
- if err != nil {
- return err
- }
- err = s.CreateDynamics("领取客户", &model.AssignCustomerReq{
- Ids: noNeedApprovalCustId,
- SalesId: req.SalesId,
- SalesName: req.SalesName,
- Remark: "",
- Receive: Receive,
- }, noNeedApprovalCustId...)
- if err != nil {
- return err
- }
- }
- userId := s.GetCxtUserId()
- userName := s.GetCxtUserName()
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- err = s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
- for _, u := range cust {
- _, err = s.Dao.TX(tx).Where("id = ?", u.Id).Data(map[string]interface{}{
- "is_public": isPublic,
- "cust_status": "10",
- }).Update()
- if err != nil {
- return err
- }
- err = s.ChangeCustBelong([]int64{int64(u.Id)}, int64(userId), userName)
- if err != nil {
- return err
- }
- err = s.BatchCreatebelong([]*model.CustCustomer{u}, &model.AssignCustomerReq{
- Ids: []int64{int64(u.Id)},
- SalesId: int64(userId),
- SalesName: userName,
- Remark: "",
- Receive: Receive,
- })
- if err != nil {
- return err
- }
- err = s.CreateDynamics("领取客户", map[string]interface{}{
- "userId": userId,
- "custId": u.Id,
- }, int64(u.Id))
- if err != nil {
- return err
- }
- }
- return nil
- })
- if err != nil {
- return err
- }
- return nil
- }
- func (s *CustomerService) AssignCustomerRequestApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
- remark := map[string]string{}
- err := json.Unmarshal([]byte(flow.Remark), &remark)
- if err != nil {
- return err
- }
- userName := remark["applyUserName"]
- bizCode := strings.Split(flow.BizCode, ":")
- if len(bizCode) != 2 {
- return fmt.Errorf("客户领取审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- custId, err := strconv.Atoi(bizCode[0])
- if err != nil {
- return fmt.Errorf("客户领取审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- userId, err := strconv.Atoi(bizCode[1])
- if err != nil {
- return fmt.Errorf("客户领取审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- cust, err := s.Dao.Where("id = ?", custId).One()
- if err != nil {
- return err
- }
- if cust == nil {
- return fmt.Errorf("客户不存在:%s Id: %d", flow.BizCode, flow.Id)
- }
- if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
- return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
- }
- if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
- return fmt.Errorf("无法识别的 Result :%s", msg.Result)
- }
- if msg.ProcessType == "terminate" {
- _, err = s.Dao.Where("id = ?", custId).Data(map[string]interface{}{
- "is_public": isPublic,
- "cust_status": "10",
- }).Update()
- return err
- }
- pass := msg.Result == "agree"
- if !pass {
- _, err = s.Dao.Where("id = ?", custId).Data(map[string]interface{}{
- "is_public": isPublic,
- "cust_status": "10",
- }).Update()
- return err
- }
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- err = s.ChangeCustBelong([]int64{int64(custId)}, int64(userId), remark["applyUserName"])
- if err != nil {
- return err
- }
- err = s.BatchCreatebelong([]*model.CustCustomer{cust}, &model.AssignCustomerReq{
- Ids: []int64{int64(custId)},
- SalesId: int64(userId),
- SalesName: userName,
- Remark: "",
- Receive: Receive,
- })
- if err != nil {
- return err
- }
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- return s.CreateDynamics("领取客户", map[string]interface{}{
- "userId": userId,
- "custId": cust.Id,
- }, int64(cust.Id))
- }
- // 移回公海
- func (s *CustomerService) MoveToPublicRequest(ctx context.Context, req *model.MoveToPubicRep) error {
- if req.Remark == "" {
- return myerrors.TipsError("请输入移回原因")
- }
- data, err := s.Dao.Where("id in (?)", req.Ids).All()
- if err != nil {
- return err
- }
- if len(data) == 0 {
- return myerrors.TipsError("移回用户不能为空")
- }
- for _, v := range data {
- if v.CustStatus == "10" {
- return myerrors.TipsError(fmt.Sprintf("客户: %s 已被移回公海", v.CustName))
- }
- if v.CustStatus == "20" {
- return myerrors.TipsError(fmt.Sprintf("客户: %s 正在等待审批", v.CustName))
- }
- if v.CustProvince == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的所在省信息", v.CustName))
- }
- if v.CustCity == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的所在市信息", v.CustName))
- }
- if v.CustIndustry == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的客户类型信息", v.CustName))
- }
- }
- userId := s.GetCxtUserId()
- userName := s.GetCxtUserName()
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- err = s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
- for _, u := range data {
- //更新客户信息
- _, err = s.Dao.Where("id = ?", u.Id).Data(map[string]interface{}{
- "cust_status": "10",
- "is_public": isPublic,
- "sales_id": 0,
- "dept_id": 0,
- "dept_name": "",
- "updated_time": gtime.Now(),
- }).Update()
- if err != nil {
- return err
- }
- //更新销售归属表结束时间
- _, err = s.BelongDao.TX(tx).Data(g.Map{
- "end_date": gtime.Now(),
- }).Where("cust_id = ?", u.Id).Update()
- if err != nil {
- return err
- }
- err = s.CreateDynamics("移入公海", map[string]interface{}{
- "userId": userId,
- "custId": u.Id,
- }, int64(u.Id))
- if err != nil {
- return err
- }
- }
- return nil
- })
- if err != nil {
- return err
- }
- return nil
- }
- // 移入公海回调
- func (s *CustomerService) MoveToPublicApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
- remark := map[string]string{}
- err := json.Unmarshal([]byte(flow.Remark), &remark)
- if err != nil {
- return err
- }
- userName := remark["applyUserName"]
- bizCode := strings.Split(flow.BizCode, ":")
- if len(bizCode) != 2 {
- return fmt.Errorf("客户移回审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- custId, err := strconv.Atoi(bizCode[0])
- if err != nil {
- return fmt.Errorf("客户移回审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- userId, err := strconv.Atoi(bizCode[1])
- if err != nil {
- return fmt.Errorf("客户移回审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- cust, err := s.Dao.Where("id = ?", custId).One()
- if err != nil {
- return err
- }
- if cust == nil {
- return fmt.Errorf("客户不存在:%s Id: %d", flow.BizCode, flow.Id)
- }
- if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
- return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
- }
- if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
- return fmt.Errorf("无法识别的 Result :%s", msg.Result)
- }
- if msg.ProcessType == "terminate" {
- _, err = s.Dao.Where("id = ?", custId).Data(map[string]interface{}{
- "cust_status": "30",
- }).Update()
- return err
- }
- pass := msg.Result == "agree"
- if !pass {
- _, err = s.Dao.Where("id = ?", custId).Data(map[string]interface{}{
- "cust_status": "30",
- }).Update()
- return err
- }
- now := gtime.Now()
- err = s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
- //更新客户信息
- _, err = s.Dao.TX(tx).Data(g.Map{
- "cust_status": "10",
- "is_public": isPublic,
- "sales_id": 0,
- "dept_id": 0,
- "dept_name": "",
- "updated_time": now,
- }).Where("id = ?", cust.Id).Update()
- if err != nil {
- return err
- }
- //更新销售归属表结束时间
- _, err = s.BelongDao.TX(tx).Data(g.Map{
- "end_date": now,
- }).Where("cust_id = ?", cust.Id).Update()
- if err != nil {
- return err
- }
- return nil
- })
- if err != nil {
- return err
- }
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- return s.CreateDynamics("移入公海", map[string]interface{}{
- "userId": userId,
- "custId": cust.Id,
- }, int64(cust.Id))
- }
- // SysAdminTransCustomer 系统管理员转移客户(不走审批)
- func (s *CustomerService) SysAdminTransCustomer(ctx context.Context, req *model.AssignCustomerReq) error {
- // 校验用户是否有修改权限
- arr := garray.NewStrArrayFrom(s.CxtUser.Roles, true)
- if !arr.Contains("SysAdmin") {
- return myerrors.TipsError("权限不足")
- }
- if req.Remark == "" {
- return myerrors.TipsError("请输入转移原因")
- }
- customerList, err := s.Dao.WherePri(req.Ids).Where(s.Dao.C.IsPublic, "20").All()
- if err != nil {
- return err
- }
- if len(customerList) == 0 {
- return myerrors.TipsError("转移客户不能为空")
- }
- var customerIds []int64
- for _, item := range customerList {
- customerIds = append(customerIds, int64(item.Id))
- }
- err = s.ChangeCustBelong(customerIds, req.SalesId, req.SalesName)
- if err != nil {
- return err
- }
- err = s.BatchCreatebelong(customerList, &model.AssignCustomerReq{
- Ids: customerIds,
- SalesId: req.SalesId,
- SalesName: req.SalesName,
- Remark: req.Remark,
- Receive: OperaTion,
- })
- if err != nil {
- return err
- }
- s.CreateDynamics("转移客户", map[string]interface{}{
- "toUserId": req.SalesId,
- "toUserNickName": req.SalesName,
- "remark": "系统管理员转移客户",
- }, customerIds...)
- return nil
- }
- // 转移客户
- func (s *CustomerService) TransCustomerRequest(ctx context.Context, req *model.AssignCustomerReq) error {
- if req.Remark == "" {
- return myerrors.TipsError("请输入转移原因")
- }
- data, err := s.Dao.Where("id in (?)", req.Ids).All()
- if err != nil {
- return err
- }
- if len(data) == 0 {
- return myerrors.TipsError("转移用户不能为空")
- }
- for _, v := range data {
- if v.CustStatus == "10" {
- return myerrors.TipsError(fmt.Sprintf("客户: %s 为公海客户", v.CustName))
- }
- if v.CustStatus == "20" {
- return myerrors.TipsError(fmt.Sprintf("客户: %s 正在等待审批", v.CustName))
- }
- if v.CustProvince == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的所在省信息", v.CustName))
- }
- if v.CustCity == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的所在市信息", v.CustName))
- }
- if v.CustIndustry == "" {
- return myerrors.TipsError(fmt.Sprintf("请先完善客户: %s 的客户类型信息", v.CustName))
- }
- }
- userId := s.GetCxtUserId()
- userName := s.GetCxtUserName()
- toUserId := req.SalesId
- toUserName := req.SalesName
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- err = s.Dao.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
- for _, u := range data {
- _, err = s.Dao.Where("id = ?", u.Id).Data(map[string]interface{}{
- "cust_status": "20",
- }).Update()
- if err != nil {
- return err
- }
- err = s.ChangeCustBelong([]int64{int64(u.Id)}, toUserId, toUserName)
- if err != nil {
- return err
- }
- err = s.BatchCreatebelong([]*model.CustCustomer{u}, &model.AssignCustomerReq{
- Ids: []int64{int64(u.Id)},
- SalesId: toUserId,
- SalesName: toUserName,
- Remark: "",
- Receive: OperaTion,
- })
- if err != nil {
- return err
- }
- err = s.CreateDynamics("转移客户", map[string]interface{}{
- "userId": userId,
- "custId": u.Id,
- "toUserId": toUserId,
- }, int64(u.Id))
- if err != nil {
- return err
- }
- }
- return nil
- })
- if err != nil {
- return err
- }
- return nil
- }
- // 转移客户回调
- func (s *CustomerService) TransCustomerApproval(flow *workflowModel.PlatWorkflow, msg *message.MixMessage) error {
- remark := map[string]string{}
- err := json.Unmarshal([]byte(flow.Remark), &remark)
- if err != nil {
- return err
- }
- userName := remark["applyUserName"]
- toUserName := remark["toUserName"]
- bizCode := strings.Split(flow.BizCode, ":")
- if len(bizCode) != 3 {
- return fmt.Errorf("转移客户审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- custId, err := strconv.Atoi(bizCode[0])
- if err != nil {
- return fmt.Errorf("转移客户审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- userId, err := strconv.Atoi(bizCode[1])
- if err != nil {
- return fmt.Errorf("转移客户审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- toUserId, err := strconv.Atoi(bizCode[2])
- if err != nil {
- return fmt.Errorf("转移客户审批 bizCode 不合法:%s Id: %d", flow.BizCode, flow.Id)
- }
- // user, err := s.UserDao.Where("id = ?", userId).One()
- // if err != nil {
- // return err
- // }
- // if user == nil {
- // return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
- // }
- // toUser, err := s.UserDao.Where("id = ?", toUserId).One()
- // if err != nil {
- // return err
- // }
- // if toUser == nil {
- // return fmt.Errorf("用户不存在:%s Id: %d", flow.BizCode, flow.Id)
- // }
- cust, err := s.Dao.Where("id = ?", custId).One()
- if err != nil {
- return err
- }
- if cust == nil {
- return fmt.Errorf("客户不存在:%s Id: %d", flow.BizCode, flow.Id)
- }
- if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
- return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
- }
- if msg.Result != "agree" && msg.Result != "refuse" && msg.Result != "" {
- return fmt.Errorf("无法识别的 Result :%s", msg.Result)
- }
- if msg.ProcessType == "terminate" {
- _, err = s.Dao.Where("id = ?", custId).Data(map[string]interface{}{
- "cust_status": "30",
- }).Update()
- return err
- }
- pass := msg.Result == "agree"
- if !pass {
- _, err = s.Dao.Where("id = ?", custId).Data(map[string]interface{}{
- "cust_status": "30",
- }).Update()
- return err
- }
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- err = s.ChangeCustBelong([]int64{int64(custId)}, int64(toUserId), toUserName)
- if err != nil {
- return err
- }
- err = s.BatchCreatebelong([]*model.CustCustomer{cust}, &model.AssignCustomerReq{
- Ids: []int64{int64(custId)},
- SalesId: int64(toUserId),
- SalesName: toUserName,
- Remark: "",
- Receive: OperaTion,
- })
- if err != nil {
- return err
- }
- s.CxtUser = &request.UserInfo{Id: userId, UserName: userName}
- return s.CreateDynamics("转移客户", map[string]interface{}{
- "userId": userId,
- "custId": cust.Id,
- "toUserId": toUserId,
- }, int64(cust.Id))
- }
- // AssignCustomer 分配客户
- func (s *CustomerService) AssignCustomer(ctx context.Context, req *model.AssignCustomerReq) (err error) {
- if req.Receive != "" {
- return s.AssignCustomerRequest(ctx, req)
- }
- data, err := s.Dao.Where("id in (?)", req.Ids).LockShared().All()
- if err != nil {
- g.Log().Error(err)
- return
- }
- if len(data) == 0 {
- return myerrors.TipsError("无可分配客户")
- }
- customerNames := ""
- for _, v := range data {
- if v.SalesId != 0 {
- return myerrors.TipsError(fmt.Sprintf("客户名称[%s]已被领取或分配", v.CustName))
- }
- if customerNames == "" {
- customerNames = v.CustName
- } else {
- customerNames += "、" + v.CustName
- }
- }
- err = s.ChangeCustBelong(req.Ids, req.SalesId, req.SalesName)
- if err != nil {
- return
- }
- req.Receive = AllocaTion
- err = s.BatchCreatebelong(data, req)
- if err != nil {
- return err
- }
- // 消息提醒
- msg := g.MapStrStr{
- "msgTitle": "公海客户分配提醒",
- "msgContent": fmt.Sprintf("客户%v已分配给您,请前往查看", customerNames),
- "msgType": "20",
- "recvUserIds": gconv.String(req.SalesId),
- "msgStatus": "10",
- "sendType": "30",
- }
- if err := service.CreateSystemMessage(msg); err != nil {
- g.Log().Error("公海客户分配提醒异常:", err)
- }
- return s.CreateDynamics("分配客户", req, req.Ids...)
- }
- // GetEntityById 客户详情
- func (s *CustomerService) GetEntityById(Ids []int64) (entityInfo []*model.CustList, err error) {
- Model := s.Dao //
- err = Model.Where(" id in (?)", Ids).Scan(&entityInfo)
- if err != nil {
- g.Log().Error(err)
- return
- }
- return
- }
- // GetCustNameIsExist 判断客户名称是否存在
- func (s *CustomerService) GetCustNameIsExist(req *model.IsExistsCustName) (exist bool, err error) {
- custDao := s.Dao.M
- if req.Id > 0 {
- custDao = custDao.Where("cust_name = ", req.CustName).WhereNot(" id ", req.Id)
- } else {
- custDao = custDao.Where("cust_name = ", req.CustName)
- }
- count, err := custDao.Count()
- if err != nil {
- g.Log().Error(err)
- return
- }
- exist = false
- if count > 0 {
- exist = true
- }
- return
- }
- // CustAbstract 客户摘要
- func (s *CustomerService) CustAbstract(Id int64) (followInfo *model.Follow, err error) {
- count, err := s.FollowDao.Where(s.FollowDao.C.CustId, Id).Count()
- if err != nil {
- g.Log().Error(err)
- return
- }
- followInfo = new(model.Follow)
- followInfo.FollowCount = count
- followTime, err := s.Dao.Fields(s.Dao.C.FollowUpDate, s.Dao.C.CreatedTime).FindOne(Id)
- if err != nil {
- g.Log().Error(err)
- return
- }
- if followTime == nil {
- err = myerrors.TipsError("获取客户信息不存在")
- return
- }
- now := gtime.Now()
- var difference time.Duration
- if followTime.FollowUpDate.IsZero() {
- difference = now.Sub(gtime.New(followTime.CreatedTime))
- } else {
- difference = now.Sub(gtime.New(followTime.FollowUpDate))
- }
- days := difference.Hours() / 24
- if days < 0 {
- followInfo.NotFollowDay = 0
- } else {
- followInfo.NotFollowDay = int(math.Floor(days))
- }
- return
- }
- // // TransCustomer 转移客户
- // func (s *CustomerService) TransCustomer(req *model.AssignCustomerReq) (err error) {
- // data, err := s.Dao.Fields("sales_id,sales_name,id").Where("id in (?)", req.Ids).All()
- // if err != nil {
- // g.Log().Error(err)
- // return err
- // }
- // if len(data) == 0 {
- // return myerrors.TipsError("数据不存在")
- // }
- // err = s.ChangeCustBelong(req.Ids, req.SalesId, req.SalesName)
- // if err != nil {
- // g.Log().Error(err)
- // return
- // }
- // req.Receive = OperaTion
- // s.BatchCreatebelong(data, req)
- // return
- // }
- // ChangeCustBelong 变更客户所属关系
- func (s *CustomerService) ChangeCustBelong(Ids []int64, salesId int64, salesName string) (err error) {
- _, err = s.Dao.Data(g.Map{
- "cust_status": "30",
- "sales_id": salesId,
- "is_public": noPublic,
- "sales_name": salesName,
- "updated_by": s.GetCxtUserId(),
- "updated_name": s.GetCxtUserName(),
- "updated_time": gtime.Now(),
- }).Where("id in (?)", Ids).Update()
- return err
- }
- // CreateDynamics 创建客户动态信息
- func (s *CustomerService) CreateDynamics(opnTpye string, content interface{}, ids ...int64) (err error) {
- datas := make([]*model.CustCustomerDynamics, 0)
- for _, id := range ids {
- dynameics := new(model.CustCustomerDynamics)
- dynameics.CustId = int(id)
- dynameics.OpnPeopleId = s.GetCxtUserId()
- dynameics.OpnPeople = s.GetCxtUserName()
- dynameics.OpnDate = gtime.Now()
- dynameics.OpnType = opnTpye
- v, _ := gjson.Encode(content)
- dynameics.OpnContent = gconv.String(v)
- service.SetCreatedInfo(dynameics, s.GetCxtUserId(), s.GetCxtUserName())
- datas = append(datas, dynameics)
- }
- _, err = s.DynamicsDao.Insert(datas)
- if err != nil {
- g.Log().Error(err)
- return
- }
- return
- }
- // GetDynamicsList 客户动态
- func (s *CustomerService) GetDynamicsList(req *model.CustomerDynameicsReq) (total int, result []interface{}, err error) {
- total, err = s.DynamicsDao.Where("cust_id = ", req.CustId).Count()
- if err != nil {
- g.Log().Error(err)
- return
- }
- dynamics := []*model.CustomerDynameicsRep{}
- err = s.DynamicsDao.Where("cust_id = ", req.CustId).Order("created_time desc").Scan(&dynamics)
- if err != nil {
- g.Log().Error(err)
- return
- }
- dynamicsList := make(map[string][]*model.CustomerDynameicsRep)
- for _, v := range dynamics {
- opnDate := gtime.New(v.OpnDate).Format("Y-m-d")
- dynamicsList[opnDate] = append(dynamicsList[opnDate], &model.CustomerDynameicsRep{
- OpnPeople: v.OpnPeople,
- OpnDate: v.OpnDate,
- OpnType: v.OpnType,
- OpnContent: v.OpnContent,
- })
- }
- result = append(result, dynamicsList)
- return
- }
- // MergeCustomer 合并客户
- func (s *CustomerService) MergeCustomer(req *model.MergeCustomerRep) (err error) {
- //当前目标客户是否存在并取出合并前的销售
- customer, err := s.Dao.Where("id = ", req.Id).One()
- if err != nil {
- g.Log().Error(err)
- return
- }
- if customer == nil {
- return myerrors.TipsError("该客户不存在")
- }
- _, err = s.ContactDao.Where(" cust_id in (?)", req.ChooseId).Delete()
- if err != nil {
- g.Log().Error(err)
- return
- }
- CustomertData := new(model.CustomerAddSeq)
- if err = gconv.Struct(req, CustomertData); err != nil {
- g.Log().Error(err)
- return
- }
- service.SetUpdatedInfo(CustomertData, s.GetCxtUserId(), s.GetCxtUserName())
- _, err = s.Dao.FieldsEx(s.Dao.C.CreatedTime, s.Dao.C.CreatedBy,
- s.Dao.C.CreatedName, s.Dao.C.Id,
- s.Dao.C.CustCode).WherePri(s.Dao.C.Id, req.Id).Update(CustomertData)
- if err != nil {
- g.Log().Error(err)
- return
- }
- //删除被合并的客户信息
- _, err = s.Dao.Where(" id in (?)", req.ChooseId).Delete()
- if err != nil {
- g.Log().Error(err)
- return
- }
- //删除 所选客户销售联系人
- _, err = s.BelongDao.Where(" cust_id in (?)", req.ChooseId).Delete()
- if err != nil {
- g.Log().Error(err)
- return
- }
- //插入一条合并成功的归属记录
- //更新销售归属表销售结束时间
- _, err = s.BelongDao.Data(
- g.Map{
- "updated_by": s.GetCxtUserId(),
- "updated_name": s.GetCxtUserName(),
- "end_date": gtime.Now(),
- }).WhereIn(s.BelongDao.C.CustId, req.Id).Update()
- if err != nil {
- g.Log().Error(err)
- return
- }
- req.CustomerBelongAddSeq.CustId = int(req.Id)
- req.CustomerBelongAddSeq.OpnType = Merge
- req.CustomerBelongAddSeq.OpnPeople = s.GetCxtUserName()
- req.CustomerBelongAddSeq.OrigSaleName = customer.SalesName
- req.CustomerBelongAddSeq.SaleName = req.SalesName
- s.BelongServer.Create(req.CustomerBelongAddSeq)
- return
- }
- // CreateContact 联系人(合并)预留
- func (s *CustomerService) CreateContact(Ids []int64, req *model.CustCustomerContactSeq) (err error) {
- _, err = s.ContactDao.Where(" cust_id in (?)", Ids).Delete()
- if err != nil {
- g.Log().Error(err)
- return
- }
- s.ContanctServer.Create(req)
- return
- }
- // BatchCreatebelong 批量插入客户归属记录表
- func (s *CustomerService) BatchCreatebelong(rep []*model.CustCustomer, req *model.AssignCustomerReq, n ...interface{}) (err error) {
- //更新销售归属表销售结束时间
- _, err = s.BelongDao.Data(
- g.Map{
- "updated_by": s.GetCxtUserId(),
- "updated_name": s.GetCxtUserName(),
- "end_date": gtime.Now(),
- }).WhereIn(s.BelongDao.C.CustId, req.Ids).Update()
- if err != nil {
- return err
- }
- var belongData []*model.CustCustomerBelong
- userName := s.GetCxtUserName()
- for _, v := range rep {
- orig_sale_name := v.SalesName
- belong := new(model.CustCustomerBelong)
- belong.CustId = v.Id
- belong.SaleName = req.SalesName
- belong.OrigSaleName = orig_sale_name
- belong.OpnType = req.Receive
- belong.OpnPeople = userName
- belong.CreatedName = userName
- belong.StartDate = gtime.Now() //新增开始时间
- belong.OpnDatetime = gtime.Now()
- belong.Remark = req.Remark
- belong.CreatedBy = s.GetCxtUserId()
- belongData = append(belongData, belong)
- }
- _, err = s.BelongDao.Insert(belongData)
- return err
- }
- // 导出数据
- func (s *CustomerService) Export(ctx context.Context, req *model.CustCustomerExport) (content *model.CustExport, err error) {
- var con model.CustExport
- req.IsRemovePage = true // 去掉分页标识
- total, data, err := s.GetList(&req.CustCustomerSearchReq)
- if err != nil {
- return
- }
- cusType, err := service.GetDictDataByType(ctx, "cust_idy")
- if err != nil {
- return nil, err
- }
- f := excelize.NewFile()
- index := f.NewSheet("Sheet1")
- for index, item := range req.Columns {
- sheetPosition := service.Div(index+1) + "1"
- f.SetCellValue("Sheet1", sheetPosition, item)
- }
- if total > 0 {
- for ck, item := range data {
- for index, v := range req.Columns {
- if v == "客户编码" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustCode)
- }
- if v == "客户名称" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustName)
- }
- if v == "助记名" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.AbbrName)
- }
- if v == "助记名" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.AbbrName)
- }
- if v == "所在地区" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustLocation)
- }
- if v == "客户类型" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), cusType[item.CustIndustry])
- }
- if v == "客户级别" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustLevel)
- }
- if v == "客户状态" {
- var CustStatus string
- CustStatus = "正常"
- if item.CustStatus != "10" {
- CustStatus = "异常"
- }
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), CustStatus)
- }
- if v == "创建人" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CreatedName)
- }
- if v == "最后跟进时间" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.FollowUpDate)
- }
- if v == "创建时间" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CreatedTime)
- }
- if v == "所在省" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustProvince)
- }
- if v == "所在市" {
- f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustCity)
- }
- }
- }
- }
- f.SetActiveSheet(index)
- var buffer *bytes.Buffer
- buffer, _ = f.WriteToBuffer()
- con.Content = buffer.Bytes()
- return &con, err
- }
- func reverseMap(originalMap map[string]string) map[string]string {
- reversedMap := make(map[string]string)
- for key, value := range originalMap {
- reversedMap[value] = key
- }
- return reversedMap
- }
- var contactExcelHeader = []partner.ExcelHeader{
- {Name: "*客户名称", Width: 30},
- {Name: "助计名", Width: 30},
- {Name: "*客户类型", Width: 30},
- {Name: "*客户来源", Width: 30},
- {Name: "所在省", Width: 30},
- {Name: "所在市", Width: 30},
- {Name: "所在区县", Width: 30},
- {Name: "详细地址", Width: 30},
- {Name: "招标关键字(以逗号分隔)", Width: 40},
- {Name: "备注", Width: 30},
- {Name: "*联系人姓名", Width: 30},
- {Name: "*联系人性别", Width: 30},
- {Name: "*联系人电话", Width: 30},
- {Name: "联系人微信", Width: 30},
- {Name: "联系人邮箱", Width: 30},
- {Name: "联系人部门", Width: 30},
- {Name: "*联系人职位", Width: 30},
- {Name: "联系人办公地点", Width: 30},
- {Name: "*关键决策人(是/否)", Width: 30},
- {Name: "联系人备注", Width: 30},
- }
- var contactFailedExcelHeader = []partner.ExcelHeader{
- {Name: "*客户名称", Width: 30},
- {Name: "助计名", Width: 30},
- {Name: "*客户类型", Width: 30},
- {Name: "*客户来源", Width: 30},
- {Name: "所在省", Width: 30},
- {Name: "所在市", Width: 30},
- {Name: "所在区县", Width: 30},
- {Name: "详细地址", Width: 30},
- {Name: "招标关键字(以逗号分隔)", Width: 40},
- {Name: "备注", Width: 30},
- {Name: "*联系人姓名", Width: 30},
- {Name: "*联系人性别", Width: 30},
- {Name: "*联系人电话", Width: 30},
- {Name: "联系人微信", Width: 30},
- {Name: "联系人邮箱", Width: 30},
- {Name: "联系人部门", Width: 30},
- {Name: "*联系人职位", Width: 30},
- {Name: "联系人办公地点", Width: 30},
- {Name: "*关键决策人(是/否)", Width: 30},
- {Name: "联系人备注", Width: 30},
- {Name: "失败原因", Width: 30},
- }
- func ExcelTemplate() (*excelizev2.File, error) {
- tempData := [][]string{
- {
- "张三", "张三(备注)", "医院", "经销商", "北京市", "北京市", "朝阳区", "ffff", "20387,生物样本库", "备注",
- "李四", "男", "18000000000", "weixin", "abc@163.com", "部门", "职务", "办公地点", "否", "联系人备注",
- },
- }
- excel, err := partner.NewExcel(contactExcelHeader, tempData)
- if err != nil {
- return nil, err
- }
- return excel, nil
- }
- // Create 导入客户
- func (s *CustomerService) Import(ctx context.Context, req *contract.ExcelImportReq) (err error, faildCount int, faildData string) {
- validErr := gvalid.CheckStruct(ctx, req, nil)
- if validErr != nil {
- return myerrors.TipsError(validErr.Current().Error()), 0, ""
- }
- // 下载文件
- buf, err := partner.DownFile(req.ExcelUrl)
- if err != nil {
- return myerrors.TipsError(fmt.Sprintf("下载 excel 异常 %s", err.Error())), 0, ""
- }
- // 解析excel
- excelData, err := s.parseExcel(buf)
- if err != nil {
- return myerrors.TipsError(fmt.Sprintf("解析 excel 异常 %s", err.Error())), 0, ""
- }
- //客户类型
- idyMap, err := service.GetDictDataByType(ctx, "cust_idy")
- if err != nil {
- return err, 0, ""
- }
- idyMap = reverseMap(idyMap)
- //客户来源
- sourceMap, err := service.GetDictDataByType(ctx, "cust_source")
- if err != nil {
- return err, 0, ""
- }
- sourceMap = reverseMap(sourceMap)
- //关键字
- keywordsMap, err := service.GetDictDataByType(ctx, "customer_bidding_keywords")
- if err != nil {
- return err, 0, ""
- }
- keywordsMap = reverseMap(keywordsMap)
- svc, err := server.NewDistrictService(ctx)
- treeList, err := svc.GetProvincesList(0)
- contactService, err := NewCustomerContactService(ctx)
- if err != nil {
- return err, 0, ""
- }
- CustomerService, err := NewCustomerService(ctx)
- if err != nil {
- return err, 0, ""
- }
- yesOrNoMap := map[string]string{
- "是": "10",
- "否": "20",
- }
- genderMap := map[string]string{
- "男": "10",
- "女": "20",
- }
- failedList := make([]*model.CustomerAddImport, 0)
- e := s.Dao.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
- for _, data := range excelData {
- var province *base.ProvincesTree
- var city *base.ProvincesTree
- var region *base.ProvincesTree
- keywords := []string{}
- data.Keyword = gstr.Trim(data.Keyword)
- if data.Keyword != "" && data.Keyword != "无" && data.Keyword != "-" {
- keywords = strings.Split(data.Keyword, ",")
- for _, keyword := range keywords {
- if _, ok := keywordsMap[keyword]; !ok {
- data.FailedReason = fmt.Sprintf("关键字 %s 不存在", keyword)
- //return myerrors.TipsError(fmt.Sprintf("关键字 %s 不存在", keyword))
- }
- }
- if data.FailedReason != "" {
- failedList = append(failedList, data)
- continue
- }
- }
- if data.CustProvince == "" {
- data.FailedReason = "客户省份不能为空"
- failedList = append(failedList, data)
- continue
- //return myerrors.TipsError("客户省份不能为空")
- }
- for _, tree := range treeList {
- if tree.DistName == data.CustProvince {
- province = tree
- if data.CustCity != "" && province.Children != nil {
- for _, cityData := range province.Children {
- if cityData.DistName == data.CustCity {
- city = cityData
- if data.CustRegion != "" && city.Children != nil {
- for _, RegionData := range cityData.Children {
- if RegionData.DistName == data.CustRegion {
- region = RegionData
- }
- }
- }
- }
- }
- }
- }
- }
- if (province == nil) || (city == nil && data.CustCity != "") || (region == nil && data.CustRegion != "") {
- data.FailedReason = "省市区填写错误,请检查后重试"
- failedList = append(failedList, data)
- continue
- //return myerrors.TipsError("客户省份不能为空")
- //return myerrors.TipsError("省市区填写错误,请检查后重试")
- }
- if idyMap[data.CustIndustry] == "" {
- data.FailedReason = "客户类型填写错误,请检查后重试"
- failedList = append(failedList, data)
- continue
- }
- if sourceMap[data.CustSource] == "" {
- data.FailedReason = "客户来源填写错误,请检查后重试"
- failedList = append(failedList, data)
- continue
- }
- insertCustomer := &model.CustomerAddSeq{
- CustName: data.CustName,
- AbbrName: data.AbbrName,
- CustAddress: data.CustAddress,
- CustProvinceId: province.Id,
- CustProvince: data.CustProvince,
- CustCityId: city.Id,
- CustCity: data.CustCity,
- CustRegionId: region.Id,
- CustRegion: data.CustRegion,
- CustIndustry: idyMap[data.CustIndustry],
- CustSource: sourceMap[data.CustSource],
- CustDistCode: province.Id,
- Remark: data.Remark,
- Keyword: keywords,
- }
- id, err := s.Create(insertCustomer)
- if err != nil {
- if err.Error() == "该客户信息已存在,不可重复添加" {
- g.Log(fmt.Sprintf("[%s]%s", data.CustName, "该客户信息已存在,不可重复添加"))
- g.Log().Error(err)
- data.FailedReason = fmt.Sprintf("[%s]%s", data.CustName, "该客户信息已存在,不可重复添加")
- failedList = append(failedList, data)
- continue
- }
- g.Log().Error(err)
- //return myerrors.TipsError(fmt.Sprintf("[%s]%s", data.CustName, "数据有误,请联系管理员"))
- }
- s.CreateDynamics("创建客户", req, id)
- data.CuctName = gstr.Trim(data.CuctName)
- if data.CuctName != "无" && data.CuctName != "" {
- seq := model.CustCustomerContactSeq{
- CustId: int(id),
- CuctName: data.CuctName,
- CuctGender: genderMap[data.CuctGender],
- Telephone: data.Telephone,
- Wechat: data.Wechat,
- Email: data.Email,
- Dept: data.Dept,
- Postion: data.Postion,
- OfficeLocation: data.OfficeLocation,
- IsDecision: yesOrNoMap[data.IsDecision],
- Remark: data.ContactRemark,
- }
- err = contactService.Create(&seq)
- if err != nil {
- data.FailedReason = "添加联系人 验证失败"
- failedList = append(failedList, data)
- continue
- //return err
- }
- CustomerService.CreateDynamics("创建联系人", req, gconv.Int64(seq.CustId))
- }
- }
- return nil
- })
- if e != nil {
- return e, 0, ""
- }
- if len(failedList) > 0 {
- f, err := ExportFailedData(failedList)
- if err != nil {
- return err, 0, ""
- }
- buf, err := f.WriteToBuffer()
- if err != nil {
- return err, 0, ""
- }
- faildData = base64.StdEncoding.EncodeToString(buf.Bytes())
- }
- return nil, len(failedList), faildData
- }
- // excel解构为数据
- func (s CustomerService) parseExcel(b []byte) ([]*model.CustomerAddImport, error) {
- f, err := excelize.OpenReader(bytes.NewBuffer(b))
- if err != nil {
- return nil, err
- }
- sheet := "Sheet1"
- rows := f.GetRows(sheet)
- if err != nil {
- return nil, err
- }
- // 客户名称 助计名 所在地区 详细地址 所在省 所在市 所在区县 客户行业 客户级别 客户来源 备注 销售名称 开票抬头 关联客户 姓名 性别 电话 微信 邮箱 部门 职位 办公地点 是否关键决策人 招标关键字
- var saleTargets []*model.CustomerAddImport
- for _, row := range rows[1:] {
- temp := &model.CustomerAddImport{
- CustName: row[0],
- AbbrName: row[1],
- CustIndustry: row[2],
- CustSource: row[3],
- CustProvince: row[4],
- CustCity: row[5],
- CustRegion: row[6],
- CustAddress: row[7],
- Keyword: row[8],
- Remark: row[9],
- CuctName: row[10],
- CuctGender: row[11],
- Telephone: row[12],
- Wechat: row[13],
- Email: row[14],
- Dept: row[15],
- Postion: row[16],
- OfficeLocation: row[17],
- IsDecision: row[18],
- ContactRemark: row[19],
- }
- saleTargets = append(saleTargets, temp)
- }
- return saleTargets, nil
- }
- func ExportFailedData(failedList []*model.CustomerAddImport) (*excelizev2.File, error) {
- tempData := [][]string{}
- for _, data := range failedList {
- tempData = append(tempData, []string{
- data.CustName, data.AbbrName, data.CustIndustry, data.CustSource, data.CustProvince, data.CustCity, data.CustRegion, data.CustAddress, data.Keyword, data.Remark,
- data.CuctName, data.CuctGender, data.Telephone, data.Wechat, data.Email, data.Dept, data.Postion, data.OfficeLocation, data.IsDecision, data.ContactRemark, data.FailedReason,
- })
- }
- excel, err := partner.NewExcel(contactFailedExcelHeader, tempData)
- if err != nil {
- return nil, err
- }
- return excel, nil
- }
|