mixed_table.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. package excel
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_api/models/data_manage"
  6. "eta/eta_api/models/data_manage/excel/request"
  7. "eta/eta_api/services/data"
  8. "eta/eta_api/utils"
  9. "fmt"
  10. "strings"
  11. "time"
  12. )
  13. // GetMixedTableCellData 获取混合表格数据
  14. func GetMixedTableCellData(cellRelationConf string, config [][]request.MixedTableCellDataReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
  15. // 单元格关系配置x信息
  16. cellRelationConfMap := make(map[string]request.CellRelationConf)
  17. cellRelationConfList := make([]request.CellRelationConf, 0)
  18. if cellRelationConf != `` {
  19. err = json.Unmarshal([]byte(cellRelationConf), &cellRelationConfList)
  20. if err != nil {
  21. return
  22. }
  23. for _, v := range cellRelationConfList {
  24. cellRelationConfMap[v.Key] = v
  25. }
  26. }
  27. // 找出所有的关联指标id
  28. config, edbInfoIdList, _, err, errMsg := handleConfig(config)
  29. if err != nil {
  30. return
  31. }
  32. // 查询所有关联的指标信息
  33. edbInfoList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
  34. if err != nil {
  35. return
  36. }
  37. // 指标信息map
  38. edbInfoMap := make(map[int]*data_manage.EdbInfo)
  39. // 日度指标数据map
  40. edbDayDataListMap := make(map[int]map[string]float64)
  41. // 月度指标数据map
  42. edbMonthDataListMap := make(map[int]map[string]float64)
  43. // 日度指标数据map
  44. edbDataListMap := make(map[int][]*data_manage.EdbDataList)
  45. for _, edbInfo := range edbInfoList {
  46. edbInfoMap[edbInfo.EdbInfoId] = edbInfo
  47. dataList := make([]*data_manage.EdbDataList, 0)
  48. switch edbInfo.EdbInfoType {
  49. case 0:
  50. dataList, _ = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, ``, ``)
  51. case 1:
  52. _, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
  53. default:
  54. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  55. }
  56. dateValMap := make(map[string]float64)
  57. monthValMap := make(map[string]float64)
  58. for _, tmpData := range dataList {
  59. // 日度数据
  60. dateValMap[tmpData.DataTime] = tmpData.Value
  61. // 月度数据(取该月份的第一个数据)
  62. yearMonth := strings.Join(strings.Split(tmpData.DataTime, "-")[0:2], "-")
  63. if _, ok := monthValMap[yearMonth]; !ok {
  64. monthValMap[yearMonth] = tmpData.Value
  65. }
  66. }
  67. edbDayDataListMap[edbInfo.EdbInfoId] = dateValMap
  68. edbMonthDataListMap[edbInfo.EdbInfoId] = monthValMap
  69. edbDataListMap[edbInfo.EdbInfoId] = dataList
  70. }
  71. // 单元格实际绑定的信息map
  72. cellDataRelationMap := make(map[string]request.MixedTableCellDataReq, 0)
  73. // 处理指定指标的日期
  74. for k, row := range config {
  75. for i, cell := range row {
  76. // 单元格是日期类型,且是日导入指标日期(指标库的最新日期)
  77. if cell.DataType == request.DateDT && cell.DataTimeType == request.EdbDateDT {
  78. if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
  79. cell.ShowValue = edbInfo.EndDate
  80. cell.DataTime = edbInfo.EndDate
  81. config[k][i] = cell
  82. }
  83. }
  84. row[i] = cell
  85. cellDataRelationMap[cell.Uid] = cell
  86. }
  87. config[k] = row
  88. }
  89. type BaseCalculate struct {
  90. DataList []*data_manage.EdbDataList
  91. Frequency string `description:"需要转换的频度"`
  92. Formula interface{}
  93. Calendar string `description:"公历/农历"`
  94. MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
  95. MoveFrequency string `description:"移动频度"`
  96. FromFrequency string `description:"来源的频度"`
  97. Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
  98. }
  99. // 指标计算的结果map
  100. edbSourceDataMap := make(map[string]map[string]float64)
  101. for k, row := range config {
  102. for i, cell := range row {
  103. switch cell.DataType {
  104. case request.EdbDT: // 指标类型
  105. if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
  106. cell.ShowValue = edbInfo.EdbName
  107. }
  108. case request.InsertDataDT, request.PopInsertDataDT: // 数据类型
  109. if cell.DataTime == `` {
  110. // 指标的最新日期
  111. if dateValList, ok := edbDataListMap[cell.EdbInfoId]; ok {
  112. tmpLenData := len(dateValList)
  113. if tmpLenData > 0 {
  114. cell.ShowValue = utils.FormatTableDataShowValue(dateValList[tmpLenData-1].Value)
  115. }
  116. }
  117. } else {
  118. tmpDateList := strings.Split(cell.DataTime, "-")
  119. tmpDateValMap := make(map[string]float64)
  120. if len(tmpDateList) == 2 {
  121. //月度数据
  122. if dateValMap, ok := edbMonthDataListMap[cell.EdbInfoId]; ok {
  123. tmpDateValMap = dateValMap
  124. }
  125. } else {
  126. // 日度数据
  127. if dateValMap, ok := edbDayDataListMap[cell.EdbInfoId]; ok {
  128. tmpDateValMap = dateValMap
  129. }
  130. }
  131. if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
  132. //cell.ShowValue = fmt.Sprint(val)
  133. cell.ShowValue = utils.FormatTableDataShowValue(val)
  134. }
  135. }
  136. case request.InsertEdbCalculateDataDT: // 指标类型
  137. if cell.Uid == `951cab4c0c4dce3ab1c8b6498632a064` {
  138. fmt.Println("a")
  139. }
  140. if cell.Uid == "dd301ffe98b5e7009454de1f362c58d0" {
  141. fmt.Println("b")
  142. }
  143. // 日期
  144. var cellDateTime string
  145. // 日期关系配置不存在,则默认最新数据
  146. if relationConf, ok := cellRelationConfMap[cell.Uid]; ok {
  147. if relationConf.RelationDate.Key == `` {
  148. // 日期关系配置未绑定
  149. continue
  150. }
  151. // 配置
  152. relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
  153. if !ok {
  154. // 找不到对应日期的单元格
  155. continue
  156. }
  157. cellDateTime = relationCell.DataTime
  158. }
  159. var tmpDataMap map[string]float64
  160. key := utils.MD5(cell.Value)
  161. tmpDataMap, ok := edbSourceDataMap[key]
  162. if !ok {
  163. // 对应的配置值
  164. var tmpConfig request.CalculateConf
  165. err = json.Unmarshal([]byte(cell.Value), &tmpConfig)
  166. if err != nil {
  167. return
  168. }
  169. tmpDataList, ok := edbDataListMap[tmpConfig.EdbInfoId]
  170. if !ok {
  171. continue
  172. }
  173. edbInfo, ok := edbInfoMap[tmpConfig.EdbInfoId]
  174. if !ok {
  175. continue
  176. }
  177. req2 := &BaseCalculate{
  178. DataList: tmpDataList,
  179. Frequency: tmpConfig.Frequency,
  180. Formula: tmpConfig.Formula,
  181. Calendar: tmpConfig.Calendar,
  182. MoveType: tmpConfig.MoveType,
  183. MoveFrequency: tmpConfig.MoveFrequency,
  184. FromFrequency: edbInfo.Frequency,
  185. Source: tmpConfig.Source,
  186. }
  187. // 调用指标库去更新
  188. reqJson, tmpErr := json.Marshal(req2)
  189. if tmpErr != nil {
  190. utils.FileLog.Error(fmt.Sprintf("计算失败1,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  191. err = tmpErr
  192. return
  193. }
  194. respItem, tmpErr := data.BaseCalculate(string(reqJson))
  195. if tmpErr != nil {
  196. utils.FileLog.Error(fmt.Sprintf("计算失败2,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  197. err = tmpErr
  198. return
  199. }
  200. if respItem.Ret != 200 {
  201. utils.FileLog.Error(fmt.Sprintf("计算失败3,配置信息;%s;原因:%s;错误原因:%s", cell.Value, respItem.Msg, respItem.ErrMsg))
  202. continue
  203. }
  204. tmpDataMap = respItem.Data.DataMap
  205. // 计算结果存一份,万一存在重复的计算方式,那么省的重新计算一下
  206. edbSourceDataMap[key] = tmpDataMap
  207. if cellDateTime == `` && len(respItem.Data.DateList) > 0 {
  208. cellDateTime = respItem.Data.DateList[0]
  209. }
  210. }
  211. val := tmpDataMap[cellDateTime]
  212. cell.ShowValue = utils.FormatTableDataShowValue(val)
  213. }
  214. row[i] = cell
  215. }
  216. config[k] = row
  217. }
  218. newMixedTableCellDataList = config
  219. return
  220. }
  221. // handleConfig
  222. // @Description: 处理混合表格配置
  223. // @author: Roc
  224. // @datetime2023-10-27 13:24:53
  225. // @param configList [][]request.MixedTableCellDataReq
  226. // @return newConfig [][]request.MixedTableCellDataReq
  227. // @return edbInfoIdList []int
  228. // @return dataEdbInfoIdList []int
  229. // @return err error
  230. // @return errMsg string
  231. func handleConfig(configList [][]request.MixedTableCellDataReq) (newConfig [][]request.MixedTableCellDataReq, edbInfoIdList []int, dataEdbInfoIdList []int, err error, errMsg string) {
  232. edbInfoIdList = make([]int, 0)
  233. dataEdbInfoIdList = make([]int, 0)
  234. for ck, rowList := range configList {
  235. for rk, cell := range rowList {
  236. switch cell.DataType {
  237. case request.EdbDT: // 指标信息
  238. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  239. case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
  240. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  241. case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
  242. var config request.CalculateConf
  243. err = json.Unmarshal([]byte(cell.Value), &config)
  244. if err != nil {
  245. return
  246. }
  247. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  248. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  249. case request.DateDT: // 日期类型
  250. if cell.DataTimeType == request.EdbDateDT {
  251. var config request.EdbDateConf
  252. err = json.Unmarshal([]byte(cell.Value), &config)
  253. if err != nil {
  254. return
  255. }
  256. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  257. } else {
  258. date, tmpErr, tmpErrMsg := handleDate(cell.DataTimeType, cell.Value)
  259. if tmpErr != nil {
  260. err = tmpErr
  261. errMsg = tmpErrMsg
  262. return
  263. }
  264. rowList[rk].DataTime = date
  265. rowList[rk].ShowValue = date
  266. }
  267. }
  268. }
  269. configList[ck] = rowList
  270. }
  271. newConfig = configList
  272. return
  273. }
  274. // HandleDate
  275. // @Description: 日期处理
  276. // @author: Roc
  277. // @datetime2023-10-27 09:37:02
  278. // @param dataTimeType int
  279. // @param val string
  280. // @return date string
  281. // @return err error
  282. // @return errMsg string
  283. func HandleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
  284. return handleDate(dataTimeType, val)
  285. }
  286. // handleDate
  287. // @Description: 日期处理
  288. // @author: Roc
  289. // @datetime2023-10-27 09:36:49
  290. // @param dataTimeType int
  291. // @param val string
  292. // @return date string
  293. // @return err error
  294. // @return errMsg string
  295. func handleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
  296. if val == `` {
  297. errMsg = "错误的日期数据"
  298. err = errors.New(errMsg)
  299. return
  300. }
  301. switch dataTimeType {
  302. case request.CustomDateT: //手动输入日期
  303. date = val
  304. case request.SystemDateT: // 系统日期
  305. date, err, errMsg = handleSystemDateT(val)
  306. case request.EdbDateDT: // 导入指标日期(指标库的最新日期)
  307. default:
  308. errMsg = "错误的日期类型"
  309. err = errors.New(errMsg)
  310. return
  311. }
  312. return
  313. }
  314. // handleSystemDateT
  315. // @Description: 处理导入系统日期
  316. // @author: Roc
  317. // @datetime2023-10-27 09:36:21
  318. // @param confStr string
  319. // @return date string
  320. // @return err error
  321. // @return errMsg string
  322. func handleSystemDateT(confStr string) (date string, err error, errMsg string) {
  323. var config request.SystemDateConf
  324. err = json.Unmarshal([]byte(confStr), &config)
  325. if err != nil {
  326. return
  327. }
  328. switch config.Source {
  329. case request.SystemCurrDateT:
  330. date = time.Now().Format(utils.FormatDate)
  331. case request.SystemCalculateDateT:
  332. date, err, errMsg = handleSystemCalculateDateT(config.CalculateNum, config.CalculateFrequency)
  333. case request.SystemFrequencyDateT: // 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  334. date, err, errMsg = handleSystemAppointDateT(config.Day, config.Frequency)
  335. default:
  336. errMsg = "错误的日期日期导入方式"
  337. err = errors.New(fmt.Sprint("错误的日期日期导入方式:", config.Source))
  338. return
  339. }
  340. return
  341. }
  342. // handleSystemCalculateDateT
  343. // @Description: 处理系统日期计算后的日期
  344. // @author: Roc
  345. // @datetime2023-10-27 09:31:22
  346. // @param num int
  347. // @param frequency string
  348. // @return date string
  349. // @return err error
  350. // @return errMsg string
  351. func handleSystemCalculateDateT(num int, frequency string) (date string, err error, errMsg string) {
  352. if err != nil {
  353. return
  354. }
  355. currDate := time.Now()
  356. switch frequency {
  357. case "", "日":
  358. date = currDate.AddDate(0, 0, num).Format(utils.FormatDate)
  359. default:
  360. errMsg = "错误的日期频度:" + frequency
  361. err = errors.New(errMsg)
  362. return
  363. }
  364. return
  365. }
  366. // handleSystemAppointDateT
  367. // @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  368. // @author: Roc
  369. // @datetime2023-10-27 09:31:35
  370. // @param Frequency string
  371. // @param Day string
  372. // @return date string
  373. // @return err error
  374. // @return errMsg string
  375. func handleSystemAppointDateT(appointDay, frequency string) (date string, err error, errMsg string) {
  376. currDate := time.Now()
  377. switch frequency {
  378. case "本周":
  379. day := int(currDate.Weekday())
  380. if day == 0 { // 周日
  381. day = 7
  382. }
  383. num := 0
  384. switch appointDay {
  385. case "周一":
  386. num = 1
  387. case "周二":
  388. num = 2
  389. case "周三":
  390. num = 3
  391. case "周四":
  392. num = 4
  393. case "周五":
  394. num = 5
  395. case "周六":
  396. num = 6
  397. case "周日":
  398. num = 7
  399. }
  400. day = num - day
  401. date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
  402. case "本旬":
  403. day := currDate.Day()
  404. var tmpDate time.Time
  405. switch appointDay {
  406. case "第一天":
  407. if day <= 10 {
  408. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  409. } else if day <= 20 {
  410. tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
  411. } else {
  412. tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
  413. }
  414. case "最后一天":
  415. if day <= 10 {
  416. tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
  417. } else if day <= 20 {
  418. tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
  419. } else {
  420. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  421. }
  422. }
  423. date = tmpDate.Format(utils.FormatDate)
  424. case "本月":
  425. var tmpDate time.Time
  426. switch appointDay {
  427. case "第一天":
  428. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  429. case "最后一天":
  430. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  431. }
  432. date = tmpDate.Format(utils.FormatDate)
  433. case "本季":
  434. month := currDate.Month()
  435. var tmpDate time.Time
  436. switch appointDay {
  437. case "第一天":
  438. if month <= 3 {
  439. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  440. } else if month <= 6 {
  441. tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
  442. } else if month <= 9 {
  443. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  444. } else {
  445. tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
  446. }
  447. case "最后一天":
  448. if month <= 3 {
  449. tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
  450. } else if month <= 6 {
  451. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  452. } else if month <= 9 {
  453. tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
  454. } else {
  455. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  456. }
  457. }
  458. date = tmpDate.Format(utils.FormatDate)
  459. default:
  460. errMsg = "错误的日期频度:" + frequency
  461. err = errors.New(errMsg)
  462. return
  463. }
  464. return
  465. }