cust_customer.go 16 KB

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