cust_customer.go 16 KB

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