mixed_table.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828
  1. package table
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "eta/eta_chart_lib/models"
  6. "eta/eta_chart_lib/models/data_manage"
  7. "eta/eta_chart_lib/models/request"
  8. "eta/eta_chart_lib/services/data"
  9. "eta/eta_chart_lib/utils"
  10. "fmt"
  11. "github.com/shopspring/decimal"
  12. "github.com/yidane/formula"
  13. "sort"
  14. "strconv"
  15. "strings"
  16. "time"
  17. )
  18. // BaseCalculate
  19. // @Description: 指标数据计算请求
  20. type BaseCalculate struct {
  21. DataList []models.EdbDataItemList
  22. Frequency string `description:"需要转换的频度"`
  23. Formula interface{}
  24. Calendar string `description:"公历/农历"`
  25. MoveType int `description:"移动方式:1:领先(默认),2:滞后"`
  26. MoveFrequency string `description:"移动频度"`
  27. FromFrequency string `description:"来源的频度"`
  28. Source int `description:"1:累计值转月;2:累计值转季;3:同比值;4:同差值;5:N数值移动平均数计算;6:环比值;7:环差值;8:升频;9:降频;10:时间移位;11:超季节性;12:年化;13:累计值;14:累计值年初至今;15:指数修匀;16:日均值"`
  29. }
  30. // Cell
  31. // @Description: 单元格位置
  32. type Cell struct {
  33. Column int `description:"行"`
  34. Row int `description:"列"`
  35. CellInfo request.MixedTableCellDataReq `description:"对应的单元格信息"`
  36. }
  37. func GetMixedTableCellData(mixedTableReq request.MixedTableReq) (newMixedTableCellDataList [][]request.MixedTableCellDataReq, err error, errMsg string) {
  38. cellRelationConf := mixedTableReq.CellRelation
  39. config := mixedTableReq.Data
  40. // 单元格关系配置x信息
  41. cellRelationConfMap := make(map[string]request.CellRelationConf)
  42. cellRelationConfList := make([]request.CellRelationConf, 0)
  43. if cellRelationConf != `` {
  44. err = json.Unmarshal([]byte(cellRelationConf), &cellRelationConfList)
  45. if err != nil {
  46. return
  47. }
  48. for _, v := range cellRelationConfList {
  49. cellRelationConfMap[v.Key] = v
  50. }
  51. }
  52. // 找出所有的关联指标id
  53. config, edbInfoIdList, _, err, errMsg := handleConfig(config)
  54. if err != nil {
  55. return
  56. }
  57. // 查询所有关联的指标信息
  58. edbInfoList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
  59. if err != nil {
  60. return
  61. }
  62. // 指标信息map
  63. edbInfoMap := make(map[int]*data_manage.EdbInfo)
  64. // 日度指标数据map
  65. edbDayDataListMap := make(map[int]map[string]float64)
  66. // 月度指标数据map
  67. edbMonthDataListMap := make(map[int]map[string]float64)
  68. // 日度指标数据map
  69. edbDataListMap := make(map[int][]models.EdbDataItemList)
  70. for _, edbInfo := range edbInfoList {
  71. edbInfoMap[edbInfo.EdbInfoId] = edbInfo
  72. dataList := make([]*models.EdbDataList, 0)
  73. switch edbInfo.EdbInfoType {
  74. case 0:
  75. dataList, _ = models.GetEdbDataList(edbInfo.Source, edbInfo.SubSource, edbInfo.EdbInfoId, ``, ``)
  76. case 1:
  77. _, dataList, _, _, _, _ = data.GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, ``, ``, false)
  78. default:
  79. err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
  80. }
  81. dateValMap := make(map[string]float64)
  82. monthValMap := make(map[string]float64)
  83. for _, tmpData := range dataList {
  84. // 日度数据
  85. dateValMap[tmpData.DataTime] = tmpData.Value
  86. // 月度数据(取该月份的第一个数据)
  87. yearMonth := strings.Join(strings.Split(tmpData.DataTime, "-")[0:2], "-")
  88. if _, ok := monthValMap[yearMonth]; !ok {
  89. monthValMap[yearMonth] = tmpData.Value
  90. }
  91. }
  92. edbDayDataListMap[edbInfo.EdbInfoId] = dateValMap
  93. edbMonthDataListMap[edbInfo.EdbInfoId] = monthValMap
  94. tmpDataList := make([]models.EdbDataItemList, 0)
  95. for _, v := range dataList {
  96. tmpDataList = append(tmpDataList, models.EdbDataItemList{
  97. EdbDataId: v.EdbDataId,
  98. EdbInfoId: v.EdbInfoId,
  99. DataTime: v.DataTime,
  100. DataTimestamp: v.DataTimestamp,
  101. Value: v.Value,
  102. })
  103. }
  104. edbDataListMap[edbInfo.EdbInfoId] = tmpDataList
  105. }
  106. // 单元格实际绑定的信息map
  107. cellDataRelationMap := make(map[string]request.MixedTableCellDataReq, 0)
  108. // 处理指定指标的日期
  109. for k, row := range config {
  110. for i, cell := range row {
  111. // 单元格是日期类型,且是日导入指标日期(指标库的最新日期)
  112. if cell.DataType == request.DateDT && cell.DataTimeType == request.EdbDateDT {
  113. // 指标id是在配置里面
  114. var edbDateConfig request.EdbDateConf
  115. err = json.Unmarshal([]byte(cell.Value), &edbDateConfig)
  116. if err != nil {
  117. return
  118. }
  119. if edbInfo, ok := edbInfoMap[edbDateConfig.EdbInfoId]; ok {
  120. cell.ShowValue = edbInfo.EndDate
  121. cell.DataTime = edbInfo.EndDate
  122. config[k][i] = cell
  123. }
  124. }
  125. row[i] = cell
  126. cellDataRelationMap[cell.Uid] = cell
  127. }
  128. config[k] = row
  129. }
  130. // 指标计算的结果map
  131. edbSourceDataMap := make(map[string]map[string]float64)
  132. // 单元格对应的key与他的值(只处理数据类型)
  133. cellKeyVal := make(map[string]float64)
  134. // 基础计算单元格的位置信息
  135. calculateCellMap := make(map[string]Cell)
  136. calculateChainList := make([]string, 0)
  137. // 处理单元格中的数据类型(除去基础计算,因为这个是依赖于其他)
  138. for k, row := range config {
  139. for i, cell := range row {
  140. switch cell.DataType {
  141. case request.EdbDT: // 指标类型
  142. if cell.Value == `` {
  143. if edbInfo, ok := edbInfoMap[cell.EdbInfoId]; ok {
  144. cell.ShowValue = edbInfo.EdbName
  145. }
  146. } else {
  147. cell.ShowValue = cell.Value
  148. }
  149. case request.InsertDataDT, request.PopInsertDataDT: // 数据类型
  150. // 数值先清空
  151. cell.ShowValue = ``
  152. //cell.Value = ``
  153. // 日期关系配置不存在,则默认最新数据
  154. if relationConf, ok := cellRelationConfMap[cell.Uid]; ok {
  155. if relationConf.RelationDate.Key == `` {
  156. // 日期关系配置未绑定
  157. continue
  158. }
  159. // 配置
  160. relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
  161. if !ok {
  162. // 找不到对应日期的单元格
  163. continue
  164. }
  165. // 确实是找到了这个关联日期的单元格,那么通过日期重新获取数据值
  166. tmpDateValMap := make(map[string]float64)
  167. // 日度数据
  168. if dateValMap, ok := edbDayDataListMap[cell.EdbInfoId]; ok {
  169. tmpDateValMap = dateValMap
  170. }
  171. if val, ok2 := tmpDateValMap[relationCell.DataTime]; ok2 {
  172. //cell.ShowValue = fmt.Sprint(val)
  173. cellKeyVal[cell.Uid] = val
  174. cell.ShowValue = fmt.Sprint(val)
  175. }
  176. } else {
  177. // 如果不是取得一个关联的日期,那么就是指定日期
  178. // 如果没有指定日期,则默认最新数据
  179. if cell.DataTime == `` {
  180. // 指标的最新日期
  181. if dateValList, ok := edbDataListMap[cell.EdbInfoId]; ok {
  182. tmpLenData := len(dateValList)
  183. if tmpLenData > 0 {
  184. cellKeyVal[cell.Uid] = dateValList[tmpLenData-1].Value
  185. //cell.ShowValue = utils.FormatTableDataShowValue(dateValList[tmpLenData-1].Value)
  186. cell.ShowValue = fmt.Sprint(dateValList[tmpLenData-1].Value)
  187. }
  188. }
  189. } else {
  190. tmpDateList := strings.Split(cell.DataTime, "-")
  191. tmpDateValMap := make(map[string]float64)
  192. if len(tmpDateList) == 2 {
  193. //月度数据
  194. if dateValMap, ok := edbMonthDataListMap[cell.EdbInfoId]; ok {
  195. tmpDateValMap = dateValMap
  196. }
  197. } else {
  198. // 日度数据
  199. if dateValMap, ok := edbDayDataListMap[cell.EdbInfoId]; ok {
  200. tmpDateValMap = dateValMap
  201. }
  202. }
  203. if val, ok2 := tmpDateValMap[cell.DataTime]; ok2 {
  204. //cell.ShowValue = fmt.Sprint(val)
  205. cellKeyVal[cell.Uid] = val
  206. //cell.ShowValue = utils.FormatTableDataShowValue(val)
  207. cell.ShowValue = fmt.Sprint(val)
  208. }
  209. }
  210. }
  211. calculateCellMap[cell.Uid] = Cell{
  212. Column: k,
  213. Row: i,
  214. CellInfo: cell,
  215. }
  216. case request.CustomTextDT: //自定义文本
  217. if cell.Value == `` {
  218. continue
  219. }
  220. // 处理看下能否转成float,如果可以的话,说明这个也是可以参与计算的
  221. tmpDeci, tmpErr := decimal.NewFromString(cell.Value)
  222. if tmpErr == nil {
  223. tmpVal, _ := tmpDeci.Float64()
  224. cellKeyVal[cell.Uid] = tmpVal
  225. calculateCellMap[cell.Uid] = Cell{
  226. Column: k,
  227. Row: i,
  228. CellInfo: cell,
  229. }
  230. }
  231. case request.FormulateCalculateDataDT: // 公式计算(A+B这种)
  232. calculateCellMap[cell.Uid] = Cell{
  233. Column: k,
  234. Row: i,
  235. CellInfo: cell,
  236. }
  237. calculateChainList = append(calculateChainList, cell.Uid)
  238. case request.InsertEdbCalculateDataDT: // 插入指标系统计算公式生成的值
  239. // 日期
  240. var cellDateTime string
  241. // 日期关系配置不存在,则默认最新数据
  242. if relationConf, ok := cellRelationConfMap[cell.Uid]; ok {
  243. if relationConf.RelationDate.Key == `` {
  244. // 日期关系配置未绑定
  245. continue
  246. }
  247. // 配置
  248. relationCell, ok := cellDataRelationMap[relationConf.RelationDate.Key]
  249. if !ok {
  250. // 找不到对应日期的单元格
  251. continue
  252. }
  253. cellDateTime = relationCell.DataTime
  254. }
  255. var tmpDataMap map[string]float64
  256. key := utils.MD5(cell.Value)
  257. tmpDataMap, ok := edbSourceDataMap[key]
  258. if !ok {
  259. // 对应的配置值
  260. var tmpConfig request.CalculateConf
  261. err = json.Unmarshal([]byte(cell.Value), &tmpConfig)
  262. if err != nil {
  263. return
  264. }
  265. tmpDataList, ok := edbDataListMap[tmpConfig.EdbInfoId]
  266. if !ok {
  267. continue
  268. }
  269. edbInfo, ok := edbInfoMap[tmpConfig.EdbInfoId]
  270. if !ok {
  271. continue
  272. }
  273. req2 := &BaseCalculate{
  274. DataList: tmpDataList,
  275. Frequency: tmpConfig.Frequency,
  276. Formula: tmpConfig.Formula,
  277. Calendar: tmpConfig.Calendar,
  278. MoveType: tmpConfig.MoveType,
  279. MoveFrequency: tmpConfig.MoveFrequency,
  280. FromFrequency: edbInfo.Frequency,
  281. Source: tmpConfig.Source,
  282. }
  283. // 调用指标库去更新
  284. reqJson, tmpErr := json.Marshal(req2)
  285. if tmpErr != nil {
  286. utils.FileLog.Error(fmt.Sprintf("计算失败1,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  287. err = tmpErr
  288. return
  289. }
  290. respItem, tmpErr := data.BaseCalculate(string(reqJson))
  291. if tmpErr != nil {
  292. utils.FileLog.Error(fmt.Sprintf("计算失败2,配置信息;%s;错误原因:%s", cell.Value, tmpErr.Error()))
  293. err = tmpErr
  294. return
  295. }
  296. if respItem.Ret != 200 {
  297. utils.FileLog.Error(fmt.Sprintf("计算失败3,配置信息;%s;原因:%s;错误原因:%s", cell.Value, respItem.Msg, respItem.ErrMsg))
  298. continue
  299. }
  300. tmpDataMap = respItem.Data.DataMap
  301. // 计算结果存一份,万一存在重复的计算方式,那么省的重新计算一下
  302. edbSourceDataMap[key] = tmpDataMap
  303. lenDataList := len(respItem.Data.DateList)
  304. if cellDateTime == `` && lenDataList > 0 {
  305. cellDateTime = respItem.Data.DateList[lenDataList-1]
  306. }
  307. }
  308. val := tmpDataMap[cellDateTime]
  309. cellKeyVal[cell.Uid] = val
  310. //cell.ShowValue = utils.FormatTableDataShowValue(val)
  311. cell.ShowValue = fmt.Sprint(val)
  312. }
  313. row[i] = cell
  314. }
  315. config[k] = row
  316. }
  317. // 公式链计算
  318. if len(calculateChainList) > 0 {
  319. for _, cellKey := range calculateChainList {
  320. // 查找这个单元格的位置,直接map找了,而不是遍历整个单元格
  321. cellPosition, ok := calculateCellMap[cellKey]
  322. if !ok {
  323. utils.FileLog.Error("找不到单元格位置:", cellKey)
  324. continue
  325. }
  326. cell := config[cellPosition.Column][cellPosition.Row]
  327. if cell.DataType != request.FormulateCalculateDataDT { // 判断公式计算(A+B这种)类型,不是的话也过滤了
  328. continue
  329. }
  330. val, tmpErr, has := getCalculateValueByCell(calculateCellMap, cellKey, cellKeyVal)
  331. if tmpErr != nil {
  332. err = tmpErr
  333. return
  334. }
  335. if !has {
  336. continue
  337. }
  338. cellKeyVal[cell.Uid] = val
  339. //cell.ShowValue = utils.FormatTableDataShowValue(val)
  340. cell.ShowValue = fmt.Sprint(val)
  341. config[cellPosition.Column][cellPosition.Row] = cell
  342. }
  343. }
  344. newMixedTableCellDataList = config
  345. return
  346. }
  347. // getCalculateValue 获取公式计算的结果
  348. func getCalculateValueByCell(calculateCellMap map[string]Cell, key string, cellKeyValMap map[string]float64) (val float64, err error, has bool) {
  349. // 单元格的标签名
  350. val, ok := cellKeyValMap[key]
  351. if ok {
  352. has = true
  353. return
  354. }
  355. // 查找单元格数据
  356. cell, ok := calculateCellMap[key]
  357. if !ok {
  358. err = errors.New("查找单元格" + key + "的数据失败")
  359. return
  360. }
  361. colData := cell.CellInfo
  362. // 如果不是基础计算单元格,直接返回
  363. if colData.DataType != request.FormulateCalculateDataDT {
  364. return
  365. }
  366. // 如果是计算单元格
  367. tagList := make([]utils.CellPosition, 0)
  368. // 计算单元格relationCellList
  369. var relationCellList []request.RelationCell
  370. if colData.Extra == `` {
  371. err = errors.New(colData.Uid + "没有绑定关系")
  372. return
  373. }
  374. err = json.Unmarshal([]byte(colData.Extra), &relationCellList)
  375. if err != nil {
  376. return
  377. }
  378. for _, relation := range relationCellList {
  379. //relationCellTagName := strings.ToUpper(relation.Tag) + relation.Row
  380. tmpVal, tmpErr, _ := getCalculateValueByCell(calculateCellMap, relation.Key, cellKeyValMap)
  381. if tmpErr != nil {
  382. err = tmpErr
  383. return
  384. }
  385. cellKeyValMap[relation.Key] = tmpVal
  386. rowInt, tmpErr := strconv.Atoi(relation.Row)
  387. if tmpErr != nil {
  388. err = tmpErr
  389. return
  390. }
  391. tagList = append(tagList, utils.CellPosition{
  392. Tag: relation.Tag,
  393. Row: rowInt,
  394. Value: tmpVal,
  395. })
  396. }
  397. // 计算
  398. val, _, err = calculateByCellList(strings.ToUpper(colData.Value), tagList)
  399. if err != nil {
  400. return
  401. }
  402. // 重新赋值
  403. has = true
  404. cellKeyValMap[key] = val
  405. return
  406. }
  407. // handleConfig
  408. // @Description: 处理混合表格配置
  409. // @author: Roc
  410. // @datetime2023-10-27 13:24:53
  411. // @param configList [][]request.MixedTableCellDataReq
  412. // @return newConfig [][]request.MixedTableCellDataReq
  413. // @return edbInfoIdList []int
  414. // @return dataEdbInfoIdList []int
  415. // @return err error
  416. // @return errMsg string
  417. func handleConfig(configList [][]request.MixedTableCellDataReq) (newConfig [][]request.MixedTableCellDataReq, edbInfoIdList []int, dataEdbInfoIdList []int, err error, errMsg string) {
  418. edbInfoIdList = make([]int, 0)
  419. dataEdbInfoIdList = make([]int, 0)
  420. for ck, rowList := range configList {
  421. for rk, cell := range rowList {
  422. switch cell.DataType {
  423. case request.EdbDT: // 指标信息
  424. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  425. case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
  426. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  427. edbInfoIdList = append(edbInfoIdList, cell.EdbInfoId)
  428. case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
  429. var config request.CalculateConf
  430. err = json.Unmarshal([]byte(cell.Value), &config)
  431. if err != nil {
  432. return
  433. }
  434. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  435. dataEdbInfoIdList = append(dataEdbInfoIdList, cell.EdbInfoId)
  436. case request.DateDT: // 日期类型
  437. date, tmpErr, tmpErrMsg := handleDate(cell.DataTimeType, cell.Value)
  438. if tmpErr != nil {
  439. err = tmpErr
  440. errMsg = tmpErrMsg
  441. return
  442. }
  443. rowList[rk].DataTime = date
  444. rowList[rk].ShowValue = date
  445. // 指标日期类型单元格的需要额外将指标id取出来
  446. if cell.DataTimeType == request.EdbDateDT {
  447. var config request.EdbDateConf
  448. err = json.Unmarshal([]byte(cell.Value), &config)
  449. if err != nil {
  450. return
  451. }
  452. edbInfoIdList = append(edbInfoIdList, config.EdbInfoId)
  453. }
  454. }
  455. }
  456. configList[ck] = rowList
  457. }
  458. newConfig = configList
  459. return
  460. }
  461. // HandleDate
  462. // @Description: 日期处理
  463. // @author: Roc
  464. // @datetime2023-10-27 09:37:02
  465. // @param dataTimeType int
  466. // @param val string
  467. // @return date string
  468. // @return err error
  469. // @return errMsg string
  470. func HandleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
  471. return handleDate(dataTimeType, val)
  472. }
  473. // handleDate
  474. // @Description: 日期处理
  475. // @author: Roc
  476. // @datetime2023-10-27 09:36:49
  477. // @param dataTimeType int
  478. // @param val string
  479. // @return date string
  480. // @return err error
  481. // @return errMsg string
  482. func handleDate(dataTimeType int, val string) (date string, err error, errMsg string) {
  483. if val == `` {
  484. errMsg = "错误的日期数据"
  485. err = errors.New(errMsg)
  486. return
  487. }
  488. switch dataTimeType {
  489. case request.CustomDateT: //手动输入日期
  490. date = val
  491. case request.SystemDateT: // 系统日期
  492. date, err, errMsg = handleSystemDateT(val)
  493. case request.EdbDateDT: // 导入指标日期(指标库的最新日期)
  494. default:
  495. errMsg = "错误的日期类型"
  496. err = errors.New(errMsg)
  497. return
  498. }
  499. return
  500. }
  501. // handleSystemDateT
  502. // @Description: 处理导入系统日期
  503. // @author: Roc
  504. // @datetime2023-10-27 09:36:21
  505. // @param confStr string
  506. // @return date string
  507. // @return err error
  508. // @return errMsg string
  509. func handleSystemDateT(confStr string) (date string, err error, errMsg string) {
  510. var config request.SystemDateConf
  511. err = json.Unmarshal([]byte(confStr), &config)
  512. if err != nil {
  513. return
  514. }
  515. switch config.Source {
  516. case request.SystemCurrDateT:
  517. date = time.Now().Format(utils.FormatDate)
  518. case request.SystemCalculateDateT:
  519. date, err, errMsg = handleSystemCalculateDateT(config.CalculateNum, config.CalculateFrequency)
  520. case request.SystemFrequencyDateT: // 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  521. date, err, errMsg = handleSystemAppointDateT(config.Day, config.Frequency)
  522. default:
  523. errMsg = "错误的日期日期导入方式"
  524. err = errors.New(fmt.Sprint("错误的日期日期导入方式:", config.Source))
  525. return
  526. }
  527. return
  528. }
  529. // handleSystemCalculateDateT
  530. // @Description: 处理系统日期计算后的日期
  531. // @author: Roc
  532. // @datetime2023-10-27 09:31:22
  533. // @param num int
  534. // @param frequency string
  535. // @return date string
  536. // @return err error
  537. // @return errMsg string
  538. func handleSystemCalculateDateT(num int, frequency string) (date string, err error, errMsg string) {
  539. if err != nil {
  540. return
  541. }
  542. currDate := time.Now()
  543. switch frequency {
  544. case "", "日":
  545. date = currDate.AddDate(0, 0, num).Format(utils.FormatDate)
  546. default:
  547. errMsg = "错误的日期频度:" + frequency
  548. err = errors.New(errMsg)
  549. return
  550. }
  551. return
  552. }
  553. // handleSystemAppointDateT
  554. // @Description: 处理系统日期相关的指定频率(所在周/旬/月/季/半年/年的最后/最早一天)
  555. // @author: Roc
  556. // @datetime2023-10-27 09:31:35
  557. // @param Frequency string
  558. // @param Day string
  559. // @return date string
  560. // @return err error
  561. // @return errMsg string
  562. func handleSystemAppointDateT(appointDay, frequency string) (date string, err error, errMsg string) {
  563. currDate := time.Now()
  564. switch frequency {
  565. case "本周":
  566. day := int(currDate.Weekday())
  567. if day == 0 { // 周日
  568. day = 7
  569. }
  570. num := 0
  571. switch appointDay {
  572. case "周一":
  573. num = 1
  574. case "周二":
  575. num = 2
  576. case "周三":
  577. num = 3
  578. case "周四":
  579. num = 4
  580. case "周五":
  581. num = 5
  582. case "周六":
  583. num = 6
  584. case "周日":
  585. num = 7
  586. }
  587. day = num - day
  588. date = currDate.AddDate(0, 0, day).Format(utils.FormatDate)
  589. case "本旬":
  590. day := currDate.Day()
  591. var tmpDate time.Time
  592. switch appointDay {
  593. case "第一天":
  594. if day <= 10 {
  595. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  596. } else if day <= 20 {
  597. tmpDate = time.Date(currDate.Year(), currDate.Month(), 11, 0, 0, 0, 0, currDate.Location())
  598. } else {
  599. tmpDate = time.Date(currDate.Year(), currDate.Month(), 21, 0, 0, 0, 0, currDate.Location())
  600. }
  601. case "最后一天":
  602. if day <= 10 {
  603. tmpDate = time.Date(currDate.Year(), currDate.Month(), 10, 0, 0, 0, 0, currDate.Location())
  604. } else if day <= 20 {
  605. tmpDate = time.Date(currDate.Year(), currDate.Month(), 20, 0, 0, 0, 0, currDate.Location())
  606. } else {
  607. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  608. }
  609. }
  610. date = tmpDate.Format(utils.FormatDate)
  611. case "本月":
  612. var tmpDate time.Time
  613. switch appointDay {
  614. case "第一天":
  615. tmpDate = time.Date(currDate.Year(), currDate.Month(), 1, 0, 0, 0, 0, currDate.Location())
  616. case "最后一天":
  617. tmpDate = time.Date(currDate.Year(), currDate.Month()+1, 1, 0, 0, 0, 0, currDate.Location()).AddDate(0, 0, -1)
  618. }
  619. date = tmpDate.Format(utils.FormatDate)
  620. case "本季":
  621. month := currDate.Month()
  622. var tmpDate time.Time
  623. switch appointDay {
  624. case "第一天":
  625. if month <= 3 {
  626. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  627. } else if month <= 6 {
  628. tmpDate = time.Date(currDate.Year(), 4, 1, 0, 0, 0, 0, currDate.Location())
  629. } else if month <= 9 {
  630. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  631. } else {
  632. tmpDate = time.Date(currDate.Year(), 10, 1, 0, 0, 0, 0, currDate.Location())
  633. }
  634. case "最后一天":
  635. if month <= 3 {
  636. tmpDate = time.Date(currDate.Year(), 3, 31, 0, 0, 0, 0, currDate.Location())
  637. } else if month <= 6 {
  638. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  639. } else if month <= 9 {
  640. tmpDate = time.Date(currDate.Year(), 9, 30, 0, 0, 0, 0, currDate.Location())
  641. } else {
  642. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  643. }
  644. }
  645. date = tmpDate.Format(utils.FormatDate)
  646. case "本半年":
  647. month := currDate.Month()
  648. var tmpDate time.Time
  649. switch appointDay {
  650. case "第一天":
  651. if month <= 6 {
  652. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  653. } else {
  654. tmpDate = time.Date(currDate.Year(), 7, 1, 0, 0, 0, 0, currDate.Location())
  655. }
  656. case "最后一天":
  657. if month <= 6 {
  658. tmpDate = time.Date(currDate.Year(), 6, 30, 0, 0, 0, 0, currDate.Location())
  659. } else {
  660. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  661. }
  662. }
  663. date = tmpDate.Format(utils.FormatDate)
  664. case "本年":
  665. var tmpDate time.Time
  666. switch appointDay {
  667. case "第一天":
  668. tmpDate = time.Date(currDate.Year(), 1, 1, 0, 0, 0, 0, currDate.Location())
  669. case "最后一天":
  670. tmpDate = time.Date(currDate.Year(), 12, 31, 0, 0, 0, 0, currDate.Location())
  671. }
  672. date = tmpDate.Format(utils.FormatDate)
  673. default:
  674. errMsg = "错误的日期频度:" + frequency
  675. err = errors.New(errMsg)
  676. return
  677. }
  678. return
  679. }
  680. // calculateByCellList
  681. // @Description: 根据单元格来进行公式计算
  682. // @author: Roc
  683. // @datetime2023-11-14 16:17:38
  684. // @param calculateFormula string
  685. // @param tagList []utils.CellPosition
  686. // @return calVal string
  687. // @return errMsg string
  688. // @return err error
  689. func calculateByCellList(calculateFormula string, tagList []utils.CellPosition) (calVal float64, errMsg string, err error) {
  690. if calculateFormula == "" {
  691. errMsg = "公式异常"
  692. err = errors.New(errMsg)
  693. return
  694. }
  695. calculateFormula = strings.TrimPrefix(calculateFormula, "=")
  696. calculateFormula = strings.Replace(calculateFormula, "(", "(", -1)
  697. calculateFormula = strings.Replace(calculateFormula, ")", ")", -1)
  698. calculateFormula = strings.Replace(calculateFormula, ",", ",", -1)
  699. calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
  700. calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
  701. rowList := make([]int, 0)
  702. rowListMap := make(map[int][]utils.CellPosition)
  703. for _, v := range tagList {
  704. tmpRowList, ok := rowListMap[v.Row]
  705. if !ok {
  706. rowList = append(rowList, v.Row)
  707. tmpRowList = make([]utils.CellPosition, 0)
  708. }
  709. tmpRowList = append(tmpRowList, v)
  710. rowListMap[v.Row] = tmpRowList
  711. }
  712. sort.Ints(rowList)
  713. list := make([]utils.CellPosition, 0)
  714. for _, row := range rowList {
  715. list = append(list, rowListMap[row]...)
  716. }
  717. formulaFormStr := utils.ReplaceFormulaByCellList(list, calculateFormula)
  718. //计算公式异常,那么就移除该指标
  719. if formulaFormStr == `` {
  720. errMsg = "公式异常"
  721. err = errors.New(errMsg)
  722. return
  723. }
  724. expression := formula.NewExpression(formulaFormStr)
  725. calResult, err := expression.Evaluate()
  726. if err != nil {
  727. errMsg = "计算失败"
  728. err = errors.New("计算失败:Err:" + err.Error() + ";formulaStr:" + formulaFormStr)
  729. // 分母为0的报错
  730. if strings.Contains(err.Error(), "divide by zero") {
  731. errMsg = "分母不能为0"
  732. err = errors.New("分母不能为空,计算公式:" + formulaFormStr)
  733. }
  734. return
  735. }
  736. // 如果计算结果是NAN,那么就提示报错
  737. if calResult.IsNan() {
  738. errMsg = "计算失败"
  739. err = errors.New("计算失败:计算结果是:NAN;formulaStr:" + formulaFormStr)
  740. return
  741. }
  742. calVal, err = calResult.Float64()
  743. if err != nil {
  744. return
  745. }
  746. // 转Decimal然后四舍五入
  747. calVal, _ = decimal.NewFromFloat(calVal).Round(4).Float64()
  748. return
  749. }