chart.go 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. package cross_variety
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta_gn/eta_api/models/data_manage"
  6. cross_varietyModel "eta_gn/eta_api/models/data_manage/cross_variety"
  7. "eta_gn/eta_api/models/data_manage/cross_variety/request"
  8. "eta_gn/eta_api/models/system"
  9. "eta_gn/eta_api/services/data"
  10. "eta_gn/eta_api/utils"
  11. "fmt"
  12. "github.com/shopspring/decimal"
  13. "strconv"
  14. "strings"
  15. "time"
  16. )
  17. type ChartInfoResp struct {
  18. XName string `description:"x轴名称"`
  19. XNameEn string `description:"x轴名称(英文)"`
  20. XUnitName string `description:"x轴单位名称"`
  21. XUnitNameEn string `description:"x轴单位名称(英文)"`
  22. YName string `description:"y轴名称"`
  23. YNameEn string `description:"y轴名称(英文)"`
  24. YUnitName string `description:"y轴单位名称"`
  25. YUnitNameEn string `description:"y轴单位名称(英文)"`
  26. XMinValue string `description:"X轴的最小值"`
  27. XMaxValue string `description:"X轴的最大值"`
  28. YMinValue string `description:"Y轴的最小值"`
  29. YMaxValue string `description:"Y轴的最大值"`
  30. DataList []SectionScatterSeriesItemResp `description:"数据列"`
  31. }
  32. type SectionScatterSeriesItemResp struct {
  33. Name string `description:"系列名"`
  34. NameEn string `description:"系列名(英文)"`
  35. Color string `description:"颜色"`
  36. CoordinatePointData []CoordinatePoint `description:"趋势线的前后坐标点"`
  37. }
  38. type SectionScatterEdbItemResp struct {
  39. XEdbInfoId int `description:"X轴指标id"`
  40. XDate string `description:"X轴指标实际日期"`
  41. XName string `description:"X轴指标名称"`
  42. XNameEn string `description:"X轴指标英文名称"`
  43. XValue float64 `description:"X轴实际值"`
  44. YEdbInfoId int `description:"Y轴指标id"`
  45. YDate string `description:"Y轴指标实际日期"`
  46. YName string `description:"Y轴指标名称"`
  47. YNameEn string `description:"Y轴指标英文名称"`
  48. YValue float64 `description:"Y轴实际值"`
  49. IsShow bool `description:"是否展示"`
  50. Name string `description:"标签名称"`
  51. NameEn string `description:"英文标签名称"`
  52. }
  53. type CoordinatePoint struct {
  54. X float64
  55. Y float64
  56. XEdbInfoId int
  57. YEdbInfoId int
  58. XDate string
  59. YDate string
  60. DateType int `description:"日期类型:1-最新日期;2-N天前;3-固定日期"`
  61. DaysAgo int `description:"N天前的N值"`
  62. ShowTips int `description:"是否显示标注:0-否;1-是"`
  63. }
  64. func GetChartData(chartInfoId int, config request.ChartConfigReq) (edbList []*data_manage.ChartEdbInfoMapping, dataResp ChartInfoResp, err error, errMsg string, isSendEmail bool) {
  65. moveUnitDays, ok := utils.FrequencyDaysMap[config.CalculateUnit]
  66. if !ok {
  67. errMsg = "错误的分析周期"
  68. err = errors.New(errMsg)
  69. isSendEmail = false
  70. return
  71. }
  72. isSendEmail = true
  73. varietyMap := make(map[int]*cross_varietyModel.ChartVariety)
  74. {
  75. varietyList, tmpErr := cross_varietyModel.GetVarietyListByIdList(config.VarietyList)
  76. if tmpErr != nil {
  77. err = tmpErr
  78. return
  79. }
  80. for _, v := range varietyList {
  81. varietyMap[v.ChartVarietyId] = v
  82. }
  83. }
  84. var xTagInfo, yTagInfo *cross_varietyModel.ChartTag
  85. {
  86. tagList, tmpErr := cross_varietyModel.GetTagListByIdList([]int{config.TagX, config.TagY})
  87. if tmpErr != nil {
  88. err = tmpErr
  89. return
  90. }
  91. for _, v := range tagList {
  92. if v.ChartTagId == config.TagX {
  93. xTagInfo = v
  94. } else if v.ChartTagId == config.TagY {
  95. yTagInfo = v
  96. }
  97. }
  98. }
  99. if xTagInfo == nil {
  100. errMsg = "找不到对应的X轴标签"
  101. err = errors.New(errMsg)
  102. return
  103. }
  104. if yTagInfo == nil {
  105. errMsg = "找不到对应的Y轴标签"
  106. err = errors.New(errMsg)
  107. return
  108. }
  109. xVarietyEdbMap, yVarietyEdbMap, edbInfoIdList, err := GetXYEdbIdList(config.TagX, config.TagY, config.VarietyList)
  110. if err != nil {
  111. return
  112. }
  113. if len(edbInfoIdList) <= 0 {
  114. errMsg = "品种未配置指标"
  115. err = errors.New(errMsg)
  116. isSendEmail = false
  117. return
  118. }
  119. mappingList, err := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdList)
  120. if err != nil {
  121. errMsg = "获取指标信息失败"
  122. err = errors.New("获取指标信息失败,ERR:" + err.Error())
  123. return
  124. }
  125. chartType := 1 //1:普通图,2:季节性图
  126. calendar := "公历"
  127. edbDataListMap, edbList, err := data.GetEdbDataMapList(chartInfoId, chartType, calendar, "", "", mappingList, "")
  128. if err != nil {
  129. return
  130. }
  131. currDay := time.Now()
  132. currDay = time.Date(currDay.Year(), currDay.Month(), currDay.Day(), 0, 0, 0, 0, time.Local)
  133. dataMap := make(map[string]float64)
  134. dateMap := make(map[string]string)
  135. dateTypeMap := make(map[int]int) // 日期配置key对应的日期类型
  136. daysAgoMap := make(map[int]int) // 日期配置key对应的N天前的N值
  137. showTipsMap := make(map[int]int) // 日期配置key对应点是否显示标注
  138. for dateIndex, dateConfig := range config.DateConfigList {
  139. dateTypeMap[dateIndex] = dateConfig.DateType
  140. daysAgoMap[dateIndex] = dateConfig.Num
  141. showTipsMap[dateIndex] = dateConfig.ShowTips
  142. for _, edbInfoMapping := range mappingList {
  143. dataList, ok := edbDataListMap[edbInfoMapping.EdbInfoId]
  144. if !ok {
  145. continue
  146. }
  147. lenData := len(dataList)
  148. if lenData <= 0 {
  149. continue
  150. }
  151. k := lenData - 1
  152. dataEndDateStr := dataList[k].DataTime
  153. dataEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, dataEndDateStr, time.Local)
  154. if tmpErr != nil {
  155. err = tmpErr
  156. return
  157. }
  158. endDateStr := ``
  159. var endDate time.Time
  160. var currVal float64
  161. switch dateConfig.DateType {
  162. case 1: // 1:最新日期;
  163. endDateStr = dataEndDateStr
  164. endDate = dataEndDate
  165. currVal = dataList[k].Value
  166. case 2: // 2:N天前(原为指标最新日期的N天前, 现为系统日期的N天)
  167. tmpEndDate := time.Now().AddDate(0, 0, -dateConfig.Num)
  168. tmpEndDateStr := tmpEndDate.Format(utils.FormatDate)
  169. for i := k; i >= 0; i-- {
  170. tmpDateStr := dataList[i].DataTime
  171. if tmpEndDateStr == tmpDateStr {
  172. k = i
  173. endDateStr = tmpDateStr
  174. endDate = tmpEndDate
  175. currVal = dataList[i].Value
  176. break
  177. }
  178. tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
  179. if tmpErr != nil {
  180. err = tmpErr
  181. return
  182. }
  183. if tmpDate.After(tmpEndDate) {
  184. continue
  185. }
  186. k = i
  187. endDateStr = tmpDateStr
  188. endDate = tmpDate
  189. currVal = dataList[i].Value
  190. break
  191. }
  192. case 3: // 固定日期
  193. if dateConfig.FixDate == "" {
  194. errMsg = "固定日期不可为空"
  195. err = fmt.Errorf("固定日期为空")
  196. return
  197. }
  198. strFixDate := dateConfig.FixDate
  199. fixDate, e := time.ParseInLocation(utils.FormatDate, strFixDate, time.Local)
  200. if e != nil {
  201. errMsg = "固定日期格式有误"
  202. err = fmt.Errorf("固定日期有误, FixDate: %s", dateConfig.FixDate)
  203. return
  204. }
  205. for i := k; i >= 0; i-- {
  206. strThisDate := dataList[i].DataTime
  207. if strFixDate == strThisDate {
  208. k = i
  209. endDateStr = strThisDate
  210. endDate = fixDate
  211. currVal = dataList[i].Value
  212. break
  213. }
  214. thisDate, e := time.ParseInLocation(utils.FormatDate, strThisDate, time.Local)
  215. if e != nil {
  216. err = fmt.Errorf("数据日期格式有误: %s", e.Error())
  217. return
  218. }
  219. if thisDate.After(fixDate) {
  220. continue
  221. }
  222. k = i
  223. endDateStr = strThisDate
  224. endDate = thisDate
  225. currVal = dataList[i].Value
  226. break
  227. }
  228. }
  229. if endDateStr == `` || endDate.IsZero() {
  230. continue
  231. }
  232. earliestDate := endDate.AddDate(0, 0, -config.CalculateValue*moveUnitDays)
  233. earliestDateStr := earliestDate.Format(utils.FormatDate)
  234. var percentVal float64 // 百分位计算值
  235. if config.PercentType == utils.PercentCalculateTypeRange {
  236. var minVal, maxVal float64
  237. var isNotFirst bool // 是否是第一条数据
  238. for i := k; i >= 0; i-- {
  239. tmpData := dataList[i]
  240. if !isNotFirst {
  241. maxVal = tmpData.Value
  242. minVal = tmpData.Value
  243. isNotFirst = true
  244. continue
  245. }
  246. tmpDateStr := dataList[i].DataTime
  247. if earliestDateStr == tmpDateStr {
  248. break
  249. }
  250. tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
  251. if tmpErr != nil {
  252. err = tmpErr
  253. return
  254. }
  255. if tmpDate.Before(earliestDate) {
  256. continue
  257. }
  258. if tmpData.Value > maxVal {
  259. maxVal = tmpData.Value
  260. }
  261. if tmpData.Value < minVal {
  262. minVal = tmpData.Value
  263. }
  264. }
  265. if maxVal == minVal {
  266. continue
  267. }
  268. tmpV := (currVal - minVal) / (maxVal - minVal) * 100
  269. percentVal, _ = decimal.NewFromFloat(tmpV).Round(4).Float64()
  270. }
  271. if config.PercentType == utils.PercentCalculateTypeNum {
  272. var tinyN, bigN int
  273. lastVal := decimal.NewFromFloat(currVal)
  274. for i := k; i >= 0; i-- {
  275. date, e := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
  276. if e != nil {
  277. err = fmt.Errorf("数据日期格式有误: %s", e.Error())
  278. return
  279. }
  280. if !date.Before(earliestDate) && !date.After(endDate) {
  281. bigN += 1
  282. dateVal := decimal.NewFromFloat(dataList[i].Value)
  283. if dateVal.LessThanOrEqual(lastVal) {
  284. tinyN += 1
  285. }
  286. }
  287. }
  288. if bigN <= 1 {
  289. continue
  290. }
  291. numerator := decimal.NewFromInt(int64(tinyN - 1))
  292. denominator := decimal.NewFromInt(int64(bigN - 1))
  293. percentVal, _ = numerator.Div(denominator).Mul(decimal.NewFromFloat(100)).Round(4).Float64()
  294. }
  295. key := fmt.Sprint(dateIndex, "_", edbInfoMapping.EdbInfoId)
  296. dataMap[key] = percentVal
  297. dateMap[key] = endDateStr
  298. }
  299. }
  300. dataList := make([]SectionScatterSeriesItemResp, 0)
  301. var xMinVal, xMaxVal, yMinVal, yMaxVal float64
  302. var isNotFirst bool
  303. for _, varietyId := range config.VarietyList {
  304. xEdbInfoId, ok1 := xVarietyEdbMap[varietyId]
  305. if !ok1 {
  306. continue
  307. }
  308. yEdbInfoId, ok2 := yVarietyEdbMap[varietyId]
  309. if !ok2 {
  310. continue
  311. }
  312. variety, ok := varietyMap[varietyId]
  313. if !ok {
  314. continue
  315. }
  316. coordinatePointList := make([]CoordinatePoint, 0)
  317. for dateIndex, _ := range config.DateConfigList {
  318. key1 := fmt.Sprint(dateIndex, "_", xEdbInfoId)
  319. xVal, ok1 := dataMap[key1]
  320. if !ok1 {
  321. continue
  322. }
  323. key2 := fmt.Sprint(dateIndex, "_", yEdbInfoId)
  324. yVal, ok2 := dataMap[key2]
  325. if !ok2 {
  326. continue
  327. }
  328. if !isNotFirst {
  329. xMinVal = xVal
  330. xMaxVal = xVal
  331. yMinVal = yVal
  332. yMaxVal = yVal
  333. isNotFirst = true
  334. } else {
  335. if xVal < xMinVal {
  336. xMinVal = xVal
  337. }
  338. if xVal > xMaxVal {
  339. xMaxVal = xVal
  340. }
  341. if yVal < yMinVal {
  342. yMinVal = yVal
  343. }
  344. if yVal > yMaxVal {
  345. yMaxVal = yVal
  346. }
  347. }
  348. coordinatePointList = append(coordinatePointList, CoordinatePoint{
  349. X: xVal,
  350. Y: yVal,
  351. XEdbInfoId: xEdbInfoId,
  352. YEdbInfoId: yEdbInfoId,
  353. XDate: dateMap[key1],
  354. YDate: dateMap[key2],
  355. DateType: dateTypeMap[dateIndex], // 日期类型
  356. DaysAgo: daysAgoMap[dateIndex], // N天前的N值
  357. ShowTips: showTipsMap[dateIndex], // 是否显示标注
  358. })
  359. }
  360. dataList = append(dataList, SectionScatterSeriesItemResp{
  361. Name: variety.ChartVarietyName,
  362. NameEn: variety.ChartVarietyNameEn,
  363. Color: "",
  364. CoordinatePointData: coordinatePointList,
  365. })
  366. }
  367. colorMap := utils.GetColorMap()
  368. for k, _ := range dataList {
  369. if c, ok1 := colorMap[k]; ok1 {
  370. dataList[k].Color = c
  371. }
  372. }
  373. dataResp = ChartInfoResp{
  374. XName: xTagInfo.ChartTagName + "百分位",
  375. XNameEn: xTagInfo.ChartTagNameEn,
  376. XUnitName: "%",
  377. XUnitNameEn: "%",
  378. YName: yTagInfo.ChartTagName + "百分位",
  379. YNameEn: yTagInfo.ChartTagNameEn,
  380. YUnitName: "%",
  381. YUnitNameEn: "%",
  382. XMinValue: fmt.Sprint(xMinVal),
  383. XMaxValue: fmt.Sprint(xMaxVal),
  384. YMinValue: fmt.Sprint(yMinVal),
  385. YMaxValue: fmt.Sprint(yMaxVal),
  386. DataList: dataList,
  387. }
  388. for k, _ := range edbList {
  389. edbList[k].DataList = nil
  390. }
  391. return
  392. }
  393. func GetXYEdbIdList(tagX, tagY int, varietyList []int) (xVarietyEdbMap, yVarietyEdbMap map[int]int, edbInfoIdList []int, err error) {
  394. edbInfoIdList = make([]int, 0)
  395. xVarietyEdbMap = make(map[int]int)
  396. yVarietyEdbMap = make(map[int]int)
  397. xList, err := cross_varietyModel.GetChartTagVarietyListByTagAndVariety(tagX, varietyList)
  398. if err != nil {
  399. err = errors.New("获取X轴的品种指标配置信息失败,Err:" + err.Error())
  400. return
  401. }
  402. yList, err := cross_varietyModel.GetChartTagVarietyListByTagAndVariety(tagY, varietyList)
  403. if err != nil {
  404. err = errors.New("获取Y轴的品种指标配置信息失败,Err:" + err.Error())
  405. return
  406. }
  407. baseVarietyIdMap := make(map[int]int)
  408. for _, v := range xList {
  409. baseVarietyIdMap[v.ChartVarietyId] = v.ChartVarietyId
  410. }
  411. needVarietyIdMap := make(map[int]int)
  412. for _, v := range yList {
  413. if val, ok := baseVarietyIdMap[v.ChartVarietyId]; ok {
  414. needVarietyIdMap[v.ChartVarietyId] = val
  415. }
  416. }
  417. for _, v := range xList {
  418. if _, ok := needVarietyIdMap[v.ChartVarietyId]; ok {
  419. xVarietyEdbMap[v.ChartVarietyId] = v.EdbInfoId
  420. edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
  421. }
  422. }
  423. for _, v := range yList {
  424. if _, ok := needVarietyIdMap[v.ChartVarietyId]; ok {
  425. yVarietyEdbMap[v.ChartVarietyId] = v.EdbInfoId
  426. edbInfoIdList = append(edbInfoIdList, v.EdbInfoId)
  427. }
  428. }
  429. return
  430. }
  431. func AddChartInfo(req request.AddChartReq, sysUser *system.Admin, lang string) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  432. isSendEmail = true
  433. source := utils.CHART_SOURCE_CROSS_HEDGING
  434. req.ChartName = strings.Trim(req.ChartName, " ")
  435. if req.ChartName == "" {
  436. errMsg = "请填写图表名称!"
  437. err = errors.New(errMsg)
  438. isSendEmail = false
  439. return
  440. }
  441. if req.TagX <= 0 {
  442. errMsg = "请选择X轴坐标的标签!"
  443. err = errors.New(errMsg)
  444. isSendEmail = false
  445. return
  446. }
  447. if req.TagY <= 0 {
  448. errMsg = "请选择Y轴坐标的标签!"
  449. err = errors.New(errMsg)
  450. isSendEmail = false
  451. return
  452. }
  453. if req.CalculateValue <= 0 {
  454. errMsg = "请设置时间长度!"
  455. err = errors.New(errMsg)
  456. isSendEmail = false
  457. return
  458. }
  459. if req.CalculateUnit == `` {
  460. errMsg = "请设置时间频度!"
  461. err = errors.New(errMsg)
  462. isSendEmail = false
  463. return
  464. }
  465. if req.PercentType != utils.PercentCalculateTypeRange && req.PercentType != utils.PercentCalculateTypeNum {
  466. errMsg = "请选择百分位"
  467. err = errors.New(errMsg)
  468. isSendEmail = false
  469. return
  470. }
  471. if len(req.VarietyList) < 0 {
  472. errMsg = "请选择品种!"
  473. err = errors.New(errMsg)
  474. isSendEmail = false
  475. return
  476. }
  477. dateConfigList := len(req.DateConfigList)
  478. if dateConfigList < 0 {
  479. errMsg = "请选择日期!"
  480. err = errors.New(errMsg)
  481. isSendEmail = false
  482. return
  483. }
  484. if dateConfigList > 5 {
  485. errMsg = "日期数量已达上限!"
  486. err = errors.New(errMsg)
  487. isSendEmail = false
  488. return
  489. }
  490. extraConfigByte, err := json.Marshal(req)
  491. if err != nil {
  492. return
  493. }
  494. chartClassify, err := data_manage.GetCrossVarietyChartClassifyBySysUserId(sysUser.AdminId)
  495. if err != nil {
  496. if !utils.IsErrNoRow(err) {
  497. errMsg = "获取分类信息失败"
  498. err = errors.New("获取分类信息失败,Err:" + err.Error())
  499. return
  500. }
  501. err = nil
  502. chartClassify, err, errMsg, isSendEmail = data.AddChartClassify(sysUser.RealName, 0, 1, source, lang, sysUser)
  503. if err != nil {
  504. return
  505. }
  506. }
  507. edbInfoIdArr := make([]int, 0)
  508. {
  509. var xTagInfo, yTagInfo *cross_varietyModel.ChartTag
  510. {
  511. tagList, tmpErr := cross_varietyModel.GetTagListByIdList([]int{req.TagX, req.TagY})
  512. if tmpErr != nil {
  513. err = tmpErr
  514. return
  515. }
  516. for _, v := range tagList {
  517. if v.ChartTagId == req.TagX {
  518. xTagInfo = v
  519. } else if v.ChartTagId == req.TagY {
  520. yTagInfo = v
  521. }
  522. }
  523. }
  524. if xTagInfo == nil {
  525. errMsg = "找不到对应的X轴标签"
  526. err = errors.New(errMsg)
  527. return
  528. }
  529. if yTagInfo == nil {
  530. errMsg = "找不到对应的Y轴标签"
  531. err = errors.New(errMsg)
  532. return
  533. }
  534. _, _, edbInfoIdList, tmpErr := GetXYEdbIdList(req.TagX, req.TagY, req.VarietyList)
  535. if tmpErr != nil {
  536. err = errors.New("获取标签配置的品种失败,ERR:" + tmpErr.Error())
  537. return
  538. }
  539. if len(edbInfoIdList) <= 0 {
  540. errMsg = "品种未配置指标"
  541. err = errors.New(errMsg)
  542. isSendEmail = false
  543. return
  544. }
  545. edbInfoIdArr = edbInfoIdList
  546. mappingList, tmpErr := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdList)
  547. if tmpErr != nil {
  548. errMsg = "获取指标信息失败"
  549. err = errors.New("获取指标信息失败,ERR:" + tmpErr.Error())
  550. return
  551. }
  552. if len(mappingList) <= 0 {
  553. errMsg = "关联指标为空"
  554. err = errors.New(errMsg)
  555. isSendEmail = false
  556. return
  557. }
  558. }
  559. var chartInfoId int
  560. chartInfo = new(data_manage.ChartInfo)
  561. chartInfo.ChartName = req.ChartName
  562. chartInfo.ChartNameEn = req.ChartNameEn
  563. chartInfo.SysUserId = sysUser.AdminId
  564. chartInfo.SysUserRealName = sysUser.RealName
  565. chartInfo.ChartImage = req.ChartImage
  566. chartInfo.CreateTime = time.Now()
  567. chartInfo.ModifyTime = time.Now()
  568. chartInfo.IsSetName = 0
  569. timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
  570. chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
  571. chartInfo.ChartType = 9 // 相关性图
  572. chartInfo.Calendar = "公历"
  573. chartInfo.DateType = 6
  574. chartInfo.LeftMin = req.LeftMin
  575. chartInfo.LeftMax = req.LeftMax
  576. chartInfo.XMin = req.XMin
  577. chartInfo.XMax = req.XMax
  578. chartInfo.Source = source
  579. chartInfo.ExtraConfig = string(extraConfigByte)
  580. chartInfo.ChartImage = req.ChartImage
  581. chartInfo.ChartThemeId = req.ChartThemeId
  582. chartInfo.SourcesFrom = req.SourcesFrom
  583. chartInfo.Instructions = req.Instructions
  584. chartInfo.MarkersLines = req.MarkersLines
  585. chartInfo.MarkersAreas = req.MarkersAreas
  586. chartVarietyMappingList := make([]*cross_varietyModel.ChartVarietyMapping, 0)
  587. for _, varietyId := range req.VarietyList {
  588. chartVarietyMappingList = append(chartVarietyMappingList, &cross_varietyModel.ChartVarietyMapping{
  589. Id: 0,
  590. ChartInfoId: 0,
  591. ChartVarietyId: varietyId,
  592. ModifyTime: time.Now(),
  593. CreateTime: time.Now(),
  594. })
  595. }
  596. chartInfoCrossVariety := &cross_varietyModel.ChartInfoCrossVariety{
  597. Id: 0,
  598. ChartInfoId: 0,
  599. ChartXTagId: req.TagX,
  600. ChartYTagId: req.TagY,
  601. CalculateValue: req.CalculateValue,
  602. CalculateUnit: req.CalculateUnit,
  603. ModifyTime: time.Now(),
  604. CreateTime: time.Now(),
  605. }
  606. chartInfoId, e := cross_varietyModel.CreateChart(chartInfo, chartClassify, chartVarietyMappingList, chartInfoCrossVariety)
  607. if e != nil {
  608. errMsg = "操作失败"
  609. err = errors.New("新增相关性图表失败, Err: " + e.Error())
  610. return
  611. }
  612. chartInfo.ChartInfoId = chartInfoId
  613. _ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartInfo)
  614. go data.EsAddOrEditChartInfo(chartInfoId)
  615. return
  616. }
  617. func EditChartInfo(req request.EditChartReq, sysUser *system.Admin, lang string) (chartItem *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
  618. isSendEmail = true
  619. chartItem, err = data_manage.GetChartInfoById(req.ChartInfoId)
  620. if err != nil {
  621. if utils.IsErrNoRow(err) {
  622. errMsg = "图表已被删除,请刷新页面"
  623. err = errors.New(errMsg)
  624. isSendEmail = false
  625. return
  626. }
  627. errMsg = "获取图表信息失败"
  628. err = errors.New("获取图表信息失败,Err:" + err.Error())
  629. return
  630. }
  631. if chartItem.Source != utils.CHART_SOURCE_CROSS_HEDGING {
  632. errMsg = "该图不是跨品种分析图表!"
  633. err = errors.New(errMsg)
  634. isSendEmail = false
  635. return
  636. }
  637. req.ChartName = strings.Trim(req.ChartName, " ")
  638. if req.ChartName == "" {
  639. errMsg = "请填写图表名称!"
  640. err = errors.New(errMsg)
  641. isSendEmail = false
  642. return
  643. }
  644. if req.TagX <= 0 {
  645. errMsg = "请选择X轴坐标的标签!"
  646. err = errors.New(errMsg)
  647. isSendEmail = false
  648. return
  649. }
  650. if req.TagY <= 0 {
  651. errMsg = "请选择Y轴坐标的标签!"
  652. err = errors.New(errMsg)
  653. isSendEmail = false
  654. return
  655. }
  656. if req.CalculateValue <= 0 {
  657. errMsg = "请设置时间长度!"
  658. err = errors.New(errMsg)
  659. isSendEmail = false
  660. return
  661. }
  662. if req.CalculateUnit == `` {
  663. errMsg = "请设置时间频度!"
  664. err = errors.New(errMsg)
  665. isSendEmail = false
  666. return
  667. }
  668. if req.PercentType != utils.PercentCalculateTypeRange && req.PercentType != utils.PercentCalculateTypeNum {
  669. errMsg = "请选择百分位"
  670. err = errors.New(errMsg)
  671. isSendEmail = false
  672. return
  673. }
  674. if len(req.VarietyList) < 0 {
  675. errMsg = "请选择品种!"
  676. err = errors.New(errMsg)
  677. isSendEmail = false
  678. return
  679. }
  680. dateConfigList := len(req.DateConfigList)
  681. if dateConfigList < 0 {
  682. errMsg = "请选择日期!"
  683. err = errors.New(errMsg)
  684. isSendEmail = false
  685. return
  686. }
  687. if dateConfigList > 5 {
  688. errMsg = "日期数量已达上限!"
  689. err = errors.New(errMsg)
  690. isSendEmail = false
  691. return
  692. }
  693. extraConfigByte, err := json.Marshal(req)
  694. if err != nil {
  695. return
  696. }
  697. ok := data.CheckOpChartPermission(sysUser, chartItem.SysUserId, true)
  698. if !ok {
  699. errMsg = "没有该图表的操作权限"
  700. err = errors.New(errMsg)
  701. isSendEmail = false
  702. return
  703. }
  704. edbInfoIdArr := make([]int, 0)
  705. {
  706. var xTagInfo, yTagInfo *cross_varietyModel.ChartTag
  707. {
  708. tagList, tmpErr := cross_varietyModel.GetTagListByIdList([]int{req.TagX, req.TagY})
  709. if tmpErr != nil {
  710. err = tmpErr
  711. return
  712. }
  713. for _, v := range tagList {
  714. if v.ChartTagId == req.TagX {
  715. xTagInfo = v
  716. } else if v.ChartTagId == req.TagY {
  717. yTagInfo = v
  718. }
  719. }
  720. }
  721. if xTagInfo == nil {
  722. errMsg = "找不到对应的X轴标签"
  723. err = errors.New(errMsg)
  724. return
  725. }
  726. if yTagInfo == nil {
  727. errMsg = "找不到对应的Y轴标签"
  728. err = errors.New(errMsg)
  729. return
  730. }
  731. _, _, edbInfoIdList, tmpErr := GetXYEdbIdList(req.TagX, req.TagY, req.VarietyList)
  732. if tmpErr != nil {
  733. err = errors.New("获取标签配置的品种失败,ERR:" + tmpErr.Error())
  734. return
  735. }
  736. if len(edbInfoIdList) <= 0 {
  737. errMsg = "品种未配置指标"
  738. err = errors.New(errMsg)
  739. isSendEmail = false
  740. return
  741. }
  742. edbInfoIdArr = edbInfoIdList
  743. mappingList, tmpErr := data_manage.GetChartEdbMappingListByEdbInfoIdList(edbInfoIdList)
  744. if tmpErr != nil {
  745. errMsg = "获取指标信息失败"
  746. err = errors.New("获取指标信息失败,ERR:" + tmpErr.Error())
  747. return
  748. }
  749. if len(mappingList) <= 0 {
  750. errMsg = "关联指标为空"
  751. err = errors.New(errMsg)
  752. isSendEmail = false
  753. return
  754. }
  755. }
  756. switch lang {
  757. case utils.EnLangVersion:
  758. chartItem.ChartNameEn = req.ChartName
  759. default:
  760. chartItem.ChartName = req.ChartName
  761. }
  762. chartItem.ExtraConfig = string(extraConfigByte)
  763. chartItem.ModifyTime = time.Now()
  764. chartItem.LeftMin = req.LeftMin
  765. chartItem.LeftMax = req.LeftMax
  766. chartItem.XMin = req.XMin
  767. chartItem.XMax = req.XMax
  768. chartUpdateCols := []string{"ChartName", "ChartNameEn", "ExtraConfig", "ModifyTime", "LeftMin", "LeftMax", "XMin", "XMax"}
  769. chartInfoCrossVariety, err := cross_varietyModel.GetChartInfoCrossVarietyByChartInfoId(chartItem.ChartInfoId)
  770. if err != nil {
  771. return
  772. }
  773. chartInfoCrossVariety.ChartXTagId = req.TagX
  774. chartInfoCrossVariety.ChartYTagId = req.TagY
  775. chartInfoCrossVariety.CalculateValue = req.CalculateValue
  776. chartInfoCrossVariety.CalculateUnit = req.CalculateUnit
  777. chartInfoCrossVariety.ModifyTime = time.Now()
  778. chartInfoCrossVarietyUpdateCols := []string{"ChartXTagId", "ChartYTagId", "CalculateValue", "CalculateUnit", "ModifyTime"}
  779. chartVarietyMappingList := make([]*cross_varietyModel.ChartVarietyMapping, 0)
  780. for _, varietyId := range req.VarietyList {
  781. chartVarietyMappingList = append(chartVarietyMappingList, &cross_varietyModel.ChartVarietyMapping{
  782. Id: 0,
  783. ChartInfoId: 0,
  784. ChartVarietyId: varietyId,
  785. ModifyTime: time.Now(),
  786. CreateTime: time.Now(),
  787. })
  788. }
  789. err = cross_varietyModel.EditChart(chartItem, chartVarietyMappingList, chartInfoCrossVariety,
  790. chartUpdateCols, chartInfoCrossVarietyUpdateCols)
  791. if err != nil {
  792. errMsg = "保存失败"
  793. err = errors.New("保存失败,Err:" + err.Error())
  794. return
  795. }
  796. resp := new(data_manage.AddChartInfoResp)
  797. resp.ChartInfoId = chartItem.ChartInfoId
  798. resp.UniqueCode = chartItem.UniqueCode
  799. _ = data.SaveChartEdbInfoRelation(edbInfoIdArr, chartItem)
  800. go data.EsAddOrEditChartInfo(chartItem.ChartInfoId)
  801. go data.EsAddOrEditMyChartInfoByChartInfoId(chartItem.ChartInfoId)
  802. return
  803. }
  804. func ModifyChartEdbMapping(tagId int) {
  805. errMsgList := make([]string, 0)
  806. var err error
  807. defer func() {
  808. if err != nil {
  809. errMsgList = append(errMsgList, err.Error())
  810. }
  811. if len(errMsgList) > 0 {
  812. utils.FileLog.Error("修改跨品种分析的图表关联指标失败:\n" + strings.Join(errMsgList, "\n"))
  813. }
  814. }()
  815. list, err := cross_varietyModel.GeChartInfoCrossVarietyListByTagId(tagId)
  816. if err != nil {
  817. return
  818. }
  819. chartInfoIdList := make([]int, 0)
  820. tagIdList := make([]int, 0)
  821. tagIdMap := make(map[int]int, 0)
  822. for _, v := range list {
  823. chartInfoIdList = append(chartInfoIdList, v.ChartInfoId)
  824. if _, ok := tagIdMap[v.ChartXTagId]; !ok {
  825. tagIdList = append(tagIdList, v.ChartXTagId)
  826. tagIdMap[v.ChartXTagId] = 1
  827. }
  828. if _, ok := tagIdMap[v.ChartYTagId]; !ok {
  829. tagIdList = append(tagIdList, v.ChartYTagId)
  830. tagIdMap[v.ChartYTagId] = 1
  831. }
  832. }
  833. chartTagVarietyList, err := cross_varietyModel.GetChartTagVarietyListByTagIdList(tagIdList)
  834. if err != nil {
  835. return
  836. }
  837. allEdbInfoIdList := make([]int, 0)
  838. tagVarietyEdbMap := make(map[string][]int)
  839. for _, v := range chartTagVarietyList {
  840. if v.EdbInfoId <= 0 {
  841. continue
  842. }
  843. key := fmt.Sprint(v.ChartTagId, "_", v.ChartVarietyId)
  844. tagVarietyEdbList, ok := tagVarietyEdbMap[key]
  845. if !ok {
  846. tagVarietyEdbList = make([]int, 0)
  847. }
  848. tagVarietyEdbMap[key] = append(tagVarietyEdbList, v.EdbInfoId)
  849. allEdbInfoIdList = append(allEdbInfoIdList, v.EdbInfoId)
  850. }
  851. edbInfoMap := make(map[int]*data_manage.EdbInfo)
  852. if len(allEdbInfoIdList) > 0 {
  853. allEdbInfoList, tmpErr := data_manage.GetEdbInfoByIdList(allEdbInfoIdList)
  854. if tmpErr != nil {
  855. err = tmpErr
  856. return
  857. }
  858. for _, v := range allEdbInfoList {
  859. edbInfoMap[v.EdbInfoId] = v
  860. }
  861. }
  862. chartVarietyMappingList, err := cross_varietyModel.GetChartVarietyMappingListByChartInfoIdList(chartInfoIdList)
  863. if err != nil {
  864. return
  865. }
  866. chartVarietyMappingListMap := make(map[int][]int)
  867. for _, v := range chartVarietyMappingList {
  868. if v.ChartInfoId <= 0 {
  869. continue
  870. }
  871. varietyMappingList, ok := chartVarietyMappingListMap[v.ChartInfoId]
  872. if !ok {
  873. varietyMappingList = make([]int, 0)
  874. }
  875. chartVarietyMappingListMap[v.ChartInfoId] = append(varietyMappingList, v.ChartVarietyId)
  876. }
  877. for _, v := range list {
  878. edbInfoList := make([]*data_manage.EdbInfo, 0)
  879. edbInfoIdMap := make(map[int]int, 0)
  880. varietyIdList, ok := chartVarietyMappingListMap[v.ChartInfoId]
  881. if ok {
  882. for _, varietyId := range varietyIdList {
  883. key := fmt.Sprint(v.ChartXTagId, "_", varietyId)
  884. if tmpEdbInfoIdList, ok2 := tagVarietyEdbMap[key]; ok2 {
  885. for _, edbInfoId := range tmpEdbInfoIdList {
  886. if _, ok3 := edbInfoIdMap[edbInfoId]; !ok3 {
  887. if edbInfo, ok4 := edbInfoMap[edbInfoId]; ok4 {
  888. edbInfoList = append(edbInfoList, edbInfo)
  889. }
  890. edbInfoIdMap[edbInfoId] = edbInfoId
  891. }
  892. }
  893. }
  894. key = fmt.Sprint(v.ChartYTagId, "_", varietyId)
  895. if tmpEdbInfoIdList, ok2 := tagVarietyEdbMap[key]; ok2 {
  896. for _, edbInfoId := range tmpEdbInfoIdList {
  897. if _, ok3 := edbInfoIdMap[edbInfoId]; !ok3 {
  898. if edbInfo, ok4 := edbInfoMap[edbInfoId]; ok4 {
  899. edbInfoList = append(edbInfoList, edbInfo)
  900. }
  901. edbInfoIdMap[edbInfoId] = edbInfoId
  902. }
  903. }
  904. }
  905. }
  906. }
  907. tmpErr := data_manage.ModifyChartEdbMapping(v.ChartInfoId, edbInfoList)
  908. if tmpErr != nil {
  909. errMsgList = append(errMsgList, fmt.Sprint("修改", v.ChartInfoId, "失败,err:", tmpErr))
  910. }
  911. }
  912. return
  913. }