company.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. package maycur
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "hongze/hz_crm_api/models"
  6. "hongze/hz_crm_api/models/system"
  7. "hongze/hz_crm_api/services/alarm_msg"
  8. "hongze/hz_crm_api/utils"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. // CompanyProfilePageListReq 客户档案分页列表请求体
  14. type CompanyProfilePageListReq struct {
  15. ReferenceDataBizCode string `description:"档案编码" json:"referenceDataBizCode"`
  16. Offset int `description:"偏移量" json:"offset"`
  17. PageSize int `description:"每页数据量" json:"pageSize"`
  18. }
  19. // CompanyProfilePageListResp 客户档案分页列表响应体
  20. type CompanyProfilePageListResp struct {
  21. Code string `description:"状态码"`
  22. Message string `description:"返回信息"`
  23. Data CompanyProfilePageListData `description:"返回数据"`
  24. Success bool `description:"是否成功"`
  25. }
  26. // CompanyProfilePageListData 客户档案分页列表数据
  27. type CompanyProfilePageListData struct {
  28. Total int `description:"数据总量" json:"total"`
  29. Offset int `description:"偏移量" json:"offset"`
  30. PageSize int `description:"每页数据量" json:"pageSize"`
  31. List []struct {
  32. BizCode string `description:"选项编码" json:"bizCode"`
  33. Name string `description:"公司名称" json:"name"`
  34. NameDisplay string `description:"公司名称-JSON(包含所有语言的名称文案)" json:"nameDisplay"`
  35. Enabled bool `description:"是否启用" json:"enabled"`
  36. ParentCode string `description:"父级选项编码/顶级档案编码" json:"parentCode"`
  37. } `description:"列表数据" json:"list"`
  38. HasNextPage bool `description:"是否还有下一页" json:"hasNextPage"`
  39. }
  40. // CurlCompanyProfilePageList 请求客户档案分页列表接口
  41. func CurlCompanyProfilePageList(req CompanyProfilePageListReq) (companyData CompanyProfilePageListData, err error) {
  42. defer func() {
  43. if err != nil {
  44. utils.FileLog.Error("CurlCompanyProfilePageList ErrMsg: %s", err.Error())
  45. go alarm_msg.SendAlarmMsg(fmt.Sprintf("每刻报销-获取客户档案分页列表失败, ErrMsg: %s", err.Error()), 3)
  46. }
  47. }()
  48. if req.PageSize == 0 {
  49. req.PageSize = 50
  50. }
  51. // 请求
  52. url := fmt.Sprintf("%s%s", utils.MayCurBaseUrl, ApiCompanyProfilePageListUrl)
  53. reqByte, e := json.Marshal(req)
  54. if e != nil {
  55. err = fmt.Errorf("request json marshal err: %s", e.Error())
  56. return
  57. }
  58. body, e := buildHttpRequest(url, "POST", string(reqByte), true)
  59. if e != nil {
  60. err = fmt.Errorf("curl api err: %s", e.Error())
  61. return
  62. }
  63. // 响应
  64. resp := new(CompanyProfilePageListResp)
  65. if e = json.Unmarshal(body, &resp); e != nil {
  66. err = fmt.Errorf("resp json unmarshal err: %s", e.Error())
  67. return
  68. }
  69. if resp == nil {
  70. err = fmt.Errorf("resp nil")
  71. return
  72. }
  73. if resp.Code != ApiSuccessCode {
  74. err = fmt.Errorf("resp err message: %s", resp.Message)
  75. return
  76. }
  77. companyData = resp.Data
  78. return
  79. }
  80. // DownloadCompanyProfile 同步每刻报销客户档案数据到CRM
  81. // 每刻没提供debug环境, 所以在CRM这里做个备份...
  82. func DownloadCompanyProfile() (err error) {
  83. defer func() {
  84. if err != nil {
  85. fmt.Println(err.Error())
  86. }
  87. }()
  88. // 清理掉本地的档案, 每刻的档案和本地的档案可能会因为每刻系统的删除操作而产生重复数据, 即使这边用BizCode去重也可能会
  89. profileOB := new(models.MaycurCompanyProfile)
  90. if e := profileOB.Clear(); e != nil {
  91. err = fmt.Errorf("清理本地客户档案失败, Err: %s", e.Error())
  92. return
  93. }
  94. // 分页请求
  95. var req CompanyProfilePageListReq
  96. req.ReferenceDataBizCode = CompanyProfileCode
  97. if e := sliceDownloadCompanyProfile(req); e != nil {
  98. err = fmt.Errorf("分页获取客户档案列表失败, Err: %s", e.Error())
  99. return
  100. }
  101. return
  102. }
  103. // sliceDownloadCompanyProfile 分片同步客户档案
  104. func sliceDownloadCompanyProfile(req CompanyProfilePageListReq) (err error) {
  105. // 请求
  106. req.ReferenceDataBizCode = CompanyProfileCode
  107. if req.PageSize <= 0 {
  108. req.PageSize = 100
  109. }
  110. fmt.Println("offset: ", req.Offset, "pageSize: ", req.PageSize)
  111. data, e := CurlCompanyProfilePageList(req)
  112. if e != nil {
  113. err = fmt.Errorf("请求客户档案接口失败, Err: %s", e.Error())
  114. return
  115. }
  116. list := data.List
  117. listLen := len(list)
  118. if listLen == 0 {
  119. return
  120. }
  121. // 去重-不知道为啥下一页有时候会出现跟这一页一样的某一条数据
  122. profileOB := new(models.MaycurCompanyProfile)
  123. profileCond := ``
  124. profilePars := make([]interface{}, 0)
  125. profileList, e := profileOB.GetItemsByCondition(profileCond, profilePars, []string{}, "")
  126. if e != nil {
  127. err = fmt.Errorf("获取客户档案列表失败, Err: %s", e.Error())
  128. return
  129. }
  130. profileMap := make(map[string]*models.MaycurCompanyProfile)
  131. for _, p := range profileList {
  132. profileMap[p.BizCode] = p
  133. }
  134. nowTime := time.Now().Local()
  135. newProfiles := make([]*models.MaycurCompanyProfile, 0)
  136. updateProfiles := make([]*models.MaycurCompanyProfile, 0)
  137. for _, v := range list {
  138. if profileMap[v.BizCode] != nil {
  139. continue
  140. }
  141. // 新增
  142. enabled := 0
  143. if v.Enabled {
  144. enabled = 1
  145. }
  146. newProfiles = append(newProfiles, &models.MaycurCompanyProfile{
  147. BizCode: v.BizCode,
  148. Name: v.Name,
  149. NameDisplay: v.NameDisplay,
  150. Enabled: enabled,
  151. ParentCode: v.ParentCode,
  152. CreateTime: nowTime,
  153. ModifyTime: nowTime,
  154. })
  155. }
  156. // 新增及更新
  157. updateCols := []string{"Name", "NameDisplay", "Enabled", "ParentCode", "ModifyTime"}
  158. if e = profileOB.MultiCreateAndUpdate(newProfiles, updateProfiles, updateCols); e != nil {
  159. err = fmt.Errorf("新增/更新客户档案失败, Err: %s", e.Error())
  160. return
  161. }
  162. // 递归请求下一页
  163. fmt.Println(data.HasNextPage)
  164. if !data.HasNextPage {
  165. return
  166. }
  167. time.Sleep(300 * time.Millisecond)
  168. req.Offset += listLen
  169. err = sliceDownloadCompanyProfile(req)
  170. return
  171. }
  172. // ImportCompanyProfileReq 批量导入客户档案请求体
  173. type ImportCompanyProfileReq struct {
  174. BizCode string `description:"" json:"bizCode"`
  175. ReferenceDataDetails []ImportCompanyProfileReferenceData `description:"" json:"referenceDataDetails"`
  176. }
  177. // ImportCompanyProfileReferenceData 批量导入客户档案数据
  178. type ImportCompanyProfileReferenceData struct {
  179. Name string `description:"选项名称, 选填, 三填一" json:"name"`
  180. NameEn string `description:"选项名称(英文), 选填, 三填一" json:"nameEn"`
  181. NameZh string `description:"选项名称(中文), 选填, 三填一" json:"nameZh"`
  182. BizCode string `description:"选项编码(全局唯一), 必填" json:"bizCode"`
  183. Enabled bool `description:"是否启用, 必填" json:"enabled"`
  184. ReferenceDataAuthz []*ReferenceDataAuth `description:"选项可见性, 选填, 空数组为清除, 不填维持原数据" json:"referenceDataAuthz"`
  185. }
  186. // ReferenceDataAuth 客户档案可见性权限
  187. type ReferenceDataAuth struct {
  188. BizCode string `description:"业务编码" json:"bizCode"`
  189. Type string `description:"STAFF-人员; DEPARTMENT-部门; LEGAL_ENTITY-公司抬头" json:"type"`
  190. IncludeChild bool `description:"是否包含子部门(type为DEPARTMENT时有效)" json:"includeChild"`
  191. }
  192. // ImportCompanyProfileResp 批量导入客户档案响应体
  193. type ImportCompanyProfileResp struct {
  194. Success bool `description:"是否成功返回" json:"success"`
  195. ErrorMsg string `description:"错误信息" json:"errorMsg"`
  196. Data interface{} `description:"不知道是要返回个啥数据..." json:"data"`
  197. }
  198. // CurlImportCompanyProfile 请求批量导入客户档案接口
  199. func CurlImportCompanyProfile(req ImportCompanyProfileReq) (success bool, err error) {
  200. defer func() {
  201. if err != nil {
  202. fmt.Println(err.Error())
  203. }
  204. }()
  205. // 请求
  206. url := fmt.Sprintf("%s%s", utils.MayCurBaseUrl, ApiImportCompanyProfileUrl)
  207. reqByte, e := json.Marshal(req)
  208. if e != nil {
  209. err = fmt.Errorf("request json marshal err: %s", e.Error())
  210. return
  211. }
  212. utils.FileLog.Info("CurlImportCompanyProfile req: %s", string(reqByte))
  213. body, e := buildHttpRequest(url, "POST", string(reqByte), true)
  214. if e != nil {
  215. err = fmt.Errorf("curl api err: %s", e.Error())
  216. return
  217. }
  218. // 响应
  219. resp := new(ImportCompanyProfileResp)
  220. if e = json.Unmarshal(body, &resp); e != nil {
  221. err = fmt.Errorf("resp json unmarshal err: %s, body: %s", e.Error(), string(body))
  222. return
  223. }
  224. if !resp.Success {
  225. err = fmt.Errorf("resp err body: %s", string(body))
  226. return
  227. }
  228. success = true
  229. return
  230. }
  231. // buildCompanyProfileCode 自定义客户档案编号
  232. func buildCompanyProfileCode() string {
  233. str := fmt.Sprintf("HZCP%v", time.Now().UnixNano()/1e6)
  234. r := utils.GetRandStringNoSpecialChar(6)
  235. return strings.ToUpper(strings.Replace(str, str[11:17], r, 1))
  236. }
  237. // GetImportCompanyData 获取导入的客户档案数据
  238. func GetImportCompanyData() (importsData []ImportCompanyProfileReferenceData, err error) {
  239. // 查询现有的客户档案列表
  240. profileOB := new(models.MaycurCompanyProfile)
  241. profiles, e := profileOB.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  242. if e != nil {
  243. err = fmt.Errorf("获取本地客户档案失败, Err: %s", e.Error())
  244. return
  245. }
  246. profileNameVal := make(map[string]*models.MaycurCompanyProfile)
  247. for _, v := range profiles {
  248. profileNameVal[v.Name] = v
  249. }
  250. // 查询所有试用、正式、永续、冻结客户(包含了FICC和私募, 可能与公募部分客户存在重合)
  251. localComps, e := models.GetMaycurSyncCompanyListWithSeller()
  252. if e != nil {
  253. err = fmt.Errorf("获取需要同步的客户列表失败, Err: %s", e.Error())
  254. return
  255. }
  256. localCompNameVal := make(map[string]*models.MaycurSyncCompanyListWithSeller)
  257. for _, v := range localComps {
  258. localCompNameVal[v.CompanyName] = v
  259. }
  260. // 本地员工及员工上级组map
  261. employeeGroupMap, _ := getEmployeeGroupMapFromList()
  262. // Test
  263. //for k, em := range employeeGroupMap {
  264. // str := ``
  265. // for _, v := range em {
  266. // str += fmt.Sprintf(" %d-%s", v.AdminId, v.RealName)
  267. // }
  268. // utils.FileLog.Info("seller-%d: %s", k, str)
  269. //}
  270. // 可见所有客户的用户组
  271. groupAuth := new(ReferenceDataAuth)
  272. groupAuth.BizCode = AuthGroupCode
  273. groupAuth.Type = "USER_GROUP"
  274. importCompsVal := make(map[string]ImportCompanyProfileReferenceData)
  275. // FICC、私募客户
  276. for _, c := range localComps {
  277. var v ImportCompanyProfileReferenceData
  278. bizArr := make(map[string]bool) // STAFF去重
  279. // 用户组均可见
  280. authArr := make([]*ReferenceDataAuth, 0)
  281. authArr = append(authArr, groupAuth)
  282. // 销售及上级可见性
  283. sellerIdStr := c.SellerIds
  284. if sellerIdStr != "" {
  285. sellerIdArr := strings.Split(sellerIdStr, ",")
  286. for _, s := range sellerIdArr {
  287. sid, _ := strconv.Atoi(s)
  288. // 匹配销售对应的销售组, 若有相应数据则加入可见性
  289. admins := employeeGroupMap[sid]
  290. if admins != nil && len(admins) > 0 {
  291. for _, a := range admins {
  292. if a.EmployeeId == "" {
  293. continue
  294. }
  295. if bizArr[a.EmployeeId] {
  296. continue
  297. }
  298. authArr = append(authArr, &ReferenceDataAuth{
  299. BizCode: a.EmployeeId,
  300. Type: "STAFF",
  301. })
  302. bizArr[a.EmployeeId] = true
  303. }
  304. }
  305. }
  306. }
  307. // 正式客户共享-销售可见性, 仅被共享的销售, 不加上级
  308. if c.IsShare == 1 && c.ShareSellerId > 0 {
  309. shareAdmins := employeeGroupMap[c.ShareSellerId]
  310. if shareAdmins != nil && len(shareAdmins) > 0 {
  311. for _, sa := range shareAdmins {
  312. if sa.AdminId == c.ShareSellerId && !bizArr[sa.EmployeeId] {
  313. authArr = append(authArr, &ReferenceDataAuth{
  314. BizCode: sa.EmployeeId,
  315. Type: "STAFF",
  316. })
  317. break
  318. }
  319. }
  320. }
  321. }
  322. v.ReferenceDataAuthz = authArr
  323. // 更新/新增
  324. v.Enabled = true
  325. local := profileNameVal[c.CompanyName]
  326. if local != nil {
  327. v.Name = local.Name
  328. v.BizCode = local.BizCode
  329. }
  330. if local == nil {
  331. v.Name = c.CompanyName
  332. v.BizCode = buildCompanyProfileCode()
  333. }
  334. importCompsVal[v.Name] = v
  335. }
  336. // 公募客户
  337. publicCompOB := new(models.MaycurPublicOfferingCompany)
  338. publicComps, e := publicCompOB.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  339. if e != nil {
  340. err = fmt.Errorf("获取公募客户列表失败, Err: %s", e.Error())
  341. return
  342. }
  343. // 公募销售对应的组长(多个)
  344. publicLeaders, e := GetPublicOfferingSaleLeader()
  345. if e != nil {
  346. err = fmt.Errorf("获取公募销售组长信息失败, Err: %s", e.Error())
  347. return
  348. }
  349. // 员工工号-此处包括禁用的
  350. employeeOB := new(system.Admin)
  351. employeeCond := ` AND employee_id <> ""`
  352. employeePars := make([]interface{}, 0)
  353. employees, e := employeeOB.GetItemsByCondition(employeeCond, employeePars, []string{}, "")
  354. if e != nil {
  355. err = fmt.Errorf("获取员工列表失败, Err: %s", e.Error())
  356. return
  357. }
  358. empNameVal := make(map[string]*system.Admin)
  359. for _, emp := range employees {
  360. empNameVal[emp.RealName] = emp
  361. }
  362. // 公募客户数据
  363. for _, p := range publicComps {
  364. // 销售可见性
  365. ps := strings.Split(p.SaleNames, ",")
  366. if len(ps) == 0 {
  367. continue
  368. }
  369. bizArr := make(map[string]bool)
  370. for _, s := range ps {
  371. // 销售
  372. emp := empNameVal[s]
  373. if emp != nil && emp.EmployeeId != "" && !bizArr[emp.EmployeeId] {
  374. bizArr[emp.EmployeeId] = true
  375. }
  376. // 组长
  377. ls := publicLeaders[s]
  378. if len(ls) > 0 {
  379. for _, l := range ls {
  380. le := empNameVal[l]
  381. if le != nil && le.EmployeeId != "" && !bizArr[le.EmployeeId] {
  382. bizArr[le.EmployeeId] = true
  383. }
  384. }
  385. }
  386. }
  387. // 是否与ficc、私募的客户有交集
  388. shared := importCompsVal[p.Name]
  389. if shared.Name != "" && shared.BizCode != "" {
  390. // 公共客户-销售可见性追加进去
  391. localBiz := make(map[string]bool)
  392. for _, s := range shared.ReferenceDataAuthz {
  393. localBiz[s.BizCode] = true
  394. }
  395. for b := range bizArr {
  396. if localBiz[b] {
  397. continue
  398. }
  399. shared.ReferenceDataAuthz = append(shared.ReferenceDataAuthz, &ReferenceDataAuth{
  400. BizCode: b,
  401. Type: "STAFF",
  402. })
  403. }
  404. importCompsVal[p.Name] = shared
  405. } else {
  406. var v ImportCompanyProfileReferenceData
  407. v.Enabled = true
  408. authArr := make([]*ReferenceDataAuth, 0)
  409. authArr = append(authArr, groupAuth)
  410. for b := range bizArr {
  411. authArr = append(authArr, &ReferenceDataAuth{
  412. BizCode: b,
  413. Type: "STAFF",
  414. })
  415. }
  416. v.ReferenceDataAuthz = authArr
  417. // 是否是已有的客户档案
  418. origin := profileNameVal[p.Name]
  419. if origin != nil {
  420. v.Name = origin.Name
  421. v.BizCode = origin.BizCode
  422. }
  423. if origin == nil {
  424. v.Name = p.Name
  425. v.BizCode = buildCompanyProfileCode()
  426. }
  427. importCompsVal[v.Name] = v
  428. }
  429. }
  430. // 遍历每刻档案, 生成导入数据
  431. for _, f := range profiles {
  432. val, ok := importCompsVal[f.Name]
  433. if ok {
  434. val.BizCode = f.BizCode
  435. importsData = append(importsData, val)
  436. continue
  437. }
  438. // 不应导入的客户, 仅用户组可见, 禁启用随原数据
  439. var o ImportCompanyProfileReferenceData
  440. o.Name = f.Name
  441. o.BizCode = f.BizCode
  442. o.Enabled = false
  443. if f.Enabled == 1 {
  444. o.Enabled = true
  445. }
  446. o.ReferenceDataAuthz = make([]*ReferenceDataAuth, 0)
  447. o.ReferenceDataAuthz = append(o.ReferenceDataAuthz, groupAuth)
  448. importsData = append(importsData, o)
  449. }
  450. // Test
  451. //testIdArr := []string{"0041"} // 亓策
  452. //testData := make([]ImportCompanyProfileReferenceData, 0)
  453. //for _, d := range importData {
  454. // has := false
  455. // for _, r := range d.ReferenceDataAuthz {
  456. // if utils.InArrayByStr(testIdArr, r.BizCode) {
  457. // has = true
  458. // break
  459. // }
  460. // }
  461. // if !has {
  462. // continue
  463. // }
  464. // testData = append(testData, d)
  465. //}
  466. return
  467. }
  468. // ImportCompanyProfile 导入客户档案
  469. func ImportCompanyProfile(importData []ImportCompanyProfileReferenceData) (err error) {
  470. // 控制每秒最多请求5次接口
  471. chanData := make(chan ImportCompanyProfileReferenceData, 50)
  472. sendDone := make(chan bool, 1)
  473. importDone := make(chan bool, 1)
  474. importErr := make(chan error, 1)
  475. sendClose := make(chan bool, 1)
  476. // 分批
  477. go func() {
  478. defer func() {
  479. utils.FileLog.Info("分批协程关闭")
  480. }()
  481. for _, d := range importData {
  482. select {
  483. case chanData <- d:
  484. case <-sendClose:
  485. return
  486. }
  487. }
  488. time.Sleep(5 * time.Second) // 分批完成后暂缓5s是为了防止倒数第二次请求接口响应时间过长, 导致接收丢失
  489. sendDone <- true
  490. }()
  491. // 接收并导入
  492. go func() {
  493. receive := 0
  494. times := 0
  495. defer func() {
  496. utils.FileLog.Info("导入协程关闭 -> 最终接收: %d -> 最终请求次数: %d", receive, times)
  497. }()
  498. batch := make([]ImportCompanyProfileReferenceData, 0)
  499. end := false
  500. for {
  501. select {
  502. case v := <-chanData:
  503. receive += 1
  504. //fmt.Printf("第%d次接收\n", receive)
  505. batch = append(batch, v)
  506. // 每50条数据请求一次, 每刻接口请求单次最大50条
  507. if len(batch) == 50 {
  508. times += 1
  509. if e := SliceImportCompanyProfile(batch); e != nil {
  510. sendClose <- true
  511. importErr <- e
  512. return
  513. }
  514. // 间隔0.3秒, 每刻有接口频率限制
  515. time.Sleep(300 * time.Millisecond)
  516. batch = make([]ImportCompanyProfileReferenceData, 0)
  517. }
  518. case <-sendDone:
  519. // 传输完毕, 执行最后一次
  520. if len(batch) > 0 {
  521. times += 1
  522. if e := SliceImportCompanyProfile(batch); e != nil {
  523. sendClose <- true
  524. importErr <- e
  525. return
  526. }
  527. }
  528. end = true
  529. }
  530. if end {
  531. importDone <- true
  532. return
  533. }
  534. }
  535. }()
  536. select {
  537. case <-importDone:
  538. utils.FileLog.Info("导入成功")
  539. case e := <-importErr:
  540. err = fmt.Errorf("批量导入客户档案失败, Err: %s", e.Error())
  541. }
  542. return
  543. }
  544. // SliceImportCompanyProfile 分批导入客户档案
  545. func SliceImportCompanyProfile(dataDetails []ImportCompanyProfileReferenceData) (err error) {
  546. if len(dataDetails) == 0 {
  547. return
  548. }
  549. var req ImportCompanyProfileReq
  550. req.BizCode = CompanyProfileCode
  551. req.ReferenceDataDetails = dataDetails
  552. // Test
  553. //b, e := json.Marshal(req)
  554. //if e != nil {
  555. // err = fmt.Errorf("request json marshal err: %s", e.Error())
  556. // return
  557. //}
  558. //utils.FileLog.Info("CurlImportCompanyProfile req: %s", string(b))
  559. //return
  560. success, e := CurlImportCompanyProfile(req)
  561. if e != nil {
  562. return e
  563. }
  564. if !success {
  565. return fmt.Errorf("导入失败")
  566. }
  567. return
  568. }
  569. // CompanyProfileDetailResp 客户档案-详情响应体
  570. type CompanyProfileDetailResp struct {
  571. Code string `description:"状态码"`
  572. Message string `description:"返回信息"`
  573. Data struct {
  574. BizCode string `description:"选项编码" json:"bizCode"`
  575. Name string `description:"公司名称" json:"name"`
  576. NameDisplay string `description:"公司名称-JSON(包含所有语言的名称文案)" json:"nameDisplay"`
  577. Enabled bool `description:"是否启用" json:"enabled"`
  578. ParentCode string `description:"父级选项编码/顶级档案编码" json:"parentCode"`
  579. ReferenceAuthzs []CompanyProfileReferenceAuthzs
  580. } `description:"详情数据"`
  581. ErrorCode string `description:"错误码" json:"errorCode"`
  582. Success bool `description:"是否成功"`
  583. }
  584. // CompanyProfileReferenceAuthzs 客户档案-可见性
  585. type CompanyProfileReferenceAuthzs struct {
  586. AuthzType string `description:"授权范围类型-详见接口文档" json:"authzType"`
  587. AuthzCode string `description:"授权码-员工工号/部门编码等" json:"authzCode"`
  588. AuthzName string `description:"授权名称" json:"authzName"`
  589. IncludeChildDept bool `description:"是否包含子节点" json:"includeChildDept"`
  590. }
  591. // UpdateLocalCompanyProfileAuth 更新本地客户档案可见性
  592. func UpdateLocalCompanyProfileAuth() (err error) {
  593. defer func() {
  594. if err != nil {
  595. fmt.Println(err.Error())
  596. }
  597. }()
  598. profileOB := new(models.MaycurCompanyProfile)
  599. profileCond := ` AND enabled = ?`
  600. profilePars := make([]interface{}, 0)
  601. profilePars = append(profilePars, 1)
  602. profiles, e := profileOB.GetItemsByCondition(profileCond, profilePars, []string{}, "")
  603. if e != nil {
  604. err = fmt.Errorf("获取客户档案列表失败, Err: %s", e.Error())
  605. return
  606. }
  607. total := len(profiles)
  608. var count, updated int
  609. for _, v := range profiles {
  610. count += 1
  611. if count > 5 {
  612. fmt.Printf("总数: %d, 已更新: %d\n", total, updated)
  613. time.Sleep(500 * time.Millisecond)
  614. count = 1
  615. }
  616. par := fmt.Sprintf(`/api/openapi/reference/data/detail/%s/%s`, CompanyProfileCode, v.BizCode)
  617. url := fmt.Sprintf("%s%s", utils.MayCurBaseUrl, par)
  618. body, e := buildHttpRequest(url, "GET", ``, true)
  619. if e != nil {
  620. err = fmt.Errorf("获取客户档案详情失败, Err: %s", e.Error())
  621. return
  622. }
  623. var resp CompanyProfileDetailResp
  624. if e = json.Unmarshal(body, &resp); e != nil {
  625. err = fmt.Errorf("客户档案详情Unmarshal, Err: %s", e.Error())
  626. return
  627. }
  628. if resp.Code != ApiSuccessCode || !resp.Success {
  629. utils.FileLog.Info("忽略客户%s -> body: %s", v.BizCode, string(body))
  630. continue
  631. }
  632. b, e := json.Marshal(resp.Data.ReferenceAuthzs)
  633. if e != nil {
  634. err = fmt.Errorf("客户档案可见性Marshal, Err: %s", e.Error())
  635. return
  636. }
  637. v.Authzs = string(b)
  638. v.ModifyTime = time.Now().Local()
  639. if e = v.Update([]string{"Authzs", "ModifyTime"}); e != nil {
  640. err = fmt.Errorf("更新本地客户档案可见性失败, Err: %s", e.Error())
  641. return
  642. }
  643. updated += 1
  644. }
  645. fmt.Printf("总数: %d, 已更新: %d\n", total, updated)
  646. return
  647. }
  648. // RecoverCompanyProfile 恢复客户档案可见性(没有测试服, 还原用的...)
  649. func RecoverCompanyProfile() (err error) {
  650. defer func() {
  651. if err != nil {
  652. fmt.Println(err.Error())
  653. }
  654. }()
  655. profileOB := new(models.MaycurCompanyProfile)
  656. profiles, e := profileOB.GetItemsByCondition(``, make([]interface{}, 0), []string{}, "")
  657. if e != nil {
  658. err = fmt.Errorf("获取客户档案列表失败, Err: %s", e.Error())
  659. return
  660. }
  661. if len(profiles) == 0 {
  662. return
  663. }
  664. var importsData []ImportCompanyProfileReferenceData
  665. for _, p := range profiles {
  666. var v ImportCompanyProfileReferenceData
  667. v.Name = p.Name
  668. v.BizCode = p.BizCode
  669. if p.Enabled == 1 {
  670. v.Enabled = true
  671. }
  672. v.ReferenceDataAuthz = nil
  673. if p.Authzs != "" && p.Authzs != "null" {
  674. var authzs []CompanyProfileReferenceAuthzs
  675. if e := json.Unmarshal([]byte(p.Authzs), &authzs); e != nil {
  676. err = fmt.Errorf(" Authzs Unmarshal Err: %s", e.Error())
  677. return
  678. }
  679. v.ReferenceDataAuthz = make([]*ReferenceDataAuth, 0)
  680. for _, a := range authzs {
  681. v.ReferenceDataAuthz = append(v.ReferenceDataAuthz, &ReferenceDataAuth{
  682. BizCode: a.AuthzCode,
  683. Type: a.AuthzType,
  684. IncludeChild: a.IncludeChildDept,
  685. })
  686. }
  687. }
  688. importsData = append(importsData, v)
  689. }
  690. // 导入
  691. utils.FileLog.Info("导入数据长度: %d", len(importsData))
  692. if e := ImportCompanyProfile(importsData); e != nil {
  693. err = fmt.Errorf("导入失败, Err: %s", e.Error())
  694. return
  695. }
  696. return
  697. }