excel_info.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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"
  7. "eta/eta_api/models/data_manage/excel/request"
  8. "eta/eta_api/models/data_manage/excel/response"
  9. "eta/eta_api/models/system"
  10. "eta/eta_api/services/data"
  11. "eta/eta_api/services/data/data_manage_permission"
  12. "eta/eta_api/utils"
  13. "fmt"
  14. "sort"
  15. "time"
  16. )
  17. // GetExcelDetailInfoByExcelInfoId 根据表格id获取表格详情
  18. func GetExcelDetailInfoByExcelInfoId(excelInfoId, sysUserId int, lang string) (excelDetail response.ExcelInfoDetail, errMsg string, err error) {
  19. errMsg = `获取失败`
  20. //获取eta表格信息
  21. excelInfo, err := excel.GetExcelInfoById(excelInfoId)
  22. if err != nil {
  23. err = errors.New("获取ETA表格信息失败,Err:" + err.Error())
  24. if err.Error() == utils.ErrNoRow() {
  25. errMsg = "ETA表格被删除,请刷新页面"
  26. err = errors.New("ETA表格被删除,请刷新页面,Err:" + err.Error())
  27. }
  28. return
  29. }
  30. return formatExcelInfo2Detail(excelInfo, sysUserId, lang)
  31. }
  32. // GetExcelDetailInfoByUnicode 根据表格编码获取表格详情
  33. func GetExcelDetailInfoByUnicode(unicode string, sysUserId int, lang string) (excelDetail response.ExcelInfoDetail, errMsg string, err error) {
  34. errMsg = `获取失败`
  35. // 获取eta表格信息
  36. excelInfo, err := excel.GetExcelInfoByUnicode(unicode)
  37. if err != nil {
  38. err = errors.New("获取ETA表格信息失败,Err:" + err.Error())
  39. if err.Error() == utils.ErrNoRow() {
  40. errMsg = "ETA表格被删除,请刷新页面"
  41. err = errors.New("ETA表格被删除,请刷新页面,Err:" + err.Error())
  42. }
  43. return
  44. }
  45. return formatExcelInfo2Detail(excelInfo, sysUserId, lang)
  46. }
  47. func formatExcelInfo2Detail(excelInfo *excel.ExcelInfo, sysUserId int, lang string) (excelDetail response.ExcelInfoDetail, errMsg string, err error) {
  48. // 数据权限
  49. haveOperaAuth, err := data_manage_permission.CheckExcelPermissionByExcelInfoId(excelInfo.ExcelInfoId, excelInfo.ExcelClassifyId, excelInfo.IsJoinPermission, sysUserId)
  50. if err != nil {
  51. err = errors.New("获取表格权限信息失败,Err" + err.Error())
  52. return
  53. }
  54. excelDetail = response.ExcelInfoDetail{
  55. ExcelInfoId: excelInfo.ExcelInfoId,
  56. Source: excelInfo.Source,
  57. ExcelType: excelInfo.ExcelType,
  58. ExcelName: excelInfo.ExcelName,
  59. UniqueCode: excelInfo.UniqueCode,
  60. ExcelClassifyId: excelInfo.ExcelClassifyId,
  61. SysUserId: excelInfo.SysUserId,
  62. SysUserRealName: excelInfo.SysUserRealName,
  63. Content: excelInfo.Content,
  64. ExcelImage: excelInfo.ExcelImage,
  65. FileUrl: excelInfo.FileUrl,
  66. Sort: excelInfo.Sort,
  67. IsDelete: excelInfo.IsDelete,
  68. ModifyTime: excelInfo.ModifyTime,
  69. CreateTime: excelInfo.CreateTime,
  70. TableData: nil,
  71. HaveOperaAuth: haveOperaAuth,
  72. ParentId: excelInfo.ParentId,
  73. BalanceType: excelInfo.BalanceType,
  74. UpdateUserId: excelInfo.UpdateUserId,
  75. UpdateUserRealName: excelInfo.UpdateUserRealName,
  76. }
  77. // 无权限,不需要返回数据
  78. if !haveOperaAuth {
  79. return
  80. }
  81. switch excelInfo.Source {
  82. case utils.TIME_TABLE: // 时间序列表格
  83. var tableDataConfig TableDataConfig
  84. err = json.Unmarshal([]byte(excelDetail.Content), &tableDataConfig)
  85. if err != nil {
  86. err = errors.New("表格json转结构体失败,Err:" + err.Error())
  87. return
  88. }
  89. result, tmpErr := GetDataByTableDataConfig(tableDataConfig)
  90. if tmpErr != nil {
  91. err = errors.New("获取最新的表格数据失败,Err:" + tmpErr.Error())
  92. return
  93. }
  94. if len(result.EdbInfoIdList) > 0 {
  95. classifyIdList := make([]int, 0)
  96. for _, v := range result.Data {
  97. classifyIdList = append(classifyIdList, v.ClassifyId)
  98. }
  99. classifyMap := make(map[int]*data_manage.EdbClassify)
  100. classifyList, tmpErr := data_manage.GetEdbClassifyByIdList(classifyIdList)
  101. if tmpErr != nil {
  102. err = errors.New("获取分类列表失败,Err:" + tmpErr.Error())
  103. return
  104. }
  105. for _, v := range classifyList {
  106. classifyMap[v.ClassifyId] = v
  107. }
  108. // 获取所有有权限的指标和分类
  109. permissionEdbIdList, permissionClassifyIdList, tmpErr := data_manage_permission.GetUserEdbAndClassifyPermissionList(sysUserId, 0, 0)
  110. if err != nil {
  111. err = errors.New("获取所有有权限的指标和分类失败,Err:" + tmpErr.Error())
  112. return
  113. }
  114. for i, v := range result.Data {
  115. if currClassify, ok := classifyMap[v.ClassifyId]; ok {
  116. result.Data[i].HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
  117. }
  118. }
  119. }
  120. excelDetail.TableData = result
  121. case utils.MIXED_TABLE, utils.BALANCE_TABLE: // 混合表格 平衡表
  122. var result request.MixedTableReq
  123. err = json.Unmarshal([]byte(excelDetail.Content), &result)
  124. if err != nil {
  125. err = errors.New("表格json转结构体失败,Err:" + err.Error())
  126. return
  127. }
  128. newData, tmpErr, tmpErrMsg := GetMixedTableCellData(result, lang)
  129. if tmpErr != nil {
  130. errMsg = "获取失败"
  131. if tmpErrMsg != `` {
  132. errMsg = tmpErrMsg
  133. }
  134. err = errors.New("获取最新的数据失败,Err:" + tmpErr.Error())
  135. return
  136. }
  137. result.Data = newData
  138. excelDetail.TableData = result
  139. }
  140. return
  141. }
  142. // GetExcelInfoOpButton 获取ETA表格的操作权限
  143. func GetExcelInfoOpButton(sysUser *system.Admin, belongUserId, source int, haveOperaAuth bool) (button response.ExcelInfoDetailButton) {
  144. // 如果没有数据权限,那么直接返回
  145. if !haveOperaAuth {
  146. return
  147. }
  148. //非管理员角色查看其他用户创建的表格,可刷新、另存为、下载表格;
  149. button.RefreshButton = true
  150. button.CopyButton = true
  151. button.DownloadButton = true
  152. // 1、本用户创建的表格,可编辑、刷新、另存为、下载、删除,删除需二次确认;
  153. // 2、管理员角色对所有表格有如上权限;
  154. // 3、在线excel所有人都能编辑
  155. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN || sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN || sysUser.AdminId == belongUserId || source == utils.EXCEL_DEFAULT {
  156. button.OpButton = true
  157. button.DeleteButton = true
  158. }
  159. // 自定义分析
  160. if source == utils.CUSTOM_ANALYSIS_TABLE {
  161. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN || sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_ADMIN || sysUser.AdminId == belongUserId {
  162. button.OpEdbButton = true // 生成、查看指标按钮
  163. button.RefreshEdbButton = true // 刷新指标按钮
  164. }
  165. }
  166. //todo 如果是平衡表,判断是否是协作人
  167. return
  168. }
  169. // GetFirstEdbDataList 获取第一列的数据
  170. func GetFirstEdbDataList(edbInfo *data_manage.EdbInfo, num int, manualDateList []string) (resultDataList []request.ManualDataReq, err error) {
  171. var dataList []*data_manage.EdbDataList
  172. switch edbInfo.EdbInfoType {
  173. case 0:
  174. dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
  175. case 1:
  176. _, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
  177. default:
  178. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  179. }
  180. if err != nil {
  181. return
  182. }
  183. // 获取需要的期数
  184. lenData := len(dataList)
  185. if lenData <= 0 {
  186. return
  187. }
  188. tmpManualDateNum := 0 // 手工数据的期数
  189. lenManualDate := len(manualDateList)
  190. if lenManualDate > 0 {
  191. sortDateList := manualDateList
  192. baseDateList := utils.StrArr{}
  193. baseDateList = append(baseDateList, sortDateList...)
  194. sort.Sort(baseDateList)
  195. sortDateList = append([]string{}, baseDateList...)
  196. lastData := dataList[lenData-1]
  197. lastDataDate, tmpErr := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
  198. if tmpErr != nil {
  199. err = tmpErr
  200. return
  201. }
  202. // 遍历倒序后的日期,然后匹配在实际数据之后日期的个数
  203. for _, tmpDateStr := range sortDateList {
  204. tmpDate, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDateStr, time.Local)
  205. if tmpErr != nil {
  206. err = tmpErr
  207. return
  208. }
  209. if tmpDate.After(lastDataDate) {
  210. tmpManualDateNum++
  211. continue
  212. }
  213. break
  214. }
  215. }
  216. // 需要的期数减去手工数据的期数,这才是A列指标需要的数据
  217. num = num - tmpManualDateNum
  218. if num > lenData {
  219. num = lenData
  220. }
  221. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, edbInfo.LatestDate, time.Local)
  222. for i := 1; i <= num; i++ {
  223. dataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[lenData-i].DataTime, time.Local)
  224. dataType := 1
  225. // 如果是预测指标,且当前值的日期,晚于实际日期,那么是预测值
  226. if edbInfo.EdbInfoType == 1 && dataTime.After(latestDateTime) {
  227. dataType = 5
  228. }
  229. resultDataList = append(resultDataList, request.ManualDataReq{
  230. DataType: dataType,
  231. DataTime: dataList[lenData-i].DataTime,
  232. ShowValue: fmt.Sprint(dataList[lenData-i].Value),
  233. Value: fmt.Sprint(dataList[lenData-i].Value),
  234. DataTimeType: 1,
  235. })
  236. }
  237. return
  238. }
  239. // GetOtherEdbDataList 获取其他列的数据
  240. func GetOtherEdbDataList(edbInfo *data_manage.EdbInfo, dateList []string) (resultDataList []request.ManualDataReq, err error) {
  241. lenDate := len(dateList)
  242. if lenDate <= 0 {
  243. return
  244. }
  245. sortDateList := dateList
  246. baseDateList := utils.StrArr{}
  247. baseDateList = append(baseDateList, sortDateList...)
  248. sort.Sort(baseDateList)
  249. sortDateList = append([]string{}, baseDateList...)
  250. endDateTime, err := time.ParseInLocation(utils.FormatDate, sortDateList[0], time.Local)
  251. if err != nil {
  252. return
  253. }
  254. firstDateTime, err := time.ParseInLocation(utils.FormatDate, sortDateList[lenDate-1], time.Local)
  255. if err != nil {
  256. return
  257. }
  258. var dataList []*data_manage.EdbDataList
  259. switch edbInfo.EdbInfoType {
  260. case 0:
  261. dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
  262. case 1:
  263. _, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
  264. default:
  265. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  266. }
  267. if err != nil {
  268. return
  269. }
  270. // 获取日期内的数据(包含开始日期前一个日期,以及 结束日期后一个日期,目的为了做空日期时的 插值法兼容)
  271. baseDataList := make([]*data_manage.EdbDataList, 0)
  272. var lastData *data_manage.EdbDataList
  273. var isInsert bool
  274. for _, data := range dataList {
  275. tmpDate := data.DataTime
  276. tmpDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
  277. if tmpErr != nil {
  278. err = tmpErr
  279. return
  280. }
  281. if tmpDateTime.Before(firstDateTime) {
  282. lastData = data
  283. continue
  284. }
  285. // 如果是第一次写入数据
  286. if !isInsert && lastData != nil {
  287. baseDataList = append(baseDataList, lastData)
  288. }
  289. if tmpDateTime.After(endDateTime) {
  290. baseDataList = append(baseDataList, data)
  291. break
  292. }
  293. baseDataList = append(baseDataList, data)
  294. isInsert = true
  295. }
  296. // 实际数据的日期map
  297. realValMap := make(map[string]string)
  298. for _, v := range baseDataList {
  299. realValMap[v.DataTime] = v.DataTime
  300. }
  301. // 插值法处理
  302. handleDataMap := make(map[string]float64)
  303. err = data.HandleDataByLinearRegression(baseDataList, handleDataMap)
  304. if err != nil {
  305. return
  306. }
  307. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, edbInfo.LatestDate, time.Local)
  308. // 对于不存在的数据做补充
  309. for _, date := range sortDateList {
  310. dataType := 1
  311. if _, ok := realValMap[date]; !ok {
  312. dataType = 2
  313. } else {
  314. dataTime, _ := time.ParseInLocation(utils.FormatDate, date, time.Local)
  315. // 如果是预测指标,且当前值的日期,晚于实际日期,那么是预测值
  316. if edbInfo.EdbInfoType == 1 && dataTime.After(latestDateTime) {
  317. dataType = 5
  318. }
  319. }
  320. var value, showValue string
  321. if tmpVal, ok := handleDataMap[date]; ok {
  322. value = fmt.Sprint(tmpVal)
  323. showValue = value
  324. } else {
  325. dataType = 3
  326. }
  327. resultDataList = append(resultDataList, request.ManualDataReq{
  328. DataType: dataType,
  329. DataTime: date,
  330. ShowValue: showValue,
  331. Value: value,
  332. })
  333. }
  334. return
  335. }
  336. // GetFirstHistoryEdbDataList 获取指标的历史的数据
  337. func GetFirstHistoryEdbDataList(edbInfo *data_manage.EdbInfo, num int, endDate string) (resultDataList []request.ManualDataReq, err error) {
  338. endDateTime, err := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
  339. if err != nil {
  340. return
  341. }
  342. var dataList []*data_manage.EdbDataList
  343. switch edbInfo.EdbInfoType {
  344. case 0:
  345. dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, endDate)
  346. case 1:
  347. _, dataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, endDate, true)
  348. default:
  349. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  350. }
  351. if err != nil {
  352. return
  353. }
  354. // 获取需要的期数
  355. lenData := len(dataList)
  356. if lenData <= 0 {
  357. return
  358. }
  359. lastData := dataList[lenData-1]
  360. lastDataDateTime, err := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
  361. if err != nil {
  362. return
  363. }
  364. if endDateTime.Equal(lastDataDateTime) || lastDataDateTime.After(endDateTime) {
  365. dataList = dataList[:lenData-1]
  366. lenData = len(dataList)
  367. }
  368. if num > lenData {
  369. num = lenData
  370. }
  371. latestDateTime, _ := time.ParseInLocation(utils.FormatDate, edbInfo.LatestDate, time.Local)
  372. for i := 1; i <= num; i++ {
  373. dataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[lenData-i].DataTime, time.Local)
  374. dataType := 1
  375. // 如果是预测指标,且当前值的日期,晚于实际日期,那么是预测值
  376. if edbInfo.EdbInfoType == 1 && dataTime.After(latestDateTime) {
  377. dataType = 5
  378. }
  379. resultDataList = append(resultDataList, request.ManualDataReq{
  380. DataType: dataType,
  381. DataTime: dataList[lenData-i].DataTime,
  382. ShowValue: fmt.Sprint(dataList[lenData-i].Value),
  383. Value: fmt.Sprint(dataList[lenData-i].Value),
  384. })
  385. }
  386. return
  387. }
  388. // GetEdbIdsFromExcelCodes 获取表格中的指标IDs
  389. func GetEdbIdsFromExcelCodes(excelCodes []string, sysUserId int, lang string) (edbIds []int, err error) {
  390. edbIds = make([]int, 0)
  391. edbIdExist := make(map[int]bool)
  392. for _, v := range excelCodes {
  393. // 表格详情
  394. detail, msg, e := GetExcelDetailInfoByUnicode(v, sysUserId, lang)
  395. if e != nil {
  396. err = fmt.Errorf("GetExcelDetailInfoByExcelInfoId err: %s, errMsg: %s", e.Error(), msg)
  397. return
  398. }
  399. // 自定义表格
  400. if detail.Source == utils.TIME_TABLE {
  401. jsonByte, e := json.Marshal(detail.TableData)
  402. if e != nil {
  403. err = fmt.Errorf("JSON格式化自定义表格数据失败, Err: %s", e.Error())
  404. return
  405. }
  406. var tableData request.TableDataReq
  407. if e = json.Unmarshal(jsonByte, &tableData); e != nil {
  408. err = fmt.Errorf("解析自定义表格数据失败, Err: %s", e.Error())
  409. return
  410. }
  411. for _, tv := range tableData.EdbInfoIdList {
  412. if edbIdExist[tv] {
  413. continue
  414. }
  415. edbIdExist[tv] = true
  416. edbIds = append(edbIds, tv)
  417. }
  418. }
  419. // 混合表格
  420. if detail.Source == utils.MIXED_TABLE {
  421. jsonByte, e := json.Marshal(detail.TableData)
  422. if e != nil {
  423. err = fmt.Errorf("JSON格式化混合表格数据失败, Err: %s", e.Error())
  424. return
  425. }
  426. var tableData request.MixedTableReq
  427. if e = json.Unmarshal(jsonByte, &tableData); e != nil {
  428. err = fmt.Errorf("解析混合表格数据失败, Err: %s", e.Error())
  429. return
  430. }
  431. if len(tableData.Data) > 0 {
  432. for _, td := range tableData.Data {
  433. for _, tv := range td {
  434. if tv.EdbInfoId > 0 && !edbIdExist[tv.EdbInfoId] {
  435. edbIdExist[tv.EdbInfoId] = true
  436. edbIds = append(edbIds, tv.EdbInfoId)
  437. }
  438. }
  439. }
  440. }
  441. }
  442. }
  443. return
  444. }
  445. // GetExcelEdbBatchRefreshKey 获取批量刷新表格指标缓存key
  446. func GetExcelEdbBatchRefreshKey(source string, primaryId, subId int) string {
  447. if source == `` {
  448. return ``
  449. }
  450. return fmt.Sprint("batch_refresh_excel_edb:", source, ":", primaryId, ":", subId)
  451. }