cust_customer.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. package cust
  2. import (
  3. "bytes"
  4. "context"
  5. "fmt"
  6. "math"
  7. "strconv"
  8. "github.com/gogf/gf/encoding/gjson"
  9. "dashoo.cn/opms_libary/myerrors"
  10. "github.com/360EntSecGroup-Skylar/excelize"
  11. "github.com/gogf/gf/frame/g"
  12. "github.com/gogf/gf/os/gtime"
  13. "github.com/gogf/gf/util/gconv"
  14. "dashoo.cn/micro/app/dao/cust"
  15. platdao "dashoo.cn/micro/app/dao/plat"
  16. model "dashoo.cn/micro/app/model/cust"
  17. "dashoo.cn/micro/app/service"
  18. )
  19. type CustomerService struct {
  20. *service.ContextService
  21. Dao *cust.CustCustomerDao
  22. BelongDao *cust.CustCustomerBelongDao
  23. DynamicsDao *cust.CustCustomerDynamicsDao
  24. ContactDao *cust.CustCustomerContactDao
  25. FollowDao *platdao.PlatFollowupDao
  26. BelongServer *CustomerbelongService
  27. ContanctServer *CustomercontactService
  28. }
  29. var isPublic, noPublic = "10", "20" // 公海,非公海
  30. var AllocaTion, OperaTion, Receive, Merge = "10", "20", "30", "40" // 10分配20转移30领取40合并
  31. type OpnType struct {
  32. OperaTion string
  33. }
  34. func NewCustomerService(ctx context.Context) (svc *CustomerService, err error) {
  35. svc = new(CustomerService)
  36. if svc.ContextService, err = svc.Init(ctx); err != nil {
  37. return nil, err
  38. }
  39. svc.Dao = cust.NewCustCustomerDao(svc.Tenant)
  40. svc.BelongDao = cust.NewCustCustomerBelongDao(svc.Tenant)
  41. svc.DynamicsDao = cust.NewCustCustomerDynamicsDao(svc.Tenant)
  42. svc.ContactDao = cust.NewCustCustomerContactDao(svc.Tenant)
  43. svc.FollowDao = platdao.NewPlatFollowupDao(svc.Tenant)
  44. svc.BelongServer, _ = NewCustomerBelongService(ctx)
  45. svc.ContanctServer, _ = NewCustomerContactService(ctx)
  46. return svc, nil
  47. }
  48. // GetList 客户列表列表
  49. func (s *CustomerService) GetList(req *model.CustCustomerSearchReq) (total int, customerList []*model.CustList, err error) {
  50. Model := s.Dao.M
  51. if req.TargetType == "" {
  52. if !req.IsPublic {
  53. Model = Model.Where(s.Dao.Columns.SalesId, s.CxtUser.Id).Where(s.Dao.Columns.IsPublic, noPublic)
  54. } else {
  55. Model = Model.Where(s.Dao.Columns.IsPublic, isPublic)
  56. }
  57. }
  58. //客户名称
  59. if req.CustName != "" {
  60. Model = Model.Where(s.Dao.Columns.CustName+" like ?", "%"+req.CustName+"%")
  61. }
  62. //客户编码
  63. if req.CustCode != "" {
  64. Model = Model.Where(s.Dao.Columns.CustCode+" like ?", "%"+req.CustCode+"%")
  65. }
  66. //客户行业
  67. if req.CustIndustry != "" {
  68. Model = Model.Where(s.Dao.Columns.CustIndustry+" like ?", "%"+req.CustIndustry+"%")
  69. }
  70. //客户级别
  71. if req.CustLevel != "" {
  72. Model = Model.Where(s.Dao.Columns.CustLevel, req.CustLevel)
  73. }
  74. //
  75. if req.FollowUpDate != "" {
  76. Model = Model.Where(s.Dao.Columns.FollowUpDate+" like ? ", req.FollowUpDate+"%")
  77. }
  78. total, err = Model.Count()
  79. if err != nil {
  80. g.Log().Error(err)
  81. return
  82. }
  83. if req.IsRemovePage {
  84. Model = Model
  85. } else {
  86. Model = Model.Page(req.GetPage())
  87. }
  88. err = Model.Order("id desc").Scan(&customerList)
  89. if err != nil {
  90. g.Log().Error(err)
  91. return
  92. }
  93. return
  94. }
  95. // Create 创建客户
  96. func (s *CustomerService) Create(req *model.CustomerAddSeq) (insertId int64, err error) {
  97. cusTomer := new(model.CustCustomer)
  98. count, err := s.Dao.Where(s.Dao.Columns.CustName, req.CustName).Count()
  99. if err != nil {
  100. g.Log().Error(err)
  101. return
  102. }
  103. if count > 0 {
  104. return 0, myerrors.NewMsgError(nil, "该客户信息已存在,不可重复添加")
  105. }
  106. if err = gconv.Struct(req, cusTomer); err != nil {
  107. return
  108. }
  109. service.SetCreatedInfo(cusTomer, s.GetCxtUserId(), s.CxtUser.NickName)
  110. cusTomer.CustCode = "CT" + strconv.Itoa(int(gtime.Timestamp()))
  111. cusTomer.CustStatus = "10"
  112. roles := s.GetCxtUserRoles()
  113. isSales := false
  114. for _, v := range roles {
  115. if v == "Sales" { // 销售角色
  116. isSales = true
  117. }
  118. }
  119. // 销售角色
  120. if isSales {
  121. cusTomer.IsPublic = noPublic
  122. cusTomer.SalesId = s.GetCxtUserId()
  123. cusTomer.SalesName = s.CxtUser.NickName
  124. insertId, err = s.Dao.InsertAndGetId(cusTomer)
  125. if err != nil {
  126. g.Log().Error(err)
  127. return 0, err
  128. }
  129. s.CreateBelong(int(insertId))
  130. } else {
  131. cusTomer.IsPublic = isPublic
  132. insertId, err = s.Dao.InsertAndGetId(cusTomer)
  133. if err != nil {
  134. g.Log().Error(err)
  135. return 0, err
  136. }
  137. }
  138. return insertId, err
  139. }
  140. // CreateBelong 创建客户归属信息
  141. func (s *CustomerService) CreateBelong(custId int) (insertId int64, err error) {
  142. belong := new(model.CustomerBelongAddSeq)
  143. belong.CustId = custId
  144. belong.SaleName = s.CxtUser.NickName
  145. belong.OpnType = AllocaTion
  146. belong.OpnPeople = s.CxtUser.NickName
  147. belong.OpnDatetime = gtime.Now()
  148. err = s.BelongServer.Create(belong)
  149. if err != nil {
  150. g.Log().Error(err)
  151. return
  152. }
  153. return
  154. }
  155. // 删除客户
  156. func (s *CustomerService) DeleteByIds(Ids []int64) (err error) {
  157. customerCount, err := s.Dao.Where(" id in (?)", Ids).Count()
  158. if err != nil {
  159. g.Log().Error(err)
  160. return
  161. }
  162. if customerCount == 0 {
  163. err = myerrors.NewMsgError(nil, "客户信息不存在")
  164. return
  165. }
  166. //删除客户表
  167. _, err = s.Dao.Where("id in (?) ", Ids).Delete()
  168. if err == nil {
  169. _, err = s.ContactDao.Where("cust_id in (?)", Ids).Delete()
  170. if err == nil {
  171. _, err = s.BelongDao.Where("cust_id in (?)", Ids).Delete()
  172. if err != nil {
  173. g.Log().Error(err)
  174. return
  175. }
  176. } else {
  177. g.Log().Error(err)
  178. return
  179. }
  180. } else {
  181. g.Log().Error(err)
  182. return
  183. }
  184. return
  185. }
  186. // UpdateById 修改客户
  187. func (s *CustomerService) UpdateById(req *model.UpdateCustomer) (err error) {
  188. //判断数据是否存在
  189. count, err := s.Dao.Where("id = ", req.Id).Count()
  190. if err != nil {
  191. g.Log().Error(err)
  192. return
  193. }
  194. if count == 0 {
  195. return
  196. }
  197. //新的客户名字是否存在
  198. num, err := s.Dao.Where(s.Dao.Columns.CustName, req.CustName).WhereNot(s.Dao.Columns.Id, req.Id).Count()
  199. if err != nil {
  200. g.Log().Error(err)
  201. return err
  202. }
  203. if num > 0 {
  204. return myerrors.NewMsgError(nil, fmt.Sprintf("客户名称[%s]已存在", req.CustName))
  205. }
  206. CustomertData := new(model.CustomerAddSeq)
  207. if err = gconv.Struct(req, CustomertData); err != nil {
  208. return
  209. }
  210. service.SetUpdatedInfo(CustomertData, s.GetCxtUserId(), s.CxtUser.NickName)
  211. _, err = s.Dao.FieldsEx(s.Dao.Columns.CreatedTime, s.Dao.Columns.CreatedBy, s.Dao.Columns.CreatedName, s.Dao.Columns.Id, s.Dao.Columns.CustCode, s.Dao.Columns.SalesName, s.Dao.Columns.SalesId).
  212. WherePri(s.Dao.Columns.Id, req.Id).Update(CustomertData)
  213. if err != nil {
  214. g.Log().Error(err)
  215. return
  216. }
  217. return
  218. }
  219. // MoveToPubic 移入公海
  220. func (s *CustomerService) MoveToPubic(Ids []int64) (err error) {
  221. count, err := s.Dao.WhereIn(s.Dao.Columns.Id, Ids).Count()
  222. if err != nil {
  223. g.Log().Error(err)
  224. return
  225. }
  226. if count == 0 {
  227. err = myerrors.NewMsgError(nil, "没有要移除的数据")
  228. return
  229. }
  230. _, err = s.Dao.Data(g.Map{
  231. "is_public": isPublic,
  232. "sales_id": 0,
  233. "sales_name": "",
  234. "dept_id": 0,
  235. "dept_name": "",
  236. "create_time": gtime.Now(),
  237. "updated_by": s.GetCxtUserId(),
  238. "updated_name": s.GetCxtUserName(),
  239. "updated_time": gtime.Now(),
  240. }).WhereIn(s.ContactDao.Columns.Id, Ids).Update()
  241. if err != nil {
  242. g.Log().Error(err)
  243. return
  244. }
  245. return nil
  246. }
  247. // AssignCustomer 分配客户
  248. func (s *CustomerService) AssignCustomer(req *model.AssignCustomerReq) (err error) {
  249. data, err := s.Dao.Where("id in (?)", req.Ids).LockShared().All()
  250. if err != nil {
  251. g.Log().Error(err)
  252. return
  253. }
  254. if len(data) == 0 {
  255. return myerrors.NewMsgError(nil, "无可分配客户")
  256. }
  257. for _, v := range data {
  258. if v.SalesId != 0 {
  259. return myerrors.NewMsgError(nil, fmt.Sprintf("客户名称[%s]已被领取或分配", v.CustName))
  260. }
  261. }
  262. s.ChangeCustBelong(req.Ids, req.SalesId, req.SalesName)
  263. if req.Receive != "" {
  264. req.Receive = Receive
  265. } else {
  266. req.Receive = AllocaTion
  267. }
  268. s.BatchCreatebelong(data, req)
  269. return
  270. }
  271. // GetEntityById 客户详情
  272. func (s *CustomerService) GetEntityById(Ids []int64) (entityInfo []*model.CustList, err error) {
  273. Model := s.Dao //
  274. err = Model.Where(" id in (?)", Ids).Scan(&entityInfo)
  275. if err != nil {
  276. g.Log().Error(err)
  277. return
  278. }
  279. return
  280. }
  281. // GetCustNameIsExist 获取客户名称
  282. func (s *CustomerService) GetCustNameIsExist(name string) (exist bool, err error) {
  283. count, err := s.Dao.Where(cust.CustCustomer.Columns.CustName, name).Count()
  284. if err != nil {
  285. g.Log().Error(err)
  286. return
  287. }
  288. exist = false
  289. if count > 0 {
  290. exist = true
  291. }
  292. return
  293. }
  294. // CustAbstract 客户摘要
  295. func (s *CustomerService) CustAbstract(Id int64) (followInfo *model.Follow, err error) {
  296. count, err := s.FollowDao.Where(s.FollowDao.Columns.CustId, Id).Count()
  297. if err != nil {
  298. g.Log().Error(err)
  299. return
  300. }
  301. followInfo = new(model.Follow)
  302. followInfo.FollowCount = count
  303. followTime, err := s.Dao.Fields(s.Dao.Columns.FollowUpDate, s.Dao.Columns.CreatedTime).FindOne(Id)
  304. if err != nil {
  305. g.Log().Error(err)
  306. return
  307. }
  308. now := gtime.Now()
  309. var hours float64
  310. if followTime.FollowUpDate == nil {
  311. poor := now.Sub(gtime.New(followTime.CreatedTime))
  312. hours = float64(poor.Hours() / 24)
  313. } else {
  314. poor := now.Sub(gtime.New(followTime.FollowUpDate))
  315. hours = float64(poor.Hours() / 24)
  316. }
  317. if hours < 0 {
  318. followInfo.NotFollowDay = 0
  319. } else {
  320. followInfo.NotFollowDay = int(math.Floor(hours))
  321. }
  322. return
  323. }
  324. // TransCustomer 转移客户
  325. func (s *CustomerService) TransCustomer(req *model.AssignCustomerReq) (err error) {
  326. data, err := s.Dao.Fields("sales_id,sales_name,id").Where("id in (?)", req.Ids).All()
  327. if err != nil {
  328. g.Log().Error(err)
  329. return err
  330. }
  331. if len(data) == 0 {
  332. return myerrors.NewMsgError(nil, "数据不存在")
  333. }
  334. s.ChangeCustBelong(req.Ids, req.SalesId, req.SalesName)
  335. s.BatchCreatebelong(data, req)
  336. return
  337. }
  338. // ChangeCustBelong 变更客户所属关系
  339. func (s *CustomerService) ChangeCustBelong(Ids []int64, salesId int64, salesName string) (err error) {
  340. _, err = s.Dao.Data(g.Map{
  341. "sales_id": salesId,
  342. "is_public": noPublic,
  343. "sales_name": salesName,
  344. "updated_by": s.GetCxtUserId(),
  345. "updated_name": s.GetCxtUserName(),
  346. "updated_time": gtime.Now(),
  347. }).Where("id in (?)", Ids).Update()
  348. if err != nil {
  349. g.Log().Error(err)
  350. return
  351. }
  352. return
  353. }
  354. //CreateDynamics 创建客户动态信息
  355. func (s *CustomerService) CreateDynamics(opnTpye string, content interface{}, ids ...int64) (err error) {
  356. datas := make([]*model.CustCustomerDynamics, 0)
  357. for _, id := range ids {
  358. dynameics := new(model.CustCustomerDynamics)
  359. dynameics.CustId = int(id)
  360. dynameics.OpnPeopleId = s.GetCxtUserId()
  361. dynameics.OpnPeople = s.GetCxtUserName()
  362. dynameics.OpnDate = gtime.Now()
  363. dynameics.OpnType = opnTpye
  364. v, _ := gjson.Encode(content)
  365. dynameics.OpnContent = gconv.String(v)
  366. service.SetCreatedInfo(dynameics, s.GetCxtUserId(), s.GetCxtUserName())
  367. datas = append(datas, dynameics)
  368. }
  369. _, err = s.DynamicsDao.Insert(datas)
  370. if err != nil {
  371. g.Log().Error(err)
  372. return
  373. }
  374. return
  375. }
  376. // GetDynamicsList 客户动态
  377. func (s *CustomerService) GetDynamicsList(req *model.CustomerDynameicsReq) (total int, result []interface{}, err error) {
  378. total, err = s.DynamicsDao.Where("cust_id = ", req.CustId).Count()
  379. if err != nil {
  380. g.Log().Error(err)
  381. return
  382. }
  383. dynamics := []*model.CustomerDynameicsRep{}
  384. err = s.DynamicsDao.Where("cust_id = ?", req.CustId).Order("created_time desc").Scan(&dynamics)
  385. if err != nil {
  386. g.Log().Error(err)
  387. return
  388. }
  389. dynamicsList := make(map[string][]*model.CustomerDynameicsRep)
  390. for _, v := range dynamics {
  391. opnDate := gtime.New(v.OpnDate).Format("Y-m-d")
  392. dynamicsList[opnDate] = append(dynamicsList[opnDate], &model.CustomerDynameicsRep{
  393. OpnPeople: v.OpnPeople,
  394. OpnDate: v.OpnDate,
  395. OpnType: v.OpnType,
  396. OpnContent: v.OpnContent,
  397. })
  398. }
  399. result = append(result, dynamicsList)
  400. return
  401. }
  402. // MergeCustomer 合并客户
  403. func (s *CustomerService) MergeCustomer(req *model.MergeCustomerRep) (err error) {
  404. //当前目标客户是否存在并取出合并前的销售
  405. customer, err := s.Dao.Where("id = ", req.Id).One()
  406. if err != nil {
  407. g.Log().Error(err)
  408. return
  409. }
  410. if customer == nil {
  411. return myerrors.NewMsgError(nil, "该客户不存在")
  412. }
  413. _, err = s.ContactDao.Where(" cust_id in (?)", req.ChooseId).Delete()
  414. if err != nil {
  415. g.Log().Error(err)
  416. return
  417. }
  418. CustomertData := new(model.CustomerAddSeq)
  419. if err = gconv.Struct(req, CustomertData); err != nil {
  420. g.Log().Error(err)
  421. return
  422. }
  423. service.SetUpdatedInfo(CustomertData, s.GetCxtUserId(), s.GetCxtUserName())
  424. _, err = s.Dao.FieldsEx(s.Dao.Columns.CreatedTime, s.Dao.Columns.CreatedBy,
  425. s.Dao.Columns.CreatedName, s.Dao.Columns.Id,
  426. s.Dao.Columns.CustCode).WherePri(s.Dao.Columns.Id, req.Id).Update(CustomertData)
  427. if err != nil {
  428. g.Log().Error(err)
  429. return
  430. }
  431. //删除被合并的客户信息
  432. _, err = s.Dao.Where(" id in (?)", req.ChooseId).Delete()
  433. if err != nil {
  434. g.Log().Error(err)
  435. return
  436. }
  437. //删除 所选客户销售联系人
  438. _, err = s.BelongDao.Where(" cust_id in (?)", req.ChooseId).Delete()
  439. if err != nil {
  440. g.Log().Error(err)
  441. return
  442. }
  443. //插入一条合并成功的归属记录
  444. req.CustomerBelongAddSeq.CustId = int(req.Id)
  445. req.CustomerBelongAddSeq.OpnType = Merge
  446. req.CustomerBelongAddSeq.OpnPeople = s.GetCxtUserName()
  447. req.CustomerBelongAddSeq.OpnDatetime = gtime.Now()
  448. req.CustomerBelongAddSeq.OrigSaleName = customer.SalesName
  449. req.CustomerBelongAddSeq.SaleName = req.SalesName
  450. s.BelongServer.Create(req.CustomerBelongAddSeq)
  451. return
  452. }
  453. // Createcontact 联系人(合并)预留
  454. func (s *CustomerService) Createcontact(Ids []int64, req *model.CustCustomerContactSeq) (err error) {
  455. _, err = s.ContactDao.Where(" cust_id in (?)", Ids).Delete()
  456. if err != nil {
  457. g.Log().Error(err)
  458. return
  459. }
  460. s.ContanctServer.Create(req)
  461. return
  462. }
  463. // BatchCreatebelong 批量插入客户归属记录表
  464. func (s *CustomerService) BatchCreatebelong(rep []*model.CustCustomer, req *model.AssignCustomerReq, n ...interface{}) (err error) {
  465. var belongData []*model.CustCustomerBelong
  466. userName := s.GetCxtUserName()
  467. for _, v := range rep {
  468. orig_sale_name := v.SalesName
  469. belong := new(model.CustCustomerBelong)
  470. belong.CustId = v.Id
  471. belong.SaleName = req.SalesName
  472. belong.OrigSaleName = orig_sale_name
  473. belong.OpnType = req.Receive
  474. belong.OpnPeople = userName
  475. belong.CreatedName = userName
  476. belong.OpnDatetime = gtime.Now()
  477. belong.Remark = req.Remark
  478. belong.CreatedBy = s.GetCxtUserId()
  479. belongData = append(belongData, belong)
  480. }
  481. _, err = s.BelongDao.Insert(belongData)
  482. if err != nil {
  483. g.Log().Error(err)
  484. return
  485. }
  486. return
  487. }
  488. // 导出数据
  489. func (s *CustomerService) Export(req *model.CustCustomerExport) (content *model.CustExport, err error) {
  490. var con model.CustExport
  491. req.IsRemovePage = true // 去掉分页标识
  492. total, data, err := s.GetList(&req.CustCustomerSearchReq)
  493. if err != nil {
  494. return
  495. }
  496. f := excelize.NewFile()
  497. index := f.NewSheet("Sheet1")
  498. for index, item := range req.Columns {
  499. sheetPosition := service.Div(index+1) + "1"
  500. f.SetCellValue("Sheet1", sheetPosition, item)
  501. }
  502. if total > 0 {
  503. for ck, item := range data {
  504. for index, v := range req.Columns {
  505. if v == "客户编码" {
  506. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustCode)
  507. }
  508. if v == "客户名称" {
  509. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustName)
  510. }
  511. if v == "助记名" {
  512. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.AbbrName)
  513. }
  514. if v == "助记名" {
  515. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.AbbrName)
  516. }
  517. if v == "所在地区" {
  518. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustLocation)
  519. }
  520. if v == "客户行业" {
  521. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustIndustry)
  522. }
  523. if v == "客户级别" {
  524. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CustLevel)
  525. }
  526. if v == "客户状态" {
  527. var CustStatus string
  528. CustStatus = "正常"
  529. if item.CustStatus != "10" {
  530. CustStatus = "异常"
  531. }
  532. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), CustStatus)
  533. }
  534. if v == "最后跟进时间" {
  535. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.FollowUpDate)
  536. }
  537. if v == "创建时间" {
  538. f.SetCellValue("Sheet1", service.Div(index+1)+strconv.Itoa(ck+2), item.CreatedTime)
  539. }
  540. }
  541. }
  542. }
  543. f.SetActiveSheet(index)
  544. var buffer *bytes.Buffer
  545. buffer, _ = f.WriteToBuffer()
  546. con.Content = buffer.Bytes()
  547. return &con, err
  548. }