excel_info.go 16 KB

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